diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index a8a7940165..7a6aeff356 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.769-230302 +Version: 7.0NG.769-230303 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 21522e4937..fa61aa49c9 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.769-230302" +pandora_version="7.0NG.769-230303" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index a1e5ea6e0e..0a12df1c9f 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1023,7 +1023,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.769'; -use constant AGENT_BUILD => '230302'; +use constant AGENT_BUILD => '230303'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 107be42b57..89ea2a0b9f 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -4,7 +4,7 @@ %global __os_install_post %{nil} %define name pandorafms_agent_linux %define version 7.0NG.769 -%define release 230302 +%define release 230303 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 0f5ae307c0..aed2381793 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -4,7 +4,7 @@ %global __os_install_post %{nil} %define name pandorafms_agent_linux %define version 7.0NG.769 -%define release 230302 +%define release 230303 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index 6c14bec893..c63a4a6cfc 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.769" -PI_BUILD="230302" +PI_BUILD="230303" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 0c79064ec1..2c51bc2a4b 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{230302} +{230303} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 13c0a7445d..acf6b701e5 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.769 Build 230302") +#define PANDORA_VERSION ("7.0NG.769 Build 230303") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index eff0e22339..c6e79f7d24 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.769(Build 230302))" + VALUE "ProductVersion", "(7.0NG.769(Build 230303))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 59ea1588fa..57d645e9b5 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.769-230302 +Version: 7.0NG.769-230303 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index aaae992e96..f701f80ec0 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.769-230302" +pandora_version="7.0NG.769-230303" package_pear=0 package_pandora=1 diff --git a/pandora_console/extras/mr/62.sql b/pandora_console/extras/mr/62.sql index 9d9c14656f..f92441a5f0 100644 --- a/pandora_console/extras/mr/62.sql +++ b/pandora_console/extras/mr/62.sql @@ -60,7 +60,31 @@ UPDATE `ttipo_modulo` SET `icon` = 'remote-execution-incremental-data@svg.svg' W UPDATE `ttipo_modulo` SET `icon` = 'server-web@svg.svg' WHERE `id_tipo` = 38; UPDATE `ttipo_modulo` SET `icon` = 'keepalive@svg.svg' WHERE `id_tipo` = 100; +CREATE TABLE IF NOT EXISTS `tagent_filter` ( + `id_filter` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `id_name` VARCHAR(600) NOT NULL, + `id_group_filter` INT NOT NULL DEFAULT 0, + `group_id` INT NOT NULL DEFAULT 0, + `recursion` TEXT, + `status` INT NOT NULL DEFAULT -1, + `search` TEXT, + `id_os` INT NOT NULL DEFAULT 0, + `policies` TEXT, + `search_custom` TEXT, + `ag_custom_fields` TEXT, + PRIMARY KEY (`id_filter`) +) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; + +CREATE TABLE `tevent_sound` ( + `id` INT NOT NULL AUTO_INCREMENT, + `name` TEXT NULL, + `sound` TEXT NULL, + `active` TINYINT NOT NULL DEFAULT '1', +PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE INDEX agente_modulo_estado ON tevento (estado, id_agentmodule); CREATE INDEX idx_disabled ON talert_template_modules (disabled); +INSERT INTO `treport_custom_sql` (`name`, `sql`) VALUES ('Agent safe mode not enable', 'select alias from tagente where safe_mode_module = 0'); + COMMIT; diff --git a/pandora_console/extras/mr/63.sql b/pandora_console/extras/mr/63.sql deleted file mode 100644 index 401d4a748c..0000000000 --- a/pandora_console/extras/mr/63.sql +++ /dev/null @@ -1,5 +0,0 @@ -START TRANSACTION; - -INSERT INTO `treport_custom_sql` (`name`, `sql`) VALUES ('Agent safe mode not enable', 'select alias from tagente where safe_mode_module = 0'); - -COMMIT; diff --git a/pandora_console/godmode/events/configuration_sounds.php b/pandora_console/godmode/events/configuration_sounds.php new file mode 100644 index 0000000000..d4e9d77688 --- /dev/null +++ b/pandora_console/godmode/events/configuration_sounds.php @@ -0,0 +1,71 @@ + '[EventSound]'.$e->getMessage() ]); + exit; + } else { + echo '[EventSound]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; +} + +// AJAX controller. +if ((bool) is_ajax() === true) { + $method = get_parameter('method'); + + if (method_exists($controller, $method) === true) { + if ($controller->ajaxMethod($method) === true) { + $controller->{$method}(); + } else { + $controller->error('Unavailable method.'); + } + } else { + $controller->error('Method not found. ['.$method.']'); + } + + // Stop any execution. + exit; +} else { + // Run. + $controller->run(); +} diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index e9c262b7cf..af15b28f7a 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -438,6 +438,10 @@ if ((bool) check_acl($config['id_user'], 0, 'PM') === true || (bool) check_acl($ } } + $sub['godmode/events/configuration_sounds']['text'] = __('Accoustic console setup'); + $sub['godmode/events/configuration_sounds']['id'] = 'Accoustic console setup'; + $sub['godmode/events/configuration_sounds']['pages'] = ['godmode/events/configuration_sounds']; + $menu_godmode['gextensions']['sub'] = $sub; } diff --git a/pandora_console/images/omnishell.png b/pandora_console/images/omnishell.png new file mode 100644 index 0000000000..02c8f0e071 Binary files /dev/null and b/pandora_console/images/omnishell.png differ diff --git a/pandora_console/include/ajax/agent.php b/pandora_console/include/ajax/agent.php index 48abefdc7e..f0884dea7f 100644 --- a/pandora_console/include/ajax/agent.php +++ b/pandora_console/include/ajax/agent.php @@ -31,6 +31,15 @@ $get_agents_interfaces = (bool) get_parameter('get_agents_interfaces'); $id_agents = get_parameter('id_agents', []); $get_agents_group = (bool) get_parameter('get_agents_group', false); $force_local = (bool) get_parameter('force_local', false); + +// Agent detail filter. +$load_filter_modal = get_parameter('load_filter_modal', 0); +$save_filter_modal = get_parameter('save_filter_modal', 0); +$get_agent_filters = get_parameter('get_agent_filters', 0); +$save_agent_filter = get_parameter('save_agent_filter', 0); +$update_agent_filter = get_parameter('update_agent_filter', 0); +$delete_agent_filter = get_parameter('delete_agent_filter', 0); + if (https_is_running()) { header('Content-type: application/json'); } @@ -345,4 +354,656 @@ if ($search_agents && (!is_metaconsole() || $force_local)) { return; } +// Saves an event filter. +if ($save_agent_filter) { + $values = []; + $values['id_name'] = get_parameter('id_name'); + $values['group_id'] = get_parameter('group_id'); + $values['recursion'] = get_parameter('recursion'); + $values['status'] = get_parameter('status'); + $values['search'] = get_parameter('search'); + $values['id_os'] = get_parameter('id_os'); + $values['policies'] = json_encode(get_parameter('policies')); + $values['search_custom'] = get_parameter('search_custom'); + $values['ag_custom_fields'] = get_parameter('ag_custom_fields'); + $values['id_group_filter'] = get_parameter('id_group_filter'); + + $exists = (bool) db_get_value_filter( + 'id_filter', + 'tagent_filter', + $values + ); + + if ($exists === true) { + echo 'duplicate'; + } else { + $result = db_process_sql_insert('tagent_filter', $values); + + if ($result === false) { + echo 'error'; + } else { + echo $result; + } + } +} + +if ($update_agent_filter) { + $values = []; + $id = get_parameter('id'); + + $values['group_id'] = get_parameter('group_id'); + $values['recursion'] = get_parameter('recursion'); + $values['status'] = get_parameter('status'); + $values['search'] = get_parameter('search'); + $values['id_os'] = get_parameter('id_os'); + $values['policies'] = json_encode(get_parameter('policies')); + $values['search_custom'] = get_parameter('search_custom'); + $values['ag_custom_fields'] = get_parameter('ag_custom_fields'); + + $result = db_process_sql_update( + 'tagent_filter', + $values, + ['id_filter' => $id] + ); + + if ($result === false) { + echo 'error'; + } else { + echo 'ok'; + } +} + +if ($delete_agent_filter) { + $id = get_parameter('id'); + + $user_groups = users_get_groups( + $config['id_user'], + 'AW', + users_can_manage_group_all('AW'), + true + ); + + $sql = 'DELETE + FROM tagent_filter + WHERE id_filter = '.$id.' AND id_group_filter IN ('.implode(',', array_keys($user_groups)).')'; + + $agent_filters = db_process_sql($sql); + + if ($agent_filters === false) { + echo 'error'; + } else { + echo 'ok'; + } +} + +if ($get_agent_filters) { + $user_groups = users_get_groups( + $config['id_user'], + 'AR', + users_can_manage_group_all('AR'), + true + ); + + $sql = 'SELECT id_filter, id_name + FROM tagent_filter + WHERE id_group_filter IN ('.implode(',', array_keys($user_groups)).')'; + + $agent_filters = db_get_all_rows_sql($sql); + + $result = []; + + if ($agent_filters !== false) { + foreach ($agent_filters as $agent_filter) { + $result[$agent_filter['id_filter']] = $agent_filter['id_name']; + } + } + + echo io_json_mb_encode($result); +} + +if ((int) $load_filter_modal === 1) { + $user_groups = users_get_groups( + $config['id_user'], + 'AR', + users_can_manage_group_all('AR'), + true + ); + + $sql = 'SELECT id_filter, id_name + FROM tagent_filter + WHERE id_group_filter IN ('.implode(',', array_keys($user_groups)).')'; + + $agent_filters = db_get_all_rows_sql($sql); + + $filters = []; + foreach ($agent_filters as $agent_filter) { + $filters[$agent_filter['id_filter']] = $agent_filter['id_name']; + } + + echo '
'; + echo '
'; + + $table = new StdClass; + $table->id = 'load_filter_form'; + $table->width = '100%'; + $table->cellspacing = 4; + $table->cellpadding = 4; + $table->class = 'databox'; + if (is_metaconsole()) { + $table->cellspacing = 0; + $table->cellpadding = 0; + $table->class = 'databox filters'; + } + + $table->styleTable = 'font-weight: bold; color: #555; text-align:left;'; + $filter_id_width = '200px'; + if (is_metaconsole()) { + $filter_id_width = '150px'; + } + + $data = []; + $table->rowid[3] = 'update_filter_row1'; + $data[0] = __('Load filter').$jump; + $data[0] .= html_print_select( + $filters, + 'filter_id', + $current, + '', + __('None'), + 0, + true, + false, + true, + '', + false, + 'margin-left:5px; width:'.$filter_id_width.';' + ); + + $data[1] = html_print_submit_button( + __('Load filter'), + 'load_filter', + false, + 'class="sub upd"', + true + ); + $data[1] .= html_print_input_hidden('load_filter', 1, true); + $table->data[] = $data; + $table->rowclass[] = ''; + html_print_table($table); + echo '
'; + echo '
'; + ?> + + + '; + if (check_acl($config['id_user'], 0, 'AW')) { + echo '
'; + + $table = new StdClass; + $table->id = 'save_filter_form'; + $table->width = '100%'; + $table->cellspacing = 4; + $table->cellpadding = 4; + $table->class = 'databox'; + + if (is_metaconsole() === true) { + $table->class = 'databox filters'; + $table->cellspacing = 0; + $table->cellpadding = 0; + } + + $table->styleTable = 'font-weight: bold; text-align:left;'; + + if (is_metaconsole() === true) { + $table->style[0] = 'width: 50%; width:50%;'; + } + + $data = []; + $table->rowid[0] = 'update_save_selector'; + $data[0] = html_print_radio_button( + 'filter_mode', + 'new', + '', + true, + true + ).__('New filter').''; + + $data[1] = html_print_radio_button( + 'filter_mode', + 'update', + '', + false, + true + ).__('Update/delete filter').''; + + $table->data[] = $data; + $table->rowclass[] = ''; + + $data = []; + $table->rowid[1] = 'save_filter_row1'; + $data[0] = __('Filter name').$jump; + $data[0] .= html_print_input_text('id_name', '', '', 15, 255, true); + + if (is_metaconsole() === true) { + $data[1] = __('Save in Group').$jump; + } else { + $data[1] = __('Filter group').$jump; + } + + $user_groups_array = users_get_groups_for_select( + $config['id_user'], + 'AW', + users_can_manage_group_all('AW'), + true + ); + + $data[1] .= html_print_select( + $user_groups_array, + 'id_group_filter_dialog', + $id_group_filter, + '', + '', + 0, + true, + false, + false, + 'w130' + ); + + $table->data[] = $data; + $table->rowclass[] = ''; + + $data = []; + $table->rowid[2] = 'save_filter_row2'; + + $table->data[] = $data; + $table->rowclass[] = ''; + + $data = []; + $table->rowid[3] = 'update_filter_row1'; + $data[0] = __('Filter').$jump; + + $user_groups = users_get_groups( + $config['id_user'], + 'AW', + users_can_manage_group_all('AW'), + true + ); + + $sql = 'SELECT id_filter, id_name + FROM tagent_filter + WHERE id_group_filter IN ('.implode(',', array_keys($user_groups)).')'; + + $agent_filters = db_get_all_rows_sql($sql); + + $_filters_update = []; + + if ($agent_filters !== false) { + foreach ($agent_filters as $agent_filter) { + $_filters_update[$agent_filter['id_filter']] = $agent_filter['id_name']; + } + } + + $data[0] .= html_print_select( + $_filters_update, + 'overwrite_filter', + '', + '', + '', + 0, + true + ); + + $table->data[] = $data; + $table->rowclass[] = ''; + + html_print_table($table); + echo '

'; + echo html_print_submit_button( + __('Update filter'), + 'update_filter', + false, + 'class="sub upd" onclick="save_update_filter();"', + true + ); + echo html_print_submit_button( + __('Delete filter'), + 'delete_filter', + false, + 'class="sub delete float-right" onclick="save_delete_filter();"', + true + ); + echo '
'; + echo '

'; + echo html_print_submit_button( + __('Save current filter'), + 'save_filter', + false, + 'class="sub upd float-right" onclick="save_new_filter();"', + true + ); + echo '
'; + } else { + include 'general/noaccess.php'; + } + + echo ''; + ?> + + 'StarTrek emergency simulation', ]; + $eventsounds = mysql_db_get_all_rows_sql('SELECT * FROM tevent_sound WHERE active = 1'); + foreach ($eventsounds as $key => $row) { + $sounds[$row['sound']] = $row['name']; + } + $inputs[] = [ 'class' => 'test-sounds', 'direct' => 1, diff --git a/pandora_console/include/ajax/module.php b/pandora_console/include/ajax/module.php index 9e57c89c1a..6cff09f98e 100755 --- a/pandora_console/include/ajax/module.php +++ b/pandora_console/include/ajax/module.php @@ -73,6 +73,7 @@ if (check_login()) { $get_monitor_filters = get_parameter('get_monitor_filters', 0); $save_monitor_filter = get_parameter('save_monitor_filter', 0); $update_monitor_filter = get_parameter('update_monitor_filter', 0); + $delete_monitor_filter = get_parameter('delete_monitor_filter', 0); if ($get_agent_modules_json_by_name === true) { $agent_name = get_parameter('agent_name'); @@ -1766,6 +1767,29 @@ if (check_login()) { } } + if ($delete_monitor_filter) { + $id = get_parameter('id'); + + $user_groups = users_get_groups( + $config['id_user'], + 'AW', + users_can_manage_group_all('AW'), + true + ); + + $sql = 'DELETE + FROM tmonitor_filter + WHERE id_filter = '.$id.' AND id_group_filter IN ('.implode(',', array_keys($user_groups)).')'; + + $monitor_filters = db_process_sql($sql); + + if ($monitor_filters === false) { + echo 'error'; + } else { + echo 'ok'; + } + } + if ($get_monitor_filters) { $sql = 'SELECT id_filter, id_name FROM tmonitor_filter'; @@ -1786,7 +1810,7 @@ if (check_login()) { $user_groups = users_get_groups( $config['id_user'], 'AR', - users_can_manage_group_all(), + users_can_manage_group_all('AR'), true ); @@ -1898,7 +1922,7 @@ if (check_login()) { ); $data[0][1] = html_print_label_input_block( - __('Update filter'), + __('Update/delete filter'), html_print_radio_button( 'filter_mode', 'update', @@ -1922,7 +1946,7 @@ if (check_login()) { $user_groups_array = users_get_groups_for_select( $config['id_user'], 'AW', - users_can_manage_group_all(), + users_can_manage_group_all('AW'), true ); @@ -1975,7 +1999,7 @@ if (check_login()) { 'id' => 'submit-save_filter', 'class' => 'action-buttons', 'content' => html_print_submit_button( - __('Save filter'), + __('Save current filter'), 'srcbutton', false, [ @@ -1989,21 +2013,35 @@ if (check_login()) { false ); + $input_actions = html_print_submit_button( + __('Delete filter'), + 'delete_filter', + false, + [ + 'icon' => 'delete', + 'mode' => 'mini', + 'onclick' => 'save_delete_filter();', + ], + true + ); + + $input_actions .= html_print_submit_button( + __('Update filter'), + 'srcbutton', + false, + [ + 'icon' => 'update', + 'mode' => 'mini', + 'onclick' => 'save_update_filter();', + ], + true + ); + html_print_div( [ 'id' => 'update_filter_row', 'class' => 'action-buttons', - 'content' => html_print_submit_button( - __('Update filter'), - 'srcbutton', - false, - [ - 'icon' => 'search', - 'mode' => 'mini', - 'onclick' => 'save_update_filter();', - ], - true - ), + 'content' => $input_actions, ], false ); @@ -2017,17 +2055,20 @@ if (check_login()) { function show_save_filter() { $('#save_filter_row2').hide(); $('#update_filter_row').hide(); + $('#update_delete_row').hide(); // Filter save mode selector $("[name='filter_mode']").click(function() { if ($(this).val() == 'new') { $('#save_filter_row2').hide(); $('#submit-save_filter').show(); $('#update_filter_row').hide(); + $('#update_delete_row').hide(); } else { $('#save_filter_row2').show(); $('#update_filter_row').show(); $('#submit-save_filter').hide(); + $('#update_delete_row').show(); } }); $("#save-filter-select").dialog({ @@ -2220,6 +2261,69 @@ if (check_login()) { $('#filter_loaded_span').html($('#filter_loaded_text').html() + ': ' + name_filter_update); return false; } + + function save_delete_filter() { + var id_filter_update = $("#overwrite_filter").val(); + + jQuery.post ("", + { + "page" : "include/ajax/module", + "delete_monitor_filter" : 1, + "id" : $("#overwrite_filter").val(), + }, + function (data) { + $(".info_box").hide(); + if (data == 'ok') { + $(".info_box").filter(function(i, item) { + if ($(item).data('type_info_box') == "success_update_filter") { + return true; + } + else + return false; + }).show(); + } + else { + $(".info_box").filter(function(i, item) { + if ($(item).data('type_info_box') == "error_create_filter") { + return true; + } + else + return false; + }).show(); + } + }); + + // First remove all options of filters select. + $('#filter_id').find('option').remove().end(); + + // Add 'none' option. + $('#filter_id').append ($('').html ( ).attr ("value", 0)); + + // Reload filters select. + jQuery.post ("", + { + "page" : "include/ajax/module", + "get_monitor_filters" : 1 + }, + function (data) { + jQuery.each (data, function (i, val) { + s = js_html_entity_decode(val); + if (i == id_filter_update) { + $('#filter_id').append ($('').html (s).attr ("value", i)); + } + else { + $('#filter_id').append ($('').html (s).attr ("value", i)); + } + }); + }, + "json" + ); + + // Close dialog + $('.ui-dialog-titlebar-close').trigger('click'); + + return false; + } $(document).ready(function() { show_save_filter(); diff --git a/pandora_console/include/class/EventSound.class.php b/pandora_console/include/class/EventSound.class.php new file mode 100644 index 0000000000..b943e9cce1 --- /dev/null +++ b/pandora_console/include/class/EventSound.class.php @@ -0,0 +1,495 @@ +ajaxController = $ajaxController; + } + + + /** + * Run view + * + * @return void + */ + public function run() + { + global $config; + $tab = get_parameter('tab', ''); + $action = get_parameter('action', ''); + $message_ok = 0; + $error_msg = __('Name already exist'); + $ok_msg = __('Successfully created'); + + if ($action == 'create') { + $name = get_parameter('name', ''); + $sound = get_parameter('file', ''); + + $exist = db_get_all_rows_sql(sprintf('SELECT * FROM tevent_sound WHERE name = "%s"', $name)); + + if ($exist === false) { + $uploadMaxFilesize = config_return_in_bytes(ini_get('upload_max_filesize')); + + $upload_status = get_file_upload_status('file'); + $upload_result = translate_file_upload_status($upload_status); + if ($uploadMaxFilesize < $sound['size']) { + $error_msg = __('File is too large to upload. Check the configuration in php.ini.'); + } else { + $pathname = $config['homedir'].'/include/sounds/'; + $nameSound = str_replace(' ', '_', $_FILES['file']['name']); + $target_file = $pathname.basename($nameSound); + + if (file_exists($target_file)) { + $error_msg = __('Sound already are exists.'); + } else { + if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) { + $insert = db_process_sql_insert( + 'tevent_sound', + [ + 'name' => $name, + 'sound' => $nameSound, + ] + ); + $ok_msg = __('Successfully created'); + } else { + $error_msg = __('Fail uploading the sound'); + } + } + } + + if ($insert > 0) { + $tab = ''; + $message_ok = 1; + } + } else { + $error_msg = __('Sound already are exists'); + } + } else if ($action == 'change_action') { + $id = get_parameter('id', ''); + $new_action = (int) get_parameter('set_action', '1'); + + $exist = db_get_all_rows_sql(sprintf('SELECT * FROM tevent_sound WHERE id = "%s"', $id)); + + if ($exist !== false) { + $result = db_process_sql_update( + 'tevent_sound', + ['active' => $new_action], + ['id' => $id] + ); + if (false === (bool) $result) { + $error_msg = __('Error on update status'); + } else { + $message_ok = 1; + } + } else { + $error_msg = __('Sound not exist'); + } + } + + if ($action) { + ui_print_result_message( + $message_ok, + $ok_msg, + $error_msg, + '', + false + ); + } + + $base_url = 'index.php?sec=eventos&sec2=godmode/events/configuration_sounds'; + $setup_url = $base_url.'&tab=add'; + $tabs = [ + 'list' => [ + 'text' => ''.html_print_image( + 'images/eye_show.png', + true, + [ + 'title' => __('Sounds'), + 'class' => 'invert_filter', + ] + ).'', + 'active' => (bool) ($tab != 'add'), + ], + 'options' => [ + 'text' => ''.html_print_image( + 'images/pen.png', + true, + [ + 'title' => __('Create'), + 'class' => 'invert_filter', + ] + ).'', + 'active' => (bool) ($tab == 'add'), + ], + ]; + + if ($tab === 'add') { + $helpHeader = ''; + $titleHeader = __('Add new sound'); + } else { + $helpHeader = 'servers_ha_clusters_tab'; + $titleHeader = __('Accoustic console sound list'); + } + + // Header. + ui_print_standard_header( + $titleHeader, + 'images/gm_servers.png', + false, + $helpHeader, + false, + $tabs, + [ + [ + 'link' => '', + 'label' => __('Admin tools'), + ], + [ + 'link' => '', + 'label' => __('Accoustic console setup'), + ], + ] + ); + + // Javascript. + ui_require_jquery_file('pandora'); + // CSS. + ui_require_css_file('wizard'); + ui_require_css_file('discovery'); + + if ($tab === 'add') { + echo '
'; + $table = new stdClass(); + $table->width = '100%'; + + $table->class = 'databox filters'; + $table->data = []; + $table->data[0][0] = __('Name:'); + + $table->data[0][1] = html_print_input_text( + 'name', + '', + '', + 80, + 100, + true, + false, + true + ); + + $table->data[1][0] = __('WAV Sound'); + $table->data[1][1] = html_print_input_file('file', true, ['required' => true]); + + html_print_table($table); + + echo '
'; + html_print_submit_button( + __('Create'), + 'save_sound', + false, + 'class="sub wand"' + ); + echo '
'; + echo '
'; + + // Load own javascript file. + echo $this->loadJS(); + } else { + // Datatables list. + try { + $columns = [ + 'name', + 'sound', + [ + 'text' => 'options', + 'class' => 'action_buttons mw120px', + ], + ]; + + $column_names = [ + __('Name'), + __('Sound'), + __('Options'), + ]; + + $this->tableId = 'event_sounds'; + + if (is_metaconsole() === true) { + // Only in case of Metaconsole, format the frame. + open_meta_frame(); + } + + // Load datatables user interface. + ui_print_datatable( + [ + 'id' => $this->tableId, + 'class' => 'info_table', + 'style' => 'width: 100%', + 'columns' => $columns, + 'column_names' => $column_names, + 'ajax_url' => $this->ajaxController, + 'ajax_data' => ['method' => 'draw'], + 'no_sortable_columns' => [-1], + 'order' => [ + 'field' => 'id', + 'direction' => 'asc', + ], + 'search_button_class' => 'sub filter', + 'form' => [ + 'inputs' => [ + [ + 'label' => __('Free search').ui_print_help_tip(__('Search filter by Name or Sound fields content'), true), + 'type' => 'text', + 'class' => 'w200px', + 'id' => 'filter_text', + 'name' => 'filter_text', + ], + [ + 'label' => __('Active'), + 'type' => 'select', + 'fields' => [ + '' => __('All'), + '0' => __('No'), + '1' => __('Yes'), + ], + 'class' => 'w100px', + 'id' => 'active', + 'name' => 'active', + ], + ], + ], + ] + ); + } catch (Exception $e) { + echo $e->getMessage(); + } + + if (is_metaconsole() === true) { + // Close the frame. + close_meta_frame(); + } + + // Load own javascript file. + echo $this->loadJS(); + } + } + + + /** + * Get the data for draw the table. + * + * @return void. + */ + public function draw() + { + global $config; + // Initialice filter. + $filter = '1=1'; + // Init data. + $data = []; + // Count of total records. + $count = 0; + // Catch post parameters. + $start = get_parameter('start', 0); + $length = get_parameter('length', $config['block_size']); + // There is a limit of (2^32)^2 (18446744073709551615) rows in a MyISAM table, show for show all use max nrows. + $length = ($length != '-1') ? $length : '18446744073709551615'; + $order = get_datatable_order(); + $filters = get_parameter('filter', []); + $filterText = $filters['filter_text']; + $filterActive = $filters['active']; + + if (empty($filterText) === false) { + $filter .= sprintf( + " AND (name LIKE '%%%s%%' OR sound LIKE '%%%s%%')", + $filterText, + $filterText + ); + } + + if (in_array($filterActive, [0, 1])) { + $filter .= sprintf( + ' AND active = %s', + $filterActive, + ); + } + + $count = (int) db_get_value_sql(sprintf('SELECT COUNT(*) as "total" FROM tevent_sound WHERE %s', $filter)); + + $sql = sprintf( + 'SELECT * + FROM tevent_sound + WHERE %s + ORDER BY %s + LIMIT %d, %d', + $filter, + $order, + $start, + $length + ); + $data = db_get_all_rows_sql($sql); + + foreach ($data as $key => $row) { + if ($row['active'] === '1') { + $img = 'images/lightbulb.png'; + $action = __('Disable sound'); + $new_action = 0; + } else { + $img = 'images/lightbulb_off.png'; + $action = __('Enable sound'); + $new_action = 1; + } + + $options = ''; + $options .= html_print_image( + $img, + true, + [ + 'title' => $action, + 'class' => 'invert_filter', + ] + ); + $options .= ''; + + $data[$key]['options'] = $options; + } + + echo json_encode( + [ + 'data' => $data, + 'recordsTotal' => $count, + 'recordsFiltered' => $count, + ] + ); + } + + + /** + * Checks if target method is available to be called using AJAX. + * + * @param string $method Target method. + * + * @return boolean True allowed, false not. + */ + public function ajaxMethod(string $method) + { + return in_array($method, $this->AJAXMethods); + } + + + /** + * Load Javascript code. + * + * @return string. + */ + public function loadJS() + { + // Nothing for this moment. + ob_start(); + + // Javascript content. + ?> + + $id_agent, 'id_usuario' => $id_user, 'id_grupo' => $id_group, 'estado' => $status, - 'timestamp' => date('Y-m-d H:i:s'), + 'timestamp' => date('Y-m-d H:i:s', $timestamp), 'evento' => $event, - 'utimestamp' => time(), + 'utimestamp' => $timestamp, 'event_type' => $event_type, 'id_agentmodule' => $id_agent_module, 'id_alert_am' => $id_aam, diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 9ef7b06d25..51b4cd427d 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -84,6 +84,27 @@ function html_debug_print($var, $file='', $oneline=false) } +/** + * Console log. + */ +function jslog($var) +{ + $more_info = ''; + if (is_string($var)) { + $more_info = 'size: '.strlen($var); + } else if (is_bool($var)) { + $more_info = 'val: '.($var ? 'true' : 'false'); + } else if (is_null($var)) { + $more_info = 'is null'; + } else if (is_array($var)) { + $more_info = count($var); + } + + echo ''."\n"; + echo ''; +} + + // Alias for "html_debug_print" function html_debug($var, $file='', $oneline=false) { diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 752eef9225..7862ad4b37 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -7557,3 +7557,22 @@ function ui_print_fullscreen_bar(array $options, bool $return=false) ); } + +function ui_print_status_div($status) +{ + switch ((int) $status) { + case 0: + $return = '
 
'; + break; + + case 1: + $return = '
 
'; + break; + + default: + $return = '
 
'; + break; + } + + return $return; +} \ No newline at end of file diff --git a/pandora_console/include/rest-api/models/VisualConsole/View.php b/pandora_console/include/rest-api/models/VisualConsole/View.php index cd1e25fd49..e8305df830 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/View.php +++ b/pandora_console/include/rest-api/models/VisualConsole/View.php @@ -144,6 +144,8 @@ class View extends \HTML tinyMCE.init({ selector: "#textarea_label", theme: "advanced", + convert_urls:false, + relative_urls:false, content_css: "'.ui_get_full_url(false, false, false, false).'include/styles/pandora.css", theme_advanced_font_sizes: "4pt=.visual_font_size_4pt, " + diff --git a/pandora_console/install.php b/pandora_console/install.php index 7938198596..f89f637f9e 100644 --- a/pandora_console/install.php +++ b/pandora_console/install.php @@ -131,7 +131,7 @@
0) { + $user_groups_fl = users_get_groups( + $config['id_user'], + 'AR', + users_can_manage_group_all('AR'), + true + ); + + $sql = sprintf( + 'SELECT id_filter, id_name + FROM tagent_filter + WHERE id_filter = %d AND id_group_filter IN (%s)', + $load_filter_id, + implode(',', array_keys($user_groups_fl)) + ); + + $loaded_filter = db_get_row_sql($sql); +} + +if ($loaded_filter['id_filter'] > 0) { + $query_filter['id_filter'] = $load_filter_id; + $filter = db_get_row_filter('tagent_filter', $query_filter, false); + + if ($filter !== false) { + $group_id = (int) $filter['group_id']; + $recursion = $filter['recursion']; + $status = $filter['status']; + $search = $filter['search']; + $os = $filter['id_os']; + $policies = json_decode($filter['policies'], true); + $search_custom = $filter['search_custom']; + $ag_custom_fields = $filter['ag_custom_fields']; + } + + + if (is_array($ag_custom_fields) === false) { + $ag_custom_fields = json_decode(io_safe_output($ag_custom_fields), true); + } + + if (is_array($policies) === false) { + $policies = json_decode(io_safe_output($policies), true); + } +} + if ((bool) check_acl($config['id_user'], 0, 'AW') === true) { // Prepare the tab system to the future. $tab = 'setup'; @@ -312,6 +362,118 @@ $table->data['search_fields'][1] = html_print_label_input_block( ) ); +/* + $table->data[1][0] = __('Operating System').' '; + + $pre_fields = db_get_all_rows_sql( + 'select distinct(tagente.id_os),tconfig_os.name from tagente,tconfig_os where tagente.id_os = tconfig_os.id_os' + ); + $fields = []; + + foreach ($pre_fields as $key => $value) { + $fields[$value['id_os']] = $value['name']; + } + + $table->data[1][0] .= html_print_select($fields, 'os', $os, '', 'All', 0, true); + + $table->data[1][1] = __('Policies').' '; + + $pre_fields = policies_get_policies(false, ['id', 'name']); + $fields = []; + + foreach ($pre_fields as $value) { + $fields[$value['id']] = $value['name']; + } + + $table->data[1][1] .= html_print_select($fields, 'policies[]', $policies, '', 'All', 0, true, true); + + $table->data[1][2] = __('Search in custom fields').' '.' '.' '; + $table->data[1][2] .= html_print_input_text('search_custom', $search_custom, '', 15, 255, true); + + + $custom_fields = db_get_all_fields_in_table('tagent_custom_fields'); + if ($custom_fields === false) { + $custom_fields = []; + } + + $div_custom_fields = '
'; + foreach ($custom_fields as $custom_field) { + $custom_field_value = ''; + if (empty($ag_custom_fields) === false) { + $custom_field_value = $ag_custom_fields[$custom_field['id_field']]; + if (empty($custom_field_value) === true) { + $custom_field_value = ''; + } + } + + $div_custom_fields .= '
'; + + $div_custom_fields .= '
'; + $div_custom_fields .= ''.$custom_field['name'].''; + $div_custom_fields .= '
'; + + $div_custom_fields .= '
'; + $div_custom_fields .= html_print_input_text( + 'ag_custom_fields['.$custom_field['id_field'].']', + $custom_field_value, + '', + 0, + 300, + true, + false, + false, + '', + 'div-input' + ); + $div_custom_fields .= '
'; + } + + $table->colspan[2][0] = 7; + $table->cellstyle[2][0] = 'padding-left: 10px;'; + $table->data[2][0] = ui_toggle( + $div_custom_fields, + __('Agent custom fields'), + '', + '', + true, + true, + '', + 'white-box-content', + 'white_table_graph' + ); + + + $table->colspan[4][0] = 4; + $table->cellstyle[4][0] = 'padding-top: 0px;'; + $table->data[4][0] = html_print_button( + __('Load filter'), + 'load-filter', + false, + '', + 'class="float-left margin-right-2 sub config"', + true + ); + + $table->cellstyle[4][0] .= 'padding-top: 0px;'; + $table->data[4][0] .= html_print_button( + __('Manage filter'), + 'save-filter', + false, + '', + 'class="float-left margin-right-2 sub wand"', + true + ); + + $table->cellstyle[4][2] = 'padding-top: 0px;'; + $table->data[4][2] = html_print_submit_button( + __('Search'), + 'srcbutton', + '', + ['class' => 'sub search'], + true + ); +*/ + $searchForm .= html_print_table($table, true); $searchForm .= html_print_div( [ @@ -367,6 +529,8 @@ $selectLastContactUp = false; $selectLastContactDown = false; $selectRemoteUp = false; $selectRemoteDown = false; +$selectLastStatusChangeUp = false; +$selectLastStatusChangeDown = false; $order = null; switch ($sortField) { @@ -526,6 +690,32 @@ switch ($sortField) { } break; + case 'last_status_change': + switch ($sort) { + case 'up': + $selectLastStatusChangeUp = $selected; + $order = [ + 'field' => 'last_status_change', + 'field2' => 'alias', + 'order' => 'ASC', + ]; + break; + + case 'down': + $selectLastStatusChangeDown = $selected; + $order = [ + 'field' => 'last_status_change', + 'field2' => 'alias', + 'order' => 'DESC', + ]; + break; + + default: + // Default. + break; + } + break; + case 'description': switch ($sort) { case 'up': @@ -565,6 +755,8 @@ switch ($sortField) { $selectDescriptionDown = false; $selectLastContactUp = false; $selectLastContactDown = false; + $selectLastStatusChangeUp = false; + $selectLastStatusChangeDown = false; $order = [ 'field' => 'alias', 'field2' => 'alias', @@ -624,6 +816,24 @@ if (empty($search_custom) === false) { $search_sql_custom = ''; } +// Filter by agent custom fields. +$sql_conditions_custom_fields = ''; +if (empty($ag_custom_fields) === false) { + $cf_filter = []; + foreach ($ag_custom_fields as $field_id => $value) { + if (empty($value) === false) { + $cf_filter[] = '(tagent_custom_data.id_field = '.$field_id.' AND tagent_custom_data.description LIKE \'%'.$value.'%\')'; + } + } + + if (empty($cf_filter) === false) { + $sql_conditions_custom_fields = ' AND tagente.id_agente IN ( + SELECT tagent_custom_data.id_agent + FROM tagent_custom_data + WHERE '.implode(' AND ', $cf_filter).')'; + } +} + // Show only selected groups. if ($group_id > 0) { $groups = [$group_id]; @@ -636,23 +846,41 @@ if ($group_id > 0) { $groups = array_keys($user_groups); } +$all_policies = in_array(0, ($policies ?? [])); + +$id_os_sql = ''; +$policies_sql = ''; + +if ($os > 0) { + $id_os_sql = ' AND id_os = '.$os; +} + +if ($all_policies === false && is_array($policies) && count($policies) > 0) { + $policies_sql = ' AND tpolicy_agents.id_policy IN ('.implode(',', $policies).')'; +} if ($strict_user) { $count_filter = [ // 'order' => 'tagente.nombre ASC', - 'order' => 'tagente.nombre ASC', - 'disabled' => 0, - 'status' => $status, - 'search' => $search, + 'order' => 'tagente.nombre ASC', + 'disabled' => 0, + 'status' => $status, + 'search' => $search, + 'id_os' => $id_os_sql, + 'policies' => $policies_sql, + 'other_condition' => $sql_conditions_custom_fields, ]; $filter = [ // 'order' => 'tagente.nombre ASC', - 'order' => 'tagente.nombre ASC', - 'disabled' => 0, - 'status' => $status, - 'search' => $search, - 'offset' => (int) get_parameter('offset'), - 'limit' => (int) $config['block_size'], + 'order' => 'tagente.nombre ASC', + 'disabled' => 0, + 'status' => $status, + 'search' => $search, + 'offset' => (int) get_parameter('offset'), + 'limit' => (int) $config['block_size'], + 'id_os' => $id_os_sql, + 'policies' => $policies_sql, + 'other_condition' => $sql_conditions_custom_fields, ]; if ($group_id > 0) { @@ -691,28 +919,48 @@ if ($strict_user) { $agents = tags_get_all_user_agents(false, $config['id_user'], $acltags, $filter, $fields, false, $strict_user, true); } else { + $count_filter = [ + 'disabled' => 0, + 'id_grupo' => $groups, + 'search' => $search_sql, + 'search_custom' => $search_sql_custom, + 'status' => $status, + 'id_os' => $id_os_sql, + 'policies' => $policies_sql, + 'other_condition' => $sql_conditions_custom_fields, + ]; + + $filter = [ + 'order' => 'nombre ASC', + 'id_grupo' => $groups, + 'disabled' => 0, + 'status' => $status, + 'search_custom' => $search_sql_custom, + 'search' => $search_sql, + 'offset' => (int) get_parameter('offset'), + 'limit' => (int) $config['block_size'], + 'id_os' => $id_os_sql, + 'policies' => $policies_sql, + 'other_condition' => $sql_conditions_custom_fields, + ]; + $total_agents = agents_count_agents_filter( - [ - 'disabled' => 0, - 'id_grupo' => $groups, - 'search' => $search_sql, - 'search_custom' => $search_sql_custom, - 'status' => $status, - ], + $count_filter, $access ); + $query_order = $order; + + if ($order['field'] === 'last_status_change') { + $query_order = [ + 'field' => 'alias', + 'field2' => 'alias', + 'order' => 'ASC', + ]; + } + $agents = agents_get_agents( - [ - 'order' => 'nombre ASC', - 'id_grupo' => $groups, - 'disabled' => 0, - 'status' => $status, - 'search_custom' => $search_sql_custom, - 'search' => $search_sql, - 'offset' => (int) get_parameter('offset'), - 'limit' => (int) $config['block_size'], - ], + $filter, [ 'id_agente', 'id_grupo', @@ -735,7 +983,7 @@ if ($strict_user) { 'agent_version', ], $access, - $order + $query_order ); } @@ -769,6 +1017,14 @@ $url_up_group = 'index.php?sec=view&sec2=operation/agentes/estado_agente& $url_down_group = 'index.php?sec=view&sec2=operation/agentes/estado_agente&refr='.$refr.'&offset='.$offset.'&group_id='.$group_id.'&recursion='.$recursion.'&search='.$search.'&status='.$status.'&sort_field=group&sort=down'; $url_up_last = 'index.php?sec=view&sec2=operation/agentes/estado_agente&refr='.$refr.'&offset='.$offset.'&group_id='.$group_id.'&recursion='.$recursion.'&search='.$search.'&status='.$status.'&sort_field=last_contact&sort=up'; $url_down_last = 'index.php?sec=view&sec2=operation/agentes/estado_agente&refr='.$refr.'&offset='.$offset.'&group_id='.$group_id.'&recursion='.$recursion.'&search='.$search.'&status='.$status.'&sort_field=last_contact&sort=down'; +$url_up_last_status_change = 'index.php?sec=view&sec2=operation/agentes/estado_agente&refr='.$refr.'&offset='.$offset.'&group_id='.$group_id.'&recursion='.$recursion.'&search='.$search.'&status='.$status.'&sort_field=last_status_change&sort=up'; +$url_down_last_status_change = 'index.php?sec=view&sec2=operation/agentes/estado_agente&refr='.$refr.'&offset='.$offset.'&group_id='.$group_id.'&recursion='.$recursion.'&search='.$search.'&status='.$status.'&sort_field=last_status_change&sort=down'; + +// Prepare pagination. +ui_pagination( + $total_agents, + ui_get_url_refresh(['group_id' => $group_id, 'recursion' => $recursion, 'search' => $search, 'sort_field' => $sortField, 'sort' => $sort, 'status' => $status]) +); // Show data. $tableAgents = new stdClass(); @@ -818,6 +1074,13 @@ $tableAgents->head[9] = ''.__('Last contact').''; $tableAgents->head[9] .= ui_get_sorting_arrows($url_up_last, $url_down_last, $selectLastContactUp, $selectLastContactDown); $tableAgents->size[9] = '15%'; +$tableAgents->head[10] = ''.__('Last status change').''; +$tableAgents->head[10] .= ui_get_sorting_arrows($url_up_last_status_change, $url_down_last_status_change, $selectLastStatusChangeUp, $selectLastStatusChangeDown); +$tableAgents->size[10] = '10%'; + +$tableAgents->head[11] = ''.__('Agent events').''; +$tableAgents->head[11] = '4%'; + $tableAgents->align = []; $tableAgents->align[2] = 'left'; @@ -828,6 +1091,8 @@ $tableAgents->align[6] = 'left'; $tableAgents->align[7] = 'left'; $tableAgents->align[8] = 'left'; $tableAgents->align[9] = 'left'; +$tableAgents->align[10] = 'left'; +$tableAgents->align[11] = 'left'; $tableAgents->style = []; $tableAgents->data = []; @@ -935,7 +1200,7 @@ foreach ($agents as $agent) { $data[1] = ''.ui_print_truncate_text($agent['description'], 'description', false, true, true, '[…]').''; - $data[10] = ''; + $data[12] = ''; if (enterprise_installed()) { enterprise_include_once('include/functions_config_agents.php'); @@ -993,6 +1258,27 @@ foreach ($agents as $agent) { $data[9] = agents_get_interval_status($agent); + $last_status_change_agent = agents_get_last_status_change($agent['id_agente']); + $time_elapsed = !empty($last_status_change_agent) ? human_time_comparation($last_status_change_agent) : ''.__('N/A').''; + $data[10] = $time_elapsed; + + $agent_event_filter = [ + 'id_agent' => $agent['id_agente'], + 'event_view_hr' => 48, + 'status' => -1, + ]; + + $fb64 = base64_encode(json_encode($agent_event_filter)); + $data[11] = ''.html_print_image( + 'images/lightning.png', + true, + [ + 'align' => 'middle', + 'title' => __('Agent events'), + 'class' => 'invert_filter', + ] + ).''; + // This old code was returning "never" on agents without modules, BAD !! // And does not print outdated agents in red. WRONG !!!! // $data[7] = ui_print_timestamp ($agent_info["last_contact"], true); @@ -1000,6 +1286,20 @@ foreach ($agents as $agent) { } if (empty($tableAgents->data) === false) { + if ($order['field'] === 'last_status_change') { + $order_direction = $order['order']; + usort( + $table->data, + function ($a, $b) use ($order_direction) { + if ($order_direction === 'ASC') { + return strtotime($a[10]) > strtotime($b[10]); + } else { + return strtotime($a[10]) < strtotime($b[10]); + } + } + ); + } + html_print_table($tableAgents); $tablePagination = ui_pagination( @@ -1046,10 +1346,68 @@ if ((bool) check_acl($config['id_user'], 0, 'AW') === true || (bool) check_acl($ echo ''; } +// Load filter div for dialog. +echo ''; +echo ''; + ?>