From b66b9fa0e74fef46411b5c29a29d0920b1644ba5 Mon Sep 17 00:00:00 2001 From: Glomberg Date: Thu, 24 Sep 2026 14:38:01 +0300 Subject: [PATCH] Upd. Security log. Actions buttons updated. --- inc/spbc-settings.php | 95 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/inc/spbc-settings.php b/inc/spbc-settings.php index bba9da98d..e819519bf 100644 --- a/inc/spbc-settings.php +++ b/inc/spbc-settings.php @@ -680,32 +680,103 @@ function spbc_field_options_overview_traffic_light() return $groups; } +/** + * Get personal (allow/ban) statuses for the given list of IP addresses. + * Mirrors the network/mask matching logic used for the Firewall log (View::getFirewallRows()) + * but works from raw IP addresses instead of the pre-computed network/mask log columns. + * + * @param array $ips IP addresses (IPv6 addresses expected to be already normalized) + * @return array IP address => status (1 - allowed, 0/negative - banned, null - no personal record) + */ +function spbc_field_security_logs__get_personal_statuses($ips) +{ + global $wpdb; + + $statuses = array(); + $ipv6_rows = null; + + foreach (array_unique($ips) as $ip) { + if (IP::validate($ip) === 'v6') { + if ($ipv6_rows === null) { + // @psalm-suppress WpdbUnsafeMethodsIssue + $ipv6_rows = $wpdb->get_results( + 'SELECT network1, network2, network3, network4, mask1, mask2, mask3, mask4, status FROM ' + . SPBC_TBL_FIREWALL_DATA__IPS_V6, + ARRAY_A + ); + $ipv6_rows = $ipv6_rows ?: array(); + } + + $extended_ip = IP::extendIPv6(IP::normalizeIPv6($ip) ?: $ip); + $max_status = null; + foreach ($ipv6_rows as $row) { + $hex_network = str_pad(dechex($row['network1']), 8, '0', STR_PAD_LEFT) + . str_pad(dechex($row['network2']), 8, '0', STR_PAD_LEFT) + . str_pad(dechex($row['network3']), 8, '0', STR_PAD_LEFT) + . str_pad(dechex($row['network4']), 8, '0', STR_PAD_LEFT); + $network = implode(':', str_split($hex_network, 4)); + if (IP::validate($network) !== 'v6') { + continue; + } + $mask = IP::convertLongIntMaskToDec($row['mask1']) + + IP::convertLongIntMaskToDec($row['mask2']) + + IP::convertLongIntMaskToDec($row['mask3']) + + IP::convertLongIntMaskToDec($row['mask4']); + if (IP::isIpv6AddrInIpv6Network($extended_ip, $network, $mask) === 1) { + $status = (int)$row['status']; + if ($max_status === null || $status > $max_status) { + $max_status = $status; + } + } + } + $statuses[$ip] = $max_status; + } elseif (IP::validate($ip) === 'v4') { + $ip_uint = sprintf('%u', ip2long($ip)); + // @psalm-suppress WpdbUnsafeMethodsIssue + $status = $wpdb->get_var( + 'SELECT MAX(status) FROM ' . SPBC_TBL_FIREWALL_DATA__IPS_V4 . ' WHERE network = (' . $ip_uint . ' & mask)' + ); + $statuses[$ip] = $status !== null ? (int)$status : null; + } else { + $statuses[$ip] = null; + } + } + + return $statuses; +} + function spbc_field_security_logs__prepare_data(&$table) { if ($table->items_count) { + $personal_status_ips = array(); foreach ($table->rows as $row) { $ips_c[] = $row->auth_ip; + $personal_status_ips[] = $row->auth_ip; } unset($row); $ips_c = spbc_get_countries_by_ips(implode(',', $ips_c)); + $personal_statuses = spbc_field_security_logs__get_personal_statuses($personal_status_ips); $time_offset = current_time('timestamp') - time(); foreach ($table->rows as $row) { - // we need to use normalized IPv6 address for allow/ban actions - $ip = IP::validate($row->auth_ip) === 'v6' - ? (IP::normalizeIPv6($row->auth_ip) ?: $row->auth_ip) - : $row->auth_ip; + $ip = $row->auth_ip; $ip_attr = Escape::escAttr($ip); $ip_js = Escape::escJs($ip); - $allow_layout = '' - . esc_html__('Allow', 'security-malware-firewall') . ''; - $ban_layout = '' - . esc_html__('Ban', 'security-malware-firewall') . ''; + $personal_status = isset($personal_statuses[$ip]) ? $personal_statuses[$ip] : null; + + $allow_layout = ($personal_status !== null && $personal_status > 0) + ? '' . esc_html__('Allowed', 'security-malware-firewall') . '' + : '' + . esc_html__('Allow', 'security-malware-firewall') . ''; + $ban_layout = ($personal_status !== null && $personal_status <= 0) + ? '' . esc_html__('Banned', 'security-malware-firewall') . '' + : '' + . esc_html__('Ban', 'security-malware-firewall') . ''; $user_part = $row->user_login; $user = get_user_by('login', $row->user_login);