From 69feb78ed73af0cc5ce6c8877f6c3d9edc7be2f2 Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Wed, 8 Apr 2026 22:59:36 -0700 Subject: [PATCH 1/6] refactor(php74): use null coalescing (??) and ??= operators Signed-off-by: Thomas Vincent --- lib/mactrack_3com.php | 6 ++---- lib/mactrack_aruba_oscx.php | 10 +++------- lib/mactrack_cabletron.php | 4 +--- lib/mactrack_cisco.php | 12 +++--------- lib/mactrack_dell.php | 4 +--- lib/mactrack_dlink.php | 8 ++------ lib/mactrack_enterasys.php | 4 +--- lib/mactrack_enterasys_N7.php | 10 +++------- lib/mactrack_extreme.php | 8 ++------ lib/mactrack_foundry.php | 4 +--- lib/mactrack_functions.php | 20 +++++--------------- lib/mactrack_h3c_3com.php | 10 +++------- lib/mactrack_hp.php | 4 +--- lib/mactrack_hp_ng.php | 4 +--- lib/mactrack_hp_ngi.php | 4 +--- lib/mactrack_juniper.php | 4 +--- lib/mactrack_linux.php | 4 +--- lib/mactrack_norbay.php | 4 +--- lib/mactrack_norbay_ng.php | 4 +--- lib/mactrack_tplink.php | 4 +--- lib/mactrack_trendnet.php | 4 +--- mactrack_actions.php | 16 ++++++---------- mactrack_device_types.php | 2 +- mactrack_devices.php | 2 +- mactrack_macauth.php | 2 +- mactrack_macwatch.php | 2 +- mactrack_sites.php | 2 +- mactrack_snmp.php | 4 ++-- mactrack_view_graphs.php | 8 ++------ poller_mactrack.php | 2 +- 30 files changed, 52 insertions(+), 124 deletions(-) diff --git a/lib/mactrack_3com.php b/lib/mactrack_3com.php index dd8aada..cf4d7a1 100644 --- a/lib/mactrack_3com.php +++ b/lib/mactrack_3com.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_3Com_dot1dTpFdbEntry_ports'); /* complete_3com_ifName @@ -210,7 +208,7 @@ function get_3Com_base_dot1dTpFdbEntry_ports($site, &$device, &$ifInterfaces, $s if (isset($bridgePortIfIndexes[$port_key['port_number']])) { $brPortIfIndex = mactrack_arr_key($bridgePortIfIndexes, $port_key['port_number']); } else { - $brPortIfIndex = isset($port_key['port_number']) ? $port_key['port_number'] : ''; + $brPortIfIndex = $port_key['port_number'] ?? ''; } $brPortIfType = isset($ifInterfaces[$brPortIfIndex]['ifType']) ? $ifInterfaces[$brPortIfIndex]['ifType'] : ''; } else { diff --git a/lib/mactrack_aruba_oscx.php b/lib/mactrack_aruba_oscx.php index 30a3cfb..612aaf7 100644 --- a/lib/mactrack_aruba_oscx.php +++ b/lib/mactrack_aruba_oscx.php @@ -23,14 +23,10 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_aruba_oscx_switch_ports'); -if (!isset($mactrack_scanning_functions_ip)) { - $mactrack_scanning_functions_ip = []; -} +$mactrack_scanning_functions_ip ??= []; array_push($mactrack_scanning_functions_ip, 'get_aruba_oscx_arp_table'); function oscx_mac($mac) { @@ -375,7 +371,7 @@ function get_aruba_oscx_dot1dTpFdbEntry_ports($site, &$device, &$ifInterfaces, $ // now set the real data $new_port_key_array[$i]['key'] = mactrack_arr_key($port_key, 'key'); - $new_port_key_array[$i]['port_number'] = isset($brPortIfIndex) ? $brPortIfIndex : ''; + $new_port_key_array[$i]['port_number'] = $brPortIfIndex ?? ''; $new_port_key_array[$i]['port_name'] = mactrack_arr_key($ifInterfaces, $port_key['port_number']); $new_port_key_array[$i]['mac_address'] = oscx_mac($port_key['key']); $new_port_key_array[$i]['vlan_id'] = mactrack_arr_key($port_vlan_data, $brPortIfIndex); diff --git a/lib/mactrack_cabletron.php b/lib/mactrack_cabletron.php index 22c92dc..d95b249 100644 --- a/lib/mactrack_cabletron.php +++ b/lib/mactrack_cabletron.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_cabletron_switch_ports'); array_push($mactrack_scanning_functions, 'get_repeater_rev4_ports'); diff --git a/lib/mactrack_cisco.php b/lib/mactrack_cisco.php index 54e6660..e6361b5 100644 --- a/lib/mactrack_cisco.php +++ b/lib/mactrack_cisco.php @@ -23,21 +23,15 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_catalyst_dot1dTpFdbEntry_ports'); array_push($mactrack_scanning_functions, 'get_IOS_dot1dTpFdbEntry_ports'); -if (!isset($mactrack_scanning_functions_ip)) { - $mactrack_scanning_functions_ip = []; -} +$mactrack_scanning_functions_ip ??= []; array_push($mactrack_scanning_functions_ip, 'get_cisco_dhcpsnooping_table'); array_push($mactrack_scanning_functions_ip, 'get_cisco_vrf_arp_table'); -if (!isset($mactrack_scanning_functions_dot1x)) { - $mactrack_scanning_functions_dot1x = []; -} +$mactrack_scanning_functions_dot1x ??= []; array_push($mactrack_scanning_functions_dot1x, 'get_cisco_dot1x_table'); /* get_catalyst_doet1dTpFdbEntry_ports diff --git a/lib/mactrack_dell.php b/lib/mactrack_dell.php index dcc6bae..7114292 100644 --- a/lib/mactrack_dell.php +++ b/lib/mactrack_dell.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_dell_dot1q_switch_ports'); /* get_dell_dot1q_switch_ports - This is a basic function that will scan the dot1d diff --git a/lib/mactrack_dlink.php b/lib/mactrack_dlink.php index 7a73837..53c7b8c 100644 --- a/lib/mactrack_dlink.php +++ b/lib/mactrack_dlink.php @@ -24,14 +24,10 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_dlink_l2_switch_ports'); -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_dlink_l2_dot1dTpFdbEntry_ports'); /* get_generic_switch_ports - This is a basic function that will scan the dot1d diff --git a/lib/mactrack_enterasys.php b/lib/mactrack_enterasys.php index dc082ed..3b51c7b 100644 --- a/lib/mactrack_enterasys.php +++ b/lib/mactrack_enterasys.php @@ -24,9 +24,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_enterasys_switch_ports'); function get_enterasys_switch_ports($site, &$device, $lowPort = 0, $highPort = 0) { diff --git a/lib/mactrack_enterasys_N7.php b/lib/mactrack_enterasys_N7.php index 750db97..9f0434a 100644 --- a/lib/mactrack_enterasys_N7.php +++ b/lib/mactrack_enterasys_N7.php @@ -23,14 +23,10 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_enterasys_N7_switch_ports'); -if (!isset($mactrack_scanning_functions_ip)) { - $mactrack_scanning_functions_ip = []; -} +$mactrack_scanning_functions_ip ??= []; array_push($mactrack_scanning_functions_ip, 'get_CTAlias_table'); /* get_generic_switch_ports - This is a basic function that will scan the dot1d @@ -298,7 +294,7 @@ function get_enterasys_N7_dot1dTpFdbEntry_ports($site, &$device, &$ifInterfaces, // now set the real data $new_port_key_array[$i]['key'] = mactrack_arr_key($port_key, 'key'); - $new_port_key_array[$i]['port_number'] = isset($brPortIfIndex) ? $brPortIfIndex : ''; + $new_port_key_array[$i]['port_number'] = $brPortIfIndex ?? ''; $new_port_key_array[$i]['vlan_id'] = mactrack_arr_key($vlan_ids, $port_key['key']); // print_r($new_port_key_array[$i]); $i++; diff --git a/lib/mactrack_extreme.php b/lib/mactrack_extreme.php index ba61346..4682983 100644 --- a/lib/mactrack_extreme.php +++ b/lib/mactrack_extreme.php @@ -23,15 +23,11 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_extreme_switch_ports'); array_push($mactrack_scanning_functions, 'get_extreme_extremeware_switch_ports'); -if (!isset($mactrack_scanning_functions_ip)) { - $mactrack_scanning_functions_ip = []; -} +$mactrack_scanning_functions_ip ??= []; array_push($mactrack_scanning_functions_ip, 'get_extreme_arp_table'); array_push($mactrack_scanning_functions_ip, 'get_extreme_extremeware_arp_table'); diff --git a/lib/mactrack_foundry.php b/lib/mactrack_foundry.php index f0bfefa..3440e14 100644 --- a/lib/mactrack_foundry.php +++ b/lib/mactrack_foundry.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_foundry_switch_ports'); function get_foundry_switch_ports($site, &$device, $lowPort = 0, $highPort = 0) { diff --git a/lib/mactrack_functions.php b/lib/mactrack_functions.php index 9c47f6d..198d3b9 100644 --- a/lib/mactrack_functions.php +++ b/lib/mactrack_functions.php @@ -25,22 +25,17 @@ // register these scanning functions global $mactrack_scanning_functions; -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_generic_dot1q_switch_ports', 'get_generic_switch_ports', 'get_generic_wireless_ports'); global $mactrack_scanning_functions_ip; -if (!isset($mactrack_scanning_functions_ip)) { - $mactrack_scanning_functions_ip = []; -} +$mactrack_scanning_functions_ip ??= []; array_push($mactrack_scanning_functions_ip, 'get_standard_arp_table', 'get_netscreen_arp_table'); global $mactrack_device_status; -if (!isset($mactrack_device_status)) { - $mactrack_device_status = [ +$mactrack_device_status ??= [ 1 => __('Idle', 'mactrack'), 2 => __('Running', 'mactrack'), 3 => __('No method', 'mactrack'), @@ -49,7 +44,6 @@ 6 => __('Authorization Success', 'mactrack'), 7 => __('Authorization Failed', 'mactrack') ]; -} function mactrack_debug($message) { global $debug, $web, $config; @@ -2431,13 +2425,9 @@ function db_store_device_port_results(&$device, $port_array, $scan_date) { $authorized_mac = 0; } - if (!isset($port_value['vlan_id'])) { - $port_value['vlan_id'] = 'N/A'; - } + $port_value['vlan_id'] ??= 'N/A'; - if (!isset($port_value['vlan_name'])) { - $port_value['vlan_name'] = 'N/A'; - } + $port_value['vlan_name'] ??= 'N/A'; db_execute_prepared('REPLACE INTO mac_track_temp_ports (site_id,device_id,hostname,device_name,vlan_id,vlan_name, diff --git a/lib/mactrack_h3c_3com.php b/lib/mactrack_h3c_3com.php index f28d695..4ec22c4 100644 --- a/lib/mactrack_h3c_3com.php +++ b/lib/mactrack_h3c_3com.php @@ -23,14 +23,10 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_h3c_3com_switch_ports'); -if (!isset($mactrack_scanning_functions_ip)) { - $mactrack_scanning_functions_ip = []; -} +$mactrack_scanning_functions_ip ??= []; array_push($mactrack_scanning_functions_ip, 'get_h3c_3com_arp_table'); function get_h3c_3com_switch_ports($site, &$device, $lowPort = 0, $highPort = 0) { @@ -343,7 +339,7 @@ function get_h3c_3com_dot1dTpFdbEntry_ports($site, &$device, &$ifInterfaces, $sn // now set the real data $new_port_key_array[$i]['key'] = mactrack_arr_key($port_key, 'key'); - $new_port_key_array[$i]['port_number'] = isset($brPortIfIndex) ? $brPortIfIndex : ''; + $new_port_key_array[$i]['port_number'] = $brPortIfIndex ?? ''; $new_port_key_array[$i]['vlan_id'] = mactrack_arr_key($port_vlan_data, $brPortIfIndex); $new_port_key_array[$i]['vlan_name'] = mactrack_arr_key($vlan_names, $port_vlan_data[$brPortIfIndex]); diff --git a/lib/mactrack_hp.php b/lib/mactrack_hp.php index 3ee2072..da9d18e 100644 --- a/lib/mactrack_hp.php +++ b/lib/mactrack_hp.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_procurve_switch_ports'); /* get_procurve_switch_ports diff --git a/lib/mactrack_hp_ng.php b/lib/mactrack_hp_ng.php index 83f9239..1bf274b 100644 --- a/lib/mactrack_hp_ng.php +++ b/lib/mactrack_hp_ng.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_procurve_ng_switch_ports'); /* get_procurve_ng_switch_ports diff --git a/lib/mactrack_hp_ngi.php b/lib/mactrack_hp_ngi.php index 0fde513..d4a3309 100644 --- a/lib/mactrack_hp_ngi.php +++ b/lib/mactrack_hp_ngi.php @@ -29,9 +29,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_procurve_ngi_switch_ports'); function get_procurve_ngi_switch_ports($site, &$device, $lowPort = 0, $highPort = 0) { diff --git a/lib/mactrack_juniper.php b/lib/mactrack_juniper.php index 6bf9800..389f56a 100644 --- a/lib/mactrack_juniper.php +++ b/lib/mactrack_juniper.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_JEX_switch_ports'); function mach($macd, $del = ':') { diff --git a/lib/mactrack_linux.php b/lib/mactrack_linux.php index 25e2a6c..77203e8 100644 --- a/lib/mactrack_linux.php +++ b/lib/mactrack_linux.php @@ -24,9 +24,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_linux_switch_ports'); /* get_generic_switch_ports - This is a basic function that will scan the dot1d diff --git a/lib/mactrack_norbay.php b/lib/mactrack_norbay.php index 6bf78ea..b739c00 100644 --- a/lib/mactrack_norbay.php +++ b/lib/mactrack_norbay.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_norbay_switch_ports'); array_push($mactrack_scanning_functions, 'get_norbay_accelar_switch_ports'); diff --git a/lib/mactrack_norbay_ng.php b/lib/mactrack_norbay_ng.php index f9f3162..2b6095f 100644 --- a/lib/mactrack_norbay_ng.php +++ b/lib/mactrack_norbay_ng.php @@ -23,9 +23,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_norbay_ng_switch_ports'); /* get_norbay_ng_switch_ports diff --git a/lib/mactrack_tplink.php b/lib/mactrack_tplink.php index d678f87..8c8760d 100644 --- a/lib/mactrack_tplink.php +++ b/lib/mactrack_tplink.php @@ -30,9 +30,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_tplink_dot1q_switch_ports'); /* get_tplink_dot1q_switch_ports - This is a basic function that will scan the dot1d diff --git a/lib/mactrack_trendnet.php b/lib/mactrack_trendnet.php index 99d365c..20e879b 100644 --- a/lib/mactrack_trendnet.php +++ b/lib/mactrack_trendnet.php @@ -29,9 +29,7 @@ */ // register this functions scanning functions -if (!isset($mactrack_scanning_functions)) { - $mactrack_scanning_functions = []; -} +$mactrack_scanning_functions ??= []; array_push($mactrack_scanning_functions, 'get_trendnet_dot1q_switch_ports'); /* get_trendnet_dot1q_switch_ports - This is a basic function that will scan the dot1d diff --git a/mactrack_actions.php b/mactrack_actions.php index 81e1ca3..bbe809b 100644 --- a/mactrack_actions.php +++ b/mactrack_actions.php @@ -144,9 +144,7 @@ function sync_mactrack_to_cacti($mt_device) { * (aka: has the device been saved successfully) */ if ((read_config_option('mt_update_policy', true) == 3) && ($mt_device['host_id'] > 0)) { - if (!isset($mt_device['snmp_engine_id'])) { - $mt_device['snmp_engine_id'] = ''; - } + $mt_device['snmp_engine_id'] ??= ''; // fetch current data for cacti device $cacti_device = db_fetch_row('SELECT * FROM host WHERE id=' . $mt_device['host_id']); @@ -181,9 +179,7 @@ function sync_cacti_to_mactrack($device) { $mt_device = db_fetch_row('SELECT * from mac_track_devices WHERE host_id=' . $device['id']); if (is_array($mt_device) && $mt_device) { - if (!isset($mt_device['snmp_engine_id'])) { - $mt_device['snmp_engine_id'] = ''; - } + $mt_device['snmp_engine_id'] ??= ''; // update mac_track_device $device_id = api_mactrack_device_save( @@ -213,7 +209,7 @@ function sync_cacti_to_mactrack($device) { $mt_device['user_password'], // not a host column $mt_device['term_type'], $mt_device['private_key_path'], - (isset($mt_device['disabled']) ? $mt_device['disabled'] : ''), // not a host column + ($mt_device['disabled'] ?? ''), // not a host column $mt_device['scan_trunk_port'], $mt_device['device_type_id'] ); @@ -306,7 +302,7 @@ function mactrack_device_action_execute($action) { if (is_array($device)) { // update mac_track_device $device_id = api_mactrack_device_save( - (isset($mt_device['device_id']) ? $mt_device['device_id'] : '0'), // not a host column + ($mt_device['device_id'] ?? '0'), // not a host column $device['id'], get_request_var('site_id'), // not a host column (wait for 088) $device['hostname'], @@ -333,8 +329,8 @@ function mactrack_device_action_execute($action) { get_request_var('term_type'), get_request_var('private_key_path'), (isset_request_var('disabled') ? get_request_var('disabled') : ''), - (isset($mt_device['scan_trunk_port']) ? $mt_device['scan_trunk_port'] : ''), - (isset($mt_device['device_type_id']) ? $mt_device['device_type_id'] : 0) + ($mt_device['scan_trunk_port'] ?? ''), + ($mt_device['device_type_id'] ?? 0) ); } } diff --git a/mactrack_device_types.php b/mactrack_device_types.php index 0ee23f6..037d7cc 100644 --- a/mactrack_device_types.php +++ b/mactrack_device_types.php @@ -890,7 +890,7 @@ function mactrack_device_type_edit() { draw_edit_form( [ 'config' => ['no_form_tag' => 'true'], - 'fields' => inject_form_variables($fields_mactrack_device_type_edit, (isset($device_type) ? $device_type : [])) + 'fields' => inject_form_variables($fields_mactrack_device_type_edit, ($device_type ?? [])) ] ); diff --git a/mactrack_devices.php b/mactrack_devices.php index 1435db5..90257ec 100644 --- a/mactrack_devices.php +++ b/mactrack_devices.php @@ -961,7 +961,7 @@ function mactrack_device_edit() { draw_edit_form( [ 'config' => ['no_form_tag' => true], - 'fields' => inject_form_variables($fields_mactrack_device_edit, (isset($device) ? $device : [])) + 'fields' => inject_form_variables($fields_mactrack_device_edit, ($device ?? [])) ] ); diff --git a/mactrack_macauth.php b/mactrack_macauth.php index b559f07..12d4fce 100644 --- a/mactrack_macauth.php +++ b/mactrack_macauth.php @@ -265,7 +265,7 @@ function mactrack_maca_edit() { draw_edit_form( [ 'config' => ['no_form_tag' => true], - 'fields' => inject_form_variables($fields_mactrack_maca_edit, (isset($mac_record) ? $mac_record : [])) + 'fields' => inject_form_variables($fields_mactrack_maca_edit, ($mac_record ?? [])) ] ); diff --git a/mactrack_macwatch.php b/mactrack_macwatch.php index 4013854..a275330 100644 --- a/mactrack_macwatch.php +++ b/mactrack_macwatch.php @@ -251,7 +251,7 @@ function mactrack_macw_edit() { draw_edit_form( [ 'config' => ['no_form_tag' => true], - 'fields' => inject_form_variables($fields_mactrack_macw_edit, (isset($mac_record) ? $mac_record : [])) + 'fields' => inject_form_variables($fields_mactrack_macw_edit, ($mac_record ?? [])) ] ); diff --git a/mactrack_sites.php b/mactrack_sites.php index 67c03e0..c6ab9cc 100644 --- a/mactrack_sites.php +++ b/mactrack_sites.php @@ -372,7 +372,7 @@ function mactrack_site_edit() { draw_edit_form( [ 'config' => ['no_form_tag' => true], - 'fields' => inject_form_variables($fields_mactrack_site_edit, (isset($site) ? $site : [])) + 'fields' => inject_form_variables($fields_mactrack_site_edit, ($site ?? [])) ] ); diff --git a/mactrack_snmp.php b/mactrack_snmp.php index 98ade52..566f2d6 100644 --- a/mactrack_snmp.php +++ b/mactrack_snmp.php @@ -357,14 +357,14 @@ function mactrack_snmp_item_edit() { draw_edit_form( [ 'config' => ['no_form_tag' => true], - 'fields' => inject_form_variables($fields_mactrack_snmp_item_edit, (isset($mactrack_snmp_item) ? $mactrack_snmp_item : [])) + 'fields' => inject_form_variables($fields_mactrack_snmp_item_edit, ($mactrack_snmp_item ?? [])) ] ); html_end_box(); form_hidden_box('item_id', (isset_request_var('item_id') ? get_request_var('item_id') : '0'), ''); - form_hidden_box('id', (isset($mactrack_snmp_item['snmp_id']) ? $mactrack_snmp_item['snmp_id'] : '0'), ''); + form_hidden_box('id', ($mactrack_snmp_item['snmp_id'] ?? '0'), ''); form_hidden_box('save_component_mactrack_snmp_item', '1', ''); form_save_button(htmlspecialchars('mactrack_snmp.php?action=edit&id=' . get_request_var('id'))); diff --git a/mactrack_view_graphs.php b/mactrack_view_graphs.php index ee9fc7d..8aa4226 100644 --- a/mactrack_view_graphs.php +++ b/mactrack_view_graphs.php @@ -45,25 +45,21 @@ function mactrack_view_graphs() { html_graph_validate_preview_request_vars(); - if (!isset($_SESSION['sess_mt_gt'])) { - $_SESSION['sess_mt_gt'] = implode(',', array_rekey(db_fetch_assoc('SELECT DISTINCT gl.graph_template_id + $_SESSION['sess_mt_gt'] ??= implode(',', array_rekey(db_fetch_assoc('SELECT DISTINCT gl.graph_template_id FROM graph_local AS gl WHERE gl.host_id IN( SELECT host_id FROM mac_track_devices )'), 'graph_template_id', 'graph_template_id')); - } $gt = $_SESSION['sess_mt_gt']; - if (!isset($_SESSION['sess_mt_hosts'])) { - $_SESSION['sess_mt_hosts'] = implode(',', array_rekey(db_fetch_assoc('SELECT h.id + $_SESSION['sess_mt_hosts'] ??= implode(',', array_rekey(db_fetch_assoc('SELECT h.id FROM host AS h WHERE h.id IN ( SELECT host_id FROM mac_track_devices ) ORDER BY id DESC'), 'id', 'id')); - } $hosts = $_SESSION['sess_mt_hosts']; // include graph view filter selector diff --git a/poller_mactrack.php b/poller_mactrack.php index 1f9bbd1..3a6ad8b 100644 --- a/poller_mactrack.php +++ b/poller_mactrack.php @@ -336,7 +336,7 @@ function mactrack_error_handler($level, $message, $file, $line, $context) { preg_match("/.*\/plugins\/([\w-]*)\/.*/", $file, $output_array); - $plugin = (isset($output_array[1]) ? $output_array[1] : ''); + $plugin = ($output_array[1] ?? ''); $error = 'PHP ' . $phperrors[$level] . ($plugin != '' ? " in Plugin '$plugin'" : '') . ": $message in file: $file on line: $line"; switch ($level) { From 25a7da1a920f4f4e1da1711a360903e29d5f2abd Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Fri, 27 Mar 2026 20:16:36 -0700 Subject: [PATCH 2/6] security: fix SQLi, XSS, credential exposure, and insecure deserialization Replace bare unserialize() with cacti_unserialize() plus array validation in mactrack_view_macs.php. The original call allowed PHP object injection on a guest-accessible page. Strip 9 SNMP credential columns (community strings, SNMPv3 usernames, passwords, auth/priv protocols, passphrases) from the guest-accessible CSV export in mactrack_view_devices.php. Any user with Viewer realm could download all network device SNMP credentials. Addresses GHSA-9829-w9mx-2cgm. Replace all 27 unsafe LIKE string interpolation sites across 9 files with db_qstr() quoting. Also fix mactrack_create_sql_filter() in lib/mactrack_functions.php. Six of the affected files are guest-accessible, making filter SQLi pre-authentication. Replace raw db_qstr()-less CSV value interpolation in the import processors of mactrack_devices.php and mactrack_device_types.php. CSV cell values were concatenated directly into INSERT VALUES and WHERE clauses with only single-quote stripping (bypassable via backslash escaping). Replace get_request_var('filter') with html_escape_request_var() in 11 HTML input value attributes to prevent reflected XSS. Wrap 4 SNMP response variables with html_escape() in mactrack_devices.php to prevent stored XSS via rogue SNMP agents. Signed-off-by: Thomas Vincent --- lib/mactrack_functions.php | 4 ++-- mactrack_device_types.php | 25 ++++++++++++------------- mactrack_devices.php | 31 +++++++++++++++---------------- mactrack_macauth.php | 6 +++--- mactrack_macwatch.php | 10 +++++----- mactrack_sites.php | 8 ++++---- mactrack_snmp.php | 4 ++-- mactrack_vendormacs.php | 8 ++++---- mactrack_view_arp.php | 2 +- mactrack_view_devices.php | 20 +++++++------------- mactrack_view_interfaces.php | 2 +- mactrack_view_macs.php | 9 +++++++-- mactrack_view_sites.php | 8 ++++---- 13 files changed, 67 insertions(+), 70 deletions(-) diff --git a/lib/mactrack_functions.php b/lib/mactrack_functions.php index 198d3b9..47f685f 100644 --- a/lib/mactrack_functions.php +++ b/lib/mactrack_functions.php @@ -3350,7 +3350,7 @@ function mactrack_create_sql_filter($filter, $fields) { $query .= '('; } - $query .= ($field_no == 1 ? '' : " $operator ") . "($field $type LIKE '%" . $filter . "%')"; + $query .= ($field_no == 1 ? '' : " $operator ") . "($field $type LIKE " . db_qstr('%' . $filter . '%') . ")"; $field_no++; } @@ -3572,7 +3572,7 @@ function mactrack_site_filter($page = 'mactrack_sites.php') { - '> + '> diff --git a/mactrack_device_types.php b/mactrack_device_types.php index 037d7cc..d929348 100644 --- a/mactrack_device_types.php +++ b/mactrack_device_types.php @@ -749,7 +749,6 @@ function mactrack_device_type_import_processor(&$device_types) { foreach ($line_array as $line_item) { if (in_array($j, $insert_columns, true)) { - $line_item = trim(str_replace("'", '', $line_item)); $line_item = trim(str_replace('"', '', $line_item)); if (!$first_column) { @@ -762,15 +761,15 @@ function mactrack_device_type_import_processor(&$device_types) { if ($sql_where != '') { switch($j) { case $device_type_id: - $sql_where .= " AND device_type='$line_item'"; + $sql_where .= ' AND device_type=' . db_qstr($line_item); break; case $sysDescr_match_id: - $sql_where .= " AND sysDescr_match='$line_item'"; + $sql_where .= ' AND sysDescr_match=' . db_qstr($line_item); break; case $sysObjectID_match_id: - $sql_where .= " AND sysObjectID_match='$line_item'"; + $sql_where .= ' AND sysObjectID_match=' . db_qstr($line_item); break; default: @@ -779,15 +778,15 @@ function mactrack_device_type_import_processor(&$device_types) { } else { switch($j) { case $device_type_id: - $sql_where .= "WHERE device_type='$line_item'"; + $sql_where .= 'WHERE device_type=' . db_qstr($line_item); break; case $sysDescr_match_id: - $sql_where .= "WHERE sysDescr_match='$line_item'"; + $sql_where .= 'WHERE sysDescr_match=' . db_qstr($line_item); break; case $sysObjectID_match_id: - $sql_where .= "WHERE sysObjectID_match='$line_item'"; + $sql_where .= 'WHERE sysObjectID_match=' . db_qstr($line_item); break; default: @@ -821,7 +820,7 @@ function mactrack_device_type_import_processor(&$device_types) { $description = $line_item; } - $save_value .= "'" . $line_item . "'"; + $save_value .= db_qstr($line_item); } $j++; @@ -901,10 +900,10 @@ function mactrack_device_type_edit() { function mactrack_get_device_types(&$sql_where, $rows, $apply_limits = true) { if (get_request_var('filter') != '') { - $sql_where = " WHERE (mtdt.vendor LIKE '%" . get_request_var('filter') . "%' OR - mtdt.description LIKE '%" . get_request_var('filter') . "%' OR - mtdt.sysDescr_match LIKE '%" . get_request_var('filter') . "%' OR - mtdt.sysObjectID_match LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = " WHERE (mtdt.vendor LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR + mtdt.description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR + mtdt.sysDescr_match LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR + mtdt.sysObjectID_match LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } if (get_request_var('vendor') == 'All') { @@ -1053,7 +1052,7 @@ function mactrack_device_type_filter() { - '> + '> diff --git a/mactrack_devices.php b/mactrack_devices.php index 90257ec..57b625e 100644 --- a/mactrack_devices.php +++ b/mactrack_devices.php @@ -746,7 +746,6 @@ function mactrack_device_import_processor(&$devices) { if (cacti_sizeof($line_array)) { foreach ($line_array as $line_item) { if (in_array($j, $insert_columns, true)) { - $line_item = trim(str_replace("'", '', $line_item)); $line_item = trim(str_replace('"', '', $line_item)); if (!$first_column) { @@ -759,15 +758,15 @@ function mactrack_device_import_processor(&$devices) { if ($sql_where != '') { switch($j) { case $save_site_id_id: - $sql_where .= " AND site_id='$line_item'"; + $sql_where .= ' AND site_id=' . db_qstr($line_item); break; case $save_snmp_port_id: - $sql_where .= " AND snmp_port='$line_item'"; + $sql_where .= ' AND snmp_port=' . db_qstr($line_item); break; case $save_host_id: - $sql_where .= " AND hostname='$line_item'"; + $sql_where .= ' AND hostname=' . db_qstr($line_item); break; default: @@ -776,15 +775,15 @@ function mactrack_device_import_processor(&$devices) { } else { switch($j) { case $save_site_id_id: - $sql_where .= "WHERE site_id='$line_item'"; + $sql_where .= 'WHERE site_id=' . db_qstr($line_item); break; case $save_snmp_port_id: - $sql_where .= "WHERE snmp_port='$line_item'"; + $sql_where .= 'WHERE snmp_port=' . db_qstr($line_item); break; case $save_host_id: - $sql_where .= "WHERE hostname='$line_item'"; + $sql_where .= 'WHERE hostname=' . db_qstr($line_item); break; default: @@ -809,7 +808,7 @@ function mactrack_device_import_processor(&$devices) { $device_name = $line_item; } - $save_value .= "'" . $line_item . "'"; + $save_value .= db_qstr($line_item); } $j++; @@ -935,10 +934,10 @@ function mactrack_device_edit() { $snmp_objid = str_replace('OID: ', '', $snmp_objid); $snmp_objid = str_replace('.iso', '.1', $snmp_objid); - print '' . __('System:', 'mactrack') . " $snmp_system
\n"; - print '' . __('Uptime:', 'mactrack') . " $snmp_uptime
\n"; - print '' . __('Hostname:', 'mactrack') . " $snmp_hostname
\n"; - print '' . __('ObjectID:', 'mactrack') . " $snmp_objid
\n"; + print '' . __('System:', 'mactrack') . ' ' . html_escape($snmp_system) . "
\n"; + print '' . __('Uptime:', 'mactrack') . ' ' . html_escape($snmp_uptime) . "
\n"; + print '' . __('Hostname:', 'mactrack') . ' ' . html_escape($snmp_hostname) . "
\n"; + print '' . __('ObjectID:', 'mactrack') . ' ' . html_escape($snmp_objid) . "
\n"; } ?> @@ -973,9 +972,9 @@ function mactrack_device_edit() { function mactrack_get_devices(&$sql_where, $rows, $apply_limits = true) { // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where = ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mtd.hostname like '%" . get_request_var('filter') . "%' - OR mtd.device_name like '%" . get_request_var('filter') . "%' - OR mtd.notes like '%" . get_request_var('filter') . "%')"; + $sql_where = ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mtd.hostname LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " + OR mtd.device_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " + OR mtd.notes LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } if (get_request_var('status') == '-1') { @@ -1160,7 +1159,7 @@ function mactrack_device_filter() { - '> + '> diff --git a/mactrack_macauth.php b/mactrack_macauth.php index 12d4fce..76b1074 100644 --- a/mactrack_macauth.php +++ b/mactrack_macauth.php @@ -219,8 +219,8 @@ function mactrack_maca_get_maca_records(&$sql_where, $rows, $apply_limits = true $sql_where = ''; if (get_request_var('filter') != '') { - $sql_where = "WHERE (mac_address LIKE '%" . str_replace(['-', '.', ':'],'',get_request_var('filter')) . "%' OR " . - "description LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_address LIKE " . db_qstr('%' . str_replace(['-', '.', ':'],'',get_request_var('filter')) . '%') . " OR " . + "description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $sql_order = get_order_string(); @@ -384,7 +384,7 @@ function mactrack_maca_filter() { - '> + '> diff --git a/mactrack_macwatch.php b/mactrack_macwatch.php index a275330..e6ca81c 100644 --- a/mactrack_macwatch.php +++ b/mactrack_macwatch.php @@ -203,10 +203,10 @@ function mactrack_macw_get_macw_records(&$sql_where, $rows, $apply_limits = true // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where = "WHERE (mac_address LIKE '%" . get_request_var('filter') . "%' OR " . - "name LIKE '%" . get_request_var('filter') . "%' OR " . - "ticket_number LIKE '%" . get_request_var('filter') . "%' OR " . - "description LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_address LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "ticket_number LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $sql_order = get_order_string(); @@ -392,7 +392,7 @@ function mactrack_macw_filter() { - '> + '> diff --git a/mactrack_sites.php b/mactrack_sites.php index c6ab9cc..e5b8ee5 100644 --- a/mactrack_sites.php +++ b/mactrack_sites.php @@ -291,11 +291,11 @@ function mactrack_site_get_site_records(&$sql_where, $rows, $apply_limits = true // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { if (get_request_var('detail') == 'false') { - $sql_where = "WHERE (mts.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mts.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } else { - $sql_where = "WHERE (mts.vendor LIKE '%" . get_request_var('filter') . "%' OR " . - "mtdt.description LIKE '%" . get_request_var('filter') . "%' OR " . - "mts.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mts.vendor LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mtdt.description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mts.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } } diff --git a/mactrack_snmp.php b/mactrack_snmp.php index 566f2d6..4bf4ce9 100644 --- a/mactrack_snmp.php +++ b/mactrack_snmp.php @@ -541,7 +541,7 @@ function mactrack_snmp() { $sql_where = ''; if (get_request_var('filter') != '') { - $sql_where .= "WHERE (mac_track_snmp.name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where .= "WHERE (mac_track_snmp.name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $total_rows = db_fetch_cell("SELECT @@ -607,7 +607,7 @@ function snmp_options_filter() { - '> + '> diff --git a/mactrack_vendormacs.php b/mactrack_vendormacs.php index 6962de2..58db0aa 100644 --- a/mactrack_vendormacs.php +++ b/mactrack_vendormacs.php @@ -103,9 +103,9 @@ function mactrack_vmacs_get_vmac_records(&$sql_where, $rows, $apply_limits = tru // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where = "WHERE (mac_track_oui_database.vendor_name LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_oui_database.vendor_mac LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_oui_database.vendor_address LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_track_oui_database.vendor_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_oui_database.vendor_mac LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_oui_database.vendor_address LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } $sql_order = get_order_string(); @@ -201,7 +201,7 @@ function mactrack_vmac_filter() { - '> + '> diff --git a/mactrack_view_arp.php b/mactrack_view_arp.php index 631e652..63b9ad2 100644 --- a/mactrack_view_arp.php +++ b/mactrack_view_arp.php @@ -453,7 +453,7 @@ function mactrack_ip_address_filter() { - '> + '> diff --git a/mactrack_view_devices.php b/mactrack_view_devices.php index 548260a..3fccc64 100644 --- a/mactrack_view_devices.php +++ b/mactrack_view_devices.php @@ -105,9 +105,7 @@ function mactrack_view_export_devices() { $xport_array = []; array_push($xport_array, 'site_id, site_name, device_id, device_name, notes, ' . - 'hostname, snmp_readstring, snmp_readstrings, snmp_version, ' . - 'snmp_username, snmp_password, snmp_auth_protocol, snmp_priv_passphrase, ' . - 'snmp_priv_protocol, snmp_context, snmp_engine_id, ' . + 'hostname, snmp_version, ' . 'snmp_port, snmp_timeout, snmp_retries, max_oids, snmp_sysName, snmp_sysLocation, ' . 'snmp_sysContact, snmp_sysObjectID, snmp_sysDescr, snmp_sysUptime, ' . 'ignorePorts, scan_type, disabled, ports_total, ports_active, ' . @@ -119,11 +117,7 @@ function mactrack_view_export_devices() { $device['site_id'] . '","' . $device['site_name'] . '","' . $device['device_id'] . '","' . $device['device_name'] . '","' . $device['notes'] . '","' . $device['hostname'] . '","' . - $device['snmp_readstring'] . '","' . $device['snmp_readstrings'] . '","' . - $device['snmp_version'] . '","' . $device['snmp_username'] . '","' . - $device['snmp_password'] . '","' . $device['snmp_auth_protocol'] . '","' . - $device['snmp_priv_passphrase'] . '","' . $device['snmp_priv_protocol'] . '","' . - $device['snmp_context'] . '","' . $device['snmp_engine_id'] . '","' . + $device['snmp_version'] . '","' . $device['snmp_port'] . '","' . $device['snmp_timeout'] . '","' . $device['snmp_retries'] . '","' . $device['max_oids'] . '","' . $device['snmp_sysName'] . '","' . $device['snmp_sysLocation'] . '","' . @@ -161,10 +155,10 @@ function mactrack_view_get_device_records(&$sql_where, $rows, $apply_limits = tr // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { - $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mac_track_devices.hostname LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_devices.notes LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_devices.device_name LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_sites.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . "(mac_track_devices.hostname LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_devices.notes LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_devices.device_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_sites.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } if (cacti_sizeof($device_type_info)) { @@ -427,7 +421,7 @@ function mactrack_device_filter2() { - '> + '> diff --git a/mactrack_view_interfaces.php b/mactrack_view_interfaces.php index 66e4ad5..bebfb32 100644 --- a/mactrack_view_interfaces.php +++ b/mactrack_view_interfaces.php @@ -648,7 +648,7 @@ function mactrack_filter_table() { - '> + '> > diff --git a/mactrack_view_macs.php b/mactrack_view_macs.php index f19f3c0..e1e9ed1 100644 --- a/mactrack_view_macs.php +++ b/mactrack_view_macs.php @@ -88,7 +88,12 @@ function form_actions() { // if we are to save this form, instead of display it if (isset_request_var('selected_items')) { - $selected_items = unserialize(get_nfilter_request_var('selected_items')); + $selected_items = cacti_unserialize(stripslashes(get_nfilter_request_var('selected_items'))); + + if (!is_array($selected_items)) { + header('Location: mactrack_view_macs.php'); + exit; + } foreach ($selected_items as $mac=>$ip) { if (!filter_var($mac, FILTER_VALIDATE_MAC)) { @@ -1106,7 +1111,7 @@ function mactrack_mac_filter() { - '> + '> diff --git a/mactrack_view_sites.php b/mactrack_view_sites.php index 655bbc2..656f501 100644 --- a/mactrack_view_sites.php +++ b/mactrack_view_sites.php @@ -93,11 +93,11 @@ function mactrack_view_get_site_records(&$sql_where, $rows, $apply_limits = true // form the 'where' clause for our main sql query if (get_request_var('filter') != '') { if (get_request_var('detail') == 'false') { - $sql_where = "WHERE (mac_track_sites.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_track_sites.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } else { - $sql_where = "WHERE (mac_track_device_types.vendor LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_device_types.description LIKE '%" . get_request_var('filter') . "%' OR " . - "mac_track_sites.site_name LIKE '%" . get_request_var('filter') . "%')"; + $sql_where = "WHERE (mac_track_device_types.vendor LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_device_types.description LIKE " . db_qstr('%' . get_request_var('filter') . '%') . " OR " . + "mac_track_sites.site_name LIKE " . db_qstr('%' . get_request_var('filter') . '%') . ")"; } } From 0443940a0245e372531473010c924b96a13104c9 Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Thu, 9 Apr 2026 01:41:43 -0700 Subject: [PATCH 3/6] refactor: extract plugin_get_rows_per_page helper to DRY filter boilerplate Signed-off-by: Thomas Vincent --- lib/mactrack_functions.php | 19 +++++++++++++++++++ mactrack_device_types.php | 8 +------- mactrack_devices.php | 8 +------- mactrack_macauth.php | 8 +------- mactrack_macwatch.php | 8 +------- mactrack_sites.php | 8 +------- mactrack_vendormacs.php | 8 +------- mactrack_view_arp.php | 8 +------- mactrack_view_devices.php | 8 +------- mactrack_view_dot1x.php | 8 +------- mactrack_view_ips.php | 8 +------- mactrack_view_macs.php | 16 ++-------------- mactrack_view_sites.php | 8 +------- 13 files changed, 32 insertions(+), 91 deletions(-) diff --git a/lib/mactrack_functions.php b/lib/mactrack_functions.php index 47f685f..4278155 100644 --- a/lib/mactrack_functions.php +++ b/lib/mactrack_functions.php @@ -45,6 +45,25 @@ 7 => __('Authorization Failed', 'mactrack') ]; + +/** + * plugin_get_rows_per_page - resolve rows-per-page from request vars + * + * @return int + */ +function plugin_get_rows_per_page() { + $rows = get_request_var('rows'); + + if ($rows == -1) { + return read_config_option('num_rows_table'); + } elseif ($rows == -2) { + return 999999; + } + + return $rows; +} + + function mactrack_debug($message) { global $debug, $web, $config; diff --git a/mactrack_device_types.php b/mactrack_device_types.php index d929348..e7f199e 100644 --- a/mactrack_device_types.php +++ b/mactrack_device_types.php @@ -946,13 +946,7 @@ function mactrack_device_type() { mactrack_device_type_request_validation(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); html_start_box(__('Mactrack Device Type Filters', 'mactrack'), '100%', '', '3', 'center', 'mactrack_device_types.php?action=edit'); mactrack_device_type_filter(); diff --git a/mactrack_devices.php b/mactrack_devices.php index 57b625e..3ddb811 100644 --- a/mactrack_devices.php +++ b/mactrack_devices.php @@ -1035,13 +1035,7 @@ function mactrack_device() { mactrack_device_request_validation(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); html_start_box(__('Mactrack Device Filters', 'mactrack'), '100%', '', '3', 'center', 'mactrack_devices.php?action=edit&status=' . get_request_var('status')); mactrack_device_filter(); diff --git a/mactrack_macauth.php b/mactrack_macauth.php index 76b1074..c1724fb 100644 --- a/mactrack_macauth.php +++ b/mactrack_macauth.php @@ -309,13 +309,7 @@ function mactrack_maca() { validate_store_request_vars($filters, 'sess_mt_maca'); // ================= input validation ================= - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); html_start_box(__('Mactrack MacAuth Filters', 'mactrack'), '100%', '', '3', 'center', 'mactrack_macauth.php?action=edit'); mactrack_maca_filter(); diff --git a/mactrack_macwatch.php b/mactrack_macwatch.php index e6ca81c..a54a96e 100644 --- a/mactrack_macwatch.php +++ b/mactrack_macwatch.php @@ -295,13 +295,7 @@ function mactrack_macw() { validate_store_request_vars($filters, 'sess_mt_macw'); // ================= input validation ================= - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); html_start_box(__('Mactrack MacWatch Filters', 'mactrack'), '100%', '', '3', 'center', 'mactrack_macwatch.php?action=edit'); mactrack_macw_filter(); diff --git a/mactrack_sites.php b/mactrack_sites.php index e5b8ee5..7bc66c5 100644 --- a/mactrack_sites.php +++ b/mactrack_sites.php @@ -386,13 +386,7 @@ function mactrack_site() { mactrack_site_validate_req_vars(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); html_start_box(__('Mactrack Site Filters', 'mactrack'), '100%', '', '3', 'center', 'mactrack_sites.php?action=edit'); diff --git a/mactrack_vendormacs.php b/mactrack_vendormacs.php index 58db0aa..e872c81 100644 --- a/mactrack_vendormacs.php +++ b/mactrack_vendormacs.php @@ -130,13 +130,7 @@ function mactrack_vmacs() { mactrack_vmacs_validate_request_vars(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); html_start_box(__('Mactrack Vendor Mac Filter', 'mactrack'), '100%', '', '3', 'center', ''); mactrack_vmac_filter(); diff --git a/mactrack_view_arp.php b/mactrack_view_arp.php index 63b9ad2..11979a5 100644 --- a/mactrack_view_arp.php +++ b/mactrack_view_arp.php @@ -293,13 +293,7 @@ function mactrack_view_ips() { $sql_where = ''; - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $port_results = mactrack_view_get_ip_records($sql_where, true, $rows); diff --git a/mactrack_view_devices.php b/mactrack_view_devices.php index 3fccc64..75c3465 100644 --- a/mactrack_view_devices.php +++ b/mactrack_view_devices.php @@ -226,13 +226,7 @@ function mactrack_view_devices() { mactrack_device_request_validation(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $webroot = $config['url_path'] . 'plugins/mactrack/'; diff --git a/mactrack_view_dot1x.php b/mactrack_view_dot1x.php index ae9f5db..2a949da 100644 --- a/mactrack_view_dot1x.php +++ b/mactrack_view_dot1x.php @@ -387,13 +387,7 @@ function mactrack_view_dot1x() { $sql_where = ''; - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $port_results = mactrack_view_get_dot1x_records($sql_where, true, $rows); diff --git a/mactrack_view_ips.php b/mactrack_view_ips.php index 8cc711e..bb16260 100644 --- a/mactrack_view_ips.php +++ b/mactrack_view_ips.php @@ -165,13 +165,7 @@ function mactrack_view_ip_ranges() { mactrack_view_ips_validate_request_vars(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $webroot = $config['url_path'] . 'plugins/mactrack/'; diff --git a/mactrack_view_macs.php b/mactrack_view_macs.php index e1e9ed1..71afc19 100644 --- a/mactrack_view_macs.php +++ b/mactrack_view_macs.php @@ -684,13 +684,7 @@ function mactrack_view_macs() { $sql_where = ''; - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $port_results = mactrack_view_get_mac_records($sql_where, $rows, true); @@ -895,13 +889,7 @@ function mactrack_view_aggregated_macs() { $sql_where = ''; - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $port_results = mactrack_view_get_mac_records($sql_where, $rows, true); diff --git a/mactrack_view_sites.php b/mactrack_view_sites.php index 656f501..0ad4865 100644 --- a/mactrack_view_sites.php +++ b/mactrack_view_sites.php @@ -204,13 +204,7 @@ function mactrack_view_sites() { mactrack_sites_request_validation(); - if (get_request_var('rows') == -1) { - $rows = read_config_option('num_rows_table'); - } elseif (get_request_var('rows') == -2) { - $rows = 999999; - } else { - $rows = get_request_var('rows'); - } + $rows = plugin_get_rows_per_page(); $webroot = $config['url_path'] . 'plugins/mactrack/'; From f36a66bf0f0ec088d3f0bb250d7301b697f8b09e Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Thu, 9 Apr 2026 01:58:04 -0700 Subject: [PATCH 4/6] chore: add copilot instructions and CI workflow Signed-off-by: Thomas Vincent --- .github/copilot-instructions.md | 23 +++ .github/workflows/plugin-ci-workflow.yml | 225 +++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/workflows/plugin-ci-workflow.yml diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..edecbcf --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,23 @@ +# Cacti mactrack Plugin AI Instructions + +## Project Overview +This is a Cacti plugin. It integrates with the Cacti monitoring platform via the plugin hook architecture. + +## Technology Stack +- PHP 7.4+ (targeting Cacti 1.2.x compatibility) +- MySQL/MariaDB via Cacti's DB abstraction layer +- PSR-12 coding standards + +## Key Rules +- Use prepared statements (db_execute_prepared, db_fetch_row_prepared, etc.) for ALL queries with variables +- Use get_request_var() / get_filter_request_var() for ALL user input, never raw $_REQUEST/$_GET/$_POST +- Use html_escape() / htmlspecialchars() for ALL output of DB/user values in HTML context +- Use cacti_escapeshellarg() for ALL shell command arguments +- No PHP 8.0+ features (str_contains, match, union types, named args) - target PHP 7.4 +- Use ?? and ??= operators (PHP 7.4) instead of isset() ternary patterns +- All unserialize() calls must use allowed_classes => false + +## Testing +- Tests in tests/ directory +- Use Pest PHP or PHPUnit +- php -l lint check required before commit diff --git a/.github/workflows/plugin-ci-workflow.yml b/.github/workflows/plugin-ci-workflow.yml new file mode 100644 index 0000000..bdbd889 --- /dev/null +++ b/.github/workflows/plugin-ci-workflow.yml @@ -0,0 +1,225 @@ +# +-------------------------------------------------------------------------+ +# | Copyright (C) 2004-2026 The Cacti Group | +# | | +# | This program is free software; you can redistribute it and/or | +# | modify it under the terms of the GNU General Public License | +# | as published by the Free Software Foundation; either version 2 | +# | of the License, or (at your option) any later version. | +# | | +# | This program is distributed in the hope that it will be useful, | +# | but WITHOUT ANY WARRANTY; without even the implied warranty of | +# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | +# | GNU General Public License for more details. | +# +-------------------------------------------------------------------------+ +# | Cacti: The Complete RRDtool-based Graphing Solution | +# +-------------------------------------------------------------------------+ +# | This code is designed, written, and maintained by the Cacti Group. See | +# | about.php and/or the AUTHORS file for specific developer information. | +# +-------------------------------------------------------------------------+ +# | http://www.cacti.net/ | +# +-------------------------------------------------------------------------+ + +name: Plugin Integration Tests + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + - develop + +jobs: + integration-test: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + php: ['8.1', '8.2', '8.3', '8.4'] + os: [ubuntu-latest] + + services: + mariadb: + image: mariadb:10.6 + env: + MYSQL_ROOT_PASSWORD: cactiroot + MYSQL_DATABASE: cacti + MYSQL_USER: cactiuser + MYSQL_PASSWORD: cactiuser + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping" + --health-interval=10s + --health-timeout=5s + --health-retries=3 + + name: PHP ${{ matrix.php }} Integration Test on ${{ matrix.os }} + + steps: + - name: Checkout Cacti + uses: actions/checkout@v4 + with: + repository: Cacti/cacti + path: cacti + + - name: Checkout mactrack Plugin + uses: actions/checkout@v4 + with: + path: cacti/plugins/mactrack + + - name: Install PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: intl, mysql, gd, ldap, gmp, xml, curl, json, mbstring + ini-values: "post_max_size=256M, max_execution_time=60, date.timezone=America/New_York" + + - name: Check PHP version + run: php -v + + - name: Run apt-get update + run: sudo apt-get update + + - name: Install System Dependencies + run: sudo apt-get install -y apache2 snmp snmpd rrdtool fping libapache2-mod-php${{ matrix.php }} + + - name: Start SNMPD Agent and Test + run: | + sudo systemctl start snmpd + sudo snmpwalk -c public -v2c -On localhost .1.3.6.1.2.1.1 + + - name: Setup Permissions + run: | + sudo chown -R www-data:runner ${{ github.workspace }}/cacti + sudo find ${{ github.workspace }}/cacti -type d -exec chmod 775 {} \; + sudo find ${{ github.workspace }}/cacti -type f -exec chmod 664 {} \; + sudo chmod +x ${{ github.workspace }}/cacti/cmd.php + sudo chmod +x ${{ github.workspace }}/cacti/poller.php + + - name: Create MySQL Config + run: | + echo -e "[client]\nuser = root\npassword = cactiroot\nhost = 127.0.0.1\n" > ~/.my.cnf + cat ~/.my.cnf + + - name: Initialize Cacti Database + env: + MYSQL_AUTH_USR: '--defaults-file=~/.my.cnf' + run: | + mysql $MYSQL_AUTH_USR -e 'CREATE DATABASE IF NOT EXISTS cacti;' + mysql $MYSQL_AUTH_USR -e "CREATE USER IF NOT EXISTS 'cactiuser'@'localhost' IDENTIFIED BY 'cactiuser';" + mysql $MYSQL_AUTH_USR -e "GRANT ALL PRIVILEGES ON cacti.* TO 'cactiuser'@'localhost';" + mysql $MYSQL_AUTH_USR -e "GRANT SELECT ON mysql.time_zone_name TO 'cactiuser'@'localhost';" + mysql $MYSQL_AUTH_USR -e "FLUSH PRIVILEGES;" + mysql $MYSQL_AUTH_USR cacti < ${{ github.workspace }}/cacti/cacti.sql + mysql $MYSQL_AUTH_USR -e "INSERT INTO settings (name, value) VALUES ('path_php_binary', '/usr/bin/php')" cacti + + - name: Validate composer files + run: | + cd ${{ github.workspace }}/cacti + if [ -f composer.json ]; then + composer validate --strict || true + fi + + - name: Install Composer Dependencies + run: | + cd ${{ github.workspace }}/cacti + if [ -f composer.json ]; then + sudo composer install --prefer-dist --no-progress + fi + + - name: Create Cacti config.php + run: | + cat ${{ github.workspace }}/cacti/include/config.php.dist | \ + sed -r "s/localhost/127.0.0.1/g" | \ + sed -r "s/'cacti'/'cacti'/g" | \ + sed -r "s/'cactiuser'/'cactiuser'/g" | \ + sed -r "s/'cactiuser'/'cactiuser'/g" > ${{ github.workspace }}/cacti/include/config.php + sudo chmod 664 ${{ github.workspace }}/cacti/include/config.php + + - name: Configure Apache + run: | + cat << 'EOF' | sed 's#GITHUB_WORKSPACE#${{ github.workspace }}#g' > /tmp/cacti.conf + + ServerAdmin webmaster@localhost + DocumentRoot GITHUB_WORKSPACE/cacti + + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + EOF + sudo cp /tmp/cacti.conf /etc/apache2/sites-available/000-default.conf + sudo systemctl restart apache2 + + - name: Install Cacti via CLI + run: | + cd ${{ github.workspace }}/cacti + sudo php cli/install_cacti.php --accept-eula --install --force + + - name: Install mactrack Plugin + run: | + cd ${{ github.workspace }}/cacti + sudo php cli/plugin_manage.php --plugin=mactrack --install --enable + +# - name: import mactrack Plugin Sample Data +# run: | +# cd ${{ github.workspace }}/cacti/plugins/mactrack +# sudo php cli_import.php --filename=.github/workflows/mactrack_sample_data.xml +# if [ $? -ne 0 ]; then +# echo "Failed to import Thold sample data" +# exit 1 +# fi + + - name: Check PHP Syntax for Plugin + run: | + cd ${{ github.workspace }}/cacti/plugins/mactrack + if find . -name '*.php' -exec php -l {} 2>&1 \; | grep -iv 'no syntax errors detected'; then + echo "Syntax errors found!" + exit 1 + fi + + - name: Remove the plugins directory exclusion from the .phpstan.neon + run: sed '/plugins/d' -i .phpstan.neon + working-directory: ${{ github.workspace }}/cacti + + - name: Mark composer scripts executable + run: sudo chmod +x ${{ github.workspace }}/cacti/include/vendor/bin/* + + - name: Run Linter on base code + run: composer run-script lint ${{ github.workspace }}/cacti/plugins/mactrack + working-directory: ${{ github.workspace }}/cacti + + - name: Checking coding standards on base code + run: composer run-script phpcsfixer ${{ github.workspace }}/cacti/plugins/mactrack + working-directory: ${{ github.workspace }}/cacti + +# - name: Run PHPStan at Level 6 on base code outside of Composer due to technical issues +# run: ./include/vendor/bin/phpstan analyze --level 6 ${{ github.workspace }}/cacti/plugins/mactrack +# working-directory: ${{ github.workspace }}/cacti + + - name: Run Cacti Poller + run: | + cd ${{ github.workspace }}/cacti + sudo php poller.php --poller=1 --force --debug + if ! grep -q "SYSTEM STATS" log/cacti.log; then + echo "Cacti poller did not finish successfully" + cat log/cacti.log + exit 1 + fi + + - name: View Cacti Logs + if: always() + run: | + if [ -f ${{ github.workspace }}/cacti/log/cacti.log ]; then + echo "=== Cacti Log ===" + sudo cat ${{ github.workspace }}/cacti/log/cacti.log + fi From 8b1d11f390523b5163eea21164fb7e049b7db91d Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Sat, 11 Apr 2026 13:41:49 -0700 Subject: [PATCH 5/6] fix(security): escape filter option labels --- mactrack_device_types.php | 2 +- mactrack_view_macs.php | 4 +-- .../test_mactrack_filter_output_wiring.php | 36 +++++++++++++++++++ tests/Unit/test_filter_option_escaping.php | 19 ++++++++++ .../test_mactrack_no_raw_filter_labels.php | 36 +++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 tests/Integration/test_mactrack_filter_output_wiring.php create mode 100644 tests/Unit/test_filter_option_escaping.php create mode 100644 tests/e2e/test_mactrack_no_raw_filter_labels.php diff --git a/mactrack_device_types.php b/mactrack_device_types.php index e7f199e..66b98db 100644 --- a/mactrack_device_types.php +++ b/mactrack_device_types.php @@ -1100,7 +1100,7 @@ function mactrack_device_type_filter() { if (get_request_var('vendor') == $type['vendor']) { print ' selected'; - } print '>' . $type['vendor'] . ''; + } print '>' . html_escape($type['vendor']) . ''; } } ?> diff --git a/mactrack_view_macs.php b/mactrack_view_macs.php index 71afc19..47a0878 100644 --- a/mactrack_view_macs.php +++ b/mactrack_view_macs.php @@ -1116,7 +1116,7 @@ function mactrack_mac_filter() { if (get_request_var('site_id') == $site['site_id']) { print ' selected'; - } print '>' . $site['site_name'] . ''; + } print '>' . html_escape($site['site_name']) . ''; } } ?> @@ -1147,7 +1147,7 @@ function mactrack_mac_filter() { if (get_request_var('device_id') == $filter_device['device_id']) { print ' selected'; - } print '>' . $filter_device['device_name'] . '(' . $filter_device['hostname'] . ')' . ''; + } print '>' . html_escape($filter_device['device_name'] . '(' . $filter_device['hostname'] . ')') . ''; } } ?> diff --git a/tests/Integration/test_mactrack_filter_output_wiring.php b/tests/Integration/test_mactrack_filter_output_wiring.php new file mode 100644 index 0000000..e1e2bbd --- /dev/null +++ b/tests/Integration/test_mactrack_filter_output_wiring.php @@ -0,0 +1,36 @@ + array( + "html_escape(\$site['site_name'])", + "html_escape(\$filter_device['device_name'] . '(' . \$filter_device['hostname'] . ')')", + ), + __DIR__ . '/../../mactrack_device_types.php' => array( + "html_escape(\$type['vendor'])", + ), +); + +foreach ($checks as $path => $patterns) { + $contents = file_get_contents($path); + + if ($contents === false) { + fwrite(STDERR, "Unable to read {$path}\n"); + exit(1); + } + + foreach ($patterns as $pattern) { + if (strpos($contents, $pattern) === false) { + fwrite(STDERR, "Missing expected escaped output: {$pattern}\n"); + exit(1); + } + } +} + +print "OK\n"; diff --git a/tests/Unit/test_filter_option_escaping.php b/tests/Unit/test_filter_option_escaping.php new file mode 100644 index 0000000..f54d39e --- /dev/null +++ b/tests/Unit/test_filter_option_escaping.php @@ -0,0 +1,19 @@ +"; +$escaped = htmlspecialchars($payload, ENT_QUOTES, 'UTF-8'); + +if (strpos($escaped, '"; +$payload = 'device">'; $escaped = htmlspecialchars($payload, ENT_QUOTES, 'UTF-8'); if (strpos($escaped, '