md5( $row['ip'] . '|' . $row['created_at'] . '|' . $row['type'] ), 'time' => Argus_Console_Stats::live_feed_time_label( $row['created_at'] ), 'desc' => esc_html( $row['desc'] ), ); } wp_send_json_success( $out ); } public static function register_menu() { add_menu_page( __( 'ARGUS Defence', 'argus-wordpress-defence' ), __( 'ARGUS Defence', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-dashboard', array( __CLASS__, 'render_overview' ), 'dashicons-shield', 2 ); add_submenu_page( 'argus-wpd-dashboard', __( 'Overview', 'argus-wordpress-defence' ), __( 'Overview', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-dashboard', array( __CLASS__, 'render_overview' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Firewall', 'argus-wordpress-defence' ), __( 'Firewall', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-firewall', array( __CLASS__, 'render_firewall' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Threats', 'argus-wordpress-defence' ), __( 'Threats', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-threats', array( __CLASS__, 'render_threats' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Findings', 'argus-wordpress-defence' ), __( 'Findings', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-findings', array( __CLASS__, 'render_findings' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Scanner', 'argus-wordpress-defence' ), __( 'Scanner', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-scanner', array( __CLASS__, 'render_scanner' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Quarantine', 'argus-wordpress-defence' ), __( 'Quarantine', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-quarantine', array( __CLASS__, 'render_quarantine' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Cache & Performance', 'argus-wordpress-defence' ), __( 'Cache & Performance', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-cache', array( __CLASS__, 'render_cache' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Backups', 'argus-wordpress-defence' ), __( 'Backups', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-backups', array( __CLASS__, 'render_backups' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Vulnerabilities', 'argus-wordpress-defence' ), __( 'Vulnerabilities', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-vulnerabilities', array( __CLASS__, 'render_vulnerabilities' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Intelligence', 'argus-wordpress-defence' ), __( 'Intelligence', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-intelligence', array( __CLASS__, 'render_intelligence' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'ANIS', 'argus-wordpress-defence' ), __( 'ANIS', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-anis', array( __CLASS__, 'render_anis' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Audit Log', 'argus-wordpress-defence' ), __( 'Audit Log', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-audit-log', array( __CLASS__, 'render_audit_log' ) ); add_submenu_page( 'argus-wpd-dashboard', __( 'Settings', 'argus-wordpress-defence' ), __( 'Settings', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-settings', array( __CLASS__, 'render_settings' ) ); // Reachable at ?page=argus-wpd-welcome right after activation, but // CSS-hidden from the sidebar (hide_settings_from_sidebar(), same // mechanism already used for Settings) -- it's a onboarding screen, // not a place to keep coming back to via the nav. Registering with a // real parent rather than null: passing null as parent_slug left // get_admin_page_title() unable to resolve a title in this WP // version, cascading into a "headers already sent" fatal-adjacent // warning -- confirmed live, not theoretical. add_submenu_page( 'argus-wpd-dashboard', __( 'Welcome to ARGUS Defence', 'argus-wordpress-defence' ), __( 'Welcome', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-welcome', array( __CLASS__, 'render_welcome' ) ); } public static function render_welcome() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'argus-wordpress-defence' ) ); } $template_applied = null; if ( isset( $_POST['argus_wpd_apply_template_nonce'], $_POST['template'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_apply_template_nonce'] ) ), 'argus_wpd_apply_template' ) ) { // phpcs:ignore $key = sanitize_key( wp_unslash( $_POST['template'] ) ); // phpcs:ignore if ( class_exists( 'Argus_Templates' ) && Argus_Templates::apply( $key ) ) { $templates = Argus_Templates::all(); $template_applied = $templates[ $key ]['label']; } } if ( isset( $_POST['argus_wpd_anis_toggle_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_anis_toggle_nonce'] ) ), 'argus_wpd_anis_toggle' ) ) { // phpcs:ignore $action = sanitize_key( wp_unslash( $_POST['anis_action'] ?? '' ) ); // phpcs:ignore $user = wp_get_current_user(); if ( 'enable' === $action ) { Argus_Settings::update( array( 'anis_enabled' => true ) ); Argus_ANIS_Client::register(); Argus_Events::record( 'anis_enabled', 'info', sprintf( 'ARGUS Cloud connection enabled by %s', $user->user_login ), array( 'actor' => $user->user_login ) ); } } if ( isset( $_POST['argus_wpd_auto_update_all_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_auto_update_all_nonce'] ) ), 'argus_wpd_save_auto_update_all' ) ) { // phpcs:ignore Argus_Settings::update( array( 'auto_update_all_enabled' => ! empty( $_POST['auto_update_all_enabled'] ) ) ); // phpcs:ignore } $settings = Argus_Settings::all(); $templates = class_exists( 'Argus_Templates' ) ? Argus_Templates::all() : array(); $active_template = class_exists( 'Argus_Templates' ) ? Argus_Templates::active() : ''; $recommended_template = class_exists( 'Argus_Templates' ) ? Argus_Templates::recommended() : null; $anis_status = Argus_ANIS_Client::status(); include ARGUS_WPD_DIR . 'admin/views/welcome.php'; } public static function hide_settings_from_sidebar() { echo ''; } public static function enqueue_assets( $hook ) { if ( false === strpos( $hook, 'argus-wpd' ) ) { return; } $css_path = ARGUS_WPD_DIR . 'assets/css/admin.css'; $version = file_exists( $css_path ) ? filemtime( $css_path ) : ARGUS_WPD_VERSION; wp_enqueue_style( 'argus-wpd-admin', ARGUS_WPD_URL . 'assets/css/admin.css', array(), $version ); } public static function render_overview() { $mu_status = Argus_MU_Installer::status(); $mu_exec_status = Argus_MU_Installer::execution_status(); $mode = Argus_Settings::mode(); $counts = Argus_Findings::open_counts(); $range = isset( $_GET['range'] ) ? sanitize_key( wp_unslash( $_GET['range'] ) ) : '24h'; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $range, array( '24h', '7d', '30d' ), true ) ) { $range = '24h'; } $blocked_today = Argus_Console_Stats::blocked_today(); $malicious_ips = Argus_Console_Stats::malicious_ip_count(); $blocked_30d = Argus_Console_Stats::blocked_since_days( 30 ); $security_events = Argus_Console_Stats::security_events_count( 30 ); $series = Argus_Console_Stats::blocked_series( $range ); $malware_open = Argus_Findings::count_open( 'malware' ); $integrity_open = Argus_Findings::count_open( 'integrity' ); $anis_status = Argus_ANIS_Client::status(); $ips_tracked = Argus_ANIS_Client::local_reputation_count(); $anis_protections = Argus_ANIS_Client::blocked_count(); // Argus_License exists only in the separately-distributed Premium // build (see includes/class-argus-license.php's own header) -- the // free WordPress.org build has no trial/license concept at all, and // this stays null there so overview.php shows nothing for it. $license_summary = class_exists( 'Argus_License' ) ? Argus_License::summary() : null; include ARGUS_WPD_DIR . 'admin/views/overview.php'; } public static function render_firewall() { $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'overview'; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $tab, array( 'overview', 'rule-activity', 'manual-block', 'blocked-ips' ), true ) ) { $tab = 'overview'; } $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $notice = isset( $_GET['notice'] ) ? sanitize_text_field( wp_unslash( $_GET['notice'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $result = Argus_Ban_Engine::paginated( $page ); $bans = $result['rows']; $page = $result['page']; $total_pages = $result['total_pages']; $rule_hits = Argus_Console_Stats::firewall_rule_hits( 24 ); $rules_active = count( Argus_WAF_Rules::corpus() ); $requests_blocked_24h = Argus_Console_Stats::blocked_today(); $malicious_ips = Argus_Console_Stats::malicious_ip_count(); $attack_categories = Argus_Console_Stats::attack_category_totals( 24 ); $security_actions = Argus_Console_Stats::security_action_totals( 24 ); include ARGUS_WPD_DIR . 'admin/views/firewall.php'; } protected static function redirect_firewall_tab( $tab, $notice ) { wp_safe_redirect( add_query_arg( array( 'page' => 'argus-wpd-firewall', 'tab' => $tab, 'notice' => rawurlencode( $notice ) ), admin_url( 'admin.php' ) ) ); exit; } public static function render_threats() { $activity_page = isset( $_GET['activity_paged'] ) ? max( 1, absint( $_GET['activity_paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $activity_result = Argus_Console_Stats::recent_activity_paginated( $activity_page ); $recent_activity = $activity_result['rows']; $activity_page = $activity_result['page']; $activity_total_pages = $activity_result['total_pages']; $category_counts = Argus_Findings::category_counts(); $blocked_per_minute = Argus_Console_Stats::blocked_per_minute_series( 30 ); $latest_blocked = Argus_Console_Stats::latest_blocked_events( 10 ); $live_feed_nonce = wp_create_nonce( 'argus_wpd_live_feed' ); include ARGUS_WPD_DIR . 'admin/views/threats.php'; } public static function render_findings() { $view = isset( $_GET['view'] ) ? sanitize_key( wp_unslash( $_GET['view'] ) ) : 'active'; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $view, array( 'active', 'needs_attention', 'resolved', 'accepted' ), true ) ) { $view = 'active'; } $finding_id = isset( $_GET['finding'] ) ? absint( $_GET['finding'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $action_result = null; if ( $finding_id && isset( $_POST['argus_wpd_status_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_status_nonce'] ) ), 'argus_wpd_set_status_' . $finding_id ) ) { // phpcs:ignore $new_status = sanitize_key( wp_unslash( $_POST['new_status'] ?? '' ) ); if ( in_array( $new_status, array( Argus_Findings::STATUS_ACKNOWLEDGED, Argus_Findings::STATUS_RESOLVED, Argus_Findings::STATUS_RISK_ACCEPTED ), true ) ) { Argus_Findings::set_status( $finding_id, $new_status ); } } if ( $finding_id && isset( $_POST['argus_wpd_action_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_action_nonce'] ) ), 'argus_wpd_run_action_' . $finding_id ) ) { // phpcs:ignore $finding = Argus_Findings::get( $finding_id ); $action = $finding->evidence['action'] ?? null; if ( $action && ! empty( $action['type'] ) ) { $action_result = Argus_Actions::run( $action['type'], array( 'plugin' => $action['plugin'] ?? '', 'theme' => $action['theme'] ?? '', 'path' => $action['path'] ?? '' ) ); if ( $action_result['success'] ) { Argus_Findings::set_status( $finding_id, Argus_Findings::STATUS_RESOLVED ); } } } $findings_notice = ''; if ( $finding_id && isset( $_POST['argus_wpd_delete_finding_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_delete_finding_nonce'] ) ), 'argus_wpd_delete_finding_' . $finding_id ) ) { // phpcs:ignore Argus_Findings::delete( $finding_id ); $findings_notice = __( 'Finding deleted.', 'argus-wordpress-defence' ); } if ( isset( $_POST['argus_wpd_resolve_all_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_resolve_all_nonce'] ) ), 'argus_wpd_resolve_all_open' ) ) { // phpcs:ignore $resolved_count = Argus_Findings::resolve_all_open(); $findings_notice = sprintf( _n( '%d open finding marked resolved.', '%d open findings marked resolved.', $resolved_count, 'argus-wordpress-defence' ), $resolved_count ); } $result = Argus_Findings::paginated_by_view( $page, $view ); $findings = $result['rows']; $page = $result['page']; $total_pages = $result['total_pages']; $view_counts = Argus_Findings::view_counts(); include ARGUS_WPD_DIR . 'admin/views/findings.php'; } public static function render_scanner() { $scan_notice = ''; if ( isset( $_POST['argus_wpd_scan_nonce'], $_POST['scan_type'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_scan_nonce'] ) ), 'argus_wpd_run_scan' ) ) { // phpcs:ignore $scan_type = sanitize_key( wp_unslash( $_POST['scan_type'] ) ); $started = time(); if ( 'full' === $scan_type ) { Argus_Integrity::full_scan(); Argus_Malware_Scanner::incremental_scan(); Argus_Scan_History::record( Argus_Scan_History::TYPE_FULL, $started, Argus_Integrity::scan_status()['files_scanned'] ); $scan_notice = __( 'Full scan complete.', 'argus-wordpress-defence' ); } elseif ( 'quick' === $scan_type ) { Argus_Integrity::incremental_scan(); Argus_Malware_Scanner::incremental_scan(); Argus_Scan_History::record( Argus_Scan_History::TYPE_QUICK, $started ); $scan_notice = __( 'Quick scan complete.', 'argus-wordpress-defence' ); } } $scan_status = Argus_Integrity::scan_status(); $malware_open = Argus_Findings::count_open( 'malware' ); $integrity_open = Argus_Findings::count_open( 'integrity' ); $lockdown_status = Argus_Malware_Scanner::lockdown_status(); $quarantine_review_count = Argus_Quarantine::count_open(); $history_page = isset( $_GET['scan_paged'] ) ? max( 1, absint( $_GET['scan_paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $history_result = Argus_Scan_History::paginated( $history_page ); $scan_history = $history_result['rows']; $history_page = $history_result['page']; $history_total_pages = $history_result['total_pages']; include ARGUS_WPD_DIR . 'admin/views/scanner.php'; } public static function render_quarantine() { $notice = ''; $notice_type = 'success'; if ( isset( $_POST['quarantine_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification $id = absint( $_POST['quarantine_id'] ); // phpcs:ignore WordPress.Security.NonceVerification if ( isset( $_POST['argus_wpd_quarantine_restore_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_quarantine_restore_nonce'] ) ), 'argus_wpd_quarantine_restore_' . $id ) ) { // phpcs:ignore $result = Argus_Quarantine::restore( $id ); $notice = $result['message']; $notice_type = $result['success'] ? 'success' : 'error'; } elseif ( isset( $_POST['argus_wpd_quarantine_delete_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_quarantine_delete_nonce'] ) ), 'argus_wpd_quarantine_delete_' . $id ) ) { // phpcs:ignore $result = Argus_Quarantine::delete( $id ); $notice = $result['message']; $notice_type = $result['success'] ? 'success' : 'error'; } elseif ( isset( $_POST['argus_wpd_quarantine_analyse_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_quarantine_analyse_nonce'] ) ), 'argus_wpd_quarantine_analyse_' . $id ) ) { // phpcs:ignore $result = Argus_Quarantine::analyse( $id ); $notice = $result['success'] ? __( 'Analysis complete.', 'argus-wordpress-defence' ) : $result['message']; $notice_type = $result['success'] ? 'success' : 'error'; } } $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $status_filter = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : Argus_Quarantine::STATUS_QUARANTINED; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $status_filter, array( Argus_Quarantine::STATUS_QUARANTINED, Argus_Quarantine::STATUS_RESTORED, Argus_Quarantine::STATUS_DELETED ), true ) ) { $status_filter = Argus_Quarantine::STATUS_QUARANTINED; } $per_page = isset( $_GET['per_page'] ) ? absint( $_GET['per_page'] ) : Argus_Quarantine::PER_PAGE; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $per_page, array( 10, 25, 50 ), true ) ) { $per_page = Argus_Quarantine::PER_PAGE; } $result = Argus_Quarantine::paginated( $page, $status_filter, $per_page ); $items = $result['rows']; $page = $result['page']; $total_pages = $result['total_pages']; $review_count = Argus_Quarantine::count_open(); $legacy_count = Argus_Quarantine::legacy_count(); $status_counts = Argus_Quarantine::counts_by_status(); include ARGUS_WPD_DIR . 'admin/views/quarantine.php'; } public static function render_cache() { $notice = ''; $notice_type = 'success'; if ( isset( $_POST['argus_wpd_cache_settings_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_settings_nonce'] ) ), 'argus_wpd_cache_settings' ) ) { // phpcs:ignore $exclude_raw = sanitize_textarea_field( wp_unslash( $_POST['cache_custom_exclude_paths'] ?? '' ) ); // phpcs:ignore $exclude_paths = array_values( array_filter( array_map( 'trim', preg_split( '/\r\n|\r|\n/', $exclude_raw ) ) ) ); Argus_Settings::update( array( 'static_cache_enabled' => ! empty( $_POST['static_cache_enabled'] ), // phpcs:ignore 'static_cache_ttl_secs' => max( 60, absint( $_POST['static_cache_ttl_secs'] ?? 3600 ) ), // phpcs:ignore 'cache_stale_grace_secs' => max( 0, absint( $_POST['cache_stale_grace_secs'] ?? 600 ) ), // phpcs:ignore 'cache_custom_exclude_paths' => $exclude_paths, ) ); $notice = __( 'Website acceleration settings saved.', 'argus-wordpress-defence' ); } if ( isset( $_POST['argus_wpd_cache_compression_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_compression_nonce'] ) ), 'argus_wpd_cache_compression' ) ) { // phpcs:ignore Argus_Settings::update( array( 'cache_gzip_enabled' => ! empty( $_POST['cache_gzip_enabled'] ), // phpcs:ignore 'cache_gzip_level' => max( 1, min( 9, absint( $_POST['cache_gzip_level'] ?? 6 ) ) ), // phpcs:ignore 'cache_brotli_enabled' => ! empty( $_POST['cache_brotli_enabled'] ), // phpcs:ignore 'cache_brotli_level' => max( 0, min( 11, absint( $_POST['cache_brotli_level'] ?? 5 ) ) ), // phpcs:ignore 'cache_min_compress_bytes' => max( 0, absint( $_POST['cache_min_compress_bytes'] ?? 1024 ) ), // phpcs:ignore ) ); $notice = __( 'Compression settings saved.', 'argus-wordpress-defence' ); } if ( isset( $_POST['argus_wpd_cache_warming_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_warming_nonce'] ) ), 'argus_wpd_cache_warming' ) ) { // phpcs:ignore Argus_Settings::update( array( 'cache_discovery_enabled' => ! empty( $_POST['cache_discovery_enabled'] ), // phpcs:ignore 'cache_warming_enabled' => ! empty( $_POST['cache_warming_enabled'] ), // phpcs:ignore 'cache_warm_concurrency' => max( 1, min( 10, absint( $_POST['cache_warm_concurrency'] ?? 4 ) ) ), // phpcs:ignore 'cache_warm_batch_size' => max( 1, min( 200, absint( $_POST['cache_warm_batch_size'] ?? 20 ) ) ), // phpcs:ignore 'cache_warm_min_interval_secs' => max( 0, min( 30, absint( $_POST['cache_warm_min_interval_secs'] ?? 1 ) ) ), // phpcs:ignore ) ); $notice = __( 'Preparation (cache warming) settings saved.', 'argus-wordpress-defence' ); } if ( isset( $_POST['argus_wpd_cache_purge_all_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_purge_all_nonce'] ) ), 'argus_wpd_cache_purge_all' ) ) { // phpcs:ignore $count = Argus_Static_Cache::purge_all(); $notice = sprintf( __( 'Cache refreshed -- %d accelerated page(s) cleared.', 'argus-wordpress-defence' ), $count ); } if ( isset( $_POST['argus_wpd_cache_purge_url_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_purge_url_nonce'] ) ), 'argus_wpd_cache_purge_url' ) ) { // phpcs:ignore $url = esc_url_raw( wp_unslash( $_POST['purge_url'] ?? '' ) ); // phpcs:ignore if ( $url ) { Argus_Static_Cache::purge_url( $url ); $notice = __( 'That page will be re-accelerated on its next visit.', 'argus-wordpress-defence' ); } } if ( isset( $_POST['argus_wpd_cache_purge_pattern_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_purge_pattern_nonce'] ) ), 'argus_wpd_cache_purge_pattern' ) ) { // phpcs:ignore $pattern = sanitize_text_field( wp_unslash( $_POST['purge_pattern'] ?? '' ) ); // phpcs:ignore if ( $pattern ) { $count = Argus_Static_Cache::purge_pattern( $pattern ); $notice = sprintf( __( '%d matching page(s) will be re-accelerated on their next visit.', 'argus-wordpress-defence' ), $count ); } } if ( isset( $_POST['argus_wpd_cache_run_discovery_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_run_discovery_nonce'] ) ), 'argus_wpd_cache_run_discovery' ) ) { // phpcs:ignore $result = Argus_Cache_Discovery::run_discovery(); $notice = $result['url_count'] > 0 ? sprintf( __( 'Found %d page(s) on your website.', 'argus-wordpress-defence' ), $result['url_count'] ) : __( "ARGUS couldn't find a sitemap for your website yet.", 'argus-wordpress-defence' ); $notice_type = $result['url_count'] > 0 ? 'success' : 'error'; } if ( isset( $_POST['argus_wpd_cache_run_warming_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_cache_run_warming_nonce'] ) ), 'argus_wpd_cache_run_warming' ) ) { // phpcs:ignore $result = Argus_Cache_Warmer::process_queue(); $notice = ! empty( $result['skipped'] ) ? __( 'ARGUS paused preparation to avoid adding extra load to your website right now -- it will try again automatically.', 'argus-wordpress-defence' ) : sprintf( __( 'Prepared %d page(s).', 'argus-wordpress-defence' ), $result['ok'] ?? 0 ); } $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'overview'; // phpcs:ignore WordPress.Security.NonceVerification if ( ! in_array( $tab, array( 'overview', 'page-cache', 'discovery', 'rules', 'compression', 'warming', 'purge', 'analytics', 'advanced' ), true ) ) { $tab = 'overview'; } $settings = Argus_Settings::all(); $cache_stats = Argus_Static_Cache::stats(); $log_summary_30d = Argus_Cache_Log::summary( 30 ); $daily_series = Argus_Cache_Log::daily_series( 14 ); $discovery_summary = class_exists( 'Argus_Cache_Discovery' ) ? Argus_Cache_Discovery::summary() : array(); $warmer_status = class_exists( 'Argus_Cache_Warmer' ) ? Argus_Cache_Warmer::status() : array(); $auto_update = Argus_Auto_Update::status(); $gzip_available = function_exists( 'gzencode' ); $brotli_available = function_exists( 'brotli_compress' ); $compression_stats = Argus_Static_Cache::compression_stats(); $discovered_urls = array(); if ( 'discovery' === $tab && class_exists( 'Argus_Cache_Discovery' ) ) { $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $discovered_urls = Argus_Cache_Discovery::paginated_urls( $page ); } $recent_log = array(); $log_page = 1; $log_total_pages = 1; $cached_urls = array(); if ( 'analytics' === $tab ) { $log_status_filter = isset( $_GET['status'] ) ? strtoupper( sanitize_key( wp_unslash( $_GET['status'] ) ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification $log_page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $log_result = Argus_Cache_Log::paginated( $log_page, 10, $log_status_filter ); $recent_log = $log_result['rows']; $log_page = $log_result['page']; $log_total_pages = $log_result['total_pages']; } if ( 'purge' === $tab ) { $cached_urls = Argus_Static_Cache::list_cached( 50 ); } include ARGUS_WPD_DIR . 'admin/views/cache.php'; } public static function render_backups() { $notice = ''; $notice_type = 'success'; if ( isset( $_POST['argus_wpd_backup_create_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_backup_create_nonce'] ) ), 'argus_wpd_backup_create' ) ) { // phpcs:ignore $result = Argus_Backup::create( Argus_Backup::TYPE_MANUAL ); $notice = $result['message']; $notice_type = $result['success'] ? 'success' : 'error'; } if ( isset( $_POST['argus_wpd_backup_delete_nonce'], $_POST['backup_id'] ) ) { // phpcs:ignore $backup_id = absint( $_POST['backup_id'] ); // phpcs:ignore WordPress.Security.NonceVerification if ( wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_backup_delete_nonce'] ) ), 'argus_wpd_backup_delete_' . $backup_id ) ) { $result = Argus_Backup::delete( $backup_id ); $notice = $result['message']; $notice_type = $result['success'] ? 'success' : 'error'; } } if ( isset( $_POST['argus_wpd_backup_schedule_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_backup_schedule_nonce'] ) ), 'argus_wpd_backup_schedule' ) ) { // phpcs:ignore $mode = sanitize_key( wp_unslash( $_POST['backup_schedule_mode'] ?? 'automatic' ) ); // phpcs:ignore if ( ! in_array( $mode, array( 'automatic', 'manual', 'custom' ), true ) ) { $mode = 'automatic'; } Argus_Settings::update( array( 'backup_schedule_mode' => $mode ) ); if ( 'custom' === $mode ) { $hours = absint( $_POST['backup_interval_hours'] ?? 24 ); // phpcs:ignore if ( ! in_array( $hours, array( 1, 6, 12, 24, 168 ), true ) ) { $hours = 24; } Argus_Settings::update( array( 'backup_interval_hours' => $hours ) ); } elseif ( 'automatic' === $mode ) { $active_template = Argus_Templates::active(); $templates = Argus_Templates::all(); if ( $active_template && isset( $templates[ $active_template ]['settings']['backup_interval_hours'] ) ) { Argus_Settings::update( array( 'backup_interval_hours' => $templates[ $active_template ]['settings']['backup_interval_hours'] ) ); } } $notice = __( 'Backup schedule updated.', 'argus-wordpress-defence' ); } $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $result = Argus_Backup::paginated( $page ); $backups = $result['rows']; $page = $result['page']; $total_pages = $result['total_pages']; $backup_status = Argus_Backup::status(); include ARGUS_WPD_DIR . 'admin/views/backups.php'; } public static function handle_backup_download() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'argus-wordpress-defence' ) ); } $id = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification if ( ! $id || ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'argus_wpd_backup_download_' . $id ) ) { // phpcs:ignore wp_die( esc_html__( 'Invalid or expired download link.', 'argus-wordpress-defence' ) ); } $backup = Argus_Backup::get( $id ); if ( ! $backup || Argus_Backup::STATUS_COMPLETE !== $backup->status ) { wp_die( esc_html__( 'Backup not found.', 'argus-wordpress-defence' ) ); } $path = trailingslashit( Argus_Backup::backup_dir() ) . $backup->filename; if ( ! file_exists( $path ) ) { wp_die( esc_html__( 'Backup file not found on disk.', 'argus-wordpress-defence' ) ); } nocache_headers(); header( 'Content-Type: application/zip' ); header( 'Content-Disposition: attachment; filename="' . $backup->filename . '"' ); header( 'Content-Length: ' . filesize( $path ) ); readfile( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions exit; } public static function render_vulnerabilities() { $vuln_status = Argus_Vuln_Intel::status(); $severity_counts = array( 'critical' => 0, 'high' => 0, 'medium' => 0, 'low' => 0 ); foreach ( $vuln_status['components'] as $component ) { if ( Argus_Vuln_Intel::STATUS_VULNERABLE === $component['status'] && isset( $severity_counts[ $component['severity'] ] ) ) { ++$severity_counts[ $component['severity'] ]; } } $per_page = 10; $components_page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $components_total = count( $vuln_status['components'] ); $components_total_pages = max( 1, (int) ceil( $components_total / $per_page ) ); $components_page = min( $components_page, $components_total_pages ); $vuln_status['components'] = array_slice( $vuln_status['components'], ( $components_page - 1 ) * $per_page, $per_page ); include ARGUS_WPD_DIR . 'admin/views/vulnerabilities.php'; } public static function render_intelligence() { global $wpdb; $waf_rule_count = count( Argus_WAF_Rules::corpus() ); $vuln_table = Argus_DB::table( 'vuln_cache' ); $vuln_row_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$vuln_table}" ); // phpcs:ignore $geoip_status = class_exists( 'Argus_GeoIP_RIR' ) ? Argus_GeoIP_RIR::status() : null; $anis_status = Argus_ANIS_Client::status(); include ARGUS_WPD_DIR . 'admin/views/intelligence.php'; } public static function render_anis() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'argus-wordpress-defence' ) ); } if ( isset( $_POST['argus_wpd_anis_toggle_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_anis_toggle_nonce'] ) ), 'argus_wpd_anis_toggle' ) ) { // phpcs:ignore $action = sanitize_key( wp_unslash( $_POST['anis_action'] ?? '' ) ); // phpcs:ignore $user = wp_get_current_user(); if ( 'enable' === $action ) { Argus_Settings::update( array( 'anis_enabled' => true ) ); Argus_ANIS_Client::register(); Argus_Events::record( 'anis_enabled', 'info', sprintf( 'ARGUS Cloud connection enabled by %s', $user->user_login ), array( 'actor' => $user->user_login ) ); } elseif ( 'disable' === $action ) { Argus_Settings::update( array( 'anis_enabled' => false ) ); Argus_Events::record( 'anis_disabled', 'info', sprintf( 'ARGUS Cloud connection disabled by %s', $user->user_login ), array( 'actor' => $user->user_login ) ); } } $anis_status = Argus_ANIS_Client::status(); include ARGUS_WPD_DIR . 'admin/views/anis.php'; } public static function render_audit_log() { $page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification $search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $severity = isset( $_GET['severity'] ) ? sanitize_key( wp_unslash( $_GET['severity'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $type = isset( $_GET['type'] ) ? sanitize_key( wp_unslash( $_GET['type'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $range = isset( $_GET['range'] ) ? sanitize_key( wp_unslash( $_GET['range'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $range_hours = array( '24h' => 24, '7d' => 24 * 7, '30d' => 24 * 30 ); $filters = array( 'search' => $search, 'severity' => in_array( $severity, array( 'critical', 'high', 'medium', 'low', 'info' ), true ) ? $severity : '', 'type' => $type, 'since' => isset( $range_hours[ $range ] ) ? gmdate( 'Y-m-d H:i:s', time() - $range_hours[ $range ] * HOUR_IN_SECONDS ) : '', ); $result = Argus_Events::paginated( $page, $filters ); $events = $result['rows']; $page = $result['page']; $total_pages = $result['total_pages']; $event_types = Argus_Events::distinct_types(); include ARGUS_WPD_DIR . 'admin/views/audit-log.php'; } public static function render_settings() { $saved = false; $template_applied = null; if ( isset( $_POST['argus_wpd_apply_template_nonce'], $_POST['template'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_apply_template_nonce'] ) ), 'argus_wpd_apply_template' ) ) { // phpcs:ignore $key = sanitize_key( wp_unslash( $_POST['template'] ) ); // phpcs:ignore if ( class_exists( 'Argus_Templates' ) && Argus_Templates::apply( $key ) ) { $templates = Argus_Templates::all(); $template_applied = $templates[ $key ]['label']; } } if ( isset( $_POST['argus_wpd_add_exception_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_add_exception_nonce'] ) ), 'argus_wpd_add_exception' ) ) { // phpcs:ignore $ip = sanitize_text_field( wp_unslash( $_POST['exception_ip'] ?? '' ) ); // phpcs:ignore if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) { Argus_Settings::add_exception( 'ip', $ip, sanitize_text_field( wp_unslash( $_POST['exception_note'] ?? '' ) ) ); // phpcs:ignore } } if ( isset( $_POST['argus_wpd_remove_exception_nonce'], $_POST['exception_value'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_remove_exception_nonce'] ) ), 'argus_wpd_remove_exception' ) ) { // phpcs:ignore Argus_Settings::remove_exception( 'ip', sanitize_text_field( wp_unslash( $_POST['exception_value'] ) ) ); // phpcs:ignore } if ( isset( $_POST['argus_wpd_auto_update_all_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_auto_update_all_nonce'] ) ), 'argus_wpd_save_auto_update_all' ) ) { // phpcs:ignore Argus_Settings::update( array( 'auto_update_all_enabled' => ! empty( $_POST['auto_update_all_enabled'] ) ) ); // phpcs:ignore $saved = true; } $update_check_result = null; if ( isset( $_POST['argus_wpd_check_updates_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_check_updates_nonce'] ) ), 'argus_wpd_check_updates' ) && class_exists( 'Argus_Update_Client' ) ) { // phpcs:ignore $update_check_result = Argus_Update_Client::check_now(); if ( empty( $update_check_result['message'] ) ) { $update_check_result['message'] = ! empty( $update_check_result['update_available'] ) ? __( 'An update is available.', 'argus-wordpress-defence' ) : __( 'ARGUS Defence is up to date.', 'argus-wordpress-defence' ); } } if ( isset( $_POST['argus_wpd_settings_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_settings_nonce'] ) ), 'argus_wpd_save_settings' ) ) { // phpcs:ignore Argus_Settings::update( array( 'mode' => sanitize_key( wp_unslash( $_POST['mode'] ?? Argus_Settings::MODE_MONITOR ) ), // phpcs:ignore 'waf_enabled' => ! empty( $_POST['waf_enabled'] ), // phpcs:ignore 'login_protection_enabled' => ! empty( $_POST['login_protection_enabled'] ), // phpcs:ignore 'xmlrpc_block_pingback' => ! empty( $_POST['xmlrpc_block_pingback'] ), // phpcs:ignore 'rest_api_protection_enabled' => ! empty( $_POST['rest_api_protection_enabled'] ), // phpcs:ignore 'integrity_scan_enabled' => ! empty( $_POST['integrity_scan_enabled'] ), // phpcs:ignore 'malware_scan_enabled' => ! empty( $_POST['malware_scan_enabled'] ), // phpcs:ignore 'upload_scan_enabled' => ! empty( $_POST['upload_scan_enabled'] ), // phpcs:ignore 'vuln_intel_enabled' => ! empty( $_POST['vuln_intel_enabled'] ), // phpcs:ignore 'geoip_rir_enabled' => ! empty( $_POST['geoip_rir_enabled'] ), // phpcs:ignore ) ); $saved = true; $user = wp_get_current_user(); Argus_Events::record( 'settings_saved', 'info', sprintf( 'Protection settings updated by %s', $user->user_login ), array( 'actor' => $user->user_login, 'mode' => Argus_Settings::mode() ) ); } $settings = Argus_Settings::all(); $geoip_status = class_exists( 'Argus_GeoIP_RIR' ) ? Argus_GeoIP_RIR::status() : null; $templates = class_exists( 'Argus_Templates' ) ? Argus_Templates::all() : array(); $active_template = class_exists( 'Argus_Templates' ) ? Argus_Templates::active() : ''; $recommended_template = class_exists( 'Argus_Templates' ) ? Argus_Templates::recommended() : null; include ARGUS_WPD_DIR . 'admin/views/settings.php'; } }