plugin = $plugin_instance; } public function settings_page_content() { if (!current_user_can('manage_options')) { return; } nocache_headers(); // Prevent caching on this admin page // 1. DEFINIR LA ESTRUCTURA COMPLETA DEL MENÚ $menu_structure = [ 'dashboard' => [ 'title' => __('Dashboard', 'advanced-ip-blocker'), 'icon' => 'dashicons-dashboard', 'sub_tabs' => [ 'main_dashboard' => __('Security Dashboard', 'advanced-ip-blocker'), 'status' => __('System Status', 'advanced-ip-blocker') ] ], 'security_headers' => [ 'title' => __('Security Headers', 'advanced-ip-blocker'), 'icon' => 'dashicons-admin-network', 'sub_tabs' => [ 'headers_config' => __('HTTP Headers', 'advanced-ip-blocker') ] ], 'settings' => [ 'title' => __('Settings', 'advanced-ip-blocker'), 'icon' => 'dashicons-admin-settings', 'sub_tabs' => [ 'general_settings' => __('General', 'advanced-ip-blocker'), '2fa_management' => __('2FA Management', 'advanced-ip-blocker'), 'import_export' => __('Import / Export', 'advanced-ip-blocker') ] ], 'rules' => [ 'title' => __('Blocking Rules', 'advanced-ip-blocker'), 'icon' => 'dashicons-shield-alt', 'sub_tabs' => [ 'waf' => __('Firewall (WAF)', 'advanced-ip-blocker'), 'user_agents' => __('User Agents', 'advanced-ip-blocker'), 'honeypot' => __('Honeypot URLs', 'advanced-ip-blocker'), 'asn_blocking' => __('ASN Blocking', 'advanced-ip-blocker'), 'advanced_rules' => __('Advanced Rules', 'advanced-ip-blocker') ] ], 'ip_management' => [ 'title' => __('IP Management', 'advanced-ip-blocker'), 'icon' => 'dashicons-location', 'sub_tabs' => [ 'blocked_ips' => __('Blocked IPs', 'advanced-ip-blocker'), 'blocked_signatures' => __('Blocked Signatures', 'advanced-ip-blocker'), 'blocked_endpoints' => __('Blocked Endpoints', 'advanced-ip-blocker'), 'whitelist' => __('Whitelist', 'advanced-ip-blocker') ] ], 'scanner' => [ 'title' => __('Site Scanner', 'advanced-ip-blocker'), 'icon' => 'dashicons-search', 'sub_tabs' => [ 'scan_overview' => __('Health & Vulnerabilities', 'advanced-ip-blocker') ] ], 'logs' => [ 'title' => __('Logs & Sessions', 'advanced-ip-blocker'), 'icon' => 'dashicons-list-view', 'sub_tabs' => [ 'security_log' => __('Security Log', 'advanced-ip-blocker'), 'audit_log' => __('Activity Audit Log', 'advanced-ip-blocker'), 'general_log' => __('General Log', 'advanced-ip-blocker'), 'ip_trust_log' => __('IP Trust Log', 'advanced-ip-blocker'), 'user_sessions' => __('User Sessions', 'advanced-ip-blocker'), 'cron_logs' => __('WP-Cron Log', 'advanced-ip-blocker') ] ], 'about' => [ 'title' => __('About', 'advanced-ip-blocker'), 'icon' => 'dashicons-info', 'sub_tabs' => [ 'credits' => __('Credits & Support', 'advanced-ip-blocker') ] ] ]; // phpcs:disable WordPress.Security.NonceVerification.Recommended // La verificación de Nonce no es necesaria aquí. // Estas variables GET solo se usan para la navegación y visualización de pestañas, // no para procesar datos ni realizar acciones. La entrada ya se sanea con sanitize_key(). $current_page_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : 'advaipbl_settings_page'; // Primero, verificamos si la navegación es interna (clic en una pestaña/sub-pestaña) if (isset($_GET['tab'])) { $active_main_tab = sanitize_key($_GET['tab']); $active_sub_tab = isset($_GET['sub-tab']) ? sanitize_key($_GET['sub-tab']) : null; // phpcs:enable } else { // Si no, es una navegación desde el menú de la izquierda. // Mapeamos el slug de la página a la pestaña correcta. $page_slug_to_tab_map = [ 'advaipbl_settings_page' => ['dashboard', 'main_dashboard'], 'advaipbl_settings_page-settings' => ['settings', 'general_settings'], 'advaipbl_settings_page-security-headers' => ['security_headers', 'headers_config'], 'advaipbl_settings_page-rules' => ['rules', 'waf'], 'advaipbl_settings_page-ip-management' => ['ip_management', 'blocked_ips'], 'advaipbl_settings_page-scanner' => ['scanner', 'scan_overview'], 'advaipbl_settings_page-logs' => ['logs', 'security_log'], 'advaipbl_settings_page-about' => ['about', 'credits'], ]; if (isset($page_slug_to_tab_map[$current_page_slug])) { list($active_main_tab, $active_sub_tab) = $page_slug_to_tab_map[$current_page_slug]; } else { // Fallback por si acaso $active_main_tab = 'dashboard'; $active_sub_tab = 'main_dashboard'; } } // Validación final para asegurarse de que las pestañas existen if (!isset($menu_structure[$active_main_tab])) { $active_main_tab = 'dashboard'; } if (empty($active_sub_tab) || !isset($menu_structure[$active_main_tab]['sub_tabs'][$active_sub_tab])) { // Asigna la primera sub-pestaña de la pestaña principal activa $active_sub_tab = key($menu_structure[$active_main_tab]['sub_tabs']); } $blocked_count = $this->plugin->get_blocked_count(); ?>

plugin->display_admin_notice(); ?>
$sub_tab_title) : $is_active = ($sub_tab_key === $active_sub_tab); $url = add_query_arg( [ 'page' => 'advaipbl_settings_page', 'tab' => $active_main_tab, 'sub-tab' => $sub_tab_key ], 'admin.php' ); ?>
display_dashboard_tab(); break; case 'status': $this->display_status_tab(); break; case 'headers_config': $this->plugin->security_headers_manager->display_settings_tab(); break; case 'general_settings': $this->display_general_settings_tab(); break; case '2fa_management': $this->display_2fa_management_tab(); break; case 'import_export': $this->render_import_export_controls_callback(); break; case 'waf': $this->display_waf_tab(); break; case 'user_agents': $this->display_user_agents_tab(); break; case 'honeypot': $this->display_honeypot_tab(); break; case 'asn_blocking': $this->display_asn_blocking_tab(); break; case 'advanced_rules': $this->display_advanced_rules_tab(); break; case 'blocked_ips': $this->display_blocked_ips_tab(); break; case 'blocked_signatures': $this->display_blocked_signatures_tab(); break; case 'blocked_endpoints': $this->display_blocked_endpoints_tab(); break; case 'whitelist': $this->display_whitelist_tab(); break; case 'scan_overview': $this->display_scanner_tab(); break; case 'security_log': $this->display_security_log_tab(); break; case 'audit_log': $this->display_audit_log_tab(); break; case 'general_log': $this->display_general_log_tab(); break; case 'ip_trust_log': $this->display_ip_trust_log_tab(); break; case 'user_sessions': $this->plugin->session_manager->display_admin_page(); break; case 'cron_logs': $this->display_cron_logs_tab(); break; case 'credits': $this->display_credits_tab(); break; default: echo '

