diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt
index 7e9650d18c..50d4b78c33 100644
--- a/pandora_console/extras/delete_files/delete_files.txt
+++ b/pandora_console/extras/delete_files/delete_files.txt
@@ -74,6 +74,10 @@ enterprise/extensions/ipam
enterprise/extensions/disabled/visual_console_manager.php
enterprise/extensions/visual_console_manager.php
pandora_console/extensions/net_tools.php
+enterprise/godmode/agentes/module_manager_editor_web.php
+enterprise/include/ajax/web_server_module_debug.php
+enterprise/include/class/WebServerModuleDebug.class.php
+enterprise/include/styles/WebServerModuleDebug.css
include/lib/WSManager.php
include/lib/WebSocketServer.php
include/lib/WebSocketUser.php
diff --git a/pandora_console/godmode/agentes/module_manager.php b/pandora_console/godmode/agentes/module_manager.php
index d8dd0eeef2..335017ab51 100644
--- a/pandora_console/godmode/agentes/module_manager.php
+++ b/pandora_console/godmode/agentes/module_manager.php
@@ -1,22 +1,38 @@
';
} else {
echo '
';
$network_available = db_get_sql(
'SELECT count(*)
FROM tserver
- WHERE server_type = 1'
+ WHERE server_type = '.SERVER_TYPE_NETWORK
);
// POSTGRESQL AND ORACLE COMPATIBLE.
$wmi_available = db_get_sql(
'SELECT count(*)
FROM tserver
- WHERE server_type = 6'
+ WHERE server_type = '.SERVER_TYPE_WMI
);
// POSTGRESQL AND ORACLE COMPATIBLE.
$plugin_available = db_get_sql(
'SELECT count(*)
FROM tserver
- WHERE server_type = 4'
+ WHERE server_type = '.SERVER_TYPE_PLUGIN
);
// POSTGRESQL AND ORACLE COMPATIBLE.
$prediction_available = db_get_sql(
'SELECT count(*)
FROM tserver
- WHERE server_type = 5'
+ WHERE server_type = '.SERVER_TYPE_PREDICTION
+);
+// POSTGRESQL AND ORACLE COMPATIBLE.
+$web_available = db_get_sql(
+ 'SELECT count(*)
+FROM tserver
+WHERE server_type = '.SERVER_TYPE_WEB
);
// POSTGRESQL AND ORACLE COMPATIBLE.
// Development mode to use all servers.
@@ -122,6 +144,10 @@ if ($prediction_available) {
$modules['predictionserver'] = __('Create a new prediction server module');
}
+if ($web_available) {
+ $modules['webserver'] = __('Create a new web Server module');
+}
+
if (enterprise_installed()) {
set_enterprise_module_types($modules);
}
@@ -298,6 +324,7 @@ if ($module_action === 'delete') {
switch ($config['dbtype']) {
case 'mysql':
case 'postgresql':
+ default:
$result = db_process_sql_delete(
'tagente_estado',
['id_agente_modulo' => $id_agent_module_del]
@@ -388,10 +415,8 @@ if ($module_action === 'delete') {
}
}
-
// Check for errors.
- if ($error != 0) {
- } else {
+ if ((int) $error == 0) {
$count_correct_delete_modules++;
}
}
@@ -489,6 +514,7 @@ switch ($sortField) {
switch ($config['dbtype']) {
case 'mysql':
case 'postgresql':
+ default:
$order[] = [
'field' => 'tagente_modulo.nombre',
'order' => 'ASC',
@@ -509,6 +535,7 @@ switch ($sortField) {
switch ($config['dbtype']) {
case 'mysql':
case 'postgresql':
+ default:
$order[] = [
'field' => 'tagente_modulo.nombre',
'order' => 'DESC',
@@ -523,6 +550,10 @@ switch ($sortField) {
break;
}
break;
+
+ default:
+ // Do none.
+ break;
}
break;
@@ -543,6 +574,10 @@ switch ($sortField) {
'order' => 'DESC',
];
break;
+
+ default:
+ // Do none.
+ break;
}
break;
@@ -563,6 +598,10 @@ switch ($sortField) {
'order' => 'DESC',
];
break;
+
+ default:
+ // Do none.
+ break;
}
break;
@@ -583,6 +622,10 @@ switch ($sortField) {
'order' => 'DESC',
];
break;
+
+ default:
+ // Do none.
+ break;
}
break;
@@ -598,6 +641,7 @@ switch ($sortField) {
switch ($config['dbtype']) {
case 'mysql':
case 'postgresql':
+ default:
$order[] = [
'field' => 'nombre',
'order' => 'ASC',
@@ -622,7 +666,7 @@ if (!empty($order)) {
$first = true;
foreach ($order as $ord) {
- if ($first) {
+ if ($first === true) {
$first = false;
} else {
$order_sql .= ',';
@@ -635,31 +679,35 @@ foreach ($order as $ord) {
$limit = (int) $config['block_size'];
$offset = (int) get_parameter('offset');
-$params = ($checked) ? 'tagente_modulo.*, tmodule_group.*' : implode(
- ',',
- [
- 'tagente_modulo.id_agente_modulo',
- 'id_tipo_modulo',
- 'descripcion',
- 'nombre',
- 'max',
- 'min',
- 'module_interval',
- 'id_modulo',
- 'id_module_group',
- 'disabled',
- 'max_warning',
- 'min_warning',
- 'str_warning',
- 'max_critical',
- 'min_critical',
- 'str_critical',
- 'quiet',
- 'critical_inverse',
- 'warning_inverse',
- 'id_policy_module',
- ]
-);
+if ((bool) $checked === true) {
+ $params = 'tagente_modulo.*, tmodule_group.*';
+} else {
+ $params = implode(
+ ',',
+ [
+ 'tagente_modulo.id_agente_modulo',
+ 'id_tipo_modulo',
+ 'descripcion',
+ 'nombre',
+ 'max',
+ 'min',
+ 'module_interval',
+ 'id_modulo',
+ 'id_module_group',
+ 'disabled',
+ 'max_warning',
+ 'min_warning',
+ 'str_warning',
+ 'max_critical',
+ 'min_critical',
+ 'str_critical',
+ 'quiet',
+ 'critical_inverse',
+ 'warning_inverse',
+ 'id_policy_module',
+ ]
+ );
+}
$where = sprintf('delete_pending = 0 AND id_agente = %s', $id_agente);
@@ -686,7 +734,11 @@ if (isset($config['paginate_module'])) {
if ($paginate_module) {
if (!isset($limit_sql)) {
- $limit_sql = " LIMIT $offset, $limit ";
+ $limit_sql = sprintf(
+ 'LIMIT %s, %s',
+ $offset,
+ $limit
+ );
}
} else {
$limit_sql = '';
@@ -732,7 +784,13 @@ if ($modules === false) {
}
// Prepare pagination.
-$url = '?'.'sec=gagente&'.'tab=module&'.'sec2=godmode/agentes/configurar_agente&'.'id_agente='.$id_agente.'&'.'sort_field='.$sortField.'&'.'&sort='.$sort.'&'.'search_string='.urlencode($search_string);
+$url = sprintf(
+ '?sec=gagente&tab=module&sec2=godmode/agentes/configurar_agente&id_agente=%s&sort_field=%s&sort=%s&search_string=%s',
+ $id_agente,
+ $sortField,
+ $sort,
+ urlencode($search_string)
+);
if ($paginate_module) {
ui_pagination($total_modules, $url);
diff --git a/pandora_console/godmode/agentes/module_manager_editor.php b/pandora_console/godmode/agentes/module_manager_editor.php
index c350866cf0..1310fa80bb 100644
--- a/pandora_console/godmode/agentes/module_manager_editor.php
+++ b/pandora_console/godmode/agentes/module_manager_editor.php
@@ -682,6 +682,22 @@ switch ($moduletype) {
include 'module_manager_editor_wmi.php';
break;
+ case 'webserver':
+ case MODULE_WEB:
+ $moduletype = MODULE_WEB;
+ // Remove content of $ip_target when it is ip_agent because
+ // it is used as HTTP auth (server) ....ONLY IN NEW MODULE!!!
+ if (empty($id_agent_module)
+ && ($ip_target === agents_get_address($id_agente))
+ ) {
+ $ip_target = '';
+ }
+
+ $categories = [9];
+ include 'module_manager_editor_common.php';
+ include 'module_manager_editor_web.php';
+ break;
+
// WARNING: type 7 is reserved on enterprise.
default:
if (enterprise_include(
diff --git a/pandora_console/godmode/agentes/module_manager_editor_web.php b/pandora_console/godmode/agentes/module_manager_editor_web.php
new file mode 100644
index 0000000000..3d02289160
--- /dev/null
+++ b/pandora_console/godmode/agentes/module_manager_editor_web.php
@@ -0,0 +1,468 @@
+ 'modal',
+ 'style' => 'display: none;',
+ ]
+);
+
+require_once $config['homedir'].'/include/ajax/web_server_module_debug.php';
+
+define('ID_NETWORK_COMPONENT_TYPE', 7);
+
+if (!$tcp_port && !$id_agent_module) {
+ $tcp_port = 80;
+}
+
+// plugin_server is the browser id
+if ($plugin_user == '' && !$id_agent_module) {
+ $plugin_user = get_product_name().' / Webcheck';
+}
+
+// plugin_server is the referer
+if ($plugin_pass == '' && !$id_agent_module) {
+ $plugin_pass = 1;
+}
+
+if (empty($update_module_id)) {
+ // Function in module_manager_editor_common.php
+ add_component_selection(ID_NETWORK_COMPONENT_TYPE);
+} else {
+ // TODO: Print network component if available
+}
+
+$data = [];
+$data[0] = __('Web checks');
+
+$adopt = false;
+if (isset($id_agent_module)) {
+ $adopt = enterprise_hook('policies_is_module_adopt', [$id_agent_module]);
+}
+
+$id_policy_module = (int) get_parameter('id_policy_module', '');
+if ($id_policy_module) {
+ $module = enterprise_hook('policies_get_module', [$id_policy_module]);
+ $plugin_parameter = $module['plugin_parameter'];
+}
+
+if ((bool) $adopt === false) {
+ $data[1] = html_print_textarea(
+ 'plugin_parameter',
+ 15,
+ 65,
+ $plugin_parameter,
+ $disabledTextBecauseInPolicy,
+ true
+ );
+} else {
+ $data[1] = html_print_textarea(
+ 'plugin_parameter',
+ 15,
+ 65,
+ $plugin_parameter,
+ false,
+ true
+ );
+}
+
+$table_simple->colspan['web_checks'][1] = 2;
+
+// Disable debug button if module has not started.
+if ($id_agent_module > 0
+ && db_get_value_filter(
+ 'debug_content',
+ 'tagente_modulo',
+ ['id_agente_modulo' => $id_agent_module]
+ ) !== null
+) {
+ $disableDebug = false;
+ $hintDebug = __('Debug remotely this module');
+} else {
+ $disableDebug = true;
+ $hintDebug = __('Debug this module once it has been initialized');
+}
+
+$suc_err_check = ' '.html_print_image('/images/ok.png', true).'';
+$suc_err_check .= ' '.html_print_image('/images/error_red.png', true).'';
+$data[2] = html_print_button(
+ __('Load basic'),
+ 'btn_loadbasic',
+ false,
+ '',
+ 'class="sub config"',
+ true
+).ui_print_help_tip(__('Load a basic structure on Web Checks'), true);
+$data[2] .= '
'.html_print_button(
+ __('Check'),
+ 'btn_checkconf',
+ false,
+ '',
+ 'class="sub upd"',
+ true
+).ui_print_help_tip(__('Check the correct structure of the WebCheck'), true).$suc_err_check;
+$data[2] .= '
'.html_print_button(
+ __('Debug'),
+ 'btn_debugModule',
+ $disableDebug,
+ '',
+ 'class="sub config" onClick="loadDebugWindow()"',
+ true
+).ui_print_help_tip($hintDebug, true);
+
+
+push_table_simple($data, 'web_checks');
+
+$http_checks_type = [
+ 0 => 'Anyauth',
+ 1 => 'NTLM',
+ 2 => 'DIGEST',
+ 3 => 'BASIC',
+];
+
+$data = [];
+$data[0] = __('Check type');
+$data[1] = html_print_select($http_checks_type, 'tcp_port', $tcp_port, false, '', '', true, false, false);
+
+push_table_advanced($data, 'web_0');
+
+$data = [];
+$data[0] = __('Requests');
+$data[1] = html_print_input_text('plugin_pass', $plugin_pass, '', 10, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+$data[2] = '';
+$data[3] = __('Agent browser id');
+$data[4] = html_print_input_text('plugin_user', $plugin_user, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+
+push_table_advanced($data, 'web_1');
+
+$data = [];
+$data[0] = __('HTTP auth (login)');
+$data[1] = html_print_input_text('http_user', $plugin_parameter_http_user, '', 10, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+$data[2] = '';
+$data[3] = __('HTTP auth (password)');
+$data[4] = html_print_input_password('http_pass', $plugin_parameter_http_pass, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+
+push_table_advanced($data, 'web_2');
+
+$data = [];
+
+$data[0] = __('Proxy URL');
+$data[1] = html_print_input_text('snmp_oid', $snmp_oid, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+$data[2] = $data[3] = $data[4] = '';
+push_table_advanced($data, 'web_3');
+
+$data = [];
+
+$data[0] = __('Proxy auth (login)');
+$data[1] = html_print_input_text('tcp_send', $tcp_send, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+
+$data[2] = '';
+$data[3] = __('Proxy auth (pass)');
+$data[4] = html_print_input_password('tcp_rcv', $tcp_rcv, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+
+push_table_advanced($data, 'web_4');
+
+$data = [];
+
+$data[0] = __('Proxy auth (server)');
+$data[1] = html_print_input_text('ip_target', $ip_target, '', 30, 100, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+
+$data[2] = '';
+$data[3] = __('Proxy auth (realm)');
+$data[4] = html_print_input_text('snmp_community', $snmp_community, '', 30, 100, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy);
+
+push_table_advanced($data, 'web_5');
+
+// Add some strings to be used from javascript
+$texts = [
+ 'lines_before_begin' => __('First line must be "task_begin"'),
+ 'missed_begin' => __('Webchecks configuration is empty'),
+ 'missed_end' => __('Last line must be "task_end"'),
+ 'lines_after_end' => __('Last line must be "task_end"'),
+ 'unknown_token' => __("There is a line with a unknown token 'token_fail'."),
+ 'missed_get_post' => __("There isn't get or post"),
+ 'correct' => __('Web checks are built correctly'),
+];
+
+foreach ($texts as $code => $text) {
+ echo ''.$text.'';
+}
+?>
+
\ No newline at end of file
diff --git a/pandora_console/include/ajax/web_server_module_debug.php b/pandora_console/include/ajax/web_server_module_debug.php
new file mode 100644
index 0000000000..36d82165fe
--- /dev/null
+++ b/pandora_console/include/ajax/web_server_module_debug.php
@@ -0,0 +1,74 @@
+ '[WebServerModuleDebug]'.$e->getMessage() ]);
+ exit;
+ } else {
+ echo '[WebServerModuleDebug]'.$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. ['.$method.']');
+ }
+
+ // Stop any execution.
+ exit;
+} else {
+ // Run.
+ $obj->run();
+}
diff --git a/pandora_console/include/class/WebServerModuleDebug.class.php b/pandora_console/include/class/WebServerModuleDebug.class.php
new file mode 100644
index 0000000000..e0e6f23c84
--- /dev/null
+++ b/pandora_console/include/class/WebServerModuleDebug.class.php
@@ -0,0 +1,407 @@
+ 'noaccess']);
+ }
+
+ include 'general/noaccess.php';
+ exit;
+ }
+
+ // Parameter assigments.
+ $this->ajaxController = $ajaxController;
+ $this->query = '';
+ $this->idAgentModule = $idAgentModule;
+ // Hardcoded request timeout.
+ $this->requestTimeout = 15;
+
+ return $this;
+
+ }
+
+
+ /**
+ * Run Module Debug window.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ // Added all necessary basic files for QueryResult.
+ ui_require_css_file('ace');
+ ui_require_javascript_file('ace', 'include/javascript/ace/');
+ // Load Javascript.
+ $this->loadJS();
+ // CSS.
+ ui_require_css_file('wizard');
+ ui_require_css_file('discovery');
+ // Specific CSS for this feature.
+ ui_require_css_file('WebServerModuleDebug', '/include/styles/', true);
+
+ }
+
+
+ /**
+ * Show the modal with the QueryResult.
+ *
+ * @return void
+ */
+ public function showWebServerDebug()
+ {
+ // Show QueryResult editor.
+ ui_query_result_editor('webserverdebug');
+ // Spinner for wait loads.
+ html_print_div(
+ [
+ 'id' => 'WebServerDebugSpinner',
+ 'style' => 'visibility: hidden;',
+ 'content' => __('Performing query. Please wait.').' '.html_print_image('images/spinner.gif', true),
+ ]
+ );
+ ?>
+
+
+
+ $this->idAgentModule,
+ ]
+ );
+
+ $this->query = ($outputDebugQuery !== false) ? $outputDebugQuery : __('Please, wait for a first execution of module');
+
+ return $this->query;
+ }
+
+
+ /**
+ * Perform the cURL execution.
+ *
+ * @return void
+ * @throws Exception $e Error message.
+ */
+ public function executeCommand()
+ {
+ try {
+ $executionForPerform = io_safe_output(get_parameter('text'));
+ // If the execution comes empty.
+ if (empty($executionForPerform) === true) {
+ throw new Exception('Execution failed');
+ }
+
+ // For security reasons, only allow the 'curl' command.
+ $executionForPerform = strstr($executionForPerform, 'curl');
+ // Avoid pipes or concatenation of commands.
+ $unallowedChars = [
+ '|',
+ '&',
+ '||',
+ '&&',
+ ';',
+ '\n',
+ ];
+ $executionForPerform = str_replace(
+ $unallowedChars,
+ ' ',
+ $executionForPerform
+ );
+ // Set execution timeout.
+ $executionForPerform .= sprintf(
+ $executionForPerform.' -m %d',
+ $this->requestTimeout
+ );
+
+ // Perform the execution.
+ system($executionForPerform, $returnCode);
+ // If execution does not got well.
+ if ($returnCode != 0) {
+ switch ($returnCode) {
+ case '2':
+ throw new Exception('Failed to initialize. Review the syntax.');
+
+ case '3':
+ throw new Exception('URL malformed. The syntax was not correct.');
+
+ case '5':
+ throw new Exception('Couldn\'t resolve proxy. The given proxy host could not be resolved.');
+
+ case '6':
+ throw new Exception('Couldn\'t resolve host. The given remote host could not be resolved.');
+
+ case '7':
+ throw new Exception('Failed to connect to host.');
+
+ default:
+ throw new Exception('Failed getting data.');
+ }
+ }
+ } catch (Exception $e) {
+ // Show execution error message.
+ echo __($e->getMessage());
+ }
+
+ exit;
+ }
+
+
+ /**
+ * Loads JS and return code.
+ *
+ * @return string
+ */
+ public function loadJS()
+ {
+ $str = '';
+ ob_start();
+ ?>
+
+
+
+ 0x01;
@@ -123,6 +124,7 @@ sub pandora_startup () {
push (@Servers, new PandoraFMS::WMIServer (\%Config, $DBH));
push (@Servers, new PandoraFMS::PluginServer (\%Config, $DBH));
push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH));
+ push (@Servers, new PandoraFMS::WebServer (\%Config, $DBH));
} else {
# Metaconsole service modules are run by the prediction server
push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH));
diff --git a/pandora_server/conf/pandora_server.conf.new b/pandora_server/conf/pandora_server.conf.new
index 2b80300950..e5f9f1b328 100644
--- a/pandora_server/conf/pandora_server.conf.new
+++ b/pandora_server/conf/pandora_server.conf.new
@@ -424,11 +424,11 @@ update_parent 1
# openstreetmaps_description 1
-# Enable (1) or disable (0) Pandora FMS Web Server/Goliat (PANDORA FMS ENTERPRISE ONLY).
+# Enable (1) or disable (0) Pandora FMS Web Server/Goliat.
webserver 1
-# Number of threads for the Web Server/Goliat (PANDORA FMS ENTERPRISE ONLY).
+# Number of threads for the Web Server/Goliat.
web_threads 1
diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm
new file mode 100755
index 0000000000..63fe5ca5de
--- /dev/null
+++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm
@@ -0,0 +1,365 @@
+##################################################################################
+# Goliath Tools CURL Module
+##################################################################################
+# Copyright (c) 2013-2021 Artica Soluciones Tecnologicas S.L
+# This code is not free or OpenSource. Please don't redistribute.
+##################################################################################
+
+package PandoraFMS::Goliat::GoliatCURL;
+
+use PandoraFMS::Goliat::GoliatTools;
+
+use strict;
+use warnings;
+use Data::Dumper;
+use PandoraFMS::DB;
+
+use IO::Socket::INET6;
+use URI::Escape;
+use Time::Local;
+use Time::HiRes qw ( gettimeofday );
+
+# Japanese encoding support
+use Encode::Guess qw/euc-jp shiftjis iso-2022-jp/;
+
+require Exporter;
+
+our @ISA = ("Exporter");
+our %EXPORT_TAGS = ( 'all' => [ qw() ] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw(
+ g_http_task
+ @task_requests
+ @task_reqsec
+ @task_fails
+ @task_time
+ @task_end
+ @task_sessions
+ @task_ssec
+ @task_get_string
+ @task_get_content
+ @task_session_fails
+);
+
+our @task_requests;
+our @task_reqsec;
+our @task_fails ;
+our @task_time;
+our @task_end;
+our @task_sessions;
+our @task_ssec;
+our @task_get_string;
+our @task_get_content;
+our @task_session_fails;
+our $goliat_abort;
+
+# Returns a string than can be safely used as a command line parameter for CURL
+sub safe_param ($) {
+ my $string = shift;
+
+ $string =~ s/'/"/g;
+ return "'" . $string . "'";
+}
+
+sub g_http_task {
+ my ( $config, $thread_id, @work_list ) = @_;
+ my ( $ax, $bx, $cx ); # used in FOR loop
+ my ( $ttime1, $ttime2, $ttime_tot );
+
+ my $resp; # HTTP Response
+ my $total_requests = 0;
+ my $total_valid_requests = 0;
+ my $total_invalid_request = 0;
+ my $cookie_file = "/tmp/gtc_".$thread_id."_".g_trash_ascii (3);
+ my $check_string = 1;
+ my $get_string = "";
+ my $get_content = "";
+ my $get_content_advanced = "";
+ my $timeout = 10;
+
+ #my $ua = new LWP::UserAgent;
+ $task_requests [$thread_id] = 0 ;
+ $task_sessions [$thread_id] = 0 ;
+ $task_reqsec[$thread_id] = 0;
+ $task_fails[$thread_id] = 0;
+ $task_session_fails[$thread_id] = 0;
+ $task_ssec[$thread_id] = 0;
+ $task_end[$thread_id] = 0;
+ $task_time[$thread_id] = 0;
+ $task_get_string[$thread_id] = "";
+ $task_get_content[$thread_id] = "";
+
+ # Set command line options for CURL
+ my $curl_opts;
+
+ # Follow redirects
+ $curl_opts .= " --location-trusted";
+
+ # User agent
+ if ($config->{"agent"} ne '') {
+ $curl_opts .= " -A " . safe_param($config->{"agent"})
+ }
+
+ # Prevent pages from being cached
+ $curl_opts .= " -H 'Pragma: no-cache'";
+
+ # Timeout
+ if (defined ($config->{"timeout"}) && $config->{"timeout"} > 0) {
+ $timeout = $config->{"timeout"};
+ }
+
+ # Maximum file size
+ if (defined($config->{"maxsize"}) && $config->{"maxsize"} > 0) {
+ $curl_opts .= " --max-filesize " . $config->{"maxsize"};
+ }
+
+ # Disable SSL certificate host verification
+ $curl_opts .= " -k";
+
+ # Proxy
+ if ($config->{'proxy'} ne ""){
+ $curl_opts .= " -x " . safe_param($config->{'proxy'});
+ }
+
+ # Proxy HTTP authentication
+ if ($config->{'auth_user'} ne "") {
+ $curl_opts .= " --proxy-anyauth -U " . safe_param($config->{'auth_user'} . ':' . $config->{'auth_pass'});
+ }
+
+ # Delete existing cookies
+ my $cookie_carry_on = 0;
+ if ( -e $cookie_file){
+ unlink ($cookie_file);
+ }
+
+ $ttime1 = Time::HiRes::gettimeofday();
+ for ($ax = 0; $ax != $config->{'retries'}; $ax++){
+ for ($bx = 0; $bx < $config->{"work_items"}; $bx++){
+ if ($config->{'con_delay'} > 0){
+ sleep ($config->{'con_delay'});
+ }
+ $total_requests++;
+ # Start to count!
+ $check_string = 1;
+ # Prepare parameters
+ my $task_curl_opts = $curl_opts;
+ my $params = "";
+ $cx = 0;
+ while (defined($work_list[$bx]->{'variable_name'}[$cx])){
+ if ($cx > 0){
+ $params = $params."&";
+ }
+ $params = $params . $work_list[$bx]->{'variable_name'}[$cx] . "=" . uri_escape($work_list[$bx]->{'variable_value'}[$cx]);
+ $cx++;
+ }
+
+ # Cookie carry on
+ if (defined ($work_list[$bx]->{'cookie'}) && $work_list[$bx]->{'cookie'} == 1){
+ $cookie_carry_on = 1;
+ }
+
+ if ($cookie_carry_on == 1) {
+ $task_curl_opts .= " -c " . safe_param ($cookie_file);
+ $task_curl_opts .= " -b " . safe_param ($cookie_file);
+ }
+
+ # HTTP authentication
+ if ($work_list[$bx]->{'http_auth_user'} ne "" && $work_list[$bx]->{'http_auth_pass'} ne "") {
+
+ if($config->{'http_check_type'} == 0){
+ $task_curl_opts .= " --anyauth -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'});
+ }
+
+ if ($config->{'http_check_type'} == 1) {
+ $task_curl_opts .= " --ntlm -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'});
+ }
+
+ if ($config->{'http_check_type'} == 2) {
+ $task_curl_opts .= " --digest -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'});
+ }
+
+ if ($config->{'http_check_type'} == 3) {
+ $task_curl_opts .= " --basic -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'});
+ }
+
+
+ }
+
+ # GET
+ if ($work_list[$bx]->{'type'} eq "GET"){
+ $task_curl_opts .= " -H 'Accept: text/html'";
+ if ($cx > 0){
+ $params = $work_list[$bx]->{'url'} . "?" . $params;
+ } else {
+ $params = $work_list[$bx]->{'url'};
+ }
+
+ $resp = curl ($config->{"plugin_exec"}, $timeout, $task_curl_opts, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}, $config->{"moduleId"}, $config->{"dbh"});
+
+ # POST
+ } elsif ($work_list[$bx]->{'type'} eq "POST") {
+ $task_curl_opts .= " -d " . safe_param($params);
+ $task_curl_opts .= " -H 'Content-type: application/x-www-form-urlencoded'";
+ $resp = curl ($config->{"plugin_exec"}, $timeout, $task_curl_opts, $work_list[$bx]->{'url'}, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}, $config->{"moduleId"}, $config->{"dbh"});
+
+ # HEAD
+ } else {
+ $task_curl_opts .= " -I";
+ if ($cx > 0){
+ $params = $work_list[$bx]->{'url'} . "?" . uri_escape($params);
+ } else {
+ $params = $work_list[$bx]->{'url'};
+ }
+ $resp = curl ($config->{"plugin_exec"}, $timeout, $task_curl_opts, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}, $config->{"moduleId"}, $config->{"dbh"});
+ }
+
+ # Get string ?
+ if (defined($work_list[$bx]->{'get_string'})) {
+ my $temp = $work_list[$bx]->{'get_string'};
+ if ($resp =~ m/($temp)/) {
+ $task_get_string[$thread_id] = $1;
+ }
+ }
+
+ # Get response ?
+ if ($work_list[$bx]->{'get_content_advanced'} ne "") {
+ my $temp = $work_list[$bx]->{'get_content_advanced'};
+ if ($resp =~ m/$temp/) {
+ $task_get_content[$thread_id] = $1 if defined ($1);
+ }
+ } elsif ($work_list[$bx]->{'get_content'} ne "") {
+ my $temp = $work_list[$bx]->{'get_content'};
+ if ($resp =~ m/($temp)/) {
+ $task_get_content[$thread_id] = $1;
+ }
+ } else {
+ $task_get_content[$thread_id] = $resp;
+ }
+
+ # Resource bashing
+ #if ((defined($work_list[$bx]->{'get_resources'})) && ($work_list[$bx]->{'get_resources'} == 1)){
+ # $total_requests = g_get_all_links ($config, $ua, $resp, $total_requests, $work_list[$bx]->{'url'}, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'});
+ #}
+
+ # CHECKSTRING check
+ $cx = 0;
+ while (defined($work_list[$bx]->{'checkstring'}[$cx])) {
+ my $match_string = $work_list[$bx]->{'checkstring'}[$cx];
+ my $as_string = $resp;
+ my $guess = Encode::Guess::guess_encoding($as_string);
+ if (ref $guess) {
+ $as_string = $guess->decode($as_string);
+ }
+ unless (utf8::is_utf8($match_string)) {
+ utf8::decode($match_string);
+ }
+
+ if ( $as_string =~ m/$match_string/i ){
+ $total_valid_requests++;
+ } else {
+ $total_invalid_request++;
+ $bx = $config->{"work_items"}; # Abort session remaining request
+ $check_string=0;
+ }
+ $cx++;
+ }
+
+ # CHECKNOTSTRING check
+ $cx = 0;
+ while (defined($work_list[$bx]->{'checknotstring'}[$cx])) {
+ my $match_string = $work_list[$bx]->{'checknotstring'}[$cx];
+ my $as_string = $resp;
+
+ my $guess = Encode::Guess::guess_encoding($as_string);
+ if (ref $guess) {
+ $as_string = $guess->decode($as_string);
+ }
+ unless (utf8::is_utf8($match_string)) {
+ utf8::decode($match_string);
+ }
+
+ if ( $as_string !~ m/$match_string/i ){
+ $total_valid_requests++;
+ } else {
+ $total_invalid_request++;
+ $bx = $config->{"work_items"}; # Abort session remaining request
+ $check_string=0;
+ }
+ $cx++;
+ }
+
+ # End just now by pressing CTRL-C or Kill Signal !
+ #if ($goliat_abort == 1){
+ #$ax = $config->{'retries'};
+ #$bx = $config->{'items'};
+ #goto END_LOOP;
+ #}
+ } #main work_detail loop
+ $ttime2 = Time::HiRes::gettimeofday();
+
+ $ttime_tot = $ttime2 - $ttime1; # Total time for this task
+ $task_time[$thread_id] = $ttime_tot;
+ $task_requests [$thread_id] = $total_requests;
+ if ($ttime_tot > 0 ){
+ $task_reqsec[$thread_id] = $total_requests / $ttime_tot;
+ } else {
+ $task_reqsec[$thread_id] = $total_requests;
+ }
+ $task_fails[$thread_id] = $total_invalid_request;
+ if ($check_string == 0){
+ $task_session_fails[$thread_id]++
+ }
+ $task_sessions [$thread_id]++;
+ if ($task_sessions [$thread_id] > 0 ){
+ $task_ssec[$thread_id] = $ttime_tot / $task_sessions [$thread_id];
+ } else {
+ $task_ssec[$thread_id] = $task_sessions[$thread_id];
+ }
+ sleep $config->{'ses_delay'};
+ }
+END_LOOP:
+
+ if ( -f $cookie_file){
+ unlink ($cookie_file);
+ }
+
+ $task_end[$thread_id] = 1;
+}
+
+# Call CURL and return its output.
+sub curl {
+ my ($exec, $timeout, $curl_opts, $url, $headers, $debug, $moduleId, $dbh) = @_;
+
+ while (my ($header, $value) = each %{$headers}) {
+ $curl_opts .= " -H " . safe_param($header . ':' . $value);
+ }
+
+ my $cmd = "curl $curl_opts " . safe_param($url);
+ my $response = `"$exec" $timeout $cmd 2>/dev/null`;
+
+ # Curl command stored for live debugging feature.
+ set_update_agentmodule ($dbh, $moduleId, { 'debug_content' => $cmd }) if defined($dbh);
+
+ return $response if ($debug eq '');
+
+ # Debug
+ if (open (DEBUG, '>>', $debug . '.req')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $cmd;
+ print "\n";
+ close (DEBUG);
+ }
+ if (open (DEBUG, '>>', $debug . '.res')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $response;
+ print "\n";
+ close (DEBUG);
+ }
+ return $response;
+}
+
+# End of function declaration
+# End of defined Code
+
+1;
+__END__
diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm
new file mode 100755
index 0000000000..da3247c1e8
--- /dev/null
+++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm
@@ -0,0 +1,265 @@
+##########################################################################
+# Goliat Config package
+##########################################################################
+# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L
+# This code is not free or OpenSource. Please don't redistribute.
+##########################################################################
+
+package PandoraFMS::Goliat::GoliatConfig;
+
+use strict;
+use warnings;
+use PandoraFMS::Tools;
+use PandoraFMS::Goliat::GoliatTools;
+
+require Exporter;
+our @ISA = ("Exporter");
+our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw( g_help_screen
+ g_init
+ g_load_config );
+
+my $g_version = "1.0";
+my $g_build = "110929";
+our $VERSION = $g_version." ".$g_build;
+
+
+sub g_load_config {
+ my ( $config , $work_list )= @_ ;
+ my $archivo_cfg = $config->{'config_file'};
+ my $buffer_line;
+ my $task_block = 0;
+ my $commit_block = 0;
+ my $task_url = "";
+ my $task_cookie = 0;
+ my $task_resources = 1;
+ my $task_type = "";
+ my $task_headers = {};
+ my $task_debug = "";
+ my $http_auth_user = "";
+ my $http_auth_pass = "";
+ my $http_auth_realm = "";
+ my $http_auth_serverport = "";
+ my $get_string = "";
+ my $get_content = "";
+ my $get_content_advanced = "";
+ my @task_variable_name;
+ my @task_variable_value;
+ my @task_check_string;
+ my @task_check_not_string;
+ my $parametro;
+ my $temp1;
+
+ # Default options
+ $config->{'con_delay'} =0;
+ $config->{'ses_delay'} =0;
+ if (!defined($config->{'agent'})){
+ $config->{'agent'}="PandoraFMS/Goliat 4.0; Linux)";
+ }
+ if (!defined($config->{'proxy'})){
+ $config->{'proxy'}="";
+ }
+
+ if (!defined($config->{'retries'})){
+ $config->{'retries'} = 1;
+ }
+
+ if ((!is_numeric($config->{'retries'})) || ($config->{'retries'} == 0)){
+ $config->{'retries'} = 1;
+ }
+
+ $config->{'refresh'} = "5";
+ $config->{"max_depth"} = 25;
+ $config->{'log_file'}="/var/log/pandora/pandora_goliat.log";
+ $config->{'log_output'} = 0;
+
+ # Collect items from config file and put in an array
+ open (CFG, "< $archivo_cfg");
+ while (){
+ $buffer_line = $_;
+ if ($buffer_line =~ /^[a-zA-Z]/){ # begins with letters
+ $parametro = $buffer_line;
+ } else {
+ $parametro = "";
+ }
+ # Need to commit block ??
+ if (($commit_block == 1) && ($task_block == 1)) {
+ my %work_item;
+ $work_item{'url'} = $task_url;
+ $work_item{'cookie'} = $task_cookie;
+ $work_item{'type'} = $task_type;
+ $work_item{'get_resources'} = $task_resources;
+ $work_item{'get_string'} = $get_string;
+ $work_item{'get_content'} = $get_content;
+ $work_item{'get_content_advanced'} = $get_content_advanced;
+ $work_item{'http_auth_user'} = $http_auth_user;
+ $work_item{'http_auth_pass'} = $http_auth_pass;
+ $work_item{'http_auth_realm'} = $http_auth_realm;
+ $work_item{'http_auth_serverport'} = $http_auth_serverport;
+ $work_item{'headers'} = $task_headers;
+ $work_item{'debug'} = $task_debug;
+
+ my $ax=0;
+ while ($#task_check_string >= 0){
+ $temp1 = pop (@task_check_string);
+ $work_item{'checkstring'}[$ax] = $temp1;
+ $ax++;
+ }
+ $ax=0;
+ while ($#task_check_not_string >= 0){
+ $temp1 = pop (@task_check_not_string);
+ $work_item{'checknotstring'}[$ax] = $temp1;
+ $ax++;
+ }
+ $ax=0;
+ while ($#task_variable_name >= 0){
+ $temp1 = pop (@task_variable_name);
+ $work_item{'variable_name'}[$ax] = $temp1;
+ $ax++;
+ }
+ $ax=0;
+ while ($#task_variable_value >= 0){
+ $temp1 = pop (@task_variable_value);
+ $work_item{'variable_value'}[$ax] = $temp1;
+ $ax++;
+
+ }
+ push @{$work_list}, \%work_item;
+ $commit_block = 0;
+ $task_block = 0;
+ $task_url = "";
+ $task_cookie = 0;
+ $task_resources = 0;
+ $task_type = "";
+ $task_headers = {};
+ $task_debug = "";
+ $config->{"work_items"}++;
+ $commit_block = 0;
+ $task_block = 0;
+ $http_auth_user = "";
+ $http_auth_pass = "";
+ $http_auth_realm = "";
+ $get_string = "";
+ $get_content = "";
+ $get_content_advanced = "";
+ }
+ # ~~~~~~~~~~~~~~
+ # Main setup items
+ # ~~~~~~~~~~~~~~
+
+ if ($parametro =~ m/^task_begin/i) {
+ $task_block = 1;
+ }
+ elsif ($parametro =~ m/^task_end/i) {
+ $commit_block = 1;
+ }
+ elsif ($parametro =~ m/^ses_delay\s(.*)/i) {
+ $config->{'ses_delay'} = $1;
+ }
+ elsif ($parametro =~ m/^con_delay\s(.*)/i) {
+ $config->{'con_delay'} = $1;
+ }
+ elsif ($parametro =~ m/^agent\s(.*)/i) {
+ $config->{'agent'} = $1;
+ }
+ elsif ($parametro =~ m/^proxy\s(.*)/i) {
+ $config->{'proxy'} = $1;
+ }
+ elsif ($parametro =~ m/^max_depth\s(.*)/i) {
+ $config->{'max_depth'} = $1;
+ }
+ elsif ($parametro =~ m/^log_file\s(.*)/i) {
+ $config->{"log_file"} = $1;
+ }
+ elsif ($parametro =~ m/^log_output\s(.*)/i) {
+ $config->{"log_output"} = $1;
+ }
+ elsif ($parametro =~ m/^log_http\s(.*)/i) {
+ $config->{"log_http"} = $1;
+ }
+ elsif ($parametro =~ m/^retries\s(.*)/i) {
+ $config->{"retries"} = $1;
+ }
+ # ~~~~~~~~~~~~~~
+ # Task items
+ # ~~~~~~~~~~~~~~
+ elsif ($parametro =~ m/^variable_name\s(.*)/i) {
+ push (@task_variable_name, $1);
+ }
+ elsif ($parametro =~ m/^variable_value\s(.*)/i) {
+ push (@task_variable_value, $1);
+ }
+ elsif ($parametro =~ m/^check_string\s(.*)/i) {
+ push (@task_check_string, $1);
+ }
+ elsif ($parametro =~ m/^check_not_string\s(.*)/i) {
+ push (@task_check_not_string, $1);
+ }
+ elsif ($parametro =~ m/^get\s(.*)/i) {
+ $task_type = "GET";
+ $task_url = $1;
+ }
+ elsif ($parametro =~ m/^post\s(.*)/i) {
+ $task_type = "POST";
+ $task_url = $1;
+ }
+ elsif ($parametro =~ m/^head\s(.*)/i) {
+ $task_type = "HEAD";
+ $task_url = $1;
+ }
+ # New in 4.0 version
+ elsif ($parametro =~ m/^get_string\s(.*)/i) {
+ $get_string = $1;
+ }
+ elsif ($parametro =~ m/^get_content\s(.*)/i) {
+ $get_content = $1;
+ }
+ elsif ($parametro =~ m/^get_content_advanced\s(.*)/i) {
+ $get_content_advanced = $1;
+ }
+ elsif ($parametro =~ m/^http_auth_user\s(.*)/i) {
+ $http_auth_user = $1;
+ }
+ elsif ($parametro =~ m/^http_auth_pass\s(.*)/i) {
+ $http_auth_pass = $1;
+ }
+ elsif ($parametro =~ m/^http_auth_realm\s(.*)/i) {
+ $http_auth_realm = $1;
+ }
+ elsif ($parametro =~ m/^http_auth_serverport\s(.*)/i) {
+ $http_auth_serverport = $1;
+ }
+ elsif ($parametro =~ m/^cookie\s(.*)/i) {
+ if ($1 =~ m/1/i){
+ $task_cookie = 1;
+ } else {
+ $task_cookie = 0;
+ }
+ }
+ elsif ($parametro =~ m/^resource\s(.*)/i) {
+ if ($1 =~ m/1/i){
+ $task_resources = 1;
+ } else {
+ $task_resources = 0;
+ }
+ }
+ # New in 5.0 version
+ elsif ($parametro =~ m/^header\s+(\S+)\s(.*)/i) {
+ $task_headers->{$1} = $2;
+ }
+ elsif ($parametro =~ m/^debug\s+(.*)/i) {
+ $task_debug = $1;
+ }
+
+ }
+ close (CFG);
+}
+
+# End of function declaration
+# End of defined Code
+
+1;
+__END__
+
+
diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm
new file mode 100755
index 0000000000..3117ab1515
--- /dev/null
+++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm
@@ -0,0 +1,478 @@
+##################################################################################
+# Goliath Tools LWP Module
+##################################################################################
+# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L
+# This code is not free or OpenSource. Please don't redistribute.
+##################################################################################
+
+package PandoraFMS::Goliat::GoliatLWP;
+
+use PandoraFMS::Goliat::GoliatTools;
+
+use strict;
+use warnings;
+use Data::Dumper;
+
+use IO::Socket::INET6;
+use LWP::UserAgent;
+use LWP::ConnCache;
+use HTTP::Request::Common;
+use HTTP::Response;
+use HTML::TreeBuilder;
+use HTML::Element;
+use HTTP::Cookies;
+use URI::URL;
+use Time::Local;
+use Time::HiRes qw ( gettimeofday );
+
+# For IPv6 support in Net::HTTP.
+BEGIN {
+ $Net::HTTP::SOCKET_CLASS = 'IO::Socket::INET6';
+ require Net::HTTP;
+}
+
+# Japanese encoding support
+use Encode::Guess qw/euc-jp shiftjis iso-2022-jp/;
+
+require Exporter;
+
+our @ISA = ("Exporter");
+our %EXPORT_TAGS = ( 'all' => [ qw() ] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw(
+ g_http_task
+ @task_requests
+ @task_reqsec
+ @task_fails
+ @task_time
+ @task_end
+ @task_sessions
+ @task_ssec
+ @task_get_string
+ @task_get_content
+ @task_session_fails
+);
+
+our @task_requests;
+our @task_reqsec;
+our @task_fails;
+our @task_time;
+our @task_end;
+our @task_sessions;
+our @task_ssec;
+our @task_get_string;
+our @task_get_content;
+our @task_session_fails;
+our $goliat_abort;
+
+sub parse_html ($;$)
+{
+ my $p = $_[1];
+ $p = _new_tree_maker() unless $p;
+ $p->parse($_[0]);
+}
+
+
+sub parse_htmlfile ($;$)
+{
+ my($file, $p) = @_;
+ local(*HTML);
+ open(HTML, $file) or return undef;
+ $p = _new_tree_maker() unless $p;
+ $p->parse_file(\*HTML);
+}
+
+sub _new_tree_maker
+{
+ my $p = HTML::TreeBuilder->new(implicit_tags => 1,
+ ignore_unknown => 1,
+ ignore_text => 0,
+ 'warn' => 0,
+ );
+ $p->strict_comment(1);
+ $p;
+}
+
+
+sub g_http_task {
+ my ( $config, $thread_id, @work_list ) = @_;
+ my ( $ax, $bx, $cx ); # used in FOR loop
+ my ( $ttime1, $ttime2, $ttime_tot );
+
+ my $resp; # HTTP Response
+ my $total_requests = 0;
+ my $total_valid_requests = 0;
+ my $total_invalid_request = 0;
+ my $cookie_file = "/tmp/gtc_".$thread_id."_".g_trash_ascii (3);
+ my $check_string = 1;
+ my $get_string = "";
+ my $get_content = "";
+ my $get_content_advanced = "";
+
+ my $ua = new LWP::UserAgent;
+ $task_requests [$thread_id] = 0 ;
+ $task_sessions [$thread_id] = 0 ;
+ $task_reqsec[$thread_id] = 0;
+ $task_fails[$thread_id] = 0;
+ $task_session_fails[$thread_id] = 0;
+ $task_ssec[$thread_id] = 0;
+ $task_end[$thread_id] = 0;
+ $task_time[$thread_id] = 0;
+ $task_get_string[$thread_id] = "";
+ $task_get_content[$thread_id] = "";
+
+ $ua->agent($config->{"agent"});
+ $ua->protocols_allowed( ['http', 'https'] );
+ $ua->default_headers->push_header('pragma' => "no-cache");
+ $ua->timeout ($config->{"timeout"});
+ $ua->max_size($config->{"maxsize"});
+ $ua->use_alarm($config->{"alarm"});
+
+ # Disable SSL certificate host verification
+ if ($ua->can ('ssl_opts')) {
+ $ua->ssl_opts("verify_hostname" => 0);
+ }
+
+ # Set proxy
+
+ if ($config->{'proxy'} ne ""){
+ $ua->proxy(['http','https'], $config->{'proxy'});
+ }
+
+ # Set HTTP Proxy auth
+ if ($config->{'auth_user'} ne "") {
+ $ua->credentials(
+ $config->{'auth_server'},
+ $config->{'auth_realm'},
+ $config->{'auth_user'} => $config->{'auth_pass'} );
+ }
+
+ if ( -e $cookie_file){
+ unlink ($cookie_file);
+ }
+ my $cookies = HTTP::Cookies->new ('file' => $cookie_file, 'autosave' => '0');
+
+ $ttime1 = Time::HiRes::gettimeofday();
+ for ($ax = 0; $ax != $config->{'retries'}; $ax++){
+ for ($bx = 0; $bx < $config->{"work_items"}; $bx++){
+ if ($config->{'con_delay'} > 0){
+ sleep ($config->{'con_delay'});
+ }
+ $total_requests++;
+ # Start to count!
+ $check_string = 1;
+ # Prepare parameters
+ my $params = "";
+ $cx = 0;
+ while (defined($work_list[$bx]->{'variable_name'}[$cx])){
+ if ($cx > 0){
+ $params = $params."&";
+ }
+ $params = $params . $work_list[$bx]->{'variable_name'}[$cx] . "=" . $work_list[$bx]->{'variable_value'}[$cx];
+ $cx++;
+ }
+
+ if ( (defined($work_list[$bx]->{'http_auth_realm'})) && (defined($work_list[$bx]->{'http_auth_serverport'}))&& (defined($work_list[$bx]->{'http_auth_user'})) && (defined($work_list[$bx]->{'http_auth_pass'}))) {
+ if ($work_list[$bx]->{'http_auth_realm'} ne "") {
+ $ua->credentials(
+ $work_list[$bx]->{'http_auth_serverport'},
+ $work_list[$bx]->{'http_auth_realm'},
+ $work_list[$bx]->{'http_auth_user'} => $work_list[$bx]->{'http_auth_pass'}
+ );
+ }
+ }
+
+ # GET
+ if ($work_list[$bx]->{'type'} eq "GET"){
+ if ($cx > 0){
+ $params = $work_list[$bx]->{'url'} . "?" . $params;
+ } else {
+ $params = $work_list[$bx]->{'url'};
+ }
+ $resp = g_get_page ( $ua, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'});
+
+ # POST
+ } elsif ($work_list[$bx]->{'type'} eq "POST") {
+ $resp = g_post_page ( $ua, $work_list[$bx]->{'url'}, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'});
+
+ # HEAD
+ } else {
+ if ($cx > 0){
+ $params = $work_list[$bx]->{'url'} . "?" . $params;
+ } else {
+ $params = $work_list[$bx]->{'url'};
+ }
+ $resp = g_head_page ( $ua, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'});
+ }
+
+ # Check for errors.
+ if ($resp->code() == 500) {
+ $total_invalid_request++;
+ $bx = $config->{"work_items"};
+ $check_string=0;
+ last;
+ }
+
+ # Get string ?
+ if (defined($work_list[$bx]->{'get_string'})) {
+ my $as_string = $resp->as_string;
+ my $temp = $work_list[$bx]->{'get_string'};
+ if ($as_string =~ m/($temp)/) {
+ $task_get_string[$thread_id] = $1;
+ }
+ }
+
+ # Get response ?
+ if ($work_list[$bx]->{'get_content_advanced'} ne "") {
+ my $content = $resp->decoded_content;
+ my $temp = $work_list[$bx]->{'get_content_advanced'};
+ if ($content =~ m/$temp/) {
+ $task_get_content[$thread_id] = $1 if defined ($1);
+ }
+ } elsif ($work_list[$bx]->{'get_content'} ne "") {
+ my $content = $resp->decoded_content;
+ my $temp = $work_list[$bx]->{'get_content'};
+ if ($content =~ m/($temp)/) {
+ $task_get_content[$thread_id] = $1;
+ }
+ }
+
+ # Resource bashing
+ if ((defined($work_list[$bx]->{'get_resources'})) && ($work_list[$bx]->{'get_resources'} == 1)){
+ $total_requests = g_get_all_links ($config, $ua, $resp, $total_requests, $work_list[$bx]->{'url'}, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'});
+ }
+
+ # CHECKSTRING check
+ $cx = 0;
+ while (defined($work_list[$bx]->{'checkstring'}[$cx])) {
+ my $match_string = $work_list[$bx]->{'checkstring'}[$cx];
+ my $as_string = $resp->as_string;
+
+ my $guess = Encode::Guess::guess_encoding($as_string);
+ if (ref $guess) {
+ $as_string = $guess->decode($as_string);
+ }
+ unless (utf8::is_utf8($match_string)) {
+ utf8::decode($match_string);
+ }
+
+ if ( $as_string =~ m/$match_string/i ){
+ $total_valid_requests++;
+ } else {
+ $total_invalid_request++;
+ $bx = $config->{"work_items"}; # Abort session remaining request
+ $check_string=0;
+ }
+ $cx++;
+ }
+
+ # CHECKNOTSTRING check
+ $cx = 0;
+ while (defined($work_list[$bx]->{'checknotstring'}[$cx])) {
+ my $match_string = $work_list[$bx]->{'checknotstring'}[$cx];
+ my $as_string = $resp->as_string;
+
+ my $guess = Encode::Guess::guess_encoding($as_string);
+ if (ref $guess) {
+ $as_string = $guess->decode($as_string);
+ }
+ unless (utf8::is_utf8($match_string)) {
+ utf8::decode($match_string);
+ }
+
+ if ( $as_string !~ m/$match_string/i ){
+ $total_valid_requests++;
+ } else {
+ $total_invalid_request++;
+ $bx = $config->{"work_items"}; # Abort session remaining request
+ $check_string=0;
+ }
+ $cx++;
+ }
+
+ # Cookie carry on
+ if (defined ($work_list[$bx]->{'cookie'}) && $work_list[$bx]->{'cookie'} == 1){
+ $cookies->extract_cookies($resp);
+ $ua->cookie_jar($cookies);
+ }
+
+ # End just now by pressing CTRL-C or Kill Signal !
+ #if ($goliat_abort == 1){
+ #$ax = $config->{'retries'};
+ #$bx = $config->{'items'};
+ #goto END_LOOP;
+ #}
+ } #main work_detail loop
+ $ttime2 = Time::HiRes::gettimeofday();
+
+ $ttime_tot = $ttime2 - $ttime1; # Total time for this task
+ $task_time[$thread_id] = $ttime_tot;
+ $task_requests [$thread_id] = $total_requests;
+ if ($ttime_tot > 0 ){
+ $task_reqsec[$thread_id] = $total_requests / $ttime_tot;
+ } else {
+ $task_reqsec[$thread_id] = $total_requests;
+ }
+ $task_fails[$thread_id] = $total_invalid_request;
+ if ($check_string == 0){
+ $task_session_fails[$thread_id]++
+ }
+ $task_sessions [$thread_id]++;
+ if ($task_sessions [$thread_id] > 0 ){
+ $task_ssec[$thread_id] = $ttime_tot / $task_sessions [$thread_id];
+ } else {
+ $task_ssec[$thread_id] = $task_sessions[$thread_id];
+ }
+ sleep $config->{'ses_delay'};
+ }
+END_LOOP:
+
+ $cookies->clear;
+
+ if ( -f $cookie_file){
+ unlink ($cookie_file);
+ }
+
+ $task_end[$thread_id] = 1;
+}
+
+
+sub g_get_all_links {
+ my ($config, $ua, $response, $counter, $myurl, $headers, $debug) = @_;
+ my $html;
+
+ if ($response->is_success) {
+ $html = $response->content;
+ } else {
+ return $counter;
+ }
+ # Beware this funcion, needs to be destroyed after use it !!!
+ my $parsed_html = parse_html($html);
+ #$ua->conn_cache(LWP::ConnCache->new());
+
+ my @url_list;
+ my $url = "";
+ my $link;
+ my $full_url;
+
+ for (@{ $parsed_html->extract_links( ) }) {
+ $link=$_->[0];
+ if (($link =~ m/.png/i) || ($link =~ m/.gif/i) || ($link =~ m/.htm/i) ||
+ ($link =~ m/.html/i) || ($link =~ m/.pdf/i) || ($link =~ m/.jpg/i)
+ || ($link =~ m/.ico/i)){
+ $url = new URI::URL $link;
+ $full_url = $url->abs($myurl);
+ @url_list = $full_url;
+ }
+
+ }
+ $parsed_html->delete;
+ my $ax = 0;
+ while ($full_url = pop(@url_list)) {
+ g_get_page ($ua, $full_url, $headers, $debug);
+ $counter++;
+ $ax++;
+ if ($ax > $config->{"max_depth"}){
+ return $counter;
+ }
+ }
+ return $counter;
+}
+
+sub g_get_page {
+ my $ua = $_[0];
+ my $url = $_[1];
+ my $headers = $_[2];
+ my $debug = $_[3];
+
+ my $req = HTTP::Request->new(GET => $url);
+ $req->header('Accept' => 'text/html');
+ while (my ($header, $value) = each %{$headers}) {
+ $req->header($header => $value);
+ }
+ my $response = $ua->request($req);
+ return $response if ($debug eq '');
+
+ # Debug
+ if (open (DEBUG, '>>', $debug . '.req')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $req->as_string ();
+ print "\n";
+ close (DEBUG);
+ }
+ if (open (DEBUG, '>>', $debug . '.res')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $response->as_string ();
+ print "\n";
+ close (DEBUG);
+ }
+ return $response;
+}
+
+sub g_head_page {
+ my $ua = $_[0];
+ my $url = $_[1];
+ my $headers = $_[2];
+ my $debug = $_[3];
+
+ my $req = HTTP::Request->new(HEAD => $url);
+ $req->header('Accept' => 'text/html');
+ while (my ($header, $value) = each %{$headers}) {
+ $req->header($header => $value);
+ }
+ my $response = $ua->request($req);
+ return $response if ($debug eq '');
+
+ # Debug
+ if (open (DEBUG, '>>', $debug . '.req')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $req->as_string ();
+ print "\n";
+ close (DEBUG);
+ }
+ if (open (DEBUG, '>>', $debug . '.res')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $response->as_string ();
+ print "\n";
+ close (DEBUG);
+ }
+ return $response;
+}
+
+sub g_post_page {
+ my $ua = $_[0];
+ my $url = $_[1];
+ my $content = $_[2];
+ my $headers = $_[3];
+ my $debug = $_[4];
+
+ my $req = HTTP::Request->new(POST => $url);
+ $req->content_type('application/x-www-form-urlencoded');
+ $req->content ($content);
+ while (my ($header, $value) = each %{$headers}) {
+ $req->header($header => $value);
+ }
+ my $response = $ua->request($req);
+ return $response if ($debug eq '');
+
+ # Debug
+ if (open (DEBUG, '>>', $debug . '.req')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $req->as_string ();
+ print "\n";
+ close (DEBUG);
+ }
+ if (open (DEBUG, '>>', $debug . '.res')) {
+ print DEBUG "[Goliat debug " . time () . "]\n";
+ print DEBUG $response->as_string ();
+ print "\n";
+ close (DEBUG);
+ }
+ return $response;
+}
+
+# End of function declaration
+# End of defined Code
+
+1;
+__END__
diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm
new file mode 100755
index 0000000000..2c320477dc
--- /dev/null
+++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm
@@ -0,0 +1,222 @@
+###############################################################################
+# Goliath Tools Module
+###############################################################################
+# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L
+# This code is not free or OpenSource. Please don't redistribute.
+###############################################################################
+
+package PandoraFMS::Goliat::GoliatTools;
+
+use 5.008004;
+use strict;
+use warnings;
+use integer;
+
+require Exporter;
+
+our @ISA = ("Exporter");
+our %EXPORT_TAGS = ( 'all' => [ qw() ] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw(
+ g_clean_string
+ g_clean_string_unicode
+ g_random_string
+ g_trash_ascii
+ g_trash_unicode
+ g_unicode );
+
+# Delaracion de funciones publicas
+
+##############################################################################
+# clean_string (string) - Purge a string for any forbidden characters (esc, etc)
+##############################################################################
+sub g_clean_string {
+ my $micadena;
+ $micadena = $_[0];
+ $micadena =~ s/[^\-\:\;\.\,\_\s\a\*\=\(\)a-zA-Z0-9]/ /g;
+ $micadena =~ s/[\n\l\f]/ /g;
+ return $micadena;
+}
+
+##############################################################################
+# limpia_cadena_unicode (string) - Purge a string for any unicode character
+##############################################################################
+sub g_clean_string_unicode {
+ my $micadena;
+ $micadena = $_[0];
+ $micadena =~ s/[%]/%%/g;
+ return $micadena;
+}
+
+#############################################################################
+# Hex converter - Convert dec value in hex representation (00 - FF)
+#############################################################################
+sub g_decToHex { #return a 16bit (o uno de 8bit) hex value
+ my @hex = (0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F");
+ my @dec = @_;
+ my $s3 = $hex[($dec[0]/4096)%16];
+ my $s2 = $hex[($dec[0]/256)%16];
+ my $s1 = $hex[($dec[0]/16)%16];
+ my $s0 = $hex[$dec[0]%16];
+ return "$s1$s0";
+}
+
+#############################################################################
+# unicode - Generate unicode string (recursive)
+#############################################################################
+
+sub g_unicode {
+ my $config_word = $_[0];
+ my $config_depth = $_[1];
+ my $config_char="%";
+ if ($config_depth == 0) {
+ return $config_word;
+ }
+
+ my $a;
+ my $pos=0;
+ my $output="";
+ my $len;
+
+ for ($a=0;$a<$config_depth;$a++){
+ $len = length($config_word);
+ while ($pos < $len ) {
+ my $item;
+ $item = substr($config_word,$pos,1);
+ $output = $output.$config_char.decToHex(ord($item));
+ $pos++;
+ }
+ $config_word = $output;
+ }
+ return $output
+}
+
+#############################################################################
+# trash - Generate "unicode" style trash string
+#############################################################################
+
+sub g_trash_unicode {
+ my $config_depth = $_[0];
+ my $config_char="%";
+ my $a;
+ my $output;
+
+ for ($a=0;$a<$config_depth;$a++){
+ $output = $output.$config_char.decToHex(int(rand(25)+97));
+ }
+ return $output
+}
+
+#############################################################################
+# trash_ascii - Generate ASCII random strings
+#############################################################################
+
+sub g_trash_ascii {
+ my $config_depth = $_[0];
+ my $config_char="%";
+ my $a;
+ my $output;
+
+ for ($a=0;$a<$config_depth;$a++){
+ $output = $output.chr(int(rand(25)+97));
+ }
+ return $output
+}
+
+#############################################################################
+# random_string (min, max, type) - Generate ASCII alphanumeric string,
+# from min and max
+#############################################################################
+
+sub g_random_string {
+ my $config_min = $_[0];
+ my $config_max = $_[1];
+ my $config_type = $_[2]; # alphanumeric, alpha, numeric, lowalpha, highalpha
+ my $a;
+ my $output = "";
+ my @valid_chars;
+ my $rango;
+
+ # First fill list of valid chars (A-Z, a-z, 0-9)
+ if (($config_type eq "alphanumeric") || ($config_type eq "numeric")){
+ for ($a=48;$a<58;$a++){ # numeric
+ push @valid_chars, chr($a);
+ }
+ }
+
+ if (($config_type eq "alphanumeric") || ($config_type eq "alpha") ||
+ ($config_type eq "highalpha") || ($config_type eq "lowalpha") ){
+ if (($config_type eq "alphanumeric") || ($config_type eq "highalpha") || ($config_type eq "alpha")){
+ for ($a=65;$a<91;$a++){ # alpha (CAPS)
+ push @valid_chars, chr($a);
+ }
+ }
+ if (($config_type eq "alphanumeric") || ($config_type eq "lowalpha") || ($config_type eq "alpha")){
+ for ($a=97;$a<123;$a++){ # alpha (low)
+ push @valid_chars, chr($a);
+ }
+ }
+ }
+
+ $rango = @valid_chars;
+
+ # Fill min. value
+ for ($a=0;$a<$config_min;$a++){
+ $output = $output.$valid_chars[(int(rand($rango)))];
+ }
+
+ # Fill to max;
+ if (($config_max - $config_min) != 0){
+ for ($a=0;$aslerena@Egmail.com
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2005 by Sancho Lerena
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.4 or,
+at your option, any later version of Perl 5 you may have available.
+
+Licenced under GPL
+
+=cut
diff --git a/pandora_server/lib/PandoraFMS/WebServer.pm b/pandora_server/lib/PandoraFMS/WebServer.pm
new file mode 100644
index 0000000000..b900c21fb9
--- /dev/null
+++ b/pandora_server/lib/PandoraFMS/WebServer.pm
@@ -0,0 +1,304 @@
+package PandoraFMS::WebServer;
+##########################################################################
+# Pandora FMS Web Server.
+# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
+##########################################################################
+# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; version 2
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+##########################################################################
+
+use strict;
+use warnings;
+
+use threads;
+use threads::shared;
+use Thread::Semaphore;
+
+use File::Temp qw(tempfile);
+use HTML::Entities;
+use POSIX qw(strftime);
+
+# Default lib dir for RPM and DEB packages
+use lib '/usr/lib/perl5';
+
+use PandoraFMS::Tools;
+use PandoraFMS::DB;
+use PandoraFMS::Core;
+use PandoraFMS::ProducerConsumerServer;
+
+use PandoraFMS::Goliat::GoliatTools;
+use PandoraFMS::Goliat::GoliatConfig;
+
+# Inherits from PandoraFMS::ProducerConsumerServer
+our @ISA = qw(PandoraFMS::ProducerConsumerServer);
+
+# Global variables
+my @TaskQueue :shared;
+my %PendingTasks :shared;
+my $Sem :shared;
+my $TaskSem :shared;
+
+########################################################################################
+# Web Server class constructor.
+########################################################################################
+sub new ($$;$) {
+ my ($class, $config, $dbh) = @_;
+
+ return undef unless defined ($config->{'webserver'}) and ($config->{'webserver'} == 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, WEBSERVER, \&PandoraFMS::WebServer::data_producer, \&PandoraFMS::WebServer::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'} . " Web Server.", 1);
+
+ # Use Goliat with CURL
+ if ($pa_config->{'web_engine'} eq 'curl') {
+ require PandoraFMS::Goliat::GoliatCURL;
+ PandoraFMS::Goliat::GoliatCURL->import;
+
+ # Check for CURL binary
+ if (system ("curl -V >$DEVNULL 2>&1") >> 8 != 0) {
+ logger ($pa_config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1);
+ print_message ($pa_config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1);
+ return undef;
+ }
+ # Check for pandora_exec binary
+ if (system ("\"" . $pa_config->{'plugin_exec'} . "\" 10 echo >$DEVNULL 2>&1") >> 8 != 0) {
+ logger ($pa_config, ' [E] ' . $pa_config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1);
+ print_message ($pa_config, ' [E] ' . $pa_config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1);
+ return undef;
+ }
+ }
+ # Use LWP by default
+ else {
+ require PandoraFMS::Goliat::GoliatLWP;
+ PandoraFMS::Goliat::GoliatLWP->import;
+
+ if (! LWP::UserAgent->can('ssl_opts')) {
+ logger($pa_config, "LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1);
+ print_message ($pa_config, " [W] LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1);
+ }
+ }
+
+ $self->setNumThreads ($pa_config->{'web_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) {
+ @rows = get_db_rows ($dbh, 'SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag, tagente_estado.current_interval + tagente_estado.last_execution_try AS time_left, last_execution_try
+ FROM tagente, tagente_modulo, tagente_estado
+ WHERE server_name = ?
+ AND tagente_modulo.id_agente = tagente.id_agente
+ AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
+ AND tagente.disabled = 0
+ AND tagente_modulo.id_modulo = 7
+ AND tagente_modulo.disabled = 0
+ AND (tagente_modulo.flag = 1 OR ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()))
+ ORDER BY tagente_modulo.flag DESC, time_left ASC, last_execution_try ASC ', $pa_config->{'servername'});
+ } else {
+ @rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, tagente_estado.current_interval + tagente_estado.last_execution_try AS time_left, last_execution_try
+ FROM tagente, tagente_modulo, tagente_estado, tserver
+ WHERE ((server_name = ?) OR (server_name = ANY(SELECT server_name FROM tserver WHERE status = 0 AND server_type = ?)))
+ AND tagente_modulo.id_agente = tagente.id_agente
+ AND tagente.disabled = 0
+ AND tagente_modulo.disabled = 0
+ AND tagente_modulo.id_modulo = 7
+ AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
+ AND ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() OR tagente_modulo.flag = 1 )
+ ORDER BY tagente_modulo.flag DESC, time_left ASC, last_execution_try ASC', $pa_config->{'servername'}, WEBSERVER);
+ }
+
+ foreach my $row (@rows) {
+
+ # Reset forced execution flag
+ if ($row->{'flag'} == 1) {
+ db_do ($dbh, 'UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = ?', $row->{'id_agente_modulo'});
+ }
+
+ push (@tasks, $row->{'id_agente_modulo'});
+ }
+
+ return @tasks;
+}
+
+###############################################################################
+# Data consumer.
+###############################################################################
+sub data_consumer ($$) {
+ my ($self, $module_id) = @_;
+ my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
+ our (@task_fails, @task_time, @task_ssec, @task_get_content); # Defined in GoliatLWP.pm and GoliatCURL.
+
+ # Retrieve module data
+ my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $module_id);
+ return unless defined ($module);
+
+ # Retrieve agent data
+ my $agent = get_db_single_row ($dbh, 'SELECT * FROM tagente WHERE id_agente = ?', $module->{'id_agente'});
+ return unless defined $agent;
+
+ # Save Goliat config to a temporary file
+ my ($fh, $temp_file) = tempfile();
+ return unless defined ($fh);
+
+ # Read the Goliat task
+ my $task = safe_output($module->{'plugin_parameter'});
+
+ # Delete any carriage returns
+ $task =~ s/\r//g;
+
+ # Agent and module macros
+ my %macros = (_agent_ => (defined ($agent)) ? $agent->{'alias'} : '',
+ _agentdescription_ => (defined ($agent)) ? $agent->{'comentarios'} : '',
+ _agentstatus_ => (defined ($agent)) ? get_agent_status ($pa_config, $dbh, $agent->{'id_agente'}) : '',
+ _address_ => (defined ($agent)) ? $agent->{'direccion'} : '',
+ _module_ => (defined ($module)) ? $module->{'nombre'} : '',
+ _modulegroup_ => (defined ($module)) ? (get_module_group_name ($dbh, $module->{'id_module_group'}) || '') : '',
+ _moduledescription_ => (defined ($module)) ? $module->{'descripcion'} : '',
+ _modulestatus_ => (defined ($module)) ? get_agentmodule_status($pa_config, $dbh, $module->{'id_agente_modulo'}) : '',
+ _moduletags_ => (defined ($module)) ? pandora_get_module_url_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '',
+ _id_agent_ => (defined ($module)) ? $module->{'id_agente'} : '',
+ _interval_ => (defined ($module) && $module->{'module_interval'} != 0) ? $module->{'module_interval'} : (defined ($agent)) ? $agent->{'intervalo'} : '',
+ _target_ip_ => (defined ($agent)) ? $agent->{'direccion'} : '',
+ _target_port_ => (defined ($module)) ? $module->{'tcp_port'} : '',
+ _policy_ => (defined ($module)) ? enterprise_hook('get_policy_name', [$dbh, $module->{'id_policy_module'}]) : '',
+ _plugin_parameters_ => (defined ($module)) ? $module->{'plugin_parameter'} : '',
+ _email_tag_ => (defined ($module)) ? pandora_get_module_email_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '',
+ _phone_tag_ => (defined ($module)) ? pandora_get_module_phone_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '',
+ _name_tag_ => (defined ($module)) ? pandora_get_module_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '',
+ );
+ $task = subst_alert_macros ($task, \%macros);
+
+ # Goliat has some trouble parsing conf files without the newlines
+ $fh->print ("\n\n" . $task . "\n\n");
+ close ($fh);
+
+ # Global vars needed by Goliat
+ my (%config, @work_list, $check_string);
+
+ # Goliat config defaults
+ $config{'verbosity'} = 1;
+ $config{'slave'} = 0;
+ $config{'port'} = 80;
+ $config{'log_file'} = "$DEVNULL";
+ $config{'log_output'} = 0;
+ $config{'log_http'} = 0;
+ $config{'work_items'} = 0;
+ $config{'config_file'} = $temp_file;
+ $config{'agent'} = safe_output($module->{'plugin_user'});
+ if ($module->{'max_retries'} != 0) {
+ $config{'retries'} = $module->{'max_retries'};
+ }
+ if ($module->{'max_timeout'} != 0) {
+ $config{'timeout'} = $module->{'max_timeout'};
+ } else {
+ $config{'timeout'} = $pa_config->{'web_timeout'};
+ }
+
+ $config{'proxy'} = $module->{'snmp_oid'};
+ $config{'auth_user'} = safe_output($module->{'tcp_send'});
+ $config{'auth_pass'} = safe_output($module->{'tcp_rcv'});
+ $config{'auth_server'} = $module->{'ip_target'};
+ $config{'auth_realm'} = $module->{'snmp_community'};
+ $config{'http_check_type'} = $module->{'tcp_port'};
+ $config{'moduleId'} = $module_id;
+ $config{'dbh'} = $dbh;
+
+ # Pandora FMS variables passed to Goliat.
+ $config{'plugin_exec'} = $pa_config->{'plugin_exec'};
+
+ eval {
+ # Load Goliat config
+ g_load_config(\%config, \@work_list);
+
+ # Run Goliat task
+ g_http_task (\%config, 0, @work_list);
+ };
+
+ if ($@) {
+ pandora_update_module_on_error ($pa_config, $module, $dbh);
+ unlink ($temp_file);
+ return;
+ }
+
+ unlink ($temp_file);
+
+ my $utimestamp = time ();
+ my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
+
+ # Get module type
+ my $module_type = get_db_value ($dbh, 'SELECT nombre FROM ttipo_modulo WHERE id_tipo = ?', $module->{'id_tipo_modulo'});
+
+ # Get data from Goliat
+ my $module_data;
+ {
+ no strict 'vars';
+ if ($module_type eq 'web_proc') {
+ $module_data = ($task_fails[0] == 0 && $task_get_content[0] ne "") ? 1 : 0;
+ }
+ elsif ($module_type eq 'web_data') {
+ $module_data = $task_ssec[0];
+ } elsif ($module_type eq 'web_server_status_code_string') {
+ my @resp_lines = split "\r\n", $task_get_content[0];
+ $module_data = $resp_lines[0];
+ } else {
+ $module_data = $task_get_content[0];
+ }
+ }
+
+ my %data = ("data" => $module_data);
+ pandora_process_module ($pa_config, \%data, undef, $module, $module_type, $timestamp, $utimestamp, $self->getServerID (), $dbh);
+
+ my $agent_os_version = get_db_value ($dbh, 'SELECT os_version FROM tagente WHERE id_agente = ?', $module->{'id_agente'});
+
+ if (! defined ($agent_os_version) || $agent_os_version eq '') {
+ $agent_os_version = $pa_config->{'servername'}.'_Web';
+ }
+
+ # Todo: Implement here
+ # 1. Detect if exists a module with the same name, but with type generic_string.
+ # 2. If not, create the module, get the id's
+ # 3. Insert data coming from $task_get_string in that module
+
+ pandora_update_agent ($pa_config, $timestamp, $module->{'id_agente'}, undef, undef, -1, $dbh);
+}
+
+1;
+__END__