diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 8ab7ed2464..e7c241251a 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.775-240112 +Version: 7.0NG.775-240123 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 de56e36492..00e1bec872 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.775-240112" +pandora_version="7.0NG.775-240123" 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 44f466714e..40317705f1 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1039,7 +1039,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.775'; -use constant AGENT_BUILD => '240112'; +use constant AGENT_BUILD => '240123'; # 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 d87249cc31..8ed67cacd8 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.775 -%define release 240112 +%define release 240123 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.redhat_bin.el8.spec b/pandora_agents/unix/pandora_agent.redhat_bin.el8.spec index 4bf5bb42d9..e073b7a1b6 100644 --- a/pandora_agents/unix/pandora_agent.redhat_bin.el8.spec +++ b/pandora_agents/unix/pandora_agent.redhat_bin.el8.spec @@ -5,7 +5,7 @@ %define name pandorafms_agent_linux_bin %define source_name pandorafms_agent_linux %define version 7.0NG.775 -%define release 240112 +%define release 240123 %define debug_package %{nil} Summary: Pandora FMS Linux agent, binary version diff --git a/pandora_agents/unix/pandora_agent.redhat_bin.el9.spec b/pandora_agents/unix/pandora_agent.redhat_bin.el9.spec index 9470be01b5..ca44c46126 100644 --- a/pandora_agents/unix/pandora_agent.redhat_bin.el9.spec +++ b/pandora_agents/unix/pandora_agent.redhat_bin.el9.spec @@ -5,7 +5,7 @@ %define name pandorafms_agent_linux_bin %define source_name pandorafms_agent_linux %define version 7.0NG.775 -%define release 240112 +%define release 240123 %define debug_package %{nil} Summary: Pandora FMS Linux agent, binary version diff --git a/pandora_agents/unix/pandora_agent.redhat_bin.spec b/pandora_agents/unix/pandora_agent.redhat_bin.spec index cd42cc9d21..857491d509 100644 --- a/pandora_agents/unix/pandora_agent.redhat_bin.spec +++ b/pandora_agents/unix/pandora_agent.redhat_bin.spec @@ -5,7 +5,7 @@ %define name pandorafms_agent_linux_bin %define source_name pandorafms_agent_linux %define version 7.0NG.775 -%define release 240112 +%define release 240123 Summary: Pandora FMS Linux agent, binary version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 59adc646e9..1491df0b07 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.775 -%define release 240112 +%define release 240123 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 cddd5afa5f..0232a6bf8c 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.775" -PI_BUILD="240112" +PI_BUILD="240123" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 48be618d30..74ffb7b496 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{240112} +{240123} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index bc28a306f8..8e094eedae 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.775 Build 240112") +#define PANDORA_VERSION ("7.0NG.775 Build 240123") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index 3dfd32e864..b7d17d6756 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Pandora FMS" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.775(Build 240112))" + VALUE "ProductVersion", "(7.0NG.775(Build 240123))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 412b9f14a2..4d832ca478 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.775-240112 +Version: 7.0NG.775-240123 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 01b0eb0de2..95ee569569 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.775-240112" +pandora_version="7.0NG.775-240123" package_pear=0 package_pandora=1 diff --git a/pandora_console/extensions/grafana/index.php b/pandora_console/extensions/grafana/index.php index e925e56233..8a02e644cc 100644 --- a/pandora_console/extensions/grafana/index.php +++ b/pandora_console/extensions/grafana/index.php @@ -3,7 +3,7 @@ // Allow Grafana proxy header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); -header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, X-Grafana-Org-Id, X-Grafana-NoCache, X-DS-Authorization'); +header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, X-Grafana-Org-Id, X-Grafana-NoCache, X-DS-Authorization, Authorization'); // Get all request headers $headers = apache_request_headers(); @@ -23,7 +23,10 @@ if ($headers['X-DS-Authorization']) { list($user, $password) = explode(':', base64_decode($headers['X-DS-Authorization'])); - // Check user login + // Prevent sql injection. + $user = mysqli_real_escape_string($config['dbconnection'], $user); + + // Check user login. $user_in_db = process_user_login($user, $password, true); if ($user_in_db !== false) { diff --git a/pandora_console/extensions/grafana/query.php b/pandora_console/extensions/grafana/query.php index c5812a32c9..3c7a843542 100644 --- a/pandora_console/extensions/grafana/query.php +++ b/pandora_console/extensions/grafana/query.php @@ -2,7 +2,7 @@ // Allow Grafana proxy. header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); -header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, X-Grafana-Org-Id, X-Grafana-NoCache, X-DS-Authorization'); +header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, X-Grafana-Org-Id, X-Grafana-NoCache, X-DS-Authorization, Authorization'); // Get all request headers. $headers = apache_request_headers(); @@ -38,7 +38,7 @@ if ($headers['Authorization']) { $result_data = []; // Decode target data sent by datasource plugin in Grafana - $target_data = json_decode($target['target'], true); + $target_data = $target['target']; if ($target_data['module']) { // Get module name as target if not defined in Grafana. diff --git a/pandora_console/extensions/grafana/search.php b/pandora_console/extensions/grafana/search.php index 48a4f819a9..9193dd290e 100644 --- a/pandora_console/extensions/grafana/search.php +++ b/pandora_console/extensions/grafana/search.php @@ -3,7 +3,7 @@ // Allow Grafana proxy header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); -header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, X-Grafana-Org-Id, X-Grafana-NoCache, X-DS-Authorization'); +header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, X-Grafana-Org-Id, X-Grafana-NoCache, X-DS-Authorization, Authorization'); // Get all request headers $headers = apache_request_headers(); diff --git a/pandora_console/extras/discovery/DiscoveryApplicationsMigrateCodes.ini b/pandora_console/extras/discovery/DiscoveryApplicationsMigrateCodes.ini index c0cee7d03f..d05611a6b5 100644 --- a/pandora_console/extras/discovery/DiscoveryApplicationsMigrateCodes.ini +++ b/pandora_console/extras/discovery/DiscoveryApplicationsMigrateCodes.ini @@ -1,11 +1,11 @@ pandorafms.vmware=248788e0fb2cd4e11623e4a52ee7d05b pandorafms.mysql=fadb4750d18285c0eca34f47c6aa3cfe pandorafms.mssql=1cc215409741d19080269ffba112810e -pandorafms.oracle=2d9320a514d1e48a0b2804e1653c31c6 +pandorafms.oracle=abdfd7280f76276f696115cabdac731e pandorafms.db2=122f2abff0ec1d668c35ee0911483021 pandorafms.sap.deset=9bb72b7f7497a8b543f25cd71f96878f pandorafms.gcp.ce=6743d39452f8e1ad85d0d56a30843973 pandorafms.aws.ec2=07416081f11d92a7d5d9441dabb5c5cb pandorafms.aws.s3=eff053a212ea112e2a37efd9debbe6a0 pandorafms.aws.rds=47d7b02019329e1698f96db4959f9516 -pandorafms.azure.mc=04a1072d1ece8583645ad88204fbeed3 \ No newline at end of file +pandorafms.azure.mc=04a1072d1ece8583645ad88204fbeed3 diff --git a/pandora_console/extras/mr/68.sql b/pandora_console/extras/mr/68.sql new file mode 100644 index 0000000000..254cb2e7c1 --- /dev/null +++ b/pandora_console/extras/mr/68.sql @@ -0,0 +1,14 @@ +START TRANSACTION; + +-- Update version for plugin oracle +UPDATE `tdiscovery_apps` SET `version` = '1.2' WHERE `short_name` = 'pandorafms.oracle'; + +ALTER TABLE `tncm_agent_data` +ADD COLUMN `id_agent_data` int not null default 0 AFTER `script_type`; + +ALTER TABLE `tusuario` CHANGE COLUMN `metaconsole_data_section` `metaconsole_data_section` TEXT NOT NULL DEFAULT '' ; + +ALTER TABLE `tmensajes` ADD COLUMN `icon_notification` VARCHAR(250) NULL DEFAULT NULL AFTER `url`; + + +COMMIT; \ No newline at end of file diff --git a/pandora_console/general/header.php b/pandora_console/general/header.php index 82da1a66dd..5ad89d8d31 100644 --- a/pandora_console/general/header.php +++ b/pandora_console/general/header.php @@ -397,21 +397,23 @@ echo sprintf('
', $menuTypeClass); $modal_box .= ''.__('Join discord community').''; $modal_box .= '
'; - $modal_help = html_print_div( - [ - 'id' => 'modal-help-content', - 'content' => html_print_image( - 'images/help@header.svg', - true, - [ - 'title' => __('Help'), - 'class' => 'main_menu_icon bot invert_filter', - 'alt' => 'user', - ] - ).$modal_box, - ], - true, - ); + if ($config['activate_feedback'] === '1') { + $modal_help = html_print_div( + [ + 'id' => 'modal-help-content', + 'content' => html_print_image( + 'images/help@header.svg', + true, + [ + 'title' => __('Help'), + 'class' => 'main_menu_icon bot invert_filter', + 'alt' => 'user', + ] + ).$modal_box, + ], + true, + ); + } // User. diff --git a/pandora_console/godmode/agentes/agent_manager.php b/pandora_console/godmode/agentes/agent_manager.php index 1af5e3d780..4e62337547 100644 --- a/pandora_console/godmode/agentes/agent_manager.php +++ b/pandora_console/godmode/agentes/agent_manager.php @@ -399,12 +399,12 @@ if ($new_agent === true) { // Ip adress. $tableAgent->data['caption_ip_address'] = __('IP Address'); -$tableAgent->rowclass['ip_address'] = 'w540px'; +$tableAgent->rowclass['ip_address'] = 'w400px'; $tableAgent->data['ip_address'][0] = html_print_input_text('direccion', $direccion_agente, '', 16, 100, true, false, false, '', 'w540px'); +$tableAgent->data['ip_address'][1] = html_print_button(__('Check unique IP'), 'check_unique_ip', false, '', ['class' => 'secondary w130px'], true); +$tableAgent->data['message_check_ip'][0] = html_print_div(['id' => 'message_check_ip'], true); $tableAgent->rowclass['additional_ip_address'] = 'subinput'; -$tableAgent->data['additional_ip_address'][0] = html_print_checkbox_switch('unique_ip', 1, $config['unique_ip'], true); -$tableAgent->data['additional_ip_address'][1] = __('Unique IP'); $tableAgent->cellclass['additional_ip_address'][1] = 'w120px'; $tableAgent->data['additional_ip_address'][2] = html_print_input( [ @@ -1130,17 +1130,12 @@ foreach ($fields as $field) { } if ((bool) $field['is_password_type'] === true) { - $customContent = html_print_input_text_extended( + $customContent = html_print_input_password( 'customvalue_'.$field['id_field'], $custom_value, - 'customvalue_'.$field['id_field'], '', - 30, - 100, - $view_mode, - '', - '', - true, + 45, + 255, true ); } else if ($field['is_link_enabled']) { @@ -1301,6 +1296,7 @@ ui_require_jquery_file('bgiframe'); ?> diff --git a/pandora_console/godmode/agentes/configurar_agente.php b/pandora_console/godmode/agentes/configurar_agente.php index 3da403ef80..c2e3a2f4f6 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -102,7 +102,6 @@ $alias_as_name = 0; $direccion_agente = get_parameter('direccion', ''); $direccion_agente = trim(io_safe_output($direccion_agente)); $direccion_agente = io_safe_input($direccion_agente); -$unique_ip = 0; $intervalo = SECONDS_5MINUTES; $ff_interval = 0; $quiet_module = 0; @@ -186,7 +185,6 @@ if ($create_agent) { $alias = io_safe_input(trim(preg_replace('/[\/\\\|%#&$]/', '', $alias_safe_output))); $alias_as_name = (int) get_parameter_post('alias_as_name', 0); $direccion_agente = (string) get_parameter_post('direccion', ''); - $unique_ip = (int) get_parameter_post('unique_ip', 0); // Safe_output only validate ip. $direccion_agente = trim(io_safe_output($direccion_agente)); @@ -269,12 +267,7 @@ if ($create_agent) { $nombre_agente = $alias; } - if ($unique_ip && $direccion_agente != '') { - $sql = 'SELECT direccion FROM tagente WHERE direccion = "'.$direccion_agente.'"'; - $exists_ip = db_get_row_sql($sql); - } - - if (!$exists_alias && !$exists_ip) { + if (!$exists_alias) { $id_agente = db_process_sql_insert( 'tagente', [ @@ -371,8 +364,6 @@ if ($create_agent) { $agent_creation_error = __('Could not be created'); if ($exists_alias) { $agent_creation_error = __('Could not be created, because name already exists'); - } else if ($exists_ip) { - $agent_creation_error = __('Could not be created, because IP already exists'); } } } @@ -962,7 +953,6 @@ if ($update_agent) { $alias = io_safe_input(trim(preg_replace('/[\/\\\|%#&$]/', '', $alias_safe_output))); $alias_as_name = (int) get_parameter_post('alias_as_name', 0); $direccion_agente = (string) get_parameter_post('direccion', ''); - $unique_ip = (int) get_parameter_post('unique_ip', 0); // Safe_output only validate ip. $direccion_agente = trim(io_safe_output($direccion_agente)); @@ -1097,18 +1087,11 @@ if ($update_agent) { // If there is an agent with the same name, but a different ID. } - if ($direccion_agente !== $address_list && (bool) $unique_ip === true && $direccion_agente != '') { - $sql = 'SELECT direccion FROM tagente WHERE direccion = "'.$direccion_agente.'"'; - $exists_ip = db_get_row_sql($sql); - } - $old_group = agents_get_agent_group($id_agente); if ($grupo <= 0) { ui_print_error_message(__('The group id %d is incorrect.', $grupo)); } else if ($old_group !== $grupo && group_allow_more_agents($grupo, true, 'update') === false) { ui_print_error_message(__('Agent cannot be updated due to the maximum agent limit for this group')); - } else if ($exists_ip) { - ui_print_error_message(__('Duplicate main IP address')); } else { // If different IP is specified than previous, add the IP. if ($direccion_agente != '' diff --git a/pandora_console/godmode/agentes/configure_field.php b/pandora_console/godmode/agentes/configure_field.php index 839040cb00..904b807bbd 100755 --- a/pandora_console/godmode/agentes/configure_field.php +++ b/pandora_console/godmode/agentes/configure_field.php @@ -275,21 +275,27 @@ $(document).ready (function () { $('#configure_field-3').show(); dialog_message("#message_no_set_password"); $('#configure_field-1').hide(); + $('#configure_field-2-0').hide(); } else{ $('#configure_field-3').hide(); $('#configure_field-1').show(); + $('#configure_field-2-0').show(); } }); $('input[type=checkbox][name=is_password_type]').change(function () { if( $('input[type=checkbox][name=is_password_type]').prop('checked')){ + $('#configure_field-1').hide(); dialog_message("#message_no_set_combo"); $('#configure_field-3').hide(); + $('#configure_field-2-1').hide(); } else{ if($('input[type=checkbox][name=is_combo_enable]').prop('checked') === true) { $('#configure_field-3').show(); } + $('#configure_field-1').show(); + $('#configure_field-2-1').show(); } }); }); diff --git a/pandora_console/godmode/agentes/inventory_manager.php b/pandora_console/godmode/agentes/inventory_manager.php index 3f27c3a6b3..d989b7d560 100644 --- a/pandora_console/godmode/agentes/inventory_manager.php +++ b/pandora_console/godmode/agentes/inventory_manager.php @@ -131,9 +131,13 @@ if ($add_inventory_module) { } } -// Load inventory module data for updating +// Load inventory module data for updating. if ($load_inventory_module) { - $sql = 'SELECT * FROM tagent_module_inventory WHERE id_module_inventory = '.$load_inventory_module; + $sql = sprintf( + 'SELECT * FROM tagent_module_inventory WHERE id_module_inventory = %s AND id_agente = %d', + $load_inventory_module, + $id_agente + ); $row = db_get_row_sql($sql); if (!empty($row)) { diff --git a/pandora_console/godmode/agentes/module_manager_editor_common.php b/pandora_console/godmode/agentes/module_manager_editor_common.php index 15620240cd..47c843f2d9 100644 --- a/pandora_console/godmode/agentes/module_manager_editor_common.php +++ b/pandora_console/godmode/agentes/module_manager_editor_common.php @@ -1131,13 +1131,13 @@ if (isset($id_agente) === true && (int) $moduletype === MODULE_DATA) { $tableCron->data['cron_to_select'][0] = html_print_extended_select_for_cron($hour_to, $minute_to, $mday_to, $month_to, $wday_to, true, $disabledBecauseInPolicy, true); } -$table_advanced->rowclass['cron_section'] = 'table_section full_section'; +$table_advanced->rowclass['cron_section'] = 'table_section full_section mrgn_top_mod_0px'; $table_advanced->data['cron_section'] = html_print_table($tableCron, true); $table_advanced->data['title_3'] = html_print_subtitle_table(__('Thresholds and state changes')); $table_advanced->rowclass['caption_min_max_values'] = 'w50p pdd_t_10px'; -$table_advanced->rowclass['min_max_values'] = 'w50p'; +$table_advanced->rowclass['min_max_values'] = 'w50p pdd_b_10px'; $table_advanced->data['caption_min_max_values'][0] = __('Min. Value'); $table_advanced->data['caption_min_max_values'][1] = __('Max. Value'); @@ -1214,7 +1214,7 @@ $tableDynamicThreshold->data['adv_dynamic_threshold_twotailed'][0] = html_print_ $disabledBecauseInPolicy ); -$table_advanced->rowclass['dynamic_threshold_table'] = 'table_section full_section'; +$table_advanced->rowclass['dynamic_threshold_table'] = 'table_section full_section mrgn_top_mod_0px'; $table_advanced->data['dynamic_threshold_table'] = html_print_table($tableDynamicThreshold, true); $tableFFThreshold = new stdClass(); @@ -1304,10 +1304,15 @@ $tableFFThreshold->data['ff_thresholds_each'][2] = html_print_input_text( $classdisabledBecauseInPolicy ); +$table_advanced->rowclass['gap_flipflop'] = 'mrgn_top_btn_10px_imp'; +$table_advanced->data['gap_flipflop'] = html_print_input_hidden('gap_flipflop', 0); -$table_advanced->rowclass['flipflop_thresholds_table'] = 'table_section full_section'; +$table_advanced->rowclass['flipflop_thresholds_table'] = 'table_section full_section mrgn_top_mod_0px'; $table_advanced->data['flipflop_thresholds_table'] = html_print_table($tableFFThreshold, true); +$table_advanced->rowclass['gap_ff'] = 'mrgn_top_btn_10px_imp'; +$table_advanced->data['gap_ff'] = html_print_input_hidden('gap_ff', 0); + $table_advanced->rowclass['caption_ff_interval_timeout'] = 'w50p'; $table_advanced->rowclass['ff_interval_timeout'] = 'w50p'; $table_advanced->cellclass['caption_ff_interval_timeout'][0] = 'w50p'; diff --git a/pandora_console/godmode/alerts/alert_actions.php b/pandora_console/godmode/alerts/alert_actions.php index e8915b05eb..7ba527b61e 100644 --- a/pandora_console/godmode/alerts/alert_actions.php +++ b/pandora_console/godmode/alerts/alert_actions.php @@ -497,7 +497,12 @@ foreach ($actions as $action) { $pagination = ''; if (isset($data)) { html_print_table($table); - $pagination = ui_pagination($total_actions, $url, 0, 0, true, 'offset', false, ''); + $show_count = false; + if (is_metaconsole() === true) { + $show_count = true; + } + + $pagination = ui_pagination($total_actions, $url, 0, 0, true, 'offset', $show_count, ''); } else { ui_print_info_message(['no_close' => true, 'message' => __('No alert actions configured') ]); } diff --git a/pandora_console/godmode/alerts/alert_commands.php b/pandora_console/godmode/alerts/alert_commands.php index a59de7f5e2..a5b4de7c80 100644 --- a/pandora_console/godmode/alerts/alert_commands.php +++ b/pandora_console/godmode/alerts/alert_commands.php @@ -1080,7 +1080,12 @@ foreach ($commands as $command) { if (isset($data) === true && count($table->data) > 0) { html_print_table($table); - $pagination = ui_pagination($total_commands, $url, 0, 0, true, 'offset', false, ''); + $show_count = false; + if (is_metaconsole() === true) { + $show_count = true; + } + + $pagination = ui_pagination($total_commands, $url, 0, 0, true, 'offset', $show_count, ''); } else { ui_print_info_message( [ diff --git a/pandora_console/godmode/alerts/alert_templates.php b/pandora_console/godmode/alerts/alert_templates.php index 8236d1e69c..537c346bac 100644 --- a/pandora_console/godmode/alerts/alert_templates.php +++ b/pandora_console/godmode/alerts/alert_templates.php @@ -493,6 +493,11 @@ foreach ($templates as $template) { $pagination = ''; if (isset($data) === true) { + $show_count = false; + if (is_metaconsole() === true) { + $show_count = true; + } + html_print_table($table); $pagination = ui_pagination( $total_templates, @@ -501,7 +506,7 @@ if (isset($data) === true) { 0, true, 'offset', - false, + $show_count, '' ); } else { diff --git a/pandora_console/godmode/events/event_filter.php b/pandora_console/godmode/events/event_filter.php index c4f1860e6f..a2ed2c72d5 100644 --- a/pandora_console/godmode/events/event_filter.php +++ b/pandora_console/godmode/events/event_filter.php @@ -88,7 +88,17 @@ if ($multiple_delete) { ['id_filter' => $id] ); - if ($result === false) { + if ($result !== false) { + db_process_sql_delete( + 'tfavmenu_user', + [ + 'id_element' => $id, + 'section' => 'Events', + 'id_user' => $config['id_user'], + ] + ); + $result = true; + } else { break; } } @@ -210,7 +220,7 @@ foreach ($filters as $filter) { true, [ 'title' => __('Delete'), - 'class' => 'invert_filter', + 'class' => 'invert_filter main_menu_icon', ] ).''; } diff --git a/pandora_console/godmode/extensions.php b/pandora_console/godmode/extensions.php index 5ec67b09a7..3ff09273c6 100644 --- a/pandora_console/godmode/extensions.php +++ b/pandora_console/godmode/extensions.php @@ -15,7 +15,7 @@ check_login(); global $config; -if (! check_acl($config['id_user'], 0, 'PM')) { +if (users_is_admin($config['id_user']) === false) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to access extensions list' diff --git a/pandora_console/godmode/gis_maps/configure_gis_map.php b/pandora_console/godmode/gis_maps/configure_gis_map.php index cc9ed5d5f0..7a0e4b61e1 100644 --- a/pandora_console/godmode/gis_maps/configure_gis_map.php +++ b/pandora_console/godmode/gis_maps/configure_gis_map.php @@ -68,7 +68,7 @@ foreach ($layer_ids as $layer_id) { $layer_list[] = [ 'id' => (strpos($layer_id, 'new_') === false) ? (int) $layer_id : null, 'layer_name' => $trimmed_name, - 'layer_visible' => ($layers[$layer_id]['visible'] === 'true'), + 'layer_visible' => ($layers[$layer_id]['visible'] == 'true' || $layers[$layer_id]['visible'] === '1'), 'layer_group' => (int) $layers[$layer_id]['agents_from_group'], 'layer_agent_list' => $layers[$layer_id]['agents'], 'layer_group_list' => $layers[$layer_id]['groups'], @@ -562,8 +562,6 @@ $table->data[9][1] = html_print_input_text('map_default_altitude', $map_default_ html_print_table($table); -$user_groups = users_get_groups($config['user'], 'AR', false); - echo '
'.__('Layers').''; $table->width = '100%'; @@ -589,7 +587,7 @@ $table->data[1][0] = ''; echo $reports_table; + $show_count = false; + if (is_metaconsole() === true) { + $show_count = true; + } $tablePagination = ui_pagination( $total_reports, @@ -1267,7 +1271,7 @@ switch ($action) { $pagination, true, 'offset', - false + $show_count ); } else { ui_print_info_message( diff --git a/pandora_console/godmode/servers/modificar_server.php b/pandora_console/godmode/servers/modificar_server.php index c51c0476d3..8a78de9592 100644 --- a/pandora_console/godmode/servers/modificar_server.php +++ b/pandora_console/godmode/servers/modificar_server.php @@ -521,7 +521,7 @@ $(document).ready (function () { function (data) { $(".white-box-content").html(data); - $("#submit-add").click(function (e) { + $("#button-add").click(function (e) { add_credential_boxes(); }); @@ -550,7 +550,7 @@ $(document).ready (function () { $(".white-box-content").html(data2); // Insert credential - $("#submit-add").click(function (e) { + $("#button-add").click(function (e) { save_credential_boxes(); }) }, @@ -609,7 +609,7 @@ $(document).ready (function () { function (data) { $(".white-box-content").html(data); - $("#submit-update").click(function (e) { + $("#button-update").click(function (e) { update_credential_boxes(datas); }); }, diff --git a/pandora_console/godmode/setup/setup_ITSM.php b/pandora_console/godmode/setup/setup_ITSM.php index 012d80f849..313e6763c0 100644 --- a/pandora_console/godmode/setup/setup_ITSM.php +++ b/pandora_console/godmode/setup/setup_ITSM.php @@ -559,7 +559,7 @@ $table_cr_settings->data[4][0] = html_print_label_input_block( // Print. echo '
'; -echo ''; +echo ''; html_print_image( 'images/pandoraITSM_logo.png', false, @@ -570,8 +570,8 @@ echo '
'; echo '
'; echo __('Pandora ITSM'); echo '
'; -echo '
'; -echo 'https://pandorafms.com/es/itsm/'; +echo ''; +echo 'https://pandorafms.com/itsm/'; echo ''; echo '
'; diff --git a/pandora_console/godmode/setup/setup_general.php b/pandora_console/godmode/setup/setup_general.php index bb1617d001..46a91e27c6 100644 --- a/pandora_console/godmode/setup/setup_general.php +++ b/pandora_console/godmode/setup/setup_general.php @@ -527,9 +527,12 @@ $table->data[$i++][] = html_print_label_input_block( true ) ); - +$help_tip = ui_print_help_tip( + __('No events or alerts will be generated, but data will still be received.'), + true +); $table->data[$i][] = html_print_label_input_block( - __('Event storm protection'), + __('Event storm protection').$help_tip, html_print_checkbox_switch( 'event_storm_protection', 1, diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 83e54f24c5..09835fe150 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -424,10 +424,13 @@ if ($create_user === true) { $values['data_section'] = $dashboard; } else if (io_safe_output($values['section']) === HOME_SCREEN_VISUAL_CONSOLE) { $values['data_section'] = $visual_console; - } else if ($values['section'] === HOME_SCREEN_OTHER) { - $values['data_section'] = get_parameter('data_section_other'); - } else if (io_safe_output($values['section']) === HOME_SCREEN_EXTERNAL_LINK) { - $values['data_section'] = get_parameter('data_section_external'); + } else if ($values['section'] === HOME_SCREEN_OTHER || io_safe_output($values['section']) === HOME_SCREEN_EXTERNAL_LINK) { + $values['data_section'] = get_parameter('data_section'); + } + + if (is_metaconsole() === true) { + $values['metaconsole_section'] = $values['section']; + $values['metaconsole_data_section'] = $values['data_section']; } // $values['section'] = $homeScreenValues[$values['section']]; @@ -724,10 +727,8 @@ if ($update_user) { $values['data_section'] = $dashboard; } else if (io_safe_output($values['section']) === HOME_SCREEN_VISUAL_CONSOLE) { $values['data_section'] = $visual_console; - } else if ($values['section'] === HOME_SCREEN_OTHER) { - $values['data_section'] = get_parameter('data_section_other'); - } else if (io_safe_output($values['section']) === HOME_SCREEN_EXTERNAL_LINK) { - $values['data_section'] = get_parameter('data_section_external'); + } else if ($values['section'] === HOME_SCREEN_OTHER || io_safe_output($values['section']) === HOME_SCREEN_EXTERNAL_LINK) { + $values['data_section'] = get_parameter('data_section'); } // $values['section'] = $homeScreenValues[$values['section']]; diff --git a/pandora_console/godmode/users/user_list.php b/pandora_console/godmode/users/user_list.php index d488b4faad..017de9869b 100644 --- a/pandora_console/godmode/users/user_list.php +++ b/pandora_console/godmode/users/user_list.php @@ -689,7 +689,7 @@ foreach ($info as $user_id => $user_info) { // User profiles. if ($user_is_admin || $user_id == $config['id_user'] || isset($group_um[0])) { $user_profiles = db_get_all_rows_sql( - 'SELECT * FROM tusuario_perfil where id_usuario LIKE "'.$user_id.'" LIMIT 5' + 'SELECT * FROM tusuario_perfil where id_usuario LIKE "'.$user_id.'"' ); } else { $user_profiles_aux = users_get_user_profile($user_id, 'LIMIT 5'); @@ -778,17 +778,25 @@ foreach ($info as $user_id => $user_info) { if ($user_profiles !== false) { $total_profile = 0; - $data[4] .= '
'; + $data[4] .= '
'; foreach ($user_profiles as $row) { + $total_profile++; + if ($total_profile > 5) { + $data[4] .= "'; + } + + if ($total_profile == 1 && count($user_profiles) > 5) { + $data[4] .= ''.html_print_image( 'images/zoom.png', true, [ @@ -803,10 +811,6 @@ foreach ($info as $user_id => $user_info) { true ); } - - $data[4] .= '
'; - - $total_profile++; } if (isset($user_info['not_delete']) === true) { @@ -1023,8 +1027,13 @@ foreach ($info as $user_id => $user_info) { array_push($table->data, $data); } +$show_count = false; +if (is_metaconsole() === true) { + $show_count = true; +} + html_print_table($table); -$tablePagination = ui_pagination(count($info), false, 0, 0, true, 'offset', false, 'dataTables_paginate paging_simple_numbers'); +$tablePagination = ui_pagination(count($info), false, 0, 0, true, 'offset', $show_count, 'dataTables_paginate paging_simple_numbers'); unset($table); if ($is_management_allowed === true) { if ($config['admin_can_add_user'] !== false) { @@ -1052,43 +1061,13 @@ if ($is_management_allowed === true) { ?> diff --git a/pandora_console/godmode/users/user_management.php b/pandora_console/godmode/users/user_management.php index b1212c11ec..4fa30a253e 100644 --- a/pandora_console/godmode/users/user_management.php +++ b/pandora_console/godmode/users/user_management.php @@ -84,8 +84,7 @@ $customHomeScreenAddition[HOME_SCREEN_DASHBOARD] = html_print_select( // Home screen. Visual consoles. $customHomeScreenAddition[HOME_SCREEN_VISUAL_CONSOLE] = html_print_select($layouts_aux, 'visual_console', $user_info['data_section'], '', '', '', true, false, true, 'w100p', false, 'width: 100%'); // Home screen. External link and Other. -$customHomeScreenAddition[HOME_SCREEN_EXTERNAL_LINK] = html_print_input_text('data_section_external', $user_info['data_section'], '', 60, 255, true); -$customHomeScreenAddition[HOME_SCREEN_OTHER] = html_print_input_text('data_section_other', $user_info['data_section'], '', 60, 255, true); +$customHomeScreenAddition[HOME_SCREEN_EXTERNAL_LINK] = html_print_input_text('data_section', $user_info['data_section'], '', 60, 400, true); $layouts = visual_map_get_user_layouts($config['id_user'], true); $layouts_aux = []; @@ -118,7 +117,7 @@ $customHomeScreenAddition[HOME_SCREEN_EXTERNAL_LINK] = html_print_input_text( $user_info['data_section'], '', 60, - 255, + 999, true ); $customHomeScreenDataField = ''; @@ -986,7 +985,7 @@ html_print_table($userManagementTable); $vcard_data = []; $vcard_data['version'] = '3.0'; -$vcard_data['firstName'] = $user_info['fullname']; +$vcard_data['firstName'] = io_safe_output($user_info['fullname']); $vcard_data['lastName'] = ''; $vcard_data['middleName'] = ''; $vcard_data['workPhone'] = $user_info['phone']; diff --git a/pandora_console/images/check-white.svg b/pandora_console/images/check-white.svg new file mode 100644 index 0000000000..e7863cf1ba --- /dev/null +++ b/pandora_console/images/check-white.svg @@ -0,0 +1,21 @@ + + + F1630B1D-C694-489C-8C8F-E98AF57D4F04 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/close_dialog.svg b/pandora_console/images/close_dialog.svg new file mode 100644 index 0000000000..79938dacf8 --- /dev/null +++ b/pandora_console/images/close_dialog.svg @@ -0,0 +1,14 @@ + + + F911E81E-C05E-4E17-B88A-07CFEEBD0229 + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/congrats.svg b/pandora_console/images/notification/congrats.svg new file mode 100644 index 0000000000..2f744df78d --- /dev/null +++ b/pandora_console/images/notification/congrats.svg @@ -0,0 +1,21 @@ + + + Icons/Dark/40/Alert icon congrats + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/disable.svg b/pandora_console/images/notification/disable.svg new file mode 100644 index 0000000000..ac34ab01b3 --- /dev/null +++ b/pandora_console/images/notification/disable.svg @@ -0,0 +1,18 @@ + + + Icons/Dark/40/Alert icon disable + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/error.svg b/pandora_console/images/notification/error.svg new file mode 100644 index 0000000000..05b07ebfb9 --- /dev/null +++ b/pandora_console/images/notification/error.svg @@ -0,0 +1,21 @@ + + + Icons/Dark/40/Alert icon error + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/favorite.svg b/pandora_console/images/notification/favorite.svg new file mode 100644 index 0000000000..eff171b67f --- /dev/null +++ b/pandora_console/images/notification/favorite.svg @@ -0,0 +1,21 @@ + + + Icons/Dark/40/Alert icon favorite + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/headsup.svg b/pandora_console/images/notification/headsup.svg new file mode 100644 index 0000000000..57e26bc4d9 --- /dev/null +++ b/pandora_console/images/notification/headsup.svg @@ -0,0 +1,21 @@ + + + Icons/Dark/40/Alert icon heads up + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/information.svg b/pandora_console/images/notification/information.svg new file mode 100644 index 0000000000..11319a4bb5 --- /dev/null +++ b/pandora_console/images/notification/information.svg @@ -0,0 +1,17 @@ + + + Icons/Dark/40/Alert icon information + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/popular.svg b/pandora_console/images/notification/popular.svg new file mode 100644 index 0000000000..20b00a83ad --- /dev/null +++ b/pandora_console/images/notification/popular.svg @@ -0,0 +1,18 @@ + + + Icons/Dark/40/Alert icon popular + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/notification/question.svg b/pandora_console/images/notification/question.svg new file mode 100644 index 0000000000..5694e5d9b2 --- /dev/null +++ b/pandora_console/images/notification/question.svg @@ -0,0 +1,18 @@ + + + Icons/Dark/40/Alert icon question + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/welcome-wizard-image.png b/pandora_console/images/welcome-wizard-image.png new file mode 100644 index 0000000000..aba9647c54 Binary files /dev/null and b/pandora_console/images/welcome-wizard-image.png differ diff --git a/pandora_console/include/ajax/agent.php b/pandora_console/include/ajax/agent.php index 65dcd96aef..b03a9e5b40 100644 --- a/pandora_console/include/ajax/agent.php +++ b/pandora_console/include/ajax/agent.php @@ -39,6 +39,7 @@ $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); +$check_unique_ip = (bool) get_parameter('check_unique_ip', 0); if (https_is_running()) { header('Content-type: application/json'); @@ -1020,4 +1021,29 @@ $(document).ready(function() { return; } +if ($check_unique_ip === true) { + $direccion_agente = (string) get_parameter_post('direccion', ''); + $ip_all = get_parameter_post('ip_all', ''); + + if (empty($direccion_agente) === true) { + echo json_encode(['success' => false, 'message' => __('Please enter an IP address.')]); + return; + } + + $sql = 'SELECT direccion FROM tagente WHERE direccion = "'.$direccion_agente.'"'; + $exists_ip = db_get_row_sql($sql); + + if ($exists_ip !== false) { + if (is_array($ip_all) === true && in_array($direccion_agente, $ip_all) === true) { + echo json_encode(['success' => true, 'message' => __('Success! but this IP is already in the list.')]); + } else { + echo json_encode(['success' => false, 'message' => __('This IP is already being used'), 'exist_ip' => true]); + } + } else { + echo json_encode(['success' => true, 'message' => __('Success! this IP is available to be used.')]); + } + + return; +} + return; diff --git a/pandora_console/include/ajax/dashboard.ajax.php b/pandora_console/include/ajax/dashboard.ajax.php index 50a0e0b7a1..40497a2ebc 100644 --- a/pandora_console/include/ajax/dashboard.ajax.php +++ b/pandora_console/include/ajax/dashboard.ajax.php @@ -41,7 +41,20 @@ if ($method === 'draw') { $length = get_parameter('length', $config['block_size']); $orderBy = get_datatable_order(true); - $sort_field = $orderBy['field']; + switch ($orderBy['field']) { + case 'groups': + $sort_field = 'nombre'; + break; + + case 'favorite': + $sort_field = 'active'; + break; + + default: + $sort_field = $orderBy['field']; + break; + } + $order = $orderBy['direction']; $pagination = ''; @@ -121,7 +134,7 @@ if ($method === 'draw') { ); } - $sql = 'SELECT * FROM tdashboard '.$where.' ORDER BY id '.$pagination; + $sql = 'SELECT * FROM tdashboard LEFT JOIN tgrupo ON tgrupo.id_grupo = tdashboard.id_group '.$where.' ORDER BY '.$sort_field.' '.$order.$pagination; $dashboards = db_get_all_rows_sql($sql); $count = db_get_value_sql('SELECT COUNT(*) FROM tdashboard '.$where); foreach ($dashboards as $dashboard) { diff --git a/pandora_console/include/ajax/events.php b/pandora_console/include/ajax/events.php index 5488622b25..007ba77d89 100644 --- a/pandora_console/include/ajax/events.php +++ b/pandora_console/include/ajax/events.php @@ -98,6 +98,8 @@ $draw_events_graph = get_parameter('drawEventsGraph', false); // User private filter. $current_filter = get_parameter('current_filter', 0); $private_filter_event = get_parameter('private_filter_event', 0); +// Asteroids. +$playAsteroids = (bool) get_parameter('playAsteroids', false); if ($get_comments === true) { global $config; @@ -2763,6 +2765,17 @@ if ($draw_row_response_info === true) { return; } +// Asteroids. +if ($playAsteroids === true) { + echo ui_require_css_file('asteroids', 'include/styles/', true); + echo ui_require_javascript_file('asteroids', 'include/asteroids/', true); + + $output = '
Asteroids game goes here!
'; + + echo $output; + return; +} + if ($update_event_custom_id) { $event_custom_id = get_parameter('event_custom_id'); $event_id = get_parameter('event_id'); @@ -2814,4 +2827,4 @@ if ((bool) $draw_events_graph === true) { $output = event_print_graph($filter); echo $output; return; -} \ No newline at end of file +} diff --git a/pandora_console/include/ajax/graph.ajax.php b/pandora_console/include/ajax/graph.ajax.php index 6ea76f373b..2db3a72912 100644 --- a/pandora_console/include/ajax/graph.ajax.php +++ b/pandora_console/include/ajax/graph.ajax.php @@ -17,6 +17,8 @@ $save_custom_graph = (bool) get_parameter('save_custom_graph'); $print_custom_graph = (bool) get_parameter('print_custom_graph', false); $print_sparse_graph = (bool) get_parameter('print_sparse_graph'); $get_graphs = (bool) get_parameter('get_graphs_container'); +$sort_items = (bool) get_parameter('sort_items'); + $width = get_parameter('width', 0); $height = get_parameter('height', 0); @@ -337,3 +339,104 @@ if ($get_graphs) { return; } } + + +if ($sort_items === true) { + $order = (string) get_parameter('order'); + $id = (string) get_parameter('id', ''); + $idGraph = (string) get_parameter('id_graph', ''); + $total = db_get_num_rows('SELECT * FROM tgraph_source WHERE id_graph = '.$idGraph.''); + $item = db_get_row_sql( + 'SELECT id_gs, field_order + FROM tgraph_source + WHERE id_gs = '.$id.' + ORDER BY field_order' + ); + + switch ($order) { + case 'up': + if (($item['field_order'] - 1) < 1) { + echo json_encode(['success' => false]); + return; + } + + $prevItem = db_get_row_sql( + 'SELECT id_gs, field_order + FROM tgraph_source + WHERE id_graph = '.$idGraph.' + AND field_order = '.($item['field_order'] - 1).' + ORDER BY field_order' + ); + + db_process_sql_begin(); + + $resultItem = db_process_sql_update( + 'tgraph_source', + ['field_order' => ($item['field_order'] - 1)], + ['id_gs' => $item['id_gs']], + false + ); + $resultPrevItem = db_process_sql_update( + 'tgraph_source', + ['field_order' => ($prevItem['field_order'] + 1)], + ['id_gs' => $prevItem['id_gs']], + false + ); + + if ($resultItem !== false && $resultPrevItem !== false) { + db_process_sql_commit(); + echo json_encode(['success' => true]); + return; + } else { + db_process_sql_rollback(); + echo json_encode(['success' => false]); + return; + } + break; + + case 'down': + if (($item['field_order'] + 1) > $total) { + echo json_encode(['success' => false]); + return; + } + + $nextItem = db_get_row_sql( + 'SELECT id_gs, field_order + FROM tgraph_source + WHERE id_graph = '.$idGraph.' + AND field_order = '.($item['field_order'] + 1).' + ORDER BY field_order' + ); + + + db_process_sql_begin(); + + $resultItem = db_process_sql_update( + 'tgraph_source', + ['field_order' => ($item['field_order'] + 1)], + ['id_gs' => $item['id_gs']], + false + ); + $resultNextItem = db_process_sql_update( + 'tgraph_source', + ['field_order' => ($nextItem['field_order'] - 1)], + ['id_gs' => $nextItem['id_gs']], + false + ); + + if ($resultItem !== false && $resultNextItem !== false) { + db_process_sql_commit(); + echo json_encode(['success' => true]); + return; + } else { + db_process_sql_rollback(); + echo json_encode(['success' => false]); + return; + } + break; + + default: + echo json_encode(['success' => false]); + break; + } +} diff --git a/pandora_console/include/asteroids/LICENSE.txt b/pandora_console/include/asteroids/LICENSE.txt new file mode 100644 index 0000000000..0dc661d166 --- /dev/null +++ b/pandora_console/include/asteroids/LICENSE.txt @@ -0,0 +1,25 @@ +Copyright (c) 2023, James Socol +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/pandora_console/include/asteroids/README.rst b/pandora_console/include/asteroids/README.rst new file mode 100644 index 0000000000..c7465358c2 --- /dev/null +++ b/pandora_console/include/asteroids/README.rst @@ -0,0 +1,46 @@ +========= +ASTEROIDS +========= + +Last week, at work, we joked about creating an Asteroids clone where every +asteroid had a bug number in it, as a bit of a joke. (Ha ha, every bug you +kill spawns two more!) + +I was bored this afternoon, so here's a port of Asteroids to JS/Canvas. + +Now all I need to do is hook in the bug numbers. + + +Gameplay +======== + +You're the triangle in the middle. You want to destroy the circles. You have +a gun (spacebar), some thrusters to turn (left and right arrow keys) and an +engine (up arrow key). + +Remember, it's kill or be killed out there. + + +Rights +====== + +The name *Asteroids* is, as far as I know, still property of Atari. I mean no +ill-will towards Atari by releasing this code. Frankly, it's a poor +substitute for anything resembling a real game. I just wanted to see if I +could do it. + +If anyone from Atari asks, I will gladly rename and/or remove this code. But +since there are so many *Asteroids* clones as it is, and the original was +released in 1979, and it was kind of a copy of *Spacewar!*, I doubt they'll +mind too much. + + +Strikes me as funny... +====================== + +The original *Spacewar!*, one of the earliest (if not the original) computer +games, took `200 hours to code `_. + +This probably took me 6. + +I am so glad we've moved past the PDP-1. diff --git a/pandora_console/include/asteroids/asteroids.js b/pandora_console/include/asteroids/asteroids.js new file mode 100644 index 0000000000..d6e9a460f4 --- /dev/null +++ b/pandora_console/include/asteroids/asteroids.js @@ -0,0 +1,840 @@ +// Asteroids.js +// Copyright (c) 2010–2023 James Socol +// See LICENSE.txt for license terms. + +// Game settings +GAME_HEIGHT = 480; +GAME_WIDTH = 640; +FRAME_PERIOD = 60; // 1 frame / x frames/sec +LEVEL_TIMEOUT = 2000; // How long to wait after clearing a level. + +// Player settings +ROTATE_SPEED = Math.PI / 10; // How fast do players turn? (radians) +MAX_SPEED = 15; // Maximum player speed +THRUST_ACCEL = 1; +DEATH_TIMEOUT = 2000; // milliseconds +INVINCIBLE_TIMEOUT = 1500; // How long to stay invincible after resurrecting? +PLAYER_LIVES = 3; +POINTS_PER_SHOT = 1; // How many points does a shot cost? (Should be >= 0.) +POINTS_TO_EXTRA_LIFE = 1000; // How many points to get a 1-up? + +// Bullet settings +BULLET_SPEED = 20; +MAX_BULLETS = 3; +MAX_BULLET_AGE = 25; + +// Asteroid settings +ASTEROID_COUNT = 2; // This + current level = number of asteroids. +ASTEROID_GENERATIONS = 3; // How many times to they split before dying? +ASTEROID_CHILDREN = 2; // How many does each death create? +ASTEROID_SPEED = 3; +ASTEROID_SCORE = 10; // How many points is each one worth? + +var Asteroids = function(home) { + // Constructor + // Order matters. + + // Set up logging. + this.log_level = Asteroids.LOG_DEBUG; + this.log = Asteroids.logger(this); + + // Create the info pane, player, and playfield. + home.innerHTML = ""; + this.info = Asteroids.infoPane(this, home); + this.playfield = Asteroids.playfield(this, home); + this.player = Asteroids.player(this); + + // Set up the event listeners. + this.keyState = Asteroids.keyState(this); + this.listen = Asteroids.listen(this); + + // Useful functions. + this.asteroids = Asteroids.asteroids(this); + this.overlays = Asteroids.overlays(this); + this.highScores = Asteroids.highScores(this); + this.level = Asteroids.level(this); + this.gameOver = Asteroids.gameOver(this); + + // Play the game. + Asteroids.play(this); + return this; +}; + +Asteroids.infoPane = function(game, home) { + var pane = document.createElement("div"); + pane.innerHTML = "ASTEROIDS"; + + var lives = document.createElement("span"); + lives.className = "lives"; + lives.innerHTML = "LIVES: " + PLAYER_LIVES; + + var score = document.createElement("span"); + score.className = "score"; + score.innerHTML = "SCORE: 0"; + + var level = document.createElement("span"); + level.className = "level"; + level.innerHTML = "LEVEL: 1"; + + pane.appendChild(lives); + pane.appendChild(score); + pane.appendChild(level); + home.appendChild(pane); + + return { + setLives: function(game, l) { + lives.innerHTML = "LIVES: " + l; + }, + setScore: function(game, s) { + score.innerHTML = "SCORE: " + s; + }, + setLevel: function(game, _level) { + level.innerHTML = "LEVEL: " + _level; + }, + getPane: function() { + return pane; + } + }; +}; + +Asteroids.playfield = function(game, home) { + var canvas = document.createElement("canvas"); + canvas.width = GAME_WIDTH; + canvas.height = GAME_HEIGHT; + home.appendChild(canvas); + return canvas; +}; + +Asteroids.logger = function(game) { + if (typeof console != "undefined" && typeof console.log != "undefined") { + return { + info: function(msg) { + if (game.log_level <= Asteroids.LOG_INFO) console.log(msg); + }, + debug: function(msg) { + if (game.log_level <= Asteroids.LOG_DEBUG) console.log(msg); + }, + warning: function(msg) { + if (game.log_level <= Asteroids.LOG_WARNING) console.log(msg); + }, + error: function(msg) { + if (game.log_level <= Asteroids.LOG_ERROR) console.log(msg); + }, + critical: function(msg) { + if (game.log_level <= Asteroids.LOG_CRITICAL) console.log(msg); + } + }; + } else { + return { + info: function(msg) {}, + debug: function(msg) {}, + warning: function(msg) {}, + error: function(msg) {}, + critical: function(msg) {} + }; + } +}; + +Asteroids.asteroids = function(game) { + var asteroids = []; + + return { + push: function(obj) { + return asteroids.push(obj); + }, + pop: function() { + return asteroids.pop(); + }, + splice: function(i, j) { + return asteroids.splice(i, j); + }, + get length() { + return asteroids.length; + }, + getIterator: function() { + return asteroids; + }, + generationCount: function(_gen) { + var total = 0; + for (var i = 0; i < asteroids.length; i++) { + if (asteroids[i].getGeneration() == _gen) total++; + } + game.log.debug("Found " + total + " asteroids in generation " + _gen); + return total; + } + }; +}; + +/** + * Creates an overlays controller. + */ +Asteroids.overlays = function(game) { + var overlays = []; + + return { + draw: function(ctx) { + for (var i = 0; i < overlays.length; i++) { + overlays[i].draw(ctx); + } + }, + add: function(obj) { + if (-1 == overlays.indexOf(obj) && typeof obj.draw != "undefined") { + overlays.push(obj); + return true; + } + return false; + }, + remove: function(obj) { + var i = overlays.indexOf(obj); + if (-1 != i) { + overlays.splice(i, 1); + return true; + } + return false; + } + }; +}; + +/** + * Creates a player object. + */ +Asteroids.player = function(game) { + // implements IScreenObject + var position = [GAME_WIDTH / 2, GAME_HEIGHT / 2], + velocity = [0, 0], + direction = -Math.PI / 2, + dead = false, + invincible = false, + lastRez = null, + lives = PLAYER_LIVES, + score = 0, + radius = 3, + path = [ + [10, 0], + [-5, 5], + [-5, -5], + [10, 0] + ]; + + return { + getPosition: function() { + return position; + }, + getVelocity: function() { + return velocity; + }, + getSpeed: function() { + return Math.sqrt(Math.pow(velocity[0], 2) + Math.pow(velocity[1], 2)); + }, + getDirection: function() { + return direction; + }, + getRadius: function() { + return radius; + }, + getScore: function() { + return score; + }, + addScore: function(pts) { + score += pts; + }, + lowerScore: function(pts) { + score -= pts; + if (score < 0) { + score = 0; + } + }, + getLives: function() { + return lives; + }, + rotate: function(rad) { + if (!dead) { + direction += rad; + game.log.info(direction); + } + }, + thrust: function(force) { + if (!dead) { + velocity[0] += force * Math.cos(direction); + velocity[1] += force * Math.sin(direction); + + if (this.getSpeed() > MAX_SPEED) { + velocity[0] = MAX_SPEED * Math.cos(direction); + velocity[1] = MAX_SPEED * Math.sin(direction); + } + + game.log.info(velocity); + } + }, + move: function() { + Asteroids.move(position, velocity); + }, + draw: function(ctx) { + let color = "#fff"; + if (invincible) { + const dt = (new Date() - lastRez) / 200; + const c = Math.floor(Math.cos(dt) * 16).toString(16); + color = `#${c}${c}${c}`; + } + Asteroids.drawPath(ctx, position, direction, 1, path, color); + }, + isDead: function() { + return dead; + }, + isInvincible: function() { + return invincible; + }, + extraLife: function(game) { + game.log.debug("Woo, extra life!"); + lives++; + }, + die: function(game) { + if (!dead) { + game.log.info("You died!"); + dead = true; + invincible = true; + lives--; + position = [GAME_WIDTH / 2, GAME_HEIGHT / 2]; + velocity = [0, 0]; + direction = -Math.PI / 2; + if (lives > 0) { + setTimeout( + (function(player, _game) { + return function() { + player.resurrect(_game); + }; + })(this, game), + DEATH_TIMEOUT + ); + } else { + game.gameOver(); + } + } + }, + resurrect: function(game) { + if (dead) { + dead = false; + invincible = true; + lastRez = new Date(); + setTimeout(function() { + invincible = false; + game.log.debug("No longer invincible!"); + }, INVINCIBLE_TIMEOUT); + game.log.debug("You ressurrected!"); + } + }, + fire: function(game) { + if (!dead) { + game.log.debug("You fired!"); + var _pos = [position[0], position[1]], + _dir = direction; + + this.lowerScore(POINTS_PER_SHOT); + + return Asteroids.bullet(game, _pos, _dir); + } + } + }; +}; + +Asteroids.bullet = function(game, _pos, _dir) { + // implements IScreenObject + var position = [_pos[0], _pos[1]], + velocity = [0, 0], + direction = _dir, + age = 0, + radius = 1, + path = [ + [0, 0], + [-4, 0] + ]; + + velocity[0] = BULLET_SPEED * Math.cos(_dir); + velocity[1] = BULLET_SPEED * Math.sin(_dir); + + return { + getPosition: function() { + return position; + }, + getVelocity: function() { + return velocity; + }, + getSpeed: function() { + return Math.sqrt(Math.pow(velocity[0], 2) + Math.pow(velocity[1], 2)); + }, + getRadius: function() { + return radius; + }, + getAge: function() { + return age; + }, + birthday: function() { + age++; + }, + move: function() { + Asteroids.move(position, velocity); + }, + draw: function(ctx) { + Asteroids.drawPath(ctx, position, direction, 1, path); + } + }; +}; + +Asteroids.keyState = function(_) { + var state = { + [Asteroids.LEFT]: false, + [Asteroids.UP]: false, + [Asteroids.RIGHT]: false, + [Asteroids.DOWN]: false, + [Asteroids.FIRE]: false + }; + + return { + on: function(key) { + state[key] = true; + }, + off: function(key) { + state[key] = false; + }, + getState: function(key) { + if (typeof state[key] != "undefined") return state[key]; + return false; + } + }; +}; + +Asteroids.listen = function(game) { + const keyMap = { + ArrowLeft: Asteroids.LEFT, + KeyA: Asteroids.LEFT, + ArrowRight: Asteroids.RIGHT, + KeyD: Asteroids.RIGHT, + ArrowUp: Asteroids.UP, + KeyW: Asteroids.UP, + Space: Asteroids.FIRE + }; + + window.addEventListener( + "keydown", + function(e) { + const state = keyMap[e.code]; + if (state) { + e.preventDefault(); + e.stopPropagation(); + game.keyState.on(state); + return false; + } + return true; + }, + true + ); + + window.addEventListener( + "keyup", + function(e) { + const state = keyMap[e.code]; + if (state) { + e.preventDefault(); + e.stopPropagation(); + game.keyState.off(state); + return false; + } + return true; + }, + true + ); +}; + +Asteroids.asteroid = function(game, _gen) { + // implements IScreenObject + var position = [0, 0], + velocity = [0, 0], + direction = 0, + generation = _gen, + radius = 7, + path = [ + [1, 7], + [5, 5], + [7, 1], + [5, -3], + [7, -7], + [3, -9], + [-1, -5], + [-4, -2], + [-8, -1], + [-9, 3], + [-5, 5], + [-1, 3], + [1, 7] + ]; + + return { + getPosition: function() { + return position; + }, + setPosition: function(pos) { + position = pos; + }, + getVelocity: function() { + return velocity; + }, + setVelocity: function(vel) { + velocity = vel; + direction = Math.atan2(vel[1], vel[0]); + }, + getSpeed: function() { + return Math.sqrt(Math.pow(velocity[0], 2) + Math.pow(velocity[1], 2)); + }, + getRadius: function() { + return radius * generation; + }, + getGeneration: function() { + return generation; + }, + move: function() { + Asteroids.move(position, velocity); + }, + draw: function(ctx) { + Asteroids.drawPath(ctx, position, direction, generation, path); + // ctx.setTransform(1, 0, 0, 1, position[0], position[1]); + // ctx.beginPath(); + // ctx.arc(0, 0, radius*generation, 0, Math.PI*2, false); + // ctx.stroke(); + // ctx.closePath(); + } + }; +}; + +Asteroids.collision = function(a, b) { + // if a.getPosition() inside b.getBounds? + var a_pos = a.getPosition(), + b_pos = b.getPosition(); + + function sq(x) { + return Math.pow(x, 2); + } + + var distance = Math.sqrt(sq(a_pos[0] - b_pos[0]) + sq(a_pos[1] - b_pos[1])); + + if (distance <= a.getRadius() + b.getRadius()) return true; + return false; +}; + +Asteroids.level = function(game) { + var level = 0, + speed = ASTEROID_SPEED, + hspeed = ASTEROID_SPEED / 2; + + return { + getLevel: function() { + return level; + }, + levelUp: function(game) { + level++; + game.log.debug("Congrats! On to level " + level); + while ( + game.asteroids.generationCount(ASTEROID_GENERATIONS) < + level + ASTEROID_COUNT + ) { + var a = Asteroids.asteroid(game, ASTEROID_GENERATIONS); + a.setPosition([ + Math.random() * GAME_WIDTH, + Math.random() * GAME_HEIGHT + ]); + a.setVelocity([ + Math.random() * speed - hspeed, + Math.random() * speed - hspeed + ]); + game.asteroids.push(a); + } + } + }; +}; + +Asteroids.gameOver = function(game) { + return function() { + game.log.debug("Game over!"); + + if (game.player.getScore() > 0) { + game.highScores.addScore("Player", game.player.getScore()); + } + + game.overlays.add({ + // implements IOverlay + draw: function(ctx) { + ctx.font = "30px System, monospace"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.fillText("GAME OVER", GAME_WIDTH / 2, GAME_HEIGHT / 2); + + var scores = game.highScores.getScores(); + ctx.font = "12px System, monospace"; + for (var i = 0; i < scores.length; i++) { + ctx.fillText( + scores[i].name + " " + scores[i].score, + GAME_WIDTH / 2, + GAME_HEIGHT / 2 + 20 + 14 * i + ); + } + } + }); + }; +}; + +Asteroids.highScores = function(game) { + var scores = []; + + if ((t = localStorage.getItem("high-scores"))) { + scores = JSON.parse(t); + } + + return { + getScores: function() { + return scores; + }, + addScore: function(_name, _score) { + scores.push({ name: _name, score: _score }); + scores.sort(function(a, b) { + return b.score - a.score; + }); + if (scores.length > 10) { + scores.length = 10; + } + game.log.debug("Saving high scores."); + var str = JSON.stringify(scores); + localStorage.setItem("high-scores", str); + } + }; +}; + +Asteroids.drawPath = function(ctx, position, direction, scale, path, color) { + if (!color) { + color = "#fff"; + } + ctx.strokeStyle = color; + ctx.setTransform( + Math.cos(direction) * scale, + Math.sin(direction) * scale, + -Math.sin(direction) * scale, + Math.cos(direction) * scale, + position[0], + position[1] + ); + + ctx.beginPath(); + ctx.moveTo(path[0][0], path[0][1]); + for (i = 1; i < path.length; i++) { + ctx.lineTo(path[i][0], path[i][1]); + } + ctx.stroke(); + ctx.closePath(); + ctx.strokeStyle = "#fff"; +}; + +Asteroids.move = function(position, velocity) { + position[0] += velocity[0]; + if (position[0] < 0) position[0] = GAME_WIDTH + position[0]; + else if (position[0] > GAME_WIDTH) position[0] -= GAME_WIDTH; + + position[1] += velocity[1]; + if (position[1] < 0) position[1] = GAME_HEIGHT + position[1]; + else if (position[1] > GAME_HEIGHT) position[1] -= GAME_HEIGHT; +}; + +Asteroids.stars = function() { + var stars = []; + for (var i = 0; i < 50; i++) { + stars.push([Math.random() * GAME_WIDTH, Math.random() * GAME_HEIGHT]); + } + + return { + draw: function(ctx) { + var ii = stars.length; + for (var i = 0; i < ii; i++) { + ctx.fillRect(stars[i][0], stars[i][1], 1, 1); + } + } + }; +}; + +Asteroids.play = function(game) { + var ctx = game.playfield.getContext("2d"); + ctx.fillStyle = "white"; + ctx.strokeStyle = "white"; + + var speed = ASTEROID_SPEED, + hspeed = ASTEROID_SPEED / 2; + + game.level.levelUp(game); + + var bullets = [], + last_fire_state = false, + last_asteroid_count = 0; + + var extra_lives = 0; + + // Add a star field. + game.overlays.add(Asteroids.stars()); + + game.pulse = setInterval(function() { + var kill_asteroids = [], + new_asteroids = [], + kill_bullets = []; + + ctx.save(); + ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT); + + // Be nice and award extra lives first. + var t_extra_lives = game.player.getScore() / POINTS_TO_EXTRA_LIFE; + t_extra_lives = Math.floor(t_extra_lives); + if (t_extra_lives > extra_lives) { + game.player.extraLife(game); + } + extra_lives = t_extra_lives; + + if (game.keyState.getState(Asteroids.UP)) { + game.player.thrust(THRUST_ACCEL); + } + + if (game.keyState.getState(Asteroids.LEFT)) { + game.player.rotate(-ROTATE_SPEED); + } + + if (game.keyState.getState(Asteroids.RIGHT)) { + game.player.rotate(ROTATE_SPEED); + } + + var fire_state = game.keyState.getState(Asteroids.FIRE); + if ( + fire_state && + fire_state != last_fire_state && + bullets.length < MAX_BULLETS + ) { + var b = game.player.fire(game); + bullets.push(b); + } + last_fire_state = fire_state; + + if (!game.player.isDead()) { + game.player.move(); + game.player.draw(ctx); + } + + for (var k = 0; k < bullets.length; k++) { + if (!bullets[k]) continue; + + if (bullets[k].getAge() > MAX_BULLET_AGE) { + kill_bullets.push(k); + continue; + } + bullets[k].birthday(); + bullets[k].move(); + bullets[k].draw(ctx); + } + + for (var r = kill_bullets.length - 1; r >= 0; r--) { + bullets.splice(r, 1); + } + + var asteroids = game.asteroids.getIterator(); + for (var i = 0; i < game.asteroids.length; i++) { + var killit = false; + asteroids[i].move(); + asteroids[i].draw(ctx); + + // Destroy the asteroid + for (var j = 0; j < bullets.length; j++) { + if (!bullets[j]) continue; + if (Asteroids.collision(bullets[j], asteroids[i])) { + game.log.debug("You shot an asteroid!"); + // Destroy the bullet. + bullets.splice(j, 1); + killit = true; // JS doesn't have "continue 2;" + continue; + } + } + + // Kill the asteroid? + if (killit) { + var _gen = asteroids[i].getGeneration() - 1; + if (_gen > 0) { + // Create children ;) + for (var n = 0; n < ASTEROID_CHILDREN; n++) { + var a = Asteroids.asteroid(game, _gen); + var _pos = [ + asteroids[i].getPosition()[0], + asteroids[i].getPosition()[1] + ]; + a.setPosition(_pos); + a.setVelocity([ + Math.random() * speed - hspeed, + Math.random() * speed - hspeed + ]); + new_asteroids.push(a); + } + } + game.player.addScore(ASTEROID_SCORE); + kill_asteroids.push(i); + continue; + } + + // Kill the player? + if ( + !game.player.isDead() && + !game.player.isInvincible() && + Asteroids.collision(game.player, asteroids[i]) + ) { + game.player.die(game); + } + } + + kill_asteroids.sort(function(a, b) { + return a - b; + }); + for (var m = kill_asteroids.length - 1; m >= 0; m--) { + game.asteroids.splice(kill_asteroids[m], 1); + } + + for (var o = 0; o < new_asteroids.length; o++) { + game.asteroids.push(new_asteroids[o]); + } + + ctx.restore(); + + // Do we need to level up? + if (0 == game.asteroids.length && last_asteroid_count != 0) { + setTimeout(function() { + game.level.levelUp(game); + }, LEVEL_TIMEOUT); + } + + last_asteroid_count = game.asteroids.length; + + // Draw overlays. + game.overlays.draw(ctx); + + // Update the info pane. + game.info.setLives(game, game.player.getLives()); + game.info.setScore(game, game.player.getScore()); + game.info.setLevel(game, game.level.getLevel()); + }, FRAME_PERIOD); +}; + +// Some boring constants. +Asteroids.LOG_ALL = 0; +Asteroids.LOG_INFO = 1; +Asteroids.LOG_DEBUG = 2; +Asteroids.LOG_WARNING = 3; +Asteroids.LOG_ERROR = 4; +Asteroids.LOG_CRITICAL = 5; +Asteroids.LOG_NONE = 6; + +Asteroids.LEFT = 37; +Asteroids.UP = 38; +Asteroids.RIGHT = 39; +Asteroids.DOWN = 40; +Asteroids.FIRE = 32; + +// Load it up! +window.onload = Asteroids(document.getElementById("asteroids")); diff --git a/pandora_console/include/asteroids/index.html b/pandora_console/include/asteroids/index.html new file mode 100644 index 0000000000..3c1dfbd690 --- /dev/null +++ b/pandora_console/include/asteroids/index.html @@ -0,0 +1,14 @@ + + + + + Asteroids + + + + +
Asteroids game goes here!
+ + + + diff --git a/pandora_console/include/asteroids/style.css b/pandora_console/include/asteroids/style.css new file mode 100644 index 0000000000..ab877caa06 --- /dev/null +++ b/pandora_console/include/asteroids/style.css @@ -0,0 +1,46 @@ +/* Style for Asteroids.js + * Copyright (c) 2010 James Socol + * See LICENSE.txt for license. + */ + +body { + background-color: #000; + color: #fff; + font-family: "Calibri", "System", monospace; + font-size: 14px; +} + +div#asteroids { + margin: 50px auto; + width: 640px; + border: 1px solid #fff; + padding: 5px; +} + +div#asteroids > * { + color: #fff; +} + +div#asteroids > div { + font-family: "System", monospace; + font-size: 11px; + padding-bottom: 5px; +} + +div#asteroids > div > span { + float: right; + padding-left: 20px; +} + +div#instructions { + width: 640px; + margin: 20px auto; +} + +h1 { + font-size: 18px; +} + +h2 { + font-size: 16px; +} diff --git a/pandora_console/include/auth/mysql.php b/pandora_console/include/auth/mysql.php index 76a6458f32..3141272352 100644 --- a/pandora_console/include/auth/mysql.php +++ b/pandora_console/include/auth/mysql.php @@ -816,8 +816,6 @@ function update_user(string $id_user, array $values) $values['metaconsole_data_section'] = $values['data_section']; $values['metaconsole_default_event_filter'] = $values['default_event_filter']; unset($values['id_skin']); - unset($values['section']); - unset($values['data_section']); unset($values['default_event_filter']); } } diff --git a/pandora_console/include/class/AuditLog.class.php b/pandora_console/include/class/AuditLog.class.php index 261ffac531..ceb98875a1 100644 --- a/pandora_console/include/class/AuditLog.class.php +++ b/pandora_console/include/class/AuditLog.class.php @@ -123,7 +123,7 @@ class AuditLog extends HTML ], [ 'text' => 'action', - 'class' => 'w80px table_action_buttons show_extended_info', + 'class' => 'w80px show_extended_info', ] ); @@ -187,7 +187,7 @@ class AuditLog extends HTML 'no_sortable_columns' => [-1], 'order' => [ 'field' => 'date', - 'direction' => 'asc', + 'direction' => 'desc', ], 'search_button_class' => 'sub filter float-right', 'form' => [ @@ -441,7 +441,7 @@ class AuditLog extends HTML $(document).ready(function() { // Add event listener for opening and closing details - $('#audit_logs tbody').on('click', 'td.show_extended_info', function() { + $(document).on('click', '#audit_logs tbody tr:has(td.show_extended_info)', function() { var tr = $(this).closest('tr'); var table = $("#tableId; ?>").DataTable(); var row = table.row(tr); diff --git a/pandora_console/include/class/ConsoleSupervisor.php b/pandora_console/include/class/ConsoleSupervisor.php index 92552242f3..9ae7b09921 100644 --- a/pandora_console/include/class/ConsoleSupervisor.php +++ b/pandora_console/include/class/ConsoleSupervisor.php @@ -58,6 +58,18 @@ class ConsoleSupervisor */ public const MIN_SYNC_QUEUE_LENGTH = 200; + /** + * Icons for notifications. + */ + public const ICON_CONGRATS = 'images/notification/congrats.svg'; + public const ICON_DISABLE = 'images/notification/disable.svg'; + public const ICON_ERROR = 'images/notification/error.svg'; + public const ICON_FAVORITE = 'images/notification/favorite.svg'; + public const ICON_HEADSUP = 'images/notification/headsup.svg'; + public const ICON_INFORMATION = 'images/notification/information.svg'; + public const ICON_POPULAR = 'images/notification/popular.svg'; + public const ICON_QUESTION = 'images/notification/question.svg'; + /** * Show if console supervisor is enabled or not. * @@ -289,6 +301,18 @@ class ConsoleSupervisor */ $this->checkLogAlerts(); + + /* + * Check total modules in system + */ + + $this->checkTotalModules(); + + /* + * Check total modules by agent + */ + + $this->checkTotalModulesByAgent(); } @@ -579,8 +603,21 @@ class ConsoleSupervisor * Check MYSQL Support Version * */ + $this->checkMYSQLSettings(); + /* + * Check total modules in system + */ + + $this->checkTotalModules(); + + /* + * Check total modules by agent + */ + + $this->checkTotalModulesByAgent(); + } @@ -666,14 +703,15 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.VARIABLES.PERFORMANCE.'.$variable, - 'title' => __('Incorrect config value'), - 'message' => __( + 'type' => 'NOTIF.VARIABLES.PERFORMANCE.'.$variable, + 'title' => __('Incorrect config value'), + 'message' => __( $message, $names[$variable], $limit_value ), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } @@ -710,12 +748,13 @@ class ConsoleSupervisor db_process_sql_update('tconfig', ['value' => 0], ['token' => 'agentaccess']); $this->notify( [ - 'type' => 'NOTIF.ACCESSSTASTICS.PERFORMANCE', - 'title' => __('Access statistics performance'), - 'message' => __( + 'type' => 'NOTIF.ACCESSSTASTICS.PERFORMANCE', + 'title' => __('Access statistics performance'), + 'message' => __( 'Usage of agent access statistics IS NOT RECOMMENDED on systems with more than 200 agents due performance penalty' ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -928,7 +967,9 @@ class ConsoleSupervisor false ); - if ($prev !== false + if ($data['type'] === 'NOTIF.LOG.ALERT' && $prev !== false) { + return; + } else if ($prev !== false && (time() - $prev['timestamp']) > $max_age ) { // Clean previous notification. @@ -960,6 +1001,9 @@ class ConsoleSupervisor $notification['subject'] = io_safe_input($data['title']); $notification['subtype'] = $data['type']; $notification['url'] = io_safe_input($data['url']); + if (isset($data['icon_notification']) === true) { + $notification['icon_notification'] = $data['icon_notification']; + } $id = db_process_sql_insert('tmensajes', $notification); @@ -1053,13 +1097,14 @@ class ConsoleSupervisor // Warn user if license is going to expire in 15 days or less. $this->notify( [ - 'type' => 'NOTIF.LICENSE.EXPIRATION', - 'title' => $title, - 'message' => __( + 'type' => 'NOTIF.LICENSE.EXPIRATION', + 'title' => $title, + 'message' => __( $msg, $days_to_expiry ), - 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/setup/license', + 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/setup/license', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else if (($days_to_expiry <= 0) && ((is_user_admin($config['id_user'])) || (check_acl($config['id_user'], 0, 'PM')))) { @@ -1074,10 +1119,11 @@ class ConsoleSupervisor // Warn user, license has expired. $this->notify( [ - 'type' => 'NOTIF.LICENSE.EXPIRATION', - 'title' => $title, - 'message' => $msg, - 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/setup/license', + 'type' => 'NOTIF.LICENSE.EXPIRATION', + 'title' => $title, + 'message' => $msg, + 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/setup/license', + 'icon_notification' => self::ICON_HEADSUP, ] ); return false; @@ -1148,13 +1194,14 @@ class ConsoleSupervisor if (is_writable($config['attachment_store']) !== true) { $this->notify( [ - 'type' => 'NOTIF.WRITABLE.ATTACHMENT', - 'title' => __('Attachment directory is not writable'), - 'message' => __( + 'type' => 'NOTIF.WRITABLE.ATTACHMENT', + 'title' => __('Attachment directory is not writable'), + 'message' => __( 'Directory %s is not writable. Please, configure corresponding permissions.', $config['attachment_store'] ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'icon_notification' => self::ICON_ERROR, ] ); return; @@ -1204,13 +1251,14 @@ class ConsoleSupervisor if (is_readable($remote_config_dir) !== true) { $this->notify( [ - 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG', - 'title' => __('Remote configuration directory is not readable'), - 'message' => __( + 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG', + 'title' => __('Remote configuration directory is not readable'), + 'message' => __( 'Remote configuration directory %s is not readable. Please, adjust configuration.', $remote_config_dir ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'icon_notification' => self::ICON_ERROR, ] ); return; @@ -1223,13 +1271,14 @@ class ConsoleSupervisor if (is_writable($remote_config_dir.'/conf') !== true) { $this->notify( [ - 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.CONF', - 'title' => __('Remote configuration directory is not writable'), - 'message' => __( + 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.CONF', + 'title' => __('Remote configuration directory is not writable'), + 'message' => __( 'Remote configuration directory %s is not writable. Please, adjust configuration.', $remote_config_dir.'/conf' ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -1241,13 +1290,14 @@ class ConsoleSupervisor if (is_writable($remote_config_dir.'/collections') !== true) { $this->notify( [ - 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.COLLECTIONS', - 'title' => __('Remote collections directory is not writable'), - 'message' => __( + 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.COLLECTIONS', + 'title' => __('Remote collections directory is not writable'), + 'message' => __( 'Collections directory %s is not writable. Please, adjust configuration.', $remote_config_dir.'/collections' ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -1259,13 +1309,14 @@ class ConsoleSupervisor if (is_writable($remote_config_dir.'/md5') !== true) { $this->notify( [ - 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.MD5', - 'title' => __('Remote md5 directory is not writable'), - 'message' => __( + 'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.MD5', + 'title' => __('Remote md5 directory is not writable'), + 'message' => __( 'MD5 directory %s is not writable. Please, adjust configuration.', $remote_config_dir.'/md5' ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=general', + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -1289,14 +1340,15 @@ class ConsoleSupervisor if ($filecount > $MAX_FILES_DATA_IN) { $this->notify( [ - 'type' => 'NOTIF.FILES.DATAIN', - 'title' => __('There are too much files in spool').'.', - 'message' => __( + 'type' => 'NOTIF.FILES.DATAIN', + 'title' => __('There are too much files in spool').'.', + 'message' => __( 'There are more than %d files in %s. Consider checking DataServer performance', $MAX_FILES_DATA_IN, $remote_config_dir ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1312,14 +1364,15 @@ class ConsoleSupervisor if ($filecount > $MAX_BADXML_FILES_DATA_IN) { $this->notify( [ - 'type' => 'NOTIF.FILES.DATAIN.BADXML', - 'title' => __('There are too many BADXML files in spool'), - 'message' => __( + 'type' => 'NOTIF.FILES.DATAIN.BADXML', + 'title' => __('There are too many BADXML files in spool'), + 'message' => __( 'There are more than %d files in %s. Consider checking software agents.', $MAX_BADXML_FILES_DATA_IN, $remote_config_dir ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1400,18 +1453,19 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SERVER.QUEUE.'.$key, - 'title' => __( + 'type' => 'NOTIF.SERVER.QUEUE.'.$key, + 'title' => __( '%s (%s) is lacking performance.', servers_get_server_string_name($type), $queue['name'] ), - 'message' => __( + 'message' => __( $msg, $modules_queued, $queue['queued_modules'] ), - 'url' => '__url__/index.php?sec=gservers&sec2=godmode/servers/modificar_server&refr=60', + 'url' => '__url__/index.php?sec=gservers&sec2=godmode/servers/modificar_server&refr=60', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1469,10 +1523,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SERVER.STATUS', - 'title' => __('No servers available.'), - 'message' => __('There are no servers registered in this console. Please, check installation guide.'), - 'url' => $url, + 'type' => 'NOTIF.SERVER.STATUS', + 'title' => __('No servers available.'), + 'message' => __('There are no servers registered in this console. Please, check installation guide.'), + 'url' => $url, + 'icon_notification' => self::ICON_ERROR, ] ); } @@ -1513,6 +1568,7 @@ class ConsoleSupervisor } } + $icon_notification = self::ICON_QUESTION; if ($server['status'] == 1) { // Fatal error. Component has die. $msg = __( @@ -1526,6 +1582,8 @@ class ConsoleSupervisor servers_get_server_string_name($server['server_type']), $server['name'] ); + + $icon_notification = self::ICON_ERROR; } else { // Non-fatal error. Controlated exit. Component is not running. $msg = __( @@ -1542,10 +1600,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SERVER.STATUS.'.$server['id_server'], - 'title' => $msg, - 'message' => $description, - 'url' => '__url__/index.php?sec=gservers&sec2=godmode/servers/modificar_server&refr=60', + 'type' => 'NOTIF.SERVER.STATUS.'.$server['id_server'], + 'title' => $msg, + 'message' => $description, + 'url' => '__url__/index.php?sec=gservers&sec2=godmode/servers/modificar_server&refr=60', + 'icon_notification' => $icon_notification, ] ); } @@ -1585,10 +1644,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SERVER.MASTER', - 'title' => __('No master servers found.'), - 'message' => __('At least one server must be defined to run as master. Please, check documentation.'), - 'url' => $url, + 'type' => 'NOTIF.SERVER.MASTER', + 'title' => __('No master servers found.'), + 'message' => __('At least one server must be defined to run as master. Please, check documentation.'), + 'url' => $url, + 'icon_notification' => self::ICON_INFORMATION, ] ); } else { @@ -1641,10 +1701,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PHP.SAFE_MODE', - 'title' => __('PHP safe mode is enabled. Some features may not work properly'), - 'message' => __('To disable it, go to your PHP configuration file (php.ini) and put safe_mode = Off (Do not forget to restart apache process after changes)'), - 'url' => $url, + 'type' => 'NOTIF.PHP.SAFE_MODE', + 'title' => __('PHP safe mode is enabled. Some features may not work properly'), + 'message' => __('To disable it, go to your PHP configuration file (php.ini) and put safe_mode = Off (Do not forget to restart apache process after changes)'), + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1659,16 +1720,17 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PHP.INPUT_TIME', - 'title' => sprintf( + 'type' => 'NOTIF.PHP.INPUT_TIME', + 'title' => sprintf( __('%s value in PHP configuration is not recommended'), 'max_input_time' ), - 'message' => sprintf( + 'message' => sprintf( __('Recommended value is %s'), '-1 ('.__('Unlimited').')' ).'

'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator (Do not forget to restart Apache process after)'), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_INFORMATION, ] ); } else { @@ -1683,16 +1745,17 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PHP.EXECUTION_TIME', - 'title' => sprintf( + 'type' => 'NOTIF.PHP.EXECUTION_TIME', + 'title' => sprintf( __("Not recommended '%s' value in PHP configuration"), 'max_execution_time' ), - 'message' => sprintf( + 'message' => sprintf( __('Recommended value is: %s'), '0 ('.__('Unlimited').')' ).'

'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator (Dont forget restart apache process after changes)'), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_INFORMATION, ] ); } else { @@ -1707,16 +1770,17 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PHP.UPLOAD_MAX_FILESIZE', - 'title' => sprintf( + 'type' => 'NOTIF.PHP.UPLOAD_MAX_FILESIZE', + 'title' => sprintf( __("Not recommended '%s' value in PHP configuration"), 'upload_max_filesize' ), - 'message' => sprintf( + 'message' => sprintf( __('Recommended value is: %s'), sprintf(__('%s or greater'), '800M') ).'

'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator (Dont forget restart apache process after changes)'), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_INFORMATION, ] ); } else { @@ -1736,16 +1800,17 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PHP.MEMORY_LIMIT', - 'title' => sprintf( + 'type' => 'NOTIF.PHP.MEMORY_LIMIT', + 'title' => sprintf( __("Not recommended '%s' value in PHP configuration"), 'memory_limit' ), - 'message' => sprintf( + 'message' => sprintf( __('Recommended value is: %s'), sprintf(__('%s or greater'), $recommended_memory) ).'

'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator'), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_INFORMATION, ] ); } else { @@ -1760,10 +1825,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PHP.DISABLE_FUNCTIONS', - 'title' => __('Problems with disable_functions in php.ini'), - 'message' => __('The variable disable_functions contains functions system() or exec() in PHP configuration file (php.ini)').'

'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator (Dont forget restart apache process after changes)'), - 'url' => $url, + 'type' => 'NOTIF.PHP.DISABLE_FUNCTIONS', + 'title' => __('Problems with disable_functions in php.ini'), + 'message' => __('The variable disable_functions contains functions system() or exec() in PHP configuration file (php.ini)').'

