From 33e1d7aca442f709f71cf4481d181844297cf308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Thu, 16 Jun 2022 16:49:09 +0200 Subject: [PATCH 001/251] DB Changes --- pandora_console/extras/mr/55.sql | 1 + pandora_console/pandoradb.sql | 1 + 2 files changed, 2 insertions(+) diff --git a/pandora_console/extras/mr/55.sql b/pandora_console/extras/mr/55.sql index 747a8da934..c01a4e3c56 100644 --- a/pandora_console/extras/mr/55.sql +++ b/pandora_console/extras/mr/55.sql @@ -37,6 +37,7 @@ ALTER TABLE `tbackup` MODIFY COLUMN `id_user` VARCHAR(255) DEFAULT ''; ALTER TABLE `tservice` ADD COLUMN `enable_sunburst` tinyint(1) NOT NULL default 0; ALTER TABLE `tdashboard` MODIFY `name` TEXT NOT NULL DEFAULT ''; +ALTER TABLE `tusuario` ADD COLUMN `api_token` VARCHAR(255) NOT NULL DEFAULT ''; SET @st_oum763 = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'tautoconfig' AND table_schema = DATABASE() AND column_name = 'disabled') > 0, diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 5550bc5413..3b70462c80 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1304,6 +1304,7 @@ CREATE TABLE IF NOT EXISTS `tusuario` ( `ehorus_user_level_enabled` TINYINT, `integria_user_level_user` VARCHAR(60), `integria_user_level_pass` VARCHAR(45), + `api_token` VARCHAR(255) NOT NULL DEFAULT '', CONSTRAINT `fk_filter_id` FOREIGN KEY (`id_filter`) REFERENCES tevent_filter (`id_filter`) ON DELETE SET NULL, UNIQUE KEY `id_user` (`id_user`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; From b871c1fb553b83c1c82228e8541a623210804222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Fri, 17 Jun 2022 12:13:23 +0200 Subject: [PATCH 002/251] Added token view and generation in user views --- .../godmode/users/configure_user.php | 91 +++++++++++++------ pandora_console/include/functions_api.php | 17 ++++ pandora_console/include/functions_users.php | 58 ++++++++++++ pandora_console/include/javascript/pandora.js | 19 ++++ pandora_console/operation/users/user_edit.php | 22 ++++- 5 files changed, 175 insertions(+), 32 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 67a269bc66..19d2d7ff0c 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -1,19 +1,34 @@ '; +$apiToken = '
'; +$apiToken .= '

'.__('API Token'); +$apiToken .= ui_print_help_tip( + __('The next string is your passphrase for use with the API instead user/password. Click over the string for renew the token.'), + true +).'

'; +$apiToken .= html_print_input_hidden('api_token', $user_info['api_token'], true); +$apiToken .= sprintf( + '%s', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_profile_form', + $user_info['api_token'] +); +$apiToken .= '
'; $user_groups = implode(',', array_keys((users_get_groups($id, 'AR', $display_all_group)))); @@ -1402,7 +1439,7 @@ if (!$id) { $user_id_create = $user_id; } -if (is_metaconsole()) { +if (is_metaconsole() === true) { $access_or_pagination = $meta_access; } else { $access_or_pagination = $size_pagination; @@ -1418,14 +1455,14 @@ if ($id != '' && !$is_err) { echo '
- -

Extra info

'.$email.$phone.$not_login.$local_user.$session_time.'
-
+ +

Extra info

'.$email.$phone.$not_login.$local_user.$session_time.$apiToken.'
+
'.$language.$access_or_pagination.$skin.$home_screen.$default_event_filter.$double_authentication.'
'.$timezone; -if (!is_metaconsole()) { +if (is_metaconsole() === false) { echo '
diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index d2c4f11823..2e7feb5e4c 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -17707,3 +17707,20 @@ function api_set_enable_disable_discovery_task($id_task, $thrash2, $other) } } } + + +/** + * Check if token is correct. + * + * @param string $token Token for check. + * + * @return integer Id of user. If returns 0 there is not valid token. + */ +function api_token_check(string $token) +{ + if (empty($token) === true) { + return 0; + } else { + return (int) db_get_value('id_user', 'tusuario', 'api_token', $token); + } +} diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index f4e6e25be8..808e98d5dd 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -877,3 +877,61 @@ function users_get_users_group_by_group($id_group) return $users; } + + +/** + * Generates a cryptographically secure chain for use with API. + * + * @return string + */ +function api_token_generate() +{ + // Generate a cryptographically secure chain. + $generateToken = bin2hex(openssl_random_pseudo_bytes(16)); + // Check if token exists in DB. + $tokenExists = (bool) api_token_check($generateToken); + // If not exists, can be assigned. In other case, try again. + return ($tokenExists === false) ? $generateToken : api_token_generate(); +} + + +/** + * Returns User API Token + * + * @param integer $idUser Id of the user. + * + * @return string + */ +function users_get_API_token(int $idUser) +{ + $apiToken = db_get_value('api_token', 'tusuario', 'id_user', $idUser); + + return $apiToken; +} + + +/** + * Renews the API Token. + * + * @param integer $idUser Id of the user. + * + * @return boolean Return true if the token was renewed. + */ +function users_renew_API_token(int $idUser) +{ + $apiToken = api_token_generate(); + + if (empty($apiToken) === false) { + $result = db_process_sql_update( + 'tusuario', + ['api_token' => $apiToken], + ['id_user' => $idUser] + ); + + if ($result !== false) { + return true; + } + } + + return false; +} diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index eb8118a911..b12745afdf 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -2057,3 +2057,22 @@ $.fn.filterByText = function(textbox) { }); }); }; + +/** + * Confirm Dialog for API token renewal request. + * + * @param {string} title Title for show. + * @param {string} message Message for show. + * @param {string} form Form to attach renewAPIToken element. + */ +function renewAPIToken(title, message, form) { + confirmDialog({ + title: title, + message: message, + onAccept: function() { + $("#" + form) + .append("") + .submit(); + } + }); +} diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index f76fbfff31..443e9dab82 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -80,6 +80,7 @@ if (isset($_GET['modified']) && !$view_mode) { $upd_info['id_skin'] = get_parameter('skin', $user_info['id_skin']); $upd_info['default_event_filter'] = get_parameter('event_filter', null); $upd_info['block_size'] = get_parameter('block_size', $config['block_size']); + $upd_info['api_token'] = ((bool) get_parameter('renewAPIToken') === true) ? api_token_generate() : (string) get_parameter('api_token'); $default_block_size = get_parameter('default_block_size', 0); if ($default_block_size) { @@ -111,14 +112,14 @@ if (isset($_GET['modified']) && !$view_mode) { $section = io_safe_output($upd_info['section']); - if (($section == 'Event list') || ($section == 'Group view') - || ($section == 'Alert detail') || ($section == 'Tactical view') - || ($section == 'Default') + if (($section === 'Event list') || ($section === 'Group view') + || ($section === 'Alert detail') || ($section === 'Tactical view') + || ($section === 'Default') ) { $upd_info['data_section'] = ''; - } else if ($section == 'Dashboard') { + } else if ($section === 'Dashboard') { $upd_info['data_section'] = $dashboard; - } else if ($section == 'Visual console') { + } else if ($section === 'Visual console') { $upd_info['data_section'] = $visual_console; } @@ -258,6 +259,17 @@ if (is_metaconsole() === false && is_management_allowed() === false) { $user_id = '

'.__('User ID').':

'; $user_id .= ''.$id.'
'; +$user_id .= '

'.__('API Token').':

'; +$user_id .= html_print_input_hidden('api_token', $user_info['api_token'], true); +$user_id .= sprintf( + '%s', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_mod', + $user_info['api_token'] +); +$user_id .= '
'; + $full_name = '
'.html_print_input_text_extended( 'fullname', $user_info['fullname'], From 8d05accb7b9b104ab9f604d1b4456d4e59a46969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Fri, 17 Jun 2022 12:30:59 +0200 Subject: [PATCH 003/251] Improve changes --- pandora_console/godmode/users/configure_user.php | 9 +++++---- pandora_console/operation/users/user_edit.php | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 19d2d7ff0c..cdeb218fa8 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -28,7 +28,7 @@ // Begin. global $config; -hd($_REQUEST); + check_login(); require_once $config['homedir'].'/vendor/autoload.php'; @@ -1289,16 +1289,17 @@ $session_time .= html_print_input_text( $apiToken = '
'; $apiToken .= '

'.__('API Token'); $apiToken .= ui_print_help_tip( - __('The next string is your passphrase for use with the API instead user/password. Click over the string for renew the token.'), + __('The next string is your passphrase for use with the API instead user/password.'), true ).'

'; $apiToken .= html_print_input_hidden('api_token', $user_info['api_token'], true); +$apiToken .= ''.$user_info['api_token'].'   '; $apiToken .= sprintf( - '%s', + '%s', __('Warning'), __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), 'user_profile_form', - $user_info['api_token'] + __('Renew') ); $apiToken .= '
'; diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index 443e9dab82..bc589bc763 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -262,12 +262,13 @@ $user_id .= ''.$id.'
'; $user_id .= '

'.__('API Token').':

'; $user_id .= html_print_input_hidden('api_token', $user_info['api_token'], true); $user_id .= sprintf( - '%s', + '%s', __('Warning'), __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), - 'user_mod', - $user_info['api_token'] + 'user_profile_form', + __('Renew') ); +$user_id .= '
'.$user_info['api_token'].''; $user_id .= '
'; $full_name = '
'.html_print_input_text_extended( From cdf5485aee3eb097479926a98a9b94eba528b4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Mon, 27 Jun 2022 18:06:51 +0200 Subject: [PATCH 004/251] Updated api checker extension --- pandora_console/extensions/api_checker.php | 128 ++++++++++++++++----- 1 file changed, 98 insertions(+), 30 deletions(-) diff --git a/pandora_console/extensions/api_checker.php b/pandora_console/extensions/api_checker.php index b4af7c77ee..ed2053036e 100755 --- a/pandora_console/extensions/api_checker.php +++ b/pandora_console/extensions/api_checker.php @@ -1,43 +1,101 @@ $url, 'result' => $result, ]; - - return $return; } +/** + * Perform API Checker + * + * @return void. + */ function extension_api_checker() { global $config; check_login(); - if (! check_acl($config['id_user'], 0, 'PM')) { + if ((bool) check_acl($config['id_user'], 0, 'PM') === false) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to access Profile Management' @@ -85,11 +146,12 @@ function extension_api_checker() $return_type = io_safe_output(get_parameter('return_type', '')); $other = io_safe_output(get_parameter('other', '')); $other_mode = io_safe_output(get_parameter('other_mode', 'url_encode_separator_|')); + $token = get_parameter('token'); - $api_execute = get_parameter('api_execute', 0); + $api_execute = (bool) get_parameter('api_execute', false); $return_call_api = ''; - if ($api_execute) { + if ($api_execute === true) { $return_call_api = api_execute( $url, $ip, @@ -103,7 +165,8 @@ function extension_api_checker() urlencode($id2), $return_type, urlencode($other), - $other_mode + $other_mode, + $token ); } @@ -182,6 +245,11 @@ function extension_api_checker() $row[] = html_print_input_text('other_mode', $other_mode, '', 50, 255, true); $table2->data[] = $row; + $row = []; + $row[] = __('API Token'); + $row[] = html_print_input_text('token', $token, '', 50, 255, true); + $table2->data[] = $row; + $table3 = new stdClass(); $table3->data = []; @@ -214,7 +282,7 @@ function extension_api_checker() echo '
'; echo ''; - if ($api_execute) { + if ($api_execute === true) { echo '
'; echo ''.__('Result').''; echo __('URL').'
'; From 23f163ed2ac186c6611e42ee8b040f00c73ba9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Tue, 28 Jun 2022 17:21:18 +0200 Subject: [PATCH 005/251] Fix api checker --- pandora_console/extensions/api_checker.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandora_console/extensions/api_checker.php b/pandora_console/extensions/api_checker.php index ed2053036e..e301f5029f 100755 --- a/pandora_console/extensions/api_checker.php +++ b/pandora_console/extensions/api_checker.php @@ -192,6 +192,11 @@ function extension_api_checker() $row[] = html_print_input_text('pandora_url', $pandora_url, '', 50, 255, true); $table->data[] = $row; + $row = []; + $row[] = __('API Token').ui_print_help_tip(__('Use API Token instead API Pass, User and Password.'), true); + $row[] = html_print_input_text('token', $token, '', 50, 255, true); + $table->data[] = $row; + $row = []; $row[] = __('API Pass'); $row[] = html_print_input_password('apipass', $apipass, '', 50, 255, true); @@ -245,11 +250,6 @@ function extension_api_checker() $row[] = html_print_input_text('other_mode', $other_mode, '', 50, 255, true); $table2->data[] = $row; - $row = []; - $row[] = __('API Token'); - $row[] = html_print_input_text('token', $token, '', 50, 255, true); - $table2->data[] = $row; - $table3 = new stdClass(); $table3->data = []; From b175ffbd3ae2cd7255bd95c50ed24dbe3dd73ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Tue, 28 Jun 2022 17:22:09 +0200 Subject: [PATCH 006/251] Fixed db change --- pandora_console/pandoradb_data.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index 8f60368737..dcae30f15c 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -341,8 +341,8 @@ INSERT INTO `tmodule_inventory` (`id_module_inventory`, `id_os`, `name`, `descri -- -- Dumping data for table `tusuario` -- -INSERT INTO `tusuario` (`id_user`, `fullname`, `firstname`, `lastname`, `middlename`, `password`, `comments`, `last_connect`, `registered`, `email`, `phone`, `is_admin`, `language`, `block_size`, `section`, `data_section`, `metaconsole_access`) VALUES -('admin', 'Pandora', 'Pandora', 'Admin', '', '1da7ee7d45b96d0e1f45ee4ee23da560', 'Admin Pandora', 1232642121, 0, 'admin@example.com', '555-555-5555', 1, 'default', 0, 'Default', '', 'advanced'); +INSERT INTO `tusuario` (`id_user`, `fullname`, `firstname`, `lastname`, `middlename`, `password`, `comments`, `last_connect`, `registered`, `email`, `phone`, `is_admin`, `language`, `block_size`, `section`, `data_section`, `metaconsole_access`, `api_token`) VALUES +('admin', 'Pandora', 'Pandora', 'Admin', '', '1da7ee7d45b96d0e1f45ee4ee23da560', 'Admin Pandora', 1232642121, 0, 'admin@example.com', '555-555-5555', 1, 'default', 0, 'Default', '', 'advanced', 'pandora1234'); -- -- Dumping data for table `tusuario_perfil` From ded27ce411c22468448496ff6868b124773860cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Tue, 28 Jun 2022 17:24:22 +0200 Subject: [PATCH 007/251] Backend changes --- pandora_console/include/api.php | 30 ++++--- pandora_console/include/auth/mysql.php | 98 ++++++--------------- pandora_console/include/functions_api.php | 6 +- pandora_console/include/functions_users.php | 9 +- 4 files changed, 54 insertions(+), 89 deletions(-) diff --git a/pandora_console/include/api.php b/pandora_console/include/api.php index cb3dae8e72..c9672816a8 100644 --- a/pandora_console/include/api.php +++ b/pandora_console/include/api.php @@ -14,7 +14,7 @@ * |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______| * * ============================================================================ - * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas + * Copyright (c) 2005-2022 Artica Soluciones Tecnologicas * Please see http://pandorafms.org for full contribution list * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -74,6 +74,7 @@ $password = get_parameter('pass', ''); $user = get_parameter('user', ''); $info = get_parameter('info', ''); $raw_decode = (bool) get_parameter('raw_decode', false); +$apiToken = (string) get_parameter('token'); $other = parseOtherParameter($otherSerialize, $otherMode, $raw_decode); $apiPassword = io_output_password( @@ -84,6 +85,7 @@ $apiPassword = io_output_password( ) ); +$apiTokenValid = (isset($_GET['token']) === true && (bool) api_token_check($apiToken)); $correctLogin = false; $no_login_msg = ''; @@ -94,8 +96,8 @@ ob_clean(); // Special call without checks to retrieve version and build of the Pandora FMS // This info is avalable from the web console without login // Don't change the format, it is parsed by applications. -if ($info == 'version') { - if (!$config['MR']) { +if ($info === 'version') { + if ((bool) $config['MR'] === false) { $config['MR'] = 0; } @@ -105,6 +107,7 @@ if ($info == 'version') { if (empty($apiPassword) === true || (empty($apiPassword) === false && $api_password === $apiPassword) + || $apiTokenValid === true ) { if (enterprise_hook('metaconsole_validate_origin', [get_parameter('server_auth')]) === true || enterprise_hook('console_validate_origin', [get_parameter('server_auth')]) === true @@ -118,7 +121,14 @@ if (empty($apiPassword) === true $correctLogin = true; } else if ((bool) isInACL($ipOrigin) === true) { // External access. - $user_in_db = process_user_login($user, $password, true); + // Token is valid. Bypass the credentials. + if ($apiTokenValid === true) { + $credentials = db_get_row('tusuario', 'api_token', $apiToken); + $user = $credentials['id_user']; + $password = $credentials['password']; + } + + $user_in_db = process_user_login($user, $password, true, $apiTokenValid); if ($user_in_db !== false) { $config['id_usuario'] = $user_in_db; // Compat. @@ -144,19 +154,19 @@ if (empty($apiPassword) === true $no_login_msg = 'Incorrect given API password'; } -if ($correctLogin) { +if ($correctLogin === true) { if (($op !== 'get') && ($op !== 'set') && ($op !== 'help')) { returnError('no_set_no_get_no_help', $returnType); } else { $function_name = ''; // Check if is an extension function and get the function name. - if ($op2 == 'extension') { + if ($op2 === 'extension') { $extension_api_url = $config['homedir'].'/'.EXTENSIONS_DIR.'/'.$ext_name.'/'.$ext_name.'.api.php'; // The extension API file must exist and the extension must be // enabled. - if (file_exists($extension_api_url) - && !in_array($ext_name, extensions_get_disabled_extensions()) + if (file_exists($extension_api_url) === true + && in_array($ext_name, extensions_get_disabled_extensions()) === false ) { include_once $extension_api_url; $function_name = 'apiextension_'.$op.'_'.$ext_function; @@ -164,7 +174,7 @@ if ($correctLogin) { } else { $function_name = 'api_'.$op.'_'.$op2; - if ($op == 'set' && $id) { + if ($op === 'set' && $id) { switch ($op2) { case 'update_agent': case 'add_module_in_conf': @@ -173,7 +183,7 @@ if ($correctLogin) { $agent = agents_locate_agent($id); if ($agent !== false) { $id_os = $agent['id_os']; - if ($id_os == 100) { + if ((int) $id_os === 100) { returnError( 'not_allowed_operation_cluster', $returnType diff --git a/pandora_console/include/auth/mysql.php b/pandora_console/include/auth/mysql.php index 67053ab0be..48e0145c4a 100644 --- a/pandora_console/include/auth/mysql.php +++ b/pandora_console/include/auth/mysql.php @@ -78,7 +78,7 @@ $config['admin_can_make_admin'] = true; * @return mixed False in case of error or invalid credentials, the username in * case it's correct. */ -function process_user_login($login, $pass, $api=false) +function process_user_login($login, $pass, $api=false, $passAlreadyEncrypted=false) { global $config; @@ -114,10 +114,10 @@ function process_user_login($login, $pass, $api=false) if ($config['fallback_local_auth'] || is_user_admin($login) || $local_user === true - || strtolower($config['auth']) == 'mysql' + || strtolower($config['auth']) === 'mysql' || (bool) $user_not_login === true ) { - return process_user_login_local($login, $pass, $api); + return process_user_login_local($login, $pass, $api, $passAlreadyEncrypted); } else { return false; } @@ -128,88 +128,44 @@ function process_user_login($login, $pass, $api=false) } -function process_user_login_local($login, $pass, $api=false) +function process_user_login_local($login, $pass, $api=false, $passAlreadyEncrypted=false) { global $config, $mysql_cache; - // Connect to Database - switch ($config['dbtype']) { - case 'mysql': - if (!$api) { - $sql = sprintf( - "SELECT `id_user`, `password` - FROM `tusuario` - WHERE `id_user` = '%s' AND `not_login` = 0 - AND `disabled` = 0", - $login - ); - } else { - $sql = sprintf( - "SELECT `id_user`, `password` - FROM `tusuario` - WHERE `id_user` = '%s' - AND `disabled` = 0", - $login - ); - } - break; - - case 'postgresql': - if (!$api) { - $sql = sprintf( - 'SELECT "id_user", "password" - FROM "tusuario" - WHERE "id_user" = \'%s\' AND "not_login" = 0 - AND "disabled" = 0', - $login - ); - } else { - $sql = sprintf( - 'SELECT "id_user", "password" - FROM "tusuario" - WHERE "id_user" = \'%s\' - AND "disabled" = 0', - $login - ); - } - break; - - case 'oracle': - if (!$api) { - $sql = sprintf( - 'SELECT id_user, password - FROM tusuario - WHERE id_user = \'%s\' AND not_login = 0 - AND disabled = 0', - $login - ); - } else { - $sql = sprintf( - 'SELECT id_user, password - FROM tusuario - WHERE id_user = \'%s\' - AND disabled = 0', - $login - ); - } - break; + if ($api === false) { + $sql = sprintf( + "SELECT `id_user`, `password` + FROM `tusuario` + WHERE `id_user` = '%s' AND `not_login` = 0 + AND `disabled` = 0", + $login + ); + } else { + $sql = sprintf( + "SELECT `id_user`, `password` + FROM `tusuario` + WHERE `id_user` = '%s' + AND `disabled` = 0", + $login + ); } $row = db_get_row_sql($sql); - // Check that row exists, that password is not empty and that password is the same hash - if ($row !== false && $row['password'] !== md5('') - && $row['password'] == md5($pass) + // Check that row exists, that password is not empty and that password is the same hash. + if (($row !== false && $row['password'] !== md5('') + && (string) $row['password'] === md5($pass)) + || ($passAlreadyEncrypted === true && (string) $row['password'] === (string) $pass) ) { // Login OK // Nick could be uppercase or lowercase (select in MySQL // is not case sensitive) // We get DB nick to put in PHP Session variable, // to avoid problems with case-sensitive usernames. - // Thanks to David Muñiz for Bug discovery :) + // Thanks to David Muñiz for Bug discovery :). $filter = ['id_usuario' => $login]; $user_profile = db_get_row_filter('tusuario_perfil', $filter); - if (!users_is_admin($login) && !$user_profile) { + if ((bool) users_is_admin($login) === false && (bool) $user_profile === false) { $mysql_cache['auth_error'] = 'User does not have any profile'; $config['auth_error'] = 'User does not have any profile'; return false; @@ -217,7 +173,7 @@ function process_user_login_local($login, $pass, $api=false) return $row['id_user']; } else { - if (!user_can_login($login)) { + if (user_can_login($login) === false) { $mysql_cache['auth_error'] = 'User only can use the API.'; $config['auth_error'] = 'User only can use the API.'; } else { diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index 2e7feb5e4c..29aafad983 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -17714,13 +17714,13 @@ function api_set_enable_disable_discovery_task($id_task, $thrash2, $other) * * @param string $token Token for check. * - * @return integer Id of user. If returns 0 there is not valid token. + * @return mixed Id of user. If returns 0 there is not valid token. */ function api_token_check(string $token) { if (empty($token) === true) { - return 0; + return -1; } else { - return (int) db_get_value('id_user', 'tusuario', 'api_token', $token); + return db_get_value('id_user', 'tusuario', 'api_token', $token); } } diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index 808e98d5dd..00a18afda5 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -886,6 +886,7 @@ function users_get_users_group_by_group($id_group) */ function api_token_generate() { + include_once 'functions_api.php'; // Generate a cryptographically secure chain. $generateToken = bin2hex(openssl_random_pseudo_bytes(16)); // Check if token exists in DB. @@ -898,15 +899,13 @@ function api_token_generate() /** * Returns User API Token * - * @param integer $idUser Id of the user. + * @param string $idUser Id of the user. * * @return string */ -function users_get_API_token(int $idUser) +function users_get_API_token(string $idUser) { - $apiToken = db_get_value('api_token', 'tusuario', 'id_user', $idUser); - - return $apiToken; + return db_get_value('api_token', 'tusuario', 'id_user', $idUser); } From c3dc1d820d454a1323aef8d5cdc9e8359efa3a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Tue, 28 Jun 2022 17:24:49 +0200 Subject: [PATCH 008/251] Frontend changes --- .../godmode/users/configure_user.php | 191 ++++++++++-------- pandora_console/include/javascript/pandora.js | 14 ++ pandora_console/include/styles/pandora.css | 8 + pandora_console/operation/users/user_edit.php | 81 +++++--- 4 files changed, 190 insertions(+), 104 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index cdeb218fa8..031e87635a 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -44,10 +44,7 @@ require_once $config['homedir'].'/include/functions_visual_map.php'; require_once $config['homedir'].'/include/functions_custom_fields.php'; enterprise_include_once('include/functions_profile.php'); -$meta = false; -if (enterprise_installed() && defined('METACONSOLE')) { - $meta = true; -} +$meta = is_metaconsole(); $isFunctionSkins = enterprise_include_once('include/functions_skins.php'); @@ -57,11 +54,10 @@ if (ENTERPRISE_NOT_HOOK !== enterprise_include('include/functions_policies.php') $enterprise_include = true; } -if ($enterprise_include) { +if ($enterprise_include === true) { enterprise_include_once('meta/include/functions_users_meta.php'); } - if (is_metaconsole() === false) { date_default_timezone_set('UTC'); include 'include/javascript/timezonepicker/includes/parser.inc'; @@ -112,13 +108,13 @@ if (is_metaconsole() === false) { // This defines the working user. Beware with this, old code get confusses // and operates with current logged user (dangerous). $id = get_parameter('id', get_parameter('id_user', '')); -// ID given as parameter +// ID given as parameter. $pure = get_parameter('pure', 0); $user_info = get_user_info($id); $is_err = false; -if (! check_acl($config['id_user'], 0, 'UM')) { +if ((bool) check_acl($config['id_user'], 0, 'UM') === false) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to access User Management' @@ -130,7 +126,7 @@ if (! check_acl($config['id_user'], 0, 'UM')) { if (is_ajax() === true) { $delete_profile = (bool) get_parameter('delete_profile'); - if ($delete_profile) { + if ($delete_profile === true) { $id2 = (string) get_parameter('id_user'); $id_up = (int) get_parameter('id_user_profile'); @@ -160,7 +156,7 @@ if (is_ajax() === true) { if ($has_profile === false && $user_is_global_admin === false) { $result = delete_user($id2); - if ($result) { + if ($result === true) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, __('Deleted user %s', io_safe_output($id_user)) @@ -174,7 +170,7 @@ if (is_ajax() === true) { ); // Delete the user in all the consoles. - if (defined('METACONSOLE')) { + if (is_metaconsole() === true) { $servers = metaconsole_get_servers(); foreach ($servers as $server) { // Connect to the remote console. @@ -182,7 +178,7 @@ if (is_ajax() === true) { // Delete the user. $result = delete_user($id_user); - if ($result) { + if ($result === true) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, __('Deleted user %s from metaconsole', io_safe_output($id_user)) @@ -193,10 +189,14 @@ if (is_ajax() === true) { metaconsole_restore_db(); // Log to the metaconsole too. - if ($result) { + if ($result === true) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, - __('Deleted user %s from %s', io_safe_input($id_user), io_safe_input($server['server_name'])) + __( + 'Deleted user %s from %s', + io_safe_input($id_user), + io_safe_input($server['server_name']) + ) ); } @@ -217,14 +217,8 @@ if (is_ajax() === true) { $tab = get_parameter('tab', 'user'); -if ($id) { - $header_title = ' » '.__('Update user'); -} else { - $header_title = ' » '.__('Create user'); -} - // Header. -if ($meta) { +if (is_metaconsole() === true) { user_meta_print_header(); $sec = 'advanced'; } else { @@ -255,19 +249,34 @@ if ($meta) { $buttons[$tab]['active'] = true; - ui_print_page_header( - __('User detail editor').$header_title, + ui_print_standard_header( + (empty($id) === false) ? __('Update user') : __('Create user'), 'images/gm_users.png', false, '', true, - $buttons + $buttons, + [ + [ + 'link' => '', + 'label' => __('Profiles'), + ], + [ + 'link' => ui_get_full_url('index.php?sec=gusuarios&sec2=godmode/users/user_list'), + 'label' => __('Manage users'), + ], + [ + 'link' => '', + 'label' => __('User Detail Editor'), + ], + ] ); + $sec = 'gusuarios'; } -if ($config['user_can_update_info']) { +if ((bool) $config['user_can_update_info'] === true) { $view_mode = false; } else { $view_mode = true; @@ -281,14 +290,14 @@ $renewAPIToken = (bool) get_parameter('renewAPIToken'); $status = get_parameter('status', -1); $json_profile = get_parameter('json_profile', ''); -// Reset status var if current action is not update_user -if ($new_user || $create_user || $add_profile - || $delete_profile || $update_user +// Reset status var if current action is not update_user. +if ($new_user === true || $create_user === true || $add_profile === true + || $delete_profile === true || $update_user === true ) { $status = -1; } -if ($new_user && $config['admin_can_add_user']) { +if ($new_user === true && (bool) $config['admin_can_add_user'] === true) { $user_info = []; $id = ''; $user_info['fullname'] = ''; @@ -312,29 +321,31 @@ if ($new_user && $config['admin_can_add_user']) { $user_info['section'] = ''; $user_info['data_section'] = ''; - // This attributes are inherited from global configuration + // This attributes are inherited from global configuration. $user_info['block_size'] = $config['block_size']; - if (enterprise_installed() && is_metaconsole() === true) { + if (enterprise_installed() === true && is_metaconsole() === true) { $user_info['metaconsole_agents_manager'] = 0; $user_info['metaconsole_assigned_server'] = ''; $user_info['metaconsole_access_node'] = 0; } - if ($config['ehorus_user_level_conf']) { + if ((bool) $config['ehorus_user_level_conf'] === true) { $user_info['ehorus_user_level_user'] = ''; $user_info['ehorus_user_level_pass'] = ''; $user_info['ehorus_user_level_enabled'] = true; } } -if ($create_user) { - if (! $config['admin_can_add_user']) { - ui_print_error_message(__('The current authentication scheme doesn\'t support creating users on %s', get_product_name())); +if ($create_user === true) { + if ((bool) $config['admin_can_add_user'] === false) { + ui_print_error_message( + __('The current authentication scheme doesn\'t support creating users on %s', get_product_name()) + ); return; } - if (html_print_csrf_error()) { + if (html_print_csrf_error() === true) { return; } @@ -375,20 +386,20 @@ if ($create_user) { $values['block_size'] = (int) get_parameter('block_size', $config['block_size']); $values['section'] = get_parameter('section'); - if (($values['section'] == 'Event list') || ($values['section'] == 'Group view') || ($values['section'] == 'Alert detail') || ($values['section'] == 'Tactical view') || ($values['section'] == 'Default')) { + if (($values['section'] === 'Event list') || ($values['section'] === 'Group view') || ($values['section'] === 'Alert detail') || ($values['section'] === 'Tactical view') || ($values['section'] === 'Default')) { $values['data_section'] = ''; - } else if ($values['section'] == 'Dashboard') { + } else if ($values['section'] === 'Dashboard') { $values['data_section'] = $dashboard; - } else if (io_safe_output($values['section']) == 'Visual console') { + } else if (io_safe_output($values['section']) === 'Visual console') { $values['data_section'] = $visual_console; - } else if ($values['section'] == 'Other' || io_safe_output($values['section']) == 'External link') { + } else if ($values['section'] === 'Other' || io_safe_output($values['section']) === 'External link') { $values['data_section'] = get_parameter('data_section'); } if (enterprise_installed()) { $values['force_change_pass'] = 1; $values['last_pass_change'] = date('Y/m/d H:i:s', get_system_time()); - if (defined('METACONSOLE')) { + if (is_metaconsole() === true) { $values['metaconsole_access'] = get_parameter('metaconsole_access', 'basic'); $values['metaconsole_agents_manager'] = ($user_is_admin == 1 ? 1 : get_parameter('metaconsole_agents_manager', '0')); $values['metaconsole_assigned_server'] = get_parameter('metaconsole_assigned_server', ''); @@ -402,7 +413,7 @@ if ($create_user) { $values['strict_acl'] = (bool) get_parameter('strict_acl', false); $values['session_time'] = (int) get_parameter('session_time', 0); - // eHorus user level conf + // Ehorus user level conf. if ($config['ehorus_user_level_conf']) { $values['ehorus_user_level_enabled'] = (bool) get_parameter('ehorus_user_level_enabled', false); if ($values['ehorus_user_level_enabled'] === true) { @@ -551,7 +562,7 @@ if ($create_user) { } if ($update_user) { - if (html_print_csrf_error()) { + if (html_print_csrf_error() === true) { return; } @@ -568,7 +579,9 @@ if ($update_user) { $values['timezone'] = (string) get_parameter('timezone'); $values['default_event_filter'] = (int) get_parameter('default_event_filter'); $values['default_custom_view'] = (int) get_parameter('default_custom_view'); - $values['api_token'] = ((bool) get_parameter('renewAPIToken') === true) ? api_token_generate() : (string) get_parameter('api_token'); + // API Token information. + $apiTokenRenewed = (bool) get_parameter('renewAPIToken'); + $values['api_token'] = ($apiTokenRenewed === true) ? api_token_generate() : users_get_API_token($values['id_user']); if (users_is_admin() === false && (bool) $values['is_admin'] !== false) { db_pandora_audit( @@ -580,7 +593,7 @@ if ($update_user) { exit; } - // eHorus user level conf. + // Ehorus user level conf. $values['ehorus_user_level_enabled'] = (bool) get_parameter('ehorus_user_level_enabled', false); $values['ehorus_user_level_user'] = (string) get_parameter('ehorus_user_level_user'); $values['ehorus_user_level_pass'] = (string) get_parameter('ehorus_user_level_pass'); @@ -597,17 +610,17 @@ if ($update_user) { $values['block_size'] = get_parameter('block_size', $config['block_size']); $values['section'] = get_parameter('section'); - if (($values['section'] == 'Event list') || ($values['section'] == 'Group view') || ($values['section'] == 'Alert detail') || ($values['section'] == 'Tactical view') || ($values['section'] == 'Default')) { + if (($values['section'] === 'Event list') || ($values['section'] === 'Group view') || ($values['section'] === 'Alert detail') || ($values['section'] === 'Tactical view') || ($values['section'] === 'Default')) { $values['data_section'] = ''; - } else if ($values['section'] == 'Dashboard') { + } else if ($values['section'] === 'Dashboard') { $values['data_section'] = $dashboard; - } else if (io_safe_output($values['section']) == 'Visual console') { + } else if (io_safe_output($values['section']) === 'Visual console') { $values['data_section'] = $visual_console; - } else if ($values['section'] == 'Other' || io_safe_output($values['section']) == 'External link') { + } else if ($values['section'] === 'Other' || io_safe_output($values['section']) === 'External link') { $values['data_section'] = get_parameter('data_section'); } - if (enterprise_installed() && defined('METACONSOLE')) { + if (enterprise_installed() === true && is_metaconsole() === true) { $values['metaconsole_access'] = get_parameter('metaconsole_access'); $values['metaconsole_agents_manager'] = get_parameter('metaconsole_agents_manager', '0'); $values['metaconsole_assigned_server'] = get_parameter('metaconsole_assigned_server', ''); @@ -734,7 +747,7 @@ if ($update_user) { $has_skin = true; } - if (enterprise_installed() && defined('METACONSOLE')) { + if (enterprise_installed() === true && is_metaconsole() === true) { $info .= ',"Wizard access":"'.$values['metaconsole_access'].'"}'; $has_wizard = true; } else if ($has_skin) { @@ -756,7 +769,7 @@ if ($update_user) { ui_print_result_message( $res1, - __('User info successfully updated'), + ($apiTokenRenewed === true) ? __('You have generated a new API Token.') : __('User info successfully updated'), __('Error updating user info (no change?)') ); } @@ -779,7 +792,7 @@ if ($update_user) { } foreach ($profiles as $profile) { - $count_groups = ($count_groups + 1); + $count_groups++; $arr_tags = explode(',', $profile['tags']); $count_tags = ($count_tags + count($arr_tags)); } @@ -792,7 +805,7 @@ if ($update_user) { $user_info = $values; } -if ($status != -1) { +if ((int) $status !== -1) { ui_print_result_message( $status, __('User info successfully updated'), @@ -862,12 +875,13 @@ if (!users_is_admin() && $config['id_user'] != $id && !$new_user) { } } -if (defined('METACONSOLE')) { - if ($id) { - echo '
'.__('Update User').'
'; - } else { - echo '
'.__('Create User').'
'; - } +if (is_metaconsole() === true) { + html_print_div( + [ + 'class' => 'user_form_title', + 'content' => (empty($id) === true) ? __('Create User') : __('Update User'), + ] + ); } if (!$new_user) { @@ -875,6 +889,42 @@ if (!$new_user) { $user_id .= ''.$id.''; $user_id .= html_print_input_hidden('id_user', $id, true); $user_id .= '
'; + $user_id .= '

'.__('API Token').'

'; + $user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:renewAPIToken(\'%s\', \'%s\', \'%s\')', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_profile_form', + ), + 'content' => html_print_image( + 'images/icono-refrescar.png', + true, + ['class' => 'renew_api_token_image clickable'] + ), + 'class' => 'renew_api_token_link', + ], + true + ); + + $user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:showAPIToken(\'%s\', \'%s\')', + __('API Token'), + base64_encode(__('Your API Token is:').' 
'.users_get_API_token($id).'
 '.__('Please, avoid share this string with others.')), + ), + 'content' => html_print_image( + 'images/eye_show.png', + true, + ['class' => 'renew_api_token_image clickable'] + ), + 'class' => 'renew_api_token_link', + ], + true + ); + $user_id .= '
'; } else { $user_id = '
'.html_print_input_text_extended( 'id_user', @@ -893,7 +943,7 @@ if (!$new_user) { ).'
'; } -if (is_user_admin($id)) { +if (is_user_admin($id) === true) { $avatar = html_print_image( 'images/people_1.png', true, @@ -1286,23 +1336,6 @@ $session_time .= html_print_input_text( 'class="input_line_small"' ).'
'; -$apiToken = '
'; -$apiToken .= '

'.__('API Token'); -$apiToken .= ui_print_help_tip( - __('The next string is your passphrase for use with the API instead user/password.'), - true -).'

'; -$apiToken .= html_print_input_hidden('api_token', $user_info['api_token'], true); -$apiToken .= ''.$user_info['api_token'].'   '; -$apiToken .= sprintf( - '%s', - __('Warning'), - __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), - 'user_profile_form', - __('Renew') -); -$apiToken .= '
'; - $user_groups = implode(',', array_keys((users_get_groups($id, 'AR', $display_all_group)))); if (empty($user_groups) === false) { @@ -1457,7 +1490,7 @@ if ($id != '' && !$is_err) { echo '
-

Extra info

'.$email.$phone.$not_login.$local_user.$session_time.$apiToken.'
+

Extra info

'.$email.$phone.$not_login.$local_user.$session_time.'
'.$language.$access_or_pagination.$skin.$home_screen.$default_event_filter.$double_authentication.'
diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index b12745afdf..d6dcbed25e 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -2076,3 +2076,17 @@ function renewAPIToken(title, message, form) { } }); } + +/** + * Show Dialog for view the API token. + * + * @param {string} title Title for show. + * @param {string} message Base64 encoded message for show. + */ +function showAPIToken(title, message) { + confirmDialog({ + title: title, + message: atob(message), + hideCancelButton: true + }); +} diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 83f2a89ac2..07c58ad27c 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -9038,6 +9038,14 @@ div#err_msg_centralised { width: 75%; } +.renew_api_token_link { + margin: 3px 0.5em 0 0; + float: right; +} + +.renew_api_token_image { + width: 16px; +} @media screen and (max-width: 1369px) { .div-col { width: 50%; diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index bc589bc763..7d12f8ec52 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -80,10 +80,12 @@ if (isset($_GET['modified']) && !$view_mode) { $upd_info['id_skin'] = get_parameter('skin', $user_info['id_skin']); $upd_info['default_event_filter'] = get_parameter('event_filter', null); $upd_info['block_size'] = get_parameter('block_size', $config['block_size']); - $upd_info['api_token'] = ((bool) get_parameter('renewAPIToken') === true) ? api_token_generate() : (string) get_parameter('api_token'); + // API Token information. + $apiTokenRenewed = (bool) get_parameter('renewAPIToken'); + $upd_info['api_token'] = ($apiTokenRenewed === true) ? api_token_generate() : users_get_API_token($config['id_user']); $default_block_size = get_parameter('default_block_size', 0); - if ($default_block_size) { + if ($default_block_size > 0) { $upd_info['block_size'] = 0; } @@ -159,17 +161,17 @@ if (isset($_GET['modified']) && !$view_mode) { } else if ($password_new !== 'NON-INIT') { $error_msg = __('Passwords didn\'t match or other problem encountered while updating passwords'); } - } else if (empty($password_new) && empty($password_confirm)) { + } else if (empty($password_new) === true && empty($password_confirm) === true) { $return = true; - } else if (empty($password_new) || empty($password_confirm)) { + } else if (empty($password_new) === true || empty($password_confirm) === true) { $return = false; } // No need to display "error" here, because when no update is needed // (no changes in data) SQL function returns 0 (FALSE), but is not an error, // just no change. Previous error message could be confussing to the user. - if ($return) { - if (!empty($password_new) && !empty($password_confirm)) { + if ($return !== false) { + if (empty($password_new) === false && empty($password_confirm) === false) { $success_msg = __('Password successfully updated'); } @@ -182,9 +184,13 @@ if (isset($_GET['modified']) && !$view_mode) { if ($return_update_user === false) { $error_msg = __('Error updating user info'); } else if ($return_update_user == true) { - $success_msg = __('User info successfully updated'); + if ($apiTokenRenewed === true) { + $success_msg = __('You have generated a new API Token.'); + } else { + $success_msg = __('User info successfully updated'); + } } else { - if (!empty($password_new) && !empty($password_confirm)) { + if (empty($password_new) === false && empty($password_confirm) === false) { $success_msg = __('Password successfully updated'); } else if ($upd_info['id_skin'] !== $user_info['id_skin']) { $success_msg = __('Skin successfully updated'); @@ -224,7 +230,7 @@ if (isset($_GET['modified']) && !$view_mode) { } // Prints action status for current message. -if ($status != -1) { +if ((int) $status !== -1) { ui_print_result_message( $status, __('User info successfully updated'), @@ -259,16 +265,41 @@ if (is_metaconsole() === false && is_management_allowed() === false) { $user_id = '

'.__('User ID').':

'; $user_id .= ''.$id.'
'; -$user_id .= '

'.__('API Token').':

'; -$user_id .= html_print_input_hidden('api_token', $user_info['api_token'], true); -$user_id .= sprintf( - '%s', - __('Warning'), - __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), - 'user_profile_form', - __('Renew') +$user_id .= '

'.__('API Token').'

'; +$user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:renewAPIToken(\'%s\', \'%s\', \'%s\')', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_profile_form', + ), + 'content' => html_print_image( + 'images/icono-refrescar.png', + true, + ['class' => 'renew_api_token_image clickable'] + ), + 'class' => 'renew_api_token_link', + ], + true +); + +$user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:showAPIToken(\'%s\', \'%s\')', + __('API Token'), + base64_encode(__('Your API Token is:').'
'.users_get_API_token($config['id_user']).'
'.__('Please, avoid share this string with others.')), + ), + 'content' => html_print_image( + 'images/eye_show.png', + true, + ['class' => 'renew_api_token_image clickable'] + ), + 'class' => 'renew_api_token_link', + ], + true ); -$user_id .= '
'.$user_info['api_token'].''; $user_id .= '
'; $full_name = '
'.html_print_input_text_extended( @@ -288,7 +319,7 @@ $full_name = '
'.html_print_input_text_extended ).'
'; // Show "Picture" (in future versions, why not, allow users to upload it's own avatar here. -if (is_user_admin($id)) { +if (is_user_admin($id) === true) { $avatar = html_print_image('images/people_1.png', true, ['class' => 'user_avatar']); } else { $avatar = html_print_image('images/people_2.png', true, ['class' => 'user_avatar']); @@ -646,10 +677,10 @@ foreach ($timezones as $timezone_name => $tz) { } } -if (is_metaconsole()) { - echo '
'; +if (is_metaconsole() === true) { + echo ''; } else { - echo ''; + echo ''; } html_print_input_hidden('id', $id, false, false, false, 'id'); @@ -668,7 +699,7 @@ if (is_metaconsole()) { -if (!is_metaconsole()) { +if (is_metaconsole() === false) { echo '
@@ -677,10 +708,10 @@ if (!is_metaconsole()) { } echo '
-
+
'.$comments.'
-
+
'; if ($config['ehorus_enabled'] && $config['ehorus_user_level_conf']) { From 8ffc5aef97c8f599bdc96115fc470265b10e242b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Wed, 29 Jun 2022 09:14:21 +0200 Subject: [PATCH 009/251] Minor improvements --- .../godmode/users/configure_user.php | 17 ++++++++++------- pandora_console/include/functions_users.php | 8 +++++++- pandora_console/operation/users/user_edit.php | 10 ++++++++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 031e87635a..b2280d9446 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -425,11 +425,8 @@ if ($create_user === true) { } } - // Generate a new API Token if user has login capability. - if ($values['not_login'] === false) { - // Generate new API token. - $values['api_token'] = api_token_generate(); - } + // Generate new API token. + $values['api_token'] = api_token_generate(); if (empty($id) === true) { ui_print_error_message(__('User ID cannot be empty')); @@ -901,7 +898,10 @@ if (!$new_user) { 'content' => html_print_image( 'images/icono-refrescar.png', true, - ['class' => 'renew_api_token_image clickable'] + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Renew API Token'), + ] ), 'class' => 'renew_api_token_link', ], @@ -918,7 +918,10 @@ if (!$new_user) { 'content' => html_print_image( 'images/eye_show.png', true, - ['class' => 'renew_api_token_image clickable'] + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Show API Token'), + ] ), 'class' => 'renew_api_token_link', ], diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index 00a18afda5..82fc2b2362 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -905,7 +905,13 @@ function api_token_generate() */ function users_get_API_token(string $idUser) { - return db_get_value('api_token', 'tusuario', 'id_user', $idUser); + $output = db_get_value('api_token', 'tusuario', 'id_user', $idUser); + + if (empty($output) === true) { + $output = '<< '.__('NONE').' >>'; + } + + return $output; } diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index 7d12f8ec52..f6ebf682f7 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -277,7 +277,10 @@ $user_id .= html_print_anchor( 'content' => html_print_image( 'images/icono-refrescar.png', true, - ['class' => 'renew_api_token_image clickable'] + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Renew API Token'), + ] ), 'class' => 'renew_api_token_link', ], @@ -294,7 +297,10 @@ $user_id .= html_print_anchor( 'content' => html_print_image( 'images/eye_show.png', true, - ['class' => 'renew_api_token_image clickable'] + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Show API Token'), + ] ), 'class' => 'renew_api_token_link', ], From 067b7a821f0980c2741b9ef65ca0fb19ed23f012 Mon Sep 17 00:00:00 2001 From: Calvo Date: Tue, 13 Sep 2022 12:31:09 +0200 Subject: [PATCH 010/251] WIP:Move inventory to open --- pandora_server/lib/PandoraFMS/Core.pm | 272 ++++++++++++++++++++ pandora_server/lib/PandoraFMS/DataServer.pm | 3 +- 2 files changed, 273 insertions(+), 2 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 589d409357..35a8b6869a 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -4987,6 +4987,278 @@ sub process_inc_abs_data ($$$$$$) { return $diff; } +################################################################################ +################################################################################ +## Inventory XML data +################################################################################ +################################################################################ + + +################################################################################ +# Process inventory data, creating the module if necessary. +################################################################################ +sub process_inventory_data ($$$$$$$) { + my ($pa_config, $data, $server_id, $agent_name, + $interval, $timestamp, $dbh) = @_; + + foreach my $inventory (@{$data->{'inventory'}}) { + + # Process inventory modules + foreach my $module_data (@{$inventory->{'inventory_module'}}) { + + my $module_name = get_tag_value ($module_data, 'name', ''); + + # Unnamed module + next if ($module_name eq ''); + + # Process inventory data + my $data_list = ''; + foreach my $list (@{$module_data->{'datalist'}}) { + + # Empty list + next unless defined ($list->{'data'}); + + foreach my $data (@{$list->{'data'}}) { + $data_list .= $data . "\n"; + } + } + + next if ($data_list eq ''); + process_inventory_module_data ($pa_config, $data_list, $server_id, $agent_name, $module_name, $interval, $timestamp, $dbh); + } + } +} + +################################################################################ +# Process inventory module data, creating the module if necessary. +################################################################################ +sub process_inventory_module_data ($$$$$$$$) { + my ($pa_config, $data, $server_id, $agent_name, + $module_name, $interval, $timestamp, $dbh) = @_; + + logger ($pa_config, "Processing inventory module '$module_name' for agent '$agent_name'.", 10); + + # Get agent data + my $agent = get_db_single_row ($dbh, + 'SELECT * FROM tagente WHERE nombre = ?', safe_input($agent_name)); + if (! defined ($agent)) { + logger ($pa_config, "Agent '$agent_name' not found for inventory module '$module_name'.", 3); + return; + } + + # Parse the timestamp and process the module + if ($timestamp !~ /(\d+)\/(\d+)\/(\d+) +(\d+):(\d+):(\d+)/ && + $timestamp !~ /(\d+)\-(\d+)\-(\d+) +(\d+):(\d+):(\d+)/) { + logger($pa_config, "Invalid timestamp '$timestamp' from module '$module_name' agent '$agent_name'.", 3); + return; + } + my $utimestamp; + eval { + $utimestamp = strftime("%s", $6, $5, $4, $3, $2 - 1, $1 - 1900); + }; + if ($@) { + logger($pa_config, "Invalid timestamp '$timestamp' from module '$module_name' agent '$agent_name'.", 3); + return; + } + + # Get module data or create it if it does not exist + my $inventory_module = get_db_single_row ($dbh, + 'SELECT tagent_module_inventory.*, tmodule_inventory.name + FROM tagent_module_inventory, tmodule_inventory + WHERE tagent_module_inventory.id_module_inventory = tmodule_inventory.id_module_inventory + AND id_agente = ? AND name = ?', + $agent->{'id_agente'}, safe_input($module_name)); + + + + if (! defined ($inventory_module)) { + # Get the module + my $module_id = get_db_value ($dbh, + 'SELECT id_module_inventory FROM tmodule_inventory WHERE name = ? AND id_os = ?', + safe_input($module_name), $agent->{'id_os'}); + return unless defined ($module_id); + + my $id_agent_module_inventory = 0; + # Update the module data + + $id_agent_module_inventory = db_insert ($dbh, 'id_agent_module_inventory', + "INSERT INTO tagent_module_inventory (id_agente, id_module_inventory, + ${RDBMS_QUOTE}interval${RDBMS_QUOTE}, data, timestamp, utimestamp, flag) + VALUES (?, ?, ?, ?, ?, ?, ?)", + $agent->{'id_agente'}, $module_id, $interval, safe_input($data), $timestamp, $utimestamp, 0); + + + return unless ($id_agent_module_inventory > 0); + + db_do ($dbh, + 'INSERT INTO tagente_datos_inventory (id_agent_module_inventory, data, timestamp, utimestamp) + VALUES (?, ?, ?, ?)', + $id_agent_module_inventory, safe_input($data), $timestamp, $utimestamp); + + return; + } + + process_inventory_module_diff($pa_config, safe_input($data), + $inventory_module, $timestamp, $utimestamp, $dbh, $interval); +} + +################################################################################ +# Searching differences between incoming module and stored module, +# creating/updating module and event +################################################################################ +sub process_inventory_module_diff ($$$$$$;$) { + my ($pa_config, $incoming_data, $inventory_module, $timestamp, $utimestamp, $dbh, $interval) = @_; + + my $stored_data = $inventory_module->{'data'}; + my $agent_id = $inventory_module->{'id_agente'}; + my $stored_utimestamp = $inventory_module->{'utimestamp'}; + my $agent_module_inventory_id = $inventory_module->{'id_agent_module_inventory'}; + my $module_inventory_id = $inventory_module->{'id_module_inventory'}; + + + process_inventory_alerts($pa_config, $incoming_data, + $inventory_module, $timestamp, $utimestamp, $dbh, $interval); + + # If there were any changes generate an event and save the new data + if (decode('UTF-8', $stored_data) ne $incoming_data) { + my $inventory_db = $stored_data; + my $inventory_new = $incoming_data; + my @inventory = split('\n', $inventory_new); + my $diff_new = ""; + my $diff_delete = ""; + + foreach my $inv (@inventory) { + my $inv_clean = quotemeta($inv); + if($inventory_db =~ m/$inv_clean/) { + $inventory_db =~ s/$inv_clean//g; + $inventory_new =~ s/$inv_clean//g; + } + else { + $diff_new .= "$inv\n"; + } + } + + # If any register is in the stored yet, we store as deleted + $inventory_db =~ s/\n\n*/\n/g; + $inventory_db =~ s/^\n//g; + + $diff_delete = $inventory_db; + + if($diff_new ne "") { + $diff_new = " NEW: '$diff_new' "; + } + if($diff_delete ne "") { + $diff_delete = " DELETED: '$diff_delete' "; + } + + db_do ($dbh, 'INSERT INTO tagente_datos_inventory (id_agent_module_inventory, data, timestamp, utimestamp) VALUES (?, ?, ?, ?)', + $agent_module_inventory_id, $incoming_data, $timestamp, $utimestamp); + + # Do not generate an event the first time the module runs + if ($stored_utimestamp != 0) { + my $inventory_changes_blacklist = pandora_get_config_value ($dbh, 'inventory_changes_blacklist'); + my $inventory_module_blocked = 0; + + if($inventory_changes_blacklist ne "") { + foreach my $inventory_id_excluded (split (',', $inventory_changes_blacklist)) { + # If the inventory_module_id is in the blacklist, the change will not be processed + if($inventory_module->{'id_module_inventory'} == $inventory_id_excluded) { + logger ($pa_config, "Inventory change omitted on inventory #$inventory_id_excluded due be on the changes blacklist", 10); + $inventory_module_blocked = 1; + } + } + } + + # If the inventory_module_id is in the blacklist, the change will not be processed + if ($inventory_module_blocked == 0) { + my $inventory_module_name = get_db_value ($dbh, "SELECT name FROM tmodule_inventory WHERE id_module_inventory = ?", $module_inventory_id); + return unless defined ($inventory_module_name); + + my $agent_name = get_agent_name ($dbh, $agent_id); + return unless defined ($agent_name); + + my $agent_alias = get_agent_alias ($dbh, $agent_id); + return unless defined ($agent_alias); + + my $group_id = get_agent_group ($dbh, $agent_id); + + + + $stored_data =~ s/&#x20;/ /g; + $incoming_data =~ s/&#x20;/ /g; + + my @values_stored = split(' ', $stored_data); + my @finalc_stored = (); + my @values_incoming = split(' ', $incoming_data); + my @finalc_incoming = (); + my @finalc_compare_added = (); + my @finalc_compare_deleted = (); + my @finalc_compare_updated = (); + my @finalc_compare_updated_del = (); + my @finalc_compare_updated_add = (); + my $temp_compare = (); + my $final_d = ''; + my $final_a = ''; + my $final_u = ''; + + + + foreach my $i (0 .. $#values_stored) { + $finalc_stored[$i] = $values_stored[$i]; + + if ( grep $_ eq $values_stored[$i], @values_incoming ) { + + } else { + # Use 'safe_output' to avoid double encode the entities when creating the event with 'pandora_event' + $final_d .= "DELETED RECORD: ".safe_output($values_stored[$i])."\n"; + } + } + + foreach my $i (0 .. $#values_incoming) { + $finalc_incoming[$i] = $values_incoming[$i]; + + if ( grep $_ eq $values_incoming[$i], @values_stored ) { + + } else { + # Use 'safe_output' to avoid double encode the entities when creating the event with 'pandora_event' + $final_a .= "NEW RECORD: ".safe_output($values_incoming[$i])."\n"; + } + } + + # foreach my $i (0 .. $#finalc_compare_deleted) { + # $finalc_compare_updated_del[$i] = split(';', $finalc_compare_deleted[$i]); + # $finalc_compare_updated_add[$i] = split(';', $finalc_compare_added[$i]); + # if($finalc_compare_updated_del[$i] ~~ @finalc_compare_updated_add){ + # $finalc_compare_updated[$i] = $finalc_compare_updated_del[$i]; + # } + # $finalc_compare_updated[$i] =~ s/DELETED RECORD:/UPDATED RECORD:/g; + # $finalc_compare_updated[$i] =~ s/NEW RECORD://g; + # } + + + pandora_event ($pa_config, "Configuration change:\n".$final_d.$final_a." for agent '" . safe_output($agent_alias) . "' module '" . safe_output($inventory_module_name) . "'.", $group_id, $agent_id, 0, 0, 0, "configuration_change", 0, $dbh); + } + } + } + + # Update the module data + if (defined($interval)) { + db_do ($dbh, 'UPDATE tagent_module_inventory + SET'. $RDBMS_QUOTE . 'interval' . + $RDBMS_QUOTE . '=?, data=?, timestamp=?, utimestamp=? + WHERE id_agent_module_inventory=?', + $interval, $incoming_data, $timestamp, + $utimestamp, $agent_module_inventory_id); + + } + else { + db_do ($dbh, 'UPDATE tagent_module_inventory + SET data = ?, timestamp = ?, utimestamp = ? + WHERE id_agent_module_inventory = ?', + $incoming_data, $timestamp, $utimestamp, $agent_module_inventory_id); + } +} + sub log4x_get_severity_num($) { my ($data_object) = @_; my $data = $data_object->{'severity'}; diff --git a/pandora_server/lib/PandoraFMS/DataServer.pm b/pandora_server/lib/PandoraFMS/DataServer.pm index 209859e9a1..e53692170e 100644 --- a/pandora_server/lib/PandoraFMS/DataServer.pm +++ b/pandora_server/lib/PandoraFMS/DataServer.pm @@ -628,8 +628,7 @@ sub process_xml_data ($$$$$) { # Process inventory modules - enterprise_hook('process_inventory_data', [$pa_config, $data, $server_id, $agent_name, - $interval, $timestamp, $dbh]); + process_inventory_data($pa_config, $data, $server_id, $agent_name, $interval, $timestamp, $dbh); # Process log modules enterprise_hook('process_log_data', [$pa_config, $data, $server_id, $agent_name, From da0dad0148623b456c3a40ecb7b1759d52116b17 Mon Sep 17 00:00:00 2001 From: Calvo Date: Wed, 14 Sep 2022 18:12:39 +0200 Subject: [PATCH 011/251] WIP:Move inventory to open --- .../godmode/agentes/configurar_agente.php | 19 +- .../godmode/agentes/inventory_manager.php | 262 ++++ pandora_console/godmode/menu.php | 4 +- .../modules/manage_inventory_modules.php | 387 ++++++ .../modules/manage_inventory_modules_form.php | 153 +++ .../include/functions_inventory.php | 1147 +++++++++++++++++ pandora_console/include/functions_menu.php | 2 +- .../include/functions_planned_downtimes.php | 3 +- .../include/functions_reporting_html.php | 1 + pandora_console/include/functions_ui.php | 256 ++++ .../operation/agentes/agent_inventory.php | 281 ++++ .../operation/agentes/ver_agente.php | 18 +- .../operation/inventory/inventory.php | 551 ++++++++ pandora_console/operation/menu.php | 6 +- pandora_server/bin/pandora_server | 3 + pandora_server/lib/PandoraFMS/Core.pm | 545 ++++---- .../lib/PandoraFMS/InventoryServer.pm | 267 ++++ 17 files changed, 3626 insertions(+), 279 deletions(-) create mode 100644 pandora_console/godmode/agentes/inventory_manager.php create mode 100644 pandora_console/godmode/modules/manage_inventory_modules.php create mode 100644 pandora_console/godmode/modules/manage_inventory_modules_form.php create mode 100644 pandora_console/include/functions_inventory.php create mode 100644 pandora_console/operation/agentes/agent_inventory.php create mode 100755 pandora_console/operation/inventory/inventory.php create mode 100644 pandora_server/lib/PandoraFMS/InventoryServer.pm diff --git a/pandora_console/godmode/agentes/configurar_agente.php b/pandora_console/godmode/agentes/configurar_agente.php index a1ebc7ce7f..208eed59a0 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -451,7 +451,20 @@ if ($id_agente) { // Inventory. - $inventorytab = enterprise_hook('inventory_tab'); + $inventorytab['text'] = ''.html_print_image( + 'images/page_white_text.png', + true, + [ + 'title' => __('Inventory'), + 'class' => 'invert_filter', + ] + ).''; + + if ($tab == 'inventory') { + $inventorytab['active'] = true; + } else { + $inventorytab['active'] = false; + } if ($inventorytab == -1) { $inventorytab = ''; @@ -2354,6 +2367,10 @@ switch ($tab) { include 'agent_wizard.php'; break; + case 'inventory': + include 'inventory_manager.php'; + break; + default: if (enterprise_hook('switch_agent_tab', [$tab])) { // This will make sure that blank pages will have at least some diff --git a/pandora_console/godmode/agentes/inventory_manager.php b/pandora_console/godmode/agentes/inventory_manager.php new file mode 100644 index 0000000000..b477d7e923 --- /dev/null +++ b/pandora_console/godmode/agentes/inventory_manager.php @@ -0,0 +1,262 @@ + $id_agente, + 'id_module_inventory' => $id_module_inventory, + ] + ); + + if (!$if_exists) { + $values = [ + 'id_agente' => $id_agente, + 'id_module_inventory' => $id_module_inventory, + 'target' => $target, + 'interval' => $interval, + 'username' => $username, + 'password' => $password, + 'custom_fields' => $custom_fields_enabled && !empty($custom_fields) ? base64_encode(json_encode($custom_fields)) : '', + ]; + + $result = db_process_sql_insert('tagent_module_inventory', $values); + + if ($result) { + ui_print_success_message(__('Successfully added inventory module')); + } else { + ui_print_error_message(__('Error adding inventory module')); + } + } else { + ui_print_error_message(__('The inventory of the module already exists')); + } + + // Remove inventory module from agent +} else if ($delete_inventory_module) { + $result = db_process_sql_delete( + 'tagent_module_inventory', + ['id_agent_module_inventory' => $delete_inventory_module] + ); + + if ($result) { + ui_print_success_message(__('Successfully deleted inventory module')); + } else { + ui_print_error_message(__('Error deleting inventory module')); + } + + // Update inventory module +} else if ($force_inventory_module) { + $result = db_process_sql_update('tagent_module_inventory', ['flag' => 1], ['id_agent_module_inventory' => $force_inventory_module]); + + if ($result) { + ui_print_success_message(__('Successfully forced inventory module')); + } else { + ui_print_error_message(__('Error forcing inventory module')); + } + + // Update inventory module +} else if ($update_inventory_module) { + $values = [ + 'target' => $target, + 'interval' => $interval, + 'username' => $username, + 'password' => $password, + 'custom_fields' => $custom_fields_enabled && !empty($custom_fields) ? base64_encode(json_encode($custom_fields)) : '', + ]; + + $result = db_process_sql_update('tagent_module_inventory', $values, ['id_agent_module_inventory' => $id_agent_module_inventory, 'id_agente' => $id_agente]); + + if ($result) { + ui_print_success_message(__('Successfully updated inventory module')); + } else { + ui_print_error_message(__('Error updating inventory module')); + } +} + +// Load inventory module data for updating +if ($load_inventory_module) { + $sql = 'SELECT * FROM tagent_module_inventory WHERE id_module_inventory = '.$load_inventory_module; + $row = db_get_row_sql($sql); + + if (!empty($row)) { + $id_agent_module_inventory = $row['id_agent_module_inventory']; + $id_module_inventory = $row['id_module_inventory']; + $target = $row['target']; + $interval = $row['interval']; + $username = $row['username']; + $password = io_output_password($row['password']); + $custom_fields = []; + + if (!empty($row['custom_fields'])) { + try { + $custom_fields = array_map( + function ($field) { + if ($field['secure']) { + $field['value'] = io_output_password($field['value']); + } + + return $field; + }, + json_decode(base64_decode($row['custom_fields']), true) + ); + $custom_fields_enabled = true; + } catch (Exception $e) { + } + } + } else { + ui_print_error_message(__('Inventory module error')); + include 'general/footer.php'; + + return; + } +} else { + $target = $direccion_agente; + $interval = (string) SECONDS_1HOUR; + $username = ''; + $password = ''; + $custom_fields_enabled = false; + $custom_fields = []; +} + +// Inventory module configuration +$form_buttons = ''; +if ($load_inventory_module) { + $form_buttons .= html_print_input_hidden('id_agent_module_inventory', $id_agent_module_inventory, true); + $form_buttons .= html_print_submit_button(__('Update'), 'update_inventory_module', false, 'class="sub next"', true); +} else { + $form_buttons .= html_print_submit_button(__('Add'), 'add_inventory_module', false, 'class="sub next"', true); +} + +echo ui_get_inventory_module_add_form( + 'index.php?sec=estado&sec2=godmode/agentes/configurar_agente&tab=inventory&id_agente='.$id_agente, + $form_buttons, + $load_inventory_module, + $id_os, + $target, + $interval, + $username, + $password, + $custom_fields_enabled, + $custom_fields +); + +// Inventory module list +$sql = sprintf( + 'SELECT * + FROM tmodule_inventory, tagent_module_inventory + WHERE tagent_module_inventory.id_agente = %d + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + ORDER BY name', + $id_agente +); +$result = db_process_sql($sql); +if (db_get_num_rows($sql) == 0) { + echo ' '; +} else { + $table->width = '100%'; + $table->class = 'databox filters'; + $table->data = []; + $table->head = []; + $table->styleTable = 'margin-top: 20px;'; + $table->head[0] = "".__('P.').''; + $table->head[1] = __('Name'); + $table->head[2] = __('Description'); + $table->head[3] = __('Target'); + $table->head[4] = __('Interval'); + $table->head[5] = __('Actions'); + $table->align = []; + $table->align[5] = 'left'; + + foreach ($result as $row) { + $data = []; + + $sql = sprintf('SELECT id_policy FROM tpolicy_modules_inventory WHERE id = %d', $row['id_policy_module_inventory']); + $id_policy = db_get_value_sql($sql); + + if ($id_policy) { + $policy = policies_get_policy($id_policy); + $data[0] = ''; + $data[0] .= html_print_image('images/policies_mc.png', true, ['border' => '0', 'title' => $policy['name']]); + $data[0] .= ''; + } else { + $data[0] = ''; + } + + $data[1] = ''.$row['name'].''; + $data[2] = $row['description']; + $data[3] = $row['target']; + $data[4] = human_time_description_raw($row['interval']); + // Delete module + $data[5] = ''; + $data[5] .= html_print_image('images/cross.png', true, ['border' => '0', 'title' => __('Delete'), 'class' => 'invert_filter']); + $data[5] .= '  '; + // Update module + $data[5] .= ''; + $data[5] .= html_print_image('images/config.png', true, ['border' => '0', 'title' => __('Update'), 'class' => 'invert_filter']); + $data[5] .= '  '; + // Force refresh module + $data[5] .= ''; + $data[5] .= html_print_image('images/target.png', true, ['border' => '0', 'title' => __('Force'), 'class' => 'invert_filter']).''; + array_push($table->data, $data); + } + + html_print_table($table); +} diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index d63595d553..7ba9973eed 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -180,7 +180,9 @@ if ($access_console_node === true) { $sub2['godmode/modules/manage_network_components']['id'] = 'Network components'; $sub['templates']['sub2'] = $sub2; - enterprise_hook('inventory_submenu'); + $sub['godmode/modules/manage_inventory_modules']['text'] = __('Inventory modules'); + $sub['godmode/modules/manage_inventory_modules']['id'] = 'Inventory modules'; + enterprise_hook('autoconfiguration_menu'); enterprise_hook('agent_repository_menu'); } diff --git a/pandora_console/godmode/modules/manage_inventory_modules.php b/pandora_console/godmode/modules/manage_inventory_modules.php new file mode 100644 index 0000000000..0eb4807beb --- /dev/null +++ b/pandora_console/godmode/modules/manage_inventory_modules.php @@ -0,0 +1,387 @@ +'.__('metaconsole').''; + } else { + $url = __('any node'); + } + + ui_print_warning_message( + __( + 'This console is not manager of this environment, please manage this feature from centralized manager console. Go to %s to manage it.', + $url + ) + ); + } +} + +$is_windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'; +if ($is_windows) { + ui_print_error_message(__('Not supported in Windows systems')); +} + +// Initialize variables. +$offset = (int) get_parameter('offset'); +$create_module_inventory = (bool) get_parameter('create_module_inventory'); +$update_module_inventory = (bool) get_parameter('update_module_inventory'); +$delete_inventory_module = (int) get_parameter('delete_inventory_module'); +$multiple_delete = (bool) get_parameter('multiple_delete', 0); +$id_module_inventory = (int) get_parameter('id_module_inventory'); +$name = (string) get_parameter('name'); +$description = (string) get_parameter('description'); +$id_os = (int) get_parameter('id_os'); +if ($id_os == 0) { + $id_os = 'NULL'; +} + +$interpreter = (string) get_parameter('interpreter'); +$code = (string) get_parameter('code'); +$code = base64_encode(str_replace("\r", '', html_entity_decode($code, ENT_QUOTES))); +$format = (string) get_parameter('format'); +$block_mode = (int) get_parameter('block_mode', 0); + +// Create inventory module. +if ($create_module_inventory === true) { + $values = [ + 'name' => $name, + 'description' => $description, + 'id_os' => $id_os, + 'interpreter' => $interpreter, + 'code' => $code, + 'data_format' => $format, + 'block_mode' => $block_mode, + ]; + + $result = (bool) inventory_create_inventory_module($values); + + $auditMessage = ((bool) $result === true) ? sprintf('Create inventory module #%s', $result) : 'Fail try to create inventory module'; + db_pandora_audit( + AUDIT_LOG_MODULE_MANAGEMENT, + $auditMessage + ); + + ui_print_result_message( + (bool) $result, + __('Successfully created inventory module'), + __('Error creating inventory module') + ); + + // Update inventory module. +} else if ($update_module_inventory === true) { + $values = [ + 'name' => $name, + 'description' => $description, + 'id_os' => $id_os, + 'interpreter' => $interpreter, + 'code' => $code, + 'data_format' => $format, + 'block_mode' => $block_mode, + ]; + + $result = inventory_update_inventory_module($id_module_inventory, $values); + + $auditMessage = ((bool) $result === true) ? 'Update inventory module' : 'Fail try to update inventory module'; + db_pandora_audit( + AUDIT_LOG_MODULE_MANAGEMENT, + sprintf('%s #%s', $auditMessage, $id_module_inventory) + ); + + ui_print_result_message( + (bool) $result, + __('Successfully updated inventory module'), + __('Error updating inventory module') + ); + + // Delete inventory module. +} else if ($delete_inventory_module === true) { + $result = db_process_sql_delete( + 'tmodule_inventory', + ['id_module_inventory' => $delete_inventory_module] + ); + + $auditMessage = ((bool) $result === true) ? 'Delete inventory module' : 'Fail try to delete inventory module'; + db_pandora_audit( + AUDIT_LOG_MODULE_MANAGEMENT, + sprintf('%s #%s', $auditMessage, $id_module_inventory) + ); + + ui_print_result_message( + (bool) $result, + __('Successfully deleted inventory module'), + __('Error deleting inventory module') + ); + + if (is_metaconsole() === true) { + $setups = db_get_all_rows_in_table('tmetaconsole_setup'); + foreach ($setups as $key => $setup) { + if (metaconsole_connect($setup) == NOERR) { + $result = db_process_sql_delete( + 'tmodule_inventory', + ['id_module_inventory' => $delete_inventory_module] + ); + + $auditMessage = ((bool) $result === true) ? 'Delete inventory module' : 'Fail try to delete inventory module'; + db_pandora_audit( + AUDIT_LOG_MODULE_MANAGEMENT, + sprintf('%s #%s', $auditMessage, $id_module_inventory) + ); + + ui_print_result_message( + (bool) $result, + $setup['server_name'].': '.__('Successfully deleted inventory module'), + $setup['server_name'].': '.__('Error deleting inventory module') + ); + } + + metaconsole_restore_db(); + } + } +} else if ($multiple_delete) { + $ids = (array) get_parameter('delete_multiple', []); + + foreach ($ids as $id) { + $result = db_process_sql_delete('tmodule_inventory', ['id_module_inventory' => $id]); + + if ($result === false) { + break; + } + } + + if ($result !== false) { + $result = true; + } else { + $result = false; + } + + $str_ids = implode(',', $ids); + $auditMessage = ($result === true) ? 'Multiple delete inventory module' : 'Fail try to delete inventory module'; + db_pandora_audit( + AUDIT_LOG_MODULE_MANAGEMENT, + sprintf('%s :%s', $auditMessage, $str_ids) + ); + + ui_print_result_message( + $result, + __('Successfully multiple deleted'), + __('Not deleted. Error deleting multiple data') + ); + + $id = 0; + + if (is_metaconsole()) { + $setups = db_get_all_rows_in_table('tmetaconsole_setup'); + foreach ($setups as $key => $setup) { + if (metaconsole_connect($setup) == NOERR) { + foreach ($ids as $id) { + $result_node = db_process_sql_delete('tmodule_inventory', ['id_module_inventory' => $id]); + + if ($result_node === false) { + break; + } + } + + if ($result_node !== false) { + $result_node = true; + } else { + $result_node = false; + } + + $str_ids = implode(',', $ids); + $auditMessage = ($result_node === true) ? 'Multiple delete inventory module' : 'Fail try to delete inventory module'; + db_pandora_audit( + AUDIT_LOG_MODULE_MANAGEMENT, + sprintf('%s :%s', $auditMessage, $str_ids) + ); + + ui_print_result_message( + $result_node, + $setup['server_name'].': '.__('Successfully multiple deleted'), + $setup['server_name'].': '.__('Not deleted. Error deleting multiple data') + ); + } + + metaconsole_restore_db(); + } + } +} + +$total_modules = db_get_sql('SELECT COUNT(*) FROM tmodule_inventory'); + +$table = new stdClass(); +$table->width = '100%'; +$table->class = 'info_table'; +$table->size = []; +$table->size[0] = '140px'; +$table->align = []; +$table->align[2] = 'left'; +$table->align[4] = 'left'; +$table->data = []; +$table->head = []; +$table->head[0] = __('Name'); +$table->head[1] = __('Description'); +$table->head[2] = __('OS'); +$table->head[3] = __('Interpreter'); + +if ($management_allowed === true) { + $table->head[4] = __('Action').html_print_checkbox('all_delete', 0, false, true, false); +} + +$result = inventory_get_modules_list($offset); + +if ($result === false) { + ui_print_info_message(['no_close' => true, 'message' => __('No inventory modules defined') ]); +} else { + $status = ''; + $begin = true; + while ($row = array_shift($result)) { + $data = []; + $begin = false; + if ($management_allowed === true) { + $data[0] = ''.$row['name'].''; + } else { + $data[0] = ''.$row['name'].''; + } + + $data[1] = $row['description']; + if ($row['os_name'] == null) { + $data[2] = html_print_image('images/agent.png', true, ['border' => '0', 'alt' => __('Agent'), 'title' => __('Agent'), 'height' => '18', 'class' => 'invert_filter']); + } else { + $data[2] = ui_print_os_icon($row['id_os'], false, true); + } + + if ($row['interpreter'] == '') { + $data[3] = __('Local module'); + } else { + $data[3] = __('Remote/Local'); + } + + if ($management_allowed === true) { + // Update module. + $data[4] = ''; + $data[4] .= html_print_image('images/config.png', true, ['border' => '0', 'title' => __('Update'), 'class' => 'invert_filter']).''; + + // Delete module. + $data[4] .= ''; + $data[4] .= html_print_image('images/cross.png', true, ['border' => '0', 'title' => __('Delete'), 'class' => 'invert_filter']); + $data[4] .= '  '; + $data[4] .= html_print_checkbox_extended('delete_multiple[]', $row['id_module_inventory'], false, false, '', 'class="check_delete"', true); + } + + array_push($table->data, $data); + } + + echo ""; + html_print_input_hidden('multiple_delete', 1); + ui_pagination($total_modules, 'index.php?sec='.$sec.'&sec2=godmode/modules/manage_inventory_modules', $offset); + html_print_table($table); + ui_pagination($total_modules, 'index.php?sec='.$sec.'&sec2=godmode/modules/manage_inventory_modules', $offset, 0, false, 'offset', true, 'pagination-bottom'); + echo "
"; + if ($management_allowed === true) { + html_print_submit_button(__('Delete'), 'delete_btn', false, 'class="sub delete"'); + } + + echo '
'; + echo ''; +} + +if ($management_allowed === true) { + echo '
'; + echo '
'; + html_print_input_hidden('create_module_inventory', 1); + html_print_submit_button(__('Create'), 'crt', false, 'class="sub next"'); + echo '
'; + echo '
'; +} + + +if (is_metaconsole() === true) { + enterprise_hook('close_meta_frame'); + echo ''; +} + +?> + diff --git a/pandora_console/godmode/modules/manage_inventory_modules_form.php b/pandora_console/godmode/modules/manage_inventory_modules_form.php new file mode 100644 index 0000000000..1d5f6a4f9a --- /dev/null +++ b/pandora_console/godmode/modules/manage_inventory_modules_form.php @@ -0,0 +1,153 @@ +width = '100%'; +$table->class = 'databox filters'; +$table->style = []; +$table->style[0] = 'font-weight: bold'; +$table->data = []; +$table->data[0][0] = ''.__('Name').''; +$table->data[0][1] = html_print_input_text('name', $name, '', 45, 100, true, $disabled); +$table->data[1][0] = ''.__('Description').''; +$table->data[1][1] = html_print_input_text('description', $description, '', 60, 500, true); +$table->data[2][0] = ''.__('OS').''; +$table->data[2][1] = html_print_select_from_sql( + 'SELECT id_os, name FROM tconfig_os ORDER BY name', + 'id_os', + $id_os, + '', + '', + '', + $return = true +); + +$table->data[3][0] = ''.__('Interpreter').''; +$table->data[3][1] = html_print_input_text('interpreter', $interpreter, '', 25, 100, true); +$table->data[3][1] .= ui_print_help_tip(__('Left blank for the LOCAL inventory modules'), true); + +$table->data['block_mode'][0] = ''.__('Block Mode').''; +$table->data['block_mode'][1] = html_print_checkbox('block_mode', 1, $block_mode, true); + +$table->data[4][0] = ''.__('Format').''; +$table->data[4][0] .= ui_print_help_tip(__('separate fields with ').SEPARATOR_COLUMN, true); +$table->data[4][1] = html_print_input_text('format', $data_format, '', 50, 100, true); + +$table->data[5][0] = ''.__('Code').''; +$table->data[5][0] .= ui_print_help_tip(__("Here is placed the script for the REMOTE inventory modules Local inventory modules don't use this field").SEPARATOR_COLUMN, true); + +$table->data[5][1] = html_print_textarea('code', 25, 80, base64_decode($code), '', true); + +echo '
'; + +html_print_table($table); +if ($id_module_inventory) { + html_print_input_hidden('update_module_inventory', 1); + html_print_input_hidden('id_module_inventory', $id_module_inventory); +} else { + html_print_input_hidden('create_module_inventory', 1); +} + +echo '
'; +if ($id_module_inventory) { + html_print_submit_button(__('Update'), 'submit', false, 'class="sub next"'); +} else { + html_print_submit_button(__('Create'), 'submit', false, 'class="sub upd"'); +} + +echo '
'; +echo '
'; + +if (defined('METACONSOLE')) { + enterprise_hook('close_meta_frame'); +} diff --git a/pandora_console/include/functions_inventory.php b/pandora_console/include/functions_inventory.php new file mode 100644 index 0000000000..2ac322a4fe --- /dev/null +++ b/pandora_console/include/functions_inventory.php @@ -0,0 +1,1147 @@ + 0) { + $data_row = db_get_row_sql( + 'SELECT data, timestamp + FROM tagente_datos_inventory + WHERE utimestamp <= '.$utimestamp.' + AND id_agent_module_inventory = '.$row['id_agent_module_inventory'].' ORDER BY utimestamp DESC' + ); + if ($data_row !== false) { + $row['data'] = $data_row['data']; + $row['timestamp'] = $data_row['timestamp']; + } + } + + if (!$order_by_agent) { + $agent_name = db_get_value('alias', 'tagente', 'id_agente', $row['id_agente']); + + $out_csv .= __('Agent alias').' --> '.io_safe_output($agent_name)."\n"; + $out_csv .= __('Timestamp').' = '.$row['timestamp']."\n"; + $out_csv .= io_safe_output($row['data_format'])."\n"; + + // Filter data by search string. + if ($inventory_search_string !== '') { + $str = io_safe_output($row['data']); + $matches = []; + $re = '/.*'.$inventory_search_string.'.*\n/m'; + if (preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0)) { + // Print the entire match result. + foreach ($matches as $match) { + $out_csv .= $match[0]; + } + + $out_csv .= "\n\n"; + } + } else { + $out_csv .= io_safe_output($row['data'])."\n\n"; + } + } else { + $agent_name = db_get_value('alias', 'tagente', 'id_agente', $row['id_agente']); + $agent_inventory_temp = []; + $agent_inventory[$agent_name][] = [ + 'name' => $row['name'], + 'data_formtat' => $row['data_format'], + 'data' => $row['data'], + ]; + } + } + + if ($order_by_agent) { + if (empty($agent_inventory) === false) { + foreach ($agent_inventory as $alias => $agent_data) { + $out_csv .= __('Agent alias').' --> '.io_safe_output($alias)."\n"; + $out_csv .= __('Timestamp').' = '.$row['timestamp']."\n"; + + foreach ($agent_data as $data) { + $out_csv .= io_safe_output($data['name'])."\n"; + $out_csv .= io_safe_output($data['data_format'])."\n"; + + // Filter data by search string. + if ($inventory_search_string !== '') { + $str = io_safe_output($data['data']); + $matches = []; + $re = '/.*'.$inventory_search_string.'.*\n/m'; + if (preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0)) { + // Print the entire match result. + foreach ($matches as $match) { + $out_csv .= $match[0]; + } + + $out_csv .= "\n\n"; + } + } else { + $out_csv .= io_safe_output($row['data'])."\n\n"; + } + } + } + } + } + } + + if ($export_csv) { + $name_file = 'inventory_'.md5( + $inventory_module_name.$utimestamp.$inventory_search_string + ).'.csv'; + file_put_contents( + $config['attachment_store'].'/'.$name_file, + $out_csv + ); + + echo "".__('Get CSV file').''; + return; + } else if ($return_mode === 'csv') { + return $out_csv; + } else if ($return_mode === 'hash') { + if ($utimestamp > 0) { + $timestamp = db_get_value_sql( + "SELECT timestamp + FROM tagente_datos_inventory + WHERE utimestamp = $utimestamp" + ); + } else { + $timestamp = db_get_value_sql( + 'SELECT timestamp + FROM tagente_datos_inventory + WHERE utimestamp = + (SELECT MAX(tagente_datos_inventory.utimestamp) + FROM tagente_datos_inventory, tmodule_inventory, + tagent_module_inventory + WHERE '.implode(' AND ', $where).' + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tagent_module_inventory.id_agent_module_inventory = tagente_datos_inventory.id_agent_module_inventory)' + ); + } + + $out_array = []; + foreach ($rows as $k => $row) { + $out_array[$k]['timestamp'] = $timestamp; + $out_array[$k]['id_module_inventory'] = $row['id_module_inventory']; + $out_array[$k]['id_os'] = $row['id_os']; + $out_array[$k]['name'] = io_safe_output($row['name']); + $out_array[$k]['description'] = io_safe_output($row['description']); + $out_array[$k]['interpreter'] = $row['interpreter']; + $out_array[$k]['id_agent_module_inventory'] = $row['id_agent_module_inventory']; + $out_array[$k]['id_agente'] = $row['id_agente']; + $agent_name = db_get_value('alias', 'tagente', 'id_agente', $row['id_agente']); + $out_array[$k]['agent_name'] = $agent_name; + $out_array[$k]['target'] = $row['target']; + $out_array[$k]['interval'] = $row['interval']; + $out_array[$k]['username'] = $row['username']; + + $items = explode(';', io_safe_output($row['data_format'])); + + $data = []; + if (empty($row['data']) === false) { + $data_rows = explode("\n", io_safe_output($row['data'])); + $data = []; + foreach ($data_rows as $data_row) { + $cells = explode(';', $data_row); + + $temp_row = []; + $i = 0; + foreach ($cells as $cell) { + $temp_row[$items[$i]] = $cell; + $i++; + } + + $data[] = $temp_row; + } + } + + $out_array[$k]['data'] = $data; + $out_array[$k]['timestamp'] = io_safe_output($row['timestamp']); + $out_array[$k]['flag'] = io_safe_output($row['flag']); + } + + return $out_array; + } else if ($return_mode === 'array') { + $out_array = []; + foreach ($rows as $k => $row) { + $out_array[$k]['id_module_inventory'] = $row['id_module_inventory']; + $out_array[$k]['id_os'] = $row['id_os']; + $out_array[$k]['name'] = io_safe_output($row['name']); + $out_array[$k]['description'] = io_safe_output($row['description']); + $out_array[$k]['interpreter'] = $row['interpreter']; + $out_array[$k]['data_format'] = $row['data_format']; + $out_array[$k]['id_agent_module_inventory'] = $row['id_agent_module_inventory']; + $out_array[$k]['id_agente'] = $row['id_agente']; + $out_array[$k]['target'] = $row['target']; + $out_array[$k]['interval'] = $row['interval']; + $out_array[$k]['username'] = $row['username']; + $out_array[$k]['data'] = ''; + $out_array[$k]['timestamp'] = io_safe_output($row['timestamp']); + $out_array[$k]['flag'] = io_safe_output($row['flag']); + } + + if (empty($out_array) === true) { + return __('No data found'); + } + + return $out_array; + } + + $idModuleInventory = null; + + $rowTable = 1; + + // Timestamp filter only allowed in nodes for performance. + if (is_metaconsole() === false) { + if ($utimestamp > 0) { + $timestamp = db_get_value_sql( + "SELECT timestamp + FROM tagente_datos_inventory + WHERE utimestamp = $utimestamp" + ); + } else { + $timestamp = db_get_value_sql( + 'SELECT timestamp + FROM tagente_datos_inventory + WHERE utimestamp = + (SELECT MAX(tagente_datos_inventory.utimestamp) + FROM tagente_datos_inventory, tmodule_inventory, + tagent_module_inventory + WHERE '.implode(' AND ', $where).' + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tagent_module_inventory.id_agent_module_inventory = tagente_datos_inventory.id_agent_module_inventory)' + ); + } + } + + // TODO: Workaround. + $timestamp = 'Last'; + if (!$order_by_agent) { + $countRows = 0; + foreach ($rows as $row) { + // Check for not show more elements that allowed in config. + if ($countRows >= (int) $config['meta_num_elements']) { + break; + } + + $countRows++; + + // Continue. + if (is_metaconsole() === false && $utimestamp > 0) { + $data_row = db_get_row_sql( + "SELECT data, timestamp + FROM tagente_datos_inventory + WHERE utimestamp <= '".$utimestamp."' + AND id_agent_module_inventory = ".$row['id_agent_module_inventory'].' ORDER BY utimestamp DESC' + ); + if ($data_row !== false) { + $row['data'] = $data_row['data']; + $row['timestamp'] = $data_row['timestamp']; + } else { + // Continue to next row in case there is no data for that timestamp. + continue; + } + } + + if ($idModuleInventory != $row['id_module_inventory']) { + if (isset($table) === true) { + $out .= "
"; + $out .= html_print_table($table, true); + $out .= '
'; + unset($table); + $rowTable = 1; + } + + $table = new stdClass(); + $table->width = '100%'; + $table->align = []; + $table->cellpadding = 0; + $table->cellspacing = 0; + $table->class = 'info_table inventory_tables'; + $table->head = []; + $table->head[0] = ''.$row['name'].' '.html_print_image('images/timestamp.png', true, ['title' => __('Timestamp'), 'style' => 'vertical-align:middle']).' ('.$timestamp.')'; + $table->headstyle[0] = 'text-align:center'; + + $subHeadTitles = explode(';', io_safe_output($row['data_format'])); + + $table->head_colspan = []; + $table->head_colspan[0] = (2 + count($subHeadTitles)); + $total_fields = count($subHeadTitles); + $table->rowspan = []; + + $table->data = []; + + $iterator = 1; + + $table->data[0][0] = __('Agent'); + foreach ($subHeadTitles as $titleData) { + $table->data[0][$iterator] = $titleData; + $iterator++; + } + + $table->data[0][] = __('Timestamp'); + $iterator++; + } + + // Setting for link the agent with the proper server. + if (is_metaconsole() === true && empty($node) === false) { + $loginHash = metaconsole_get_servers_url_hash($node); + $urlToAgent = sprintf( + '%sindex.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=%s%s', + $node['server_url'], + $row['id_agente'], + $loginHash + ); + } else { + $urlToAgent = sprintf( + 'index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=%s', + $row['id_agente'] + ); + } + + $agent_name = db_get_value_sql( + 'SELECT alias + FROM tagente + WHERE id_agente = '.$row['id_agente'] + ); + + $table->data[$rowTable][0] = html_print_anchor( + [ + 'href' => $urlToAgent, + 'content' => ''.$agent_name.'', + ], + true + ); + + $arrayDataRowsInventory = explode(SEPARATOR_ROW, io_safe_output($row['data'])); + // SPLIT DATA IN ROWS + // Remove the empty item caused by a line ending with a new line. + $len = count($arrayDataRowsInventory); + if (end($arrayDataRowsInventory) == '') { + $len--; + unset($arrayDataRowsInventory[$len]); + } + + $iterator1 = 0; + $numRowHasNameAgent = $rowTable; + + $rowPair = true; + $iterator = 0; + foreach ($arrayDataRowsInventory as $dataRowInventory) { + if ($rowPair === true) { + $table->rowclass[$iterator] = 'rowPair'; + } else { + $table->rowclass[$iterator] = 'rowOdd'; + } + + $rowPair = !$rowPair; + $iterator++; + + // Because SQL query extract all rows (row1;row2;row3...) and only I want the row has + // the search string. + if ($inventory_search_string && preg_match('/'.io_safe_output($inventory_search_string).'/', ($dataRowInventory)) == 0) { + continue; + } + + if ($rowTable > $numRowHasNameAgent) { + $table->data[$rowTable][0] = ''; + } + + $arrayDataColumnInventory = explode(SEPARATOR_COLUMN, $dataRowInventory); + // SPLIT ROW IN COLUMNS. + $iterator2 = 1; + + foreach ($arrayDataColumnInventory as $dataColumnInventory) { + $table->data[$rowTable][$iterator2] = $dataColumnInventory; + $iterator2++; + } + + // Fill unfilled cells with empty string. + $countArray = count($arrayDataColumnInventory); + for ($i = 0; $i < ($total_fields - $countArray); $i++) { + $table->data[$rowTable][$iterator2] = ''; + $iterator2++; + } + + $table->data[$rowTable][$iterator2] = $row['timestamp']; + + $iterator1++; + + $rowTable++; + if ($rowPair === true) { + $table->rowclass[$rowTable] = 'rowPair'; + } else { + $table->rowclass[$rowTable] = 'rowOdd'; + } + } + + if ($rowPair === true) { + $table->rowclass[$iterator] = 'rowPair'; + } else { + $table->rowclass[$iterator] = 'rowOdd'; + } + + $rowPair = !$rowPair; + if ($rowPair) { + $table->rowclass[($iterator + 1)] = 'rowPair'; + } else { + $table->rowclass[($iterator + 1)] = 'rowOdd'; + } + + if ($iterator1 > 5) { + // PRINT COUNT TOTAL. + $table->data[$rowTable][0] = ''; + $table->data[$rowTable][1] = ''.__('Total').': '.$iterator1; + $countSubHeadTitles = count($subHeadTitles); + for ($row_i = 2; $row_i <= $countSubHeadTitles; $row_i++) { + $table->data[$rowTable][$row_i] = ''; + } + + $rowTable++; + } + + $idModuleInventory = $row['id_module_inventory']; + } + } else { + $agent_data = []; + foreach ($rows as $row) { + $agent_data[$row['id_agente']][] = $row; + } + + foreach ($agent_data as $id_agent => $rows) { + $agent_name = db_get_value_sql( + 'SELECT alias + FROM tagente + WHERE id_agente = '.$id_agent + ); + + $out .= '
'; + $out .= '
'.$agent_name.'
'; + $out .= '
'; + + foreach ($rows as $row) { + if ($utimestamp > 0) { + $data_row = db_get_row_sql( + "SELECT data, timestamp + FROM tagente_datos_inventory + WHERE utimestamp <= '".$utimestamp."' + AND id_agent_module_inventory = ".$row['id_agent_module_inventory'].' ORDER BY utimestamp DESC' + ); + + if ($data_row !== false) { + $row['data'] = $data_row['data']; + $row['timestamp'] = $data_row['timestamp']; + } else { + continue; + } + } + + $table = new stdClass(); + $table->colspan = []; + if ($idModuleInventory != $row['id_module_inventory']) { + $table->width = '98%'; + $table->align = []; + $table->styleTable = 'margin:0 auto; text-align:left;'; + $table->cellpadding = 0; + $table->cellspacing = 0; + $table->class = 'databox data'; + $table->head = []; + $table->head[0] = $row['name'].' - ('.$timestamp.')'; + $table->headstyle[0] = 'text-align:center'; + + $subHeadTitles = explode(';', io_safe_output($row['data_format'])); + + $table->head_colspan = []; + $table->head_colspan[0] = (2 + count($subHeadTitles)); + $total_fields = count($subHeadTitles); + $table->rowspan = []; + + $table->data = []; + + $iterator = 0; + + foreach ($subHeadTitles as $titleData) { + $table->data[0][$iterator] = $titleData; + $iterator++; + } + + $table->data[0][] = __('Timestamp'); + $iterator++; + } + + $rowTable = 1; + + $arrayDataRowsInventory = explode(SEPARATOR_ROW, io_safe_output($row['data'])); + // SPLIT DATA IN ROWS + // Remove the empty item caused by a line ending with a new line. + $len = count($arrayDataRowsInventory); + if (end($arrayDataRowsInventory) == '') { + $len--; + unset($arrayDataRowsInventory[$len]); + } + + $iterator1 = 0; + $rowPair = true; + + foreach ($arrayDataRowsInventory as $dataRowInventory) { + if ($rowPair === true) { + $table->rowclass[$iterator] = 'rowPair'; + } else { + $table->rowclass[$iterator] = 'rowOdd'; + } + + $rowPair = !$rowPair; + $iterator++; + + // Because SQL query extract all rows (row1;row2;row3...) and only I want the row has + // the search string. + if ($inventory_search_string && preg_match('/'.io_safe_output($inventory_search_string).'/', ($dataRowInventory)) == 0) { + continue; + } + + if ($rowTable > $numRowHasNameAgent) { + $table->data[$rowTable][0] = ''; + } + + $arrayDataColumnInventory = explode(SEPARATOR_COLUMN, $dataRowInventory); + // SPLIT ROW IN COLUMNS. + $iterator2 = 0; + + foreach ($arrayDataColumnInventory as $dataColumnInventory) { + $table->data[$rowTable][$iterator2] = $dataColumnInventory; + $iterator2++; + } + + // Fill unfilled cells with empty string. + $countArrayDataColumnInventory = count($arrayDataColumnInventory); + for ($i = 0; $i < ($total_fields - $countArrayDataColumnInventory); $i++) { + $table->data[$rowTable][$iterator2] = ''; + $iterator2++; + } + + $table->data[$rowTable][$iterator2] = $row['timestamp']; + + $iterator1++; + + $rowTable++; + if ($rowPair === true) { + $table->rowclass[$rowTable] = 'rowPair'; + } else { + $table->rowclass[$rowTable] = 'rowOdd'; + } + } + + if ($iterator1 > 5) { + // PRINT COUNT TOTAL. + $table->data[$rowTable][0] = ''; + $table->data[$rowTable][1] = ''.__('Total').': '.$iterator1; + $countSubHeadTitles = count($subHeadTitles); + for ($row_i = 2; $row_i <= $countSubHeadTitles; $row_i++) { + $table->data[$rowTable][$row_i] = ''; + } + + $rowTable++; + } + + $idModuleInventory = $row['id_module_inventory']; + + if (isset($table) === true) { + $out .= html_print_table($table, true); + } + + $out .= '
'; + } + + $out .= '
'; + $out .= '
'; + $out .= '
'; + $out .= '
'; + } + + return $out; + } + + if (isset($table) === true) { + $out .= html_print_table($table, true); + $out .= ui_pagination($count, $url, $offset, 0, true); + } + + return $out; +} + + +function inventory_get_dates($module_inventory_name, $inventory_agent, $inventory_id_group) +{ + $sql = 'SELECT tagente_datos_inventory.utimestamp, + tagente_datos_inventory.timestamp + FROM tmodule_inventory, tagent_module_inventory, + tagente_datos_inventory, tagente + WHERE + tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tagente_datos_inventory.id_agent_module_inventory = tagent_module_inventory.id_agent_module_inventory + AND tagente.id_agente = tagent_module_inventory.id_agente'; + + if ($inventory_agent != 0) { + $sql .= ' AND tagent_module_inventory.id_agente IN ('."'".implode(',', (array) $inventory_agent)."'".')'; + } + + if ($inventory_id_group != 0) { + $sql .= " AND tagente.id_grupo = $inventory_id_group"; + } + + if (is_string($module_inventory_name) === true + && $module_inventory_name != 'all' + ) { + $sql .= " AND tmodule_inventory.name IN ('".str_replace(',', "','", $module_inventory_name)."')"; + } + + $sql .= ' ORDER BY tagente_datos_inventory.utimestamp DESC'; + + $dates_raw = db_get_all_rows_sql($sql); + + if ($dates_raw == false) { + return []; + } + + $dates = []; + foreach ($dates_raw as $date) { + $dates[$date['utimestamp']] = $date['timestamp']; + } + + return $dates; +} + + +function inventory_get_agents($filter=false, $fields=false) +{ + $inventory_agents_id = db_get_all_rows_sql( + 'SELECT DISTINCT(id_agente) + FROM tagent_module_inventory' + ); + + if ($inventory_agents_id == false) { + $inventory_agents_id = []; + return []; + } + + $ids = []; + foreach ($inventory_agents_id as $ia) { + $ids[] = $ia['id_agente']; + } + + $filter['id_agente'] = $ids; + + $agents = agents_get_agents($filter, $fields); + + if ($agents === false) { + $agents = []; + } + + return $agents; +} + + +function inventory_get_changes( + $id_agent, + $module_names, + $start_utimestamp, + $end_utimestamp, + $return_mode=false +) { + global $config; + + $any_inventory_modules = false; + if (empty($module_names)) { + $any_inventory_modules = true; + } else if (((string) ($module_names[0])) === '0') { + $any_inventory_modules = true; + } + + $module_names = (array) $module_names; + + if ($id_agent[0] == -1) { + // Any agent + $sql = sprintf( + "SELECT evento, utimestamp + FROM tevento + WHERE utimestamp >= %d + AND utimestamp <= %d + AND event_type = 'configuration_change'", + $start_utimestamp, + $end_utimestamp + ); + } else { + $sql = sprintf( + "SELECT evento, utimestamp + FROM tevento + WHERE id_agente IN (%s) + AND utimestamp >= %d + AND utimestamp <= %d + AND event_type = 'configuration_change'", + implode(',', (array) $id_agent), + $start_utimestamp, + $end_utimestamp + ); + } + + $events = db_get_all_rows_sql($sql); + + if ($events === false) { + return ERR_NODATA; + } + + $inventory_changes = []; + $are_data = false; + + foreach ($events as $k => $event) { + $changes = io_safe_output($event['evento']); + $changes = explode("\n", $changes); + + $check = preg_match( + '/agent \'(.*)\' module \'(.*)\'/', + end($changes), + $matches + ); + + $agent_name = $matches[1]; + $module_name = $matches[2]; + + if (!$any_inventory_modules) { + if (!in_array($module_name, $module_names)) { + continue; + } + } + + $are_data = true; + + $inventory_changes[$k]['agent_name'] = $matches[1]; + $inventory_changes[$k]['module_name'] = $module_name; + $inventory_changes[$k]['utimestamp'] = $event['utimestamp']; + $changes[0] = str_replace('Configuration changes (', '', $changes[0]); + + unset($changes[(count($changes) - 1)]); + $state = ''; + foreach ($changes as $ch) { + if (preg_match('/NEW RECORD: (.*)/', $ch)) { + $ch = preg_replace('/NEW RECORD: /', '', $ch); + $ch = preg_replace('/^\'/', '', $ch); + $ch = '
'.$ch.'
'; + $state = 'new'; + } + + if (preg_match('/\s*DELETED RECORD: (.*)/', $ch)) { + $ch = preg_replace('/\s*DELETED RECORD/', '', $ch); + $ch = preg_replace('/^\'/', '', $ch); + $ch = '
'.$ch.'
'; + $state = 'deleted'; + } + + $inventory_changes[$k][$state][] = $ch; + } + } + + if ($are_data === false) { + if ($return_mode !== false) { + switch ($return_mode) { + case 'array': + return ERR_NODATA; + + break; + default: + return __('No changes found'); + break; + } + } + + return ERR_NODATA; + } + + switch ($return_mode) { + case 'csv': + $out_csv = ''; + foreach ($inventory_changes as $ic) { + $out_csv .= __('Agent').SEPARATOR_COLUMN_CSV.$ic['agent_name']."\n"; + $out_csv .= __('Module').SEPARATOR_COLUMN_CSV.$ic['module_name']."\n"; + $out_csv .= __('Date').SEPARATOR_COLUMN_CSV.date($config['date_format'], $ic['utimestamp'])."\n"; + if (isset($ic['new'])) { + foreach ($ic['new'] as $icc) { + $out_csv .= __('Added').SEPARATOR_COLUMN_CSV.$icc."\n"; + } + } + + if (isset($ic['deleted'])) { + foreach ($ic['deleted'] as $icc) { + $out_csv .= __('Deleted').SEPARATOR_COLUMN_CSV.$icc."\n"; + } + } + } + return $out_csv; + + break; + case 'array': + $out_array = []; + + foreach ($inventory_changes as $k => $ic) { + $out_array[$k]['agent'] = $ic['agent_name']; + $out_array[$k]['module'] = $ic['module_name']; + $out_array[$k]['date'] = date($config['date_format'], $ic['utimestamp']); + + if (isset($ic['new'])) { + foreach ($ic['new'] as $icc) { + $out_array[$k]['added'][] = $icc; + } + } + + if (isset($ic['deleted'])) { + foreach ($ic['deleted'] as $icc) { + $out_array[$k]['deleted'][] = $icc; + } + } + } + + if (empty($out_array)) { + return ERR_NODATA; + } + return $out_array; + + break; + } + + $out = ''; + foreach ($inventory_changes as $ic) { + $out .= ''; + } + + $out .= '
'; + + unset($table); + $table->width = '98%'; + $table->style[0] = 'text-align:50%'; + $table->style[1] = 'text-align:50%'; + + $table->data[0][0] = ''.__('Agent').': '.$ic['agent_name']; + $table->data[0][1] = ''.__('Module').': '.$ic['module_name']; + + $timestamp = date($config['date_format'], $ic['utimestamp']); + + $table->colspan[1][0] = 2; + $table->data[1][0] = '
('.$timestamp.')
'; + $row = 2; + + if (isset($ic['new'])) { + foreach ($ic['new'] as $icc) { + $table->colspan[$row][0] = 2; + $table->data[$row][0] = ''.__('Added').': '.$icc; + $row++; + } + } + + if (isset($ic['deleted'])) { + foreach ($ic['deleted'] as $icc) { + $table->colspan[$row][0] = 2; + $table->data[$row][0] = ''.__('Deleted').': '.$icc; + $row++; + } + } + + $out .= html_print_table($table, true); + + $out .= '
'; + + return $out; +} + + +/** + * Get a list with inventory modules + * + * @param mixed An integer can be place here to get a response + * to paginate. If this parameter is false, return full list + * + * @return array with inventory modules (paginated or not) + */ +function inventory_get_modules_list($offset=false) +{ + global $config; + + $filter = []; + if (is_numeric($offset)) { + $filter['limit'] = $config['block_size']; + $filter['offset'] = $offset; + } + + return db_get_all_rows_filter( + 'tmodule_inventory LEFT JOIN tconfig_os + ON tmodule_inventory.id_os = tconfig_os.id_os', + $filter, + [ + 'tmodule_inventory.id_module_inventory', + 'tmodule_inventory.name', + 'tmodule_inventory.description', + 'tmodule_inventory.interpreter', + 'tconfig_os.name AS os_name', + 'tconfig_os.id_os', + ] + ); +} + + +/** + * Validate the modules inventory + * + * @param array with inventory modules data. + * + * @return boolean True if the values are valid + */ +function inventory_validate_inventory_module($values) +{ + return !(empty($values['name']) || empty($values['id_os']) || + empty($values['data_format']) + ); +} + + +/** + * Insert the module inventory data into database + * + * @param array with inventory modules data. + * + * @return boolean False if values are invalid or cannot put it on database + */ +function inventory_create_inventory_module($values) +{ + if (!inventory_validate_inventory_module($values)) { + return false; + } + + return db_process_sql_insert('tmodule_inventory', $values); +} + + +/** + * Update the module inventory data into database + * + * @param int ID inventory module + * @param array with inventory modules data. + * + * @return boolean False if values are invalid or cannot put it on database + */ +function inventory_update_inventory_module($id_module_inventory, $values) +{ + if (!inventory_validate_inventory_module($values)) { + return false; + } + + return db_process_sql_update( + 'tmodule_inventory', + $values, + ['id_module_inventory' => $id_module_inventory] + ); +} + + +/** + * Returns inventory module names given agent id. + * + * @param integer $id_agent + * @param string $all + * @param integer $server_id + * @param string $server_name + * @return void + */ +function inventory_get_agent_modules($id_agent, $all='all', $server_id=0, $server_name=null) +{ + global $config; + + if ($config['metaconsole']) { + $server_id = metaconsole_get_id_server($server_name); + } + + switch ($all) { + default: + case 'all': + $enabled = '1 = 1'; + break; + case 'enabled': + $enabled = 'disabled = 0'; + break; + } + + if (is_array($id_agent)) { + $count_id_agent = count(($id_agent)); + $id_agent = implode(',', $id_agent); + } else { + $count_id_agent = 1; + } + + $sql = 'SELECT t1.id_module_inventory, name + FROM tmodule_inventory t1, tagent_module_inventory t2 + WHERE t1.id_module_inventory = t2.id_module_inventory + AND id_agente IN ('.$id_agent.') AND ( + SELECT count(name) + FROM tmodule_inventory t3, tagent_module_inventory t4 + WHERE t3.id_module_inventory = t4.id_module_inventory + AND t3.name = t1.name + AND t4.id_agente IN ('.$id_agent.')) = ('.$count_id_agent.') + ORDER BY name'; + + // Only in template editor from metaconsole. + if ($config['metaconsole']) { + $server_data = metaconsole_get_connection_by_id($server_id); + + if ($server_data === false) { + return ''; + } + + $modules = []; + + // Establishes connection. + if (metaconsole_load_external_db($server_data) !== NOERR) { + return ''; + } + + $modules = db_get_all_rows_sql($sql); + + if ($modules == false) { + $modules = []; + } + + $result = []; + foreach ($modules as $module) { + $result[$module['name']] = io_safe_output($module['name']); + } + + // Restore DB connection. + metaconsole_restore_db(); + } else { + $modules = db_get_all_rows_sql($sql); + + if ($modules == false) { + $modules = []; + } + + $result = []; + foreach ($modules as $module) { + $result[$module['name']] = io_safe_output($module['name']); + } + } + + return $result; +} diff --git a/pandora_console/include/functions_menu.php b/pandora_console/include/functions_menu.php index d9c86aa66a..a2e8356e3a 100644 --- a/pandora_console/include/functions_menu.php +++ b/pandora_console/include/functions_menu.php @@ -487,7 +487,7 @@ function menu_add_extras(&$menu) $menu_extra['gusuarios']['sub']['godmode/users/configure_profile']['text'] = __('Configure profile'); $menu_extra['gmodules']['sub']['godmode/modules/manage_network_templates_form']['text'] = __('Module templates management'); - $menu_extra['gmodules']['sub']['enterprise/godmode/modules/manage_inventory_modules_form']['text'] = __('Inventory modules management'); + $menu_extra['gmodules']['sub']['godmode/modules/manage_inventory_modules_form']['text'] = __('Inventory modules management'); $menu_extra['gagente']['sub']['godmode/agentes/configurar_agente']['text'] = __('Agents management'); diff --git a/pandora_console/include/functions_planned_downtimes.php b/pandora_console/include/functions_planned_downtimes.php index e8c4344c05..38ee77a422 100644 --- a/pandora_console/include/functions_planned_downtimes.php +++ b/pandora_console/include/functions_planned_downtimes.php @@ -24,7 +24,8 @@ global $config; * Include the usual functions */ require_once $config['homedir'].'/include/functions_ui.php'; -// enterprise_include_once('include/functions_inventory.php'); + + function planned_downtimes_check_dates($type_execution='once', $type_periodicity='', $datetime_from=false, $datetime_to=false, $periodically_time_from=false, $periodically_time_to=false, $periodically_day_from=false, $periodically_day_to=false) { global $config; diff --git a/pandora_console/include/functions_reporting_html.php b/pandora_console/include/functions_reporting_html.php index 03070811cf..3a1861b48b 100644 --- a/pandora_console/include/functions_reporting_html.php +++ b/pandora_console/include/functions_reporting_html.php @@ -38,6 +38,7 @@ require_once $config['homedir'].'/include/functions_alerts.php'; require_once $config['homedir'].'/include/functions_users.php'; enterprise_include_once('include/functions_metaconsole.php'); enterprise_include_once('include/functions_inventory.php'); +require_once $config['homedir'].'/include/functions_inventory.php'; require_once $config['homedir'].'/include/functions_forecast.php'; require_once $config['homedir'].'/include/functions_ui.php'; require_once $config['homedir'].'/include/functions_netflow.php'; diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index d30171eba3..7ecc5763ff 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -6783,3 +6783,259 @@ function ui_print_spinner(string $text='Loading', bool $return=false) echo $output; } } + + +function ui_get_inventory_module_add_form( + $form_action, + $form_buttons='', + $inventory_module_id=0, + $os_id=false, + $target=false, + $interval=3600, + $username='', + $password='', + $custom_fields_enabled=false, + $custom_fields=[] +) { + $table = new stdClass(); + $table->id = 'inventory-module-form'; + $table->width = '100%'; + $table->class = 'databox filters'; + $table->style['module-title'] = 'font-weight: bold;'; + $table->style['interval-title'] = 'font-weight: bold;'; + $table->style['target-title'] = 'font-weight: bold;'; + $table->style['chkbx-custom-fields-title'] = 'font-weight: bold;'; + $table->style['username-title'] = 'font-weight: bold;'; + $table->style['password-title'] = 'font-weight: bold;'; + $table->rowstyle = []; + $table->rowstyle['hidden-custom-field-row'] = 'display: none;'; + $table->colspan = []; + $table->colspan['custom-fields-row'] = []; + $table->colspan['custom-fields-row']['custom-fields-column'] = 4; + $table->data = []; + + $row = []; + $row['module-title'] = __('Module'); + if (empty($inventory_module_id)) { + if (empty($os_id)) { + $sql = 'SELECT mi.id_module_inventory AS id, mi.name AS name, co.name AS os + FROM tmodule_inventory mi, tconfig_os co + WHERE co.id_os = mi.id_os + ORDER BY co.name, mi.name'; + $inventory_modules_raw = db_get_all_rows_sql($sql); + + $inventory_modules = []; + foreach ($inventory_modules_raw as $im) { + $inventory_modules[$im['id']] = [ + 'name' => $im['name'], + 'optgroup' => $im['os'], + ]; + } + } else { + $sql = sprintf( + 'SELECT id_module_inventory AS id, name + FROM tmodule_inventory + WHERE id_os = %d + ORDER BY name', + $os_id + ); + $inventory_modules_raw = db_get_all_rows_sql($sql); + + $inventory_modules = []; + foreach ($inventory_modules_raw as $im) { + $inventory_modules[$im['id']] = $im['name']; + } + } + + $row['module-input'] = html_print_select($inventory_modules, 'id_module_inventory', 0, '', __('Select inventory module'), 0, true, false, false); + } else { + $row['module-input'] = db_get_sql('SELECT name FROM tmodule_inventory WHERE id_module_inventory = '.$inventory_module_id); + } + + $row['interval-title'] = __('Interval'); + $row['interval-input'] = html_print_extended_select_for_time('interval', $interval, '', '', '', false, true); + + $table->data['first-row'] = $row; + + $row = []; + + if ($target !== false) { + $row['target-title'] = __('Target'); + $row['target-input'] = html_print_input_text('target', $target, '', 25, 40, true); + } + + $row['chkbx-custom-fields-title'] = __('Use custom fields'); + $row['chkbx-custom-fields-input'] = html_print_checkbox('custom_fields_enabled', 1, $custom_fields_enabled, true); + + $table->data['second-row'] = $row; + + $row = []; + $row['username-title'] = __('Username'); + $row['username-input'] = html_print_input_text('username', $username, '', 25, 40, true); + $row['password-title'] = __('Password'); + $row['password-input'] = html_print_input_password('password', $password, '', 25, 40, true); + + $table->data['userpass-row'] = $row; + + $row = []; + $row['hidden-title'] = ''; + $row['hidden-input'] = html_print_input_hidden('hidden-custom-field-name', '', true); + $row['hidden-input'] .= html_print_input_hidden('hidden-custom-field-is-secure', 0, true); + $row['hidden-input'] .= html_print_input_text('hidden-custom-field-input', '', '', 25, 40, true); + $row['hidden-input'] .= ' '; + $row['hidden-input'] .= html_print_image( + 'images/cross.png', + true, + [ + 'border' => '0', + 'title' => __('Remove'), + 'style' => 'cursor: pointer;', + 'class' => 'remove-custom-field invert_filter', + ] + ); + + $table->data['hidden-custom-field-row'] = $row; + + if ($custom_fields_enabled) { + foreach ($custom_fields as $i => $field) { + $row = []; + $row['title'] = ''.$field['name'].''; + $row['input'] = html_print_input_hidden( + 'custom_fields['.$i.'][name]', + $field['name'], + true + ); + $row['input'] .= html_print_input_hidden( + 'custom_fields['.$i.'][secure]', + $field['secure'], + true + ); + if ($field['secure']) { + $row['input'] .= html_print_input_password( + 'custom_fields['.$i.'][value]', + $field['value'], + '', + 25, + 40, + true + ); + } else { + $row['input'] .= html_print_input_text( + 'custom_fields['.$i.'][value]', + $field['value'], + '', + 25, + 40, + true + ); + } + + $row['input'] .= ' '; + $row['input'] .= html_print_image( + 'images/cross.png', + true, + [ + 'border' => '0', + 'title' => __('Remove'), + 'style' => 'cursor: pointer;', + 'class' => 'remove-custom-field invert_filter', + ] + ); + + $table->data['custom-field-row-'.$i] = $row; + } + } + + $row = []; + $row['custom-fields-column'] = ''.__('Field name').''.'  '.html_print_input_text('field-name', '', '', 25, 40, true).'   '.html_print_checkbox('field-is-password', 1, false, true).__("It's a password").'   '.html_print_button(__('Add field'), 'add-field', false, '', 'class="sub add"', true); + + $table->data['custom-fields-row'] = $row; + + ob_start(); + + echo '
'; + echo html_print_table($table); + echo '
'; + echo $form_buttons; + echo '
'; + echo '
'; + + ?> + + + width = '100%'; +$table->class = 'databox filters'; +$table->size = []; +$table->data = []; + +$table->data[0][0] = __('Module'); +$table->data[0][1] = html_print_select_from_sql( + $sqlModuleInventoryAgentView, + 'module_inventory_agent_view', + $module, + 'javascript:this.form.submit();', + __('All'), + 0, + true +); + +$table->data[0][2] = __('Date'); +$table->data[0][3] = html_print_select( + $utimestampSelectValues, + 'utimestamp', + $utimestamp, + 'javascript:this.form.submit();', + __('Now'), + 0, + true +); + +$table->data[0][4] = __('Search'); +$table->data[0][5] = html_print_input_text('search_string', $search_string, '', 25, 0, true); +$table->data[0][6] = html_print_submit_button(__('Search'), 'search_button', false, 'class="sub wand"', true); + +// Show filters table. +echo sprintf( + '
%s
', + $id_agente, + html_print_table($table, true) +); + +unset($table); + +$idModuleInventory = null; +$rowTable = 1; +$printedTables = 0; + +// Inventory module data. +foreach ($rows as $row) { + if ($utimestamp > 0) { + $data_row = db_get_row_sql( + "SELECT data, timestamp + FROM tagente_datos_inventory + WHERE utimestamp <= '".$utimestamp."' + AND id_agent_module_inventory = ".$row['id_agent_module_inventory'].' + ORDER BY utimestamp DESC' + ); + if ($data_row !== false) { + $row['data'] = $data_row['data']; + $row['timestamp'] = $data_row['timestamp']; + } + } + + if ($idModuleInventory != $row['id_module_inventory']) { + if (isset($table) === true && $rowTable > 1) { + html_print_table($table); + unset($table); + $rowTable = 1; + $printedTables++; + } + + $table = new StdClass(); + $table->width = '98%'; + $table->align = []; + $table->cellpadding = 4; + $table->cellspacing = 4; + $table->class = 'databox filters'; + $table->head = []; + $table->head[0] = $row['name'].' - ('.date($config['date_format'], $row['utimestamp']).')'; + + if ((bool) $row['block_mode'] === true) { + $table->head[0] .= '   '.html_print_image( + 'images/op_inventory.menu.png', + true, + [ + 'alt' => __('Diff view'), + 'title' => __('Diff view'), + 'style' => 'vertical-align: middle; opacity: 0.8;', + ] + ).''; + } + + $subHeadTitles = explode(';', io_safe_output($row['data_format'])); + + $table->head_colspan = []; + $table->head_colspan[0] = (1 + count($subHeadTitles)); + $total_fields = count($subHeadTitles); + $table->rowspan = []; + + $table->data = []; + + $iterator = 0; + + foreach ($subHeadTitles as $titleData) { + $table->data[0][$iterator] = $titleData; + $table->cellstyle[0][$iterator] = 'background: #373737; color: #FFF;'; + + $iterator++; + } + } + + if ($row['block_mode']) { + $rowTable++; + $table->data[$rowTable][0] = '
'.$row['data'].'
'; + } else { + $arrayDataRowsInventory = explode(SEPARATOR_ROW, io_safe_output($row['data'])); + // SPLIT DATA IN ROWS + // Remove the empty item caused by a line ending with a new line. + $len = count($arrayDataRowsInventory); + if (end($arrayDataRowsInventory) == '') { + $len--; + unset($arrayDataRowsInventory[$len]); + } + + $iterator1 = 0; + $numRowHasNameAgent = $rowTable; + + $rowPair = true; + $iterator = 0; + foreach ($arrayDataRowsInventory as $dataRowInventory) { + $table->rowclass[$iterator] = ($rowPair === true) ? 'rowPair' : 'rowOdd'; + $rowPair = !$rowPair; + $iterator++; + + // Because SQL query extract all rows (row1;row2;row3...) and only I want the row has + // the search string. + if ($search_string && preg_match('/'.io_safe_output($search_string).'/i', io_safe_output($dataRowInventory)) == 0) { + continue; + } + + if ($rowTable > $numRowHasNameAgent) { + $table->data[$rowTable][0] = ''; + } + + $arrayDataColumnInventory = explode(SEPARATOR_COLUMN, $dataRowInventory); + // SPLIT ROW IN COLUMNS. + $iterator2 = 0; + foreach ($arrayDataColumnInventory as $dataColumnInventory) { + $table->data[$rowTable][$iterator2] = $dataColumnInventory; + $iterator2++; + } + + $iterator1++; + $rowTable++; + } + + if ($iterator1 > 5) { + // PRINT COUNT TOTAL. + $table->data[$rowTable][0] = ''.__('Total').': '.$iterator1; + $rowTable++; + } + } + + $idModuleInventory = $row['id_module_inventory']; +} + +if (isset($table) === true && $rowTable > 1) { + html_print_table($table); + $printedTables++; +} + +if ($printedTables === 0) { + echo "
".__('No data found.').'
'; +} diff --git a/pandora_console/operation/agentes/ver_agente.php b/pandora_console/operation/agentes/ver_agente.php index 3c4eebb991..c728cdc773 100644 --- a/pandora_console/operation/agentes/ver_agente.php +++ b/pandora_console/operation/agentes/ver_agente.php @@ -1437,8 +1437,20 @@ if ($tab === 'alert') { // Inventory. $inventoryCount = db_get_num_rows('SELECT id_agent_module_inventory FROM tagent_module_inventory WHERE id_agente = '.$agent['id_agente']); -$inventorytab = enterprise_hook('inventory_tab'); -if ($inventorytab == -1 || $inventoryCount === 0) { +$inventorytab['text'] = ''.html_print_image( + 'images/page_white_text.png', + true, + [ + 'class' => 'invert_filter', + 'title' => __('Inventory'), + ] +).''; + +if ($tab == 'inventory') { + $inventorytab['active'] = true; +} else { + $inventorytab['active'] = false; +}if ($inventorytab == -1 || $inventoryCount === 0) { $inventorytab = ''; } @@ -1968,7 +1980,7 @@ switch ($tab) { break; case 'inventory': - enterprise_include('operation/agentes/agent_inventory.php'); + include 'operation/agentes/agent_inventory.php'; break; case 'collection': diff --git a/pandora_console/operation/inventory/inventory.php b/pandora_console/operation/inventory/inventory.php new file mode 100755 index 0000000000..0a1cd508bd --- /dev/null +++ b/pandora_console/operation/inventory/inventory.php @@ -0,0 +1,551 @@ + 0) { + $sql .= ' WHERE id_grupo = '.$inventory_id_group; + } else { + $user_groups = implode(',', array_keys(users_get_groups($config['id_user']))); + + // Avoid errors if there are no groups. + if (empty($user_groups) === true) { + $user_groups = '"0"'; + } + + $sql .= ' WHERE id_grupo IN ('.$user_groups.')'; + } + + $result = db_get_all_rows_sql($sql); + if ($result !== false) { + foreach ($result as $row) { + $agents[$row['id_agente']] = $row['nombre']; + } + } + + $agents_select = $agents; + + if (strlen($inventory_agent) == 0) { + $inventory_id_agent = -1; + $inventory_agent = __('All'); + } else if ($inventory_agent == __('All')) { + $inventory_id_agent = 0; + } else { + $sql = 'SELECT id_agente + FROM tagente + WHERE nombre LIKE "'.$inventory_agent.'"'; + + $result = db_get_all_rows_sql($sql); + $inventory_id_agent = $result[0]['id_agente']; + } + + // Single agent selected. + if ($inventory_id_agent > 0 && isset($agents[$inventory_id_agent]) === true) { + $agents = [$inventory_id_agent => $agents[$inventory_id_agent]]; + } + + $agents_ids = array_keys($agents); + if (count($agents_ids) > 0) { + $inventory_data = inventory_get_data( + $agents_ids, + $inventory_module, + $utimestamp, + $inventory_search_string, + $export, + false, + $order_by_agent + ); + + if ((int) $inventory_data === ERR_NODATA) { + $inventory_data = ''; + } + } + + return; + } + + return; +} + +global $config; + +check_login(); + + +$is_metaconsole = is_metaconsole(); + +if ($is_metaconsole === true) { + open_meta_frame(); +} + +if (! check_acl($config['id_user'], 0, 'AR') && ! check_acl($config['id_user'], 0, 'AW')) { + db_pandora_audit( + AUDIT_LOG_ACL_VIOLATION, + 'Trying to access Inventory' + ); + include 'general/noaccess.php'; + return; +} + +require_once $config['homedir'].'/include/functions_users.php'; +require_once $config['homedir'].'/include/functions_inventory.php'; + +// Header. +ui_print_standard_header( + __('Inventory'), + 'images/op_inventory.png', + false, + '', + false, + [], + [ + [ + 'link' => '', + 'label' => __('Monitoring'), + ], + ] +); + +$inventory_id_agent = (int) get_parameter('agent_id', -1); +$inventory_agent = (string) get_parameter('agent', ''); +if (strlen($inventory_agent) == 0) { + $inventory_id_agent = -1; + $inventory_agent = __('All'); +} else if ($inventory_agent == __('All')) { + $inventory_id_agent = 0; +} + +$inventory_module = get_parameter('module_inventory_general_view'); +$inventory_id_group = (int) get_parameter('id_group'); +$inventory_search_string = (string) get_parameter('search_string'); +$order_by_agent = (bool) get_parameter('order_by_agent'); +$export = (string) get_parameter('export'); +$utimestamp = (int) get_parameter('utimestamp'); +$submit_filter = (bool) get_parameter('submit_filter'); + +$pagination_url_parameters = [ + 'inventory_id_agent' => $inventory_id_agent, + 'inventory_agent' => $inventory_agent, + 'inventory_id_group' => $inventory_id_group, +]; + +$noFilterSelected = false; +// Get variables. +if ($is_metaconsole === true) { + $nodes_connection = metaconsole_get_connections(); + $id_server = (int) get_parameter('id_server', 0); + $pagination_url_parameters['id_server'] = $id_server; + + if ($inventory_id_agent > 0) { + $inventory_id_server = (int) get_parameter('id_server_agent', -1); + $pagination_url_parameters['inventory_id_server'] = $inventory_id_server; + + if ($inventory_id_server !== -1) { + $id_server = $inventory_id_server; + $pagination_url_parameters['id_server'] = $id_server; + } + } + + // No filter selected. + $noFilterSelected = $inventory_id_agent === -1 && $inventory_id_group === 0 && $id_server === 0; +} + +if ($is_metaconsole === true) { + if ($id_server > 0) { + $connection = metaconsole_get_connection_by_id($id_server); + $agents_node = metaconsole_get_agents_servers($connection['server_name'], $inventory_id_group); + $node = metaconsole_get_servers($id_server); + + if (metaconsole_connect($connection) !== NOERR) { + ui_print_error_message( + __('There was a problem connecting with the node') + ); + } + + $sql = 'SELECT DISTINCT name as indexname, name + FROM tmodule_inventory, tagent_module_inventory + WHERE tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory'; + if ($inventory_id_agent > 0) { + $sql .= ' AND id_agente = '.$inventory_id_agent; + } + + $result_module = db_get_all_rows_sql($sql); + if ($submit_filter === true) { + $inventory_data .= inventory_get_data( + array_keys($agents_node), + $inventory_module, + $utimestamp, + $inventory_search_string, + $export, + false, + $order_by_agent, + $node, + $pagination_url_parameters + ); + } + + // Restore db connection. + metaconsole_restore_db(); + } else { + $result_module = []; + foreach ($nodes_connection as $key => $server) { + $agents_node = metaconsole_get_agents_servers($server['server_name'], $inventory_id_group); + $connection = metaconsole_get_connection($server['server_name']); + if (metaconsole_connect($connection) !== NOERR) { + continue; + } + + $sql = 'SELECT DISTINCT name as indexname, name + FROM tmodule_inventory, tagent_module_inventory + WHERE tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory'; + if ($inventory_id_agent > 0) { + $sql .= ' AND id_agente = '.$inventory_id_agent; + } + + $result = db_get_all_rows_sql($sql); + + if ($result !== false) { + $result_module = array_merge($result_module, $result); + if ($submit_filter === true) { + // Get the data. + $result_data = inventory_get_data( + array_keys($agents_node), + $inventory_module, + $utimestamp, + $inventory_search_string, + $export, + false, + $order_by_agent, + $server, + $pagination_url_parameters + ); + if ($result_data !== ERR_NODATA) { + $inventory_data .= $result_data; + } + } + } + + // Restore db connection. + metaconsole_restore_db(); + } + } + + $fields = []; + foreach ($result_module as $row) { + $id = array_shift($row); + $value = array_shift($row); + $fields[$id] = $value; + } +} + +$agent_a = (bool) check_acl($config['id_user'], 0, 'AR'); +$agent_w = (bool) check_acl($config['id_user'], 0, 'AW'); +$access = ($agent_a === true) ? 'AR' : (($agent_w === true) ? 'AW' : 'AR'); + +if (is_metaconsole() === true) { + $filteringFunction = 'active_inventory_submit()'; + ui_print_info_message(['no_close' => true, 'message' => __('You must select at least one filter.'), 'force_class' => 'select_one_filter']); + ?> + + '; + +$table = new stdClass(); +$table->width = '100%'; +$table->class = 'databox filters'; +$table->size = []; +$table->size[0] = '120px'; +$table->cellpadding = 0; +$table->cellspacing = 0; +$table->data = []; +$table->rowspan[0][4] = 2; + +if ($is_metaconsole === true) { + // Node select. + $nodes = []; + foreach ($nodes_connection as $row) { + $nodes[$row['id']] = $row['server_name']; + } + + $table->data[-1][0] = ''.__('Server').''; + $table->data[-1][1] = html_print_select($nodes, 'id_server', $id_server, $filteringFunction, __('All'), 0, true, false, true, '', false, 'min-width: 250px; max-width: 300px;'); +} + +// Group select. +$table->data[0][0] = ''.__('Group').''; + +$table->data[0][1] = '
'; +$table->data[0][1] .= html_print_select_groups( + $config['id_user'], + $access, + true, + 'id_group', + $inventory_id_group, + $filteringFunction, + '', + '1', + true, + false, + true, + '', + false +); +$table->data[0][1] .= '
'; + +// Module selected. +$table->data[0][2] = ''.__('Module').''; + +if ($is_metaconsole === true) { + $table->data[0][3] = html_print_select($fields, 'module_inventory_general_view', $inventory_module, $filteringFunction, __('All'), 0, true, false, true, '', false, 'min-width: 194px; max-width: 200px;'); +} else { + $sql = 'SELECT name as indexname, name + FROM tmodule_inventory, tagent_module_inventory + WHERE tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory'; + if ($inventory_id_agent > 0) { + $sql .= ' AND id_agente = '.$inventory_id_agent; + } + + $table->data[0][3] = html_print_select_from_sql($sql, 'module_inventory_general_view', $inventory_module, '', __('All'), 'all', true, false, false); +} + + +// Button of submit. +$table->data[0][4] = html_print_submit_button(__('Search'), 'submit_filter', $noFilterSelected, "class='sub search'", true); + +// Agent select. +if ($is_metaconsole === false) { + $agents = []; + $sql = 'SELECT id_agente, nombre FROM tagente'; + if ($inventory_id_group > 0) { + $sql .= ' WHERE id_grupo = '.$inventory_id_group; + } else { + $user_groups = implode(',', array_keys(users_get_groups($config['id_user']))); + + // Avoid errors if there are no groups. + if (empty($user_groups) === true) { + $user_groups = '"0"'; + } + + $sql .= ' WHERE id_grupo IN ('.$user_groups.')'; + } + + $result = db_get_all_rows_sql($sql); + if ($result) { + foreach ($result as $row) { + $agents[$row['id_agente']] = $row['nombre']; + } + } +} + +$table->data[1][0] = ''.__('Agent').''; + +$params = []; +$params['return'] = true; +$params['show_helptip'] = true; +$params['input_name'] = 'agent'; +$params['value'] = $inventory_agent; +$params['selectbox_id'] = 'module_inventory_general_view'; +$params['javascript_is_function_select'] = true; +$params['javascript_function_action_after_select'] = 'this.form.submit'; +$params['use_hidden_input_idagent'] = true; +$params['print_hidden_input_idagent'] = true; +$params['hidden_input_idagent_id'] = 'hidden-autocomplete_id_agent'; +$params['hidden_input_idagent_name'] = 'agent_id'; +$params['hidden_input_idagent_value'] = $inventory_id_agent; +if ($is_metaconsole === true) { + $params['print_input_id_server'] = true; + $params['input_id_server_id'] = 'hidden-autocomplete_id_server'; + $params['input_id_server_name'] = 'id_server_agent'; + $params['input_id_server_value'] = $inventory_id_server; + $params['metaconsole_enabled'] = true; +} + +$table->data[1][1] = ui_print_agent_autocomplete_input($params); + +// String search_string. +$table->data[1][2] = ''.__('Search').''; +$table->data[1][3] = html_print_input_text('search_string', $inventory_search_string, '', 25, 0, true, false, false, '', '', $filteringFunction, 'off', false, $filteringFunction); + +// Date filter. In Metaconsole has not reason for show. +if (is_metaconsole() === false) { + $table->data[2][0] = ''.__('Date').''; + $dates = inventory_get_dates($inventory_module, $inventory_agent, $inventory_id_group); + $table->data[2][1] = html_print_select($dates, 'utimestamp', $utimestamp, '', __('Last'), 0, true); +} + +// Order by agent filter. +$table->data[2][2] = ''.__('Order by agent').''; + +$table->data[2][3] = html_print_checkbox('order_by_agent', 1, $order_by_agent, true, false, ''); + +html_print_table($table); + +echo ''; + +// No agent selected or no search performed. +if ($inventory_id_agent < 0 || $submit_filter === false) { + echo ' '; + + return; +} + +if ($is_metaconsole === false) { + // Single agent selected. + if ($inventory_id_agent > 0 && isset($agents[$inventory_id_agent]) === true) { + $agents = [$inventory_id_agent => $agents[$inventory_id_agent]]; + } + + $agents_ids = array_keys($agents); + if (count($agents_ids) > 0) { + $inventory_data = inventory_get_data( + $agents_ids, + $inventory_module, + $utimestamp, + $inventory_search_string, + $export, + false, + $order_by_agent, + '', + $pagination_url_parameters + ); + } + + if (count($agents_ids) === 0 || (int) $inventory_data === ERR_NODATA) { + ui_print_info_message(['no_close' => true, 'message' => __('No data found.') ]); + echo ' '; + + return; + } + + echo "'; + echo "'; + ?> + + true, 'message' => __('No data found.') ]); + } else { + echo $inventory_data; + } + + close_meta_frame(); +} + +ui_require_jquery_file('pandora.controls'); +ui_require_jquery_file('ajaxqueue'); +ui_require_jquery_file('bgiframe'); +?> + + diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 1e3eae4c8a..49c2400088 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -73,7 +73,11 @@ if ($access_console_node === true) { $sub['view']['sub2'] = $sub2; - enterprise_hook('inventory_menu'); + if (check_acl($config['id_user'], 0, 'AR') || check_acl($config['id_user'], 0, 'AW')) { + $sub['operation/inventory/inventory']['text'] = __('Inventory'); + $sub['operation/inventory/inventory']['id'] = 'Inventory'; + $sub['operation/inventory/inventory']['refr'] = 0; + } if ($config['activate_netflow']) { $sub['network_traffic'] = [ diff --git a/pandora_server/bin/pandora_server b/pandora_server/bin/pandora_server index ce091872e2..5275829422 100755 --- a/pandora_server/bin/pandora_server +++ b/pandora_server/bin/pandora_server @@ -40,6 +40,7 @@ use PandoraFMS::WMIServer; use PandoraFMS::PluginServer; use PandoraFMS::PredictionServer; use PandoraFMS::WebServer; +use PandoraFMS::InventoryServer; # Constants for Win32 services. use constant WIN32_SERVICE_STOPPED => 0x01; @@ -157,6 +158,8 @@ sub pandora_startup () { push (@Servers, new PandoraFMS::PluginServer (\%Config, $DBH)); push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH)); push (@Servers, new PandoraFMS::WebServer (\%Config, $DBH)); + push (@Servers, new PandoraFMS::InventoryServer (\%Config, $DBH)); + } else { # Metaconsole service modules are run by the prediction server push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH)); diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 35a8b6869a..5d01eadf67 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -278,6 +278,8 @@ our @EXPORT = qw( notification_set_targets notification_get_users notification_get_groups + process_inventory_data + process_inventory_module_diff ); # Some global variables @@ -4987,277 +4989,6 @@ sub process_inc_abs_data ($$$$$$) { return $diff; } -################################################################################ -################################################################################ -## Inventory XML data -################################################################################ -################################################################################ - - -################################################################################ -# Process inventory data, creating the module if necessary. -################################################################################ -sub process_inventory_data ($$$$$$$) { - my ($pa_config, $data, $server_id, $agent_name, - $interval, $timestamp, $dbh) = @_; - - foreach my $inventory (@{$data->{'inventory'}}) { - - # Process inventory modules - foreach my $module_data (@{$inventory->{'inventory_module'}}) { - - my $module_name = get_tag_value ($module_data, 'name', ''); - - # Unnamed module - next if ($module_name eq ''); - - # Process inventory data - my $data_list = ''; - foreach my $list (@{$module_data->{'datalist'}}) { - - # Empty list - next unless defined ($list->{'data'}); - - foreach my $data (@{$list->{'data'}}) { - $data_list .= $data . "\n"; - } - } - - next if ($data_list eq ''); - process_inventory_module_data ($pa_config, $data_list, $server_id, $agent_name, $module_name, $interval, $timestamp, $dbh); - } - } -} - -################################################################################ -# Process inventory module data, creating the module if necessary. -################################################################################ -sub process_inventory_module_data ($$$$$$$$) { - my ($pa_config, $data, $server_id, $agent_name, - $module_name, $interval, $timestamp, $dbh) = @_; - - logger ($pa_config, "Processing inventory module '$module_name' for agent '$agent_name'.", 10); - - # Get agent data - my $agent = get_db_single_row ($dbh, - 'SELECT * FROM tagente WHERE nombre = ?', safe_input($agent_name)); - if (! defined ($agent)) { - logger ($pa_config, "Agent '$agent_name' not found for inventory module '$module_name'.", 3); - return; - } - - # Parse the timestamp and process the module - if ($timestamp !~ /(\d+)\/(\d+)\/(\d+) +(\d+):(\d+):(\d+)/ && - $timestamp !~ /(\d+)\-(\d+)\-(\d+) +(\d+):(\d+):(\d+)/) { - logger($pa_config, "Invalid timestamp '$timestamp' from module '$module_name' agent '$agent_name'.", 3); - return; - } - my $utimestamp; - eval { - $utimestamp = strftime("%s", $6, $5, $4, $3, $2 - 1, $1 - 1900); - }; - if ($@) { - logger($pa_config, "Invalid timestamp '$timestamp' from module '$module_name' agent '$agent_name'.", 3); - return; - } - - # Get module data or create it if it does not exist - my $inventory_module = get_db_single_row ($dbh, - 'SELECT tagent_module_inventory.*, tmodule_inventory.name - FROM tagent_module_inventory, tmodule_inventory - WHERE tagent_module_inventory.id_module_inventory = tmodule_inventory.id_module_inventory - AND id_agente = ? AND name = ?', - $agent->{'id_agente'}, safe_input($module_name)); - - - - if (! defined ($inventory_module)) { - # Get the module - my $module_id = get_db_value ($dbh, - 'SELECT id_module_inventory FROM tmodule_inventory WHERE name = ? AND id_os = ?', - safe_input($module_name), $agent->{'id_os'}); - return unless defined ($module_id); - - my $id_agent_module_inventory = 0; - # Update the module data - - $id_agent_module_inventory = db_insert ($dbh, 'id_agent_module_inventory', - "INSERT INTO tagent_module_inventory (id_agente, id_module_inventory, - ${RDBMS_QUOTE}interval${RDBMS_QUOTE}, data, timestamp, utimestamp, flag) - VALUES (?, ?, ?, ?, ?, ?, ?)", - $agent->{'id_agente'}, $module_id, $interval, safe_input($data), $timestamp, $utimestamp, 0); - - - return unless ($id_agent_module_inventory > 0); - - db_do ($dbh, - 'INSERT INTO tagente_datos_inventory (id_agent_module_inventory, data, timestamp, utimestamp) - VALUES (?, ?, ?, ?)', - $id_agent_module_inventory, safe_input($data), $timestamp, $utimestamp); - - return; - } - - process_inventory_module_diff($pa_config, safe_input($data), - $inventory_module, $timestamp, $utimestamp, $dbh, $interval); -} - -################################################################################ -# Searching differences between incoming module and stored module, -# creating/updating module and event -################################################################################ -sub process_inventory_module_diff ($$$$$$;$) { - my ($pa_config, $incoming_data, $inventory_module, $timestamp, $utimestamp, $dbh, $interval) = @_; - - my $stored_data = $inventory_module->{'data'}; - my $agent_id = $inventory_module->{'id_agente'}; - my $stored_utimestamp = $inventory_module->{'utimestamp'}; - my $agent_module_inventory_id = $inventory_module->{'id_agent_module_inventory'}; - my $module_inventory_id = $inventory_module->{'id_module_inventory'}; - - - process_inventory_alerts($pa_config, $incoming_data, - $inventory_module, $timestamp, $utimestamp, $dbh, $interval); - - # If there were any changes generate an event and save the new data - if (decode('UTF-8', $stored_data) ne $incoming_data) { - my $inventory_db = $stored_data; - my $inventory_new = $incoming_data; - my @inventory = split('\n', $inventory_new); - my $diff_new = ""; - my $diff_delete = ""; - - foreach my $inv (@inventory) { - my $inv_clean = quotemeta($inv); - if($inventory_db =~ m/$inv_clean/) { - $inventory_db =~ s/$inv_clean//g; - $inventory_new =~ s/$inv_clean//g; - } - else { - $diff_new .= "$inv\n"; - } - } - - # If any register is in the stored yet, we store as deleted - $inventory_db =~ s/\n\n*/\n/g; - $inventory_db =~ s/^\n//g; - - $diff_delete = $inventory_db; - - if($diff_new ne "") { - $diff_new = " NEW: '$diff_new' "; - } - if($diff_delete ne "") { - $diff_delete = " DELETED: '$diff_delete' "; - } - - db_do ($dbh, 'INSERT INTO tagente_datos_inventory (id_agent_module_inventory, data, timestamp, utimestamp) VALUES (?, ?, ?, ?)', - $agent_module_inventory_id, $incoming_data, $timestamp, $utimestamp); - - # Do not generate an event the first time the module runs - if ($stored_utimestamp != 0) { - my $inventory_changes_blacklist = pandora_get_config_value ($dbh, 'inventory_changes_blacklist'); - my $inventory_module_blocked = 0; - - if($inventory_changes_blacklist ne "") { - foreach my $inventory_id_excluded (split (',', $inventory_changes_blacklist)) { - # If the inventory_module_id is in the blacklist, the change will not be processed - if($inventory_module->{'id_module_inventory'} == $inventory_id_excluded) { - logger ($pa_config, "Inventory change omitted on inventory #$inventory_id_excluded due be on the changes blacklist", 10); - $inventory_module_blocked = 1; - } - } - } - - # If the inventory_module_id is in the blacklist, the change will not be processed - if ($inventory_module_blocked == 0) { - my $inventory_module_name = get_db_value ($dbh, "SELECT name FROM tmodule_inventory WHERE id_module_inventory = ?", $module_inventory_id); - return unless defined ($inventory_module_name); - - my $agent_name = get_agent_name ($dbh, $agent_id); - return unless defined ($agent_name); - - my $agent_alias = get_agent_alias ($dbh, $agent_id); - return unless defined ($agent_alias); - - my $group_id = get_agent_group ($dbh, $agent_id); - - - - $stored_data =~ s/&#x20;/ /g; - $incoming_data =~ s/&#x20;/ /g; - - my @values_stored = split(' ', $stored_data); - my @finalc_stored = (); - my @values_incoming = split(' ', $incoming_data); - my @finalc_incoming = (); - my @finalc_compare_added = (); - my @finalc_compare_deleted = (); - my @finalc_compare_updated = (); - my @finalc_compare_updated_del = (); - my @finalc_compare_updated_add = (); - my $temp_compare = (); - my $final_d = ''; - my $final_a = ''; - my $final_u = ''; - - - - foreach my $i (0 .. $#values_stored) { - $finalc_stored[$i] = $values_stored[$i]; - - if ( grep $_ eq $values_stored[$i], @values_incoming ) { - - } else { - # Use 'safe_output' to avoid double encode the entities when creating the event with 'pandora_event' - $final_d .= "DELETED RECORD: ".safe_output($values_stored[$i])."\n"; - } - } - - foreach my $i (0 .. $#values_incoming) { - $finalc_incoming[$i] = $values_incoming[$i]; - - if ( grep $_ eq $values_incoming[$i], @values_stored ) { - - } else { - # Use 'safe_output' to avoid double encode the entities when creating the event with 'pandora_event' - $final_a .= "NEW RECORD: ".safe_output($values_incoming[$i])."\n"; - } - } - - # foreach my $i (0 .. $#finalc_compare_deleted) { - # $finalc_compare_updated_del[$i] = split(';', $finalc_compare_deleted[$i]); - # $finalc_compare_updated_add[$i] = split(';', $finalc_compare_added[$i]); - # if($finalc_compare_updated_del[$i] ~~ @finalc_compare_updated_add){ - # $finalc_compare_updated[$i] = $finalc_compare_updated_del[$i]; - # } - # $finalc_compare_updated[$i] =~ s/DELETED RECORD:/UPDATED RECORD:/g; - # $finalc_compare_updated[$i] =~ s/NEW RECORD://g; - # } - - - pandora_event ($pa_config, "Configuration change:\n".$final_d.$final_a." for agent '" . safe_output($agent_alias) . "' module '" . safe_output($inventory_module_name) . "'.", $group_id, $agent_id, 0, 0, 0, "configuration_change", 0, $dbh); - } - } - } - - # Update the module data - if (defined($interval)) { - db_do ($dbh, 'UPDATE tagent_module_inventory - SET'. $RDBMS_QUOTE . 'interval' . - $RDBMS_QUOTE . '=?, data=?, timestamp=?, utimestamp=? - WHERE id_agent_module_inventory=?', - $interval, $incoming_data, $timestamp, - $utimestamp, $agent_module_inventory_id); - - } - else { - db_do ($dbh, 'UPDATE tagent_module_inventory - SET data = ?, timestamp = ?, utimestamp = ? - WHERE id_agent_module_inventory = ?', - $incoming_data, $timestamp, $utimestamp, $agent_module_inventory_id); - } -} sub log4x_get_severity_num($) { my ($data_object) = @_; @@ -7400,6 +7131,278 @@ sub notification_get_groups { return @results; } +################################################################################ +################################################################################ +## Inventory XML data +################################################################################ +################################################################################ + + +################################################################################ +# Process inventory data, creating the module if necessary. +################################################################################ +sub process_inventory_data ($$$$$$$) { + my ($pa_config, $data, $server_id, $agent_name, + $interval, $timestamp, $dbh) = @_; + + foreach my $inventory (@{$data->{'inventory'}}) { + + # Process inventory modules + foreach my $module_data (@{$inventory->{'inventory_module'}}) { + + my $module_name = get_tag_value ($module_data, 'name', ''); + + # Unnamed module + next if ($module_name eq ''); + + # Process inventory data + my $data_list = ''; + foreach my $list (@{$module_data->{'datalist'}}) { + + # Empty list + next unless defined ($list->{'data'}); + + foreach my $data (@{$list->{'data'}}) { + $data_list .= $data . "\n"; + } + } + + next if ($data_list eq ''); + process_inventory_module_data ($pa_config, $data_list, $server_id, $agent_name, $module_name, $interval, $timestamp, $dbh); + } + } +} + +################################################################################ +# Process inventory module data, creating the module if necessary. +################################################################################ +sub process_inventory_module_data ($$$$$$$$) { + my ($pa_config, $data, $server_id, $agent_name, + $module_name, $interval, $timestamp, $dbh) = @_; + + logger ($pa_config, "Processing inventory module '$module_name' for agent '$agent_name'.", 10); + + # Get agent data + my $agent = get_db_single_row ($dbh, + 'SELECT * FROM tagente WHERE nombre = ?', safe_input($agent_name)); + if (! defined ($agent)) { + logger ($pa_config, "Agent '$agent_name' not found for inventory module '$module_name'.", 3); + return; + } + + # Parse the timestamp and process the module + if ($timestamp !~ /(\d+)\/(\d+)\/(\d+) +(\d+):(\d+):(\d+)/ && + $timestamp !~ /(\d+)\-(\d+)\-(\d+) +(\d+):(\d+):(\d+)/) { + logger($pa_config, "Invalid timestamp '$timestamp' from module '$module_name' agent '$agent_name'.", 3); + return; + } + my $utimestamp; + eval { + $utimestamp = strftime("%s", $6, $5, $4, $3, $2 - 1, $1 - 1900); + }; + if ($@) { + logger($pa_config, "Invalid timestamp '$timestamp' from module '$module_name' agent '$agent_name'.", 3); + return; + } + + # Get module data or create it if it does not exist + my $inventory_module = get_db_single_row ($dbh, + 'SELECT tagent_module_inventory.*, tmodule_inventory.name + FROM tagent_module_inventory, tmodule_inventory + WHERE tagent_module_inventory.id_module_inventory = tmodule_inventory.id_module_inventory + AND id_agente = ? AND name = ?', + $agent->{'id_agente'}, safe_input($module_name)); + + + + if (! defined ($inventory_module)) { + # Get the module + my $module_id = get_db_value ($dbh, + 'SELECT id_module_inventory FROM tmodule_inventory WHERE name = ? AND id_os = ?', + safe_input($module_name), $agent->{'id_os'}); + return unless defined ($module_id); + + my $id_agent_module_inventory = 0; + # Update the module data + + $id_agent_module_inventory = db_insert ($dbh, 'id_agent_module_inventory', + "INSERT INTO tagent_module_inventory (id_agente, id_module_inventory, + ${RDBMS_QUOTE}interval${RDBMS_QUOTE}, data, timestamp, utimestamp, flag) + VALUES (?, ?, ?, ?, ?, ?, ?)", + $agent->{'id_agente'}, $module_id, $interval, safe_input($data), $timestamp, $utimestamp, 0); + + + return unless ($id_agent_module_inventory > 0); + + db_do ($dbh, + 'INSERT INTO tagente_datos_inventory (id_agent_module_inventory, data, timestamp, utimestamp) + VALUES (?, ?, ?, ?)', + $id_agent_module_inventory, safe_input($data), $timestamp, $utimestamp); + + return; + } + + process_inventory_module_diff($pa_config, safe_input($data), + $inventory_module, $timestamp, $utimestamp, $dbh, $interval); +} + +################################################################################ +# Searching differences between incoming module and stored module, +# creating/updating module and event +################################################################################ +sub process_inventory_module_diff ($$$$$$;$) { + my ($pa_config, $incoming_data, $inventory_module, $timestamp, $utimestamp, $dbh, $interval) = @_; + + my $stored_data = $inventory_module->{'data'}; + my $agent_id = $inventory_module->{'id_agente'}; + my $stored_utimestamp = $inventory_module->{'utimestamp'}; + my $agent_module_inventory_id = $inventory_module->{'id_agent_module_inventory'}; + my $module_inventory_id = $inventory_module->{'id_module_inventory'}; + + + enterprise_hook('process_inventory_alerts', [$pa_config, $incoming_data, + $inventory_module, $timestamp, $utimestamp, $dbh, $interval]); + + # If there were any changes generate an event and save the new data + if (decode('UTF-8', $stored_data) ne $incoming_data) { + my $inventory_db = $stored_data; + my $inventory_new = $incoming_data; + my @inventory = split('\n', $inventory_new); + my $diff_new = ""; + my $diff_delete = ""; + + foreach my $inv (@inventory) { + my $inv_clean = quotemeta($inv); + if($inventory_db =~ m/$inv_clean/) { + $inventory_db =~ s/$inv_clean//g; + $inventory_new =~ s/$inv_clean//g; + } + else { + $diff_new .= "$inv\n"; + } + } + + # If any register is in the stored yet, we store as deleted + $inventory_db =~ s/\n\n*/\n/g; + $inventory_db =~ s/^\n//g; + + $diff_delete = $inventory_db; + + if($diff_new ne "") { + $diff_new = " NEW: '$diff_new' "; + } + if($diff_delete ne "") { + $diff_delete = " DELETED: '$diff_delete' "; + } + + db_do ($dbh, 'INSERT INTO tagente_datos_inventory (id_agent_module_inventory, data, timestamp, utimestamp) VALUES (?, ?, ?, ?)', + $agent_module_inventory_id, $incoming_data, $timestamp, $utimestamp); + + # Do not generate an event the first time the module runs + if ($stored_utimestamp != 0) { + my $inventory_changes_blacklist = pandora_get_config_value ($dbh, 'inventory_changes_blacklist'); + my $inventory_module_blocked = 0; + + if($inventory_changes_blacklist ne "") { + foreach my $inventory_id_excluded (split (',', $inventory_changes_blacklist)) { + # If the inventory_module_id is in the blacklist, the change will not be processed + if($inventory_module->{'id_module_inventory'} == $inventory_id_excluded) { + logger ($pa_config, "Inventory change omitted on inventory #$inventory_id_excluded due be on the changes blacklist", 10); + $inventory_module_blocked = 1; + } + } + } + + # If the inventory_module_id is in the blacklist, the change will not be processed + if ($inventory_module_blocked == 0) { + my $inventory_module_name = get_db_value ($dbh, "SELECT name FROM tmodule_inventory WHERE id_module_inventory = ?", $module_inventory_id); + return unless defined ($inventory_module_name); + + my $agent_name = get_agent_name ($dbh, $agent_id); + return unless defined ($agent_name); + + my $agent_alias = get_agent_alias ($dbh, $agent_id); + return unless defined ($agent_alias); + + my $group_id = get_agent_group ($dbh, $agent_id); + + + + $stored_data =~ s/&#x20;/ /g; + $incoming_data =~ s/&#x20;/ /g; + + my @values_stored = split(' ', $stored_data); + my @finalc_stored = (); + my @values_incoming = split(' ', $incoming_data); + my @finalc_incoming = (); + my @finalc_compare_added = (); + my @finalc_compare_deleted = (); + my @finalc_compare_updated = (); + my @finalc_compare_updated_del = (); + my @finalc_compare_updated_add = (); + my $temp_compare = (); + my $final_d = ''; + my $final_a = ''; + my $final_u = ''; + + + + foreach my $i (0 .. $#values_stored) { + $finalc_stored[$i] = $values_stored[$i]; + + if ( grep $_ eq $values_stored[$i], @values_incoming ) { + + } else { + # Use 'safe_output' to avoid double encode the entities when creating the event with 'pandora_event' + $final_d .= "DELETED RECORD: ".safe_output($values_stored[$i])."\n"; + } + } + + foreach my $i (0 .. $#values_incoming) { + $finalc_incoming[$i] = $values_incoming[$i]; + + if ( grep $_ eq $values_incoming[$i], @values_stored ) { + + } else { + # Use 'safe_output' to avoid double encode the entities when creating the event with 'pandora_event' + $final_a .= "NEW RECORD: ".safe_output($values_incoming[$i])."\n"; + } + } + + # foreach my $i (0 .. $#finalc_compare_deleted) { + # $finalc_compare_updated_del[$i] = split(';', $finalc_compare_deleted[$i]); + # $finalc_compare_updated_add[$i] = split(';', $finalc_compare_added[$i]); + # if($finalc_compare_updated_del[$i] ~~ @finalc_compare_updated_add){ + # $finalc_compare_updated[$i] = $finalc_compare_updated_del[$i]; + # } + # $finalc_compare_updated[$i] =~ s/DELETED RECORD:/UPDATED RECORD:/g; + # $finalc_compare_updated[$i] =~ s/NEW RECORD://g; + # } + + + pandora_event ($pa_config, "Configuration change:\n".$final_d.$final_a." for agent '" . safe_output($agent_alias) . "' module '" . safe_output($inventory_module_name) . "'.", $group_id, $agent_id, 0, 0, 0, "configuration_change", 0, $dbh); + } + } + } + + # Update the module data + if (defined($interval)) { + db_do ($dbh, 'UPDATE tagent_module_inventory + SET'. $RDBMS_QUOTE . 'interval' . + $RDBMS_QUOTE . '=?, data=?, timestamp=?, utimestamp=? + WHERE id_agent_module_inventory=?', + $interval, $incoming_data, $timestamp, + $utimestamp, $agent_module_inventory_id); + + } + else { + db_do ($dbh, 'UPDATE tagent_module_inventory + SET data = ?, timestamp = ?, utimestamp = ? + WHERE id_agent_module_inventory = ?', + $incoming_data, $timestamp, $utimestamp, $agent_module_inventory_id); + } +} + # End of function declaration # End of defined Code diff --git a/pandora_server/lib/PandoraFMS/InventoryServer.pm b/pandora_server/lib/PandoraFMS/InventoryServer.pm new file mode 100644 index 0000000000..f0c92a7fd3 --- /dev/null +++ b/pandora_server/lib/PandoraFMS/InventoryServer.pm @@ -0,0 +1,267 @@ +package PandoraFMS::InventoryServer; + +########################################################################## +# Pandora FMS Inventory Server. +########################################################################## +# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L +# This code is not free or OpenSource. Please don't redistribute. +########################################################################## + +use strict; +use warnings; + +use threads; +use threads::shared; +use Thread::Semaphore; + +use File::Temp qw(tempfile unlink0); +use POSIX qw(strftime); +use HTML::Entities; +use MIME::Base64; +use JSON; + +# UTF-8 flags control with I/O for multibyte characters +use open ":utf8"; + +# Default lib dir for RPM and DEB packages +BEGIN { push @INC, '/usr/lib/perl5'; } + +use PandoraFMS::Tools; +use PandoraFMS::DB; +use PandoraFMS::Core; +use PandoraFMS::ProducerConsumerServer; + +# Inherits from PandoraFMS::ProducerConsumerServer +our @ISA = qw(PandoraFMS::ProducerConsumerServer); + +# Global variables +my @TaskQueue :shared; +my %PendingTasks :shared; +my $Sem :shared; +my $TaskSem :shared; + +######################################################################################## +# Inventory Server class constructor. +######################################################################################## +sub new ($$;$) { + my ($class, $config, $dbh) = @_; + + return undef unless $config->{'inventoryserver'} == 1; + + # Initialize semaphores and queues + @TaskQueue = (); + %PendingTasks = (); + $Sem = Thread::Semaphore->new; + $TaskSem = Thread::Semaphore->new (0); + + # Call the constructor of the parent class + my $self = $class->SUPER::new($config, INVENTORYSERVER, \&PandoraFMS::InventoryServer::data_producer, \&PandoraFMS::InventoryServer::data_consumer, $dbh); + + bless $self, $class; + return $self; +} + +############################################################################### +# Run. +############################################################################### +sub run ($) { + my $self = shift; + my $pa_config = $self->getConfig (); + + print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Inventory Server.", 1); + $self->setNumThreads ($pa_config->{'inventory_threads'}); + $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem); +} + +############################################################################### +# Data producer. +############################################################################### +sub data_producer ($) { + my $self = shift; + my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); + + my @tasks; + my @rows; + + if (pandora_is_master($pa_config) == 0) { + if ($pa_config->{'dbengine'} ne 'oracle') { + @rows = get_db_rows ($dbh, + 'SELECT tagent_module_inventory.id_agent_module_inventory, tagent_module_inventory.flag, tagent_module_inventory.timestamp + FROM tagente, tagent_module_inventory, tmodule_inventory + WHERE tagente.server_name = ? + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tmodule_inventory.id_os IS NOT NULL + AND tagente.id_agente = tagent_module_inventory.id_agente + AND tagent_module_inventory.target <> \'\' + AND tagente.disabled = 0 + AND (tagent_module_inventory.timestamp = \'1970-01-01 00:00:00\' + OR UNIX_TIMESTAMP(tagent_module_inventory.timestamp) + tagent_module_inventory.interval < UNIX_TIMESTAMP() + OR tagent_module_inventory.flag = 1) + ORDER BY tagent_module_inventory.timestamp ASC', + $pa_config->{'servername'}); + } + else { + @rows = get_db_rows ($dbh, + 'SELECT tagent_module_inventory.id_agent_module_inventory, tagent_module_inventory.flag, tagent_module_inventory.timestamp + FROM tagente, tagent_module_inventory, tmodule_inventory + WHERE tagente.server_name = ? + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tmodule_inventory.id_os IS NOT NULL + AND tagente.id_agente = tagent_module_inventory.id_agente + AND tagent_module_inventory.target IS NOT NULL + AND tagente.disabled = 0 + AND (tagent_module_inventory.timestamp = \'1970-01-01 00:00:00\' + OR UNIX_TIMESTAMP(tagent_module_inventory.timestamp) + tagent_module_inventory.' . ${RDBMS_QUOTE} . 'interval' . ${RDBMS_QUOTE} . '< UNIX_TIMESTAMP() + OR tagent_module_inventory.flag = 1) + ORDER BY tagent_module_inventory.timestamp ASC', + $pa_config->{'servername'}); + } + } + else { + if ($pa_config->{'dbengine'} ne 'oracle') { + @rows = get_db_rows ($dbh, + 'SELECT tagent_module_inventory.id_agent_module_inventory, tagent_module_inventory.flag, tagent_module_inventory.timestamp + FROM tagente, tagent_module_inventory, tmodule_inventory + WHERE (server_name = ? OR server_name = ANY(SELECT name FROM tserver WHERE status <> 1 AND server_type = ?)) + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tmodule_inventory.id_os IS NOT NULL + AND tagente.id_agente = tagent_module_inventory.id_agente + AND tagent_module_inventory.target <> \'\' + AND tagente.disabled = 0 + AND (tagent_module_inventory.timestamp = \'1970-01-01 00:00:00\' + OR UNIX_TIMESTAMP(tagent_module_inventory.timestamp) + tagent_module_inventory.interval < UNIX_TIMESTAMP() + OR tagent_module_inventory.flag = 1) + ORDER BY tagent_module_inventory.timestamp ASC', + $pa_config->{'servername'}, INVENTORYSERVER); + } + else { + @rows = get_db_rows ($dbh, + 'SELECT tagent_module_inventory.id_agent_module_inventory, tagent_module_inventory.flag, tagent_module_inventory.timestamp + FROM tagente, tagent_module_inventory, tmodule_inventory + WHERE (server_name = ? OR server_name = ANY(SELECT name FROM tserver WHERE status <> 1 AND server_type = ?)) + AND tmodule_inventory.id_module_inventory = tagent_module_inventory.id_module_inventory + AND tmodule_inventory.id_os IS NOT NULL + AND tagente.id_agente = tagent_module_inventory.id_agente + AND tagent_module_inventory.target IS NOT NULL + AND tagente.disabled = 0 + AND (tagent_module_inventory.timestamp = \'1970-01-01 00:00:00\' + OR UNIX_TIMESTAMP(tagent_module_inventory.timestamp) + tagent_module_inventory.' . ${RDBMS_QUOTE} . 'interval' . ${RDBMS_QUOTE} . ' < UNIX_TIMESTAMP() + OR tagent_module_inventory.flag = 1) + ORDER BY tagent_module_inventory.timestamp ASC', + $pa_config->{'servername'}, INVENTORYSERVER); + } + } + + foreach my $row (@rows) { + + # Reset forced execution flag + if ($row->{'flag'} == 1) { + db_do ($dbh, 'UPDATE tagent_module_inventory SET flag = 0 WHERE id_agent_module_inventory = ?', $row->{'id_agent_module_inventory'}); + } + + push (@tasks, $row->{'id_agent_module_inventory'}); + } + + return @tasks; +} + +############################################################################### +# Data consumer. +############################################################################### +sub data_consumer ($$) { + my ($self, $module_id) = @_; + my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); + + my $timeout = $pa_config->{'inventory_timeout'}; + + # Get inventory module data + my $module = get_db_single_row ($dbh, + 'SELECT * FROM tagent_module_inventory, tmodule_inventory + WHERE tagent_module_inventory.id_agent_module_inventory = ? + AND tagent_module_inventory.id_module_inventory = tmodule_inventory.id_module_inventory', + $module_id); + + # No code to run + return if ($module->{'interpreter'} eq ''); + + # Save script in a temporary file + my ($fh, $temp_file) = tempfile(); + $fh->print (decode_base64($module->{'code'})); + close ($fh); + set_file_permissions($pa_config, $temp_file, "0777"); + + # Run the script + my $command = $module->{'interpreter'} . ' ' . $temp_file . ' "' . $module->{'target'} . '"'; + + # Try to read the custom fields to use them as arguments into the command + if (defined($module->{'custom_fields'}) && $module->{'custom_fields'} ne '') { + my $decoded_cfields; + + eval { + $decoded_cfields = decode_json (decode_base64 ($module->{'custom_fields'})); + }; + if ($@) { + logger($pa_config, "Failed to encode received inventory data", 10); + } + + if (!defined ($decoded_cfields)) { + logger ($pa_config, "Remote inventory module ".$module->{'name'}." has failed because the custom fields can't be read", 6); + unlink ($temp_file); + return; + } + + foreach my $field (@{$decoded_cfields}) { + if ($field->{'secure'}) { + $command .= ' "' . pandora_output_password($pa_config, $field->{'value'}) . '"'; + } + else { + $command .= ' "' . $field->{'value'} . '"'; + } + } + } + # Add the default user/password arguments to the command + else { + # Initialize macros. + my %macros = ( + '_agentcustomfield_\d+_' => undef, + ); + + my $wmi_user = safe_output(subst_column_macros($module->{"username"}, \%macros, $pa_config, $dbh, undef, $module)); + my $wmi_pass = safe_output(pandora_output_password($pa_config, subst_column_macros($module->{"password"}, \%macros, $pa_config, $dbh, undef, $module))); + $command .= ' "' . $wmi_user . '" "' . $wmi_pass . '"'; + } + + logger ($pa_config, "Inventory execution command $command", 10); + my $data = `$command 2>$DEVNULL`; + + # Check for errors + if ($? != 0) { + logger ($pa_config, "Remote inventory module ".$module->{'name'}." has failed with error level $?", 6); + unlink ($temp_file); + return; + } + + unlink ($temp_file); + my $utimestamp = time (); + my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime ($utimestamp)); + eval { + $data = encode_entities ($data, "'<>&"); + }; + if ($@) { + logger($pa_config, "Failed to encode received inventory data", 10); + return; + } + + # Get previous data from the database + my $inventory_module = get_db_single_row ($dbh, + 'SELECT * FROM tagent_module_inventory + WHERE id_agent_module_inventory = ?', + $module_id); + return unless defined ($inventory_module); + + process_inventory_module_diff($pa_config, $data, + $inventory_module, $timestamp, $utimestamp, $dbh); +} + +1; +__END__ From 72e2b623b990d7c7f29d2fb0cf8f63049e88bde2 Mon Sep 17 00:00:00 2001 From: Calvo Date: Fri, 16 Sep 2022 11:45:03 +0200 Subject: [PATCH 012/251] Move inventory to open --- pandora_console/godmode/agentes/inventory_manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/godmode/agentes/inventory_manager.php b/pandora_console/godmode/agentes/inventory_manager.php index b477d7e923..09336ec88b 100644 --- a/pandora_console/godmode/agentes/inventory_manager.php +++ b/pandora_console/godmode/agentes/inventory_manager.php @@ -27,7 +27,7 @@ if (! check_acl($config['id_user'], 0, 'AW')) { global $direccion_agente, $id_agente, $id_os; // include_once ($config['homedir'].'/'.ENTERPRISE_DIR.'/include/functions_policies.php'); -enterprise_include_once('include/functions_ui.php'); +require_once $config['homedir'].'/include/functions_ui.php'; // Initialize data $add_inventory_module = (boolean) get_parameter('add_inventory_module'); From 498a9db9973714f7e7b8ab4e71f57b4e0f07cb89 Mon Sep 17 00:00:00 2001 From: alejandro Date: Mon, 3 Oct 2022 13:33:31 +0200 Subject: [PATCH 013/251] adding new parameter check_type for define types of modules --- pandora_plugins/MySQL/pandora_mysql.pl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pandora_plugins/MySQL/pandora_mysql.pl b/pandora_plugins/MySQL/pandora_mysql.pl index ad9c4ebaa4..356db681e0 100644 --- a/pandora_plugins/MySQL/pandora_mysql.pl +++ b/pandora_plugins/MySQL/pandora_mysql.pl @@ -303,6 +303,10 @@ sub parse_config { if ($parametro =~ m/^check\_name\s(.*)/i) { $checks[$plugin_setup{"numchecks"}]{'check_name'} = trim($1); } + + if ($parametro =~ m/^check\_type\s(.*)/i) { + $checks[$plugin_setup{"numchecks"}]{'check_type'} = trim($1); + } if ($parametro =~ m/^check\_schema\s(.*)/i) { $checks[$plugin_setup{"numchecks"}]{'check_schema'} = trim($1); @@ -1015,6 +1019,7 @@ foreach (@checks) { my $check_show = $_->{'show'}; my $return_type = $_->{'return_type'}; my $check_name = $_->{'check_name'}; + my $check_type = $_->{'check_type'}; $result_check = 0; # Process check (System parameters) @@ -1156,7 +1161,7 @@ foreach (@checks) { print_module("MySQL_" . $type . '_' . $check_show, $module_type, $result_check, '', $check_status); } else { if (defined($check_name)) { - print_module("MySQL_" . $type . "_" . $check_name, $module_type, $result_check, '', $check_status); + print_module("MySQL_" . $type . "_" . $check_name, $check_type, $result_check, '', $check_status); } else { print_module("MySQL_" . $type, $module_type, $result_check, '', $check_status); } @@ -1186,3 +1191,4 @@ foreach (@checks) { } # type ne 'unknown' } + From 192754b95c3768294b80cfbb3bdac9fb247d085c Mon Sep 17 00:00:00 2001 From: alejandro Date: Mon, 17 Oct 2022 14:16:59 +0200 Subject: [PATCH 014/251] adding 1st version plugin google sheets --- .../google_sheets/pandora_googlesheet.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 pandora_plugins/google_sheets/pandora_googlesheet.py diff --git a/pandora_plugins/google_sheets/pandora_googlesheet.py b/pandora_plugins/google_sheets/pandora_googlesheet.py new file mode 100644 index 0000000000..a6e599b429 --- /dev/null +++ b/pandora_plugins/google_sheets/pandora_googlesheet.py @@ -0,0 +1,47 @@ +import gspread +import argparse +from oauth2client.service_account import ServiceAccountCredentials +from pprint import pprint + +__author__ = "Alejandro Sánchez Carrion" +__copyright__ = "Copyright 2022, PandoraFMS" +__maintainer__ = "Operations department" +__status__ = "Production" +__version__= '1.0' + +info = f""" +Pandora FMS Google Sheets +Version = {__version__} + +Manual execution + +python3 pandora_googlesheets.py --cred --row --column + +""" + +parser = argparse.ArgumentParser(description= info, formatter_class=argparse.RawTextHelpFormatter) +parser.add_argument('--cred', help='') +parser.add_argument('--name', help='') +parser.add_argument('--row', help='',type=int) +parser.add_argument('--column', help='',type=int) + +args = parser.parse_args() + +scope = ["https://spreadsheets.google.com/feeds",'https://www.googleapis.com/auth/spreadsheets',"https://www.googleapis.com/auth/drive.file","https://www.googleapis.com/auth/drive"] +creds = ServiceAccountCredentials.from_json_keyfile_name(args.cred, scope) + +client = gspread.authorize(creds) + +sheet = client.open(args.name).sheet1 # Open the spreadhseet + +data = sheet.get_all_records() # Get a list of all records + +if args.row is not None and args.column==None: + row = sheet.row_values(args.row) # Get a specific row + print(row) +elif args.row ==None and args.column is not None: + col = sheet.col_values(args.column) # Get a specific column + print(col) +elif args.row is not None and args.column is not None: + cell = sheet.cell(args.row,args.column).value # Get the value of a specific cell + print(cell) From 17d7261173e701a49423497688959653a1f3ebd2 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Thu, 20 Oct 2022 13:17:26 +0200 Subject: [PATCH 015/251] implement cluster in open project --- .../extras/delete_files/delete_files.txt | 8 + .../general/first_task/cluster_builder.php | 4 +- .../godmode/agentes/modificar_agente.php | 62 +- pandora_console/include/functions_api.php | 2 +- .../include/functions_treeview.php | 4 +- pandora_console/include/lib/Cluster.php | 906 ++++++++++++ pandora_console/include/lib/ClusterModule.php | 268 ++++ .../lib/ClusterViewer/ClusterManager.php | 767 ++++++++++ .../lib/ClusterViewer/ClusterWizard.php | 1258 +++++++++++++++++ .../operation/agentes/estado_agente.php | 8 +- pandora_console/operation/cluster/cluster.php | 70 + pandora_console/operation/menu.php | 7 +- pandora_console/views/cluster/edit.php | 129 ++ pandora_console/views/cluster/list.php | 132 ++ pandora_console/views/cluster/view.php | 453 ++++++ 15 files changed, 4034 insertions(+), 44 deletions(-) create mode 100644 pandora_console/include/lib/Cluster.php create mode 100644 pandora_console/include/lib/ClusterModule.php create mode 100644 pandora_console/include/lib/ClusterViewer/ClusterManager.php create mode 100644 pandora_console/include/lib/ClusterViewer/ClusterWizard.php create mode 100755 pandora_console/operation/cluster/cluster.php create mode 100644 pandora_console/views/cluster/edit.php create mode 100644 pandora_console/views/cluster/list.php create mode 100644 pandora_console/views/cluster/view.php diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index f9acc8ade4..d092e8629a 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -1666,3 +1666,11 @@ godmode/um_client/vendor/sebastian/object-enumerator godmode/um_client/vendor/sebastian godmode/um_client/vendor update_manager_client/resources/styles/pandora.css +enterprise/views/cluster/edit.php +enterprise/views/cluster/list.php +enterprise/views/cluster/view.php +enterprise/include/lib/Cluster.php +enterprise/include/lib/ClusterModule.php +enterprise/include/lib/ClusterViewer/ClusterManager.php +enterprise/include/lib/ClusterViewer/ClusterWizard.php +enterprise/operation/cluster/cluster.php diff --git a/pandora_console/general/first_task/cluster_builder.php b/pandora_console/general/first_task/cluster_builder.php index 3e6fe3dad4..fe14491322 100644 --- a/pandora_console/general/first_task/cluster_builder.php +++ b/pandora_console/general/first_task/cluster_builder.php @@ -68,7 +68,7 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no cluster if (check_acl($config['id_user'], 0, 'AW')) { ?> -
+
@@ -76,4 +76,4 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no cluster } ?>
- \ No newline at end of file + diff --git a/pandora_console/godmode/agentes/modificar_agente.php b/pandora_console/godmode/agentes/modificar_agente.php index 3b714c277b..bc835af3d7 100644 --- a/pandora_console/godmode/agentes/modificar_agente.php +++ b/pandora_console/godmode/agentes/modificar_agente.php @@ -732,17 +732,15 @@ if ($agents !== false) { } if ($agent['id_os'] == CLUSTER_OS_ID) { - if (enterprise_installed()) { - $cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId( - $agent['id_agente'] - ); - $url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR; - $url .= '/operation/cluster/cluster'; - $url = ui_get_full_url( - $url.'&op=update&id='.$cluster->id() - ); - echo ''.ui_print_truncate_text($agent['alias'], 'agent_medium').''; - } + $cluster = PandoraFMS\Cluster::loadFromAgentId( + $agent['id_agente'] + ); + $url = 'index.php?sec=reporting&sec2='; + $url .= '/operation/cluster/cluster'; + $url = ui_get_full_url( + $url.'&op=update&id='.$cluster->id() + ); + echo ''.ui_print_truncate_text($agent['alias'], 'agent_medium').''; } else { echo '
'; if ($check_aw) { if ($agent['id_os'] == CLUSTER_OS_ID) { - if (enterprise_installed()) { - $cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId( - $agent['id_agente'] - ); - $url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR; - $url .= '/operation/cluster/cluster'; - $url = ui_get_full_url( - $url.'&op=update&id='.$cluster->id() - ); - echo ''.__('Edit').''; - echo ' | '; - } + $cluster = PandoraFMS\Cluster::loadFromAgentId( + $agent['id_agente'] + ); + $url = 'index.php?sec=reporting&sec2='; + $url .= '/operation/cluster/cluster'; + $url = ui_get_full_url( + $url.'&op=update&id='.$cluster->id() + ); + echo ''.__('Edit').''; + echo ' | '; } else { echo ''.__('View').''; - } + $cluster = PandoraFMS\Cluster::loadFromAgentId( + $agent['id_agente'] + ); + $url = 'index.php?sec=reporting&sec2='; + $url .= '/operation/cluster/cluster'; + $url = ui_get_full_url( + $url.'&op=view&id='.$cluster->id() + ); + echo ''.__('View').''; } else { echo 'alias().'".'; + throw new \Exception( + $msg + ); + } + + // Method searchModules returns multiple occurrences. + $module = $module[0]; + $module = $module->toArray(); + break; + } + } + + // Remove specific fields. + unset($module['id_agente_modulo']); + unset($module['id_agente']); + + return $module; + + } + + + /** + * Add an item to the cluster. + * + * @param string $name Target name. + * @param integer $type Item type. + * @param array $definition Module definition. + * + * @return ClusterModule Created module. + * @throws \Exception On error. + */ + public function addItem(string $name, int $type, array $definition) + { + $item = new ClusterModule(); + $item->name($name); + $item->id_cluster($this->id()); + + // Skel values. + $module_skel = $this->getModuleSkel($name); + + // Customize definition. + $definition = array_merge($module_skel, $definition); + + // Store in cluster agent. + $definition['id_agente'] = $this->id_agent(); + + if ($type === MODULE_PREDICTION_CLUSTER_AA) { + $item->item_type('AA'); + } else if ($type === MODULE_PREDICTION_CLUSTER_AP) { + $item->item_type('AP'); + } else { + throw new \Exception(__METHOD__.' error: Invalid item type'); + } + + // Set module definition. + $item->setModule($definition); + + // Default values. + $item->critical_limit(0); + $item->warning_limit(0); + $item->is_critical(0); + + return $item; + } + + + /** + * Add AA module to the cluster. + * + * @param string $name Target name. + * + * @return void + */ + public function addAAModule(string $name) + { + if (empty($this->aaModules[$name]) === true) { + $main_id = $this->clusterStatus->id_agente_modulo(); + + // Register module in agent. + // id_modulo = 0, + // tcp_port = 1, + // prediction_moddule = 6. + // Set thresholds while updating. + $this->aaModules[$name] = $this->addItem( + $name, + MODULE_PREDICTION_CLUSTER_AA, + [ + 'nombre' => $name, + 'id_modulo' => 0, + 'prediction_module' => 6, + 'tcp_port' => 1, + 'id_tipo_modulo' => 1, + 'custom_integer_1' => $this->id(), + 'parent_module_id' => $main_id, + ] + ); + + \db_pandora_audit( + AUDIT_LOG_AGENT_MANAGEMENT, + 'Module '.io_safe_output( + $name + ).' added to cluster'.io_safe_output( + $this->fields['name'] + ).' as Active-Active module' + ); + } + } + + + /** + * Add AP module to the cluster. + * + * @param string $name Target name. + * + * @return void + */ + public function addAPModule(string $name) + { + if (empty($this->apModules[$name]) === true) { + $main_id = $this->clusterStatus->id_agente_modulo(); + + $type = db_get_value( + 'id_tipo_modulo', + 'tagente_modulo', + 'nombre', + $name + ); + + if (empty($type) === true) { + $type = 1; + } + + // Register module in agent. + // id_modulo = 5, + // tcp_port = 1, + // prediction_moddule = 7. + // Set thresholds while updating. + $this->apModules[$name] = $this->addItem( + $name, + MODULE_PREDICTION_CLUSTER_AP, + [ + 'nombre' => $name, + 'id_modulo' => 5, + 'prediction_module' => 7, + 'tcp_port' => 1, + 'id_tipo_modulo' => $type, + 'custom_integer_1' => $this->id(), + 'parent_module_id' => $main_id, + ] + ); + + \db_pandora_audit( + AUDIT_LOG_AGENT_MANAGEMENT, + 'Module '.io_safe_output( + $name + ).' added to cluster'.io_safe_output( + $this->fields['name'] + ).' as Active-Passive module' + ); + } + } + + + /** + * Removes AA module from the cluster. + * + * @param string $name Target name. + * + * @return void + */ + public function removeAAModule(string $name) + { + if (empty($this->aaModules[$name]) === false) { + // Mark item for db elimination. + $this->removedItems[] = [ + 'id' => $this->aaModules[$name]->id(), + 'item_type' => $this->aaModules[$name]->item_type(), + ]; + $this->aaModules[$name]->delete(); + unset($this->aaModules[$name]); + } + } + + + /** + * Removes AP module from the cluster. + * + * @param string $name Target name. + * + * @return void + */ + public function removeAPModule(string $name) + { + if (empty($this->apModules[$name]) === false) { + // Mark item for db elimination. + $this->removedItems[] = [ + 'id' => $this->apModules[$name]->id(), + 'item_type' => $this->apModules[$name]->item_type(), + ]; + $this->apModules[$name]->delete(); + unset($this->apModules[$name]); + } + } + + + /** + * Return found cluster definitions. + * + * @param array $filter Conditions. + * + * @return mixed Array or false. + */ + public static function search(array $filter) + { + return \db_get_all_rows_filter( + 'tcluster', + $filter + ); + } + + + /** + * Operates with group. + * + * @param integer|null $id_group Target group to update. Retrieve group obj + * if null. + * + * @return mixed Void if set, PandoraFMS\Group if argument is null. + */ + public function group(?int $id_group=null) + { + if (is_numeric($id_group) === true && $id_group > 0) { + $this->fields['group'] = new Group($id_group); + } else { + return $this->fields['group']; + } + } + + + /** + * Returns AA modules as nodes for a map if any, if not, retrieves members. + * + * @return array Of PandoraFMS\Networkmap nodes. + */ + public function getNodes() + { + // Parse agents. + $nodes = []; + $node_count = 0; + $parent = $node_count; + $id_node = $node_count++; + $status = \agents_get_status_from_counts($this->agent()->toArray()); + $image = 'images/networkmap/'.os_get_icon($this->agent()->id_os()); + + if (empty($this->aaModules) === true) { + // No AA modules, use members. + $parent = $this->agent()->id_agente(); + + // Add node. + foreach ($this->members as $agent) { + $node = []; + + foreach ($agent->toArray() as $k => $v) { + $node[$k] = $v; + } + + $node['id_agente'] = $agent->id_agente(); + $node['id_parent'] = $parent; + $node['id_node'] = $node_count; + $node['image'] = 'images/networkmap/'.os_get_icon( + $agent->id_os() + ); + $node['status'] = \agents_get_status_from_counts( + $agent->toArray() + ); + + $nodes[$node_count++] = $node; + } + } else { + foreach ($this->aaModules as $cl_item) { + $cl_module = $cl_item->getModule(); + + if ($cl_module === null) { + continue; + } + + foreach ($this->members as $agent) { + $module = $agent->searchModules( + ['nombre' => $cl_module->nombre()] + ); + + if (empty($module) === true) { + // AA Module not found in member. + continue; + } + + // Transform multi array to get first occurrence. + // Warning. Here must only be 1 result. + $module = array_shift($module); + + $node = []; + + $node['type'] = NODE_GENERIC; + $node['label'] = $agent->alias().' » '; + $node['label'] .= $module->nombre(); + $node['id_agente'] = $module->id_agente(); + $node['id_agente_modulo'] = $module->id_agente_modulo(); + $node['id_parent'] = $parent; + $node['id_node'] = $node_count; + $node['image'] = 'images/networkmap/'.os_get_icon( + $agent->id_os() + ); + $node['status'] = $module->getStatus()->last_known_status(); + + $nodes[$node_count++] = $node; + } + } + } + + $nodes[$parent] = $this->agent()->toArray(); + $nodes[$parent] = ($nodes[$parent] + [ + 'id_parent' => $parent, + 'id_node' => $id_node, + 'status' => $status, + 'id_agente' => $this->agent()->id_agente(), + 'image' => $image, + ]); + + return $nodes; + } + + + /** + * Saves current group definition to database. + * + * @return mixed Affected rows of false in case of error. + * @throws \Exception On error. + */ + public function save() + { + $values = $this->fields; + + unset($values['agent']); + $values['group'] = $this->group()->id_grupo(); + if (isset($values['id']) === true && $values['id'] > 0) { + // Update. + $rs = \db_process_sql_update( + 'tcluster', + $values, + ['id' => $this->fields['id']] + ); + + if ($rs === false) { + global $config; + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + \db_pandora_audit( + AUDIT_LOG_AGENT_MANAGEMENT, + 'Cluster '.io_safe_output($this->fields['name']).' modified' + ); + } else { + // New. + $rs = \db_process_sql_insert( + 'tcluster', + $values + ); + + if ($rs === false) { + global $config; + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + $this->fields['id'] = $rs; + \db_pandora_audit( + AUDIT_LOG_AGENT_MANAGEMENT, + 'Cluster '.io_safe_output($this->fields['name']).' created' + ); + } + + $this->saveMembers(); + $this->saveItems(); + + return true; + } + + + /** + * Updates entries in tcluster_agent. + * + * @return void + * @throws \Exception On error. + */ + public function saveMembers() + { + $err = __METHOD__.' error: '; + + $values = []; + foreach ($this->members as $agent) { + $values[$agent->id_agente()] = [ + 'id_cluster' => $this->fields['id'], + 'id_agent' => $agent->id_agente(), + ]; + } + + if (empty($values) === true) { + return; + } + + // Clean previous relationships. + $rs = \db_process_sql_delete( + 'tcluster_agent', + [ 'id_cluster' => $this->fields['id'] ] + ); + + foreach ($values as $set) { + // Add current relationships. + $rs = \db_process_sql_insert( + 'tcluster_agent', + $set + ); + + if ($rs === false) { + global $config; + throw new \Exception( + $err.$config['dbconnection']->error + ); + } + } + } + + + /** + * Undocumented function + * + * @return void + */ + public function saveItems() + { + $items = $this->getItems(); + + foreach ($this->removedItems as $item) { + \db_process_sql_delete( + 'tcluster_item', + $item + ); + } + + // Save cluster modules. + foreach ($items as $item) { + $item->save(); + } + + } + + + /** + * Force cluster status module to be executed. + * + * @param boolean $get_informed Throw exception if clusterStatus is null. + * + * @return void + * @throws \Exception On error. + */ + public function force(?bool $get_informed=true) + { + if ($this->clusterStatus === null) { + if ($get_informed === true) { + throw new \Exception( + __METHOD__.' error: Cluster status module does not exist' + ); + } + } else { + $this->clusterStatus->flag(1); + $this->clusterStatus->save(); + } + } + + + /** + * Delete cluster from db. + * + * @return void + * @throws \Exception On error. + */ + public function delete() + { + global $config; + + if ($this->agent() !== null) { + // Delete agent and modules. + $this->agent()->delete(); + } + + // Remove entries from db. + // Table tcluster_agent. + $rs = \db_process_sql_delete( + 'tcluster_agent', + ['id_cluster' => $this->fields['id']] + ); + + if ($rs === false) { + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + // Table tcluster_item. + $rs = \db_process_sql_delete( + 'tcluster_item', + ['id_cluster' => $this->fields['id']] + ); + + if ($rs === false) { + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + // Table tcluster. + $rs = \db_process_sql_delete( + 'tcluster', + ['id' => $this->fields['id']] + ); + + if ($rs === false) { + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + \db_pandora_audit( + AUDIT_LOG_AGENT_MANAGEMENT, + 'Cluster '.io_safe_output($this->fields['name']).' deleted' + ); + + unset($this->aaModules); + unset($this->apModules); + unset($this->fields); + + } + + +} diff --git a/pandora_console/include/lib/ClusterModule.php b/pandora_console/include/lib/ClusterModule.php new file mode 100644 index 0000000000..19e25e6a5d --- /dev/null +++ b/pandora_console/include/lib/ClusterModule.php @@ -0,0 +1,268 @@ + 0) { + try { + parent::__construct('tcluster_item', ['id' => $id]); + } catch (\Exception $e) { + throw new \Exception('ClusterModule id not found.'); + } + + // Get module. + $this->module = Module::search( + [ + 'nombre' => $this->name(), + 'custom_integer_1' => $this->id_cluster(), + ], + 1 + ); + } else { + parent::__construct('tcluster_item'); + + $this->module = new Module(); + } + + } + + + /** + * Returns current object as array. + * + * @return array Of fields. + */ + public function toArray() + { + return $this->fields; + } + + + /** + * Associates a module to this clusterModule. + * + * @param array $params Module parameters. + * + * @return void + */ + public function setModule(array $params) + { + $this->module = new Module(); + foreach ($params as $k => $v) { + $this->module->{$k}($v); + } + } + + + /** + * Associates a module to this clusterModule. + * + * @param PandoraFMS\Module $module Module definition. + * + * @return void + */ + public function setModuleObject(Module $module) + { + $this->module = $module; + } + + + /** + * Returns current module. + * + * @return PandoraFMS\Module Object. + */ + public function getModule() + { + return $this->module; + } + + + /** + * Saves or retrieves value of warning_limit. + * + * @param float|null $value Warning value. + * + * @return mixed Value or empty. + */ + public function warning_limit(?float $value=null) + { + if ($value !== null) { + $this->fields['warning_limit'] = $value; + if ($this->module !== null) { + $this->module->min_warning($value); + } + } else { + return $this->fields['warning_limit']; + } + } + + + /** + * Saves or retrieves value of critical_limit. + * + * @param float|null $value Critical value. + * + * @return mixed Value or empty. + */ + public function critical_limit(?float $value=null) + { + if ($value !== null) { + $this->fields['critical_limit'] = $value; + if ($this->module !== null) { + $this->module->min_critical($value); + } + } else { + return $this->fields['critical_limit']; + } + } + + + /** + * Save ClusterModule. + * + * @return boolean True if success, false if error. + * @throws \Exception On db error. + */ + public function save() + { + $values = $this->fields; + + if ($this->module === null) { + return false; + } + + if (method_exists($this->module, 'save') === false) { + throw new \Exception( + __METHOD__.' error: Cluster module "'.$this->name().'" invalid.' + ); + } + + if (isset($values['id']) === true && $values['id'] > 0) { + // Update. + $rs = \db_process_sql_update( + 'tcluster_item', + $values, + ['id' => $this->fields['id']] + ); + + if ($rs === false) { + global $config; + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + if ($this->module === null) { + throw new \Exception( + __METHOD__.' error: Cluster module "'.$this->name().'" is not defined' + ); + } + + // Update reference. + $this->module->custom_integer_2($this->fields['id']); + + // Update module. + $this->module->save(); + + return true; + } else { + // New. + $rs = \db_process_sql_insert( + 'tcluster_item', + $values + ); + + if ($rs === false) { + global $config; + throw new \Exception( + __METHOD__.' error: '.$config['dbconnection']->error + ); + } + + $this->fields['id'] = $rs; + + // Update reference. + $this->module->custom_integer_2($this->fields['id']); + + // Update module. + $this->module->save(); + + return true; + } + + return false; + } + + + /** + * Erases this object and its module. + * + * @return void + */ + public function delete() + { + if (method_exists($this->module, 'delete') === true) { + $this->module->delete(); + } + + unset($this->fields); + unset($this->module); + + } + + +} diff --git a/pandora_console/include/lib/ClusterViewer/ClusterManager.php b/pandora_console/include/lib/ClusterViewer/ClusterManager.php new file mode 100644 index 0000000000..884be3f2a7 --- /dev/null +++ b/pandora_console/include/lib/ClusterViewer/ClusterManager.php @@ -0,0 +1,767 @@ + 'noaccess']); + } else { + include 'general/noaccess.php'; + } + + exit; + } + + $this->ajaxController = $ajax_page; + $this->url = $url; + + } + + + /** + * Main program starts here. + * + * @return void + */ + public function run() + { + + $operation = get_parameter('op', ''); + + switch ($operation) { + case 'new': + case 'update': + $this->showClusterEditor($operation); + break; + + case 'view': + $this->showCluster(); + break; + + case 'delete': + $this->deleteCluster(); + break; + + case 'force': + $this->forceCluster(); + break; + + default: + $n_clusters = $this->getCount(); + + if ($n_clusters > 0) { + $this->showList(); + } else { + $this->showWelcome(); + } + break; + } + } + + + /** + * Prints error message + * + * @param string $msg Message. + * + * @return void + */ + public function error(string $msg) + { + if (is_ajax()) { + echo json_encode( + ['error' => $msg] + ); + } else { + ui_print_error_message($msg); + } + } + + + /** + * Loads view 'first tasks' for cluster view. + * Old style. + * + * @return void + */ + public function showWelcome() + { + global $config; + include_once $config['homedir'].'/general/first_task/cluster_builder.php'; + } + + + /** + * Prepares available clusters definition for current users and loads view. + * + * @param string|null $msg Message (if any). + * + * @return void + */ + public function showList(?string $msg='') + { + global $config; + + // Extract data. + $n_clusters = $this->getCount(); + + if ($n_clusters > 0) { + $clusters = $this->getAll(); + } else { + $clusters = []; + } + + View::render( + 'cluster/list', + [ + 'message' => $msg, + 'config' => $config, + 'model' => $this, + 'n_clusters' => $n_clusters, + 'clusters' => $clusters, + ] + ); + } + + + /** + * Show cluster information. + * + * @param string|null $msg Message (if any). + * + * @return void + */ + public function showCluster(?string $msg=null) + { + global $config; + + $err = ''; + $id = get_parameter('id', null); + + try { + $cluster = new Cluster($id); + } catch (\Exception $e) { + $err = ui_print_error_message( + __('Cluster not found: '.$e->getMessage()), + '', + true + ); + } + + if ($cluster->agent()->id_agente() === null) { + // Failed. + $err = ui_print_error_message( + __('Cluster agent not found: '), + '', + true + ); + $critical = true; + } + + View::render( + 'cluster/view', + [ + 'message' => $msg, + 'error' => $err, + 'config' => $config, + 'model' => $this, + 'cluster' => $cluster, + 'critical' => $critical, + ] + ); + } + + + /** + * Removes a cluster from db. + * + * @return void + */ + public function deleteCluster() + { + $msg = ''; + $id = get_parameter('id', null); + + try { + $cluster = new Cluster($id); + $cluster->delete(); + unset($cluster); + } catch (\Exception $e) { + $msg = ui_print_error_message( + __('Error while deleting, reason: %s', $e->getMessage()), + '', + true + ); + } + + if (empty($msg) === true) { + $msg = ui_print_success_message( + __('Cluster successfully deleted.'), + '', + true + ); + } + + $this->showList($msg); + } + + + /** + * Force cluster execution. + * + * @return void + */ + public function forceCluster() + { + $msg = ''; + $id = get_parameter('id', null); + + try { + $cluster = new Cluster($id); + $cluster->force(); + unset($cluster); + } catch (\Exception $e) { + $msg = ui_print_error_message( + __('Error while forcing, reason: %s', $e->getMessage()), + '', + true + ); + } + + if (empty($msg) === true) { + $msg = ui_print_success_message( + __('Cluster successfully forced.'), + '', + true + ); + } + + $this->showCluster($msg); + } + + + /** + * Shows editor for target cluster (or new one). + * + * @param string $operation Current operation. + * + * @return void + */ + public function showClusterEditor(string $operation) + { + + global $config; + if (!check_acl($config['id_user'], 0, 'AW')) { + + db_pandora_audit( + AUDIT_LOG_ACL_VIOLATION, + 'Trying to create clusters' + ); + include 'general/noaccess.php'; + } else { + $wizard = new ClusterWizard( + $this->url, + $operation + ); + + $wizard->run(); + } + } + + + /** + * Returns number of clusters registered. + * + * @return integer + */ + public function getCount() + { + if (isset($this->count) !== true) { + $this->count = $this->getAll('count'); + } + + return $this->count; + } + + + /** + * Return all cluster definitons matching given filters. + * + * @param mixed $fields Fields array or 'count' keyword to retrieve + * count, null or default to use default ones. + * @param array $filter Filters to be applied. + * @param integer $offset Offset (pagination). + * @param integer $limit Limit (pagination). + * @param string $order Sort order. + * @param string $sort_field Sort field. + * + * @return array With all results or false if error. + * @throws \Exception On error. + */ + public static function getAll( + $fields=null, + array $filter=[], + ?int $offset=null, + ?int $limit=null, + ?string $order=null, + ?string $sort_field=null + ) { + $sql_filters = []; + $order_by = ''; + $pagination = ''; + + global $config; + + if (is_array($filter) === false) { + throw new \Exception('[ClusterManager::getAll] Filter must be an array.'); + } + + if (empty($filter['id_group']) === false + && (int) $filter['id_group'] !== 0 + ) { + $sql_filters[] = sprintf( + ' AND tc.`group` = %d', + $filter['id_group'] + ); + } + + if (empty($filter['free_search']) === false) { + $topic = io_safe_input($filter['free_search']); + $sql_filters[] = sprintf( + ' AND (lower(tc.name) like lower("%%%s%%") + OR lower(tc.description) like lower("%%%s%%") ) ', + $topic, + $topic + ); + } + + $count = false; + if (is_array($fields) === false && $fields === 'count') { + $fields = ['tc.*']; + $count = true; + } else if (is_array($fields) === false) { + // Default values. + $fields = [ + 'tc.*', + '(SELECT COUNT(*) FROM `tcluster_agent` WHERE `id_cluster` = tc.`id`) as `nodes`', + 'tas.known_status', + ]; + } + + if (isset($order) === true) { + $dir = 'asc'; + if ($order === 'desc') { + $dir = 'desc'; + }; + + if ($sort_field === 'type') { + $sort_field = 'cluster_type'; + } + + if (in_array( + $sort_field, + [ + 'name', + 'description', + 'group', + 'cluster_type', + 'nodes', + 'known_status', + ] + ) === true + ) { + $order_by = sprintf( + 'ORDER BY `%s` %s', + $sort_field, + $dir + ); + } + } + + if (isset($limit) === true && $limit > 0 + && isset($offset) === true && $offset >= 0 + ) { + $pagination = sprintf( + ' LIMIT %d OFFSET %d ', + $limit, + $offset + ); + } + + $sql = sprintf( + 'SELECT %s + FROM tcluster tc + LEFT JOIN tagente ta + ON tc.id_agent = ta.id_agente + LEFT JOIN tagente_modulo tam + ON tam.id_agente = tc.id_agent + AND tam.nombre = "%s" + LEFT JOIN tagente_estado tas + ON tam.id_agente_modulo=tas.id_agente_modulo + WHERE 1=1 + %s + %s + %s', + join(',', $fields), + io_safe_input('Cluster status'), + join(' ', $sql_filters), + $order_by, + $pagination + ); + + if ($count === true) { + $sql = sprintf('SELECT count(*) as n FROM ( %s ) tt', $sql); + + // Counter.. All data. + return db_get_value_sql($sql); + } + + return db_get_all_rows_sql($sql); + + } + + + /** + * Return data for datatables painting. + * + * @return void + * @throws \Exception On Error. + */ + public function draw() + { + global $config; + + // Datatables offset, limit and order. + $filter = get_parameter('filter', []); + $start = get_parameter('start', 0); + $length = get_parameter('length', $config['block_size']); + $order = get_datatable_order(true); + try { + ob_start(); + + $fields = [ + 'tc.*', + '(SELECT COUNT(*) FROM `tcluster_agent` WHERE `id_cluster` = tc.`id`) as `nodes`', + 'tas.known_status', + ]; + + // Retrieve data. + $data = self::getAll( + // Fields. + $fields, + // Filter. + $filter, + // Offset. + $start, + // Limit. + $length, + // Order. + $order['direction'], + // Sort field. + $order['field'] + ); + + // Retrieve counter. + $count = self::getAll( + 'count', + $filter + ); + + if ($data) { + $data = array_reduce( + $data, + function ($carry, $item) { + global $config; + // Transforms array of arrays $data into an array + // of objects, making a post-process of certain fields. + $tmp = (object) $item; + + $manage = check_acl( + $config['id_user'], + $tmp->group, + 'AW', + true + ); + + $tmp->name = ''.$tmp->name.''; + + if (empty($tmp->group) === true) { + $tmp->group = __('Not set'); + } else { + $tmp->group = ui_print_group_icon( + $tmp->group, + true + ); + } + + // Type. + if ($tmp->cluster_type === 'AA') { + $tmp->type = __('Active-Active'); + } else if ($tmp->cluster_type === 'AP') { + $tmp->type = __('Active-Passive'); + } else { + $tmp->type = __('Unknown'); + } + + // Status. + $tmp->known_status = ui_print_module_status( + $tmp->known_status, + true + ); + + // Options. View. + $tmp->options = ''; + $tmp->options .= html_print_image( + 'images/operation.png', + true, + [ + 'title' => __('View'), + 'class' => 'invert_filter', + ] + ); + $tmp->options .= ''; + + if ($manage) { + // Options. Edit. + $tmp->options .= ''; + $tmp->options .= html_print_image( + 'images/config.png', + true, + [ + 'title' => __('Edit'), + 'class' => 'invert_filter', + ] + ); + $tmp->options .= ''; + + // Options. Delete. + $tmp->options .= ''; + $tmp->options .= html_print_image( + 'images/cross.png', + true, + [ + 'title' => __('Delete'), + 'class' => 'invert_filter', + ] + ); + $tmp->options .= ''; + } + + $carry[] = $tmp; + return $carry; + } + ); + } + + // Datatables format: RecordsTotal && recordsfiltered. + echo json_encode( + [ + 'data' => $data, + 'recordsTotal' => $count, + 'recordsFiltered' => $count, + ] + ); + // Capture output. + $response = ob_get_clean(); + } catch (\Exception $e) { + echo json_encode(['error' => $e->getMessage()]); + exit; + } + + // If not valid, show error with issue. + json_decode($response); + if (json_last_error() == JSON_ERROR_NONE) { + // If valid dump. + echo $response; + } else { + echo json_encode( + ['error' => $response] + ); + } + } + + + /** + * Provides data for wizard. Ajax method. + * + * @return void + */ + public function getAgentsFromGroup() + { + $side = get_parameter('side', null); + $id = get_parameter('id', null); + $group_id = get_parameter('group_id', 0); + $group_recursion = (bool) get_parameter('group_recursion', 0); + + $groups = []; + if ($group_recursion === true) { + $groups = groups_get_children_ids($group_id, true); + } else { + $groups = $group_id; + } + + if ($side === 'left') { + // Available agents. + $agents = agents_get_agents( + [ 'id_grupo' => $groups ], + [ + 'id_agente', + 'alias', + ] + ); + + $agents = array_reduce( + $agents, + function ($carry, $item) { + $carry[$item['id_agente']] = io_safe_output($item['alias']); + return $carry; + } + ); + } else if ($side === 'right') { + // Selected agents. + $cluster = new Cluster($id); + $agents = $cluster->getMembers(); + $agents = array_reduce( + $agents, + function ($carry, $item) use ($groups) { + if (in_array($item->id_grupo(), $groups) === true) { + $carry[$item->id_agente()] = io_safe_output( + $item->alias() + ); + } + + return $carry; + } + ); + } + + if (empty($agents) === true) { + echo '[]'; + } else { + // Dump response. + echo json_encode($agents); + } + } + + + /** + * Returns a goBack form structure. + * + * @return array Form structure. + */ + public function getGoBackForm() + { + $form['form']['action'] = $this->url; + $form['form']['method'] = 'POST'; + $form['form']['id'] = 'go-back-form'; + $form['inputs'] = [ + [ + 'arguments' => [ + 'name' => 'submit', + 'label' => __('Go back'), + 'type' => 'submit', + 'attributes' => 'class="sub cancel"', + 'return' => true, + ], + ], + ]; + + return $form; + } + + +} diff --git a/pandora_console/include/lib/ClusterViewer/ClusterWizard.php b/pandora_console/include/lib/ClusterViewer/ClusterWizard.php new file mode 100644 index 0000000000..50a14d9c85 --- /dev/null +++ b/pandora_console/include/lib/ClusterViewer/ClusterWizard.php @@ -0,0 +1,1258 @@ + 'A-A Modules', + 3 => 'A-A thresholds', + 6 => 'Alerts', + ]; + + /** + * Label set for AP clusters. + * + * @var array + */ + public $APLabels = [ + 2 => 'A-P Modules', + 3 => 'A-P thresholds', + 4 => 'A-P module', + 5 => 'Critical A-P modules', + 6 => 'Alerts', + ]; + + /** + * Variable to store error messages while parsing + * different steps. + * + * @var string + */ + public $errMessages = []; + + /** + * Current operation (New | Update). + * + * @var string + */ + public $operation; + + /** + * Parent url (for go back forms). + * + * @var string + */ + public $parentUrl; + + /** + * Current cluster definition (if any). + * + * @var PandoraFMS\ClusterViewer\Cluster + */ + private $cluster; + + /** + * Current cluster agent definition (if any). + * + * @var array + */ + private $agent; + + + /** + * Builds a Cluster Wizard. + * + * @param string $url Main url. + * @param string $operation Operation (new|update). + */ + public function __construct(string $url, string $operation=null) + { + // Check access. + check_login(); + + ui_require_css_file('wizard'); + ui_require_css_file('discovery'); + + $this->access = 'AW'; + $this->operation = $operation; + $this->url = $url; + $this->parentUrl = $url; + $this->page = (int) get_parameter('page', 0); + $this->id = (int) get_parameter('id', 0); + } + + + /** + * Run wizard. + * + * @return void + * @throws \Exception On error. + */ + public function run() + { + global $config; + + ui_require_css_file('cluster_wizard'); + + $this->operation = get_parameter('op', ''); + $cluster_id = get_parameter('id', ''); + $name = get_parameter('name', ''); + + $this->errMessages = []; + + // Cluster initialization. Load. + $load_success = true; + + try { + if (empty($cluster_id) === false) { + // Load data. + $this->cluster = new Cluster($cluster_id); + + if ($this->cluster->agent()->id_agente() === null) { + $this->errMessages['noagent'] = 'Agent associated to cluster does not exist. Please update to create it.'; + } + + if ($this->cluster->group()->id_grupo() === null) { + throw new \Exception( + 'Group associated to cluster does not exist.' + ); + } + } else if (empty($name) === false) { + $cluster_data = Cluster::search(['name' => $name]); + + if ($cluster_data !== false) { + $init_failed = true; + $this->page--; + throw new \Exception( + __('Cluster already defined, please use another name.') + ); + } + } + } catch (\Exception $e) { + $this->errMessages[] = $e->getMessage(); + $load_success = false; + } + + if (empty($this->cluster) === true) { + // Empty cluster. Initialize. + $this->cluster = new Cluster(); + } else { + // Cluster already exists. Update operation. + $this->operation = 'update'; + } + + try { + // Check user has grants to edit this cluster. + if ($this->operation !== 'new' + && (!check_acl( + $config['id_user'], + $this->cluster->group()->id_grupo(), + 'AW' + )) + ) { + // User has no grants to edit this cluster. + throw new \Exception( + 'You have no permission to edit this cluster.' + ); + } + } catch (\Exception $e) { + $this->errMessages[] = $e->getMessage(); + $load_success = false; + } + + if ($load_success === true) { + if ($this->cluster->id() === null + && $this->page > 1 + ) { + $load_success = false; + $this->errMessages[] = 'Please define this cluster first'; + } else { + try { + // Parse results (previous step). + $status = $this->parseForm(); + } catch (\Exception $e) { + $this->errMessages[] = $e->getMessage(); + if ($this->page > 0) { + $this->page--; + } + } + } + } + + // Get form structure (current page). + $form = $this->getForm($load_success); + + // Force Cluster calculation. Cluster defined. + $this->cluster->force(false); + + View::render( + 'cluster/edit', + [ + 'config' => $config, + 'wizard' => $this, + 'model' => $this, + 'cluster' => $this->cluster, + 'form' => $form, + ] + ); + } + + + /** + * Retrieve page value. + * + * @return integer Page value. + */ + public function getPage() + { + return $this->page; + } + + + /** + * Set page to target value., + * + * @param integer $page New page value. + * + * @return void + */ + public function setPage(int $page) + { + $this->page = $page; + } + + + /** + * Return current operation. + * + * @return string New or Update. + */ + public function getOperation() + { + return $this->operation; + } + + + /** + * Retrieve labels. + * + * @return array With labels (breadcrum). + */ + public function getLabels() + { + $labels = $this->labels; + if ($this->cluster->cluster_type() !== null) { + if ($this->cluster->cluster_type() === 'AA') { + $labels = ($this->labels + $this->AALabels); + } else { + $labels = ($this->labels + $this->APLabels); + } + } + + return $labels; + } + + + /** + * Returns a goBack form structure. + * + * @param boolean $main Go to main page. + * + * @return array Form structure. + */ + public function getGoBackForm(?bool $main=false) + { + $url = $this->url; + + if ($main === false) { + $page = ($this->page - 1); + + if ($page >= 0) { + $extra_url = ''; + if ($this->cluster->id() !== null) { + $extra_url = '&id='.$this->cluster->id(); + if ($this->cluster->cluster_type() === 'AA') { + // Jump from Alerts back to A-A Thresholds. + if ($page === 5) { + $page = 3; + } + } + } + + $url = $this->url.'&op='.$this->operation; + $url .= '&page='.$page.$extra_url; + } + } + + $form['form']['action'] = $url; + $form['form']['method'] = 'POST'; + $form['form']['id'] = 'go-back-form'; + $form['inputs'] = [ + [ + 'arguments' => [ + 'name' => 'submit', + 'label' => __('Go back'), + 'type' => 'submit', + 'attributes' => 'class="sub cancel"', + 'return' => true, + ], + ], + ]; + + return $form; + } + + + /** + * Parse responses from previous steps. + * + * @return void + * @throws \Exception On error. + */ + private function parseForm() + { + global $config; + + // Parse user responses. + if ($this->page <= 0) { + // No previous steps, return OK. + return; + } + + if ($this->page === 1) { + /* + * + * PARSE DEFINITION. + * + */ + + $name = get_parameter('name', ''); + $type = get_parameter('type', null); + $description = get_parameter('description', ''); + $id_group = get_parameter('id_group', ''); + $server_name = get_parameter('server_name', ''); + + if ($name === '' + && $type === null + && $description === '' + && $id_group === '' + && $server_name === '' + ) { + if ($this->cluster->id() === null) { + throw new \Exception( + 'Please fulfill all required fields.' + ); + } + + // Default values, show page. + return; + } + + if (empty($name) === true + || empty($type) === true + || empty($id_group) === true + || empty($server_name) === true + ) { + if (empty($server_name) === true) { + throw new \Exception( + 'Please select a valid Prediction server' + ); + } + + throw new \Exception('Please fulfill all required fields'); + } + + // Verify cluster type is one from the list. + if (in_array($type, ['AA', 'AP']) === false) { + throw new \Exception('Invalid cluster type selected'); + } + + if ($this->cluster->id() === null) { + // Create. + // 1. Create agent. + $this->cluster->agent()->alias($name); + $this->cluster->agent()->comentarios($description); + $this->cluster->agent()->intervalo(300); + $this->cluster->agent()->id_grupo($id_group); + $this->cluster->agent()->id_os(CLUSTER_OS_ID); + $this->cluster->agent()->server_name($server_name); + $this->cluster->agent()->modo(1); + + $this->cluster->agent()->save(); + + if ($this->cluster->agent()->id_agente() === false) { + throw new \Exception( + 'Failed to create agent: '.$config['dbconnection']->error + ); + } + + // 2. Create cluster entry. + $this->cluster->name($name); + $this->cluster->cluster_type($type); + $this->cluster->description($description); + $this->cluster->group($id_group); + $this->cluster->id_agent($this->cluster->agent()->id_agente()); + + $this->cluster->save(); + + if ($this->cluster->id() === null) { + // Delete agent created in previous step. + \agents_delete_agent($this->cluster->agent()->id()); + + throw new \Exception( + 'Failed to create cluster: '.$config['dbconnection']->error + ); + } + + // 3. Create cluster module in agent. + $this->cluster->agent()->addModule( + [ + 'nombre' => io_safe_input('Cluster status'), + 'id_modulo' => 5, + 'prediction_module' => 5, + 'custom_integer_1' => $this->cluster->id(), + 'id_tipo_modulo' => 1, + 'descripcion' => io_safe_input( + 'Cluster status information module' + ), + 'min_warning' => 1, + 'min_critical' => 2, + ] + ); + } else { + // Update. + $this->cluster->name($name); + $this->cluster->cluster_type($type); + $this->cluster->description($description); + $this->cluster->group($id_group); + + $this->cluster->agent()->alias($name); + $this->cluster->agent()->comentarios($description); + $this->cluster->agent()->intervalo(300); + $this->cluster->agent()->id_grupo($id_group); + $this->cluster->agent()->id_os(CLUSTER_OS_ID); + $this->cluster->agent()->server_name($server_name); + $this->cluster->agent()->modo(1); + $this->cluster->agent()->save(); + + // 2. Re link. + $this->cluster->id_agent($this->cluster->agent()->id_agente()); + $this->cluster->save(); + + // If agent has been deleted, recreate module. + if ($this->errMessages['noagent'] !== null) { + // 3. Create cluster module in agent. + $this->cluster->agent()->addModule( + [ + 'nombre' => io_safe_input('Cluster status'), + 'id_modulo' => 5, + 'prediction_module' => 5, + 'custom_integer_1' => $this->cluster->id(), + 'id_tipo_modulo' => 1, + 'descripcion' => io_safe_input( + 'Cluster status information module' + ), + 'min_warning' => 1, + 'min_critical' => 2, + ] + ); + } + + unset($this->errMessages['noagent']); + } + + return; + } + + if ($this->page === 2) { + /* + * + * PARSE MEMBERS. + * + */ + + // Parse responses from page 1. + $agents_selected = get_parameter('selected-select-members', null); + + if ($agents_selected === null) { + // Direct access. + return; + } + + // Clear members. Reparse. + $this->cluster->cleanMembers(); + + // Remove 'None' field. + if (array_search(0, $agents_selected) === 0) { + unset($agents_selected[0]); + } + + if (empty($agents_selected) === true) { + throw new \Exception('No members selected'); + } + + foreach ($agents_selected as $id_agent) { + $agent = $this->cluster->addMember($id_agent); + + \db_pandora_audit( + AUDIT_LOG_AGENT_MANAGEMENT, + 'Agent '.io_safe_output($agent->alias()).' added to cluster '.io_safe_output( + $this->cluster->name() + ) + ); + } + + $this->cluster->save(); + + return; + } + + if ($this->page === 3) { + /* + * + * PARSE AA MODULES. + * + */ + + $aa_modules = get_parameter('selected-select-aa-modules', null); + + if (is_array($aa_modules) === true) { + if ($aa_modules[0] === '0') { + unset($aa_modules[0]); + } + + $current = array_keys($this->cluster->getAAModules()); + $removed = array_diff($current, $aa_modules); + $changes = false; + + foreach ($aa_modules as $m) { + $this->cluster->addAAModule($m); + $changes = true; + } + + foreach ($removed as $m) { + $this->cluster->removeAAModule($m); + $changes = true; + } + + if ($changes === true) { + $this->cluster->save(); + } + } + + return; + } + + if ($this->page === 4) { + /* + * + * PARSE AA THRESHOLDS + * + */ + + $modules = $this->cluster->getAAModules(); + + $changes = false; + + foreach ($modules as $item) { + $value_warning = get_parameter( + 'warning-'.md5($item->name()), + null + ); + + $value_critical = get_parameter( + 'critical-'.md5($item->name()), + null + ); + + if ($value_warning !== null) { + $item->warning_limit($value_warning); + $changes = true; + } + + if ($value_critical !== null) { + $item->critical_limit($value_critical); + $changes = true; + } + } + + if ($changes === true) { + $this->cluster->save(); + } + + if ($this->cluster->cluster_type() === 'AA') { + // Force next page '6' (alerts). + $this->page = 6; + } + + return; + } + + if ($this->page === 5) { + /* + * + * PARSE AP MODULES + * + */ + + if ($this->cluster->cluster_type() === 'AA') { + // Direct access. Accessed by URL. + $this->page = 0; + throw new \Exception( + 'Unavailable page for this cluster type, please follow this wizard.' + ); + } + + $ap_modules = get_parameter('selected-select-ap-modules', null); + if (is_array($ap_modules) === true) { + if ($ap_modules[0] === '0') { + unset($ap_modules[0]); + } + + $current = array_keys($this->cluster->getAPModules()); + $removed = array_diff($current, $ap_modules); + $changes = false; + + foreach ($ap_modules as $m) { + $this->cluster->addAPModule($m); + $changes = true; + } + + foreach ($removed as $m) { + $this->cluster->removeAPModule($m); + $changes = true; + } + + if ($changes === true) { + $this->cluster->save(); + } + } + + return; + } + + if ($this->page === 6) { + /* + * + * PARSE AP MODULES CRITICAL + * + */ + + if ($this->cluster->cluster_type() === 'AA') { + // Direct access. + return; + } + + $modules = $this->cluster->getAPModules(); + $changes = false; + + foreach ($modules as $item) { + $value = get_parameter_switch( + 'switch-'.md5($item->name()), + null + ); + + if ($value !== null) { + // Unchecked. + $item->is_critical($value); + $changes = true; + } + } + + if ($changes === true) { + $this->cluster->save(); + } + + return; + } + + if ($this->page === 7) { + /* + * + * PARSE ALERTS + * + */ + + // There is no need to parse anything. Already managed by alert + // builder. + header('Location: '.$this->url.'&op=view&id='.$this->cluster->id()); + } + + throw new \Exception('Unexpected error'); + } + + + /** + * Retrieves form estructure for current step. + * + * @param boolean $load_success Load process has been success or not. + * + * @return array Form. + */ + private function getForm(?bool $load_success=true) + { + $form = []; + $final = false; + + $extra_url = ''; + if ($this->cluster->id() !== null) { + $extra_url = '&id='.$this->cluster->id(); + } + + $url = $this->url.'&op='.$this->operation; + $target_url .= $url.'&page='.($this->page + 1).$extra_url; + + $form['form'] = [ + 'action' => $target_url, + 'method' => 'POST', + 'extra' => 'autocomplete="false"', + ]; + + if ($load_success === false && $this->page !== 0) { + return []; + } + + if ($this->page === 0) { + /* + * + * Page: Cluster Definition. + * + */ + + // Input cluster name. + $form['inputs'][] = [ + 'label' => ''.__('Cluster name').''.ui_print_help_tip( + __('An agent with the same name of the cluster will be created, as well a special service with the same name'), + true + ), + 'arguments' => [ + 'name' => 'name', + 'value' => $this->cluster->name(), + 'type' => 'text', + 'size' => 25, + 'required' => true, + ], + ]; + + // Input cluster type. + $form['inputs'][] = [ + 'label' => ''.__('Cluster type').''.ui_print_help_tip( + __('AA is a cluster where all members are working. In AP cluster only master member is working'), + true + ), + 'arguments' => [ + 'name' => 'type', + 'selected' => $this->cluster->cluster_type(), + 'type' => 'select', + 'fields' => [ + 'AA' => __('Active - Active'), + 'AP' => __('Active - Pasive'), + ], + 'required' => true, + ], + ]; + + // Input cluster description. + $form['inputs'][] = [ + 'label' => ''.__('Description').'', + 'arguments' => [ + 'name' => 'description', + 'value' => $this->cluster->description(), + 'type' => 'text', + 'size' => 25, + ], + ]; + + // Input Group. + $form['inputs'][] = [ + 'label' => ''.__('Group').''.ui_print_help_tip( + __('Target cluster agent will be stored under this group'), + true + ), + 'arguments' => [ + 'name' => 'id_group', + 'returnAllGroup' => false, + 'privilege' => $this->access, + 'type' => 'select_groups', + 'selected' => $this->cluster->group()->id_grupo(), + 'return' => true, + 'required' => true, + ], + ]; + + // Input. Servername. + $form['inputs'][] = [ + 'label' => ''.__('Prediction server').':'.ui_print_help_tip( + __('You must select a Prediction Server to perform all cluster status calculations'), + true + ), + 'arguments' => [ + 'type' => 'select_from_sql', + 'sql' => sprintf( + 'SELECT name as k, name as v + FROM tserver + WHERE server_type = %d + ORDER BY name', + SERVER_TYPE_PREDICTION + ), + 'name' => 'server_name', + 'selected' => $this->cluster->agent()->server_name(), + 'return' => true, + 'required' => true, + ], + ]; + } else if ($this->page === 1) { + /* + * + * Page: Cluster members. + * + */ + + $all_agents = agents_get_agents( + false, + [ + 'id_agente', + 'alias', + ] + ); + + if ($all_agents === false) { + $all_agents = []; + } + + $all_agents = array_reduce( + $all_agents, + function ($carry, $item) { + $carry[$item['id_agente']] = $item['alias']; + return $carry; + }, + [] + ); + + $selected = $this->cluster->getMembers(); + + $selected = array_reduce( + $selected, + function ($carry, $item) use (&$all_agents) { + $carry[$item->id_agente()] = $item->alias(); + unset($all_agents[$item->id_agente()]); + return $carry; + }, + [] + ); + + $form['inputs'][] = [ + 'arguments' => [ + 'type' => 'select_multiple_filtered', + 'class' => 'w80p mw600px', + 'name' => 'members', + 'available' => $all_agents, + 'selected' => $selected, + 'group_filter' => [ + 'page' => 'operation/cluster/cluster', + 'method' => 'getAgentsFromGroup', + 'id' => $this->cluster->id(), + ], + 'texts' => [ + 'title-left' => 'Available agents', + 'title-right' => 'Selected cluster members', + ], + ], + ]; + } else if ($this->page === 2) { + /* + * + * Page: A-A modules. + * + */ + + $selected = $this->cluster->getAAModules(); + + $selected = array_reduce( + $selected, + function ($carry, $item) { + $name = io_safe_output($item->name()); + $carry[$name] = $name; + return $carry; + }, + [] + ); + + $members = $this->cluster->getMembers(); + + // Agent ids are stored in array keys. + $members = array_keys($members); + + // Get common modules. + $modules = \select_modules_for_agent_group( + // Module group. 0 => All. + 0, + // Agents. + $members, + // Show all modules or common ones. + false, + // Return. + false, + // Group by name. + true + ); + + // Escape html special chars on array keys for select value. + $modules = array_combine( + array_map( + function ($k) { + return htmlspecialchars($k); + }, + array_keys($modules) + ), + $modules + ); + + $selected = array_combine( + array_map( + function ($k) { + return htmlspecialchars($k); + }, + array_keys($selected) + ), + $selected + ); + + $modules = array_diff_key($modules, $selected); + if ($this->cluster->cluster_type() === 'AP') { + $form['inputs'][] = [ + 'arguments' => [ + 'type' => 'select_multiple_filtered', + 'class' => 'w80p mw600px', + 'name' => 'aa-modules', + 'available' => $modules, + 'selected' => $selected, + 'texts' => [ + 'title-left' => 'Available modules (common)', + 'title-right' => 'Selected active-passive modules', + 'filter-item' => 'Filter options by module name', + ], + 'sections' => [ + 'filters' => 1, + 'item-available-filter' => 1, + 'item-selected-filter' => 1, + ], + ], + ]; + } else if ($this->cluster->cluster_type() === 'AA') { + $form['inputs'][] = [ + 'arguments' => [ + 'type' => 'select_multiple_filtered', + 'class' => 'w80p mw600px', + 'name' => 'aa-modules', + 'available' => $modules, + 'selected' => $selected, + 'texts' => [ + 'title-left' => 'Available modules (common)', + 'title-right' => 'Selected active-active modules', + 'filter-item' => 'Filter options by module name', + ], + 'sections' => [ + 'filters' => 1, + 'item-available-filter' => 1, + 'item-selected-filter' => 1, + ], + ], + ]; + } + } else if ($this->page === 3) { + /* + * + * Page: A-A module limits. + * + */ + + $aa_modules = $this->cluster->getAAModules(); + $inputs = []; + foreach ($aa_modules as $module) { + $inputs[] = [ + 'block_id' => 'from-to-threshold', + 'class' => 'flex-row line w100p', + 'direct' => 1, + 'block_content' => [ + [ + 'label' => ''.$module->name().'', + ], + [ + 'label' => ''.__('critical if').'', + 'arguments' => [ + 'name' => 'critical-'.md5($module->name()), + 'type' => 'number', + 'value' => $module->critical_limit(), + 'required' => true, + ], + ], + [ + 'label' => __('% of balanced modules are down (equal or greater).'), + ], + ], + ]; + + $inputs[] = [ + 'block_id' => 'from-to-threshold', + 'class' => 'flex-row line w100p', + 'direct' => 1, + 'block_content' => [ + [ + 'label' => ''.$module->name().'', + ], + [ + 'label' => ''.('warning if').'', + 'arguments' => [ + 'name' => 'warning-'.md5($module->name()), + 'type' => 'number', + 'value' => $module->warning_limit(), + 'required' => true, + ], + ], + [ + 'label' => __('% of balanced modules are down (equal or greater).'), + ], + ], + ]; + + $inputs[] = [ + 'block_id' => 'from-to-threshold', + 'class' => 'flex-row line w100p', + 'direct' => 1, + 'block_content' => [], + ]; + } + + if ($this->cluster->cluster_type() === 'AP') { + $form['inputs'][] = [ + 'label' => __( + 'Please, set thresholds for all active-passive modules'.ui_print_help_tip( + 'If you want your cluster module to be critical when 3 of 6 instances are down, set critical to \'50%\'', + true + ) + ), + 'class' => 'indented', + 'block_content' => $inputs, + ]; + } else if ($this->cluster->cluster_type() === 'AA') { + $form['inputs'][] = [ + 'label' => __( + 'Please, set thresholds for all active-active modules'.ui_print_help_tip( + 'If you want your cluster module to be critical when 3 of 6 instances are down, set critical to \'50%\'', + true + ) + ), + 'class' => 'indented', + 'block_content' => $inputs, + ]; + } + } else if ($this->page === 4) { + /* + * + * Page: A-P modules. + * + */ + + $selected = $this->cluster->getAPModules(); + $aa = $this->cluster->getAAModules(); + + $selected = array_reduce( + $selected, + function ($carry, $item) { + $name = io_safe_output($item->name()); + $carry[$name] = $name; + return $carry; + }, + [] + ); + + $aa = array_reduce( + $aa, + function ($carry, $item) { + $name = io_safe_output($item->name()); + $carry[$name] = $name; + return $carry; + }, + [] + ); + + $members = $this->cluster->getMembers(); + + // Agent ids are stored in array keys. + $members = array_keys($members); + + // Get common modules. + $modules = \select_modules_for_agent_group( + // Module group. 0 => All. + 0, + // Agents. + $members, + // Show all modules or common ones. + true, + // Return. + false, + // Group by name. + true + ); + + // Exclude AA modules from available options. + $modules = array_diff_key($modules, $aa); + + // Exclude already used from available options. + $modules = array_diff_key($modules, $selected); + + $form['inputs'][] = [ + 'arguments' => [ + 'type' => 'select_multiple_filtered', + 'class' => 'w80p mw600px', + 'name' => 'ap-modules', + 'available' => $modules, + 'selected' => $selected, + 'texts' => [ + 'title-left' => 'Available modules (any)', + 'title-right' => 'Selected active-passive modules', + 'filter-item' => 'Filter options by module name', + ], + 'sections' => [ + 'filters' => 1, + 'item-available-filter' => 1, + 'item-selected-filter' => 1, + ], + ], + ]; + } else if ($this->page === 5) { + /* + * + * Page: A-P critical modules. + * + */ + + $ap_modules = $this->cluster->getAPModules(); + $inputs = []; + foreach ($ap_modules as $module) { + $inputs[] = [ + 'label' => $module->name(), + 'arguments' => [ + 'type' => 'switch', + 'name' => 'switch-'.md5($module->name()), + 'value' => $module->is_critical(), + ], + ]; + } + + $form['inputs'][] = [ + 'label' => __( + 'Please, check all active-passive modules critical for this cluster' + ).ui_print_help_tip( + __('If a critical balanced module is going to critical status, then cluster will be critical.'), + true + ), + 'class' => 'indented', + 'block_content' => $inputs, + ]; + } else if ($this->page === 6) { + /* + * + * Page: Alerts. + * + */ + + ob_start(); + global $config; + + $id_agente = $this->cluster->agent()->id_agente(); + $dont_display_alert_create_bttn = true; + include_once $config['homedir'].'/godmode/alerts/alert_list.php'; + include_once $config['homedir'].'/godmode/alerts/alert_list.builder.php'; + + // XXX: Please do not use this kind of thing never more. + $hack = ob_get_clean(); + + // TODO: Alert form. + $form['pre-content'] = $hack; + + $final = true; + } + + // Submit. + $str = __('Next'); + if ($this->cluster->id() !== null) { + $str = __('Update and continue'); + } + + if ($final === true) { + $str = __('Finish'); + } + + // Submit button. + $form['inputs'][] = [ + 'arguments' => [ + 'name' => 'next', + 'label' => $str, + 'type' => 'submit', + 'attributes' => 'class="sub next"', + 'return' => true, + ], + ]; + + return $form; + } + + +} diff --git a/pandora_console/operation/agentes/estado_agente.php b/pandora_console/operation/agentes/estado_agente.php index 0210545a26..dc15caeaa1 100644 --- a/pandora_console/operation/agentes/estado_agente.php +++ b/pandora_console/operation/agentes/estado_agente.php @@ -847,10 +847,10 @@ foreach ($agents as $agent) { if ($agent['id_os'] == CLUSTER_OS_ID) { if (enterprise_installed()) { - $cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId( + $cluster = PandoraFMS\Cluster::loadFromAgentId( $agent['id_agente'] ); - $url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR; + $url = 'index.php?sec=reporting&sec2='; $url .= '/operation/cluster/cluster'; $url = ui_get_full_url( $url.'&op=view&id='.$cluster->id() @@ -866,10 +866,10 @@ foreach ($agents as $agent) { if ($agent['id_os'] == CLUSTER_OS_ID) { if (enterprise_installed()) { - $cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId( + $cluster = PandoraFMS\Cluster::loadFromAgentId( $agent['id_agente'] ); - $url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR; + $url = 'index.php?sec=reporting&sec2='; $url .= '/operation/cluster/cluster'; $url = ui_get_full_url( $url.'&op=update&id='.$cluster->id() diff --git a/pandora_console/operation/cluster/cluster.php b/pandora_console/operation/cluster/cluster.php new file mode 100755 index 0000000000..2cc078ef4b --- /dev/null +++ b/pandora_console/operation/cluster/cluster.php @@ -0,0 +1,70 @@ + '[ClusterManager]'.$e->getMessage() ]); + exit; + } else { + echo '[ClusterManager]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; +} + +// AJAX controller. +if (is_ajax()) { + $method = get_parameter('method'); + + if (method_exists($obj, $method) === true) { + $obj->{$method}(); + } else { + $obj->error('Method not found. [ClusterManager::'.$method.']'); + } + + // Stop any execution. + exit; +} else { + // Run. + $obj->run(); +} diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index fb303dd3fa..e933cf91f6 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -147,7 +147,12 @@ if ($access_console_node === true) { $sub['snmpconsole']['subtype'] = 'nolink'; } - enterprise_hook('cluster_menu'); + if (check_acl($config['id_user'], 0, 'AR')) { + $sub['operation/cluster/cluster']['text'] = __('Cluster View'); + $sub['operation/cluster/cluster']['id'] = 'cluster'; + $sub['operation/cluster/cluster']['refr'] = 0; + } + enterprise_hook('aws_menu'); enterprise_hook('SAP_view'); diff --git a/pandora_console/views/cluster/edit.php b/pandora_console/views/cluster/edit.php new file mode 100644 index 0000000000..393951f470 --- /dev/null +++ b/pandora_console/views/cluster/edit.php @@ -0,0 +1,129 @@ +operation; + +if ($wizard->id !== null) { + $extra .= '&id='.$wizard->id; +} + +$bc[] = [ + 'link' => $wizard->parentUrl, + 'label' => __('Cluster list'), + 'selected' => false, +]; + +$labels = $wizard->getLabels(); +foreach ($labels as $key => $label) { + $bc[] = [ + 'link' => $wizard->url.(($key >= 0) ? $extra.'&page='.$key : ''), + 'label' => __($label), + 'selected' => ($wizard->page == $key), + ]; +} + +$wizard->prepareBreadcrum($bc); + +$header_str = __(ucfirst($wizard->getOperation())).' '; +$header_str .= (($cluster->name() !== null) ? $cluster->name() : __('cluster ')); +$header_str .= ' » '.__($labels[$wizard->page]); + +// Header. +$buttons = []; + +$main_page = ''; +$main_page .= html_print_image( + 'images/list.png', + true, + [ + 'title' => __('Cluster list'), + 'class' => 'invert_filter', + ] +); +$main_page .= ''; + +$buttons = [ + [ + 'active' => false, + 'text' => $main_page, + ], +]; + +if ($cluster !== null) { + if ($cluster->id() !== null) { + $view = ''; + $view .= html_print_image( + 'images/operation.png', + true, + [ + 'title' => __('View this cluster'), + 'class' => 'invert_filter', + ] + ); + $view .= ''; + + $buttons[] = [ + 'active' => false, + 'text' => $view, + ]; + } +} + +ui_print_page_header( + $header_str, + '', + false, + 'cluster_view', + true, + // Buttons. + $buttons, + false, + '', + GENERIC_SIZE_TEXT, + '', + $wizard->printHeader(true) +); + +// Check if any error ocurred. +if (empty($wizard->errMessages) === false) { + foreach ($wizard->errMessages as $msg) { + ui_print_error_message(__($msg)); + } +} + +if (empty($form) === false) { + // Print form (prepared in ClusterWizard). + HTML::printForm($form, false, ($wizard->page < 6)); +} + +// Print always go back button. +HTML::printForm($wizard->getGoBackForm(), false); diff --git a/pandora_console/views/cluster/list.php b/pandora_console/views/cluster/list.php new file mode 100644 index 0000000000..c72f1752a1 --- /dev/null +++ b/pandora_console/views/cluster/list.php @@ -0,0 +1,132 @@ + 'options', + 'class' => 'action_buttons', + ], + ]; + + $column_names = [ + __('Name'), + __('Description'), + __('Group'), + __('Type'), + __('Nodes'), + __('Status'), + __('Options'), + ]; + + $tableId = 'clusters'; + + // Load datatables user interface. + ui_print_datatable( + [ + 'id' => $tableId, + 'class' => 'info_table', + 'style' => 'width: 100%', + 'columns' => $columns, + 'column_names' => $column_names, + 'ajax_url' => $model->ajaxController, + 'ajax_data' => ['method' => 'draw'], + 'no_sortable_columns' => [-1], + 'order' => [ + 'field' => 'known_status', + 'direction' => 'asc', + ], + 'search_button_class' => 'sub filter float-right', + 'form' => [ + 'inputs' => [ + [ + 'label' => __('Filter group'), + 'name' => 'id_group', + 'returnAllGroup' => true, + 'privilege' => 'AR', + 'type' => 'select_groups', + 'return' => true, + 'size' => '250px', + ], + [ + 'label' => __('Free search'), + 'type' => 'text', + 'class' => 'mw250px', + 'id' => 'free_search', + 'name' => 'free_search', + ], + ], + ], + ] + ); +} catch (Exception $e) { + echo $e->getMessage(); +} + +if (check_acl($config['id_user'], 0, 'AW')) { + HTML::printForm( + [ + 'form' => [ + 'method' => 'POST', + 'action' => ui_get_full_url($model->url.'&op=new'), + ], + 'inputs' => [ + [ + 'class' => 'w100p', + 'arguments' => [ + 'name' => 'submit', + 'label' => __('New cluster'), + 'type' => 'submit', + 'attributes' => 'class="sub next"', + 'return' => true, + ], + ], + ], + ] + ); +} diff --git a/pandora_console/views/cluster/view.php b/pandora_console/views/cluster/view.php new file mode 100644 index 0000000000..1742930ad1 --- /dev/null +++ b/pandora_console/views/cluster/view.php @@ -0,0 +1,453 @@ + $model->url, + 'label' => __('Cluster list'), + 'selected' => false, +]; + +$bc[] = [ + 'link' => $model->url.'&op=view&id='.$cluster->id(), + 'label' => __('Cluster details'), + 'selected' => true, +]; + + +$html->prepareBreadcrum($bc); + +// Header. +$main_page = ''; +$main_page .= html_print_image( + 'images/list.png', + true, + [ + 'title' => __('Cluster list'), + 'class' => 'invert_filter', + ] +); +$main_page .= ''; + +$edit = ''; +$edit .= html_print_image( + 'images/setup.png', + true, + [ + 'title' => __('Edit this cluster'), + 'class' => 'invert_filter', + ] +); +$edit .= ''; + +ui_print_page_header( + __('Cluster details').' » '.$cluster->name(), + '', + false, + // Help link. + 'cluster_view', + true, + // Buttons. + [ + [ + 'active' => false, + 'text' => $main_page, + ],[ + 'active' => false, + 'text' => $edit, + ], + ], + false, + '', + GENERIC_SIZE_TEXT, + '', + $html->printHeader(true) +); + + +if (empty($error) === false) { + echo $error; +} + +if (empty($message) === false) { + echo $message; +} + +if ($critical === true) { + // Print always go back button. + HTML::printForm($model->getGoBackForm(), false); + return; +} + + +/* + * + * All this block has been retrieved from 'estado_generalagente.php' as + * described in issue #5755. + * + */ + + + +/* + * + * + * CLUSTER AGENT DETAILS. + * + */ + +// Prepare information for view. +$alive_animation = agents_get_status_animation( + agents_get_interval_status($cluster->agent()->toArray(), false) +); + + +$agent_name = ui_print_agent_name( + $cluster->agent()->id_agente(), + true, + 500, + 'font-size: medium;font-weight:bold', + true, + '', + '', + false, + false +); +$in_planned_downtime = db_get_sql( + 'SELECT executed FROM tplanned_downtime + INNER JOIN tplanned_downtime_agents + ON tplanned_downtime.id = tplanned_downtime_agents.id_downtime + WHERE tplanned_downtime_agents.id_agent = '.$cluster->agent()->id_agente().' AND tplanned_downtime.executed = 1' +); + +if ($cluster->agent()->disabled()) { + if ($in_planned_downtime) { + $agent_name = ''.$agent_name.ui_print_help_tip(__('Disabled'), true); + } else { + $agent_name = ''.$agent_name.''.ui_print_help_tip(__('Disabled'), true); + } +} else if ($cluster->agent()->quiet()) { + if ($in_planned_downtime) { + $agent_name = "".$agent_name.' '.html_print_image('images/dot_blue.png', true, ['border' => '0', 'title' => __('Quiet'), 'alt' => '']); + } else { + $agent_name = "".$agent_name.' '.html_print_image('images/dot_blue.png', true, ['border' => '0', 'title' => __('Quiet'), 'alt' => '']).''; + } +} else { + $agent_name = $agent_name; +} + +if ($in_planned_downtime && !$cluster->agent()->disabled() && !$cluster->agent()->quiet()) { + $agent_name .= ' '.ui_print_help_tip( + __('Agent in scheduled downtime'), + true, + 'images/minireloj-16.png' + ).''; +} else if (($in_planned_downtime && !$cluster->agent()->disabled()) + || ($in_planned_downtime && !$cluster->agent()->quiet()) +) { + $agent_name .= ' '.ui_print_help_tip( + __('Agent in scheduled downtime'), + true, + 'images/minireloj-16.png' + ).''; +} + + +$table_agent_header = '
'; +$table_agent_header .= $agent_name; +$table_agent_header .= '
'; +$table_agent_header .= '
'; +if (!$config['show_group_name']) { + $table_agent_header .= ui_print_group_icon( + $cluster->agent()->id_grupo(), + true, + 'groups_small', + 'padding-right: 6px;' + ); +} + +$table_agent_header .= '
'; + +$status_img = agents_detail_view_status_img( + $cluster->agent()->critical_count(), + $cluster->agent()->warning_count(), + $cluster->agent()->unknown_count(), + $cluster->agent()->total_count(), + $cluster->agent()->notinit_count() +); + +$table_agent_header .= '
'.$status_img.'
'; +$table_agent_header .= '  '; +$table_agent_header .= ''.html_print_image( + 'images/target.png', + true, + [ + 'title' => __('Force cluster status calculation'), + 'alt' => '', + 'class' => 'invert_filter', + + ] +).''; +// Fixed width non interactive charts. +$status_chart_width = 180; +$graph_width = 180; + +$table_agent_graph = '
'; +$table_agent_graph .= graph_agent_status( + $cluster->agent()->id_agente(), + $graph_width, + $graph_width, + true, + false, + false, + true +); +$table_agent_graph .= '
'; + +$table_agent_os = '

'.ui_print_os_icon( + $cluster->agent()->id_os(), + false, + true, + true, + false, + false, + false, + ['title' => __('OS').': '.get_os_name($cluster->agent()->id_os())] +); +$table_agent_os .= (empty($cluster->agent()->os_version()) === true) ? get_os_name((int) $cluster->agent()->id_os()) : $cluster->agent()->os_version().'

'; + + + +$addresses = agents_get_addresses($cluster->agent()->id_agente()); +$address = agents_get_address($cluster->agent()->id_agente()); + +foreach ($addresses as $k => $add) { + if ($add == $address) { + unset($addresses[$k]); + } +} + +if (empty($address) === false) { + $table_agent_ip = '

'.html_print_image( + 'images/world.png', + true, + [ + 'title' => __('IP address'), + 'class' => 'invert_filter', + ] + ); + $table_agent_ip .= ''; + $table_agent_ip .= empty($address) ? ''.__('N/A').'' : $address; + $table_agent_ip .= '

'; +} + +$table_agent_description = '

'.html_print_image( + 'images/list.png', + true, + [ + 'title' => __('Description'), + 'class' => 'invert_filter', + ] +); +$table_agent_description .= ''; +$table_agent_description .= empty( + $cluster->description() +) ? ''.__('N/A').'' : $cluster->description(); +$table_agent_description .= '

'; + +$table_agent_count_modules = reporting_tiny_stats( + $cluster->agent()->toArray(), + true, + 'agent', + // Useless. + ':', + true +); + +$table_agent_version = '

'.html_print_image( + 'images/version.png', + true, + [ + 'title' => __('Agent Version'), + 'class' => 'invert_filter', + ] +); +$table_agent_version .= ''; +$table_agent_version .= empty($cluster->agent()->agent_version()) ? ''.__('Cluster agent').'' : $cluster->agent()->agent_version(); +$table_agent_version .= '

'; + +/* + * + * MAP + * + */ + +$nodes = $cluster->getNodes(); + +$font_size = 20; +$width = '45%'; +$height = '500'; +$node_radius = 40; + +// Generate map. +$map_manager = new NetworkMap( + [ + 'nodes' => $nodes, + 'no_pandora_node' => 1, + 'pure' => 1, + 'map_options' => [ + 'generation_method' => LAYOUT_SPRING1, + 'font_size' => $font_size, + 'node_radius' => $node_radius, + 'height' => $height, + 'width' => '100%', + 'tooltip' => true, + 'size_image' => 50, + 'z_dash' => 0.5, + 'map_filter' => [ + 'node_sep' => 7, + 'node_radius' => 50, + 'x_offs' => 130, + 'y_offs' => -70, + ], + ], + ] +); + + +/* + * + * EVENTS 24h + * + */ + +$table_events = '
'; +$table_events .= '
'; +$table_events .= html_print_image( + 'images/arrow_down_green.png', + true +); +$table_events .= ''; +$table_events .= __('Events (Last 24h)'); +$table_events .= ''; +$table_events .= '
'; +$table_events .= '
'; +$table_events .= graph_graphic_agentevents( + $cluster->agent()->id_agente(), + 95, + 70, + SECONDS_1DAY, + '', + true, + true, + 500 +); +$table_events .= '
'; +$table_events .= '
'; + +?> +
+
+
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+ +
+
+ printMap(); ?> +
+
+
+ +
+ +
+ +
+agent()->id_agente(); +require_once $config['homedir'].'/operation/agentes/estado_monitores.php'; +?> +
+ + + [ + 'action' => $model->url.'&op=view&id='.$cluster->id(), + 'method' => 'POST', + ], + 'inputs' => [ + [ + 'arguments' => [ + 'name' => 'submit', + 'label' => __('Reload'), + 'type' => 'submit', + 'attributes' => 'class="sub cancel"', + 'return' => true, + ], + ], + ], + ], + false +); + +echo '
'; + +// Print always go back button. +HTML::printForm($model->getGoBackForm(), false); From b8c2fe52b55ff34337361ef0cf5f0c28a67eacf4 Mon Sep 17 00:00:00 2001 From: Calvo Date: Tue, 25 Oct 2022 15:33:22 +0200 Subject: [PATCH 016/251] =?UTF-8?q?Added=20ACL=20to=20ap=C3=AC=20get=20tre?= =?UTF-8?q?e=20agents=20plugin=20user=20and=20plugin=20pass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pandora_console/include/functions_api.php | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index 90935bbc6d..14a71bfdb8 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -652,8 +652,6 @@ $module_field_column_mampping = [ 'module_id_module' => 'id_modulo as module_id_module', 'module_disabled' => 'disabled as module_disabled', 'module_id_export' => 'id_export as module_id_export', - 'module_plugin_user' => 'plugin_user as module_plugin_user', - 'module_plugin_pass' => 'plugin_pass as module_plugin_pass', 'module_plugin_parameter' => 'plugin_parameter as module_plugin_parameter', 'module_id_plugin' => 'id_plugin as module_id_plugin', 'module_post_process' => 'post_process as module_post_process', @@ -805,8 +803,6 @@ function api_get_tree_agents($trash1, $trahs2, $other, $returnType) 'module_id_module', 'module_disabled', 'module_id_export', - 'module_plugin_user', - 'module_plugin_pass', 'module_plugin_parameter', 'module_id_plugin', 'module_post_process', @@ -1015,9 +1011,9 @@ function api_get_tree_agents($trash1, $trahs2, $other, $returnType) $groups = []; } - $groups = str_replace('\n', $returnReplace, $groups); - foreach ($groups as &$group) { + $group = str_replace('\n', $returnReplace, $group); + $group['type_row'] = 'group'; $returnVar[] = $group; @@ -1033,9 +1029,19 @@ function api_get_tree_agents($trash1, $trahs2, $other, $returnType) $agents = []; } - $agents = str_replace('\n', $returnReplace, $agents); + if ((bool) check_acl($config['id_user'], $id_group, 'AW') === true) { + if (array_search('module_plugin_user', $fields) !== false) { + $module_additional_columns .= ' ,plugin_user as module_plugin_user'; + } + + if (array_search('module_plugin_user', $fields) !== false) { + $module_additional_columns .= ' ,plugin_pass as module_plugin_pass'; + } + } foreach ($agents as $index => &$agent) { + $agent = str_replace('\n', $returnReplace, $agent); + $agent['type_row'] = 'agent'; $returnVar[] = $agent; @@ -1062,9 +1068,9 @@ function api_get_tree_agents($trash1, $trahs2, $other, $returnType) $modules = []; } - $modules = str_replace('\n', $returnReplace, $modules); - foreach ($modules as &$module) { + $module = str_replace('\n', $returnReplace, $module); + $module['type_row'] = 'module'; if ($module['module_macros']) { From 6dbc71713a630366095da8f97594468e7c70ec1f Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Tue, 25 Oct 2022 15:52:30 +0200 Subject: [PATCH 017/251] add enable modules massive option --- .../godmode/agentes/module_manager.php | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/pandora_console/godmode/agentes/module_manager.php b/pandora_console/godmode/agentes/module_manager.php index 6cfa2685b4..89c9ef5c81 100644 --- a/pandora_console/godmode/agentes/module_manager.php +++ b/pandora_console/godmode/agentes/module_manager.php @@ -454,8 +454,6 @@ if ($module_action === 'delete') { } } else if ($module_action === 'disable') { $id_agent_modules_disable = (array) get_parameter('id_delete'); - - $count_correct_delete_modules = 0; $updated_count = 0; foreach ($id_agent_modules_disable as $id_agent_module_disable) { @@ -499,6 +497,52 @@ if ($module_action === 'delete') { ); } } +} else if ($module_action === 'enable') { + $id_agent_modules_enable = (array) get_parameter('id_delete'); + $updated_count = 0; + + foreach ($id_agent_modules_enable as $id_agent_module_enable) { + $sql = sprintf( + 'UPDATE tagente_modulo + SET disabled = 0 + WHERE id_agente_modulo = %d', + $id_agent_module_enable + ); + + $id_agent_changed[] = modules_get_agentmodule_agent($id_agent_module_enable); + $agent_update_result = db_process_sql_update( + 'tagente', + ['update_module_count' => 1], + ['id_agente' => $id_agent_changed] + ); + + if (db_process_sql($sql) !== false && $agent_update_result !== false) { + $updated_count++; + } + } + + $count_modules_to_enable = count($id_agent_modules_enable); + + if ($updated_count === 0) { + ui_print_error_message( + sprintf( + __('There was a problem completing the operation. Applied to 0/%d modules.'), + $count_modules_to_enable + ) + ); + } else { + if ($updated_count == $count_modules_to_enable) { + ui_print_success_message(__('Operation finished successfully.')); + } else { + ui_print_error_message( + sprintf( + __('There was a problem completing the operation. Applied to %d/%d modules.'), + $updated_count, + $count_modules_to_enable + ) + ); + } + } } @@ -1283,6 +1327,7 @@ if (check_acl_one_of_groups($config['id_user'], $all_groups, 'AW')) { html_print_select( [ 'disable' => 'Disable selected modules', + 'enable' => 'Enable selected modules', 'delete' => 'Delete selected modules', ], 'module_action', @@ -1295,6 +1340,8 @@ if (check_acl_one_of_groups($config['id_user'], $all_groups, 'AW')) { false ); + echo '    '; + html_print_submit_button( __('Execute action'), 'submit_modules_action', From 8d611a8e7fd4f2647b241e1faf89138a84e07478 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Wed, 26 Oct 2022 18:25:16 +0200 Subject: [PATCH 018/251] implemented float formatting and option in reports to change visualization format --- pandora_console/extras/mr/60.sql | 6 ++ .../reporting_builder.item_editor.php | 29 +++++++- .../godmode/reporting/reporting_builder.php | 12 ++++ .../godmode/setup/setup_visuals.php | 21 ++++++ .../include/ajax/custom_fields.php | 4 +- pandora_console/include/ajax/module.php | 12 +++- .../include/class/AgentWizard.class.php | 9 ++- .../include/class/Diagnostics.class.php | 8 ++- pandora_console/include/functions.php | 27 ++++---- pandora_console/include/functions_config.php | 13 ++++ pandora_console/include/functions_html.php | 2 +- pandora_console/include/functions_modules.php | 10 +-- .../include/functions_reporting.php | 67 ++++++++++++++----- .../include/functions_reporting_html.php | 22 ++++-- .../include/functions_treeview.php | 10 +-- pandora_console/include/functions_ui.php | 4 +- .../include/functions_visual_map.php | 14 ++-- .../include/graphs/functions_flot.php | 6 +- .../lib/Dashboard/Widgets/module_icon.php | 2 +- .../lib/Dashboard/Widgets/module_value.php | 4 +- .../models/VisualConsole/Items/Group.php | 10 +-- .../models/VisualConsole/Items/Percentile.php | 4 +- .../VisualConsole/Items/StaticGraph.php | 2 +- .../agentes/pandora_networkmap.view.php | 7 +- .../operation/agentes/status_monitor.php | 44 ++++++++---- pandora_console/pandoradb.sql | 2 + .../extensions/intel_dcm_agent_view.php | 14 ++-- 27 files changed, 270 insertions(+), 95 deletions(-) create mode 100644 pandora_console/extras/mr/60.sql diff --git a/pandora_console/extras/mr/60.sql b/pandora_console/extras/mr/60.sql new file mode 100644 index 0000000000..8d662a5fb7 --- /dev/null +++ b/pandora_console/extras/mr/60.sql @@ -0,0 +1,6 @@ +START TRANSACTION; + +ALTER TABLE treport_content ADD COLUMN use_prefix_notation tinyint(1) default '1'; +ALTER TABLE treport_content_template ADD COLUMN use_prefix_notation tinyint(1) default '1'; + +COMMIT; diff --git a/pandora_console/godmode/reporting/reporting_builder.item_editor.php b/pandora_console/godmode/reporting/reporting_builder.item_editor.php index 3cc78b737c..51653d0ce0 100755 --- a/pandora_console/godmode/reporting/reporting_builder.item_editor.php +++ b/pandora_console/godmode/reporting/reporting_builder.item_editor.php @@ -168,6 +168,7 @@ $visual_format = 0; $filter_search = ''; $filter_exclude = ''; +$use_prefix_notation = true; // Added for select fields. $total_time = true; @@ -460,6 +461,7 @@ switch ($action) { $lapse = $item['lapse']; $lapse_calc = $item['lapse_calc']; $visual_format = $item['visual_format']; + $use_prefix_notation = $item['use_prefix_notation']; break; case 'max_value': @@ -475,6 +477,7 @@ switch ($action) { $lapse = $item['lapse']; $lapse_calc = $item['lapse_calc']; $visual_format = $item['visual_format']; + $use_prefix_notation = $item['use_prefix_notation']; break; case 'min_value': @@ -490,6 +493,7 @@ switch ($action) { $lapse = $item['lapse']; $lapse_calc = $item['lapse_calc']; $visual_format = $item['visual_format']; + $use_prefix_notation = $item['use_prefix_notation']; break; case 'sumatory': @@ -503,6 +507,7 @@ switch ($action) { $idAgentModule = $item['id_agent_module']; $period = $item['period']; $uncompressed_module = $item['uncompressed_module']; + $use_prefix_notation = $item['use_prefix_notation']; break; case 'historical_data': @@ -771,6 +776,7 @@ switch ($action) { $show_resume = $item['show_resume']; $show_graph = $item['show_graph']; $order_uptodown = $item['order_uptodown']; + $use_prefix_notation = $item['use_prefix_notation']; $text_agent = ''; if (isset($style['text_agent']) === true @@ -3407,6 +3413,22 @@ $class = 'databox filters'; + + + + + + + + + data[$row][1] = ''.__('Example').' '.date($config['date_f $table_other->data[$row][1] .= html_print_input_text('date_format', $config['date_format'], '', 30, 100, true); $row++; +$decimal_separators = [ + ',' => ',', + '.' => '.' +]; + +$table_other->data[$row][0] = __('Decimal separator'); +$table_other->data[$row][1] = html_print_select( + $decimal_separators, + 'decimal_separator', + $config['decimal_separator'], + '', + '', + '', + true, + false, + false +); + + +$row++; + if ($config['prominent_time'] == 'comparation') { $timestamp = false; $comparation = true; diff --git a/pandora_console/include/ajax/custom_fields.php b/pandora_console/include/ajax/custom_fields.php index 3fd81ec4b0..77e79800aa 100644 --- a/pandora_console/include/ajax/custom_fields.php +++ b/pandora_console/include/ajax/custom_fields.php @@ -429,7 +429,9 @@ if (check_login()) { $table_modules->data[$key][1] = remove_right_zeros( number_format( $value['datos'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } else { diff --git a/pandora_console/include/ajax/module.php b/pandora_console/include/ajax/module.php index c43da3e146..8efb03df12 100755 --- a/pandora_console/include/ajax/module.php +++ b/pandora_console/include/ajax/module.php @@ -499,7 +499,9 @@ if (check_login()) { $data[] = remove_right_zeros( number_format( $row[$attr[0]], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } @@ -507,7 +509,9 @@ if (check_login()) { $data[] = remove_right_zeros( number_format( $row[$attr[0]], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } @@ -524,7 +528,9 @@ if (check_login()) { $data[] = remove_right_zeros( number_format( $row[$attr[0]], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } diff --git a/pandora_console/include/class/AgentWizard.class.php b/pandora_console/include/class/AgentWizard.class.php index dc6bd5df5f..2602b9a0c2 100644 --- a/pandora_console/include/class/AgentWizard.class.php +++ b/pandora_console/include/class/AgentWizard.class.php @@ -2546,6 +2546,8 @@ class AgentWizard extends HTML */ private function resultsInterfaceWizard() { + global $config; + $generalInterfaceModules = $this->getInterfacesModules(); $generalInterfaceTables = []; $generalInterfaceModulesUpdated = []; @@ -2759,7 +2761,12 @@ class AgentWizard extends HTML // Format current value with thousands and decimals. if (is_numeric($currentValue) === true) { $decimals = (is_float($currentValue) === true) ? 2 : 0; - $currentValue = number_format($currentValue, $decimals); + $currentValue = number_format( + $currentValue, + $decimals, + $config['decimal_separator'], + $config['thousand_separator'] + ); } // It unit of measure have data, attach to current value. diff --git a/pandora_console/include/class/Diagnostics.class.php b/pandora_console/include/class/Diagnostics.class.php index b8ca6e3690..5215a09aa3 100644 --- a/pandora_console/include/class/Diagnostics.class.php +++ b/pandora_console/include/class/Diagnostics.class.php @@ -986,7 +986,7 @@ class Diagnostics extends Wizard ], 'tablesFragmentationValue' => [ 'name' => __('Tables fragmentation (current value)'), - 'value' => number_format($tFragmentationValue, 2).'%', + 'value' => number_format($tFragmentationValue, 2, $config['decimal_separator'], $config['thousand_separator']).'%', ], 'tablesFragmentationStatus' => [ 'name' => __('Table fragmentation status'), @@ -1121,7 +1121,9 @@ class Diagnostics extends Wizard if ($totalModuleIntervalTime !== false) { $averageTime = number_format( ((int) $totalNetworkModules / (int) $totalModuleIntervalTime), - 3 + 3, + $config['decimal_separator'], + $config['thousand_separator'] ); } @@ -1748,7 +1750,7 @@ class Diagnostics extends Wizard $sizeServerLog = number_format($fileSize); $sizeServerLog = (0 + str_replace(',', '', $sizeServerLog)); - $value = number_format(($fileSize / $mega), 3); + $value = number_format(($fileSize / $mega), 3, $config['decimal_separator'], $config['thousand_separator']); $message = __('You have more than 10 MB of logs'); $status = 0; if ($sizeServerLog <= $tenMega) { diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index ed999553cb..f2363edc71 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -219,6 +219,8 @@ function list_files($directory, $stringSearch, $searchHandler, $return=false) */ function format_numeric($number, $decimals=1) { + global $config; + // Translate to float in case there are characters in the string so // fmod doesn't throw a notice $number = (float) $number; @@ -227,17 +229,11 @@ function format_numeric($number, $decimals=1) return 0; } - // Translators: This is separator of decimal point - $dec_point = __('.'); - // Translators: This is separator of decimal point - $thousands_sep = __(','); - - // If has decimals if (fmod($number, 1) > 0) { - return number_format($number, $decimals, $dec_point, $thousands_sep); + return number_format($number, $decimals, $config['decimal_separator'], $config['thousand_separator']); } - return number_format($number, 0, $dec_point, $thousands_sep); + return number_format($number, 0, $config['decimal_separator'], $config['thousand_separator']); } @@ -4084,14 +4080,18 @@ function series_type_graph_array($data, $show_elements_graph) $data_return['legend'][$key] .= remove_right_zeros( number_format( $value['min'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); $data_return['legend'][$key] .= ' '.__('Max:'); $data_return['legend'][$key] .= remove_right_zeros( number_format( $value['max'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); $data_return['legend'][$key] .= ' '._('Avg:'); @@ -4099,7 +4099,8 @@ function series_type_graph_array($data, $show_elements_graph) number_format( $value['avg'], $config['graph_precision'], - $config['csv_decimal_separator'] + $config['decimal_separator'], + $config['thousand_separator'] ) ).' '.$str; } @@ -4156,7 +4157,9 @@ function series_type_graph_array($data, $show_elements_graph) $data_return['legend'][$key] .= remove_right_zeros( number_format( $value['data'][0][1], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ).' '.$str; } diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 958261274a..8d9e4b0b50 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -1467,6 +1467,15 @@ function config_update_config() if (config_update_value('use_data_multiplier', get_parameter('use_data_multiplier', '1'), true) === false) { $error_update[] = __('Use data multiplier'); } + + if (config_update_value('decimal_separator', (string) get_parameter('decimal_separator', '.'), true) === false) { + $error_update[] = __('Decimal separator'); + } else { + $thousand_separator = ((string) get_parameter('decimal_separator', '.') === '.') ? ',' : '.'; + if (config_update_value('thousand_separator', $thousand_separator, true) === false) { + $error_update[] = __('Thousand separator'); + } + } break; case 'net': @@ -3422,6 +3431,10 @@ function config_process_config() config_update_value('module_library_password', ''); } + if (!isset($config['decimal_separator'])) { + config_update_value('decimal_separator', '.'); + } + // Finally, check if any value was overwritten in a form. config_update_config(); } diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index ef41904c38..a777f4389c 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -1950,7 +1950,7 @@ function html_print_extended_select_for_post_process( $found = false; if ($selected) { - if (array_key_exists(number_format($selected, 14, '.', ','), $fields)) { + if (array_key_exists(number_format($selected, 14, $config['decimal_separator'], $config['thousand_separator']), $fields)) { $found = true; } } diff --git a/pandora_console/include/functions_modules.php b/pandora_console/include/functions_modules.php index 443e482173..59ead9b943 100755 --- a/pandora_console/include/functions_modules.php +++ b/pandora_console/include/functions_modules.php @@ -2589,12 +2589,12 @@ function modules_get_agentmodule_data_for_humans($module) $salida = human_milliseconds_to_string($module['datos']); } } else { - $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } break; default: - $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); break; } break; @@ -2613,12 +2613,12 @@ function modules_get_agentmodule_data_for_humans($module) $salida = human_milliseconds_to_string($module['datos']); } } else { - $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } break; default: - $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($module['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); break; } } @@ -2900,7 +2900,7 @@ function modules_get_status($id_agent_module, $db_status, $data, &$status, &$tit } if (is_numeric($data)) { - $title .= ': '.remove_right_zeros(number_format($data, $config['graph_precision'])); + $title .= ': '.remove_right_zeros(number_format($data, $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } else { $text = io_safe_output($data); diff --git a/pandora_console/include/functions_reporting.php b/pandora_console/include/functions_reporting.php index ab1e64cfcf..cbd6e276a9 100755 --- a/pandora_console/include/functions_reporting.php +++ b/pandora_console/include/functions_reporting.php @@ -1833,14 +1833,24 @@ function reporting_event_top_n( $divisor = get_data_multiplier($units[$key_dt]); - $data['formated_value'] = format_for_graph( - $dt, - 2, - '.', - ',', - $divisor, - $units[$key_dt] - ); + if ((bool) $content['use_prefix_notation'] === false) { + $data['formated_value'] = number_format( + $dt, + 2, + $config['decimal_separator'], + $config['thousand_separator'] + ).' '.$units[$key_dt]; + } else { + $data['formated_value'] = format_for_graph( + $dt, + 2, + '.', + ',', + $divisor, + $units[$key_dt] + ); + } + $data_return[] = $data; } @@ -1901,14 +1911,25 @@ function reporting_event_top_n( $data['agent'] = $an; $data['module'] = $module_name[$key_an]; $data['value'] = $data_top[$key_an]; - $data['formated_value'] = format_for_graph( - $data_top[$key_an], - 2, - '.', - ',', - $divisor, - $units[$key_an] - ); + + if ((bool) $content['use_prefix_notation'] === false) { + $data['formated_value'] = number_format( + $data_top[$key_an], + 2, + $config['decimal_separator'], + $config['thousand_separator'] + ).' '.$units[$key_an]; + } else { + $data['formated_value'] = format_for_graph( + $data_top[$key_an], + 2, + '.', + ',', + $divisor, + $units[$key_an] + ); + } + $data_return[] = $data; } @@ -6925,6 +6946,13 @@ function reporting_value($report, $content, $type, $pdf=false) if (!$config['simple_module_value']) { $formated_value = $value; + } else if ((bool) $content['use_prefix_notation'] === false) { + $formated_value = number_format( + $value, + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] + ).' '.$unit; } else { $formated_value = format_for_graph( $value, @@ -7085,6 +7113,13 @@ function reporting_value($report, $content, $type, $pdf=false) ); if (!$config['simple_module_value']) { $formated_value = $value; + } else if ((bool) $content['use_prefix_notation'] === false) { + $formated_value = number_format( + $value, + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] + ).' '.$unit; } else { $divisor = get_data_multiplier($unit); diff --git a/pandora_console/include/functions_reporting_html.php b/pandora_console/include/functions_reporting_html.php index 029b0d70b6..27b7037751 100644 --- a/pandora_console/include/functions_reporting_html.php +++ b/pandora_console/include/functions_reporting_html.php @@ -2283,7 +2283,9 @@ function reporting_html_agent_module_status($table, $item, $pdf=0) $row['data_module'] = remove_right_zeros( number_format( $data['data_module'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } else { @@ -2776,7 +2778,7 @@ function reporting_html_historical_data($table, $item, $pdf=0) } else { $row = [ $data[__('Date')], - remove_right_zeros(number_format($data[__('Data')], $config['graph_precision'])), + remove_right_zeros(number_format($data[__('Data')], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])), ]; } @@ -2916,7 +2918,9 @@ function reporting_html_last_value($table, $item, $pdf=0) $dataDatos = remove_right_zeros( number_format( $item['data']['datos'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } else { @@ -3461,7 +3465,9 @@ function reporting_html_monitor_report($table, $item, $mini, $pdf=0) ).' '.__('OK').': '.remove_right_zeros( number_format( $item['data']['ok']['value'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ).' %

'; @@ -3472,7 +3478,9 @@ function reporting_html_monitor_report($table, $item, $mini, $pdf=0) ).' '.__('Not OK').': '.remove_right_zeros( number_format( $item['data']['fail']['value'], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ).' % '.'

'; } @@ -3826,7 +3834,9 @@ function reporting_html_value( remove_right_zeros( number_format( $data[__('Maximun')], - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ), ]; diff --git a/pandora_console/include/functions_treeview.php b/pandora_console/include/functions_treeview.php index 3fc35f4d84..e230ba54ca 100755 --- a/pandora_console/include/functions_treeview.php +++ b/pandora_console/include/functions_treeview.php @@ -193,7 +193,7 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals if ($value == '.1.3.6.1.2.1.1.3.0' || $value == '.1.3.6.1.2.1.25.1.1.0') { $data = "".human_milliseconds_to_string($last_data['datos']).''; } else if (is_numeric($last_data['datos'])) { - $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'])).''; + $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])).''; } else { $data = ui_print_truncate_text( io_safe_output($last_data['datos']), @@ -209,7 +209,7 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals default: if (is_numeric($last_data['datos'])) { - $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'])).''; + $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])).''; } else { $data = ui_print_truncate_text( io_safe_output($last_data['datos']), @@ -232,7 +232,7 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals if ($value == '.1.3.6.1.2.1.1.3.0' || $value == '.1.3.6.1.2.1.25.1.1.0') { $data = "".human_milliseconds_to_string($last_data['datos']).''; } else if (is_numeric($last_data['datos'])) { - $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'])).''; + $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])).''; } else { $data = ui_print_truncate_text( io_safe_output($last_data['datos']), @@ -248,7 +248,7 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals default: if (is_numeric($last_data['datos'])) { - $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'])).''; + $data = "".remove_right_zeros(number_format($last_data['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])).''; } else { $data = ui_print_truncate_text( io_safe_output($last_data['datos']), @@ -271,7 +271,7 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals $data_macro = modules_get_unit_macro($last_data['datos'], $module['unit']); if ($data_macro) { if (is_numeric($data_macro)) { - $last_data_str = "".remove_right_zeros(number_format($data_macro, $config['graph_precision'])).''; + $last_data_str = "".remove_right_zeros(number_format($data_macro, $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])).''; } else { $last_data_str = ui_print_truncate_text( io_safe_output($data_macro), diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 1e9d9f8dd7..dfc5b5e4ea 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -6558,10 +6558,10 @@ function ui_print_comments($comments) } else { $rest_time = (time() - $last_comment[0][0]['utimestamp']); $time_last = (($rest_time / 60) / 60); - $comentario = ''.number_format($time_last, 0).'  Hours  ('.$last_comment[0][0]['id_user'].'): '.$last_comment[0][0]['comment'].''; + $comentario = ''.number_format($time_last, 0, $config['decimal_separator'], $config['thousand_separator']).'  Hours  ('.$last_comment[0][0]['id_user'].'): '.$last_comment[0][0]['comment'].''; if (strlen($comentario) > '200px') { - $comentario = ''.number_format($time_last, 0).'  Hours  ('.$last_comment[0][0]['id_user'].'): '.$short_comment.'...'; + $comentario = ''.number_format($time_last, 0, $config['decimal_separator'], $config['thousand_separator']).'  Hours  ('.$last_comment[0][0]['id_user'].'): '.$short_comment.'...'; } } diff --git a/pandora_console/include/functions_visual_map.php b/pandora_console/include/functions_visual_map.php index fce3aabe2d..97b14e4275 100755 --- a/pandora_console/include/functions_visual_map.php +++ b/pandora_console/include/functions_visual_map.php @@ -924,7 +924,7 @@ function visual_map_print_item( $value_text = format_for_graph($module_value, 2); if ($value_text <= 0) { - $value_text = remove_right_zeros(number_format($module_value, $config['graph_precision'])); + $value_text = remove_right_zeros(number_format($module_value, $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } if (!empty($unit_text)) { @@ -1743,7 +1743,7 @@ function visual_map_print_item( || (modules_is_boolean($layoutData['id_agente_modulo']) && $layoutData['show_last_value'] != 0) ) { if (is_numeric($value)) { - $img_style_title .= '
'.__('Last value: ').remove_right_zeros(number_format($value, $config['graph_precision'])); + $img_style_title .= '
'.__('Last value: ').remove_right_zeros(number_format($value, $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } else { $img_style_title .= '
'.__('Last value: ').$value; } @@ -1881,13 +1881,13 @@ function visual_map_print_item( echo ''; echo ""; echo ''; - echo "
".remove_right_zeros(number_format($stat_agent_cr, 2)).'%
'; + echo "
".remove_right_zeros(number_format($stat_agent_cr, 2, $config['decimal_separator'], $config['thousand_separator'])).'%
'; echo "
Critical
"; - echo "
".remove_right_zeros(number_format($stat_agent_wa, 2)).'%
'; + echo "
".remove_right_zeros(number_format($stat_agent_wa, 2, $config['decimal_separator'], $config['thousand_separator'])).'%
'; echo "
Warning
"; - echo "
".remove_right_zeros(number_format($stat_agent_ok, 2)).'%
'; + echo "
".remove_right_zeros(number_format($stat_agent_ok, 2, $config['decimal_separator'], $config['thousand_separator'])).'%
'; echo "
Normal
"; - echo "
".remove_right_zeros(number_format($stat_agent_un, 2)).'%
'; + echo "
".remove_right_zeros(number_format($stat_agent_un, 2, $config['decimal_separator'], $config['thousand_separator'])).'%
'; echo "
Unknown
"; echo ''; echo ''; @@ -2462,7 +2462,7 @@ function visual_map_get_simple_value($type, $id_module, $period=SECONDS_1DAY) } else { if (is_numeric($value)) { if ($config['simple_module_value']) { - $value = remove_right_zeros(number_format($value, $config['graph_precision'])); + $value = remove_right_zeros(number_format($value, $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } } diff --git a/pandora_console/include/graphs/functions_flot.php b/pandora_console/include/graphs/functions_flot.php index 8f5256e757..821b85c4d6 100644 --- a/pandora_console/include/graphs/functions_flot.php +++ b/pandora_console/include/graphs/functions_flot.php @@ -499,11 +499,11 @@ function flot_custom_pie_chart( foreach ($graph_values as $label => $value) { if ($value['value']) { if ($value['value'] > 1000000) { - $legendvalue = sprintf('%sM', remove_right_zeros(number_format(($value['value'] / 1000000), $config['graph_precision']))); + $legendvalue = sprintf('%sM', remove_right_zeros(number_format(($value['value'] / 1000000), $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator']))); } else if ($value['value'] > 1000) { - $legendvalue = sprintf('%sK', remove_right_zeros(number_format(($value['value'] / 1000), $config['graph_precision']))); + $legendvalue = sprintf('%sK', remove_right_zeros(number_format(($value['value'] / 1000), $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator']))); } else { - $legendvalue = remove_right_zeros(number_format($value['value'], $config['graph_precision'])); + $legendvalue = remove_right_zeros(number_format($value['value'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } } else { $legendvalue = __('No data'); diff --git a/pandora_console/include/lib/Dashboard/Widgets/module_icon.php b/pandora_console/include/lib/Dashboard/Widgets/module_icon.php index 3b1adc888b..5523a851ef 100644 --- a/pandora_console/include/lib/Dashboard/Widgets/module_icon.php +++ b/pandora_console/include/lib/Dashboard/Widgets/module_icon.php @@ -555,7 +555,7 @@ class ModuleIconWidget extends Widget // Div value. $output .= '
'; $output .= remove_right_zeros( - number_format($data_module, $config['graph_precision']) + number_format($data_module, $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator']) ); $output .= '
'; diff --git a/pandora_console/include/lib/Dashboard/Widgets/module_value.php b/pandora_console/include/lib/Dashboard/Widgets/module_value.php index 41fdd41663..6577ad3c89 100644 --- a/pandora_console/include/lib/Dashboard/Widgets/module_value.php +++ b/pandora_console/include/lib/Dashboard/Widgets/module_value.php @@ -439,7 +439,9 @@ class ModuleValueWidget extends Widget $dataDatos = remove_right_zeros( number_format( $data_module, - $config['graph_precision'] + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] ) ); } else { diff --git a/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php b/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php index 27b400db97..50fca70543 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Items/Group.php @@ -397,10 +397,12 @@ final class Group extends Item string $groupName, array $agentStats ): string { - $critical = \number_format($agentStats['critical'], 2).'%'; - $warning = \number_format($agentStats['warning'], 2).'%'; - $normal = \number_format($agentStats['normal'], 2).'%'; - $unknown = \number_format($agentStats['unknown'], 2).'%'; + global $config; + + $critical = \number_format($agentStats['critical'], 2, $config['decimal_separator'], $config['thousand_separator']).'%'; + $warning = \number_format($agentStats['warning'], 2, $config['decimal_separator'], $config['thousand_separator']).'%'; + $normal = \number_format($agentStats['normal'], 2, $config['decimal_separator'], $config['thousand_separator']).'%'; + $unknown = \number_format($agentStats['unknown'], 2, $config['decimal_separator'], $config['thousand_separator']).'%'; $html = '
'; $html .= '
'; diff --git a/pandora_console/include/rest-api/models/VisualConsole/Items/Percentile.php b/pandora_console/include/rest-api/models/VisualConsole/Items/Percentile.php index 19e14f3456..657f73364d 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Items/Percentile.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Items/Percentile.php @@ -396,8 +396,8 @@ final class Percentile extends Item $data['value'] = (float) \number_format( (float) $moduleValue, (int) $config['graph_precision'], - '.', - '' + $config['decimal_separator'], + $config['thousand_separator'] ); $unit = ''; if ($moduleId !== null && $moduleId !== 0) { diff --git a/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php b/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php index adeaa9c29e..4eb1ba3abc 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Items/StaticGraph.php @@ -281,7 +281,7 @@ final class StaticGraph extends Item ) { if (\is_numeric($value)) { $imgTitle .= __('Last value: ').\remove_right_zeros( - \number_format((float) $value, (int) $config['graph_precision']) + \number_format((float) $value, (int) $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator']) ); } else { $imgTitle .= __('Last value: ').$value; diff --git a/pandora_console/operation/agentes/pandora_networkmap.view.php b/pandora_console/operation/agentes/pandora_networkmap.view.php index ac888a13fa..6d118d6e10 100644 --- a/pandora_console/operation/agentes/pandora_networkmap.view.php +++ b/pandora_console/operation/agentes/pandora_networkmap.view.php @@ -2048,7 +2048,12 @@ if (is_ajax() === true) { $array_filter = json_decode($networkmap['filter']); if (isset($array_filter->z_dash)) { - $array_filter->z_dash = number_format($scale, 2); + $array_filter->z_dash = number_format( + $scale, + 2, + $config['decimal_separator'], + $config['thousand_separator'] + ); } $filter = json_encode($array_filter); diff --git a/pandora_console/operation/agentes/status_monitor.php b/pandora_console/operation/agentes/status_monitor.php index 320282e403..b0c7c3eba1 100644 --- a/pandora_console/operation/agentes/status_monitor.php +++ b/pandora_console/operation/agentes/status_monitor.php @@ -1589,7 +1589,7 @@ if (!empty($result)) { if (is_numeric($row['datos'])) { $data[6] = ui_print_status_image( STATUS_MODULE_OK, - __('NORMAL').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'])), + __('NORMAL').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])), true ); } else { @@ -1604,7 +1604,12 @@ if (!empty($result)) { $data[6] = ui_print_status_image( STATUS_MODULE_CRITICAL, __('CRITICAL').': '.remove_right_zeros( - number_format($row['datos'], $config['graph_precision']) + number_format( + $row['datos'], + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] + ) ), true ); @@ -1620,7 +1625,12 @@ if (!empty($result)) { $data[6] = ui_print_status_image( STATUS_MODULE_WARNING, __('WARNING').': '.remove_right_zeros( - number_format($row['datos'], $config['graph_precision']) + number_format( + $row['datos'], + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] + ) ), true ); @@ -1636,7 +1646,12 @@ if (!empty($result)) { $data[6] = ui_print_status_image( STATUS_MODULE_UNKNOWN, __('UNKNOWN').': '.remove_right_zeros( - number_format($row['datos'], $config['graph_precision']) + number_format( + $row['datos'], + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] + ) ), true ); @@ -1652,7 +1667,12 @@ if (!empty($result)) { $data[6] = ui_print_status_image( STATUS_MODULE_NO_DATA, __('NO DATA').': '.remove_right_zeros( - number_format($row['datos'], $config['graph_precision']) + number_format( + $row['datos'], + $config['graph_precision'], + $config['decimal_separator'], + $config['thousand_separator'] + ) ), true ); @@ -1672,7 +1692,7 @@ if (!empty($result)) { if (is_numeric($row['datos'])) { $data[6] = ui_print_status_image( STATUS_MODULE_UNKNOWN, - __('UNKNOWN').' - '.__('Last status').' '.__('NORMAL').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'])), + __('UNKNOWN').' - '.__('Last status').' '.__('NORMAL').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])), true ); } else { @@ -1688,7 +1708,7 @@ if (!empty($result)) { if (is_numeric($row['datos'])) { $data[6] = ui_print_status_image( STATUS_MODULE_UNKNOWN, - __('UNKNOWN').' - '.__('Last status').' '.__('CRITICAL').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'])), + __('UNKNOWN').' - '.__('Last status').' '.__('CRITICAL').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])), true ); } else { @@ -1704,7 +1724,7 @@ if (!empty($result)) { if (is_numeric($row['datos'])) { $data[6] = ui_print_status_image( STATUS_MODULE_UNKNOWN, - __('UNKNOWN').' - '.__('Last status').' '.__('WARNING').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'])), + __('UNKNOWN').' - '.__('Last status').' '.__('WARNING').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])), true ); } else { @@ -1849,12 +1869,12 @@ if (!empty($result)) { if ($value == '.1.3.6.1.2.1.1.3.0' || $value == '.1.3.6.1.2.1.25.1.1.0') { $salida = human_milliseconds_to_string($row['datos']); } else { - $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } break; default: - $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); break; } break; @@ -1866,12 +1886,12 @@ if (!empty($result)) { if ($value == '.1.3.6.1.2.1.1.3.0' || $value == '.1.3.6.1.2.1.25.1.1.0') { $salida = human_milliseconds_to_string($row['datos']); } else { - $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); } break; default: - $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'])); + $salida = remove_right_zeros(number_format($row['datos'], $config['graph_precision'], $config['decimal_separator'], $config['thousand_separator'])); break; } } diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 880f77063f..304010ca75 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1617,6 +1617,7 @@ CREATE TABLE IF NOT EXISTS `treport_content` ( `ipam_ip_not_assigned_to_agent` TINYINT UNSIGNED NOT NULL DEFAULT 0, `macros_definition` TEXT, `render_definition` TEXT, + `use_prefix_notation` TINYINT UNSIGNED NOT NULL DEFAULT 1, PRIMARY KEY(`id_rc`), FOREIGN KEY (`id_report`) REFERENCES treport(`id_report`) ON UPDATE CASCADE ON DELETE CASCADE @@ -3244,6 +3245,7 @@ CREATE TABLE IF NOT EXISTS `treport_content_template` ( `ipam_ip_not_assigned_to_agent` TINYINT UNSIGNED NOT NULL DEFAULT 0, `macros_definition` TEXT, `render_definition` TEXT, + `use_prefix_notation` TINYINT UNSIGNED NOT NULL DEFAULT 1, PRIMARY KEY(`id_rc`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; diff --git a/pandora_plugins/intel_dcm/extensions/intel_dcm_agent_view.php b/pandora_plugins/intel_dcm/extensions/intel_dcm_agent_view.php index bdc1186044..737aa70770 100644 --- a/pandora_plugins/intel_dcm/extensions/intel_dcm_agent_view.php +++ b/pandora_plugins/intel_dcm/extensions/intel_dcm_agent_view.php @@ -142,26 +142,26 @@ function main_intel_dcm_agent_view() $sql = "SELECT description FROM tagent_custom_data WHERE id_field = $id_field_derated_power AND id_agent = $id_agent"; $derated_power = db_get_value_sql($sql); - $percent = number_format((($avg_power / $derated_power) * 100), 2); + $percent = number_format((($avg_power / $derated_power) * 100), 2, $config['decimal_separator'], $config['thousand_separator']); $data[0] = ''.__('Power utilization')." $percent%"; $data[0] .= progress_bar($percent, 400, 30, '', 2); $data[0] .= '

'; $data[0] .= ''.__('Current stats').''; $data[0] .= '

'; - $data[0] .= __('Power demand').': '.number_format($avg_power, 2).' Wh'; + $data[0] .= __('Power demand').': '.number_format($avg_power, 2, $config['decimal_separator'], $config['thousand_separator']).' Wh'; $data[0] .= '
'; - $data[0] .= __('Inlet temp').': '.number_format($avg_temp, 2).' ºC'; + $data[0] .= __('Inlet temp').': '.number_format($avg_temp, 2, $config['decimal_separator'], $config['thousand_separator']).' ºC'; $data[0] .= '


'; $data[0] .= ''.__('Last week summary').''; $data[0] .= '

'; - $data[0] .= __('Equipment energy consumed').': '.number_format($mnged_energy, 2).' Wh'; + $data[0] .= __('Equipment energy consumed').': '.number_format($mnged_energy, 2, $config['decimal_separator'], $config['thousand_separator']).' Wh'; $data[0] .= '
'; - $data[0] .= __('Equipment energy bill').': '.number_format($mnged_energy_bill, 2).' €'; + $data[0] .= __('Equipment energy bill').': '.number_format($mnged_energy_bill, 2, $config['decimal_separator'], $config['thousand_separator']).' €'; $data[0] .= '
'; - $data[0] .= __('Calculated cooling energy').': '.number_format($cooling_energy, 2).' Wh'; + $data[0] .= __('Calculated cooling energy').': '.number_format($cooling_energy, 2, $config['decimal_separator'], $config['thousand_separator']).' Wh'; $data[0] .= '
'; - $data[0] .= __('Calculated cooling energy bill').': '.number_format($cooling_energy_bill, 2).' €'; + $data[0] .= __('Calculated cooling energy bill').': '.number_format($cooling_energy_bill, 2, $config['decimal_separator'], $config['thousand_separator']).' €'; // Print avg. power graph $start_date = date('Y-m-d'); From 548308405c2862a268831acc5628178e4db2f0a2 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Thu, 27 Oct 2022 09:40:33 +0200 Subject: [PATCH 019/251] #9447 WIP --- pandora_server/util/pandora_manage.pl | 31 +++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 17a62f37dc..4ce5d40ae9 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -21,7 +21,7 @@ use JSON qw(decode_json encode_json); use MIME::Base64; use Encode qw(decode encode_utf8); use LWP::Simple; -#use Data::Dumper; +use Data::Dumper; # Default lib dir for RPM and DEB packages BEGIN { push @INC, '/usr/lib/perl5'; } @@ -1144,6 +1144,22 @@ sub help_screen_line($$$){ print "\n\t$option $parameters : $help.\n" unless ($param ne '' && $param ne $option); } +sub test ($) { + my (@item) = @_; + my @args = @ARGV; + my $arg_cont = 2; + my $total = $#args; + + print_log Dumper(@item); + + # print_log "$item[0]{name}\n\n"; + + while ($arg_cont <= $total) { + print_log "$args[$arg_cont]\n\n"; + $arg_cont++; + } +} + ############################################################################### ############################################################################### # CLI FUNCTIONS @@ -7648,9 +7664,16 @@ sub pandora_manage_main ($$$) { cli_delete_profile(); } elsif ($param eq '--create_event') { - param_check($ltotal, 20, 17); - cli_create_event(); - } + my @items = ( + {'type' => 'string', 'name' => 'user'}, + {'type' => 'int', 'name' => 'group'} + ); + + test(\@items); + # param_check($ltotal, 20, 17); + + # cli_create_event(); + } elsif ($param eq '--validate_event') { param_check($ltotal, 8, 7); cli_validate_event(); From a96eb2ce299a1cf122c89e2db3876459526c19b9 Mon Sep 17 00:00:00 2001 From: Calvo Date: Thu, 27 Oct 2022 12:35:31 +0200 Subject: [PATCH 020/251] Hide meta treeview user hash --- pandora_console/include/functions_treeview.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pandora_console/include/functions_treeview.php b/pandora_console/include/functions_treeview.php index 3fc35f4d84..ef7107ae7a 100755 --- a/pandora_console/include/functions_treeview.php +++ b/pandora_console/include/functions_treeview.php @@ -594,10 +594,10 @@ function treeview_printTable($id_agente, $server_data=[], $no_head=false) $hashdata = $user.$pwd_deserialiced['auth_token']; $hashdata = md5($hashdata); - $url = $server_data['server_url'].'/index.php?'.'sec=estado&'.'sec2=operation/agentes/ver_agente&'.'id_agente='.$agent['id_agente'].'&'.'loginhash=auto&'."loginhash_data=$hashdata&".'loginhash_user='.str_rot13($user); + $url = $server_data['server_url'].'/index.php?'.'sec=estado&'.'sec2=operation/agentes/ver_agente&'.'id_agente='.$agent['id_agente']; if ($grants_on_node && (bool) $user_access_node !== false) { - $cellName .= ''.''.$agent['alias'].''; + $cellName .= ''.$agent['alias'].''; } else { $cellName .= ''.$agent['alias'].''; } @@ -703,7 +703,7 @@ function treeview_printTable($id_agente, $server_data=[], $no_head=false) $go_to_agent .= html_print_submit_button(__('Edit cluster'), 'upd_button', false, 'class="sub config"', true); } } else { - $go_to_agent .= ''; + $go_to_agent .= ''; $go_to_agent .= html_print_submit_button(__('Go to agent edition'), 'upd_button', false, 'class="sub config"', true); } @@ -905,5 +905,12 @@ function treeview_printTable($id_agente, $server_data=[], $no_head=false) metaconsole_restore_db(); } - return; + echo " + "; } From eed83616214b4bef4123148522cad6aabee8bf22 Mon Sep 17 00:00:00 2001 From: Calvo Date: Thu, 27 Oct 2022 15:03:50 +0200 Subject: [PATCH 021/251] Check group and profile exist on api add permission user to group --- pandora_console/include/functions_api.php | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index 0f5f01590d..0c9c13839e 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -17185,6 +17185,32 @@ function api_set_add_permission_user_to_group($thrash1, $thrash2, $other, $retur ]; + $group_exist = db_get_value_filter( + 'id_grupo', + 'tgrupo', + [ + 'id_grupo' => $values['id_grupo'], + ] + ); + + if ((bool) $group_exist === false) { + returnError('Selected group does not exist'); + return; + } + + $profile_exist = db_get_value_filter( + 'id_perfil', + 'tperfil', + [ + 'id_perfil' => $values['id_perfil'], + ] + ); + + if ((bool) $profile_exist === false) { + returnError('Selected profile does not exist'); + return; + } + $where_id_up = ['id_up' => $other['data'][4]]; if ($exist_profile === $other['data'][4] && $where_id_up !== null) { $sucessfull_insert = db_process_sql_update('tusuario_perfil', $values, $where_id_up); From 8a43421b49aad8d5ee2a72d44a4a41247de2d35e Mon Sep 17 00:00:00 2001 From: Calvo Date: Thu, 27 Oct 2022 15:18:15 +0200 Subject: [PATCH 022/251] Fix module type validadion on api set create network module --- pandora_console/include/functions_api.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index 0f5f01590d..8b8c46e7c3 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -3587,6 +3587,19 @@ function api_set_create_network_module($id, $thrash1, $other, $thrash3) // Column 'module_macros' cannot be null. } + $type_exist = db_get_value_filter( + 'id_tipo', + 'ttipo_modulo', + [ + 'id_tipo' => $values['id_tipo_modulo'], + ] + ); + + if ((bool) $type_exist === false) { + returnError('Module type does not exist'); + return; + } + if ($agent_by_alias) { $agents_affected = 0; $idModule = false; From f4693b3cba3f1c3f36272d9d1f7e9852be3398de Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Mon, 31 Oct 2022 16:59:38 +0100 Subject: [PATCH 023/251] #9447 Added check_value --- pandora_server/util/pandora_manage.pl | 103 ++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 13 deletions(-) diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 4ce5d40ae9..19bf26c81d 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -1144,18 +1144,54 @@ sub help_screen_line($$$){ print "\n\t$option $parameters : $help.\n" unless ($param ne '' && $param ne $option); } -sub test ($) { - my (@item) = @_; - my @args = @ARGV; +sub check_values($) { + my ($check) = @_; + use experimental 'smartmatch'; + my $arg_cont = 2; + my $cont = 0; + my @args = @ARGV; my $total = $#args; - print_log Dumper(@item); - - # print_log "$item[0]{name}\n\n"; - while ($arg_cont <= $total) { - print_log "$args[$arg_cont]\n\n"; + # Check type. + if ($check->[$cont]->{'type'} eq 'json') { + my $json_out = eval { decode_json($args[$arg_cont]) }; + if ($@) + { + print "\nValue `$args[$arg_cont]` is an invalid json. \nError:$@\n"; + exit; + } + } + + # Check values. + if (defined($check->[$cont]->{'values'})) { + if (!($args[$arg_cont] ~~ $check->[$cont]->{'values'})) { + print "\nError: value `$args[$arg_cont]` is not valid for $check->[$cont]->{'name'}\n"; + print "\tAvailable options: \t$check->[$cont]->{'values'}->[0]"; + if (defined($check->[$cont]->{'text_extra'}->[0])) { + print " $check->[$cont]->{'text_extra'}->[0]"; + } + print "\n"; + + my $cont_aux = 1; + my $while = 'false'; + while ($while eq 'false') { + if (defined($check->[$cont]->{'values'}->[$cont_aux])) { + print "\t\t\t\t$check->[$cont]->{'values'}->[$cont_aux]"; + if (defined($check->[$cont]->{'text_extra'}->[$cont_aux])) { + print " $check->[$cont]->{'text_extra'}->[$cont_aux]"; + } + print "\n"; + } else { + exit; + } + $cont_aux++; + } + } + } + + $cont++; $arg_cont++; } } @@ -7664,13 +7700,54 @@ sub pandora_manage_main ($$$) { cli_delete_profile(); } elsif ($param eq '--create_event') { - my @items = ( - {'type' => 'string', 'name' => 'user'}, - {'type' => 'int', 'name' => 'group'} + my @fields = ( + {'name' => 'event'}, + { + 'name' => 'event_type', + 'values' => [ + 'unknown','alert_fired','alert_recovered','alert_ceased', + 'alert_manual_validation','recon_host_detected','system', + 'error','new_agent','going_up_warning','going_up_criticalgoing_down_warning', + 'going_down_normal','going_down_critical','going_up_normal','configuration_change' + ] + }, + {'name' => 'group_name'}, + {'name' => 'agent_name'}, + {'name' => 'module_name'}, + { + 'name' => 'event_status', + 'values' => ['0', '1'], + 'text_extra' => ['(New)', '(Validated)'] + }, + { + 'name' => 'severity', + 'values' => ['0', '1', '2', '3', '4', '5', '6'], + 'text_extra' => [ + '(Maintenance)', '(Informational)', '(Normal)', + '(Warning)', '(Critical)', '(Minor)', '(Major)' + ] + }, + {'name' => 'template_name'}, + {'name' => 'user_name'}, + {'name' => 'comment'}, + {'name' => 'source'}, + {'name' => 'id_extra'}, + {'name' => 'tags'}, + {'type' => 'json', 'name' => 'custom_data_json'}, + { + 'name' => 'force_create_agent', + 'values' => ['0', '1'] + }, + {'name' => 'critical_instructions'}, + {'name' => 'warning_instructions'}, + {'name' => 'unknown_instructions'}, + {'name' => 'use_alias'}, + {'name' => 'metaconsole'} ); - test(\@items); - # param_check($ltotal, 20, 17); + param_check($ltotal, 20, 17); + + check_values(\@fields); # cli_create_event(); } From 8971dba9c5f25c9fdb39e319b9f032fb77084ab3 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Mon, 31 Oct 2022 17:16:08 +0100 Subject: [PATCH 024/251] #9447 uncomment --- pandora_server/util/pandora_manage.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 19bf26c81d..3a90ea074a 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -7749,7 +7749,7 @@ sub pandora_manage_main ($$$) { check_values(\@fields); - # cli_create_event(); + cli_create_event(); } elsif ($param eq '--validate_event') { param_check($ltotal, 8, 7); From 0ff07d7224dcad2ca44a26be92a2ee581384aca0 Mon Sep 17 00:00:00 2001 From: Daniel Barbero Date: Wed, 2 Nov 2022 16:59:04 +0100 Subject: [PATCH 025/251] add new macro event response group_contact pandora_enterprise#9246 --- pandora_console/include/functions_events.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pandora_console/include/functions_events.php b/pandora_console/include/functions_events.php index 3aa121ec6a..f034e48ca1 100644 --- a/pandora_console/include/functions_events.php +++ b/pandora_console/include/functions_events.php @@ -3721,6 +3721,15 @@ function events_get_response_target( ); } + if (strpos($target, '_group_contact_') !== false) { + $info_groups = groups_get_group_by_id($event['id_grupo']); + $target = str_replace( + '_group_contact_', + (isset($info_groups['contact']) === true) ? $info_groups['contact'] : 'N/A', + $target + ); + } + if (strpos($target, '_event_utimestamp_') !== false) { $target = str_replace( '_event_utimestamp_', From 33b1c0ab8f560664feb21c10bdb8ed6bc24f21df Mon Sep 17 00:00:00 2001 From: Daniel Barbero Date: Thu, 3 Nov 2022 12:00:58 +0100 Subject: [PATCH 026/251] add new filter pandora_enterprise#9135 --- pandora_console/extras/mr/59.sql | 5 + .../godmode/events/event_edit_filter.php | 94 +++++++++++-------- pandora_console/include/ajax/events.php | 7 ++ pandora_console/include/functions_events.php | 11 ++- pandora_console/operation/events/events.php | 18 ++++ pandora_console/pandoradb.sql | 1 + 6 files changed, 98 insertions(+), 38 deletions(-) create mode 100644 pandora_console/extras/mr/59.sql diff --git a/pandora_console/extras/mr/59.sql b/pandora_console/extras/mr/59.sql new file mode 100644 index 0000000000..69f93d9e8a --- /dev/null +++ b/pandora_console/extras/mr/59.sql @@ -0,0 +1,5 @@ +START TRANSACTION; + +ALTER TABLE `tevent_filter` ADD COLUMN `owner_user` INT NOT NULL DEFAULT 0; + +COMMIT; \ No newline at end of file diff --git a/pandora_console/godmode/events/event_edit_filter.php b/pandora_console/godmode/events/event_edit_filter.php index af086d55d7..c796feaa90 100644 --- a/pandora_console/godmode/events/event_edit_filter.php +++ b/pandora_console/godmode/events/event_edit_filter.php @@ -73,6 +73,7 @@ if ($id) { $pagination = $filter['pagination']; $event_view_hr = $filter['event_view_hr']; $id_user_ack = $filter['id_user_ack']; + $owner_user = $filter['owner_user']; $group_rep = $filter['group_rep']; $date_from = str_replace('-', '/', $filter['date_from']); $date_to = str_replace('-', '/', $filter['date_to']); @@ -119,6 +120,7 @@ if ($id) { $pagination = ''; $event_view_hr = ''; $id_user_ack = ''; + $owner_user = ''; $group_rep = ''; $date_from = ''; $date_to = ''; @@ -157,6 +159,7 @@ if ($update || $create) { $pagination = get_parameter('pagination', ''); $event_view_hr = get_parameter('event_view_hr', ''); $id_user_ack = get_parameter('id_user_ack', ''); + $owner_user = get_parameter('owner_user', ''); $group_rep = get_parameter('group_rep', ''); $date_from = get_parameter('date_from', ''); $date_to = get_parameter('date_to', ''); @@ -191,6 +194,7 @@ if ($update || $create) { 'pagination' => $pagination, 'event_view_hr' => $event_view_hr, 'id_user_ack' => $id_user_ack, + 'owner_user' => $owner_user, 'group_rep' => $group_rep, 'tag_with' => $tag_with_json, 'tag_without' => $tag_without_json, @@ -420,7 +424,12 @@ $table->data[9][1] = html_print_input_text( true ); -$table->data[10][0] = ''.__('User ack.').''.' '.ui_print_help_tip(__('Choose between the users who have validated an event. '), true); +$table->data[10][0] = ''.__('User ack.').''; +$table->data[10][0] .= ' '; +$table->data[10][0] .= ui_print_help_tip( + __('Choose between the users who have validated an event. '), + true +); if ($strict_user) { $users = [$config['id_user'] => $config['id_user']]; @@ -442,14 +451,25 @@ $table->data[10][1] = html_print_select( true ); +$table->data[11][0] = ''.__('Owner.').''; +$table->data[11][1] = html_print_select( + $users, + 'owner_user', + $owner_user, + '', + __('Any'), + 0, + true +); + $repeated_sel = [ EVENT_GROUP_REP_ALL => __('All events'), EVENT_GROUP_REP_EVENTS => __('Group events'), EVENT_GROUP_REP_AGENTS => __('Group agents'), EVENT_GROUP_REP_EXTRAIDS => __('Group extra id'), ]; -$table->data[11][0] = ''.__('Repeated').''; -$table->data[11][1] = html_print_select( +$table->data[12][0] = ''.__('Repeated').''; +$table->data[12][1] = html_print_select( $repeated_sel, 'group_rep', $group_rep, @@ -459,11 +479,11 @@ $table->data[11][1] = html_print_select( true ); -$table->data[12][0] = ''.__('Date from').''; -$table->data[12][1] = html_print_input_text('date_from', $date_from, '', 15, 10, true); +$table->data[13][0] = ''.__('Date from').''; +$table->data[13][1] = html_print_input_text('date_from', $date_from, '', 15, 10, true); -$table->data[13][0] = ''.__('Date to').''; -$table->data[13][1] = html_print_input_text('date_to', $date_to, '', 15, 10, true); +$table->data[14][0] = ''.__('Date to').''; +$table->data[14][1] = html_print_input_text('date_to', $date_to, '', 15, 10, true); $tag_with = json_decode($tag_with_json_clean, true); if (empty($tag_with)) { @@ -502,9 +522,9 @@ $remove_with_tag_disabled = empty($tag_with_temp); $add_without_tag_disabled = empty($tags_select_without); $remove_without_tag_disabled = empty($tag_without_temp); -$table->colspan[14][0] = '2'; -$table->data[14][0] = ''.__('Events with following tags').''; -$table->data[15][0] = html_print_select( +$table->colspan[15][0] = '2'; +$table->data[15][0] = ''.__('Events with following tags').''; +$table->data[16][0] = html_print_select( $tags_select_with, 'select_with', '', @@ -518,7 +538,7 @@ $table->data[15][0] = html_print_select( false, 'width: 220px;' ); -$table->data[15][1] = html_print_button( +$table->data[16][1] = html_print_button( __('Add'), 'add_whith', $add_with_tag_disabled, @@ -527,7 +547,7 @@ $table->data[15][1] = html_print_button( true ); -$table->data[16][0] = html_print_select( +$table->data[17][0] = html_print_select( $tag_with_temp, 'tag_with_temp', [], @@ -541,12 +561,12 @@ $table->data[16][0] = html_print_select( false, 'width: 220px; height: 50px;' ); -$table->data[16][0] .= html_print_input_hidden( +$table->data[17][0] .= html_print_input_hidden( 'tag_with', $tag_with_base64, true ); -$table->data[16][1] = html_print_button( +$table->data[17][1] = html_print_button( __('Remove'), 'remove_whith', $remove_with_tag_disabled, @@ -555,9 +575,9 @@ $table->data[16][1] = html_print_button( true ); -$table->colspan[17][0] = '2'; -$table->data[17][0] = ''.__('Events without following tags').''; -$table->data[18][0] = html_print_select( +$table->colspan[18][0] = '2'; +$table->data[18][0] = ''.__('Events without following tags').''; +$table->data[19][0] = html_print_select( $tags_select_without, 'select_without', '', @@ -571,7 +591,7 @@ $table->data[18][0] = html_print_select( false, 'width: 220px;' ); -$table->data[18][1] = html_print_button( +$table->data[19][1] = html_print_button( __('Add'), 'add_whithout', $add_without_tag_disabled, @@ -580,7 +600,7 @@ $table->data[18][1] = html_print_button( true ); -$table->data[19][0] = html_print_select( +$table->data[20][0] = html_print_select( $tag_without_temp, 'tag_without_temp', [], @@ -594,12 +614,12 @@ $table->data[19][0] = html_print_select( false, 'width: 220px; height: 50px;' ); -$table->data[19][0] .= html_print_input_hidden( +$table->data[20][0] .= html_print_input_hidden( 'tag_without', $tag_without_base64, true ); -$table->data[19][1] = html_print_button( +$table->data[20][1] = html_print_button( __('Remove'), 'remove_whithout', $remove_without_tag_disabled, @@ -608,8 +628,8 @@ $table->data[19][1] = html_print_button( true ); -$table->data[20][0] = ''.__('Alert events').''; -$table->data[20][1] = html_print_select( +$table->data[21][0] = ''.__('Alert events').''; +$table->data[21][1] = html_print_select( [ '-1' => __('All'), '0' => __('Filter alert events'), @@ -624,8 +644,8 @@ $table->data[20][1] = html_print_select( ); if (!is_metaconsole()) { - $table->data[21][0] = ''.__('Module search').''; - $table->data[21][1] .= html_print_autocomplete_modules( + $table->data[22][0] = ''.__('Module search').''; + $table->data[22][1] .= html_print_autocomplete_modules( 'module_search', $text_module, false, @@ -637,17 +657,17 @@ if (!is_metaconsole()) { ); } -$table->data[22][0] = ''.__('Source').''; -$table->data[22][1] = html_print_input_text('source', $source, '', 35, 255, true); +$table->data[23][0] = ''.__('Source').''; +$table->data[23][1] = html_print_input_text('source', $source, '', 35, 255, true); -$table->data[23][0] = ''.__('Extra ID').''; -$table->data[23][1] = html_print_input_text('id_extra', $id_extra, '', 11, 255, true); +$table->data[24][0] = ''.__('Extra ID').''; +$table->data[24][1] = html_print_input_text('id_extra', $id_extra, '', 11, 255, true); -$table->data[24][0] = ''.__('Comment').''; -$table->data[24][1] = html_print_input_text('user_comment', $user_comment, '', 35, 255, true); +$table->data[25][0] = ''.__('Comment').''; +$table->data[25][1] = html_print_input_text('user_comment', $user_comment, '', 35, 255, true); -$table->data[25][0] = ''.__('Custom data filter type').''; -$table->data[25][1] = html_print_select( +$table->data[26][0] = ''.__('Custom data filter type').''; +$table->data[26][1] = html_print_select( [ '0' => __('Filter custom data by name field'), '1' => __('Filter custom data by value field'), @@ -660,12 +680,12 @@ $table->data[25][1] = html_print_select( true ); -$table->data[26][0] = ''.__('Custom data').''; -$table->data[26][1] = html_print_input_text('custom_data', $custom_data, '', 35, 255, true); +$table->data[27][0] = ''.__('Custom data').''; +$table->data[27][1] = html_print_input_text('custom_data', $custom_data, '', 35, 255, true); if (is_metaconsole()) { - $table->data[27][0] = ''.__('Id souce event').''; - $table->data[27][1] = html_print_input_text( + $table->data[28][0] = ''.__('Id souce event').''; + $table->data[28][1] = html_print_input_text( 'id_source_event', $id_source_event, '', diff --git a/pandora_console/include/ajax/events.php b/pandora_console/include/ajax/events.php index 5cb86d027e..9de1b29988 100644 --- a/pandora_console/include/ajax/events.php +++ b/pandora_console/include/ajax/events.php @@ -357,6 +357,7 @@ if ($save_event_filter) { $values['pagination'] = get_parameter('pagination'); $values['event_view_hr'] = get_parameter('event_view_hr'); $values['id_user_ack'] = get_parameter('id_user_ack'); + $values['owner_user'] = get_parameter('owner_user'); $values['group_rep'] = get_parameter('group_rep'); $values['tag_with'] = get_parameter('tag_with', io_json_mb_encode([])); $values['tag_without'] = get_parameter( @@ -415,6 +416,7 @@ if ($update_event_filter) { $values['pagination'] = get_parameter('pagination'); $values['event_view_hr'] = get_parameter('event_view_hr'); $values['id_user_ack'] = get_parameter('id_user_ack'); + $values['owner_user'] = get_parameter('owner_user'); $values['group_rep'] = get_parameter('group_rep'); $values['tag_with'] = get_parameter('tag_with', io_json_mb_encode([])); $values['tag_without'] = get_parameter( @@ -481,6 +483,7 @@ if ($get_filter_values) { 'user_comment' => '', 'id_extra' => '', 'id_user_ack' => '', + 'owner_user' => '', 'date_from' => '', 'time_from' => '', 'date_to' => '', @@ -654,6 +657,8 @@ function load_form_filter() { $("#text-event_view_hr").val(val); if (i == 'id_user_ack') $("#id_user_ack").val(val); + if (i == 'owner_user') + $("#owner_user").val(val); if (i == 'group_rep') $("#group_rep").val(val); if (i == 'tag_with') @@ -904,6 +909,7 @@ function save_new_filter() { "pagination" : $("#pagination").val(), "event_view_hr" : $("#text-event_view_hr").val(), "id_user_ack" : $("#id_user_ack").val(), + "owner_user" : $("#owner_user").val(), "group_rep" : $("#group_rep").val(), "tag_with": Base64.decode($("#hidden-tag_with").val()), "tag_without": Base64.decode($("#hidden-tag_without").val()), @@ -981,6 +987,7 @@ function save_update_filter() { "pagination" : $("#pagination").val(), "event_view_hr" : $("#text-event_view_hr").val(), "id_user_ack" : $("#id_user_ack").val(), + "owner_user" : $("#owner_user").val(), "group_rep" : $("#group_rep").val(), "tag_with" : Base64.decode($("#hidden-tag_with").val()), "tag_without" : Base64.decode($("#hidden-tag_without").val()), diff --git a/pandora_console/include/functions_events.php b/pandora_console/include/functions_events.php index 3aa121ec6a..0f41ef9574 100644 --- a/pandora_console/include/functions_events.php +++ b/pandora_console/include/functions_events.php @@ -645,6 +645,7 @@ function events_update_status($id_evento, $status, $filter=null) * 'user_comment' * 'source' * 'id_user_ack' + * 'owner_user' * 'tag_with' * 'tag_without' * 'filter_only_alert' @@ -1153,11 +1154,19 @@ function events_get_all( // Validated or in process by. if (empty($filter['id_user_ack']) === false) { $sql_filters[] = sprintf( - ' AND te.owner_user like lower("%%%s%%") ', + ' AND te.id_usuario like lower("%%%s%%") ', $filter['id_user_ack'] ); } + // Owner by. + if (empty($filter['owner_user']) === false) { + $sql_filters[] = sprintf( + ' AND te.owner_user like lower("%%%s%%") ', + $filter['owner_user'] + ); + } + $tag_names = []; // With following tags. if (empty($filter['tag_with']) === false) { diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php index e95f16b355..a74ffd9eae 100644 --- a/pandora_console/operation/events/events.php +++ b/pandora_console/operation/events/events.php @@ -153,6 +153,10 @@ $id_user_ack = get_parameter( 'filter[id_user_ack]', ($filter['id_user_ack'] ?? '') ); +$owner_user = get_parameter( + 'filter[owner_user]', + ($filter['owner_user'] ?? '') +); $group_rep = get_parameter( 'filter[group_rep]', ($filter['group_rep'] ?? '') @@ -1089,6 +1093,7 @@ if ($loaded_filter !== false && $from_event_graph != 1 && isset($fb64) === false $pagination = $filter['pagination']; $event_view_hr = $filter['event_view_hr']; $id_user_ack = $filter['id_user_ack']; + $owner_user = $filter['owner_user']; $group_rep = $filter['group_rep']; $tag_with = json_decode(io_safe_output($filter['tag_with'])); $tag_without = json_decode(io_safe_output($filter['tag_without'])); @@ -1914,6 +1919,19 @@ $in = '
'; $in .= $data.'
'; $adv_inputs[] = $in; +$data = html_print_select( + $user_users, + 'owner_user', + $owner_user, + '', + __('Any'), + 0, + true +); +$in = '
'; +$in .= $data.'
'; +$adv_inputs[] = $in; + // Only alert events. $data = html_print_select( [ diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 48768a9508..08a42f8ad6 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1258,6 +1258,7 @@ CREATE TABLE IF NOT EXISTS `tevent_filter` ( `time_to` TIME NULL, `custom_data` VARCHAR(500) DEFAULT '', `custom_data_filter_type` TINYINT UNSIGNED DEFAULT 0, + `owner_user` TEXT, PRIMARY KEY (`id_filter`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; From ccc2e830f4231ae4219266d36df1c4282476e836 Mon Sep 17 00:00:00 2001 From: Daniel Barbero Date: Thu, 3 Nov 2022 15:12:50 +0100 Subject: [PATCH 027/251] add sound events to metaconsole pandora_enterprise#8854 --- pandora_console/include/ajax/events.php | 2 +- .../include/javascript/pandora_events.js | 14 +++++++------- pandora_console/include/styles/sound_events.css | 3 +++ pandora_console/operation/menu.php | 5 +---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pandora_console/include/ajax/events.php b/pandora_console/include/ajax/events.php index 5cb86d027e..b9a863cfcd 100644 --- a/pandora_console/include/ajax/events.php +++ b/pandora_console/include/ajax/events.php @@ -2270,7 +2270,7 @@ if ($drawConsoleSound === true) { ], ], [ - 'label' => __('Time Sound'), + 'label' => __('Sound duration'), 'arguments' => [ 'type' => 'select', 'fields' => $times_sound, diff --git a/pandora_console/include/javascript/pandora_events.js b/pandora_console/include/javascript/pandora_events.js index df84985a37..84be4f824c 100644 --- a/pandora_console/include/javascript/pandora_events.js +++ b/pandora_console/include/javascript/pandora_events.js @@ -920,7 +920,7 @@ function openSoundEventModal(settings) { sound = true; } - test_sound_button(sound); + test_sound_button(sound, settings.urlSound); }); // Play Stop. @@ -977,9 +977,9 @@ function openSoundEventModal(settings) { .show(); } -function test_sound_button(test_sound) { +function test_sound_button(test_sound, urlSound) { if (test_sound === true) { - add_audio(); + add_audio(urlSound); } else { remove_audio(); } @@ -1035,8 +1035,8 @@ function action_events_sound(mode, settings) { } } -function add_audio() { - var sound = "./include/sounds/" + $("#tabs-sound-modal #sound_id").val(); +function add_audio(urlSound) { + var sound = urlSound + $("#tabs-sound-modal #sound_id").val(); $(".actions-sound-modal").append( "
'; $data[1] .= html_print_image('images/file.png', true, ['class' => 'invert_filter'], false, true); @@ -411,11 +408,7 @@ if (($create != '') || ($view != '')) { $data = []; $data[0] = __('Plug-in parameters'); - $data[1] = ''; - if ($locked) { - $data[1] .= html_print_image('images/lock_mc.png', true, ['class' => 'command_advanced_conf lock', 'class' => 'invert_filter']); - } - + $data[1] = ''; $table->data['plugin_parameters'] = $data; $data = []; @@ -484,16 +477,10 @@ if (($create != '') || ($view != '')) { $datam = []; $datam[0] = __('Description')." ($macro_name)"; $datam[0] .= html_print_input_hidden($macro_name_name, $macro_name, true); - $datam[1] = html_print_input_text_extended($macro_desc_name, $macro_desc_value, 'text-'.$macro_desc_name, '', 30, 255, $locked, '', "class='command_macro text_input'", true); - if ($locked) { - $datam[1] .= html_print_image('images/lock_mc.png', true, ['class' => 'command_macro lock', 'class' => 'invert_filter']); - } + $datam[1] = html_print_input_text_extended($macro_desc_name, $macro_desc_value, 'text-'.$macro_desc_name, '', 30, 255, false, '', "class='command_macro text_input'", true); $datam[2] = __('Default value')." ($macro_name)"; - $datam[3] = html_print_input_text_extended($macro_value_name, $macro_value_value, 'text-'.$macro_value_name, '', 30, 255, $locked, '', "class='command_component command_macro text_input'", true); - if ($locked) { - $datam[3] .= html_print_image('images/lock_mc.png', true, ['class' => 'command_macro lock', 'class' => 'invert_filter']); - } + $datam[3] = html_print_input_text_extended($macro_value_name, $macro_value_value, 'text-'.$macro_value_name, '', 30, 255, false, '', "class='command_component command_macro text_input'", true); $table->data['plugin_'.$next_name_number] = $datam; @@ -524,24 +511,15 @@ if (($create != '') || ($view != '')) { $datam = []; $datam[0] = __('Help')." ($macro_name)


"; - $tadisabled = $locked === true ? ' disabled' : ''; $datam[1] = html_print_textarea( $macro_help_name, 6, 100, $macro_help_value, - 'class="command_macro" class="w97p"'.$tadisabled, + 'class="command_macro" class="w97p"', true ); - if ($locked) { - $datam[1] .= html_print_image( - 'images/lock_mc.png', - true, - ['class' => 'command_macro lock invert_filter'] - ); - } - $datam[1] .= '


'; $table->data['plugin_'.$next_name_number] = $datam; @@ -551,15 +529,16 @@ if (($create != '') || ($view != '')) { // Add/Delete buttons $datam = []; - $datam[0] = '
'.''.__('Add macro').''.' '.html_print_image( - 'images/add.png', - true, - ['class' => 'invert_filter'] - ).''; - $datam[0] .= ''; - $datam[0] .= ''; if (!$locked) { + $datam[0] = ''.''.__('Add macro').''.' '.html_print_image( + 'images/add.png', + true, + ['class' => 'invert_filter'] + ).''; + $datam[0] .= ''; + $datam[0] .= ''; + $delete_macro_style = ''; if ($i <= 2) { $delete_macro_style = 'display:none;'; @@ -1002,8 +981,11 @@ ui_require_javascript_file('pandora_modules'); }); update_preview(); } - $('a#add_macro_btn').click(add_macro_click_event); - + + if (locked === 0) { + $('a#add_macro_btn').click(add_macro_click_event); + } + // Delete macro var delete_macro_click_event = function (event) { delete_macro_form('table-form-plugin_'); @@ -1031,45 +1013,12 @@ ui_require_javascript_file('pandora_modules'); } } - var command_click_locked_event = function (event) { - var $element = $(this); - - if (!$element.is('input') || ($element.is('input') && ($element.prop('readonly') || $element.prop('disabled')))) { - if ($element.prop('id') === 'form_parameters') { - var message = '' - + '.\n' + ''; - - if (confirm(message)) { - if ($element.is('input')) { - $element - .prop('readonly', false) - .prop('disabled', false) - .siblings('img.command_advanced_conf.lock') - .remove(); - } - else { - $element - .siblings('input.command_advanced_conf') - .prop('readonly', false) - .prop('disabled', false) - $element.remove(); - } - } - } - else { - alert(""); - } - } - } - var macros_click_locked_event = function (event) { alert(""); } if (locked) { $('a#add_macro_btn').click(add_macro_click_locked_event); - $('.command_advanced_conf').click(command_click_locked_event); - $('.command_macro').click(macros_click_locked_event); } From e10455c90256c82e3fcd11237553a1d82e236d81 Mon Sep 17 00:00:00 2001 From: Daniel Barbero Date: Thu, 10 Nov 2022 16:10:50 +0100 Subject: [PATCH 036/251] new widget datamatrix pandora_enterprise#8619 --- pandora_console/include/ajax/module.php | 20 ++++- pandora_console/include/functions_modules.php | 82 +++++++++++++++++-- .../lib/Dashboard/Widgets/DataMatrix.php | 64 ++++++--------- 3 files changed, 118 insertions(+), 48 deletions(-) diff --git a/pandora_console/include/ajax/module.php b/pandora_console/include/ajax/module.php index f4e8722930..507faff3d6 100755 --- a/pandora_console/include/ajax/module.php +++ b/pandora_console/include/ajax/module.php @@ -26,6 +26,8 @@ * ============================================================================ */ +use PandoraFMS\Enterprise\Metaconsole\Node; + // Begin. if (check_login()) { global $config; @@ -1472,7 +1474,16 @@ if (check_login()) { $date = (get_system_time() - ($time_all_box * $start)); $datelimit = ($date - $time_all_box); foreach ($modules as $key => $value) { - // TODO: tresholds. + if (is_metaconsole() === true) { + try { + $node = new Node((int) $value['id_node']); + $node->connect(); + } catch (\Exception $e) { + // Unexistent agent. + $node->disconnect(); + } + } + $value['thresholds'] = [ 'min_critical' => (empty($value['c_min']) === true) ? null : $value['c_min'], 'max_critical' => (empty($value['c_max']) === true) ? null : $value['c_max'], @@ -1504,8 +1515,9 @@ if (check_login()) { $vdata, $value['thresholds'] ); + $resultData = ''; - if ($vdata !== null && $vdata !== '') { + if ($vdata !== null && $vdata !== '' && $vdata !== false) { if (isset($formatData) === true && (bool) $formatData === true ) { @@ -1535,6 +1547,10 @@ if (check_login()) { }, [] ); + + if (is_metaconsole() === true) { + $node->disconnect(); + } } if (empty($uncompressData) === false) { diff --git a/pandora_console/include/functions_modules.php b/pandora_console/include/functions_modules.php index e8d37d19bc..00ce23070f 100755 --- a/pandora_console/include/functions_modules.php +++ b/pandora_console/include/functions_modules.php @@ -4338,7 +4338,16 @@ function modules_get_regex( } -function get_status_data_modules($id_module, $data, $thresholds) +/** + * Status for data thresholds modules. + * + * @param integer $id_module Module ID. + * @param mixed $data Data int, bool, null, etc. + * @param array $thresholds Array thresholds. + * + * @return array + */ +function get_status_data_modules(int $id_module, $data, $thresholds) { // Check not init. if ($data === false) { @@ -4355,6 +4364,8 @@ function get_status_data_modules($id_module, $data, $thresholds) } } + $thresholds = calculateThreshold($thresholds); + foreach (getStatuses() as $status) { if ($thresholds[$status]['min'] === null && $thresholds[$status]['max'] === null @@ -4369,7 +4380,13 @@ function get_status_data_modules($id_module, $data, $thresholds) || ($thresholds[$status]['min'] <= $data && $thresholds[$status]['max'] >= $data) ) { - return $status; + if ($status === 'critical') { + return ['color' => COL_CRITICAL]; + } else if ($status === 'warning') { + return ['color' => COL_WARNING]; + } else { + return ['color' => COL_NORMAL]; + } } } @@ -4377,6 +4394,61 @@ function get_status_data_modules($id_module, $data, $thresholds) } +/** + * Calculate thresholds. + * + * @param array $thresholds_array + * + * @return array + */ +function calculateThreshold(array $thresholds_array) +{ + $nMax = null; + if ($thresholds_array['min_warning'] !== null) { + $nMax = $thresholds_array['min_warning']; + } else if ($thresholds_array['min_critical'] !== null) { + $nMax = $thresholds_array['min_critical']; + } + + $wMin = null; + if ($thresholds_array['min_warning'] !== null) { + $wMin = $thresholds_array['min_warning']; + } + + $wMax = null; + if ($thresholds_array['max_warning'] !== null) { + $wMax = $thresholds_array['max_warning']; + } + + $cMin = null; + if ($thresholds_array['min_critical'] !== null) { + $cMin = $thresholds_array['min_critical']; + } + + $cMax = null; + if ($thresholds_array['max_critical'] !== null) { + $cMax = $thresholds_array['max_critical']; + } + + $thresholds = [ + 'normal' => [ + 'min' => null, + 'max' => $nMax, + ], + 'warning' => [ + 'min' => $wMin, + 'max' => $wMax, + ], + 'critical' => [ + 'min' => $cMin, + 'max' => $cMax, + ], + ]; + + return $thresholds; +} + + /** * Get status. * @@ -4385,8 +4457,8 @@ function get_status_data_modules($id_module, $data, $thresholds) function getStatuses() { return [ - 'CRITICAL', - 'WARNING', - 'NORMAL', + 'critical', + 'warning', + 'normal', ]; } diff --git a/pandora_console/include/lib/Dashboard/Widgets/DataMatrix.php b/pandora_console/include/lib/Dashboard/Widgets/DataMatrix.php index 7a326a0549..e75d7da9e4 100644 --- a/pandora_console/include/lib/Dashboard/Widgets/DataMatrix.php +++ b/pandora_console/include/lib/Dashboard/Widgets/DataMatrix.php @@ -117,13 +117,6 @@ class DataMatrix extends Widget */ protected $cellId; - /** - * Size. - * - * @var array - */ - private $size; - /** * Construct. @@ -287,21 +280,10 @@ class DataMatrix extends Widget $inputs['inputs']['row1'][] = $vInput; } - if (empty($values['fontColor']) === true) { - $values['fontColor'] = '#2c3e50'; + if (isset($values['formatData']) === false) { + $values['formatData'] = 1; } - $inputs['inputs']['row1'][] = [ - 'label' => __('Font color'), - 'arguments' => [ - 'wrapper' => 'div', - 'name' => 'fontColor', - 'type' => 'color', - 'value' => $values['fontColor'], - 'return' => true, - ], - ]; - // Format Data. $inputs['inputs']['row1'][] = [ 'label' => __('Format Data'), @@ -313,24 +295,6 @@ class DataMatrix extends Widget ], ]; - // Type Label. - $fields = [ - 'module' => __('Module'), - 'agent' => __('Agent'), - 'agent_module' => __('Agent / module'), - ]; - - $inputs['inputs']['row1'][] = [ - 'label' => __('Label'), - 'arguments' => [ - 'type' => 'select', - 'fields' => $fields, - 'name' => 'label', - 'selected' => $values['label'], - 'return' => true, - ], - ]; - if (isset($values['period']) === false) { $values['period'] = SECONDS_1DAY; } @@ -390,6 +354,24 @@ class DataMatrix extends Widget ], ]; + // Type Label. + $fields = [ + 'module' => __('Module'), + 'agent' => __('Agent'), + 'agent_module' => __('Agent / module'), + ]; + + $inputs['inputs']['row2'][] = [ + 'label' => __('Label'), + 'arguments' => [ + 'type' => 'select', + 'fields' => $fields, + 'name' => 'label', + 'selected' => $values['label'], + 'return' => true, + ], + ]; + $inputs['inputs']['row2'][] = [ 'arguments' => [ 'type' => 'select_multiple_modules_filtered_select2', @@ -450,7 +432,7 @@ class DataMatrix extends Widget $agModule ); - $values['formatData'] = \get_parameter_switch('formatData', 0); + $values['formatData'] = \get_parameter_switch('formatData', 1); $values['fontColor'] = \get_parameter('fontColor', '#2c3e50'); $values['label'] = \get_parameter('label', 'module'); @@ -544,7 +526,6 @@ class DataMatrix extends Widget 'ajax_data' => [ 'get_data_dataMatrix' => 1, 'table_id' => $tableId, - 'length' => $this->values['limit'], 'period' => $this->values['period'], 'slice' => $this->values['slice'], 'formatData' => $this->values['formatData'], @@ -556,6 +537,7 @@ class DataMatrix extends Widget 'field' => 'date', 'direction' => 'desc', ], + 'csv' => 0, ] ); } catch (\Exception $e) { @@ -704,7 +686,7 @@ class DataMatrix extends Widget { $size = [ 'width' => (is_metaconsole() === true) ? 1000 : 900, - 'height' => 550, + 'height' => 480, ]; return $size; From 6a173664d4a715be8810c4573cc32b14bc11b79d Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Fri, 11 Nov 2022 12:09:03 +0100 Subject: [PATCH 037/251] Removed transactional server --- .../general/first_task/transactional_list.php | 46 ------------------- pandora_console/include/functions_servers.php | 3 -- pandora_console/operation/menu.php | 2 - .../FreeBSD/pandora_server.conf.new | 8 ---- pandora_server/conf/pandora_server.conf.new | 8 ---- .../conf/pandora_server.conf.windows | 8 ---- pandora_server/lib/PandoraFMS/Config.pm | 8 ---- pandora_server/lib/PandoraFMS/Core.pm | 1 - pandora_server/lib/PandoraFMS/Tools.pm | 2 - 9 files changed, 86 deletions(-) delete mode 100644 pandora_console/general/first_task/transactional_list.php diff --git a/pandora_console/general/first_task/transactional_list.php b/pandora_console/general/first_task/transactional_list.php deleted file mode 100644 index c1d9ef2f42..0000000000 --- a/pandora_console/general/first_task/transactional_list.php +++ /dev/null @@ -1,46 +0,0 @@ - - true, 'message' => __('There are no transactions defined yet.') ]); - -if ($networkmaps_write || $networkmaps_manage) { - ?> - -
-
- __('Transactions')]); ?> -
-
-

- -

-
- -
-
-
- {"inventoryserver"} = 1; # default $pa_config->{"webserver"} = 1; # 3.0 $pa_config->{"web_timeout"} = 60; # 6.0SP5 - $pa_config->{"transactionalserver"} = 0; # Default 0, introduced on 6.1 - $pa_config->{"transactional_threshold"} = 2; # Default 2, introduced on 6.1 $pa_config->{"transactional_pool"} = $pa_config->{"incomingdir"} . "/" . "trans"; # Default, introduced on 6.1 $pa_config->{'snmp_logfile'} = "/var/log/pandora_snmptrap.log"; $pa_config->{"network_threads"} = 3; # Fixed default @@ -776,12 +774,6 @@ sub pandora_load_config { elsif ($parametro =~ m/^web_timeout\s+([0-9]*)/i) { $pa_config->{'web_timeout'}= clean_blank($1); } - elsif ($parametro =~ m/^transactionalserver\s+([0-9]*)/i) { - $pa_config->{'transactionalserver'}= clean_blank($1); - } - elsif ($parametro =~ m/^transactional_threshold\s+([0-9]*\.{0,1}[0-9]*)/i) { - $pa_config->{'transactional_threshold'}= clean_blank($1); - } if ($parametro =~ m/^transactional_pool\s(.*)/i) { $tbuf= clean_blank($1); if ($tbuf =~ m/^\.(.*)/){ diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index b3c8b2576a..f806908a7b 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -299,7 +299,6 @@ our @ServerTypes = qw ( icmpserver snmpserver satelliteserver - transactionalserver mfserver syncserver wuxserver diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index f922e75854..590fdf2020 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -72,7 +72,6 @@ our @EXPORT = qw( SNMPSERVER SATELLITESERVER MFSERVER - TRANSACTIONALSERVER SYNCSERVER SYSLOGSERVER WUXSERVER @@ -2837,7 +2836,6 @@ sub get_server_name { return "ICMPSERVER" if ($server_type eq ICMPSERVER); return "SNMPSERVER" if ($server_type eq SNMPSERVER); return "SATELLITESERVER" if ($server_type eq SATELLITESERVER); - return "TRANSACTIONALSERVER" if ($server_type eq TRANSACTIONALSERVER); return "MFSERVER" if ($server_type eq MFSERVER); return "SYNCSERVER" if ($server_type eq SYNCSERVER); return "WUXSERVER" if ($server_type eq WUXSERVER); From 780e6ac51473280e19c03ad06e22a557fcb698ca Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Fri, 11 Nov 2022 12:53:41 +0100 Subject: [PATCH 038/251] Removed transactional server --- pandora_console/extras/mr/59.sql | 6 ++++++ pandora_console/pandoradb.sql | 31 +------------------------------ 2 files changed, 7 insertions(+), 30 deletions(-) create mode 100644 pandora_console/extras/mr/59.sql diff --git a/pandora_console/extras/mr/59.sql b/pandora_console/extras/mr/59.sql new file mode 100644 index 0000000000..e5016f9da1 --- /dev/null +++ b/pandora_console/extras/mr/59.sql @@ -0,0 +1,6 @@ +START TRANSACTION; + +DROP TABLE IF EXISTS `tphase`; +DROP TABLE IF EXISTS `ttransaction`; + +COMMIT; diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 89fa418389..78746b9881 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -3410,37 +3410,8 @@ CREATE TABLE IF NOT EXISTS `tmetaconsole_agent` ( ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; -- --------------------------------------------------------------------- --- Table `ttransaction` +-- Table `treset_pass` -- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `ttransaction` ( - `transaction_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `agent_id` INT UNSIGNED NOT NULL, - `group_id` INT UNSIGNED NOT NULL DEFAULT 0, - `description` TEXT, - `name` VARCHAR(250) NOT NULL, - `loop_interval` INT UNSIGNED NOT NULL DEFAULT 40, - `ready` INT UNSIGNED NOT NULL DEFAULT 0, - `running` INT UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY (`transaction_id`) -) engine=InnoDB DEFAULT CHARSET=UTF8MB4; - --- --------------------------------------------------------------------- --- Table `tphase` --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tphase`( - `phase_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `transaction_id` INT UNSIGNED NOT NULL, - `agent_id` INT UNSIGNED NOT NULL, - `name` VARCHAR(250) NOT NULL, - `idx` INT UNSIGNED NOT NULL, - `dependencies` TEXT, - `enables` TEXT, - `launch` TEXT, - `retries` INT UNSIGNED DEFAULT null, - `timeout` INT UNSIGNED DEFAULT null, - PRIMARY KEY (`phase_id`,`transaction_id`) -) engine=InnoDB DEFAULT CHARSET=UTF8MB4; - CREATE TABLE IF NOT EXISTS `treset_pass` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `id_user` VARCHAR(255) NOT NULL DEFAULT '', From a357dcfb0d38b39f0531cae1921052c77ad70ef5 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Fri, 11 Nov 2022 13:20:23 +0100 Subject: [PATCH 039/251] updated delete files file --- pandora_console/extras/delete_files/delete_files.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index 96223ccd69..90107df226 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -1667,3 +1667,13 @@ godmode/um_client/vendor/sebastian godmode/um_client/vendor update_manager_client/resources/styles/pandora.css enterprise/meta/general/upload_head_image.php +general/first_task/transactional_list.php +enterprise/include/ajax/transactional.ajax.php +enterprise/include/class/Transactionalmap.class.php +enterprise/include/help/es/help_transactional_map_phases.php +enterprise/include/javascript/transactional/TransactionalController.js +enterprise/include/functions_transactional.php +enterprise/operation/agentes/manage_transmap.php +enterprise/operation/agentes/manage_transmap_creation.php +enterprise/operation/agentes/manage_transmap_creation_phases_data.php +enterprise/operation/agentes/transactional_map.php From 564cd837ae73fc762914eab97a97a6dcc261d0db Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Mon, 14 Nov 2022 17:43:35 +0100 Subject: [PATCH 040/251] #9292 code refactoring --- .../include/class/SnmpConsole.class.php | 1073 +++++++++++++ pandora_console/include/styles/pandora.css | 13 + .../operation/snmpconsole/snmp_view.php | 1352 +---------------- 3 files changed, 1115 insertions(+), 1323 deletions(-) create mode 100644 pandora_console/include/class/SnmpConsole.class.php diff --git a/pandora_console/include/class/SnmpConsole.class.php b/pandora_console/include/class/SnmpConsole.class.php new file mode 100644 index 0000000000..50ada73852 --- /dev/null +++ b/pandora_console/include/class/SnmpConsole.class.php @@ -0,0 +1,1073 @@ +ajaxController = $ajaxController; + } + + + /** + * Run view + * + * @return void + */ + public function run() + { + global $config; + // Javascript. + ui_require_jquery_file('pandora'); + // CSS. + ui_require_css_file('wizard'); + ui_require_css_file('discovery'); + + $statistics['text'] = ''.html_print_image( + 'images/op_reporting.png', + true, + [ + 'title' => __('Statistics'), + 'class' => 'invert_filter', + ] + ).''; + $list['text'] = ''.html_print_image( + 'images/op_snmp.png', + true, + [ + 'title' => __('List'), + 'class' => 'invert_filter', + ] + ).''; + $list['active'] = true; + + // Header + ui_print_standard_header( + __('SNMP Console'), + 'images/op_snmp.png', + false, + 'snmp_console', + false, + [ + $list, + $statistics, + ], + [ + [ + 'link' => '', + 'label' => __('Monitoring'), + ], + [ + 'link' => '', + 'label' => __('SNMP'), + ], + ] + ); + + // Datatables list. + try { + $checkbox_all = html_print_checkbox( + 'all_validate_box', + 1, + false, + true + ); + + $columns = [ + 'status', + [ + 'text' => 'snmp_agent', + 'class' => 'snmp-td', + ], + [ + 'text' => 'enterprise_string', + 'class' => 'snmp-td', + ], + [ + 'text' => 'count', + 'class' => 'snmp-td', + ], + [ + 'text' => 'trap_subtype', + 'class' => 'snmp-td', + ], + [ + 'text' => 'user_id', + 'class' => 'snmp-td', + ], + [ + 'text' => 'timestamp', + 'class' => 'snmp-td', + ], + 'alert', + 'action', + [ + 'text' => 'm', + 'class' => 'mw60px pdd_0px', + ], + ]; + + $column_names = [ + __('Status'), + __('SNMP Agent'), + __('Enterprise String'), + __('Count'), + __('Trap subtype'), + __('User ID'), + __('Timestamp'), + __('Alert'), + __('Actions'), + [ + 'text' => 'm', + 'extra' => $checkbox_all, + 'class' => 'w20px no-text-imp', + ], + ]; + + $show_alerts = [ + -1 => __('All'), + 0 => __('Not triggered'), + 1 => __('Triggered'), + ]; + + $severities = get_priorities(); + $severities[-1] = __('All'); + + $paginations = [ + $config['block_size'] => __('Default'), + 25 => '25', + 50 => '50', + 100 => '100', + 200 => '200', + 500 => '500', + ]; + + $status_array = [ + -1 => __('All'), + 0 => __('Not validated'), + 1 => __('Validated'), + ]; + + $trap_types = [ + -1 => __('None'), + 0 => __('Cold start (0)'), + 1 => __('Warm start (1)'), + 2 => __('Link down (2)'), + 3 => __('Link up (3)'), + 4 => __('Authentication failure (4)'), + 5 => __('Other'), + ]; + + $this->tableId = 'snmp_console'; + + // Load datatables user interface. + ui_print_datatable( + [ + 'id' => $this->tableId, + 'class' => 'info_table', + 'style' => 'width: 100%', + 'columns' => $columns, + 'column_names' => $column_names, + 'ajax_url' => $this->ajaxController, + 'ajax_data' => ['method' => 'draw'], + 'ajax_postprocces' => 'process_datatables_item(item)', + 'search_button_class' => 'sub filter float-right', + 'no_sortable_columns' => [ + 0, + 7, + 8, + 9, + ], + 'form' => [ + 'class' => 'flex-row', + 'inputs' => [ + [ + 'label' => __('Alert'), + 'type' => 'select', + 'id' => 'filter_alert', + 'name' => 'filter_alert', + 'class' => 'w200px', + 'fields' => $show_alerts, + 'return' => true, + 'selected' => -1, + ], + [ + 'label' => __('Severity'), + 'type' => 'select', + 'id' => 'filter_severity', + 'name' => 'filter_severity', + 'class' => 'w200px', + 'fields' => $severities, + 'return' => true, + 'selected' => -1, + ], + [ + 'label' => __('Free search'), + 'type' => 'text', + 'class' => 'w400px', + 'id' => 'filter_free_search', + 'name' => 'filter_free_search', + ], + [ + 'label' => __('Status'), + 'type' => 'select', + 'id' => 'filter_status', + 'name' => 'filter_status', + 'class' => 'w200px', + 'fields' => $status_array, + 'return' => true, + 'selected' => -1, + ], + [ + 'label' => __('Group by Enterprise String/IP'), + 'type' => 'select', + 'name' => 'filter_group_by', + 'selected' => 0, + 'disabled' => false, + 'return' => true, + 'id' => 'filter_group_by', + 'fields' => [ + 0 => __('No'), + 1 => __('Yes'), + ], + ], + [ + 'label' => __('Max. hours old'), + 'type' => 'text', + 'class' => 'w200px', + 'id' => 'filter_hours_ago', + 'name' => 'filter_hours_ago', + 'value' => '8', + ], + [ + 'label' => __('Trap type'), + 'type' => 'select', + 'id' => 'filter_trap_type', + 'name' => 'filter_trap_type', + 'class' => 'w200px', + 'fields' => $trap_types, + 'return' => true, + 'selected' => -1, + ], + ], + ], + ] + ); + } catch (Exception $e) { + echo $e->getMessage(); + } + + echo '
'; + html_print_submit_button(__('Validate'), 'updatebt', false, 'class="sub ok"'); + echo ' '; + html_print_submit_button(__('Delete'), 'deletebt', false, 'class="sub delete" onClick="javascript:return confirm(\''.__('Are you sure?').'\')"'); + echo '
'; + + echo '
'; + echo '

'.__('Status').'

'; + echo html_print_image( + 'images/pixel_green.png', + true, + [ + 'width' => '20', + 'height' => '20', + ] + ).' - '.__('Validated'); + echo '
'; + echo html_print_image( + 'images/pixel_red.png', + true, + [ + 'width' => '20', + 'height' => '20', + ] + ).' - '.__('Not validated'); + echo '
'; + echo '
'; + echo '

'.__('Alert').'

'; + echo html_print_image( + 'images/pixel_yellow.png', + true, + [ + 'width' => '20', + 'height' => '20', + ] + ).' - '.__('Fired'); + echo '
'; + echo html_print_image( + 'images/pixel_gray.png', + true, + [ + 'width' => '20', + 'height' => '20', + ] + ).' - '.__('Not fired'); + echo '
'; + echo '
'; + echo '

'.__('Action').'

'; + echo html_print_image('images/ok.png', true).' - '.__('Validate'); + echo '
'; + echo html_print_image('images/cross.png', true, ['class' => 'invert_filter']).' - '.__('Delete'); + echo '
'; + echo '
'; + echo '

'.__('Severity').'

'; + foreach (get_priorities() as $num => $name) { + echo ''.$name.''; + echo '
'; + } + + echo '
'; + + // Load own javascript file. + echo $this->loadJS(); + } + + + /** + * Get the data for draw the table. + * + * @return void. + */ + public function draw() + { + global $config; + + // Init data. + $data = []; + // Count of total records. + $count = 0; + // Catch post parameters. + $start = get_parameter('start', 0); + $length = get_parameter('length', $config['block_size']); + + $order = get_datatable_order(true); + $filters = get_parameter('filter', []); + + // Build ranges. + $now = new DateTime(); + $ago = new DateTime(); + $interval = new DateInterval(sprintf('PT%dH', $filters['filter_hours_ago'])); + $ago->sub($interval); + + $date_from_trap = $ago->format('Y/m/d'); + $date_to_trap = $now->format('Y/m/d'); + $time_from_trap = $ago->format('H:i:s'); + $time_to_trap = $now->format('H:i:s'); + + try { + ob_start(); + $data = []; + + $user_groups = users_get_groups($config['id_user'], 'AR', false); + $prea = array_keys($user_groups); + $ids = join(',', $prea); + + $user_in_group_wo_agents = db_get_value_sql('select count(DISTINCT(id_usuario)) from tusuario_perfil where id_usuario ="'.$config['id_user'].'" and id_perfil = 1 and id_grupo in (select id_grupo from tgrupo where id_grupo in ('.$ids.') and id_grupo not in (select id_grupo from tagente))'); + if ($user_in_group_wo_agents == 0) { + $rows = db_get_all_rows_filter( + 'tagente', + ['id_grupo' => array_keys($user_groups)], + ['id_agente'] + ); + $id_agents = []; + foreach ($rows as $row) { + $id_agents[] = $row['id_agente']; + } + + if (!empty($id_agents)) { + $address_by_user_groups = agents_get_addresses($id_agents); + foreach ($address_by_user_groups as $i => $a) { + $address_by_user_groups[$i] = '"'.$a.'"'; + } + } + } else { + $rows = db_get_all_rows_filter( + 'tagente', + [], + ['id_agente'] + ); + $id_agents = []; + foreach ($rows as $row) { + $id_agents[] = $row['id_agente']; + } + + $all_address_agents = agents_get_addresses($id_agents); + foreach ($all_address_agents as $i => $a) { + $all_address_agents[$i] = '"'.$a.'"'; + } + } + + if (empty($address_by_user_groups)) { + $address_by_user_groups = []; + array_unshift($address_by_user_groups, '""'); + } + + if (empty($all_address_agents)) { + $all_address_agents = []; + array_unshift($all_address_agents, '""'); + } + + $sql = 'SELECT * FROM ttrap + WHERE ( + `source` IN ('.implode(',', $address_by_user_groups).") OR + `source`='' OR + `source` NOT IN (".implode(',', $all_address_agents).') + ) + %s + ORDER BY timestamp DESC + LIMIT %d,%d'; + + $whereSubquery = ''; + if ($filters['filter_alert'] != -1) { + $whereSubquery .= ' AND alerted = '.$filters['filter_alert']; + } + + if ($filters['filter_severity'] != -1) { + // There are two special severity values aimed to match two different trap standard severities + // in database: warning/critical and critical/normal. + if ($filters['filter_severity'] != EVENT_CRIT_OR_NORMAL + && $filters['filter_severity'] != EVENT_CRIT_WARNING_OR_CRITICAL + ) { + // Test if enterprise is installed to search oid in text or oid field in ttrap. + if ($config['enterprise_installed']) { + $whereSubquery .= ' AND ( + (alerted = 0 AND severity = '.$filters['filter_severity'].') OR + (alerted = 1 AND priority = '.$filters['filter_severity'].'))'; + } else { + $whereSubquery .= ' AND ( + (alerted = 0 AND 1 = '.$filters['filter_severity'].') OR + (alerted = 1 AND priority = '.$filters['filter_severity'].'))'; + } + } else if ($filters['filter_severity'] === EVENT_CRIT_WARNING_OR_CRITICAL) { + // Test if enterprise is installed to search oid in text or oid field in ttrap. + if ($config['enterprise_installed']) { + $whereSubquery .= ' AND ( + (alerted = 0 AND (severity = '.EVENT_CRIT_WARNING.' OR severity = '.EVENT_CRIT_CRITICAL.')) OR + (alerted = 1 AND (priority = '.EVENT_CRIT_WARNING.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; + } else { + $whereSubquery .= ' AND ( + (alerted = 1 AND (priority = '.EVENT_CRIT_WARNING.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; + } + } else if ($filters['filter_severity'] === EVENT_CRIT_OR_NORMAL) { + // Test if enterprise is installed to search oid in text or oid field in ttrap. + if ($config['enterprise_installed']) { + $whereSubquery .= ' AND ( + (alerted = 0 AND (severity = '.EVENT_CRIT_NORMAL.' OR severity = '.EVENT_CRIT_CRITICAL.')) OR + (alerted = 1 AND (priority = '.EVENT_CRIT_NORMAL.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; + } else { + $whereSubquery .= ' AND ( + (alerted = 1 AND (priority = '.EVENT_CRIT_NORMAL.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; + } + } + } + + if ($filters['filter_status'] != -1) { + $whereSubquery .= ' AND status = '.$filters['filter_status']; + } + + if ($date_from_trap != '') { + if ($time_from_trap != '') { + $whereSubquery .= ' + AND (UNIX_TIMESTAMP(timestamp) > UNIX_TIMESTAMP("'.$date_from_trap.' '.$time_from_trap.'")) + '; + } else { + $whereSubquery .= ' + AND (UNIX_TIMESTAMP(timestamp) > UNIX_TIMESTAMP("'.$date_from_trap.' 23:59:59")) + '; + } + } + + if ($date_to_trap != '') { + if ($time_to_trap) { + $whereSubquery .= ' + AND (UNIX_TIMESTAMP(timestamp) < UNIX_TIMESTAMP("'.$date_to_trap.' '.$time_to_trap.'")) + '; + } else { + $whereSubquery .= ' + AND (UNIX_TIMESTAMP(timestamp) < UNIX_TIMESTAMP("'.$date_to_trap.' 23:59:59")) + '; + } + } + + if ($filters['filter_trap_type'] == 5) { + $whereSubquery .= ' AND type NOT IN (0, 1, 2, 3, 4)'; + } else if ($filters['filter_trap_type'] != -1) { + $whereSubquery .= ' AND type = '.$filters['filter_trap_type']; + } + + if ($filters['filter_group_by']) { + $where_without_group = $whereSubquery; + $whereSubquery .= ' GROUP BY source,oid'; + } + + $sql = sprintf($sql, $whereSubquery, $start, $length); + $sql_count = 'SELECT COUNT(id_trap) FROM ttrap + WHERE ( + source IN ('.implode(',', $address_by_user_groups).") OR + source='' OR + source NOT IN (".implode(',', $all_address_agents).') + ) + %s'; + + $sql_count = sprintf($sql_count, $whereSubquery); + + $traps = db_get_all_rows_sql($sql, true); + $total = (int) db_get_value_sql($sql_count, false, true); + + if (empty($traps) === false) { + $data = $traps; + $data = array_reduce( + $data, + function ($carry, $item) use ($filters, $where_without_group) { + global $config; + // Transforms array of arrays $data into an array + // of objects, making a post-process of certain fields. + $tmp = (object) $item; + + $severity_class = get_priority_class($tmp->severity); + + $status = $tmp->status; + + // Status. + if ($status == 0) { + $tmp->status = html_print_image( + 'images/pixel_red.png', + true, + [ + 'title' => __('Not validated'), + 'width' => '20', + 'height' => '20', + ] + ); + } else { + $tmp->status = html_print_image( + 'images/pixel_green.png', + true, + [ + 'title' => __('Validated'), + 'width' => '20', + 'height' => '20', + ] + ); + } + + // SNMP Agent. + $agent = agents_get_agent_with_ip($tmp->source); + if ($agent === false) { + $tmp->snmp_agent .= ''.$tmp->source.''; + } else { + $tmp->snmp_agent .= ''; + } + + // Enterprise string. + if (empty($tmp->text) === false) { + $enterprise_string = $tmp->text; + } else if (empty($tmp->oid) === false) { + $enterprise_string = $tmp->oid; + } else { + $enterprise_string = __('N/A'); + } + + $tmp->enterprise_string = ''; + + // Count. + if ($filters['filter_group_by']) { + $sql = "SELECT count(*) FROM ttrap WHERE 1=1 + $where_without_group + AND oid='".$tmp->oid."' + AND source='".$tmp->source."'"; + $group_traps = db_get_value_sql($sql); + $tmp->count = '
'.$group_traps.'
'; + } + + // Trap subtype. + $tmp->trap_subtype = '
'; + if (empty($tmp->value) === true) { + $tmp->trap_subtype .= __('N/A'); + } else { + $tmp->trap_subtype .= ui_print_truncate_text($tmp->value, GENERIC_SIZE_TEXT, false); + } + + $tmp->trap_subtype .= '
'; + + // User ID. + $tmp->user_id = '
'; + if (empty($status) === false) { + $tmp->user_id .= ''.substr($tmp->id_usuario, 0, 8).''; + if (!empty($tmp->id_usuario)) { + $tmp->user_id .= ui_print_help_tip(get_user_fullname($tmp->id_usuario), true); + } + } else { + $tmp->user_id .= '--'; + } + + $tmp->user_id .= '
'; + + // Timestamp. + $timestamp = $tmp->timestamp; + $tmp->timestamp = '
'; + $tmp->timestamp .= ''; + $tmp->timestamp .= ui_print_timestamp($timestamp, true); + $tmp->timestamp .= '
'; + + // Use alert severity if fired. + if (empty($tmp->alerted) === false) { + $tmp->alert = html_print_image('images/pixel_yellow.png', true, ['width' => '20', 'height' => '20', 'border' => '0', 'title' => __('Alert fired')]); + } else { + $tmp->alert = html_print_image('images/pixel_gray.png', true, ['width' => '20', 'height' => '20', 'border' => '0', 'title' => __('Alert not fired')]); + } + + // Actions. + $tmp->action = ''; + if ($status != 1) { + $tmp->action .= ''.html_print_image( + 'images/ok.png', + true, + [ + 'border' => '0', + 'title' => __('Validate'), + 'onclick' => 'validate_trap(\''.$tmp->id_trap.'\')', + ] + ).' '; + } + + if ($tmp->source == '') { + if (\user_is_admin()) { + $tmp->action .= ''.html_print_image( + 'images/cross.png', + true, + [ + 'border' => '0', + 'title' => __('Delete'), + 'class' => 'invert_filter', + 'onclick' => 'delete_trap(\''.$tmp->id_trap.'\')', + ] + ).' '; + } + } else { + $tmp->action .= ''.html_print_image( + 'images/cross.png', + true, + [ + 'border' => '0', + 'title' => __('Delete'), + 'class' => 'invert_filter', + 'onclick' => 'delete_trap(\''.$tmp->id_trap.'\')', + ] + ).' '; + } + + $tmp->action .= ''.html_print_image( + 'images/eye.png', + true, + [ + 'alt' => __('Show more'), + 'title' => __('Show more'), + 'class' => 'invert_filter', + ] + ).''; + $tmp->action .= ''.html_print_image('images/edit.png', true, ['alt' => __('SNMP trap editor'), 'title' => __('SNMP trap editor')]).''; + + $tmp->m = html_print_checkbox_extended('snmptrapid[]', $tmp->id_trap, false, false, '', 'class="chk"', true); + + $carry[] = $tmp; + return $carry; + }, + ); + } + + if (empty($data) === true) { + $total = 0; + $data = []; + } + + echo json_encode( + [ + 'data' => $data, + 'recordsTotal' => $total, + 'recordsFiltered' => $total, + ] + ); + // Capture output. + $response = ob_get_clean(); + } catch (Exception $e) { + echo json_encode(['error' => $e->getMessage()]); + exit; + } + + // If not valid, show error with issue. + json_decode($response); + if (json_last_error() === JSON_ERROR_NONE) { + // If valid dump. + echo $response; + } else { + echo json_encode( + ['error' => $response] + ); + } + + exit; + } + + + /** + * Checks if target method is available to be called using AJAX. + * + * @param string $method Target method. + * + * @return boolean True allowed, false not. + */ + public function ajaxMethod(string $method) + { + return in_array($method, $this->AJAXMethods); + } + + + /** + * Delete snmp trap. + * + * @return void + */ + public function deleteTrap() + { + $id_trap = get_parameter('id', 0); + $group_by = (bool) get_parameter('group_by', 0); + + if ($id_trap > 0) { + if ($group_by === true) { + $sql_ids_traps = 'SELECT id_trap, source FROM ttrap WHERE oid IN (SELECT oid FROM ttrap WHERE id_trap = '.$id_trap.') + AND source IN (SELECT source FROM ttrap WHERE id_trap = '.$id_trap.')'; + $ids_traps = db_get_all_rows_sql($sql_ids_traps); + + foreach ($ids_traps as $key => $value) { + $result = db_process_sql_delete('ttrap', ['id_trap' => $value['id_trap']]); + enterprise_hook('snmp_update_forwarded_modules', [$value]); + } + } else { + $forward_info = db_get_row('ttrap', 'id_trap', $id_trap); + $result = db_process_sql_delete('ttrap', ['id_trap' => $id_trap]); + enterprise_hook('snmp_update_forwarded_modules', [$forward_info]); + } + } + } + + + /** + * Delete snmp traps. + * + * @return void + */ + public function deleteTraps() + { + $ids = get_parameter('ids', []); + $group_by = (bool) get_parameter('group_by', false); + + if (empty($ids) === false) { + $string_ids = implode(',', $ids); + if ($group_by === true) { + $sql_ids_traps = 'SELECT id_trap, source FROM ttrap WHERE oid IN (SELECT oid FROM ttrap WHERE id_trap IN ('.$string_ids.')) + AND source IN (SELECT source FROM ttrap WHERE id_trap IN ('.$string_ids.'))'; + $ids_traps = db_get_all_rows_sql($sql_ids_traps); + + $array = array_column($ids_traps, 'id_trap'); + + $delete = sprintf( + 'DELETE FROM `ttrap` WHERE id_trap IN (%s)', + implode(',', $array), + ); + db_process_sql($delete); + + foreach ($ids_traps as $key => $value) { + enterprise_hook('snmp_update_forwarded_modules', [$value]); + } + } else { + $delete = sprintf( + 'DELETE FROM `ttrap` WHERE id_trap IN (%s)', + $string_ids, + ); + db_process_sql($delete); + foreach ($ids as $id_trap) { + enterprise_hook('snmp_update_forwarded_modules', [$id_trap]); + } + } + } + } + + + /** + * Validate snmp trap. + * + * @return void + */ + public function validateTrap() + { + global $config; + + $id_trap = get_parameter('id', 0); + + $values = [ + 'status' => 1, + 'id_usuario' => $config['id_user'], + ]; + + $result = db_process_sql_update('ttrap', $values, ['id_trap' => $id_trap]); + enterprise_hook('snmp_update_forwarded_modules', [$id_trap]); + } + + + /** + * Validate snmp traps. + * + * @return void + */ + public function validateTraps() + { + global $config; + + $ids = get_parameter('ids', []); + + if (empty($ids) === false) { + $update = sprintf( + 'UPDATE ttrap SET `status` = 1, `id_usuario` = "%s" WHERE id_trap IN (%s)', + $config['id_user'], + implode(',', $ids) + ); + db_process_sql($update); + + foreach ($ids as $id_trap) { + enterprise_hook('snmp_update_forwarded_modules', [$id_trap]); + } + } + } + + + /** + * Load Javascript code. + * + * @return string. + */ + public function loadJS() + { + // Nothing for this moment. + ob_start(); + + // Javascript content. + ?> + + sub($interval); - -$date_from_trap = $ago->format('Y/m/d'); -$date_to_trap = $now->format('Y/m/d'); -$time_from_trap = $ago->format('H:i:s'); -$time_to_trap = $now->format('H:i:s'); - -$user_groups = users_get_groups($config['id_user'], $access, false); - -$str_user_groups = ''; -$i = 0; -foreach ($user_groups as $id => $name) { - if ($i == 0) { - $str_user_groups .= $id; +// Control call flow. +try { + // User access and validation is being processed on class constructor. + $controller = new SnmpConsole($ajaxPage); +} catch (Exception $e) { + if ((bool) is_ajax() === true) { + echo json_encode(['error' => '[SnmpConsole]'.$e->getMessage() ]); + exit; } else { - $str_user_groups .= ','.$id; - } - - $i++; -} - -$url = 'index.php?sec=estado&sec2=operation/snmpconsole/snmp_view'; -$url .= '&filter_severity='.$filter_severity.'&filter_fired='.$filter_fired; -$url .= '&free_search_string='.$free_search_string.'&pagination='.$pagination; -$url .= '&offset='.$offset.'&trap_type='.$trap_type.'&group_by='.$group_by; -$url .= '&hours_ago='.$hours_ago.'&pure='.$pure; - -$statistics['text'] = ''.html_print_image( - 'images/op_reporting.png', - true, - [ - 'title' => __('Statistics'), - 'class' => 'invert_filter', - ] -).''; -$list['text'] = ''.html_print_image( - 'images/op_snmp.png', - true, - [ - 'title' => __('List'), - 'class' => 'invert_filter', - ] -).''; -$list['active'] = true; - -if ($config['pure']) { - $fullscreen['text'] = ''.html_print_image( - 'images/normal_screen.png', - true, - [ - 'title' => __('Normal screen'), - 'class' => 'invert_filter', - ] - ).''; -} else { - // Fullscreen. - $fullscreen['text'] = ''.html_print_image( - 'images/full_screen.png', - true, - [ - 'title' => __('Full screen'), - 'class' => 'invert_filter', - ] - ).''; -} - - -// OPERATIONS -// Delete SNMP Trap entry Event. -if (isset($_GET['delete'])) { - $id_trap = (int) get_parameter_get('delete', 0); - if ($id_trap > 0) { - if ($group_by) { - $sql_ids_traps = 'SELECT id_trap, source FROM ttrap WHERE oid IN (SELECT oid FROM ttrap WHERE id_trap = '.$id_trap.') - AND source IN (SELECT source FROM ttrap WHERE id_trap = '.$id_trap.')'; - $ids_traps = db_get_all_rows_sql($sql_ids_traps); - - foreach ($ids_traps as $key => $value) { - $result = db_process_sql_delete('ttrap', ['id_trap' => $value['id_trap']]); - enterprise_hook('snmp_update_forwarded_modules', [$value]); - } - } else { - $forward_info = db_get_row('ttrap', 'id_trap', $id_trap); - $result = db_process_sql_delete('ttrap', ['id_trap' => $id_trap]); - enterprise_hook('snmp_update_forwarded_modules', [$forward_info]); - ui_print_result_message( - $result, - __('Successfully deleted'), - __('Could not be deleted') - ); - } - } -} - -// Check Event. -if (isset($_GET['check'])) { - $id_trap = (int) get_parameter_get('check', 0); - $values = [ - 'status' => 1, - 'id_usuario' => $config['id_user'], - ]; - $result = db_process_sql_update('ttrap', $values, ['id_trap' => $id_trap]); - enterprise_hook('snmp_update_forwarded_modules', [$id_trap]); - - ui_print_result_message( - $result, - __('Successfully updated'), - __('Could not be updated') - ); -} - -// Mass-process DELETE. -if (isset($_POST['deletebt'])) { - $trap_ids = get_parameter_post('snmptrapid', []); - if (is_array($trap_ids)) { - if ($group_by) { - foreach ($trap_ids as $key => $value) { - $sql_ids_traps = 'SELECT id_trap, source FROM ttrap WHERE oid IN (SELECT oid FROM ttrap WHERE id_trap = '.$value.') - AND source IN (SELECT source FROM ttrap WHERE id_trap = '.$value.')'; - $ids_traps = db_get_all_rows_sql($sql_ids_traps); - - foreach ($ids_traps as $key2 => $value2) { - $result = db_process_sql_delete('ttrap', ['id_trap' => $value2['id_trap']]); - enterprise_hook('snmp_update_forwarded_modules', [$value2]); - } - } - } else { - foreach ($trap_ids as $id_trap) { - $forward_info = db_get_row('ttrap', 'id_trap', $id_trap); - db_process_sql_delete('ttrap', ['id_trap' => $id_trap]); - enterprise_hook('snmp_update_forwarded_modules', [$forward_info]); - } - } - } -} - -// Mass-process UPDATE. -if (isset($_POST['updatebt'])) { - $trap_ids = get_parameter_post('snmptrapid', []); - if (is_array($trap_ids)) { - foreach ($trap_ids as $id_trap) { - $sql = sprintf("UPDATE ttrap SET status = 1, id_usuario = '%s' WHERE id_trap = %d", $config['id_user'], $id_trap); - db_process_sql($sql); - enterprise_hook('snmp_update_forwarded_modules', [$id_trap]); - } - } -} - -// All traps. -$all_traps = db_get_all_rows_sql('SELECT DISTINCT source FROM ttrap'); - -if (empty($all_traps)) { - $all_traps = []; -} - -// Set filters. -$agents = []; -$oids = []; -$severities = get_priorities(); -$alerted = [ - __('Not fired'), - __('Fired'), -]; -foreach ($all_traps as $trap) { - $agent = agents_get_agent_with_ip($trap['source']); - $agents[$trap['source']] = $agent !== false ? ($agent['alias'] ? $agent['alias'] : $agent['nombre']) : $trap['source']; - $oid = enterprise_hook('get_oid', [$trap]); - if ($oid === ENTERPRISE_NOT_HOOK) { - $oid = $trap['oid']; - } - - $oids[$oid] = $oid; -} - -$prea = array_keys($user_groups); -$ids = join(',', $prea); -// Cuantos usuarios hay operadores con un grupo que exista y no lo tenga ningun usuario. -$user_in_group_wo_agents = db_get_value_sql('select count(DISTINCT(id_usuario)) from tusuario_perfil where id_usuario ="'.$config['id_user'].'" and id_perfil = 1 and id_grupo in (select id_grupo from tgrupo where id_grupo in ('.$ids.') and id_grupo not in (select id_grupo from tagente))'); - -switch ($config['dbtype']) { - case 'mysql': - case 'postgresql': - if ($user_in_group_wo_agents == 0) { - $rows = db_get_all_rows_filter( - 'tagente', - ['id_grupo' => array_keys($user_groups)], - ['id_agente'] - ); - $id_agents = []; - foreach ($rows as $row) { - $id_agents[] = $row['id_agente']; - } - - if (!empty($id_agents)) { - $address_by_user_groups = agents_get_addresses($id_agents); - foreach ($address_by_user_groups as $i => $a) { - $address_by_user_groups[$i] = '"'.$a.'"'; - } - } - } else { - $rows = db_get_all_rows_filter( - 'tagente', - [], - ['id_agente'] - ); - $id_agents = []; - foreach ($rows as $row) { - $id_agents[] = $row['id_agente']; - } - - $all_address_agents = agents_get_addresses($id_agents); - foreach ($all_address_agents as $i => $a) { - $all_address_agents[$i] = '"'.$a.'"'; - } - } - break; - - default: - // Default. - break; -} - -if (empty($address_by_user_groups)) { - $address_by_user_groups = []; - array_unshift($address_by_user_groups, '""'); -} - -if (empty($all_address_agents)) { - $all_address_agents = []; - array_unshift($all_address_agents, '""'); -} - - -// Make query to extract traps of DB. -switch ($config['dbtype']) { - case 'mysql': - $sql = 'SELECT * - FROM ttrap - WHERE ( - `source` IN ('.implode(',', $address_by_user_groups).") OR - `source`='' OR - `source` NOT IN (".implode(',', $all_address_agents).') - ) - %s - ORDER BY timestamp DESC - LIMIT %d,%d'; - break; - - case 'postgresql': - $sql = 'SELECT * - FROM ttrap - WHERE ( - source IN ('.implode(',', $address_by_user_groups).") OR - source='' OR - source NOT IN (".implode(',', $all_address_agents).') - ) - %s - ORDER BY timestamp DESC - LIMIT %d OFFSET %d'; - break; - - case 'oracle': - $sql = "SELECT * - FROM ttrap - WHERE (source IN ( - SELECT direccion FROM tagente - WHERE id_grupo IN ($str_user_groups) - ) OR source='' OR source NOT IN (SELECT direccion FROM tagente WHERE direccion IS NOT NULL)) %s - ORDER BY timestamp DESC"; - break; - - default: - // Default. - break; -} - -switch ($config['dbtype']) { - case 'mysql': - case 'postgresql': - $sql_all = 'SELECT * - FROM ttrap - WHERE ( - source IN ('.implode(',', $address_by_user_groups).") OR - source='' OR - source NOT IN (".implode(',', $all_address_agents).') - ) - %s - ORDER BY timestamp DESC'; - $sql_count = 'SELECT COUNT(id_trap) - FROM ttrap - WHERE ( - source IN ('.implode(',', $address_by_user_groups).") OR - source='' OR - source NOT IN (".implode(',', $all_address_agents).') - ) - %s'; - break; - - case 'oracle': - $sql_all = "SELECT * - FROM ttrap - WHERE (source IN ( - SELECT direccion FROM tagente - WHERE id_grupo IN ($str_user_groups) - ) OR source='' OR source NOT IN (SELECT direccion FROM tagente WHERE direccion IS NOT NULL)) - %s - ORDER BY timestamp DESC"; - $sql_count = "SELECT COUNT(id_trap) - FROM ttrap - WHERE ( - source IN ( - SELECT direccion FROM tagente - WHERE id_grupo IN ($str_user_groups) - ) OR source='' OR source NOT IN (SELECT direccion FROM tagente WHERE direccion IS NOT NULL)) - %s"; - break; - - default: - // Default. - break; -} - -// $whereSubquery = 'WHERE 1=1'; -$whereSubquery = ''; - -if ($filter_fired != -1) { - $whereSubquery .= ' AND alerted = '.$filter_fired; -} - -if ($free_search_string != '') { - switch ($config['dbtype']) { - case 'mysql': - $whereSubquery .= ' - AND (source LIKE "%'.$free_search_string.'%" OR - oid LIKE "%'.$free_search_string.'%" OR - oid_custom LIKE "%'.$free_search_string.'%" OR - type_custom LIKE "%'.$free_search_string.'%" OR - value LIKE "%'.$free_search_string.'%" OR - value_custom LIKE "%'.$free_search_string.'%" OR - id_usuario LIKE "%'.$free_search_string.'%" OR - text LIKE "%'.$free_search_string.'%" OR - description LIKE "%'.$free_search_string.'%")'; - break; - - case 'postgresql': - case 'oracle': - $whereSubquery .= ' - AND (source LIKE \'%'.$free_search_string.'%\' OR - oid LIKE \'%'.$free_search_string.'%\' OR - oid_custom LIKE \'%'.$free_search_string.'%\' OR - type_custom LIKE \'%'.$free_search_string.'%\' OR - value LIKE \'%'.$free_search_string.'%\' OR - value_custom LIKE \'%'.$free_search_string.'%\' OR - id_usuario LIKE \'%'.$free_search_string.'%\' OR - text LIKE \'%'.$free_search_string.'%\' OR - description LIKE \'%'.$free_search_string.'%\')'; - break; - - default: - // Default. - break; - } -} - -if ($date_from_trap != '') { - if ($time_from_trap != '') { - $whereSubquery .= ' - AND (UNIX_TIMESTAMP(timestamp) > UNIX_TIMESTAMP("'.$date_from_trap.' '.$time_from_trap.'")) - '; - } else { - $whereSubquery .= ' - AND (UNIX_TIMESTAMP(timestamp) > UNIX_TIMESTAMP("'.$date_from_trap.' 23:59:59")) - '; - } -} - -if ($date_to_trap != '') { - if ($time_to_trap) { - $whereSubquery .= ' - AND (UNIX_TIMESTAMP(timestamp) < UNIX_TIMESTAMP("'.$date_to_trap.' '.$time_to_trap.'")) - '; - } else { - $whereSubquery .= ' - AND (UNIX_TIMESTAMP(timestamp) < UNIX_TIMESTAMP("'.$date_to_trap.' 23:59:59")) - '; - } -} - -if ($filter_severity != -1) { - // There are two special severity values aimed to match two different trap standard severities in database: warning/critical and critical/normal. - if ($filter_severity != EVENT_CRIT_OR_NORMAL && $filter_severity != EVENT_CRIT_WARNING_OR_CRITICAL) { - // Test if enterprise is installed to search oid in text or oid field in ttrap. - if ($config['enterprise_installed']) { - $whereSubquery .= ' AND ( - (alerted = 0 AND severity = '.$filter_severity.') OR - (alerted = 1 AND priority = '.$filter_severity.'))'; - } else { - $whereSubquery .= ' AND ( - (alerted = 0 AND 1 = '.$filter_severity.') OR - (alerted = 1 AND priority = '.$filter_severity.'))'; - } - } else if ($filter_severity === EVENT_CRIT_WARNING_OR_CRITICAL) { - // Test if enterprise is installed to search oid in text or oid field in ttrap. - if ($config['enterprise_installed']) { - $whereSubquery .= ' AND ( - (alerted = 0 AND (severity = '.EVENT_CRIT_WARNING.' OR severity = '.EVENT_CRIT_CRITICAL.')) OR - (alerted = 1 AND (priority = '.EVENT_CRIT_WARNING.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; - } else { - $whereSubquery .= ' AND ( - (alerted = 1 AND (priority = '.EVENT_CRIT_WARNING.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; - } - } else if ($filter_severity === EVENT_CRIT_OR_NORMAL) { - // Test if enterprise is installed to search oid in text or oid field in ttrap. - if ($config['enterprise_installed']) { - $whereSubquery .= ' AND ( - (alerted = 0 AND (severity = '.EVENT_CRIT_NORMAL.' OR severity = '.EVENT_CRIT_CRITICAL.')) OR - (alerted = 1 AND (priority = '.EVENT_CRIT_NORMAL.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; - } else { - $whereSubquery .= ' AND ( - (alerted = 1 AND (priority = '.EVENT_CRIT_NORMAL.' OR priority = '.EVENT_CRIT_CRITICAL.')))'; - } - } -} - -if ($filter_status != -1) { - $whereSubquery .= ' AND status = '.$filter_status; -} - -if ($trap_type == 5) { - $whereSubquery .= ' AND type NOT IN (0, 1, 2, 3, 4)'; -} else if ($trap_type != -1) { - $whereSubquery .= ' AND type = '.$trap_type; -} - -// Disable this feature (time will decide if temporarily) in Oracle cause the group by is very confictive. -if ($group_by && $config['dbtype'] != 'oracle') { - $where_without_group = $whereSubquery; - $whereSubquery .= ' GROUP BY source,oid'; -} - -switch ($config['dbtype']) { - case 'mysql': - $sql = sprintf($sql, $whereSubquery, $offset, $pagination); - break; - - case 'postgresql': - $sql = sprintf($sql, $whereSubquery, $pagination, $offset); - break; - - case 'oracle': - $set = []; - $set['limit'] = $pagination; - $set['offset'] = $offset; - $sql = sprintf($sql, $whereSubquery); - $sql = oracle_recode_query($sql, $set); - break; - - default: - // Default. - break; -} - -$sql_all = sprintf($sql_all, $whereSubquery); -$sql_count = sprintf($sql_count, $whereSubquery); - -$table = new stdClass(); -$table->width = '100%'; -$table->cellpadding = 0; -$table->cellspacing = 0; -$table->class = 'databox filters'; -$table->size = []; -$table->size[0] = '120px'; -$table->data = []; - -// Alert status select. -$table->data[1][0] = ''.__('Alert').''; -$table->data[1][1] = html_print_select( - $alerted, - 'filter_fired', - $filter_fired, - '', - __('All'), - '-1', - true -); - -// Block size for pagination select. -$table->data[2][0] = ''.__('Block size for pagination').''; -$paginations[25] = 25; -$paginations[50] = 50; -$paginations[100] = 100; -$paginations[200] = 200; -$paginations[500] = 500; -$table->data[2][1] = html_print_select( - $paginations, - 'pagination', - $pagination, - '', - __('Default'), - $config['block_size'], - true -); - -// Severity select. -$table->data[1][2] = ''.__('Severity').''; -$table->data[1][3] = html_print_select( - $severities, - 'filter_severity', - $filter_severity, - '', - __('All'), - -1, - true -); - -// Status. -$table->data[3][0] = ''.__('Status').''; - -$status_array[-1] = __('All'); -$status_array[0] = __('Not validated'); -$status_array[1] = __('Validated'); -$table->data[3][1] = html_print_select( - $status_array, - 'filter_status', - $filter_status, - '', - '', - '', - true -); - -// Free search (search by all alphanumeric fields). -$table->data[2][3] = ''.__('Free search').''.ui_print_help_tip( - __( - 'Search by any alphanumeric field in the trap. - REMEMBER trap sources need to be searched by IP Address' - ), - true -); -$table->data[2][4] = html_print_input_text( - 'free_search_string', - $free_search_string, - '', - 40, - 0, - true -); - -$table->data[4][0] = ''.__('Max. hours old').''; -$table->data[4][1] = html_print_input( - [ - 'type' => 'number', - 'name' => 'hours_ago', - 'value' => $hours_ago, - 'step' => 1, - 'return' => true, - ] -); - -// Type filter (ColdStart, WarmStart, LinkDown, LinkUp, authenticationFailure, Other). -$table->data[4][3] = ''.__('Trap type').''.ui_print_help_tip(__('Search by trap type'), true); -$trap_types = [ - -1 => __('None'), - 0 => __('Cold start (0)'), - 1 => __('Warm start (1)'), - 2 => __('Link down (2)'), - 3 => __('Link up (3)'), - 4 => __('Authentication failure (4)'), - 5 => __('Other'), -]; -$table->data[4][4] = html_print_select( - $trap_types, - 'trap_type', - $trap_type, - '', - '', - '', - true, - false, - false -); - -// Disable this feature (time will decide if temporarily) in Oracle cause the group by is very confictive. -if ($config['dbtype'] != 'oracle') { - $table->data[3][3] = ''.__('Group by Enterprise String/IP').''; - $table->data[3][4] = __('Yes').' '.html_print_radio_button('group_by', 1, '', $group_by, true).'  '; - $table->data[3][4] .= __('No').' '.html_print_radio_button('group_by', 0, '', $group_by, true); -} - -$filter = '
'; -$filter .= html_print_table($table, true); -$filter .= '
'; -$filter .= html_print_submit_button(__('Update'), 'search', false, 'class="sub upd"', true); -$filter .= '
'; -$filter .= '
'; - -$filter_resume = []; -$filter_resume['filter_fired'] = $alerted[$filter_fired]; -$filter_resume['filter_severity'] = $severities[$filter_severity]; -$filter_resume['pagination'] = $paginations[$pagination]; -$filter_resume['free_search_string'] = $free_search_string; -$filter_resume['filter_status'] = $status_array[$filter_status]; -$filter_resume['group_by'] = $group_by; -$filter_resume['hours_ago'] = $hours_ago; -$filter_resume['trap_type'] = $trap_types[$trap_type]; - -$traps = db_get_all_rows_sql($sql, true); -$trapcount = (int) db_get_value_sql($sql_count, false, true); - -// Re-sort traps by timestamp if history db is enabled. -if ($config['history_db_enabled'] == 1) { - usort( - $traps, - function ($a, $b) { - return strtotime($a['timestamp']) < strtotime($b['timestamp']); - } - ); -} - -// No traps. -if (empty($traps)) { - // Header - ui_print_standard_header( - __('SNMP Console'), - 'images/op_snmp.png', - false, - 'snmp_console', - false, - [ - $list, - $statistics, - ], - [ - [ - 'link' => '', - 'label' => __('Monitoring'), - ], - [ - 'link' => '', - 'label' => __('SNMP'), - ], - ] - ); - - $sql2 = 'SELECT * - FROM ttrap - WHERE ( - `source` IN ('.implode(',', $address_by_user_groups).") OR - `source`='' OR - `source` NOT IN (".implode(',', $all_address_agents).') - ) - AND status = 0 - ORDER BY timestamp DESC'; - $traps2 = db_get_all_rows_sql($sql2); - - if (!empty($traps2)) { - ui_toggle($filter, __('Toggle filter(s)')); - - print_snmp_tags_active_filters($filter_resume); - - ui_print_info_message(['no_close' => true, 'message' => __('There are no SNMP traps in database that contains this filter') ]); - } else { - ui_print_info_message(['no_close' => true, 'message' => __('There are no SNMP traps in database') ]); + echo '[SnmpConsole]'.$e->getMessage(); } + // Stop this execution, but continue 'globally'. return; -} else { - if ($config['pure']) { - echo '
'; +} - echo ''; - - echo '
'; - - ui_require_css_file('pandora_enterprise', ENTERPRISE_DIR.'/include/styles/'); - ui_require_css_file('pandora_dashboard', ENTERPRISE_DIR.'/include/styles/'); - ui_require_css_file('cluetip', 'include/styles/js/'); - - ui_require_jquery_file('countdown'); - ui_require_javascript_file('pandora_dashboard', ENTERPRISE_DIR.'/include/javascript/'); - ui_require_javascript_file('wz_jsgraphics'); - ui_require_javascript_file('pandora_visual_console'); + if (method_exists($controller, $method) === true) { + if ($controller->ajaxMethod($method) === true) { + $controller->{$method}(); + } else { + $controller->error('Unavailable method.'); + } } else { - // Header - ui_print_standard_header( - __('SNMP Console'), - 'images/op_snmp.png', - false, - '', - false, - [ - $fullscreen, - $list, - $statistics, - ], - [ - [ - 'link' => '', - 'label' => __('Monitoring'), - ], - [ - 'link' => '', - 'label' => __('SNMP'), - ], - ] - ); + $controller->error('Method not found. ['.$method.']'); } -} -ui_toggle($filter, __('Toggle filter(s)')); -unset($table); - -print_snmp_tags_active_filters($filter_resume); - -if (($config['dbtype'] == 'oracle') && ($traps !== false)) { - $traps_size = count($traps); - for ($i = 0; $i < $traps_size; $i++) { - unset($traps[$i]['rnum']); - } -} - -$url_snmp = 'index.php?sec=snmpconsole&sec2=operation/snmpconsole/snmp_view'; -$url_snmp .= '&filter_severity='.$filter_severity.'&filter_fired='.$filter_fired; -$url_snmp .= '&filter_status='.$filter_status.'&refresh='.((int) get_parameter('refresh', 0)); -$url_snmp .= '&pure='.$config['pure'].'&trap_type='.$trap_type; -$url_snmp .= '&group_by='.$group_by.'&free_search_string='.$free_search_string; -$url_snmp .= '&hours_ago='.$hours_ago; - -$urlPagination = $url_snmp.'&pagination='.$pagination.'&offset='.$offset; - -ui_pagination($trapcount, $urlPagination, $offset, $pagination); - -echo '
'; - -$table = new StdClass(); -$table->cellpadding = 0; -$table->cellspacing = 0; -$table->width = '100%'; -$table->class = 'databox data'; -$table->head = []; -$table->size = []; -$table->data = []; -$table->align = []; -$table->headstyle = []; - -$table->head[0] = __('Status'); -$table->align[0] = 'center'; -$table->size[0] = '5%'; -$table->headstyle[0] = 'text-align: center'; - -$table->head[1] = __('SNMP Agent'); -$table->align[1] = 'center'; -$table->size[1] = '15%'; -$table->headstyle[1] = 'text-align: center'; - -$table->head[2] = __('Enterprise String'); -$table->align[2] = 'center'; -$table->size[2] = '18%'; -$table->headstyle[2] = 'text-align: center'; - -if ($group_by) { - $table->head[3] = __('Count'); - $table->align[3] = 'center'; - $table->size[3] = '5%'; - $table->headstyle[3] = 'text-align: center'; -} - -$table->head[4] = __('Trap subtype'); -$table->align[4] = 'center'; -$table->size[4] = '10%'; -$table->headstyle[4] = 'text-align: center'; - -$table->head[5] = __('User ID'); -$table->align[5] = 'center'; -$table->size[5] = '10%'; -$table->headstyle[5] = 'text-align: center'; - -$table->head[6] = __('Timestamp'); -$table->align[6] = 'center'; -$table->size[6] = '10%'; -$table->headstyle[6] = 'text-align: center'; - -$table->head[7] = __('Alert'); -$table->align[7] = 'center'; -$table->size[7] = '5%'; -$table->headstyle[7] = 'text-align: center'; - -$table->head[8] = __('Action'); -$table->align[8] = 'center'; -$table->size[8] = '10%'; -$table->headstyle[8] = 'min-width: 125px;text-align: center'; - -$table->head[9] = html_print_checkbox_extended( - 'allbox', - 1, - false, - false, - 'javascript:CheckAll();', - 'class="chk" title="'.__('All').'"', - true -); -$table->align[9] = 'center'; -$table->size[9] = '5%'; -$table->headstyle[9] = 'text-align: center'; - -$table->style[8] = 'background: #F3F3F3; color: #111 !important;'; - -// Skip offset records. -$idx = 0; -if ($traps !== false) { - foreach ($traps as $trap) { - $data = []; - if (empty($trap['description'])) { - $trap['description'] = ''; - } - - $severity = enterprise_hook('get_severity', [$trap]); - if ($severity === ENTERPRISE_NOT_HOOK) { - $severity = $trap['alerted'] == 1 ? $trap['priority'] : 1; - } - - // Status. - if ($trap['status'] == 0) { - $data[0] = html_print_image( - 'images/pixel_red.png', - true, - [ - 'title' => __('Not validated'), - 'width' => '20', - 'height' => '20', - ] - ); - } else { - $data[0] = html_print_image( - 'images/pixel_green.png', - true, - [ - 'title' => __('Validated'), - 'width' => '20', - 'height' => '20', - ] - ); - } - - // Agent matching source address. - $table->cellclass[$idx][1] = get_priority_class($severity); - $agent = agents_get_agent_with_ip($trap['source']); - if ($agent === false) { - if (! check_acl($config['id_user'], 0, 'AR')) { - continue; - } - - $data[1] = ''.$trap['source'].''; - } else { - if (! check_acl($config['id_user'], $agent['id_grupo'], 'AR')) { - continue; - } - - $data[1] = ''; - $data[1] .= ''.$agent['alias'].ui_print_help_tip($trap['source'], true, 'images/tip-blanco.png'); - ''; - } - - // OID. - $table->cellclass[$idx][2] = get_priority_class($severity); - if (! empty($trap['text'])) { - $enterprise_string = $trap['text']; - } else if (! empty($trap['oid'])) { - $enterprise_string = $trap['oid']; - } else { - $enterprise_string = __('N/A'); - } - - $data[2] = ''.$enterprise_string.''; - - // Count. - if ($group_by) { - $sql = "SELECT * FROM ttrap WHERE 1=1 - $where_without_group - AND oid='".$trap['oid']."' - AND source='".$trap['source']."'"; - $group_traps = db_get_all_rows_sql($sql); - $count_group_traps = count($group_traps); - $table->cellclass[$idx][3] = get_priority_class($severity); - $data[3] = ''.$count_group_traps.''; - } - - // Value. - $table->cellclass[$idx][4] = get_priority_class($severity); - if (empty($trap['value'])) { - $data[4] = __('N/A'); - } else { - $data[4] = ui_print_truncate_text($trap['value'], GENERIC_SIZE_TEXT, false); - } - - // User. - $table->cellclass[$idx][5] = get_priority_class($severity); - if (!empty($trap['status'])) { - $data[5] = ''.substr($trap['id_usuario'], 0, 8).''; - if (!empty($trap['id_usuario'])) { - $data[5] .= ui_print_help_tip(get_user_fullname($trap['id_usuario']), true); - } - } else { - $data[5] = '--'; - } - - // Timestamp. - $table->cellclass[$idx][6] = get_priority_class($severity); - $data[6] = ''; - $data[6] .= ui_print_timestamp($trap['timestamp'], true); - $data[6] .= ''; - - // Use alert severity if fired. - if (!empty($trap['alerted'])) { - $data[7] = html_print_image('images/pixel_yellow.png', true, ['width' => '20', 'height' => '20', 'border' => '0', 'title' => __('Alert fired')]); - } else { - $data[7] = html_print_image('images/pixel_gray.png', true, ['width' => '20', 'height' => '20', 'border' => '0', 'title' => __('Alert not fired')]); - } - - // Actions. - $data[8] = ''; - - if (empty($trap['status'])) { - $data[8] .= ''.html_print_image('images/ok.png', true, ['border' => '0', 'title' => __('Validate')]).' '; - } - - if ($trap['source'] == '') { - $is_admin = db_get_value('is_admin', 'tusuario', 'id_user', $config['id_user']); - if ($is_admin) { - $data[8] .= ''.html_print_image( - 'images/cross.png', - true, - [ - 'border' => '0', - 'title' => __('Delete'), - 'class' => 'invert_filter', - ] - ).' '; - } - } else { - $agent_trap_group = db_get_value('id_grupo', 'tagente', 'nombre', $trap['source']); - - $data[8] .= ''.html_print_image( - 'images/cross.png', - true, - [ - 'border' => '0', - 'title' => __('Delete'), - 'class' => 'invert_filter', - ] - ).' '; - } - - $data[8] .= ''.html_print_image( - 'images/eye.png', - true, - [ - 'alt' => __('Show more'), - 'title' => __('Show more'), - 'class' => 'invert_filter', - ] - ).''; - $data[8] .= enterprise_hook('editor_link', [$trap]); - - - $data[9] = html_print_checkbox_extended('snmptrapid[]', $trap['id_trap'], false, false, '', 'class="chk"', true); - - array_push($table->data, $data); - - // Hiden file for description. - $string = ' - - - - - - - - '; - - if ($trap['description'] != '') { - $string .= ' - - - '; - } - - if ($trap['type'] != '') { - $trap_types = [ - -1 => __('None'), - 0 => __('Cold start (0)'), - 1 => __('Warm start (1)'), - 2 => __('Link down (2)'), - 3 => __('Link up (3)'), - 4 => __('Authentication failure (4)'), - 5 => __('Other'), - ]; - - switch ($trap['type']) { - case -1: - $desc_trap_type = __('None'); - break; - - case 0: - $desc_trap_type = __('Cold start (0)'); - break; - - case 1: - $desc_trap_type = __('Warm start (1)'); - break; - - case 2: - $desc_trap_type = __('Link down (2)'); - break; - - case 3: - $desc_trap_type = __('Link up (3)'); - break; - - case 4: - $desc_trap_type = __('Authentication failure (4)'); - break; - - default: - $desc_trap_type = __('Other'); - break; - } - - $string .= ''; - } - - if ($group_by) { - $sql = "SELECT * FROM ttrap WHERE 1=1 - $where_without_group - AND oid='".$trap['oid']."' - AND source='".$trap['source']."'"; - $group_traps = db_get_all_rows_sql($sql); - $count_group_traps = count($group_traps); - - $sql = "SELECT timestamp FROM ttrap WHERE 1=1 - $where_without_group - AND oid='".$trap['oid']."' - AND source='".$trap['source']."' - ORDER BY `timestamp` DESC"; - $last_trap = db_get_value_sql($sql); - - $sql = "SELECT timestamp FROM ttrap WHERE 1=1 - $where_without_group - AND oid='".$trap['oid']."' - AND source='".$trap['source']."' - ORDER BY `timestamp` ASC"; - $first_trap = db_get_value_sql($sql); - - $string .= ' - - - '; - $string .= ' - - - '; - $string .= ' - - - '; - } - - $string .= '
'.''.__('Variable bindings:').''; - - if ($group_by) { - $new_url = 'index.php?sec=snmpconsole&sec2=operation/snmpconsole/snmp_view'; - $new_url .= '&filter_severity='.$filter_severity; - $new_url .= '&filter_fired='.$filter_fired; - $new_url .= '&filter_status='.$filter_status; - $new_url .= '&refresh='.((int) get_parameter('refresh', 0)); - $new_url .= '&pure='.$config['pure']; - $new_url .= '&group_by=0&free_search_string='.$free_search_string; - $new_url .= '&hours_ago='.$hours_ago; - - $string .= ''.__('See more details').''; - } else { - // Print binding vars separately. - $binding_vars = explode("\t", $trap['oid_custom']); - foreach ($binding_vars as $var) { - $string .= $var.'
'; - } - } - - $string .= '
'.''.__('Enterprise String:').' '.$trap['oid'].'
'.''.__('Description:').''.$trap['description'].'
'.__('Trap type:').''.$desc_trap_type.'
'.''.__('Count:').''.$count_group_traps.'
'.''.__('First trap:').''.$first_trap.'
'.''.__('Last trap:').''.$last_trap.'
'; - - $data = [$string]; - // $data = array($trap['description']); - $idx++; - $table->rowclass[$idx] = 'trap_info_'.$trap['id_trap']; - $table->colspan[$idx][0] = 10; - $table->rowstyle[$idx] = 'display: none;'; - array_push($table->data, $data); - - $idx++; - } -} - -// No matching traps. -if ($idx == 0) { - echo '
'.__('No matching traps found').'
'; + // Stop any execution. + exit; } else { - html_print_table($table); + // Run. + $controller->run(); } - -unset($table); - -echo '
'; - -html_print_submit_button(__('Validate'), 'updatebt', false, 'class="sub ok"'); - -echo ' '; -html_print_submit_button(__('Delete'), 'deletebt', false, 'class="sub delete" onClick="javascript:return confirm(\''.__('Are you sure?').'\')"'); - -echo '
'; - - -echo '
'; -echo '

'.__('Status').'

'; -echo html_print_image( - 'images/pixel_green.png', - true, - [ - 'width' => '20', - 'height' => '20', - ] -).' - '.__('Validated'); -echo '
'; -echo html_print_image( - 'images/pixel_red.png', - true, - [ - 'width' => '20', - 'height' => '20', - ] -).' - '.__('Not validated'); -echo '
'; -echo '
'; -echo '

'.__('Alert').'

'; -echo html_print_image( - 'images/pixel_yellow.png', - true, - [ - 'width' => '20', - 'height' => '20', - ] -).' - '.__('Fired'); -echo '
'; -echo html_print_image( - 'images/pixel_gray.png', - true, - [ - 'width' => '20', - 'height' => '20', - ] -).' - '.__('Not fired'); -echo '
'; -echo '
'; -echo '

'.__('Action').'

'; -echo html_print_image('images/ok.png', true).' - '.__('Validate'); -echo '
'; -echo html_print_image('images/cross.png', true, ['class' => 'invert_filter']).' - '.__('Delete'); -echo '
'; -echo '
'; -echo '

'.__('Legend').'

'; -foreach (get_priorities() as $num => $name) { - echo ''.$name.''; - echo '
'; -} - -echo '
'; -echo '
 
'; - -ui_include_time_picker(); -?> - - \ No newline at end of file From 5e510e7e12770a677aac8de9209f3ea0dc20bb84 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Wed, 16 Nov 2022 10:28:50 +0100 Subject: [PATCH 041/251] implemented custom field --- pandora_console/extras/mr/60.sql | 7 ++ .../godmode/agentes/agent_manager.php | 8 +++ .../godmode/agentes/configure_field.php | 70 ++++++++++++++++++- .../godmode/agentes/fields_manager.php | 24 ++++++- pandora_console/pandoradb.sql | 3 + pandora_console/pandoradb_data.sql | 2 +- 6 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 pandora_console/extras/mr/60.sql diff --git a/pandora_console/extras/mr/60.sql b/pandora_console/extras/mr/60.sql new file mode 100644 index 0000000000..40a0a86c4f --- /dev/null +++ b/pandora_console/extras/mr/60.sql @@ -0,0 +1,7 @@ +START TRANSACTION; + +ALTER TABLE `tagent_custom_fields` ADD `is_link_enabled` TINYINT(1) NOT NULL DEFAULT 0; +ALTER TABLE `tagent_custom_fields` ADD COLUMN `link_text` VARCHAR(500) NOT NULL DEFAULT ''; +ALTER TABLE `tagent_custom_fields` ADD COLUMN `link_url` VARCHAR(2048) NOT NULL DEFAULT ''; + +COMMIT; diff --git a/pandora_console/godmode/agentes/agent_manager.php b/pandora_console/godmode/agentes/agent_manager.php index 676a4db993..e5e37e63ea 100644 --- a/pandora_console/godmode/agentes/agent_manager.php +++ b/pandora_console/godmode/agentes/agent_manager.php @@ -872,6 +872,14 @@ foreach ($fields as $field) { true, true ); + } else if ($field['is_link_enabled']) { + $link_text = $field['link_text']; + + if ($field['link_text'] === '') { + $link_text = $field['link_url']; + } + + $data_field[1] = ''.$link_text.''; } else { $data_field[1] = html_print_textarea( 'customvalue_'.$field['id_field'], diff --git a/pandora_console/godmode/agentes/configure_field.php b/pandora_console/godmode/agentes/configure_field.php index 7ef0fe042a..281c4a7447 100755 --- a/pandora_console/godmode/agentes/configure_field.php +++ b/pandora_console/godmode/agentes/configure_field.php @@ -30,6 +30,10 @@ $display_on_front = (bool) get_parameter('display_on_front', 0); $is_password_type = (bool) get_parameter('is_password_type', 0); $is_combo_enable = (bool) get_parameter('is_combo_enable', 0); $combo_values = (string) get_parameter('combo_values', ''); +$is_link_enabled = (bool) get_parameter('is_link_enabled', 0); +$link_text = (string) get_parameter('link_text', ''); +$link_url = (string) get_parameter('link_url', ''); + // Header. if ($id_field) { $field = db_get_row_filter('tagent_custom_fields', ['id_field' => $id_field]); @@ -38,6 +42,9 @@ if ($id_field) { $is_password_type = $field['is_password_type']; $combo_values = $field['combo_values'] ? $field['combo_values'] : ''; $is_combo_enable = $config['is_combo_enable']; + $is_link_enabled = $field['is_link_enabled']; + $link_text = $field['link_text']; + $link_url = $field['link_url']; ui_print_page_header(__('Update agent custom field'), 'images/custom_field.png', false, '', true, ''); } else { ui_print_page_header(__('Create agent custom field'), 'images/custom_field.png', false, '', true, ''); @@ -128,6 +135,39 @@ $table->data[4][1] = html_print_textarea( true ); +$table->data[5][0] = __('Link type'); +$table->data[5][1] = html_print_checkbox_switch_extended( + 'is_link_enabled', + 1, + $is_link_enabled, + false, + '', + '', + true +); + +$table->rowstyle[6] = 'display: none;'; +$table->data[6][0] = __('Link text'); +$table->data[6][1] = html_print_textarea( + 'link_text', + 3, + 65, + io_safe_output($link_text), + '', + true +); + +$table->rowstyle[7] = 'display: none;'; +$table->data[7][0] = __('Link URL'); +$table->data[7][1] = html_print_textarea( + 'link_url', + 3, + 65, + io_safe_output($link_url), + '', + true +); + echo '
'; html_print_table($table); echo '
'; @@ -167,7 +207,35 @@ $(document).ready (function () { }); } - + if ($('input[type=checkbox][name=is_link_enabled]').is(":checked") === true) { + $('#configure_field-6').show(); + $('#configure_field-7').show(); + $('#configure_field-1').hide(); + $('#configure_field-3').hide(); + } else { + $('#configure_field-6').hide(); + $('#configure_field-7').hide(); + $('#configure_field-1').show(); + $('#configure_field-3').show(); + } + + // if ( $('input[type=checkbox][name=is_link_enabled]').val() === 1) { + + //} + $('input[type=checkbox][name=is_link_enabled]').change(function () { + if( $(this).is(":checked") ){ + $('#configure_field-6').show(); + $('#configure_field-7').show(); + $('#configure_field-1').hide(); + $('#configure_field-3').hide(); + } else{ + $('#configure_field-6').hide(); + $('#configure_field-7').hide(); + $('#configure_field-1').show(); + $('#configure_field-3').show(); + } + }); + $('input[type=checkbox][name=is_combo_enable]').change(function () { if( $(this).is(":checked") ){ $('#configure_field-4').show(); diff --git a/pandora_console/godmode/agentes/fields_manager.php b/pandora_console/godmode/agentes/fields_manager.php index 960ed62776..3f0212388d 100644 --- a/pandora_console/godmode/agentes/fields_manager.php +++ b/pandora_console/godmode/agentes/fields_manager.php @@ -38,14 +38,26 @@ $display_on_front = (int) get_parameter('display_on_front', 0); $is_password_type = (int) get_parameter('is_password_type', 0); $combo_values = (string) get_parameter('combo_values', ''); $combo_value_selected = (string) get_parameter('combo_value_selected', ''); +$is_link_enabled = (bool) get_parameter('is_link_enabled', 0); +$link_text = (string) get_parameter('link_text', ''); +$link_url = (string) get_parameter('link_url', ''); + +if ($is_link_enabled === true && $link_url !== '') { + $parsed_url = parse_url($link_url); + if (empty($parsed_url['scheme']) === true) { + $link_url = 'http://'.ltrim($link_url, '/'); + } +} // Create field. if ($create_field) { // Check if name field is empty. - if ($name == '') { + if ($name === '') { ui_print_error_message(__('The name must not be empty')); } else if ($name == db_get_value('name', 'tagent_custom_fields', 'name', $name)) { ui_print_error_message(__('The name must be unique')); + } else if ($is_link_enabled === true && $link_url === '') { + ui_print_error_message(__('The link URL must not be empty')); } else { $result = db_process_sql_insert( 'tagent_custom_fields', @@ -54,6 +66,9 @@ if ($create_field) { 'display_on_front' => $display_on_front, 'is_password_type' => $is_password_type, 'combo_values' => $combo_values, + 'is_link_enabled' => $is_link_enabled, + 'link_text' => $link_text, + 'link_url' => $link_url, ] ); ui_print_success_message(__('Field successfully created')); @@ -63,12 +78,17 @@ if ($create_field) { // Update field. if ($update_field) { // Check if name field is empty. - if ($name != '') { + if ($name !== '' + && ($is_link_enabled === false || ($is_link_enabled === true && $link_url !== '')) + ) { $values = [ 'name' => $name, 'display_on_front' => $display_on_front, 'is_password_type' => $is_password_type, 'combo_values' => $combo_values, + 'is_link_enabled' => $is_link_enabled, + 'link_text' => $link_text, + 'link_url' => $link_url, ]; $result = db_process_sql_update('tagent_custom_fields', $values, ['id_field' => $id_field]); diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 89fa418389..df51e426ff 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -2103,6 +2103,9 @@ CREATE TABLE IF NOT EXISTS `tagent_custom_fields` ( `display_on_front` TINYINT NOT NULL DEFAULT 0, `is_password_type` TINYINT NOT NULL DEFAULT 0, `combo_values` TEXT , + `is_link_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `link_text` VARCHAR(500) NOT NULL DEFAULT '', + `link_url` VARCHAR(2048) NOT NULL DEFAULT '', PRIMARY KEY (`id_field`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index 369fab0092..fca70188ef 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -1189,7 +1189,7 @@ INSERT INTO `tplugin` (`id`, `name`, `description`, `max_timeout`, `execute`, `p INSERT INTO `tplugin` (`id`, `name`, `description`, `max_timeout`, `max_retries`, `execute`, `net_dst_opt`, `net_port_opt`, `user_opt`, `pass_opt`, `plugin_type`, `macros`, `parameters`, `no_delete`) VALUES (9,'Packet Loss','Checks for dropped packages after X seconds of testing. It returns % of dropped packets. It uses ping flood mode to launch 50 consecutive pings to a remote destination. On local, stable networks, value should be 0. ',30,0,'/usr/share/pandora_server/util/plugin/packet_loss.sh','','','','',0,'{\"1\":{\"macro\":\"_field1_\",\"desc\":\"Test time\",\"help\":\"\",\"value\":\"8\",\"hide\":\"\"},\"2\":{\"macro\":\"_field2_\",\"desc\":\"Target IP\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"}}','_field1_ _field2_', 1); -INSERT INTO `tagent_custom_fields` VALUES (1,'Serial Number',0,0,''),(2,'Department',0,0,''),(3,'Additional ID',0,0,''),(4,'eHorusID',0,0,''); +INSERT INTO `tagent_custom_fields` VALUES (1,'Serial Number',0,0,'',0,'',''),(2,'Department',0,0,'',0,'',''),(3,'Additional ID',0,0,'',0,'',''),(4,'eHorusID',0,0,'',0,'',''); INSERT INTO `ttag` VALUES (1,'network','Network equipment','http://artica.es','','',''),(2,'critical','Critical modules','','','',''),(3,'dmz','DMZ Network Zone','','','',''),(4,'performance','Performance anda capacity modules','','','',''),(5,'configuration','','','','',''); From 4118a46b9fc340ac5b7fd0b45267bf0d64b557ef Mon Sep 17 00:00:00 2001 From: Daniel Barbero Date: Fri, 18 Nov 2022 14:04:54 +0100 Subject: [PATCH 042/251] add new filter search events pandora_enterprise#9135 --- pandora_console/extras/mr/59.sql | 3 +- .../godmode/events/event_edit_filter.php | 21 +++++++++ pandora_console/include/ajax/events.php | 7 +++ pandora_console/include/functions_events.php | 45 ++++++++++++++----- pandora_console/include/styles/events.css | 5 +++ pandora_console/operation/events/events.php | 23 ++++++++-- pandora_console/pandoradb.sql | 1 + 7 files changed, 90 insertions(+), 15 deletions(-) diff --git a/pandora_console/extras/mr/59.sql b/pandora_console/extras/mr/59.sql index 69f93d9e8a..b78fda6904 100644 --- a/pandora_console/extras/mr/59.sql +++ b/pandora_console/extras/mr/59.sql @@ -1,5 +1,6 @@ START TRANSACTION; -ALTER TABLE `tevent_filter` ADD COLUMN `owner_user` INT NOT NULL DEFAULT 0; +ALTER TABLE `tevent_filter` ADD COLUMN `owner_user` TEXT; +ALTER TABLE `tevent_filter` ADD COLUMN `not_search` INT NOT NULL DEFAULT 0; COMMIT; \ No newline at end of file diff --git a/pandora_console/godmode/events/event_edit_filter.php b/pandora_console/godmode/events/event_edit_filter.php index c796feaa90..302c75e46b 100644 --- a/pandora_console/godmode/events/event_edit_filter.php +++ b/pandora_console/godmode/events/event_edit_filter.php @@ -66,6 +66,7 @@ if ($id) { $severity = explode(',', $filter['severity']); $status = $filter['status']; $search = $filter['search']; + $not_search = $filter['not_search']; $text_agent = $filter['text_agent']; $id_agent = $filter['id_agent']; $text_module = $filter['text_module']; @@ -116,6 +117,7 @@ if ($id) { $severity = ''; $status = ''; $search = ''; + $not_search = 0; $text_agent = ''; $pagination = ''; $event_view_hr = ''; @@ -142,6 +144,7 @@ if ($update || $create) { $severity = implode(',', get_parameter('severity', -1)); $status = get_parameter('status', ''); $search = get_parameter('search', ''); + $not_search = get_parameter_switch('not_search', 0); $text_agent = get_parameter('text_agent', ''); $id_agent = (int) get_parameter('id_agent'); $text_module = get_parameter('text_module', ''); @@ -188,6 +191,7 @@ if ($update || $create) { 'severity' => $severity, 'status' => $status, 'search' => $search, + 'not_search' => $not_search, 'text_agent' => $text_agent, 'id_agent_module' => $id_agent_module, 'id_agent' => $id_agent, @@ -380,6 +384,15 @@ $table->data[6][1] = html_print_input_text( 255, true ); +$table->data[6][1] .= ' '.html_print_checkbox_switch( + 'not_search', + $not_search, + $not_search, + true, + false, + 'checked_slide_events(this);', + true +); $table->data[7][0] = ''.__('Agent search').''; $params = []; @@ -747,6 +760,14 @@ $(document).ready( function() { }); +function checked_slide_events(element) { + var value = $("#checkbox-"+element.name).val(); + if (value == 0) { + $("#checkbox-"+element.name).val(1); + } else { + $("#checkbox-"+element.name).val(0); + } +} function click_button_remove_tag(what_button) { if (what_button == "with") { diff --git a/pandora_console/include/ajax/events.php b/pandora_console/include/ajax/events.php index 9de1b29988..9ad3eda6fc 100644 --- a/pandora_console/include/ajax/events.php +++ b/pandora_console/include/ajax/events.php @@ -351,6 +351,7 @@ if ($save_event_filter) { $values['severity'] = implode(',', get_parameter('severity', -1)); $values['status'] = get_parameter('status'); $values['search'] = get_parameter('search'); + $values['not_search'] = get_parameter('not_search'); $values['text_agent'] = get_parameter('text_agent'); $values['id_agent'] = get_parameter('id_agent'); $values['id_agent_module'] = get_parameter('id_agent_module'); @@ -410,6 +411,7 @@ if ($update_event_filter) { $values['severity'] = implode(',', get_parameter('severity', -1)); $values['status'] = get_parameter('status'); $values['search'] = get_parameter('search'); + $values['not_search'] = get_parameter('not_search'); $values['text_agent'] = get_parameter('text_agent'); $values['id_agent'] = get_parameter('id_agent'); $values['id_agent_module'] = get_parameter('id_agent_module'); @@ -645,6 +647,8 @@ function load_form_filter() { $("#status").val(val); if (i == 'search') $('#text-search').val(val); + if (i == 'not_search') + $('#checkbox-not_search').val(val); if (i == 'text_agent') $('input[name=text_agent]').val(val); if (i == 'id_agent') @@ -903,6 +907,7 @@ function save_new_filter() { "severity" : $("#severity").val(), "status" : $("#status").val(), "search" : $("#text-search").val(), + "not_search" : $("#checkbox-not_search").val(), "text_agent" : $("#text_id_agent").val(), "id_agent" : $('input:hidden[name=id_agent]').val(), "id_agent_module" : $('input:hidden[name=module_search_hidden]').val(), @@ -981,6 +986,7 @@ function save_update_filter() { "severity" : $("#severity").val(), "status" : $("#status").val(), "search" : $("#text-search").val(), + "not_search" : $("#checkbox-not_search").val(), "text_agent" : $("#text_id_agent").val(), "id_agent" : $('input:hidden[name=id_agent]').val(), "id_agent_module" : $('input:hidden[name=module_search_hidden]').val(), @@ -2424,6 +2430,7 @@ if ($get_events_fired) { 'severity' => -1, 'status' => -1, 'search' => '', + 'not_search' => 0, 'text_agent' => '', 'id_agent' => 0, 'id_agent_module' => 0, diff --git a/pandora_console/include/functions_events.php b/pandora_console/include/functions_events.php index 795488529d..ab54ca0389 100644 --- a/pandora_console/include/functions_events.php +++ b/pandora_console/include/functions_events.php @@ -640,6 +640,7 @@ function events_update_status($id_evento, $status, $filter=null) * 'status' * 'agent_alias' * 'search' + * 'not_search' * 'id_extra' * 'id_source_event' * 'user_comment' @@ -1059,16 +1060,40 @@ function events_get_all( $custom_data_search = 'te.custom_data'; } - $sql_filters[] = vsprintf( - ' AND (lower(ta.alias) like lower("%%%s%%") - OR te.id_evento like "%%%s%%" - OR lower(te.evento) like lower("%%%s%%") - OR lower(te.user_comment) like lower("%%%s%%") - OR lower(te.id_extra) like lower("%%%s%%") - OR lower(te.source) like lower("%%%s%%") - OR lower('.$custom_data_search.') like lower("%%%s%%") )', - array_fill(0, 7, $filter['search']) - ); + $not_search = ''; + $nexo = 'OR'; + $array_search = [ + 'te.id_evento', + 'lower(te.evento)', + 'lower(te.user_comment)', + 'lower(te.id_extra)', + 'lower(te.source)', + 'lower('.$custom_data_search.')', + ]; + if (isset($filter['not_search']) === true + && empty($filter['not_search']) === false + ) { + $not_search = 'NOT'; + $nexo = 'AND'; + } else { + $array_search[] = 'lower(ta.alias)'; + } + + $sql_search = ' AND ('; + foreach ($array_search as $key => $field) { + $sql_search .= sprintf( + '%s %s %s like lower("%%%s%%")', + ($key === 0) ? '' : $nexo, + $field, + $not_search, + $filter['search'] + ); + $sql_search .= ' '; + } + + $sql_search .= ' )'; + + $sql_filters[] = $sql_search; } // Free search exclude. diff --git a/pandora_console/include/styles/events.css b/pandora_console/include/styles/events.css index 32317e3e4c..2f43d50beb 100644 --- a/pandora_console/include/styles/events.css +++ b/pandora_console/include/styles/events.css @@ -140,6 +140,11 @@ form.flex-row div.filter_input.filter_input_switch .p-slider { width: 30px; } +form .filter_input_not_search .p-switch { + flex: 0 1 30px; + margin: 0; +} + fieldset { margin: 0 auto; } diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php index a74ffd9eae..566fcb26d8 100644 --- a/pandora_console/operation/events/events.php +++ b/pandora_console/operation/events/events.php @@ -122,6 +122,10 @@ $search = get_parameter( 'filter[search]', ($filter['search'] ?? '') ); +$not_search = get_parameter( + 'filter[not_search]', + 0 +); $text_agent = get_parameter( 'filter[text_agent]', ($filter['text_agent'] ?? '') @@ -1080,6 +1084,7 @@ if ($loaded_filter !== false && $from_event_graph != 1 && isset($fb64) === false $severity = $filter['severity']; $status = $filter['status']; $search = $filter['search']; + $not_search = $filter['not_search']; $text_agent = $filter['text_agent']; $id_agent = $filter['id_agent']; $id_agent_module = $filter['id_agent_module']; @@ -1692,7 +1697,17 @@ $inputs[] = $in; // Free search. $data = html_print_input_text('search', $search, '', '', 255, true); -$in = '
'; +// Search recursive groups. +$data .= html_print_checkbox_switch( + 'not_search', + $not_search, + $not_search, + true, + false, + 'checked_slide_events(this);', + true +); +$in = ''; $inputs[] = $in; @@ -1732,7 +1747,7 @@ $data = html_print_checkbox_switch( $search_recursive_groups, true, false, - 'search_in_secondary_groups(this);', + 'checked_slide_events(this);', true ); @@ -1754,7 +1769,7 @@ $data = html_print_checkbox_switch( $search_secondary_groups, true, false, - 'search_in_secondary_groups(this);', + 'checked_slide_events(this);', true ); @@ -3066,7 +3081,7 @@ $(document).ready( function() { }); -function search_in_secondary_groups(element) { +function checked_slide_events(element) { var value = $("#checkbox-"+element.name).val(); if (value == 0) { $("#checkbox-"+element.name).val(1); diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index cd4e192407..517fb5cb03 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1238,6 +1238,7 @@ CREATE TABLE IF NOT EXISTS `tevent_filter` ( `severity` TEXT, `status` INT NOT NULL DEFAULT -1, `search` TEXT, + `not_search` INT NOT NULL DEFAULT 0, `text_agent` TEXT, `id_agent` INT DEFAULT 0, `id_agent_module` INT DEFAULT 0, From 14745a962568b00985bd4487b93daad8c7aca158 Mon Sep 17 00:00:00 2001 From: Luis Date: Mon, 21 Nov 2022 09:23:31 +0100 Subject: [PATCH 043/251] WIP:Prepare download control --- pandora_console/include/functions.php | 30 +++++++++ .../include/javascript/pandora_ui.js | 65 +++++++++++++++++++ pandora_console/include/php_to_js_values.php | 4 ++ 3 files changed, 99 insertions(+) diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index ed999553cb..4facfad081 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -6269,3 +6269,33 @@ function arrayOutputSorting($sort, $sortField) } }; } + + +function setCookieToken($cookieName, $cookieValue, $httpOnly=true, $secure=false) +{ + // See: http://stackoverflow.com/a/1459794/59087 + // See: http://shiflett.org/blog/2006/mar/server-name-versus-http-host + // See: http://stackoverflow.com/a/3290474/59087 + setcookie( + $cookieName, + $cookieValue, + 2147483647, + // expires January 1, 2038 + '/', + // your path + $_SERVER['HTTP_HOST'], + // your domain + $secure, + // Use true over HTTPS + $httpOnly + // Set true for $AUTH_COOKIE_NAME + ); +} + + +function setDownloadCookieToken() +{ + $token = 'downloadToken'; + + setCookieToken($token, $_GET[$token], false, false); +} diff --git a/pandora_console/include/javascript/pandora_ui.js b/pandora_console/include/javascript/pandora_ui.js index ecb23827d9..30e7ee32ee 100644 --- a/pandora_console/include/javascript/pandora_ui.js +++ b/pandora_console/include/javascript/pandora_ui.js @@ -763,3 +763,68 @@ function getGroupIcon(id_group, img_container) { } }); } + +/* Prepare download control */ +function getCookie(name) { + var parts = document.cookie.split(name + "="); + if (parts.length == 2) + return parts + .pop() + .split(";") + .shift(); +} + +function expireCookie(cName) { + document.cookie = + encodeURIComponent(cName) + + "=deleted; expires=" + + new Date(0).toUTCString(); +} + +function setCursor(buttonStyle, button) { + button.css("cursor", buttonStyle); +} + +function setFormToken(button) { + var downloadToken = new Date().getTime(); + button.append(" 'forced_title_layer', 'class' => 'forced_title_layer', ' set_js_value('absolute_homeurl', ui_get_full_url(false, false, false, false)); set_js_value('homeurl', $config['homeurl']); set_js_value('homedir', $config['homedir'].'/'); +// Prevent double request message. +set_js_value('prepareDownloadTitle', __('Generating content')); +set_js_value('prepareDownloadMsg', __('Generating content, please wait')); + // ====================================================================== From c56787c459214be739f4f5317c3b5714e8712506 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Mon, 21 Nov 2022 09:55:35 +0100 Subject: [PATCH 044/251] visual fix --- pandora_console/godmode/agentes/configure_field.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pandora_console/godmode/agentes/configure_field.php b/pandora_console/godmode/agentes/configure_field.php index 281c4a7447..9303a645cf 100755 --- a/pandora_console/godmode/agentes/configure_field.php +++ b/pandora_console/godmode/agentes/configure_field.php @@ -219,9 +219,6 @@ $(document).ready (function () { $('#configure_field-3').show(); } - // if ( $('input[type=checkbox][name=is_link_enabled]').val() === 1) { - - //} $('input[type=checkbox][name=is_link_enabled]').change(function () { if( $(this).is(":checked") ){ $('#configure_field-6').show(); @@ -241,19 +238,23 @@ $(document).ready (function () { $('#configure_field-4').show(); dialog_message("#message_no_set_password"); $('#configure_field-1').hide(); + $('#configure_field-5').hide(); } else{ $('#configure_field-4').hide(); $('#configure_field-1').show(); + $('#configure_field-5').show(); } }); $('input[type=checkbox][name=is_password_type]').change(function () { if( $(this).is(":checked")){ dialog_message("#message_no_set_combo"); $('#configure_field-3').hide(); + $('#configure_field-5').hide(); } else{ $('#configure_field-3').show(); + $('#configure_field-5').show(); } }); }); From 5910002e9d32855c5ab601ac47354565f2a1e13e Mon Sep 17 00:00:00 2001 From: sergio Date: Mon, 21 Nov 2022 18:01:53 +0100 Subject: [PATCH 045/251] #9833 Fixed general user search in open --- pandora_console/operation/search_results.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandora_console/operation/search_results.php b/pandora_console/operation/search_results.php index 9951ec528e..650bda0c36 100644 --- a/pandora_console/operation/search_results.php +++ b/pandora_console/operation/search_results.php @@ -18,7 +18,8 @@ require_once $config['homedir'].'/include/functions_reporting.php'; enterprise_include('operation/reporting/custom_reporting.php'); $searchAgents = $searchAlerts = $searchModules = check_acl($config['id_user'], 0, 'AR'); -$searchUsers = $searchPolicies = (check_acl($config['id_user'], 0, 'AR') && enterprise_installed()); +$searchUsers = (check_acl($config['id_user'], 0, 'AR')); +$searchPolicies = (check_acl($config['id_user'], 0, 'AR') && enterprise_installed()); $searchReports = $searchGraphs = check_acl($config['id_user'], 0, 'RR'); $searchMaps = check_acl($config['id_user'], 0, 'VR'); $searchMain = true; From 195e3cdd3f7e840dd5e3ea6d1b0a15ed44a6305a Mon Sep 17 00:00:00 2001 From: Shinichi Matsumoto Date: Tue, 22 Nov 2022 03:59:01 +0000 Subject: [PATCH 046/251] collection is not updated if the md5 file size of collection is 0 If the md5 file in collection has size 0, delete it. Set $local_collection_md5 to "Size 0", which is impossible for md5, and let $remote_collection_md5 be adopted. --- pandora_agents/unix/pandora_agent | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 1c91f31f38..a4d71094e8 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -2403,6 +2403,11 @@ sub check_collections () { if (open (MD5_FILE, "< $ConfDir/collections/$collection_md5_file")) { $local_collection_md5 = ; close MD5_FILE; + if ( ! defined ($local_collection_md5) ) { + log_message ('Collection', "Size of $ConfDir/collections/$collection_md5_file is 0"); + unlink ("$ConfDir/collections/$collection_md5_file"); + $local_collection_md5 = "Size 0"; + } } else { log_message ('Collection', "Could not open dir $ConfDir/collections/$collection_md5_file"); next; From 767624b0c38ef02357778d0df353a6d655559dc9 Mon Sep 17 00:00:00 2001 From: "alejandro.campos@artica.es" Date: Tue, 22 Nov 2022 11:50:07 +0100 Subject: [PATCH 047/251] implemented link type custom field --- pandora_console/extras/mr/60.sql | 2 -- .../godmode/agentes/agent_manager.php | 29 +++++++++++++--- .../godmode/agentes/configurar_agente.php | 27 +++++++++++++-- .../godmode/agentes/configure_field.php | 34 ------------------- .../godmode/agentes/fields_manager.php | 19 +---------- .../agentes/estado_generalagente.php | 13 +++++++ pandora_console/pandoradb.sql | 2 -- pandora_console/pandoradb_data.sql | 2 +- 8 files changed, 65 insertions(+), 63 deletions(-) diff --git a/pandora_console/extras/mr/60.sql b/pandora_console/extras/mr/60.sql index 40a0a86c4f..bf1ff4131a 100644 --- a/pandora_console/extras/mr/60.sql +++ b/pandora_console/extras/mr/60.sql @@ -1,7 +1,5 @@ START TRANSACTION; ALTER TABLE `tagent_custom_fields` ADD `is_link_enabled` TINYINT(1) NOT NULL DEFAULT 0; -ALTER TABLE `tagent_custom_fields` ADD COLUMN `link_text` VARCHAR(500) NOT NULL DEFAULT ''; -ALTER TABLE `tagent_custom_fields` ADD COLUMN `link_url` VARCHAR(2048) NOT NULL DEFAULT ''; COMMIT; diff --git a/pandora_console/godmode/agentes/agent_manager.php b/pandora_console/godmode/agentes/agent_manager.php index e5e37e63ea..b35dab9574 100644 --- a/pandora_console/godmode/agentes/agent_manager.php +++ b/pandora_console/godmode/agentes/agent_manager.php @@ -873,13 +873,34 @@ foreach ($fields as $field) { true ); } else if ($field['is_link_enabled']) { - $link_text = $field['link_text']; + list($link_text, $link_url) = json_decode($custom_value, true); - if ($field['link_text'] === '') { - $link_text = $field['link_url']; + if (json_last_error() !== JSON_ERROR_NONE) { + $link_text = ''; + $link_url = ''; } - $data_field[1] = ''.$link_text.''; + $data_field[1] = ''.__('Link text:').''; + $data_field[1] .= '
'; + $data_field[1] .= html_print_textarea( + 'customvalue_'.$field['id_field'].'[]', + 2, + 65, + $link_text, + 'class="min-height-30px', + true + ); + $data_field[1] .= '
'; + $data_field[1] .= ''.__('Link URL:').''; + $data_field[1] .= '
'; + $data_field[1] .= html_print_textarea( + 'customvalue_'.$field['id_field'].'[]', + 2, + 65, + $link_url, + 'class="min-height-30px', + true + ); } else { $data_field[1] = html_print_textarea( 'customvalue_'.$field['id_field'], diff --git a/pandora_console/godmode/agentes/configurar_agente.php b/pandora_console/godmode/agentes/configurar_agente.php index f873795ae6..2fd9fa8948 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -238,7 +238,15 @@ if ($create_agent) { $field_values = []; foreach ($fields as $field) { - $field_values[$field['id_field']] = (string) get_parameter_post('customvalue_'.$field['id_field'], ''); + $field_value = get_parameter_post('customvalue_'.$field['id_field'], ''); + + if ($field['is_link_enabled']) { + $field_value = json_encode($field_value); + } else { + $field_value = (string) $field_value; + } + + $field_values[$field['id_field']] = $field_value; } // Check if agent exists (BUG WC-50518-2). @@ -999,7 +1007,22 @@ if ($update_agent) { $field_values = []; foreach ($fields as $field) { - $field_values[$field['id_field']] = (string) get_parameter_post('customvalue_'.$field['id_field'], ''); + $field_value = get_parameter_post('customvalue_'.$field['id_field'], ''); + + if ($field['is_link_enabled']) { + if ($field_value[1] !== '') { + $parsed_url = parse_url($field_value[1]); + if (empty($parsed_url['scheme']) === true) { + $field_value[1] = 'http://'.ltrim($field_value[1], '/'); + } + } + + $field_value = json_encode($field_value); + } else { + $field_value = (string) $field_value; + } + + $field_values[$field['id_field']] = $field_value; } foreach ($field_values as $key => $value) { diff --git a/pandora_console/godmode/agentes/configure_field.php b/pandora_console/godmode/agentes/configure_field.php index 9303a645cf..f7c80c832c 100755 --- a/pandora_console/godmode/agentes/configure_field.php +++ b/pandora_console/godmode/agentes/configure_field.php @@ -31,8 +31,6 @@ $is_password_type = (bool) get_parameter('is_password_type', 0); $is_combo_enable = (bool) get_parameter('is_combo_enable', 0); $combo_values = (string) get_parameter('combo_values', ''); $is_link_enabled = (bool) get_parameter('is_link_enabled', 0); -$link_text = (string) get_parameter('link_text', ''); -$link_url = (string) get_parameter('link_url', ''); // Header. if ($id_field) { @@ -43,8 +41,6 @@ if ($id_field) { $combo_values = $field['combo_values'] ? $field['combo_values'] : ''; $is_combo_enable = $config['is_combo_enable']; $is_link_enabled = $field['is_link_enabled']; - $link_text = $field['link_text']; - $link_url = $field['link_url']; ui_print_page_header(__('Update agent custom field'), 'images/custom_field.png', false, '', true, ''); } else { ui_print_page_header(__('Create agent custom field'), 'images/custom_field.png', false, '', true, ''); @@ -146,28 +142,6 @@ $table->data[5][1] = html_print_checkbox_switch_extended( true ); -$table->rowstyle[6] = 'display: none;'; -$table->data[6][0] = __('Link text'); -$table->data[6][1] = html_print_textarea( - 'link_text', - 3, - 65, - io_safe_output($link_text), - '', - true -); - -$table->rowstyle[7] = 'display: none;'; -$table->data[7][0] = __('Link URL'); -$table->data[7][1] = html_print_textarea( - 'link_url', - 3, - 65, - io_safe_output($link_url), - '', - true -); - echo ''; html_print_table($table); echo '
'; @@ -208,26 +182,18 @@ $(document).ready (function () { } if ($('input[type=checkbox][name=is_link_enabled]').is(":checked") === true) { - $('#configure_field-6').show(); - $('#configure_field-7').show(); $('#configure_field-1').hide(); $('#configure_field-3').hide(); } else { - $('#configure_field-6').hide(); - $('#configure_field-7').hide(); $('#configure_field-1').show(); $('#configure_field-3').show(); } $('input[type=checkbox][name=is_link_enabled]').change(function () { if( $(this).is(":checked") ){ - $('#configure_field-6').show(); - $('#configure_field-7').show(); $('#configure_field-1').hide(); $('#configure_field-3').hide(); } else{ - $('#configure_field-6').hide(); - $('#configure_field-7').hide(); $('#configure_field-1').show(); $('#configure_field-3').show(); } diff --git a/pandora_console/godmode/agentes/fields_manager.php b/pandora_console/godmode/agentes/fields_manager.php index 3f0212388d..608b6b1f65 100644 --- a/pandora_console/godmode/agentes/fields_manager.php +++ b/pandora_console/godmode/agentes/fields_manager.php @@ -39,15 +39,6 @@ $is_password_type = (int) get_parameter('is_password_type', 0); $combo_values = (string) get_parameter('combo_values', ''); $combo_value_selected = (string) get_parameter('combo_value_selected', ''); $is_link_enabled = (bool) get_parameter('is_link_enabled', 0); -$link_text = (string) get_parameter('link_text', ''); -$link_url = (string) get_parameter('link_url', ''); - -if ($is_link_enabled === true && $link_url !== '') { - $parsed_url = parse_url($link_url); - if (empty($parsed_url['scheme']) === true) { - $link_url = 'http://'.ltrim($link_url, '/'); - } -} // Create field. if ($create_field) { @@ -56,8 +47,6 @@ if ($create_field) { ui_print_error_message(__('The name must not be empty')); } else if ($name == db_get_value('name', 'tagent_custom_fields', 'name', $name)) { ui_print_error_message(__('The name must be unique')); - } else if ($is_link_enabled === true && $link_url === '') { - ui_print_error_message(__('The link URL must not be empty')); } else { $result = db_process_sql_insert( 'tagent_custom_fields', @@ -67,8 +56,6 @@ if ($create_field) { 'is_password_type' => $is_password_type, 'combo_values' => $combo_values, 'is_link_enabled' => $is_link_enabled, - 'link_text' => $link_text, - 'link_url' => $link_url, ] ); ui_print_success_message(__('Field successfully created')); @@ -78,17 +65,13 @@ if ($create_field) { // Update field. if ($update_field) { // Check if name field is empty. - if ($name !== '' - && ($is_link_enabled === false || ($is_link_enabled === true && $link_url !== '')) - ) { + if ($name !== '') { $values = [ 'name' => $name, 'display_on_front' => $display_on_front, 'is_password_type' => $is_password_type, 'combo_values' => $combo_values, 'is_link_enabled' => $is_link_enabled, - 'link_text' => $link_text, - 'link_url' => $link_url, ]; $result = db_process_sql_update('tagent_custom_fields', $values, ['id_field' => $id_field]); diff --git a/pandora_console/operation/agentes/estado_generalagente.php b/pandora_console/operation/agentes/estado_generalagente.php index 91714803f9..742e55adf5 100755 --- a/pandora_console/operation/agentes/estado_generalagente.php +++ b/pandora_console/operation/agentes/estado_generalagente.php @@ -546,6 +546,19 @@ foreach ($fields as $field) { if ($custom_value[0]['is_password_type']) { $data[1] = '••••••••'; + } else if ($field['is_link_enabled'] === '1') { + list($link_text, $link_url) = json_decode($custom_value[0]['description'], true); + + if (json_last_error() !== JSON_ERROR_NONE) { + $link_text = ''; + $link_url = ''; + } + + if ($link_text === '') { + $link_text = $link_url; + } + + $data[1] = ''.$link_text.''; } else { $data[1] = $custom_value[0]['description']; } diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index df51e426ff..87a1428702 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -2104,8 +2104,6 @@ CREATE TABLE IF NOT EXISTS `tagent_custom_fields` ( `is_password_type` TINYINT NOT NULL DEFAULT 0, `combo_values` TEXT , `is_link_enabled` TINYINT(1) NOT NULL DEFAULT 0, - `link_text` VARCHAR(500) NOT NULL DEFAULT '', - `link_url` VARCHAR(2048) NOT NULL DEFAULT '', PRIMARY KEY (`id_field`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index fca70188ef..611f11453c 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -1189,7 +1189,7 @@ INSERT INTO `tplugin` (`id`, `name`, `description`, `max_timeout`, `execute`, `p INSERT INTO `tplugin` (`id`, `name`, `description`, `max_timeout`, `max_retries`, `execute`, `net_dst_opt`, `net_port_opt`, `user_opt`, `pass_opt`, `plugin_type`, `macros`, `parameters`, `no_delete`) VALUES (9,'Packet Loss','Checks for dropped packages after X seconds of testing. It returns % of dropped packets. It uses ping flood mode to launch 50 consecutive pings to a remote destination. On local, stable networks, value should be 0. ',30,0,'/usr/share/pandora_server/util/plugin/packet_loss.sh','','','','',0,'{\"1\":{\"macro\":\"_field1_\",\"desc\":\"Test time\",\"help\":\"\",\"value\":\"8\",\"hide\":\"\"},\"2\":{\"macro\":\"_field2_\",\"desc\":\"Target IP\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"}}','_field1_ _field2_', 1); -INSERT INTO `tagent_custom_fields` VALUES (1,'Serial Number',0,0,'',0,'',''),(2,'Department',0,0,'',0,'',''),(3,'Additional ID',0,0,'',0,'',''),(4,'eHorusID',0,0,'',0,'',''); +INSERT INTO `tagent_custom_fields` VALUES (1,'Serial Number',0,0,'',0),(2,'Department',0,0,'',0),(3,'Additional ID',0,0,'',0),(4,'eHorusID',0,0,'',0); INSERT INTO `ttag` VALUES (1,'network','Network equipment','http://artica.es','','',''),(2,'critical','Critical modules','','','',''),(3,'dmz','DMZ Network Zone','','','',''),(4,'performance','Performance anda capacity modules','','','',''),(5,'configuration','','','','',''); From fcd918d00b9015a5b4cd2eadb9887fe93875de39 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Thu, 24 Nov 2022 15:49:11 +0100 Subject: [PATCH 048/251] #9851 Fixed background image size --- pandora_console/general/login_page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/general/login_page.php b/pandora_console/general/login_page.php index 6d7a9864ce..bb9fa19185 100755 --- a/pandora_console/general/login_page.php +++ b/pandora_console/general/login_page.php @@ -91,7 +91,7 @@ $login_body_class = ''; // Overrides the default background with the defined by the user. if (!empty($config['login_background'])) { $background_url = 'images/backgrounds/'.$config['login_background']; - $login_body_style = "style=\"background:linear-gradient(74deg, rgba(2, 2, 2, 0.333) 36%, transparent 36%), url('".$background_url."');\""; + $login_body_style = "style=\"background-size: 100% 100% !important;background:linear-gradient(74deg, rgba(2, 2, 2, 0.333) 36%, transparent 36%), url('".$background_url."');\""; } // Support for Internet Explorer and Microsoft Edge browsers From d6af3c7121dd47a00cfa9212f088f434a1266fdb Mon Sep 17 00:00:00 2001 From: SHIMIZU Hiroki Date: Mon, 28 Nov 2022 11:40:45 +0900 Subject: [PATCH 049/251] On pandora_server/util/plugin/pandora_snmp_bandwidth.pl fixed typo (bandwith -> bandwidth) added new condition to determine if SNMP has a 64-bit counter fixed a bug that bandwidth utilization was not output when bandwidth utilization was 0% --- .../util/plugin/pandora_snmp_bandwidth.pl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pandora_server/util/plugin/pandora_snmp_bandwidth.pl b/pandora_server/util/plugin/pandora_snmp_bandwidth.pl index 3eb2b4fb53..8b5d505116 100755 --- a/pandora_server/util/plugin/pandora_snmp_bandwidth.pl +++ b/pandora_server/util/plugin/pandora_snmp_bandwidth.pl @@ -2,7 +2,7 @@ # ################################################################################ # -# Bandwith usage plugin +# Bandwidth usage plugin # # Requirements: # snmpget @@ -55,7 +55,7 @@ Where OPTIONS could be: [EXTRA] -ifIndex Target interface to retrieve, if not specified, total - bandwith will be reported. + bandwidth will be reported. -uniqid Use custom temporary file name. -inUsage Show only input usage (in percentage) - 1, or not 0. -outUsage Show only output usage (in percentage) - 1, or not 0. @@ -492,9 +492,9 @@ $config->{'tmp_separator'} = ';' if empty($config->{'tmp_separator'}); $config->{'tmp'} = (($^O =~ /win/)?$ENV{'TMP'}:'/tmp') if empty($config->{'tmp'}); # Create unique name for tmp and log file for host -my $filename = $config->{'tmp'}.'/pandora_bandwith_'.$config->{'host'}; +my $filename = $config->{'tmp'}.'/pandora_bandwidth_'.$config->{'host'}; if (!empty($config->{'uniqid'})) { - $filename = $config->{'tmp'}.'/pandora_bandwith_'.$config->{'uniqid'}; + $filename = $config->{'tmp'}.'/pandora_bandwidth_'.$config->{'uniqid'}; } # Replace every dot for underscore $filename =~ tr/./_/; @@ -511,7 +511,7 @@ if ( defined($sysobjectid->{'error'}) || $sysobjectid->{'data'} eq '' ) { # Check SNMP x64 interfaces my $walk64 = snmp_walk({%{$config}, 'oid' => '.1.3.6.1.2.1.31.1.1.1.6'}); -if ( $walk64 =~ 'No Such Instance currently exists at this OID' || $walk64 =~ 'No more variables left in this MIB View') { +if ( $walk64 =~ 'No Such Instance currently exists at this OID' || $walk64 =~ 'No more variables left in this MIB View' || $walk64 =~ 'No Such Object available on this agent at this OID') { $config->{'use_x64'} = 0; } else { $config->{'use_x64'} = 1; @@ -556,15 +556,15 @@ my $j = 0; my $k = 0; foreach my $iface (keys %{$analysis_tree}) { # Calculate summary; - if (is_enabled($analysis_tree->{$iface}{'bandwidth'})) { + if (is_enabled($analysis_tree->{$iface}{'bandwidth'}) || $analysis_tree->{$iface}{'bandwidth'} == 0) { $bandwidth = $analysis_tree->{$iface}{'bandwidth'}; $i++; } - if (is_enabled($analysis_tree->{$iface}{'inUsage'})) { + if (is_enabled($analysis_tree->{$iface}{'inUsage'}) || $analysis_tree->{$iface}{'inUsage'} == 0) { $inUsage = $analysis_tree->{$iface}{'inUsage'}; $j++; } - if (is_enabled($analysis_tree->{$iface}{'outUsage'})) { + if (is_enabled($analysis_tree->{$iface}{'outUsage'}) || $analysis_tree->{$iface}{'inUsage'} == 0) { $outUsage = $analysis_tree->{$iface}{'outUsage'}; $k++; } From 695f457a09ff13cd1ab3f2405fe5aa1c80c127ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <79-jose.gonzalez@users.noreply.brutus.artica.es> Date: Mon, 28 Nov 2022 07:47:47 +0000 Subject: [PATCH 050/251] Fix issue with Database Lock. --- pandora_console/include/functions_db.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pandora_console/include/functions_db.php b/pandora_console/include/functions_db.php index 83b972ca75..2ec5486766 100644 --- a/pandora_console/include/functions_db.php +++ b/pandora_console/include/functions_db.php @@ -2313,7 +2313,13 @@ function db_get_lock(string $lockname, int $expiration_time=86400) :?int } if ($lock_status === false) { - return null; + db_pandora_audit( + AUDIT_LOG_SYSTEM, + 'Issue in Database Lock', + 'system' + ); + + return (int) null; } return (int) $lock_status; From 57bd23f94c84f274e7888b94c3dba5722e3d4fb4 Mon Sep 17 00:00:00 2001 From: Daniel Maya Date: Tue, 29 Nov 2022 16:45:44 +0100 Subject: [PATCH 051/251] #9873 Fixed images --- .../include/rest-api/models/VisualConsole/Item.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandora_console/include/rest-api/models/VisualConsole/Item.php b/pandora_console/include/rest-api/models/VisualConsole/Item.php index be075d5e75..c132be2885 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Item.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Item.php @@ -2296,6 +2296,7 @@ class Item extends CachedModel false ); + $aux_images = $all_images; foreach ($all_images as $image_file) { $image_file = substr($image_file, 0, (strlen($image_file) - 4)); @@ -2311,7 +2312,11 @@ class Item extends CachedModel continue; } - $result[$image_file] = $image_file; + // Check the 4 images. + $array_images = preg_grep('/'.$image_file.'(_ok|_bad|_warning)*\./', $aux_images); + if (count($array_images) >= 4) { + $result[$image_file] = $image_file; + } } } From c45505954683a005b85c997a9ac6ca9fd49d9148 Mon Sep 17 00:00:00 2001 From: Enrique Martin Date: Thu, 1 Dec 2022 16:47:44 +0100 Subject: [PATCH 052/251] Added metaconsole_access_node value to new_user API function --- pandora_console/include/functions_api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index 8d2061d3c7..1e9b083f19 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -9528,6 +9528,7 @@ function api_set_new_user($id, $thrash2, $other, $thrash3) $values['default_event_filter'] = $other['data'][10]; $values['section'] = $other['data'][11]; $values['session_time'] = $other['data'][12]; + $values['metaconsole_access_node'] = $other['data'][13]; if (empty($password) === true) { returnError('Password cannot be empty.'); From 028176e58dcd7850792827539f414b525cd48d12 Mon Sep 17 00:00:00 2001 From: KANAYAMA Akihiro Date: Fri, 2 Dec 2022 16:20:21 +0900 Subject: [PATCH 053/251] Fixed const UNKNOWN_DUPLEX Changed the condition to switch x86 or x64 Added conditions in sub prepare_tree when snmp_get returns empty array Fixed "Calculate summary" to sum up each value Adjusted indents --- .../util/plugin/pandora_snmp_bandwidth.pl | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/pandora_server/util/plugin/pandora_snmp_bandwidth.pl b/pandora_server/util/plugin/pandora_snmp_bandwidth.pl index 8b5d505116..9b28848b48 100755 --- a/pandora_server/util/plugin/pandora_snmp_bandwidth.pl +++ b/pandora_server/util/plugin/pandora_snmp_bandwidth.pl @@ -66,7 +66,7 @@ e.g. -v is equal to -version, -c to -community, etc. EO_HELP use constant { - UNKNOWN_DUPLEX => 0, + UNKNOWN_DUPLEX => 1, HALF_DUPLEX => 2, FULL_DUPLEX => 3, }; @@ -133,9 +133,9 @@ sub update_config_key ($) { if ($arg eq 'inUsage') { return "inUsage"; } - if ($arg eq 'outUsage') { - return "outUsage"; - } + if ($arg eq 'outUsage') { + return "outUsage"; + } } ################################################################################ @@ -188,7 +188,7 @@ sub prepare_tree { my $inOctets = snmp_get(\%inOctets_call); if (ref($inOctets) eq "HASH") { - if ($inOctets->{'data'} eq '') { + if (! exists($inOctets->{'data'}) || $inOctets->{'data'} eq '') { $inOctets = 0; } else { $inOctets = int $inOctets->{'data'}; @@ -198,18 +198,18 @@ sub prepare_tree { next; } - my %outOctets_call = %{$config}; - if (is_enabled($config->{'use_x64'})) { - $outOctets_call{'oid'} = $config->{'oid_base'}; - $outOctets_call{'oid'} .= $config->{'x64_indexes'}{'outOctets'}.$ifIndex; - } else { - $outOctets_call{'oid'} = $config->{'oid_base'}; - $outOctets_call{'oid'} .= $config->{'x86_indexes'}{'outOctets'}.$ifIndex; - } + my %outOctets_call = %{$config}; + if (is_enabled($config->{'use_x64'})) { + $outOctets_call{'oid'} = $config->{'oid_base'}; + $outOctets_call{'oid'} .= $config->{'x64_indexes'}{'outOctets'}.$ifIndex; + } else { + $outOctets_call{'oid'} = $config->{'oid_base'}; + $outOctets_call{'oid'} .= $config->{'x86_indexes'}{'outOctets'}.$ifIndex; + } my $outOctets = snmp_get(\%outOctets_call); if (ref($outOctets) eq "HASH") { - if ($outOctets->{'data'} eq '') { + if (! exists($outOctets->{'data'}) || $outOctets->{'data'} eq '') { $outOctets = 0; } else { $outOctets = int $outOctets->{'data'}; @@ -220,28 +220,27 @@ sub prepare_tree { } my %duplex_call = %{$config}; - if (is_enabled($config->{'use_x64'})) { - $duplex_call{'oid'} = $config->{'oid_base'}; - $duplex_call{'oid'} .= $config->{'x64_indexes'}{'duplex'}.$ifIndex; - } else { - $duplex_call{'oid'} = $config->{'oid_base'}; - $duplex_call{'oid'} .= $config->{'x86_indexes'}{'duplex'}.$ifIndex; - } + if (is_enabled($config->{'use_x64'})) { + $duplex_call{'oid'} = $config->{'oid_base'}; + $duplex_call{'oid'} .= $config->{'x64_indexes'}{'duplex'}.$ifIndex; + } else { + $duplex_call{'oid'} = $config->{'oid_base'}; + $duplex_call{'oid'} .= $config->{'x86_indexes'}{'duplex'}.$ifIndex; + } my $duplex = snmp_get(\%duplex_call); if (ref($duplex) eq "HASH") { - if ($duplex->{'data'} eq '') { + if (! exists($duplex->{'data'}) || $duplex->{'data'} eq '') { $duplex = 0; } else { $duplex = int $duplex->{'data'}; } - } else { # Ignore, cannot retrieve inOctets. next; } - my %speed = %{$config}; + my %speed = %{$config}; if (is_enabled($config->{'use_x64'})) { $speed{'oid'} = $config->{'oid_base'}; $speed{'oid'} .= $config->{'x64_indexes'}{'ifSpeed'}.$ifIndex; @@ -511,7 +510,7 @@ if ( defined($sysobjectid->{'error'}) || $sysobjectid->{'data'} eq '' ) { # Check SNMP x64 interfaces my $walk64 = snmp_walk({%{$config}, 'oid' => '.1.3.6.1.2.1.31.1.1.1.6'}); -if ( $walk64 =~ 'No Such Instance currently exists at this OID' || $walk64 =~ 'No more variables left in this MIB View' || $walk64 =~ 'No Such Object available on this agent at this OID') { +if ( $walk64 !~ /.*\.[0-9]+ = Counter64: [0-9]+/ ) { $config->{'use_x64'} = 0; } else { $config->{'use_x64'} = 1; @@ -557,34 +556,34 @@ my $k = 0; foreach my $iface (keys %{$analysis_tree}) { # Calculate summary; if (is_enabled($analysis_tree->{$iface}{'bandwidth'}) || $analysis_tree->{$iface}{'bandwidth'} == 0) { - $bandwidth = $analysis_tree->{$iface}{'bandwidth'}; + $bandwidth += $analysis_tree->{$iface}{'bandwidth'}; $i++; } if (is_enabled($analysis_tree->{$iface}{'inUsage'}) || $analysis_tree->{$iface}{'inUsage'} == 0) { - $inUsage = $analysis_tree->{$iface}{'inUsage'}; + $inUsage += $analysis_tree->{$iface}{'inUsage'}; $j++; } if (is_enabled($analysis_tree->{$iface}{'outUsage'}) || $analysis_tree->{$iface}{'inUsage'} == 0) { - $outUsage = $analysis_tree->{$iface}{'outUsage'}; + $outUsage += $analysis_tree->{$iface}{'outUsage'}; $k++; } } if ($j > 0 && is_enabled($config->{'inUsage'})) { - $inUsage /= $j; - print sprintf("%.9f\n", $inUsage); + $inUsage /= $j; + print sprintf("%.9f\n", $inUsage); } elsif ($k > 0 && is_enabled($config->{'outUsage'})) { - $outUsage /= $k; - print sprintf("%.9f\n", $outUsage); + $outUsage /= $k; + print sprintf("%.9f\n", $outUsage); } if ($i > 0 && !is_enabled($config->{'inUsage'}) && !is_enabled($config->{'outUsage'}) ) { - $bandwidth /= $i; - print sprintf("%.9f\n", $bandwidth); + $bandwidth /= $i; + print sprintf("%.9f\n", $bandwidth); } logger($config, 'info', "Plugin ends") if (is_enabled($config->{'debug'})); From d525cb594c67c6450f6d8fa911bb01b905636e84 Mon Sep 17 00:00:00 2001 From: Calvo Date: Fri, 2 Dec 2022 09:42:24 +0100 Subject: [PATCH 054/251] WIP: Download wait message --- .../godmode/reporting/reporting_builder.php | 2 +- .../include/class/ModuleTemplates.class.php | 3 +- pandora_console/include/functions.php | 41 +++++++--------- .../include/functions_reporting_xml.php | 2 + pandora_console/include/functions_ui.php | 5 +- .../include/graphs/export_data.php | 3 ++ .../include/graphs/flot/pandora.flot.js | 1 + .../include/javascript/pandora_ui.js | 47 +++++++++++-------- pandora_console/operation/events/events.php | 2 +- .../operation/events/export_csv.php | 1 + pandora_console/vendor/mpdf/mpdf/src/Mpdf.php | 2 + 11 files changed, 60 insertions(+), 49 deletions(-) diff --git a/pandora_console/godmode/reporting/reporting_builder.php b/pandora_console/godmode/reporting/reporting_builder.php index 60b1601dc0..5357bdad13 100755 --- a/pandora_console/godmode/reporting/reporting_builder.php +++ b/pandora_console/godmode/reporting/reporting_builder.php @@ -1055,7 +1055,7 @@ switch ($action) { ] ); $data[2] .= ''; - $data[3] = ''; + $data[3] = ''; $data[3] .= html_print_image( 'images/xml.png', true, diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index ba67142560..782d3bb82d 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -506,6 +506,7 @@ class ModuleTemplates extends HTML header('Content-Disposition: attachment; filename='.preg_replace('/\s/', '_', $fileName).'.csv'); header('Pragma: no-cache'); header('Expires: 0'); + setDownloadCookieToken(); // Clean up output buffering while (@ob_end_clean()) { @@ -931,7 +932,7 @@ class ModuleTemplates extends HTML ] ); $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete'), 'class' => 'invert_filter']).''; - $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV'), 'class' => 'invert_filter']).''; + $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV'), 'class' => 'invert_filter']).''; array_push($table->data, $data); } diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index 4facfad081..3ee1815e08 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -6271,31 +6271,22 @@ function arrayOutputSorting($sort, $sortField) } -function setCookieToken($cookieName, $cookieValue, $httpOnly=true, $secure=false) -{ - // See: http://stackoverflow.com/a/1459794/59087 - // See: http://shiflett.org/blog/2006/mar/server-name-versus-http-host - // See: http://stackoverflow.com/a/3290474/59087 - setcookie( - $cookieName, - $cookieValue, - 2147483647, - // expires January 1, 2038 - '/', - // your path - $_SERVER['HTTP_HOST'], - // your domain - $secure, - // Use true over HTTPS - $httpOnly - // Set true for $AUTH_COOKIE_NAME - ); -} - - +/** + * Get dowload started cookie from js and set ready cokkie for download ready comntrol. + * + * @return + */ function setDownloadCookieToken() { - $token = 'downloadToken'; - - setCookieToken($token, $_GET[$token], false, false); + $download_cookie = get_cookie('downloadToken', false); + if ($download_cookie === false) { + return; + } else { + setcookie( + 'downloadReady', + $download_cookie, + (time() + 15), + '/' + ); + } } diff --git a/pandora_console/include/functions_reporting_xml.php b/pandora_console/include/functions_reporting_xml.php index 196027e90c..9b733c40d3 100644 --- a/pandora_console/include/functions_reporting_xml.php +++ b/pandora_console/include/functions_reporting_xml.php @@ -46,6 +46,8 @@ function reporting_xml_get_report($report, $filename, $return=false) // Download if marked to download. if ($filename !== false) { + // Cookie for download control. + setDownloadCookieToken(); header('Content-Type: application/xml; charset=UTF-8'); header('Content-Disposition: attachment; filename="'.$filename.'.xml"'); } diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 6ae90f29ef..ae346f1783 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -3540,6 +3540,9 @@ function ui_print_datatable(array $parameters) titleAttr: "'.__('Export current page to CSV').'", title: "export_'.$parameters['id'].'_current_page_'.date('Y-m-d').'", fieldSeparator: "'.$config['csv_divider'].'", + action: function ( e, dt, node, config ) { + blockResubmit(node); + }, exportOptions : { modifier : { // DataTables core @@ -3547,7 +3550,7 @@ function ui_print_datatable(array $parameters) page : "All", search : "applied" }'.$export_columns.' - } + }, } ] : [], lengthMenu: '.json_encode($pagination_options).', diff --git a/pandora_console/include/graphs/export_data.php b/pandora_console/include/graphs/export_data.php index a3c42577be..17b59b2baa 100644 --- a/pandora_console/include/graphs/export_data.php +++ b/pandora_console/include/graphs/export_data.php @@ -51,6 +51,9 @@ $default_filename = 'data_exported - '.date($config['date_format']); $filename = (string) get_parameter('filename', $default_filename); $filename = io_safe_output($filename); +// Set cookie for download control. +setDownloadCookieToken(); + /* * $data = array( * 'head' => array(,,...,), diff --git a/pandora_console/include/graphs/flot/pandora.flot.js b/pandora_console/include/graphs/flot/pandora.flot.js index 16e1b31a82..8084d4d6b3 100644 --- a/pandora_console/include/graphs/flot/pandora.flot.js +++ b/pandora_console/include/graphs/flot/pandora.flot.js @@ -2716,6 +2716,7 @@ function pandoraFlotArea( $("#menu_export_csv_" + graph_id).click(function(e) { e.preventDefault(); + blockResubmit($(this)); plot.exportDataCSV(); var es_firefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1; diff --git a/pandora_console/include/javascript/pandora_ui.js b/pandora_console/include/javascript/pandora_ui.js index 30e7ee32ee..1d9db8e328 100644 --- a/pandora_console/include/javascript/pandora_ui.js +++ b/pandora_console/include/javascript/pandora_ui.js @@ -456,8 +456,7 @@ function load_modal(settings) { // Function that shows a dialog box to confirm closures of generic manners. // The modal id is random. // eslint-disable-next-line no-unused-vars -function confirmDialog(settings) { - var randomStr = uniqId(); +function confirmDialog(settings, idDialog = uniqId()) { var hideOkButton = ""; var hideCancelButton = ""; @@ -487,11 +486,11 @@ function confirmDialog(settings) { if (typeof settings.message == "function") { $("body").append( - '
' + settings.message() + "
" + '
' + settings.message() + "
" ); } else { $("body").append( - '
' + settings.message + "
" + '
' + settings.message + "
" ); } @@ -542,8 +541,8 @@ function confirmDialog(settings) { buttons.unshift(newButton); } - $("#confirm_" + randomStr); - $("#confirm_" + randomStr) + $("#confirm_" + idDialog); + $("#confirm_" + idDialog) .dialog({ open: settings.open, title: settings.title, @@ -785,10 +784,11 @@ function setCursor(buttonStyle, button) { button.css("cursor", buttonStyle); } -function setFormToken(button) { +function setToken() { var downloadToken = new Date().getTime(); - button.append("'.html_print_image( + $csv['text'] = ''.html_print_image( 'images/csv.png', true, [ diff --git a/pandora_console/operation/events/export_csv.php b/pandora_console/operation/events/export_csv.php index 20856b707e..4b91f36e6d 100644 --- a/pandora_console/operation/events/export_csv.php +++ b/pandora_console/operation/events/export_csv.php @@ -150,6 +150,7 @@ $now = date('Y-m-d'); // Download header. header('Content-type: text/txt'); header('Content-Disposition: attachment; filename="export_events_'.$now.'.csv"'); +setDownloadCookieToken(); try { $fb64 = get_parameter('fb64', null); diff --git a/pandora_console/vendor/mpdf/mpdf/src/Mpdf.php b/pandora_console/vendor/mpdf/mpdf/src/Mpdf.php index 2c60309f83..ffe70a1f64 100644 --- a/pandora_console/vendor/mpdf/mpdf/src/Mpdf.php +++ b/pandora_console/vendor/mpdf/mpdf/src/Mpdf.php @@ -9478,6 +9478,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface function Output($name = '', $dest = '') { $this->logger->debug(sprintf('PDF generated in %.6F seconds', microtime(true) - $this->time0), ['context' => LogContext::STATISTICS]); + // Set cokie token to indicate download is ready. + setDownloadCookieToken(); // Finish document if necessary if ($this->state < 3) { From e0afcd0b859d6fefb0f6e2d0a11a58500aa9395c Mon Sep 17 00:00:00 2001 From: Calvo Date: Fri, 2 Dec 2022 13:12:58 +0100 Subject: [PATCH 055/251] WIP: Download wait message. datatables --- pandora_console/include/functions_ui.php | 12 ++++++++ .../include/javascript/buttons.html5.min.js | 29 +------------------ .../include/javascript/pandora_ui.js | 11 ++++--- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index ae346f1783..1f547342d7 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -3542,6 +3542,8 @@ function ui_print_datatable(array $parameters) fieldSeparator: "'.$config['csv_divider'].'", action: function ( e, dt, node, config ) { blockResubmit(node); + // Call the default csvHtml5 action method to create the CSV file + $.fn.dataTable.ext.buttons.csvHtml5.action.call(this, e, dt, node, config); }, exportOptions : { modifier : { @@ -3674,6 +3676,16 @@ function ui_print_datatable(array $parameters) $js .= '$(".datatables_thead_tr").css("height", 0);'; } + if (isset($parameters['csv']) === true) { + $js."'$('#".$table_id."').on( 'buttons-processing', function ( e, indicator ) { + if ( indicator ) { + console.log('a'); + } + else { + console.log('b'); + }"; + } + $js .= '});'; $js .= ''; diff --git a/pandora_console/include/javascript/buttons.html5.min.js b/pandora_console/include/javascript/buttons.html5.min.js index deee7fee68..c65fb2737a 100644 --- a/pandora_console/include/javascript/buttons.html5.min.js +++ b/pandora_console/include/javascript/buttons.html5.min.js @@ -5,31 +5,4 @@ FileSaver.js (1.3.3) - MIT license Copyright © 2016 Eli Grey - http://eligrey.com */ -(function(f){"function"===typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(g){return f(g,window,document)}):"object"===typeof exports?module.exports=function(g,p,z,t){g||(g=window);p&&p.fn.dataTable||(p=require("datatables.net")(g,p).$);p.fn.dataTable.Buttons||require("datatables.net-buttons")(g,p);return f(p,g,g.document,z,t)}:f(jQuery,window,document)})(function(f,g,p,z,t,w){function A(a){for(var b="";0<=a;)b=String.fromCharCode(a%26+65)+b,a=Math.floor(a/ -26)-1;return b}function E(a,b){y===w&&(y=-1===C.serializeToString(f.parseXML(F["xl/worksheets/sheet1.xml"])).indexOf("xmlns:r"));f.each(b,function(b,c){if(f.isPlainObject(c))b=a.folder(b),E(b,c);else{if(y){var d=c.childNodes[0],e,h=[];for(e=d.attributes.length-1;0<=e;e--){var m=d.attributes[e].nodeName;var k=d.attributes[e].nodeValue;-1!==m.indexOf(":")&&(h.push({name:m,value:k}),d.removeAttribute(m))}e=0;for(m=h.length;e'+c),c=c.replace(/_dt_b_namespace_token_/g,":"),c=c.replace(/xmlns:NS[\d]+="" NS[\d]+:/g,""));c=c.replace(/<([^<>]*?) xmlns=""([^<>]*?)>/g,"<$1 $2>");a.file(b,c)}})}function r(a,b,d){var c=a.createElement(b);d&&(d.attr&&f(c).attr(d.attr),d.children&&f.each(d.children,function(a,b){c.appendChild(b)}),null!==d.text&&d.text!==w&&c.appendChild(a.createTextNode(d.text))); -return c}function L(a,b){var d=a.header[b].length;a.footer&&a.footer[b].length>d&&(d=a.footer[b].length);for(var c=0,f=a.body.length;cd&&(d=e);if(401*a[1]?!0:!1};try{var C=new XMLSerializer,y}catch(a){}var F={"_rels/.rels":'', -"xl/_rels/workbook.xml.rels":'',"[Content_Types].xml":'', -"xl/workbook.xml":'', -"xl/worksheets/sheet1.xml":'',"xl/styles.xml":''}, -K=[{match:/^\-?\d+\.\d%$/,style:60,fmt:function(a){return a/100}},{match:/^\-?\d+\.?\d*%$/,style:56,fmt:function(a){return a/100}},{match:/^\-?\$[\d,]+.?\d*$/,style:57},{match:/^\-?£[\d,]+.?\d*$/,style:58},{match:/^\-?€[\d,]+.?\d*$/,style:59},{match:/^\-?\d+$/,style:65},{match:/^\-?\d+\.\d{2}$/,style:66},{match:/^\([\d,]+\)$/,style:61,fmt:function(a){return-1*a.replace(/[\(\)]/g,"")}},{match:/^\([\d,]+\.\d{2}\)$/,style:62,fmt:function(a){return-1*a.replace(/[\(\)]/g,"")}},{match:/^\-?[\d,]+$/,style:63}, -{match:/^\-?[\d,]+\.\d{2}$/,style:64}];v.ext.buttons.copyHtml5={className:"buttons-copy buttons-html5",text:function(a){return a.i18n("buttons.copy","Copy")},action:function(a,b,d,c){this.processing(!0);var g=this;a=I(b,c);var e=b.buttons.exportInfo(c),h=H(c),m=a.str;d=f("
").css({height:1,width:1,overflow:"hidden",position:"fixed",top:0,left:0});e.title&&(m=e.title+h+h+m);e.messageTop&&(m=e.messageTop+h+h+m);e.messageBottom&&(m=m+h+h+e.messageBottom);c.customize&&(m=c.customize(m,c,b));c=f("