Error: Content for this tab is not available.

'; break; } ?>

'; esc_html_e( 'This log shows which IP addresses are triggering WP-Cron tasks on your site, and which scheduled tasks (hooks) were due to run at that moment.', 'advanced-ip-blocker' ); echo '

'; // phpcs:disable WordPress.Security.NonceVerification.Recommended $search_term = isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''; $orderby = isset($_GET['orderby']) && in_array($_GET['orderby'], ['timestamp', 'ip'], true) ? sanitize_key($_GET['orderby']) : 'timestamp'; $order = isset($_GET['order']) && in_array(strtolower($_GET['order']), ['asc', 'desc'], true) ? strtolower(sanitize_key($_GET['order'])) : 'desc'; $current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; $per_page = isset($_GET['advaipbl_per_page']) ? absint($_GET['advaipbl_per_page']) : 25; // phpcs:enable global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $where_clauses = [$wpdb->prepare("log_type = %s", 'wp_cron')]; if (!empty($search_term)) { $search_like = '%' . $wpdb->esc_like($search_term) . '%'; $where_clauses[] = $wpdb->prepare("(ip LIKE %s OR details LIKE %s)", $search_like, $search_like); } $where_sql = implode(' AND ', $where_clauses); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql"); $total_pages = ceil($total_items / $per_page); $offset = ($current_page - 1) * $per_page; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); ?>
plugin->render_per_page_selector( $per_page ); ?>
add_query_arg([ 'paged' => '%#%', 's' => $search_term, 'advaipbl_per_page' => $per_page, ]), 'format' => '', 'total' => $total_pages, 'current' => $current_page ]); if ($page_links) echo wp_kses_post($page_links); ?>