'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator (Dont forget restart apache process after changes)'), + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1777,10 +1843,11 @@ class ConsoleSupervisor // } $this->notify( [ - 'type' => 'NOTIF.PHP.CHROMIUM', - 'title' => __('chromium is not installed'), - 'message' => __('To be able to create images of the graphs for PDFs, please install the chromium extension. For that, it is necessary to follow these steps:'), - 'url' => $url, + 'type' => 'NOTIF.PHP.CHROMIUM', + 'title' => __('chromium is not installed'), + 'message' => __('To be able to create images of the graphs for PDFs, please install the chromium extension. For that, it is necessary to follow these steps:'), + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1838,10 +1905,11 @@ class ConsoleSupervisor $url = 'https://www.php.net/supported-versions.php'; $this->notify( [ - 'type' => 'NOTIF.PHP.VERSION.SUPPORT', - 'title' => __('PHP UPDATE REQUIRED'), - 'message' => __('You should update your PHP version because it will be out of official support').'
'.__('Current PHP version: ').PHP_VERSION, - 'url' => $url, + 'type' => 'NOTIF.PHP.VERSION.SUPPORT', + 'title' => __('PHP UPDATE REQUIRED'), + 'message' => __('You should update your PHP version because it will be out of official support').'
'.__('Current PHP version: ').PHP_VERSION, + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1864,10 +1932,11 @@ class ConsoleSupervisor $url = 'https://www.mysql.com/support/eol-notice.html'; $this->notify( [ - 'type' => 'NOTIF.MYSQL.VERSION', - 'title' => __('MYSQL UPDATE REQUIRED'), - 'message' => __('You should update your MYSQL version because it will be out of official support').'
'.__('Current MYSQL version: ').$mysql_version, - 'url' => $url, + 'type' => 'NOTIF.MYSQL.VERSION', + 'title' => __('MYSQL UPDATE REQUIRED'), + 'message' => __('You should update your MYSQL version because it will be out of official support').'
'.__('Current MYSQL version: ').$mysql_version, + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -1906,10 +1975,11 @@ class ConsoleSupervisor if ($config['history_db_connection'] === false) { $this->notify( [ - 'type' => 'NOTIF.HISTORYDB', - 'title' => __('Historical database not available'), - 'message' => __('Historical database is enabled, though not accessible with the current configuration.'), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=hist_db', + 'type' => 'NOTIF.HISTORYDB', + 'title' => __('Historical database not available'), + 'message' => __('Historical database is enabled, though not accessible with the current configuration.'), + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=hist_db', + 'icon_notification' => self::ICON_QUESTION, ] ); } else { @@ -1950,13 +2020,14 @@ class ConsoleSupervisor if ($last_maintance > 172800) { $this->notify( [ - 'type' => 'NOTIF.PANDORADB', - 'title' => __('Database maintenance problem'), - 'message' => __( + 'type' => 'NOTIF.PANDORADB', + 'title' => __('Database maintenance problem'), + 'message' => __( 'Your database hasn\'t been through maintenance for 48hrs. Please, check documentation on how to perform this maintenance process on %s and enable it as soon as possible.', io_safe_output(get_product_name()) ), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -2011,12 +2082,13 @@ class ConsoleSupervisor if ($last_maintance > 172800) { $this->notify( [ - 'type' => 'NOTIF.PANDORADB.HISTORY', - 'title' => __( + 'type' => 'NOTIF.PANDORADB.HISTORY', + 'title' => __( 'Historical database maintenance problem.' ), - 'message' => __('Your historical database hasn\'t been through maintenance for 48hrs. Please, check documentation on how to perform this maintenance process on %s and enable it as soon as possible.', get_product_name()), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'message' => __('Your historical database hasn\'t been through maintenance for 48hrs. Please, check documentation on how to perform this maintenance process on %s and enable it as soon as possible.', get_product_name()), + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=perf', + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -2052,10 +2124,11 @@ class ConsoleSupervisor if ($mrh_version != $config['MR']) { $this->notify( [ - 'type' => 'NOTIF.HISTORYDB.MR', - 'title' => __('Historical database MR mismatch'), - 'message' => __('Your historical database is not using the same schema as the main DB. This could produce anomalies while storing historical data.'), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=hist_db', + 'type' => 'NOTIF.HISTORYDB.MR', + 'title' => __('Historical database MR mismatch'), + 'message' => __('Your historical database is not using the same schema as the main DB. This could produce anomalies while storing historical data.'), + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=hist_db', + 'icon_notification' => self::ICON_QUESTION, ] ); } else { @@ -2093,10 +2166,11 @@ class ConsoleSupervisor if ($elasticsearch === false) { $this->notify( [ - 'type' => 'NOTIF.EXT.ELASTICSEARCH', - 'title' => __('Log collector cannot connect to OpenSearch'), - 'message' => __('OpenSearch is not available using current configuration.'), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=log', + 'type' => 'NOTIF.EXT.ELASTICSEARCH', + 'title' => __('Log collector cannot connect to OpenSearch'), + 'message' => __('OpenSearch is not available using current configuration.'), + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=log', + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -2163,10 +2237,11 @@ class ConsoleSupervisor } else { $this->notify( [ - 'type' => 'NOTIF.METACONSOLE.DB_CONNECTION', - 'title' => __('Metaconsole DB is not available.'), - 'message' => __('Cannot connect with Metaconsole DB using current configuration.'), - 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=enterprise', + 'type' => 'NOTIF.METACONSOLE.DB_CONNECTION', + 'title' => __('Metaconsole DB is not available.'), + 'message' => __('Cannot connect with Metaconsole DB using current configuration.'), + 'url' => '__url__/index.php?sec=general&sec2=godmode/setup/setup§ion=enterprise', + 'icon_notification' => self::ICON_ERROR, ] ); } @@ -2382,10 +2457,11 @@ class ConsoleSupervisor if (update_manager_verify_registration() === false) { $this->notify( [ - 'type' => 'NOTIF.UPDATEMANAGER.REGISTRATION', - 'title' => __('This instance is not registered in the Warp Update section'), - 'message' => __('Click here to start the registration process'), - 'url' => '__url__/index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online', + 'type' => 'NOTIF.UPDATEMANAGER.REGISTRATION', + 'title' => __('This instance is not registered in the Warp Update section'), + 'message' => __('Click here to start the registration process'), + 'url' => '__url__/index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online', + 'icon_notification' => self::ICON_QUESTION, ] ); } else { @@ -2412,9 +2488,10 @@ class ConsoleSupervisor if (update_manager_verify_api() === false) { $this->notify( [ - 'type' => 'NOTIF.API.ACCESS', - 'title' => __('Cannot access the Pandora FMS API '), - 'message' => __('Please check the configuration, some components may fail due to this misconfiguration in '.$server_name.' ('.$config['public_url'].')'), + 'type' => 'NOTIF.API.ACCESS', + 'title' => __('Cannot access the Pandora FMS API '), + 'message' => __('Please check the configuration, some components may fail due to this misconfiguration in '.$server_name.' ('.$config['public_url'].')'), + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -2445,10 +2522,11 @@ class ConsoleSupervisor if ($admin_with_default_pass > 0) { $this->notify( [ - 'type' => 'NOTIF.SECURITY.DEFAULT_PASSWORD', - 'title' => __('Default password for "Admin" user has not been changed'), - 'message' => __('Please, change the default password since it is a commonly reported vulnerability.'), - 'url' => '__url__/index.php?sec=gusuarios&sec2=godmode/users/user_list', + 'type' => 'NOTIF.SECURITY.DEFAULT_PASSWORD', + 'title' => __('Default password for "Admin" user has not been changed'), + 'message' => __('Please, change the default password since it is a commonly reported vulnerability.'), + 'url' => '__url__/index.php?sec=gusuarios&sec2=godmode/users/user_list', + 'icon_notification' => self::ICON_HEADSUP, ] ); } else { @@ -2560,10 +2638,11 @@ class ConsoleSupervisor foreach ($_SESSION['return_installation_open']['text'] as $message) { $this->notify( [ - 'type' => 'NOTIF.UPDATEMANAGER.OPENSETUP', - 'title' => __('Failed to retrieve updates, please configure utility'), - 'message' => $message, - 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/setup/setup§ion=general', + 'type' => 'NOTIF.UPDATEMANAGER.OPENSETUP', + 'title' => __('Failed to retrieve updates, please configure utility'), + 'message' => $message, + 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/setup/setup§ion=general', + 'icon_notification' => self::ICON_ERROR, ] ); } @@ -2577,13 +2656,14 @@ class ConsoleSupervisor if ($_SESSION['new_update'] == 'new') { $this->notify( [ - 'type' => 'NOTIF.UPDATEMANAGER.UPDATE', - 'title' => __( + 'type' => 'NOTIF.UPDATEMANAGER.UPDATE', + 'title' => __( 'New %s Console update', get_product_name() ), - 'message' => __('There is a new update available. Please go to Administration:Setup:Update Manager for more details.'), - 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=online', + 'message' => __('There is a new update available. Please go to Administration:Setup:Update Manager for more details.'), + 'url' => '__url__/index.php?sec=gsetup&sec2=godmode/update_manager/update_manager&tab=online', + 'icon_notification' => self::ICON_CONGRATS, ] ); } else { @@ -2615,13 +2695,14 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.UPDATEMANAGER.MINOR', - 'title' => __('Minor release/s available'), - 'message' => __( + 'type' => 'NOTIF.UPDATEMANAGER.MINOR', + 'title' => __('Minor release/s available'), + 'message' => __( 'There is one or more minor releases available. .About minor release update.', $url ), - 'url' => '__url__/index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online', + 'url' => '__url__/index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online', + 'icon_notification' => self::ICON_CONGRATS, ] ); } else { @@ -2678,10 +2759,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.CRON.CONFIGURED', - 'title' => __('DiscoveryConsoleTasks is not configured.'), - 'message' => __($message_conf_cron), - 'url' => $url, + 'type' => 'NOTIF.CRON.CONFIGURED', + 'title' => __('DiscoveryConsoleTasks is not configured.'), + 'message' => __($message_conf_cron), + 'url' => $url, + 'icon_notification' => self::ICON_QUESTION, ] ); } else { @@ -2780,10 +2862,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SERVER.MISALIGNED', - 'title' => __($title_ver_misaligned), - 'message' => __($message_ver_misaligned), - 'url' => '__url__/index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online', + 'type' => 'NOTIF.SERVER.MISALIGNED', + 'title' => __($title_ver_misaligned), + 'message' => __($message_ver_misaligned), + 'url' => '__url__/index.php?sec=messages&sec2=godmode/update_manager/update_manager&tab=online', + 'icon_notification' => self::ICON_HEADSUP, ] ); @@ -2836,10 +2919,11 @@ class ConsoleSupervisor $is_none = true; $this->notify( [ - 'type' => 'NOTIF.ALLOWOVERRIDE.MESSAGE', - 'title' => __('AllowOverride is disabled'), - 'message' => __($message), - 'url' => '__url__/index.php', + 'type' => 'NOTIF.ALLOWOVERRIDE.MESSAGE', + 'title' => __('AllowOverride is disabled'), + 'message' => __($message), + 'url' => '__url__/index.php', + 'icon_notification' => self::ICON_HEADSUP, ] ); } @@ -2882,10 +2966,11 @@ class ConsoleSupervisor if ((int) $db_master !== (int) $cluster_master) { $this->notify( [ - 'type' => 'NOTIF.HAMASTER.MESSAGE', - 'title' => __('Desynchronized operation on the node '.$node['host']), - 'message' => __($message), - 'url' => '__url__/index.php?sec=gservers&sec2=enterprise/godmode/servers/HA_cluster', + 'type' => 'NOTIF.HAMASTER.MESSAGE', + 'title' => __('Desynchronized operation on the node '.$node['host']), + 'message' => __($message), + 'url' => '__url__/index.php?sec=gservers&sec2=enterprise/godmode/servers/HA_cluster', + 'icon_notification' => self::ICON_ERROR, ] ); } else { @@ -2922,10 +3007,11 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.PANDORACONSOLE.LOG.OLD', - 'title' => __($title_pandoraconsole_old_log), - 'message' => __($message_pandoraconsole_old_log), - 'url' => $url, + 'type' => 'NOTIF.PANDORACONSOLE.LOG.OLD', + 'title' => __($title_pandoraconsole_old_log), + 'message' => __($message_pandoraconsole_old_log), + 'url' => $url, + 'icon_notification' => self::ICON_QUESTION, ] ); } else { @@ -3006,15 +3092,16 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SYNCQUEUE.LENGTH.'.$node_id, - 'title' => __('Node %s sync queue length exceeded, ', $node->server_name()), - 'message' => __( + 'type' => 'NOTIF.SYNCQUEUE.LENGTH.'.$node_id, + 'title' => __('Node %s sync queue length exceeded, ', $node->server_name()), + 'message' => __( 'Synchronization queue lenght for node %s is %d items, this value should be 0 or lower than %d, please check the queue status.', $node->server_name(), $count, $items_min ), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_HEADSUP, ] ); } catch (\Exception $e) { @@ -3061,14 +3148,15 @@ class ConsoleSupervisor $this->notify( [ - 'type' => 'NOTIF.SYNCQUEUE.STATUS.'.$node_id, - 'title' => __('Node %s sync queue failed, ', $node->server_name()), - 'message' => __( + 'type' => 'NOTIF.SYNCQUEUE.STATUS.'.$node_id, + 'title' => __('Node %s sync queue failed, ', $node->server_name()), + 'message' => __( 'Node %s cannot process synchronization queue due %s, please check the queue status.', $node->server_name(), $item->error() ), - 'url' => $url, + 'url' => $url, + 'icon_notification' => self::ICON_ERROR, ] ); } catch (\Exception $e) { @@ -3094,13 +3182,14 @@ class ConsoleSupervisor if ($error_dependecies > 0) { $this->notify( [ - 'type' => 'NOTIF.AGENT.LIBRARY', - 'title' => __('Agent dependency error'), - 'message' => __( + 'type' => 'NOTIF.AGENT.LIBRARY', + 'title' => __('Agent dependency error'), + 'message' => __( 'There are omnishell agents with dependency errors', ), - 'url' => '__url__/index.php?sec=gextensions&sec2=enterprise/tools/omnishell', + 'url' => '__url__/index.php?sec=gextensions&sec2=enterprise/tools/omnishell', + 'icon_notification' => self::ICON_ERROR, ] ); } @@ -3135,4 +3224,65 @@ class ConsoleSupervisor } + /** + * Check if the total number of modules in Pandora is greater than 80000. + * + * @return void + */ + public function checkTotalModules() + { + $total_modules = db_get_num_rows('select * from tagente_modulo'); + if ($total_modules > 80000) { + $this->notify( + [ + 'type' => 'NOTIF.MODULES.ALERT', + 'title' => __('Your system has a total of %s modules', $total_modules), + 'message' => __('This is higher than the recommended maximum 80,000 modules per node. This may result in poor performance of your system.'), + 'icon_notification' => self::ICON_HEADSUP, + 'url' => '__url__index.php?sec=gagente&sec2=godmode/agentes/modificar_agente', + ] + ); + } else { + $this->cleanNotifications('NOTIF.MODULES.ALERT'); + } + } + + + /** + * Check if the total number of modules by agent is greater than 200 + * + * @return void + */ + public function checkTotalModulesByAgent() + { + $modules_by_agent = db_process_sql( + 'SELECT count(*) AS modules_by_agent + FROM tagente a + LEFT JOIN tagente_modulo m ON a.id_agente = m.id_agente + GROUP BY m.id_agente' + ); + + $show_warning = false; + foreach ($modules_by_agent as $key => $total_modules) { + if ($total_modules['modules_by_agent'] > 200) { + $this->notify( + [ + 'type' => 'NOTIF.MODULES_AGENT.ALERT', + 'title' => __('Your system has an average of %s modules per agent', $total_modules['modules_by_agent']), + 'message' => __('This is higher than the recommended maximum (200). This may result in poor performance of your system.'), + 'icon_notification' => self::ICON_HEADSUP, + 'url' => '__url__index.php?sec=gagente&sec2=godmode/agentes/modificar_agente', + ] + ); + $show_warning = true; + break; + } + } + + if ($show_warning === false) { + $this->cleanNotifications('NOTIF.MODULES_AGENT.ALERT'); + } + } + + } diff --git a/pandora_console/include/class/SatelliteAgent.class.php b/pandora_console/include/class/SatelliteAgent.class.php index 29fa2e3b77..a40b3ecc7a 100644 --- a/pandora_console/include/class/SatelliteAgent.class.php +++ b/pandora_console/include/class/SatelliteAgent.class.php @@ -388,26 +388,40 @@ class SatelliteAgent extends HTML $tmp->actions = ''; if ($delete === false) { - $tmp->actions .= html_print_image( - ($disable === true) ? 'images/lightbulb_off.png' : 'images/lightbulb.png', - true, + $tmp->actions .= html_print_anchor( [ - 'border' => '0', - 'class' => 'main_menu_icon mrgn_lft_05em invert_filter', - 'onclick' => 'disable_agent(\''.$tmp->address.'\',\''.strip_tags($tmp->name).'\',\''.(int) $disable.'\',\''.$id_agente.'\')', - ] + 'href' => '#', + 'content' => html_print_image( + ($disable === true) ? 'images/lightbulb_off.png' : 'images/lightbulb.png', + true, + [ + 'title' => ($disable === true) ? __('Enable') : __('Disable'), + 'border' => '0', + 'class' => 'main_menu_icon mrgn_lft_05em invert_filter', + 'onclick' => 'disable_agent(\''.$tmp->address.'\',\''.strip_tags($tmp->name).'\',\''.(int) $disable.'\',\''.$id_agente.'\')', + ] + ), + ], + true ); } if ($disable === false) { - $tmp->actions .= html_print_image( - ($delete === true) ? 'images/add.png' : 'images/delete.svg', - true, + $tmp->actions .= html_print_anchor( [ - 'border' => '0', - 'class' => 'main_menu_icon mrgn_lft_05em invert_filter', - 'onclick' => 'delete_agent(\''.$tmp->address.'\',\''.strip_tags($tmp->name).'\',\''.(int) $delete.'\',\''.$id_agente.'\')', - ] + 'href' => '#', + 'content' => html_print_image( + ($delete === true) ? 'images/add.png' : 'images/delete.svg', + true, + [ + 'title' => ($delete === true) ? __('Add') : __('Delete'), + 'border' => '0', + 'class' => 'main_menu_icon mrgn_lft_05em invert_filter', + 'onclick' => 'delete_agent(\''.$tmp->address.'\',\''.strip_tags($tmp->name).'\',\''.(int) $delete.'\',\''.$id_agente.'\')', + ] + ), + ], + true ); } diff --git a/pandora_console/include/class/Tree.class.php b/pandora_console/include/class/Tree.class.php index 99b4f5b039..ed515dee87 100644 --- a/pandora_console/include/class/Tree.class.php +++ b/pandora_console/include/class/Tree.class.php @@ -995,6 +995,11 @@ class Tree } } } + + // Quiet name on agent. + if (isset($agent['quiet']) && $agent['quiet']) { + $agent['alias'] .= ' '.__('(Quiet)'); + } } diff --git a/pandora_console/include/class/WebServerModuleDebug.class.php b/pandora_console/include/class/WebServerModuleDebug.class.php index f09d1f3a68..872582e6a3 100644 --- a/pandora_console/include/class/WebServerModuleDebug.class.php +++ b/pandora_console/include/class/WebServerModuleDebug.class.php @@ -265,7 +265,7 @@ class WebServerModuleDebug extends Wizard ); // Set execution timeout. $executionForPerform .= sprintf( - $executionForPerform.' -m %d', + ' -m %d', $this->requestTimeout ); diff --git a/pandora_console/include/class/WelcomeWindow.class.php b/pandora_console/include/class/WelcomeWindow.class.php index 4c72046548..378a194e32 100644 --- a/pandora_console/include/class/WelcomeWindow.class.php +++ b/pandora_console/include/class/WelcomeWindow.class.php @@ -156,11 +156,14 @@ class WelcomeWindow extends Wizard modal: { title: "", cancel: '', - ok: '' + ok: '', + overlay: true, + overlayExtraClass: 'welcome-overlay', }, onshow: { page: 'ajaxController; ?>', method: 'loadWelcomeWindow', + width: 1000, }, oncancel: { page: 'ajaxController; ?>', @@ -178,6 +181,34 @@ class WelcomeWindow extends Wizard } }) } + }, + onload: () => { + $(document).ready(function () { + var buttonpane = $("div[aria-describedby='welcome_modal_window'] .ui-dialog-buttonpane.ui-widget-content.ui-helper-clearfix"); + $(buttonpane).append(` +
+ + +
+ `); + + var closeWizard = $("button.close-wizard-button"); + + $(closeWizard).click(function (e) { + var close = $("div[aria-describedby='welcome_modal_window'] button.sub.ok.submit-next.ui-button"); + var cancel = $("div[aria-describedby='welcome_modal_window'] button.sub.upd.submit-cancel.ui-button"); + var checkbox = $("div[aria-describedby='welcome_modal_window'] .welcome-wizard-do-not-show:checked").length; + + if (checkbox === 1) { + $(cancel).click(); + } else { + $(close).click() + } + }); + }); } }); @@ -412,11 +443,11 @@ class WelcomeWindow extends Wizard $inputs[] = [ 'wrapper' => 'div', 'block_id' => 'div_diagnosis', - 'class' => 'flex-row flex-items-center w98p ', + 'class' => 'flex-row flex-items-center ', 'direct' => 1, 'block_content' => [ [ - 'label' => __('Post-installation status diagnostic'), + 'label' => __('This is your post-installation status diagnostic:'), 'arguments' => [ 'class' => 'first_lbl', 'name' => 'lbl_diagnosis', @@ -434,7 +465,7 @@ class WelcomeWindow extends Wizard 'direct' => 1, 'block_content' => [ [ - 'label' => __('Warp Update registration'), + 'label' => ''.__('Warp Update registration'), 'arguments' => [ 'class' => 'first_lbl', 'name' => 'lbl_update_manager', @@ -443,7 +474,7 @@ class WelcomeWindow extends Wizard ], [ 'arguments' => [ - 'label' => '', + 'label' => __('Cancel'), 'type' => 'button', 'attributes' => [ 'class' => (empty($btn_update_manager_class) === false) ? $btn_update_manager_class : 'invisible_important', @@ -462,7 +493,7 @@ class WelcomeWindow extends Wizard 'direct' => 1, 'block_content' => [ [ - 'label' => __('Default mail to send alerts'), + 'label' => ''.__('Default mail to send alerts'), 'arguments' => [ 'class' => 'first_lbl', 'name' => 'lbl_create_agent', @@ -471,7 +502,7 @@ class WelcomeWindow extends Wizard ], [ 'arguments' => [ - 'label' => '', + 'label' => __('Cancel'), 'type' => 'button', 'attributes' => [ 'class' => (empty($btn_configure_mail_class) === false) ? $btn_configure_mail_class : 'invisible_important', @@ -490,7 +521,7 @@ class WelcomeWindow extends Wizard 'direct' => 1, 'block_content' => [ [ - 'label' => __('All servers running'), + 'label' => ''.__('All servers running'), 'arguments' => [ 'class' => 'first_lbl', 'name' => 'lbl_servers_up', @@ -499,7 +530,7 @@ class WelcomeWindow extends Wizard ], [ 'arguments' => [ - 'label' => '', + 'label' => __('Cancel'), 'type' => 'button', 'attributes' => [ 'class' => (empty($btn_servers_up_class) === false) ? $btn_servers_up_class : 'invisible_important', @@ -518,7 +549,7 @@ class WelcomeWindow extends Wizard 'direct' => 1, 'block_content' => [ [ - 'label' => __('Enterprise licence valid'), + 'label' => ''.__('Enterprise licence valid'), 'arguments' => [ 'class' => 'first_lbl', 'name' => 'lbl_license_valid', @@ -527,7 +558,7 @@ class WelcomeWindow extends Wizard ], [ 'arguments' => [ - 'label' => '', + 'label' => __('Cancel'), 'type' => 'button', 'attributes' => [ 'class' => (empty($btn_license_valid_class) === false) ? $btn_license_valid_class : 'invisible_important', @@ -567,7 +598,7 @@ class WelcomeWindow extends Wizard $inputs[] = [ 'wrapper' => 'div', 'block_id' => 'div_task_todo', - 'class' => 'flex-row flex-items-center w98p', + 'class' => 'flex-row flex-items-center', 'direct' => 1, 'block_content' => [ [ @@ -591,7 +622,7 @@ class WelcomeWindow extends Wizard $inputs[] = [ 'wrapper' => 'div', 'block_id' => 'div_wizard_agent', - 'class' => 'flex space-between w98p', + 'class' => 'flex space-between', 'direct' => 1, 'block_content' => [ [ @@ -599,7 +630,7 @@ class WelcomeWindow extends Wizard 'type' => 'select', 'fields' => $fields, 'name' => 'task_to_perform', - 'selected' => '', + 'selected' => 'check_net', 'return' => true, 'nothing' => \__('Please select one'), 'nothing_value' => '', @@ -630,6 +661,24 @@ class WelcomeWindow extends Wizard $output .= $this->loadJS($flag_task); echo $output; + + echo ' +
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+ +
+ '; ?> '; $output .= '