plugin->print_log_sortable_header(__('Date/Time', 'advanced-ip-blocker'), 'timestamp', $orderby, $order); ?> plugin->print_log_sortable_header(__('IP Address', 'advanced-ip-blocker'), 'ip', $orderby, $order); ?>
'; foreach ( $details['due_hooks'] as $hook ) { echo '
  • ' . esc_html( $hook ) . '
  • '; } echo ''; } else { echo '–'; } ?>
    plugin->options['geolocation_provider'] ?? ''; $is_compatible = in_array($provider, ['ip-api.com', 'ipinfo.io'], true); $is_spamhaus_enabled = !empty($this->plugin->options['enable_spamhaus_asn']); $is_manual_enabled = !empty($this->plugin->options['enable_manual_asn']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings'); $spamhaus_stats = $this->plugin->dashboard_manager->get_spamhaus_stats(); ?>

    Warning: Your current geolocation provider (%1$s) does not support ASN lookups. This feature is fully supported by ip-api.com and ipinfo.io. Please change your provider to use ASN blocking.', 'advanced-ip-blocker'), ['strong' => [], 'a' => ['href' => []]] ), esc_html($provider), esc_url($settings_url) ); ?>




    prefix . 'advaipbl_malicious_signatures'; $is_enabled = !empty($this->plugin->options['enable_signature_blocking']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings#section-signature_engine'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: 1: Status (Enabled/Disabled), 2: Link to settings page. */ __('The Attack Signature Blocking system is currently %1$s. You can change this in the Settings.', 'advanced-ip-blocker'), [ 'span' => ['class' => true], 'a' => ['href' => []] ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $status_tag, esc_url($settings_url) ); ?>

    get_var("SELECT COUNT(id) FROM {$table_name}"); $total_pages = ceil($total_items / $per_page); $offset = ($current_page - 1) * $per_page; $query = "SELECT * FROM {$table_name} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d"; // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $items = $wpdb->get_results($wpdb->prepare($query, $per_page, $offset), ARRAY_A); // phpcs:enable ?>

    plugin->render_per_page_selector($per_page); ?>
    add_query_arg('paged', '%#%'), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) echo wp_kses_post($page_links); ?>

    plugin->print_log_sortable_header(__('Signature Hash', 'advanced-ip-blocker'), 'signature_hash', $orderby, $order); ?> plugin->print_log_sortable_header(__('Reason', 'advanced-ip-blocker'), 'reason', $orderby, $order); ?> plugin->print_log_sortable_header(__('Last Seen', 'advanced-ip-blocker'), 'last_seen', $orderby, $order); ?> plugin->print_log_sortable_header(__('Expires In', 'advanced-ip-blocker'), 'expires_at', $orderby, $order); ?>

    prefix . 'advaipbl_endpoint_lockdowns'; // Array para definir los endpoints que soportan lockdown $lockdown_endpoints = [ 'xmlrpc' => [ 'name' => 'XML-RPC', 'option' => 'enable_xmlrpc_lockdown', 'anchor' => '#sub-section-xmlrpc-lockdown' ], 'login' => [ 'name' => 'Login Page (wp-login.php)', 'option' => 'enable_login_lockdown', 'anchor' => '#sub-section-login-lockdown' ], '404' => [ 'name' => '404 Errors', 'option' => 'enable_404_lockdown', 'anchor' => '#section-blocking_rules' ], '403' => [ 'name' => '403 Errors', 'option' => 'enable_403_lockdown', 'anchor' => '#section-blocking_rules' ], ]; $settings_base_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings'); $status_parts = []; foreach ($lockdown_endpoints as $key => $details) { $is_enabled = !empty($this->plugin->options[$details['option']]); $status_tag = sprintf( '%s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); $settings_link = sprintf( '%s', esc_url($settings_base_url . $details['anchor']), esc_html__('Configure', 'advanced-ip-blocker') ); /* translators: 1: Endpoint name (e.g., XML-RPC), 2: Status tag (Active/Inactive), 3: Link to configure */ $status_parts[] = sprintf('%1$s: %2$s (%3$s)', esc_html($details['name']), $status_tag, $settings_link); } ?>

    [], 'span' => ['class' => true], 'a' => ['href' => true], ]); ?>

    query($wpdb->prepare("DELETE FROM {$table_name} WHERE expires_at <= %d", time())); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $items = $wpdb->get_results("SELECT * FROM {$table_name} ORDER BY created_at DESC", ARRAY_A); ?>


    'advaipbl_delete_lockdown', 'lockdown_id' => $item['id'] ]), 'advaipbl_delete_lockdown_' . $item['id'] ); ?>
    plugin->options['enable_waf']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings#sub-section-waf'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: 1: Status tag (Active/Inactive), 2: Link to settings page. */ __('Web Application Firewall (WAF) is currently %1$s. You can change this in the Settings.', 'advanced-ip-blocker'), [ 'span' => ['class' => true], 'a' => ['href' => []] ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $status_tag, esc_url($settings_url) ); ?>


    plugin->options = get_option(ADVAIPBL_Main::OPTION_SETTINGS); $sections = [ 'general' => __('General', 'advanced-ip-blocker'), 'notifications' => __('Notifications', 'advanced-ip-blocker'), 'htaccess' => __('Server Firewall (.htaccess)', 'advanced-ip-blocker'), 'cloudflare' => __('Cloud Edge Defense', 'advanced-ip-blocker'), 'ip_detection' => __('IP Detection', 'advanced-ip-blocker'), 'geolocation' => __('Geolocation', 'advanced-ip-blocker'), 'threat_intelligence' => __('Threat Intelligence', 'advanced-ip-blocker'), 'protections' => __('Core Protections', 'advanced-ip-blocker'), 'blocking_rules' => __('Threshold Blocking', 'advanced-ip-blocker'), 'ip_trust' => __('IP Trust & Scoring', 'advanced-ip-blocker'), 'login_protection' => __('Login Protection', 'advanced-ip-blocker'), 'signature_engine' => __('Signature Engine', 'advanced-ip-blocker'), 'internal_security' => __('Internal Security', 'advanced-ip-blocker'), 'uninstall' => __('Uninstallation', 'advanced-ip-blocker'), ]; // Obtener estadísticas de la lista comunitaria $community_stats = $this->plugin->community_manager->get_stats(); $list_count = $community_stats['count'] ?? 0; $last_update = $community_stats['last_update'] ?? 0; ?>

    '; echo '' . esc_html__('Compatibility Warning:', 'advanced-ip-blocker') . ' '; echo esc_html__('Your server appears to be running Nginx independently. Nginx does NOT support .htaccess files. Enabling these options will write to the file, but the server will likely ignore them.', 'advanced-ip-blocker'); echo '

    '; } ?>

    plugin->htaccess_manager->is_writable()) : ?>

    X-Forwarded-For if the request comes from one of these IPs, preventing IP spoofing.', 'advanced-ip-blocker'); ?>

    free API key is required.', 'advanced-ip-blocker'), ['a' => ['href' => [], 'target' => []]] ), 'https://www.abuseipdb.com/pricing' ); ?>

    plugin->options['enable_community_blocking'] ) ) : ?>
    0 ) { printf( wp_kses( /* translators: 1: Number of IPs, 2: Time since last update. */ __( 'Blocking %1$s known malicious IPs. Updated %2$s ago.', 'advanced-ip-blocker' ), [ 'strong' => [] ] // Permitimos la etiqueta strong ), '' . esc_html( number_format_i18n( $list_count ) ) . '', esc_html( human_time_diff( $last_update ) ) ); } else { esc_html_e('Waiting for initial download...', 'advanced-ip-blocker'); } ?>

    plugin->options['allow_telemetry'])) : $telemetry_setting_id = 'advaipbl_allow_telemetry'; ?>

    Enable anonymous usage tracking.', 'advanced-ip-blocker'), ['a' => ['href' => []]]), '#' . esc_attr($telemetry_setting_id)); ?>

    plugin->options['enable_2fa']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings#sub-section-2FA'); $profile_url = admin_url('profile.php'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: %1$s: Status tag (Active/Inactive), %2$s: Link to Settings, %3$s: Link to Profile. */ __('Two-Factor Authentication (2FA) is currently %1$s. You can change this in the Settings. When enabled, users will see the 2FA setup section in their Profile.', 'advanced-ip-blocker'), [ 'span' => ['class' => true], 'a' => ['href' => true], ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $status_tag, esc_url($settings_url), esc_url($profile_url) ); ?>

    process_bulk_action(); $users_list_table->prepare_items(); ?>


    views(); ?>
    search_box( __( 'Search Users', 'advanced-ip-blocker' ), 'user' ); $users_list_table->display(); ?>
    plugin->options['enable_user_agent_blocking']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings#sub-section-user-agent'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: 1: Status tag (Active/Inactive), 2: Link to settings page. */ __('User-Agent Protection is currently %1$s. You can change this in the Settings.', 'advanced-ip-blocker'), [ 'span' => ['class' => true], 'a' => ['href' => []] ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $status_tag, esc_url($settings_url) ); ?>


    plugin->options['enable_honeypot_blocking']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings#sub-section-honeypot'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: 1: Status tag (Active/Inactive), 2: Link to settings page. */ __('Honeypot Protection is currently %1$s. You can change this in the Settings.', 'advanced-ip-blocker'), [ 'span' => ['class' => true], 'a' => ['href' => []] ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $status_tag, esc_url($settings_url) ); ?>

    /blog/ or /contact/). Use attack-specific patterns.', 'advanced-ip-blocker') ); ?>


    prefix . 'advaipbl_blocked_ips'; // phpcs:disable WordPress.Security.NonceVerification.Recommended $filter_type = isset($_GET['filter_type']) ? sanitize_key($_GET['filter_type']) : 'all'; $search_term = isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''; $orderby = isset($_GET['orderby']) && in_array($_GET['orderby'], ['ip_range', 'block_type', 'timestamp'], true) ? sanitize_key($_GET['orderby']) : 'timestamp'; $order = isset($_GET['order']) && in_array(strtolower($_GET['order']), ['asc', 'desc'], true) ? strtolower(sanitize_key($_GET['order'])) : 'desc'; $current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; $per_page = isset($_GET['advaipbl_per_page']) ? absint($_GET['advaipbl_per_page']) : 20; // phpcs:enable $offset = ($current_page - 1) * $per_page; $where_clauses = []; if ('all' !== $filter_type) { $where_clauses[] = $wpdb->prepare("block_type = %s", $filter_type); } // Add Search Clause if (!empty($search_term)) { $search_like = '%' . $wpdb->esc_like($search_term) . '%'; $where_clauses[] = $wpdb->prepare("ip_range LIKE %s", $search_like); } $where_sql = !empty($where_clauses) ? 'WHERE ' . implode(' AND ', $where_clauses) : ''; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name} {$where_sql}"); $total_pages = ceil($total_items / $per_page); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $items_for_page = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$table_name} {$where_sql} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); $ips_and_ranges_on_page = wp_list_pluck($items_for_page, 'ip_range'); $single_ips_on_page = array_filter($ips_and_ranges_on_page, function($entry) { return filter_var($entry, FILTER_VALIDATE_IP); }); $locations = !empty($single_ips_on_page) ? $this->plugin->session_manager->get_cached_locations($single_ips_on_page) : []; $definitions = $this->plugin->get_all_block_type_definitions(); ?>

    plugin->render_per_page_selector($per_page); ?>
    add_query_arg(['paged' => '%#%', 'filter_type' => $filter_type, 's' => $search_term, 'advaipbl_per_page' => $per_page]), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) echo wp_kses_post($page_links); ?>


    plugin->print_sortable_header(__('IP', 'advanced-ip-blocker'), 'ip_range', $orderby, $order); ?> plugin->print_sortable_header(__('Block Type', 'advanced-ip-blocker'), 'block_type', $orderby, $order); ?> plugin->print_sortable_header(__('Since', 'advanced-ip-blocker'), 'timestamp', $orderby, $order); ?>
    1 año, legacy permanent), lo mostramos como permanente. if ($block['block_type'] === 'manual' || $duration_seconds <= 0 || $duration_seconds > 31536000) { esc_html_e('Permanent', 'advanced-ip-blocker'); } else { $duration_minutes = round($duration_seconds / 60); printf( /* translators: %d: The number of minutes for a block duration. */ esc_html__('%d minutes', 'advanced-ip-blocker'), (int) $duration_minutes ); } } ?> '; } } else { esc_html_e( 'Not available', 'advanced-ip-blocker' ); } ?> 'advaipbl_unblock_ip', 'ip' => $block['ip_range']]), 'advaipbl_unblock_ip' ); ?>

    $data) { if ( is_array($data) && isset($data['timestamp']) ) { $table_data[] = [ 'ip' => $ip, 'timestamp' => $data['timestamp'], 'detail' => $data['detail'] ?? '' ]; } elseif ( is_numeric($data) ) { $table_data[] = [ 'ip' => $ip, 'timestamp' => $data, 'detail' => __('Migrated from old format', 'advanced-ip-blocker') ]; } } } // phpcs:disable WordPress.Security.NonceVerification.Recommended $sortable_columns = ['ip', 'timestamp', 'detail']; $orderby = isset($_GET['orderby']) && in_array($_GET['orderby'], $sortable_columns, true) ? sanitize_key($_GET['orderby']) : 'timestamp'; $order = isset($_GET['order']) && in_array(strtolower($_GET['order']), ['asc', 'desc'], true) ? strtolower(sanitize_key($_GET['order'])) : 'desc'; // phpcs:enable usort($table_data, function($a, $b) use ($orderby, $order) { $a_val = $a[$orderby] ?? ''; $b_val = $b[$orderby] ?? ''; if ($a_val == $b_val) return 0; return ($order === 'asc') ? strnatcasecmp((string)$a_val, (string)$b_val) : strnatcasecmp((string)$b_val, (string)$a_val); }); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $per_page = isset($_GET['advaipbl_per_page']) ? absint($_GET['advaipbl_per_page']) : 20; $total_items = count($table_data); $total_pages = ceil($total_items / $per_page); $items_for_page = array_slice($table_data, ($current_page - 1) * $per_page, $per_page); $ips_on_page = wp_list_pluck($items_for_page, 'ip'); $locations = $this->plugin->session_manager->get_cached_locations($ips_on_page); ?>

    plugin->render_per_page_selector($per_page); ?>
    add_query_arg('paged', '%#%'), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) echo wp_kses_post($page_links); ?>


    plugin->print_log_sortable_header(__('IP / Location', 'advanced-ip-blocker'), 'ip', $orderby, $order); ?> plugin->print_log_sortable_header(__('User', 'advanced-ip-blocker'), 'user', $orderby, $order); ?> plugin->print_log_sortable_header(__('Details', 'advanced-ip-blocker'), 'detail', $orderby, $order); ?> plugin->print_log_sortable_header(__('Added Since', 'advanced-ip-blocker'), 'timestamp', $orderby, $order); ?>
    ' . esc_html(implode(', ', $location_parts)) . ''; } ?> ' . esc_html($matches[1]) . ''; echo '
    ' . esc_html($matches[2]) . ''; } ?>
    0 ? esc_html(ADVAIPBL_Main::get_formatted_datetime($item['timestamp'])) : '...'; ?>

    display_log_table_generic($security_log_types, ['critical', 'warning']); } /** * Muestra la pestaña de logs generales (auditoría), restaurada a su formato original. */ public function display_general_log_tab() { if (empty($this->plugin->options['enable_logging'])) { echo '

    ' . esc_html__('General event logging is disabled in the "Settings" tab.', 'advanced-ip-blocker') . '

    '; return; } // phpcs:disable WordPress.Security.NonceVerification.Recommended // phpcs:disable WordPress.Security.NonceVerification.Recommended $search_term = isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''; $orderby = isset($_GET['orderby']) && in_array($_GET['orderby'], ['timestamp', 'level', 'ip', 'message'], true) ? sanitize_key($_GET['orderby']) : 'timestamp'; $order = isset($_GET['order']) && in_array(strtolower($_GET['order']), ['asc', 'desc'], true) ? strtolower(sanitize_key($_GET['order'])) : 'desc'; $current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; $per_page = isset($_GET['advaipbl_per_page']) ? absint($_GET['advaipbl_per_page']) : 25; // phpcs:enable // phpcs:enable global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $where_clauses = [$wpdb->prepare("log_type = %s", 'general')]; if (!empty($search_term)) { $search_like = '%' . $wpdb->esc_like($search_term) . '%'; $where_clauses[] = $wpdb->prepare("(ip LIKE %s OR message LIKE %s)", $search_like, $search_like); } $where_sql = implode(' AND ', $where_clauses); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql"); $total_pages = ceil($total_items / $per_page); $offset = ($current_page - 1) * $per_page; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); ?>

    plugin->render_per_page_selector( $per_page ); ?>
    add_query_arg('paged', '%#%'), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) echo wp_kses_post($page_links); ?>

    plugin->print_log_sortable_header(__('Date/Time', 'advanced-ip-blocker'), 'timestamp', $orderby, $order); ?> plugin->print_log_sortable_header(__('Level', 'advanced-ip-blocker'), 'level', $orderby, $order); ?> plugin->print_log_sortable_header(__('IP', 'advanced-ip-blocker'), 'ip', $orderby, $order); ?> plugin->print_log_sortable_header(__('Message', 'advanced-ip-blocker'), 'message', $orderby, $order); ?>
    prefix . 'advaipbl_ip_scores'; $is_enabled = !empty($this->plugin->options['enable_threat_scoring']); $settings_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings#section-ip_trust'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: 1: Status tag (Active/Inactive), 2: Link to settings page. */ __('The Threat Scoring System is currently %1$s. You can change this in the Settings.', 'advanced-ip-blocker'), [ 'span' => ['class' => true], 'a' => ['href' => []] ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $status_tag, esc_url($settings_url) ); ?>

    0"]; if (!empty($search_term)) { $where_clauses[] = $wpdb->prepare("ip LIKE %s", '%' . $wpdb->esc_like($search_term) . '%'); } $where_sql = implode(' AND ', $where_clauses); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name} WHERE {$where_sql}"); $total_pages = ceil($total_items / $per_page); $offset = ($current_page - 1) * $per_page; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $items = $wpdb->get_results($wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared "SELECT * FROM {$table_name} WHERE {$where_sql} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset ), ARRAY_A); $ips_on_page = wp_list_pluck($items, 'ip'); $locations = $this->plugin->session_manager->get_cached_locations($ips_on_page); $threshold = (int) ($this->plugin->options['threat_score_threshold'] ?? 100); ?>

    plugin->render_per_page_selector($per_page); ?>
    add_query_arg('paged', '%#%'), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) echo wp_kses_post($page_links); ?>

    plugin->print_log_sortable_header(__('IP / Location', 'advanced-ip-blocker'), 'ip', $orderby, $order); ?> plugin->print_log_sortable_header(__('Current Score', 'advanced-ip-blocker'), 'score', $orderby, $order); ?> plugin->print_log_sortable_header(__('Last Activity', 'advanced-ip-blocker'), 'last_event_timestamp', $orderby, $order); ?>
    ' . esc_html(trim("$city, $country", ', ')) . ''; } ?> 0 ? min(100, ($item['score'] / $threshold) * 100) : 100; $progress_color = $score_percentage > 80 ? '#dc3232' : ($score_percentage > 50 ? '#f59e0b' : '#0073aa'); ?>

    ' . esc_html(ucfirst(str_replace('_', ' ', $last_event['event']))) . ''; echo ' (+ ' . esc_html($last_event['points']) . ' ' . esc_html__('points', 'advanced-ip-blocker') . ')'; } ?>
    __('General System Event Log', 'advanced-ip-blocker'), 'wp_cron' => __('WP-Cron Execution Log', 'advanced-ip-blocker'), ]; $title = $titles[$log_types] ?? ucfirst($log_types) . ' Log'; $current_sub_tab = ($log_types === 'general') ? 'general_log' : $log_types . '_logs'; } // phpcs:disable WordPress.Security.NonceVerification.Recommended $search_term = isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''; $orderby = isset($_GET['orderby']) && in_array($_GET['orderby'], ['timestamp', 'ip', 'log_type', 'message'], true) ? sanitize_key($_GET['orderby']) : 'timestamp'; $order = isset($_GET['order']) && in_array(strtolower($_GET['order']), ['asc', 'desc'], true) ? strtolower(sanitize_key($_GET['order'])) : 'desc'; $current_page = isset($_GET['paged']) ? absint($_GET['paged']) : 1; $per_page = isset($_GET['advaipbl_per_page']) ? absint($_GET['advaipbl_per_page']) : 20; $hide_community = isset($_GET['hide_community']) && $_GET['hide_community'] === '1'; // phpcs:enable global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $where_clauses = []; $level_placeholders = implode(', ', array_fill(0, count($levels_to_show), '%s')); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare $where_clauses[] = $wpdb->prepare("level IN ({$level_placeholders})", ...$levels_to_show); if ($is_unified_log) { $types_to_query = ($current_filter !== 'all' && in_array($current_filter, $log_types)) ? [$current_filter] : $log_types; if (!empty($types_to_query)) { $placeholders = implode(', ', array_fill(0, count($types_to_query), '%s')); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare $where_clauses[] = $wpdb->prepare("log_type IN ({$placeholders})", ...$types_to_query); } } else { $where_clauses[] = $wpdb->prepare("log_type = %s", $log_types); } if (!empty($search_term)) { $search_like = '%' . $wpdb->esc_like($search_term) . '%'; $where_clauses[] = $wpdb->prepare("(ip LIKE %s OR details LIKE %s OR message LIKE %s)", $search_like, $search_like, $search_like); } if ($is_unified_log && $hide_community && $current_filter !== 'aib_network') { $where_clauses[] = "log_type != 'aib_network'"; } $where_sql = implode(' AND ', $where_clauses); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql"); $total_pages = ceil($total_items / $per_page); $offset = ($current_page - 1) * $per_page; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A); ?>

    plugin->render_per_page_selector( $per_page ); ?>
    add_query_arg('paged', '%#%'), 'format' => '', 'total' => $total_pages, 'current' => $current_page]); if ($page_links) echo wp_kses_post($page_links); ?>

    plugin->print_log_sortable_header(__('Date/Time', 'advanced-ip-blocker'), 'timestamp', $orderby, $order); ?> plugin->print_log_sortable_header(__('IP', 'advanced-ip-blocker'), 'ip', $orderby, $order); ?> plugin->print_log_sortable_header(__('Type', 'advanced-ip-blocker'), 'log_type', $orderby, $order); ?>
    plugin->options['duration_' . $log_type])) { $duration_minutes = (int) $this->plugin->options['duration_' . $log_type]; } $duration_text = ''; if ($duration_minutes <= 0) { $duration_text = __('Permanent', 'advanced-ip-blocker'); } else { /* translators: %d: The number of minutes for a block duration. */ $duration_text = sprintf(esc_html__('%d min', 'advanced-ip-blocker'), $duration_minutes); } echo '
    ' . esc_html__('Blocked:', 'advanced-ip-blocker') . ' ' . esc_html($duration_text); } ?>
    ' . implode(', ', $location_parts) . ''; } ?> plugin->get_all_block_type_definitions()[$log_type]['label'] ?? ucwords(str_replace('_', ' ', $log_type))); ?> ' . esc_html__('User:', 'advanced-ip-blocker') . ' ' . esc_html($details['username'] ?? 'N/A'); break; case 'waf': $detail_display = '' . esc_html__('Rule:', 'advanced-ip-blocker') . ' ' . esc_html($details['rule'] ?? 'N/A'); if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'asn': $detail_display = esc_html($details['asn_number'] ?? 'N/A') . ' (' . esc_html($details['asn_name'] ?? '') . ')'; if (!empty($details['source'])) { $detail_display .= ' - ' . __('Source:', 'advanced-ip-blocker') . ' ' . esc_html($details['source']); } if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'threat_score': $detail_display = esc_html($entry['message']); if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'advanced_rule': $level = $entry['level']; $rule_name_html = '' . esc_html__('Rule:', 'advanced-ip-blocker') . ' ' . esc_html($details['rule_name'] ?? 'N/A'); if ($level === 'critical') { // Block $detail_display = $rule_name_html; } elseif ($level === 'warning') { // Challenge $detail_display = $rule_name_html; } else { // Score (info) $points = $details['points_added'] ?? 0; $detail_display = $rule_name_html . ' (+ ' . esc_html($points) . ' ' . esc_html__('points', 'advanced-ip-blocker') . ')'; } if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'geo_challenge': $country_name = esc_html($details['country'] ?? 'N/A'); $detail_display = '' . esc_html__('Country:', 'advanced-ip-blocker') . ' ' . $country_name; if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'signature_challenge': $detail_display = esc_html($entry['message']); if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'signature_flagged': $hash = $details['signature_hash'] ?? 'N/A'; $short_hash = substr($hash, 0, 12) . '...'; $detail_display = '' . esc_html__('Signature:', 'advanced-ip-blocker') . ' ' . esc_html($short_hash) . ''; $detail_display .= '
    ' . esc_html($entry['message']) . ''; break; case 'endpoint_challenge': $reason = $details['reason'] ?? $entry['message']; $detail_display = '' . esc_html($reason) . ''; if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case 'login_geoblock': $detail_display = '' . esc_html($entry['message']) . ''; if (!empty($uri)) { $detail_display .= '
    ' . $uri . ''; } break; case '404': case '403': case 'honeypot': default: $detail_display = !empty($uri) ? $uri : esc_html($entry['message']); break; } echo wp_kses_post($detail_display); ?>

    • Stripe
    • bc1qxfsmpqk0q7an82ckm7380pzpsea2sa294824lg
    • 0xAF8CC1B71EAbF5dffDa2aF58AEF43b2559163284

    
    # General Help
    wp help advaipbl
    
    # IP Management
    wp advaipbl block <ip> [--reason=<reason>]
    wp advaipbl unblock <ip>
    wp advaipbl whitelist <add|remove|list> [<ip>]
    
    # Threat Scoring & Signatures
    wp advaipbl score <list|get|reset|decay-run> [--ip=<ip>]
    wp advaipbl signature <list|delete|whitelist> [--hash=<hash>]
    wp advaipbl signature-analyze
    
    # Geolocation, ASN & WAF
    wp advaipbl geoblock <add|remove|list> <country_code>
    wp advaipbl asn <add|remove|list> <asn>
    wp advaipbl asn-whitelist <add|remove|list> <asn>
    wp advaipbl waf <add|remove|list> [<rule>] [--from-file=<file>]
    
    # User & Session Management
    wp advaipbl session <list|terminate> [--user-id=<id>]
    wp advaipbl 2fa <status|reset> <user>
    
    # System & Config
    wp advaipbl log <list|clear> [--type=<type>] [--count=<number>]
    wp advaipbl config <get|set> [<key>] [<value>]
    wp advaipbl provider <list|set|set_key|remove_key>
    wp advaipbl spamhaus-update
    

    plugin->get_ip_intelligence(); $server_ip = $this->plugin->get_server_ip(); $client_ip = $ip_data['visitor_ip'] ?? 'N/A'; ?>

    plugin->get_remote_addr(); $client_ip = $this->plugin->get_client_ip(); if ( $remote_addr && $client_ip !== $remote_addr && filter_var( $remote_addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) { echo '

    '; /* translators: %1$s: Client's real IP. %2$s: Proxy/CDN IP. */ echo '' . esc_html__( 'Info:', 'advanced-ip-blocker' ) . ' ' . sprintf( esc_html__( 'It seems your site is behind a reverse proxy or CDN. Your IP is correctly detected as %1$s, while your server connects through %2$s. This is a normal and correct configuration.', 'advanced-ip-blocker' ), '' . esc_html( $client_ip ) . '', '' . esc_html( $remote_addr ) . '' ); echo '

    '; $has_recommendations = true; } // Comprobación de la IP del servidor if ( ! $this->plugin->get_server_ip() ) { echo '

    '; echo '' . esc_html__( 'Warning:', 'advanced-ip-blocker' ) . ' ' . esc_html__( 'The plugin could not automatically determine your server\'s public IP. The feature that adds the server IP to the whitelist on activation will not work. Please add your server IP to the whitelist manually to prevent any issues with geoblocking or other functionalities.', 'advanced-ip-blocker' ); echo '

    '; $has_recommendations = true; } $xmlrpc_plugins = $this->plugin->get_xmlrpc_dependent_plugins(); if ( ! empty( $xmlrpc_plugins ) ) : ?>


    '; echo '' . esc_html__( 'All Clear!', 'advanced-ip-blocker' ) . ' ' . esc_html__( 'No potential configuration issues were detected.', 'advanced-ip-blocker' ); echo '

    '; } ?>



    plugin->get_client_ip(); $server_ip = $this->plugin->get_server_ip(); $is_cloudflare = isset($_SERVER['HTTP_CF_CONNECTING_IP']); ?>

    plugin->options['enable_threat_scoring']); $is_geolocation_ready = !empty($this->plugin->options['geolocation_provider']); $settings_base_url = admin_url('admin.php?page=advaipbl_settings_page-settings&sub-tab=general_settings'); $status_parts = []; $status_parts[] = sprintf( '%1$s: %3$s (%5$s)', esc_html__('Threat Scoring', 'advanced-ip-blocker'), $is_threat_scoring_enabled ? 'enabled' : 'disabled', $is_threat_scoring_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker'), esc_url($settings_base_url . '#section-ip_trust'), esc_html__('configure', 'advanced-ip-blocker') ); $status_parts[] = sprintf( '%1$s: %3$s (%5$s)', esc_html__('Geolocation', 'advanced-ip-blocker'), $is_geolocation_ready ? 'enabled' : 'disabled', $is_geolocation_ready ? esc_html__('Ready', 'advanced-ip-blocker') : esc_html__('Not Configured', 'advanced-ip-blocker'), esc_url($settings_base_url . '#section-geolocation'), esc_html__('configure', 'advanced-ip-blocker') ); ?>


    ', $status_parts), [ 'strong' => [], 'span' => ['class' => true], 'a' => ['href' => []], 'br' => [] ]); ?>

    plugin->site_scanner->run_local_scan(); $get_icon = function($status) { switch($status) { case 'good': return ''; case 'warning': return ''; case 'critical': return ''; default: return ''; } }; ?>

    PHP Version
    Database
    SSL (HTTPS)

    Version
    Debug Mode

    0) : ?>
      $data) { if ($count >= 5) { echo '
    • ...and more
    • '; break; } // Intentar obtener nombre legible si está disponible en el objeto, sino usar slug $name = $slug; // (Nota: el objeto de update_plugins es complejo, usar slug es seguro por ahora) echo '
    • ' . esc_html($slug) . '
    • '; $count++; } ?>

    $theme) : ?>
    ' . esc_html__('Parent Theme', 'advanced-ip-blocker') . ''; } elseif ($theme['is_active'] && !$theme['is_parent'] && $theme['is_active']) { // is child // Simplificación: sies activo y no es padre, suele ser hijo o standalone. // La logica exacta de "padre" depende de si OTRO tema lo usa. // Aqui simplificamos: Si un active_theme tiene parent(), el active es Child. // El parent fue marcado en el loop. echo esc_html__('Standard / Child', 'advanced-ip-blocker'); } else { echo esc_html__('Inactive', 'advanced-ip-blocker'); } ?>

    ' . esc_html__('You do not have permission to view this log.', 'advanced-ip-blocker') . '

    '; return; } $is_enabled = !empty($this->plugin->options['enable_audit_log']) && '1' === $this->plugin->options['enable_audit_log']; $settings_url = admin_url('admin.php?page=advaipbl_settings_page&tab=settings&sub-tab=general_settings#section-internal_security'); ?>

    %s', $is_enabled ? 'enabled' : 'disabled', $is_enabled ? esc_html__('Active', 'advanced-ip-blocker') : esc_html__('Inactive', 'advanced-ip-blocker') ); printf( wp_kses( /* translators: 1: Status tag (Active/Inactive), 2: Link to settings page. */ __('Activity Logging is currently %1$s. You can configure this feature in the Settings tab.', 'advanced-ip-blocker'), ['a' => ['href' => []], 'span' => ['class' => []]] ), wp_kses_post($status_tag), esc_url($settings_url) ); ?>

    prefix . 'advaipbl_activity_log'; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { $logs = []; $total_items = 0; $total_pages = 0; } else { // Fetch logs $logs = $this->plugin->audit_logger->get_logs($per_page, $offset); // Count total for pagination (Simple implementation) // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $total_items = $wpdb->get_var("SELECT COUNT(id) FROM $table_name"); $total_pages = ceil($total_items / $per_page); } ?>
    add_query_arg('paged', '%#%'), 'format' => '', 'total' => $total_pages, 'current' => $current_page ]); if ($page_links) echo wp_kses_post($page_links); ?>

    user_login : __('System/Guest', 'advanced-ip-blocker'); $details = json_decode($log['details'], true); $formatted_details = $details ? '
    ' . esc_html(json_encode($details, JSON_PRETTY_PRINT)) . '
    ' : ''; ?>

    (ID: )