1<?php
2
3// Pandora FMS - http://pandorafms.com
4// ==================================================
5// Copyright (c) 2005-2010 Artica Soluciones Tecnologicas
6// Please see http://pandorafms.org for full contribution list
7
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the  GNU Lesser General Public License
10// as published by the Free Software Foundation; version 2
11
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17/**
18 * @package Include
19 * @subpackage Agents
20 */
21
22require_once($config['homedir'] . '/include/functions.php');
23require_once($config['homedir'] . "/include/functions_modules.php");
24require_once($config['homedir'] . '/include/functions_users.php');
25
26/**
27 * Check the agent exists in the DB.
28 *
29 * @param int $id_agent The agent id.
30 * @param boolean $show_disabled Show the agent found althought it is disabled. By default false.
31 *
32 * @return boolean The result to check if the agent is in the DB.
33 */
34function agents_check_agent_exists($id_agent, $show_disabled = true) {
35	$agent = db_get_value_filter('id_agente', 'tagente',
36		array('id_agente' => $id_agent, 'disabled' => !$show_disabled));
37
38	if (!empty($agent)) {
39		return true;
40	}
41	else {
42		return false;
43	}
44}
45
46/**
47 * Get agent id from a module id that it has.
48 *
49 * @param int $id_module Id module is list modules this agent.
50 *
51 * @return int Id from the agent of the given id module.
52 */
53function agents_get_agent_id_by_module_id ($id_agente_modulo) {
54	return (int) db_get_value ('id_agente', 'tagente_modulo',
55		'id_agente_modulo', $id_agente_modulo);
56}
57
58/**
59 * Creates an agent
60 *
61 * @param string Agent name.
62 * @param string Group to be included.
63 * @param int Agent interval
64 * @param string Agent IP
65 *
66 * @return int New agent id if created. False if it could not be created.
67 */
68function agents_create_agent ($name, $id_group, $interval, $ip_address, $values = false) {
69	if (empty ($name))
70		return false;
71
72	if (empty ($id_group))
73		return false;
74
75	if (empty ($ip_address))
76		return false;
77
78	// Check interval greater than zero
79	if ($interval < 0)
80		$interval = false;
81	if (empty ($interval))
82		return false;
83
84	if (! is_array ($values))
85		$values = array ();
86	$values['nombre'] = $name;
87	$values['id_grupo'] = $id_group;
88	$values['intervalo'] = $interval;
89	$values['direccion'] = $ip_address;
90
91	$id_agent = db_process_sql_insert ('tagente', $values);
92	if ($id_agent === false) {
93		return false;
94	}
95
96	// Create address for this agent in taddress
97	agents_add_address ($id_agent, $ip_address);
98
99
100	db_pandora_audit ("Agent management", "New agent '$name' created");
101
102	return $id_agent;
103}
104
105/**
106 * Get all the simple alerts of an agent.
107 *
108 * @param int Agent id
109 * @param string Filter on "fired", "notfired" or "disabled". Any other value
110 * will not do any filter.
111 * @param array Extra filter options in an indexed array. See
112 * db_format_array_where_clause_sql()
113 * @param boolean $allModules
114 *
115 * @return array All simple alerts defined for an agent. Empty array if no
116 * alerts found.
117 */
118function agents_get_alerts_simple ($id_agent = false, $filter = '', $options = false, $where = '', $allModules = false, $orderby = false, $idGroup = false, $count = false, $strict_user = false, $tag = false) {
119	global $config;
120
121	if (is_array($filter)) {
122		$disabled = $filter['disabled'];
123		if (isset($filter['standby'])) {
124			$filter = ' AND talert_template_modules.standby = "'.$filter['standby'].'"';
125		}
126		else {
127			$filter = '';
128		}
129	}
130	else {
131		$filter = '';
132		$disabled = $filter;
133	}
134
135	switch ($disabled) {
136		case "notfired":
137			$filter .= ' AND times_fired = 0 AND talert_template_modules.disabled = 0';
138			break;
139		case "fired":
140			$filter .= ' AND times_fired > 0 AND talert_template_modules.disabled = 0';
141			break;
142		case "disabled":
143			$filter .= ' AND talert_template_modules.disabled = 1';
144			break;
145		case "all_enabled":
146			$filter .= ' AND talert_template_modules.disabled = 0';
147			break;
148		default:
149			$filter .= '';
150			break;
151	}
152
153	if ($tag) {
154		$filter .= ' AND (id_agent_module IN (SELECT id_agente_modulo FROM ttag_module WHERE id_tag IN ('.$tag.')))';
155	}
156
157	if (isset($options['offset'])) {
158		$offset = $options['offset'];
159		unset($options['offset']);
160	}
161
162	if (isset($options['limit'])) {
163		$limit = $options['limit'];
164		unset($options['limit']);
165	}
166
167	if (is_array ($options)) {
168		$filter .= db_format_array_where_clause_sql ($options);
169	}
170
171	if (($id_agent !== false) && ($idGroup !== false)) {
172		$groups = users_get_groups($config["id_user"]);
173
174		if ($idGroup != 0) { //All group
175			$subQuery = 'SELECT id_agente_modulo
176				FROM tagente_modulo
177				WHERE delete_pending = 0 AND id_agente IN (SELECT id_agente FROM tagente WHERE id_grupo = ' . $idGroup . ')';
178		}
179		else {
180			$subQuery = 'SELECT id_agente_modulo
181				FROM tagente_modulo WHERE delete_pending = 0';
182		}
183
184		if ($strict_user) {
185			$where_tags = tags_get_acl_tags($config['id_user'], $groups, 'AR', 'module_condition', 'AND', 'tagente_modulo');
186			// If there are any errors add imposible condition
187			if(in_array($where_tags, array(ERR_WRONG_PARAMETERS, ERR_ACL))) {
188				$subQuery .= ' AND 1 = 0';
189			}
190			else {
191				$subQuery .= $where_tags;
192			}
193		}
194	}
195	else if ($id_agent === false || empty($id_agent)) {
196		if ($allModules)
197			$disabled = '';
198		else
199			$disabled = 'WHERE disabled = 0';
200
201		$subQuery = 'SELECT id_agente_modulo
202			FROM tagente_modulo ' . $disabled;
203	}
204	else {
205		$id_agent = (array) $id_agent;
206		$id_modules = array_keys (agents_get_modules ($id_agent, false, array('delete_pending' => 0)));
207
208		if (empty ($id_modules))
209			return array ();
210
211		$subQuery = implode (",", $id_modules);
212	}
213
214	$orderbyText = '';
215	if ($orderby !== false) {
216		if (is_array($orderby)) {
217			$orderbyText = sprintf("ORDER BY %s", $orderby['field'], $orderby['order']);
218		}
219		else {
220			$orderbyText = sprintf("ORDER BY %s", $orderby);
221		}
222	}
223
224	$selectText = 'talert_template_modules.*, t2.nombre AS agent_module_name, t3.nombre AS agent_name, t4.name AS template_name';
225	if ($count !== false) {
226		$selectText = 'COUNT(talert_template_modules.id) AS count';
227	}
228
229
230	$sql = sprintf ("SELECT %s
231		FROM talert_template_modules
232			INNER JOIN tagente_modulo t2
233				ON talert_template_modules.id_agent_module = t2.id_agente_modulo
234			INNER JOIN tagente t3
235				ON t2.id_agente = t3.id_agente
236			INNER JOIN talert_templates t4
237				ON talert_template_modules.id_alert_template = t4.id
238		WHERE id_agent_module in (%s) %s %s %s",
239		$selectText, $subQuery, $where, $filter, $orderbyText);
240
241	switch ($config["dbtype"]) {
242		case "mysql":
243			$limit_sql = '';
244			if (isset($offset) && isset($limit)) {
245				$limit_sql = " LIMIT $offset, $limit ";
246			}
247			$sql = sprintf("%s %s", $sql, $limit_sql);
248
249			$alerts = db_get_all_rows_sql($sql);
250			break;
251		case "postgresql":
252			$limit_sql = '';
253			if (isset($offset) && isset($limit)) {
254				$limit_sql = " OFFSET $offset LIMIT $limit ";
255			}
256			$sql = sprintf("%s %s", $sql, $limit_sql);
257
258			$alerts = db_get_all_rows_sql($sql);
259
260			break;
261		case "oracle":
262			$set = array();
263			if (isset($offset) && isset($limit)) {
264				$set['limit'] = $limit;
265				$set['offset'] = $offset;
266			}
267
268			$alerts = oracle_recode_query ($sql, $set, 'AND', false);
269			break;
270	}
271
272	if ($alerts === false)
273		return array ();
274
275	if ($count !== false) {
276		return $alerts[0]['count'];
277	}
278	else {
279		return $alerts;
280	}
281}
282
283/**
284 * Get a list of agents.
285 *
286 * By default, it will return all the agents where the user has reading access.
287 *
288 * @param array filter options in an indexed array. See
289 * db_format_array_where_clause_sql()
290 * @param array Fields to get.
291 * @param string Access needed in the agents groups.
292 * @param array $order The order of agents, by default is upward for field nombre.
293 * @param bool $return Whether to return array with agents or false, or sql string statement
294 *
295 * @return mixed An array with all alerts defined for an agent or false in case no allowed groups are specified.
296 */
297function agents_get_agents ($filter = false, $fields = false,
298	$access = 'AR',
299	$order = array('field' => 'nombre', 'order' => 'ASC'),
300	$return = false) {
301
302	global $config;
303
304	if (! is_array ($filter)) {
305		$filter = array ();
306	}
307
308	if (isset($filter['search'])) {
309		$search = $filter['search'];
310		unset($filter['search']);
311	}
312	else {
313		$search = '';
314	}
315
316	if (isset($filter['offset'])) {
317		$offset = $filter['offset'];
318		unset($filter['offset']);
319	}
320
321	if (isset($filter['limit'])) {
322		$limit = $filter['limit'];
323		unset($filter['limit']);
324	}
325
326	$status_sql = ' 1 = 1';
327	if (isset($filter['status'])) {
328		switch ($filter['status']) {
329			case AGENT_STATUS_NORMAL:
330				$status_sql =
331					"normal_count = total_count
332						AND notinit_count <> total_count";
333				break;
334			case AGENT_STATUS_WARNING:
335				$status_sql =
336					"critical_count = 0 AND warning_count > 0";
337				break;
338			case AGENT_STATUS_CRITICAL:
339				$status_sql =
340					"critical_count > 0";
341				break;
342			case AGENT_STATUS_UNKNOWN:
343				$status_sql =
344					"critical_count = 0 AND warning_count = 0
345						AND unknown_count > 0";
346				break;
347			case AGENT_STATUS_NOT_NORMAL:
348				$status_sql =
349					"(
350						normal_count <> total_count
351						AND
352						(normal_count + notinit_count) <> total_count)";
353				break;
354			case AGENT_STATUS_NOT_INIT:
355				$status_sql = "notinit_count = total_count";
356				break;
357		}
358		unset($filter['status']);
359	}
360
361
362	unset($filter['order']);
363
364	$filter_nogroup = $filter;
365
366	//Get user groups
367	$groups = array_keys (users_get_groups ($config["id_user"], $access, false));
368
369	//If no group specified, get all user groups
370	if (empty ($filter['id_grupo'])) {
371		$all_groups = true;
372		$filter['id_grupo'] = $groups;
373	}
374	elseif (! is_array ($filter['id_grupo'])) {
375		$all_groups = false;
376		//If group is specified but not allowed, return false
377		if (! in_array ($filter['id_grupo'], $groups)) {
378			return false;
379		}
380		$filter['id_grupo'] = (array) $filter['id_grupo']; //Make an array
381	}
382	else {
383		$all_groups = true;
384		//Check each group specified to the user groups, remove unwanted groups
385		foreach ($filter['id_grupo'] as $key => $id_group) {
386			if (! in_array ($id_group, $groups)) {
387				unset ($filter['id_grupo'][$key]);
388			}
389		}
390		//If no allowed groups are specified return false
391		if (count ($filter['id_grupo']) == 0) {
392			return false;
393		}
394	}
395
396	if (in_array (0, $filter['id_grupo'])) {
397		unset ($filter['id_grupo']);
398	}
399
400	if (!is_array ($fields)) {
401		$fields = array ();
402		$fields[0] = "id_agente";
403		$fields[1] = "nombre";
404	}
405
406	if (isset($order['field'])) {
407		if(!isset($order['order'])) {
408			$order['order'] = 'ASC';
409		}
410		if (!isset($order['field2'])) {
411			$order = 'ORDER BY '.$order['field'] . ' ' . $order['order'];
412		}
413		else {
414			$order = 'ORDER BY '.$order['field'] . ' ' . $order['order'] . ', ' . $order['field2'];
415		}
416	}
417
418	//Fix for postgresql
419	if (empty($filter['id_agente'])) {
420		unset($filter['id_agente']);
421	}
422
423	$where = db_format_array_where_clause_sql ($filter, 'AND', '');
424
425	$where_nogroup = db_format_array_where_clause_sql(
426		$filter_nogroup, 'AND', '');
427
428	if ($where_nogroup == '') {
429		$where_nogroup = '1 = 1';
430	}
431
432	$extra = false;
433
434	// TODO: CLEAN extra_sql
435	$sql_extra = '';
436	if ($all_groups) {
437		$where_nogroup = '1 = 1';
438	}
439
440	if ($extra) {
441		$where = sprintf('(%s OR (%s)) AND (%s) AND (%s) %s',
442			$sql_extra, $where, $where_nogroup, $status_sql, $search);
443	}
444	else {
445		$where = sprintf('%s AND %s AND (%s) %s',
446			$where, $where_nogroup, $status_sql, $search);
447	}
448	$sql = sprintf('SELECT %s
449		FROM tagente
450		WHERE %s %s', implode(',',$fields), $where, $order);
451
452	switch ($config["dbtype"]) {
453		case "mysql":
454			$limit_sql = '';
455			if (isset($offset) && isset($limit)) {
456				$limit_sql = " LIMIT $offset, $limit ";
457			}
458			$sql = sprintf("%s %s", $sql, $limit_sql);
459
460			if ($return)
461				return $sql;
462			else
463				$agents = db_get_all_rows_sql($sql);
464			break;
465		case "postgresql":
466			$limit_sql = '';
467			if (isset($offset) && isset($limit)) {
468				$limit_sql = " OFFSET $offset LIMIT $limit ";
469			}
470			$sql = sprintf("%s %s", $sql, $limit_sql);
471
472			if ($return)
473				return $sql;
474			else
475				$agents = db_get_all_rows_sql($sql);
476
477			break;
478		case "oracle":
479			$set = array();
480			if (isset($offset) && isset($limit)) {
481				$set['limit'] = $limit;
482				$set['offset'] = $offset;
483			}
484
485			if ($return)
486				return $sql;
487			else
488				$agents = oracle_recode_query ($sql, $set, 'AND', false);
489			break;
490	}
491
492	return $agents;
493}
494
495/**
496 * Get all the alerts of an agent, simple and combined.
497 *
498 * @param int $id_agent Agent id
499 * @param string Special filter. Can be: "notfired", "fired" or "disabled".
500 * @param array Extra filter options in an indexed array. See
501 * db_format_array_where_clause_sql()
502 *
503 * @return array An array with all alerts defined for an agent.
504 */
505function agents_get_alerts ($id_agent = false, $filter = false, $options = false) {
506	$simple_alerts = agents_get_alerts_simple ($id_agent, $filter, $options);
507
508	return array ('simple' => $simple_alerts);
509}
510
511/**
512 * Copy the agents config from one agent to the other
513 *
514 * @param int Agent id
515 * @param mixed Agent id or id's (array) to copy to
516 * @param bool Whether to copy modules as well (defaults to $_REQUEST['copy_modules'])
517 * @param bool Whether to copy alerts as well
518 * @param array Which modules to copy.
519 * @param array Which alerts to copy. Only will be used if target_modules is empty.
520 *
521 * @return bool True in case of good, false in case of bad
522 */
523function agents_process_manage_config ($source_id_agent, $destiny_id_agents, $copy_modules = false, $copy_alerts = false, $target_modules = false, $target_alerts = false) {
524	global $config;
525
526	if (empty ($source_id_agent)) {
527		ui_print_error_message(__('No source agent to copy'));
528		return false;
529	}
530
531	if (empty ($destiny_id_agents)) {
532		ui_print_error_message(__('No destiny agent(s) to copy'));
533		return false;
534	}
535
536	if ($copy_modules == false) {
537		$copy_modules = (bool) get_parameter ('copy_modules', $copy_modules);
538	}
539
540	if ($copy_alerts == false) {
541		$copy_alerts = (bool) get_parameter ('copy_alerts', $copy_alerts);
542	}
543
544	if (! $copy_modules && ! $copy_alerts)
545		return false;
546
547	if (empty ($target_modules)) {
548		$target_modules = (array) get_parameter ('target_modules', array ());
549	}
550
551	if (empty ($target_alerts)) {
552		$target_alerts = (array) get_parameter ('target_alerts', array ());
553	}
554
555	if (empty ($target_modules)) {
556		if (! $copy_alerts) {
557			ui_print_error_message(__('No modules have been selected'));
558			return false;
559		}
560		$target_modules = array ();
561
562		foreach ($target_alerts as $id_alert) {
563			$alert = alerts_get_alert_agent_module ($id_alert);
564			if ($alert === false)
565				continue;
566			/* Check if some alerts which doesn't belong to the agent was given */
567			if (modules_get_agentmodule_agent ($alert['id_agent_module']) != $source_id_agent)
568				continue;
569			array_push ($target_modules, $alert['id_agent_module']);
570		}
571	}
572
573	switch ($config['dbtype']) {
574		case "mysql":
575		case "postgresql":
576			db_process_sql ('SET AUTOCOMMIT = 0');
577			db_process_sql ('START TRANSACTION');
578			break;
579		case "oracle":
580			db_process_sql_begin();
581			break;
582	}
583	$error = false;
584
585	$repeated_modules = array();
586	foreach ($destiny_id_agents as $id_destiny_agent) {
587		foreach ($target_modules as $id_agent_module) {
588
589			// Check the module name exists in target
590			$module = modules_get_agentmodule ($id_agent_module);
591			if ($module === false)
592				return false;
593
594			$modules = agents_get_modules ($id_destiny_agent, false,
595				array ('nombre' => $module['nombre'], 'disabled' => false));
596
597			// Keep all modules repeated
598			if (! empty ($modules)) {
599				$modules_repeated = array_pop (array_keys ($modules));
600				$result = $modules_repeated;
601				$repeated_modules[] = $modules_repeated;
602			}
603			else {
604
605				$result = modules_copy_agent_module_to_agent ($id_agent_module,
606					$id_destiny_agent);
607
608				if ($result === false) {
609					$error = true;
610					break;
611				}
612			}
613
614			// Check if all modules are repeated and no alerts are copied, if YES then error
615			if (empty($target_alerts) and count($repeated_modules) == count($target_modules)) {
616				$error = true;
617				break;
618			}
619
620			$id_destiny_module = $result;
621
622			if (! $copy_alerts)
623				continue;
624
625			/* If the alerts were given, copy afterwards. Otherwise, all the
626			alerts for the module will be copied */
627			if (! empty ($target_alerts)) {
628				foreach ($target_alerts as $id_alert) {
629					$alert = alerts_get_alert_agent_module ($id_alert);
630					if ($alert === false)
631						continue;
632					if ($alert['id_agent_module'] != $id_agent_module)
633						continue;
634					$result = alerts_copy_alert_module_to_module ($alert['id'],
635						$id_destiny_module);
636					if ($result === false) {
637						$error = true;
638						break;
639					}
640				}
641				continue;
642			}
643
644			$alerts = alerts_get_alerts_agent_module ($id_agent_module, true);
645
646			if ($alerts === false)
647				continue;
648
649			foreach ($alerts as $alert) {
650				$result = alerts_copy_alert_module_to_module ($alert['id'],
651					$id_destiny_module);
652				if ($result === false) {
653					$error = true;
654					break;
655				}
656			}
657		}
658		if ($error)
659			break;
660	}
661
662	if ($error) {
663		ui_print_error_message(
664			__('There was an error copying the agent configuration, the copy has been cancelled'));
665		switch ($config['dbtype']) {
666			case "mysql":
667			case "postgresql":
668				db_process_sql ('ROLLBACK');
669				break;
670			case "oracle":
671				db_process_sql_rollback();
672				break;
673		}
674	}
675	else {
676		ui_print_success_message(__('Successfully copied'));
677		switch ($config['dbtype']) {
678			case "mysql":
679			case "postgresql":
680				db_process_sql ('COMMIT');
681				break;
682			case "oracle":
683				db_process_sql_commit();
684				break;
685		}
686	}
687	switch ($config['dbtype']) {
688		case "mysql":
689		case "postgresql":
690			db_process_sql ('SET AUTOCOMMIT = 1');
691			break;
692	}
693
694	if ($error)
695		return false;
696	else
697		return true;
698}
699
700function agents_get_next_contact($idAgent, $maxModules = false) {
701	$agent = db_get_row_sql("SELECT *
702		FROM tagente
703		WHERE id_agente = " . $idAgent);
704
705
706	$difference = get_system_time () - strtotime ($agent["ultimo_contacto"]);
707
708
709	if ($agent["intervalo"] > 0 && strtotime($agent["ultimo_contacto"]) > 0) {
710		return round ($difference / ($agent["intervalo"] / 100));
711	}
712	else {
713		return 0;
714	}
715}
716
717/**
718 * Get all the modules common in various agents. If an empty list is passed it will select all
719 *
720 * @param mixed Agent id to get modules. It can also be an array of agent id's.
721 * @param mixed Array, comma delimited list or singular value of rows to
722 * select. If nothing is specified, nombre will be selected. A special
723 * character "*" will select all the values.
724 * @param mixed Aditional filters to the modules. It can be an indexed array
725 * (keys would be the field name and value the expected value, and would be
726 * joined with an AND operator) or a string, including any SQL clause (without
727 * the WHERE keyword).
728 * @param bool Wheter to return the modules indexed by the id_agente_modulo or
729 * not. Default is indexed.
730 * Example:
731 <code>
732 Both are similars:
733 $modules = agents_get_modules ($id_agent, false, array ('disabled' => 0));
734 $modules = agents_get_modules ($id_agent, false, 'disabled = 0');
735
736 Both are similars:
737 $modules = agents_get_modules ($id_agent, '*', array ('disabled' => 0, 'history_data' => 0));
738 $modules = agents_get_modules ($id_agent, '*', 'disabled = 0 AND history_data = 0');
739 </code>
740 *
741 * @return array An array with all modules in the agent.
742 * If multiple rows are selected, they will be in an array
743 */
744function agents_common_modules ($id_agent, $filter = false, $indexed = true, $get_not_init_modules = true) {
745	$id_agent = safe_int ($id_agent, 1);
746
747	$where = '';
748	if (! empty ($id_agent)) {
749		$where = sprintf (' WHERE delete_pending = 0 AND id_agente IN (%s)
750			AND (
751				SELECT count(nombre)
752				FROM tagente_modulo t2
753				WHERE delete_pending = 0 AND t1.nombre = t2.nombre
754					AND id_agente IN (%s)) = (%s)', implode (",", (array) $id_agent), implode (",", (array) $id_agent), count($id_agent));
755	}
756
757	if (! empty ($filter)) {
758		$where .= ' AND ';
759		if (is_array ($filter)) {
760			$fields = array ();
761			foreach ($filter as $field => $value) {
762				array_push ($fields, $field.'="'.$value.'"');
763			}
764			$where .= implode (' AND ', $fields);
765		}
766		else {
767			$where .= $filter;
768		}
769	}
770
771	$sql = sprintf ('SELECT DISTINCT(t1.id_agente_modulo) as id_agente_modulo
772		FROM tagente_modulo t1, talert_template_modules t2
773		%s
774		ORDER BY nombre',
775		$where);
776	$result = db_get_all_rows_sql ($sql);
777
778	if (empty ($result)) {
779		return array ();
780	}
781
782	if (! $indexed)
783		return $result;
784
785	$modules = array ();
786	foreach ($result as $module) {
787		if ($get_not_init_modules || modules_get_agentmodule_is_init($module['id_agente_modulo'])) {
788			$modules[$module['id_agente_modulo']] = $module['id_agente_modulo'];
789		}
790	}
791	return $modules;
792}
793
794/**
795 * Get all the agents within a group(s).
796 *
797 * @param mixed $id_group Group id or an array of ID's. If nothing is selected, it will select all
798 * @param mixed $search to add Default: False. If True will return disabled agents as well. If searching array (disabled => (bool), string => (string))
799 * @param string $case Which case to return the agentname as (lower, upper, none)
800 * @param boolean $noACL jump the ACL test.
801 * @param boolean $childGroups The flag to get agents in the child group of group parent passed. By default false.
802 * @param boolean $serialized Only in metaconsole. Return the key as <server id><SEPARATOR><agent id>. By default false.
803 * @param string $separator Only in metaconsole. Separator for the serialized data. By default |.
804 *
805 * @return array An array with all agents in the group or an empty array
806 */
807function agents_get_group_agents ($id_group = 0, $search = false,
808	$case = "lower", $noACL = false, $childGroups = false, $serialized = false, $separator = '|', $add_alert_bulk_op = false) {
809
810	global $config;
811
812	$filter = array();
813
814	if (!$noACL) {
815		$id_group = groups_safe_acl($config["id_user"], $id_group, "AR");
816
817		if (empty ($id_group)) {
818			//An empty array means the user doesn't have access
819			return array ();
820		}
821	}
822
823	if ($childGroups) {
824		if (is_array($id_group)) {
825			foreach ($id_group as $parent) {
826				$id_group = array_merge($id_group,
827					groups_get_id_recursive($parent, true));
828			}
829		}
830		else {
831			$id_group = groups_get_id_recursive($id_group, true);
832		}
833
834		if (!$noACL) {
835			$id_group = array_keys(
836				users_get_groups(false, "AR", true, false, (array)$id_group));
837		}
838	}
839
840	if (!empty($id_group)) {
841		$filter['id_grupo'] = $id_group;
842	}
843
844	if ($search === true) {
845		//No added search. Show both disabled and non-disabled
846	}
847	else if (is_array ($search)) {
848		$filter['disabled'] = 0;
849		if (isset ($search["disabled"])) {
850			$filter['disabled'] = (int) $search["disabled"];
851
852			unset ($search["disabled"]);
853		}
854
855		if (isset ($search["string"])) {
856			$string = io_safe_input ($search["string"]);
857			switch ($config["dbtype"]) {
858				case "mysql":
859				case "postgresql":
860					$filter[] = "(nombre COLLATE utf8_general_ci LIKE '%$string%' OR direccion LIKE '%$string%')";
861					break;
862				case "oracle":
863					$filter[] = "(UPPER(nombre) LIKE UPPER('%$string%') OR direccion LIKE upper('%$string%'))";
864					break;
865			}
866
867			unset ($search["string"]);
868		}
869
870		if (isset ($search["name"])) {
871			$name = io_safe_input ($search["name"]);
872			switch ($config["dbtype"]) {
873				case "mysql":
874				case "postgresql":
875					$filter[] = "nombre COLLATE utf8_general_ci LIKE '$name'";
876					break;
877				case "oracle":
878					$filter[] = "UPPER(nombre) LIKE UPPER('$name')";
879					break;
880			}
881
882			unset ($search["name"]);
883		}
884
885		if (isset($search['status'])) {
886			switch ($search['status']) {
887				case AGENT_STATUS_NORMAL:
888					$filter[] = "normal_count = total_count";
889					break;
890				case AGENT_STATUS_WARNING:
891					$filter[] = "(critical_count = 0 AND warning_count > 0)";
892					break;
893				case AGENT_STATUS_CRITICAL:
894					$filter[] = "critical_count > 0";
895					break;
896				case AGENT_STATUS_UNKNOWN:
897					$filter[] = "(critical_count = 0 AND warning_count = 0 AND unknown_count > 0)";
898					break;
899				case AGENT_STATUS_NOT_NORMAL:
900					$filter[] = "normal_count <> total_count
901							AND critical_count = 0 AND warning_count = 0";
902					break;
903				case AGENT_STATUS_NOT_INIT:
904					$filter[] = "notinit_count = total_count";
905					break;
906			}
907			unset($search['status']);
908		}
909		if ($add_alert_bulk_op) {
910			if (isset($search['id_agente'])) {
911				$filter['id_agente'] = $search['id_agente'];
912			}
913		}
914
915		if (is_metaconsole() && isset($search['id_server'])) {
916			$filter['id_tmetaconsole_setup'] = $search['id_server'];
917
918			if ($filter['id_tmetaconsole_setup'] == 0)	{
919				// All nodes
920				unset ($filter['id_tmetaconsole_setup']);
921			}
922
923			unset ($search["id_server"]);
924		}
925		if (!$add_alert_bulk_op) {
926			// Add the rest of the filter from the search array
927			foreach ($search as $key => $value) {
928				$filter[] = $value;
929			}
930		}
931	}
932	else {
933		$filter['disabled'] = 0;
934	}
935
936	$filter['order'] = 'nombre';
937
938	if (is_metaconsole()) {
939		$table_name = 'tmetaconsole_agent';
940
941		$fields = array(
942				'id_tagente AS id_agente',
943				'nombre',
944				'id_tmetaconsole_setup AS id_server'
945			);
946	}
947	else {
948		$table_name = 'tagente';
949
950		$fields = array(
951				'id_agente',
952				'nombre'
953			);
954	}
955
956	$result = db_get_all_rows_filter($table_name, $filter, $fields);
957
958	if ($result === false)
959		return array (); //Return an empty array
960
961	$agents = array ();
962	foreach ($result as $row) {
963		if (!isset($row["id_agente"]) || !isset($row["nombre"]))
964			continue;
965
966		if ($serialized && isset($row["id_server"])) {
967			$key = $row["id_server"] . $separator . $row["id_agente"];
968		}
969		else {
970			$key = $row["id_agente"];
971		}
972
973		switch ($case) {
974			case "lower":
975				$value = mb_strtolower ($row["nombre"], "UTF-8");
976				break;
977			case "upper":
978				$value = mb_strtoupper ($row["nombre"], "UTF-8");
979				break;
980			default:
981				$value = $row["nombre"];
982				break;
983		}
984
985		$agents[$key] = $value;
986	}
987	return ($agents);
988}
989
990/**
991 * Get all the modules in an agent. If an empty list is passed it will select all
992 *
993 * @param mixed Agent id to get modules. It can also be an array of agent id's, by default is null and this mean that use the ids of agents in user's groups.
994 * @param mixed Array, comma delimited list or singular value of rows to
995 * select. If nothing is specified, nombre will be selected. A special
996 * character "*" will select all the values.
997 * @param mixed Aditional filters to the modules. It can be an indexed array
998 * (keys would be the field name and value the expected value, and would be
999 * joined with an AND operator) or a string, including any SQL clause (without
1000 * the WHERE keyword).
1001 * @param bool Wheter to return the modules indexed by the id_agente_modulo or
1002 * not. Default is indexed.
1003 * Example:
1004 <code>
1005 Both are similars:
1006 $modules = agents_get_modules ($id_agent, false, array ('disabled' => 0));
1007 $modules = agents_get_modules ($id_agent, false, 'disabled = 0');
1008
1009 Both are similars:
1010 $modules = agents_get_modules ($id_agent, '*', array ('disabled' => 0, 'history_data' => 0));
1011 $modules = agents_get_modules ($id_agent, '*', 'disabled = 0 AND history_data = 0');
1012 </code>
1013 *
1014 * @return array An array with all modules in the agent.
1015 * If multiple rows are selected, they will be in an array
1016 */
1017function agents_get_modules ($id_agent = null, $details = false,
1018	$filter = false, $indexed = true, $get_not_init_modules = true,
1019	$noACLs = false) {
1020
1021	global $config;
1022
1023	$userGroups = users_get_groups($config['id_user'], 'AR', false);
1024	if (empty($userGroups)) {
1025		return array();
1026	}
1027	$id_userGroups = $id_groups = array_keys($userGroups);
1028
1029	// =================================================================
1030	// When there is not a agent id. Get a agents of groups that the
1031	// user can read the agents.
1032	// =================================================================
1033	if ($id_agent === null) {
1034
1035		$sql = "SELECT id_agente
1036			FROM tagente
1037			WHERE id_grupo IN (" . implode(',', $id_groups) . ")";
1038		$id_agent = db_get_all_rows_sql($sql);
1039
1040		if ($id_agent == false) {
1041			$id_agent = array();
1042		}
1043
1044		$temp = array();
1045		foreach ($id_agent as $item) {
1046			$temp[] = $item['id_agente'];
1047		}
1048		$id_agent = $temp;
1049	}
1050
1051	// =================================================================
1052	// Fixed strange values. Only array of ids or id as int
1053	// =================================================================
1054	if (!is_array($id_agent)) {
1055		$id_agent = safe_int ($id_agent, 1);
1056	}
1057
1058
1059	$where = "(
1060			1 = (
1061				SELECT is_admin
1062				FROM tusuario
1063				WHERE id_user = '" . $config['id_user'] . "'
1064			)
1065			OR
1066			tagente_modulo.id_agente IN (
1067				SELECT id_agente
1068				FROM tagente
1069				WHERE id_grupo IN (
1070						" . implode(',', $id_userGroups) . "
1071					)
1072			)
1073			OR 0 IN (
1074				SELECT id_grupo
1075				FROM tusuario_perfil
1076				WHERE id_usuario = '" . $config['id_user'] . "'
1077					AND id_perfil IN (
1078						SELECT id_perfil
1079						FROM tperfil WHERE agent_view = 1
1080					)
1081				)
1082		)";
1083
1084	if (! empty ($id_agent)) {
1085		$where .= sprintf (' AND id_agente IN (%s)', implode (",", (array) $id_agent));
1086	}
1087
1088	$where .= ' AND delete_pending = 0 ';
1089
1090	if (! empty ($filter)) {
1091		$where .= ' AND ';
1092		if (is_array ($filter)) {
1093			$fields = array ();
1094
1095
1096			//----------------------------------------------------------
1097			// Code for filters as array of arrays
1098			//  for example:
1099			//    $filter =  array(
1100			//      'id_modulo' => 2, // networkmap type
1101			//      'id_tipo_modulo' => array(
1102			//        '<>2', // != generic_proc
1103			//        '<>6', // != remote_icmp_proc
1104			//        '<>9'));
1105			//----------------------------------------------------------
1106			$list_filter = array();
1107			foreach ($filter as $field => $value) {
1108				if (is_array($value)) {
1109					foreach ($value as $v) {
1110						$list_filter[] = array('field' => $field,
1111							'value' => $v);
1112					}
1113				}
1114				else {
1115					$list_filter[] = array('field' => $field,
1116						'value' => $value);
1117				}
1118			}
1119			//----------------------------------------------------------
1120
1121			foreach ($list_filter as $item) {
1122				$field = $item['field'];
1123				$value = $item['value'];
1124
1125				//Check <> operator
1126				$operatorDistin = false;
1127				if (strlen($value) > 2) {
1128					if ($value[0] . $value[1] == '<>') {
1129						$operatorDistin = true;
1130					}
1131				}
1132
1133				if ($value[0] == '%') {
1134					switch ($config['dbtype']) {
1135						case "mysql":
1136						case "postgresql":
1137							array_push ($fields,
1138								$field . ' LIKE "' . $value . '"');
1139							break;
1140						case "oracle":
1141							array_push ($fields,
1142								$field . ' LIKE \'' . $value . '\'');
1143							break;
1144					}
1145				}
1146				else if ($operatorDistin) {
1147					array_push($fields, $field.' <> ' . substr($value, 2));
1148				}
1149				else if (substr($value, -1) == '%') {
1150					switch ($config['dbtype']) {
1151						case "mysql":
1152						case "postgresql":
1153							array_push ($fields, $field.' LIKE "'.$value.'"');
1154							break;
1155						case "oracle":
1156							array_push ($fields, $field.' LIKE \''.$value.'\'');
1157							break;
1158					}
1159				}
1160				//else if (strstr($value, '666=666', true) == '') {
1161				else if (strncmp($value, '666=666', 7) == 0) {
1162					switch ($config['dbtype']) {
1163						case "mysql":
1164						case "postgresql":
1165							array_push ($fields, ' '.$value);
1166							break;
1167						case "oracle":
1168							array_push ($fields, ' '.$value);
1169							break;
1170					}
1171				}
1172				else {
1173					switch ($config["dbtype"]) {
1174						case "mysql":
1175							array_push ($fields, $field.' = "'.$value.'"');
1176							break;
1177						case "postgresql":
1178							array_push ($fields, $field.' = \''.$value.'\'');
1179							break;
1180						case "oracle":
1181							if (is_int ($value) || is_float ($value) || is_double ($value))
1182								array_push ($fields, $field.' = '.$value.'');
1183							else
1184								array_push ($fields, $field.' = \''.$value.'\'');
1185							break;
1186					}
1187				}
1188			}
1189			$where .= implode (' AND ', $fields);
1190		}
1191		else {
1192			$where .= $filter;
1193		}
1194	}
1195
1196	if (empty ($details)) {
1197		$details = "nombre";
1198	}
1199	else {
1200		$details = io_safe_input ($details);
1201	}
1202
1203	//$where .= " AND id_policy_module = 0 ";
1204
1205	$where_tags = tags_get_acl_tags($config['id_user'], $id_groups, 'AR',
1206		'module_condition', 'AND', 'tagente_modulo', false, array(),
1207		true);
1208
1209	$where .= "\n\n" . $where_tags;
1210
1211	$sql = sprintf ('SELECT %s%s
1212					FROM tagente_modulo
1213					WHERE
1214						%s
1215					ORDER BY nombre',
1216					($details != '*' && $indexed) ? 'id_agente_modulo,' : '',
1217					io_safe_output(implode (",", (array) $details)),
1218					$where);
1219
1220
1221	$result = db_get_all_rows_sql ($sql);
1222
1223
1224	if (empty ($result)) {
1225		return array ();
1226	}
1227
1228	if (! $indexed)
1229		return $result;
1230
1231	$modules = array ();
1232	foreach ($result as $module) {
1233		if ($get_not_init_modules || modules_get_agentmodule_is_init($module['id_agente_modulo'])) {
1234			if (is_array ($details) || $details == '*') {
1235				//Just stack the information in array by ID
1236				$modules[$module['id_agente_modulo']] = $module;
1237			}
1238			else {
1239				$modules[$module['id_agente_modulo']] = $module[$details];
1240			}
1241		}
1242	}
1243	return $modules;
1244}
1245
1246/**
1247 * Get agent id from a module id that it has.
1248 *
1249 * @param int $id_module Id module is list modules this agent.
1250 *
1251 * @return int Id from the agent of the given id module.
1252 */
1253function agents_get_module_id ($id_agente_modulo) {
1254	return (int) db_get_value ('id_agente', 'tagente_modulo', 'id_agente_modulo', $id_agente_modulo);
1255}
1256
1257/**
1258 * Get agent id from an agent name.
1259 *
1260 * @param string $agent_name Agent name to get its id.
1261 * @param boolean $io_safe_input If it is true transform to safe string, by default false.
1262 *
1263 * @return int Id from the agent of the given name.
1264 */
1265function agents_get_agent_id ($agent_name, $io_safe_input = false) {
1266	if ($io_safe_input) {
1267		$agent_name = io_safe_input($agent_name);
1268	}
1269	return (int) db_get_value ('id_agente', 'tagente', 'nombre', $agent_name);
1270}
1271
1272/**
1273 * Get name of an agent.
1274 *
1275 * @param int $id_agent Agent id.
1276 * @param string $case Case (upper, lower, none)
1277 *
1278 * @return string Name of the given agent.
1279 */
1280function agents_get_name ($id_agent, $case = "none") {
1281	$agent = (string) db_get_value ('nombre',
1282		'tagente', 'id_agente', (int) $id_agent);
1283
1284	// Version 3.0 has enforced case sensitive agent names
1285	// so we always should show real case names.
1286	switch ($case) {
1287		case "upper":
1288			return mb_strtoupper ($agent,"UTF-8");
1289			break;
1290		case "lower":
1291			return mb_strtolower ($agent,"UTF-8");
1292			break;
1293		case "none":
1294		default:
1295			return ($agent);
1296			break;
1297	}
1298}
1299
1300/**
1301 * Get the number of pandora data packets in the database.
1302 *
1303 * In case an array is passed, it will have a value for every agent passed
1304 * incl. a total otherwise it will just return the total
1305 *
1306 * @param mixed Agent id or array of agent id's, 0 for all
1307 *
1308 * @return mixed The number of data in the database
1309 */
1310function agents_get_modules_data_count ($id_agent = 0) {
1311	$id_agent = safe_int ($id_agent, 1);
1312
1313	if (empty ($id_agent)) {
1314		$id_agent = array ();
1315	}
1316	else {
1317		$id_agent = (array) $id_agent;
1318	}
1319
1320	$count = array ();
1321	$count["total"] = 0;
1322
1323	$query[0] = "SELECT COUNT(*) FROM tagente_datos";
1324
1325	foreach ($id_agent as $agent_id) {
1326		//Init value
1327		$count[$agent_id] = 0;
1328		$modules = array_keys (agents_get_modules ($agent_id));
1329		foreach ($query as $sql) {
1330			//Add up each table's data
1331			//Avoid the count over empty array
1332			if (!empty($modules))
1333				$count[$agent_id] += (int) db_get_sql ($sql .
1334					" WHERE id_agente_modulo IN (".implode (",", $modules).")", 0, true);
1335		}
1336		//Add total agent count to total count
1337		$count["total"] += $count[$agent_id];
1338	}
1339
1340	if ($count["total"] == 0) {
1341		foreach ($query as $sql) {
1342			$count["total"] += (int) db_get_sql ($sql, 0, true);
1343		}
1344	}
1345
1346	return $count; //Return the array
1347}
1348
1349/**
1350 * Check if an agent has alerts fired.
1351 *
1352 * @param int Agent id.
1353 *
1354 * @return bool True if the agent has fired alerts.
1355 */
1356function agents_check_alert_fired ($id_agent) {
1357	$sql = sprintf ("SELECT COUNT(*)
1358		FROM talert_template_modules, tagente_modulo
1359		WHERE talert_template_modules.id_agent_module = tagente_modulo.id_agente_modulo
1360			AND times_fired > 0 AND id_agente = %d",
1361	$id_agent);
1362
1363	$value = db_get_sql ($sql);
1364	if ($value > 0)
1365		return true;
1366
1367	return false;
1368}
1369
1370/**
1371 * Get the interval of an agent.
1372 *
1373 * @param int Agent id.
1374 *
1375 * @return int The interval value of a given agent
1376 */
1377function agents_get_interval ($id_agent) {
1378	return (int) db_get_value ('intervalo', 'tagente', 'id_agente', $id_agent);
1379}
1380
1381/**
1382 * Get the operating system of an agent.
1383 *
1384 * @param int Agent id.
1385 *
1386 * @return int The interval value of a given agent
1387 */
1388function agents_get_os ($id_agent) {
1389	return (int) db_get_value ('id_os', 'tagente', 'id_agente', $id_agent);
1390}
1391
1392/**
1393 * Get the flag value of an agent module.
1394 *
1395 * @param int Agent module id.
1396 *
1397 * @return bool The flag value of an agent module.
1398 */
1399function agents_give_agentmodule_flag ($id_agent_module) {
1400	return db_get_value ('flag', 'tagente_modulo', 'id_agente_modulo', $id_agent_module);
1401}
1402
1403/**
1404 * Assign an IP address to an agent.
1405 *
1406 * @param int Agent id
1407 * @param string IP address to assign
1408 */
1409function agents_add_address ($id_agent, $ip_address) {
1410	global $config;
1411
1412	// Check if already is attached to agent
1413	switch ($config["dbtype"]) {
1414		case "mysql":
1415			$sql = sprintf ("SELECT COUNT(`ip`)
1416				FROM taddress_agent, taddress
1417				WHERE taddress_agent.id_a = taddress.id_a
1418					AND ip = '%s' AND id_agent = %d",$ip_address,$id_agent);
1419			break;
1420		case "postgresql":
1421		case "oracle":
1422			$sql = sprintf ("SELECT COUNT(ip)
1423				FROM taddress_agent, taddress
1424				WHERE taddress_agent.id_a = taddress.id_a
1425					AND ip = '%s' AND id_agent = %d", $ip_address, $id_agent);
1426			break;
1427	}
1428	$current_address = db_get_sql ($sql);
1429	if ($current_address > 0)
1430		return;
1431
1432	// Look for a record with this IP Address
1433	$id_address = (int) db_get_value ('id_a', 'taddress', 'ip', $ip_address);
1434
1435	if ($id_address === 0) {
1436		// Create IP address in tadress table
1437		$id_address = db_process_sql_insert('taddress', array('ip' => $ip_address));
1438	}
1439
1440	// Add address to agent
1441	$values = array('id_a' => $id_address, 'id_agent' => $id_agent);
1442	db_process_sql_insert('taddress_agent', $values);
1443}
1444
1445/**
1446 * Unassign an IP address from an agent.
1447 *
1448 * @param int Agent id
1449 * @param string IP address to unassign
1450 */
1451function agents_delete_address ($id_agent, $ip_address) {
1452	global $config;
1453
1454	$sql = sprintf ("SELECT id_ag
1455		FROM taddress_agent, taddress
1456		WHERE taddress_agent.id_a = taddress.id_a
1457			AND ip = '%s'
1458			AND id_agent = %d", $ip_address, $id_agent);
1459	$id_ag = db_get_sql ($sql);
1460	if ($id_ag !== false) {
1461		db_process_sql_delete('taddress_agent', array('id_ag' => $id_ag));
1462	}
1463
1464	$agent_name = agents_get_name($id_agent, "");
1465	db_pandora_audit("Agent management",
1466		"Deleted IP $ip_address from agent '$agent_name'");
1467
1468	// Need to change main address?
1469	if (agents_get_address($id_agent) == $ip_address) {
1470		$new_ips = agents_get_addresses ($id_agent);
1471		if (empty($new_ips)) {
1472			$new_ip = '';
1473		}
1474		else {
1475			$new_ip = reset($new_ips);
1476		}
1477
1478		// Change main address in agent to first one in the list
1479
1480		db_process_sql_update('tagente',
1481			array('direccion' => $new_ip),
1482			array('id_agente' => $id_agent));
1483
1484		return $new_ip;
1485	}
1486}
1487
1488/**
1489 * Get address of an agent.
1490 *
1491 * @param int Agent id
1492 *
1493 * @return string The address of the given agent
1494 */
1495function agents_get_address ($id_agent) {
1496	return (string) db_get_value ('direccion', 'tagente', 'id_agente', (int) $id_agent);
1497}
1498
1499/**
1500 * Get the agent that matches an IP address
1501 *
1502 * @param string IP address to get the agents.
1503 *
1504 * @return mixed The agent that has the IP address given. False if none were found.
1505 */
1506function agents_get_agent_with_ip ($ip_address) {
1507	global $config;
1508
1509	switch ($config["dbtype"]) {
1510		case "mysql":
1511			$sql = sprintf ('SELECT tagente.*
1512				FROM tagente, taddress, taddress_agent
1513				WHERE tagente.id_agente = taddress_agent.id_agent
1514					AND taddress_agent.id_a = taddress.id_a
1515					AND ip = "%s"', $ip_address);
1516			break;
1517		case "postgresql":
1518		case "oracle":
1519			$sql = sprintf ('SELECT tagente.*
1520				FROM tagente, taddress, taddress_agent
1521				WHERE tagente.id_agente = taddress_agent.id_agent
1522					AND taddress_agent.id_a = taddress.id_a
1523					AND ip = \'%s\'', $ip_address);
1524			break;
1525	}
1526
1527	return db_get_row_sql ($sql);
1528}
1529
1530/**
1531 * Get all IP addresses of an agent
1532 *
1533 * @param int Agent id
1534 *
1535 * @return array Array with the IP address of the given agent or an empty array.
1536 */
1537function agents_get_addresses ($id_agent) {
1538	if (is_array($id_agent)) {
1539		$sql = sprintf ("SELECT ip
1540			FROM taddress_agent, taddress
1541			WHERE taddress_agent.id_a = taddress.id_a
1542				AND id_agent IN (%s)", implode(",", $id_agent));
1543	}
1544	else {
1545		$sql = sprintf ("SELECT ip
1546			FROM taddress_agent, taddress
1547			WHERE taddress_agent.id_a = taddress.id_a
1548				AND id_agent = %d", $id_agent);
1549	}
1550
1551	$ips = db_get_all_rows_sql ($sql);
1552
1553	if ($ips === false) {
1554		$ips = array ();
1555	}
1556
1557	$ret_arr = array ();
1558	foreach ($ips as $row) {
1559		$ret_arr[$row["ip"]] = $row["ip"];
1560	}
1561
1562	return $ret_arr;
1563}
1564
1565/**
1566 * Get the worst status of all modules of a given agent from the counts.
1567 *
1568 * @param array agent to check.
1569 *
1570 * @return int Worst status of an agent for all of its modules.
1571 * return -1 if the data are wrong
1572 */
1573function agents_get_status_from_counts($agent) {
1574
1575
1576	// Check if in the data there are all the necessary values
1577	if (!isset($agent['normal_count']) &&
1578		!isset($agent['warning_count']) &&
1579		!isset($agent['critical_count']) &&
1580		!isset($agent['unknown_count']) &&
1581		!isset($agent['notinit_count']) &&
1582		!isset($agent['total_count'])) {
1583		return -1;
1584	}
1585
1586	# Juanma (05/05/2014) Fix:  This status is not init! 0 modules or all not init
1587	if ($agent['notinit_count'] == $agent['total_count']) {
1588		return AGENT_MODULE_STATUS_NOT_INIT;
1589	}
1590	if ($agent['critical_count'] > 0) {
1591		return AGENT_MODULE_STATUS_CRITICAL_BAD;
1592	}
1593	else if ($agent['warning_count'] > 0) {
1594		return AGENT_MODULE_STATUS_WARNING;
1595	}
1596	else if ($agent['unknown_count'] > 0) {
1597		return AGENT_MODULE_STATUS_UNKNOWN;
1598	}
1599	else if ($agent['normal_count'] == $agent['total_count']) {
1600		return AGENT_MODULE_STATUS_NORMAL;
1601	}
1602	else if ($agent['normal_count'] + $agent['notinit_count'] == $agent['total_count']) {
1603		return AGENT_MODULE_STATUS_NORMAL;
1604	}
1605	//~ else if($agent['notinit_count'] == $agent['total_count']) {
1606		//~ return AGENT_MODULE_STATUS_NORMAL;
1607	//~ }
1608
1609	return -1;
1610}
1611
1612/**
1613 * Get the worst status of all modules of a given agent.
1614 *
1615 * @param int Id agent to check.
1616 * @param bool Whether the call check ACLs or not
1617 *
1618 * @return int Worst status of an agent for all of its modules.
1619 * The value -1 is returned in case the agent has exceed its interval.
1620 */
1621function agents_get_status($id_agent = 0, $noACLs = false) {
1622	global $config;
1623
1624	if (!$noACLs) {
1625		$modules = agents_get_modules ($id_agent, 'id_agente_modulo',
1626			array('disabled' => 0), true, false);
1627	}
1628	else {
1629		$filter_modules['id_agente'] = $id_agent;
1630		$filter_modules['disabled'] = 0;
1631		$filter_modules['delete_pending'] = 0;
1632		// Get all non disabled modules of the agent
1633		$all_modules = db_get_all_rows_filter('tagente_modulo',
1634			$filter_modules, 'id_agente_modulo');
1635
1636		$result_modules = array();
1637		// Skip non init modules
1638		foreach ($all_modules as $module) {
1639			if (modules_get_agentmodule_is_init($module['id_agente_modulo'])) {
1640				$modules[] = $module['id_agente_modulo'];
1641			}
1642		}
1643	}
1644
1645	$modules_status = array();
1646	$modules_async = 0;
1647	foreach ($modules as $module) {
1648		$modules_status[] = modules_get_agentmodule_status($module);
1649
1650		$module_type = modules_get_agentmodule_type($module);
1651		if (($module_type >= 21 && $module_type <= 23) ||
1652			$module_type == 100) {
1653			$modules_async++;
1654		}
1655	}
1656
1657	// If all the modules are asynchronous or keep alive, the group cannot be unknown
1658	if ($modules_async < count($modules)) {
1659		$time = get_system_time ();
1660
1661		switch ($config["dbtype"]) {
1662			case "mysql":
1663				$status = db_get_value_filter ('COUNT(*)',
1664					'tagente',
1665					array ('id_agente' => (int) $id_agent,
1666						'UNIX_TIMESTAMP(ultimo_contacto) + intervalo * 2 > '.$time));
1667				break;
1668			case "postgresql":
1669				$status = db_get_value_filter ('COUNT(*)',
1670					'tagente',
1671					array ('id_agente' => (int) $id_agent,
1672						'ceil(date_part(\'epoch\', ultimo_contacto)) + intervalo * 2 > '.$time));
1673				break;
1674			case "oracle":
1675				$status = db_get_value_filter ('count(*)',
1676					'tagente',
1677					array ('id_agente' => (int) $id_agent,
1678						'ceil((to_date(ultimo_contacto, \'YYYY-MM-DD HH24:MI:SS\') - to_date(\'19700101000000\',\'YYYYMMDDHH24MISS\')) * (' . SECONDS_1DAY . ')) > ' . $time));
1679				break;
1680		}
1681
1682		if (! $status)
1683			return AGENT_MODULE_STATUS_UNKNOWN;
1684	}
1685
1686	// Checking if any module has alert fired
1687	if (is_int(array_search(AGENT_MODULE_STATUS_CRITICAL_ALERT, $modules_status))) {
1688		return AGENT_MODULE_STATUS_CRITICAL_ALERT;
1689	}
1690	// Checking if any module has alert fired
1691	elseif (is_int(array_search(AGENT_MODULE_STATUS_WARNING_ALERT, $modules_status))) {
1692		return AGENT_MODULE_STATUS_WARNING_ALERT;
1693	}
1694	// Checking if any module has critical status
1695	elseif (is_int(array_search(AGENT_MODULE_STATUS_CRITICAL_BAD, $modules_status))) {
1696		return AGENT_MODULE_STATUS_CRITICAL_BAD;
1697	}
1698	// Checking if any module has critical status
1699	elseif (is_int(array_search(AGENT_MODULE_STATUS_NORMAL_ALERT, $modules_status))) {
1700		return AGENT_STATUS_ALERT_FIRED;
1701	}
1702	// Checking if any module has warning status
1703	elseif (is_int(array_search(AGENT_MODULE_STATUS_WARNING,$modules_status))) {
1704		return AGENT_MODULE_STATUS_WARNING;
1705	}
1706	// Checking if any module has unknown status
1707	elseif (is_int(array_search(AGENT_MODULE_STATUS_UNKNOWN, $modules_status))) {
1708		return AGENT_MODULE_STATUS_UNKNOWN;
1709	}
1710	else {
1711		return AGENT_MODULE_STATUS_NORMAL;
1712	}
1713}
1714
1715/**
1716 * Delete an agent from the database.
1717 *
1718 * @param mixed An array of agents ids or a single integer id to be erased
1719 * @param bool Disable the ACL checking, for default false.
1720 *
1721 * @return bool False if error, true if success.
1722 */
1723function agents_delete_agent ($id_agents, $disableACL = false) {
1724	global $config;
1725
1726	$error = false;
1727
1728	//Convert single values to an array
1729	if (! is_array ($id_agents))
1730		$id_agents = (array) $id_agents;
1731
1732	foreach ($id_agents as $id_agent) {
1733		$id_agent = (int) $id_agent; //Cast as integer
1734		if ($id_agent < 1)
1735		continue;
1736
1737		$agent_name = agents_get_name($id_agent, "");
1738
1739		/* Check for deletion permissions */
1740		$id_group = agents_get_agent_group ($id_agent);
1741		if ((! check_acl ($config['id_user'], $id_group, "AW")) && !$disableACL) {
1742			return false;
1743		}
1744
1745		//A variable where we store that long subquery thing for
1746		//modules
1747		$where_modules = "ANY(SELECT id_agente_modulo FROM tagente_modulo WHERE id_agente = ".$id_agent.")";
1748
1749		//IP address
1750		$sql = sprintf ("SELECT id_ag
1751			FROM taddress_agent, taddress
1752			WHERE taddress_agent.id_a = taddress.id_a
1753				AND id_agent = %d",
1754		$id_agent);
1755		$addresses = db_get_all_rows_sql ($sql);
1756
1757		if ($addresses === false) {
1758			$addresses = array ();
1759		}
1760		foreach ($addresses as $address) {
1761			db_process_delete_temp ("taddress_agent",
1762				"id_ag", $address["id_ag"]);
1763		}
1764
1765		// We cannot delete tagente_datos and tagente_datos_string here
1766		// because it's a huge ammount of time. tagente_module has a special
1767		// field to mark for delete each module of agent deleted and in
1768		// daily maintance process, all data for that modules are deleted
1769
1770		//Alert
1771		db_process_delete_temp ("talert_template_modules",
1772			"id_agent_module", $where_modules, true);
1773
1774		//Events (up/down monitors)
1775		// Dont delete here, could be very time-exausting, let the daily script
1776		// delete them after XXX days
1777		// db_process_delete_temp ("tevento", "id_agente", $id_agent);
1778
1779		//Graphs, layouts, reports & networkmapenterprise
1780		db_process_delete_temp ("tgraph_source",
1781			"id_agent_module", $where_modules, true);
1782		db_process_delete_temp ("tlayout_data",
1783			"id_agente_modulo", $where_modules, true);
1784		db_process_delete_temp ("treport_content",
1785			"id_agent_module", $where_modules, true);
1786		if (enterprise_installed()) {
1787			$nodes = db_get_all_rows_filter(
1788				"tnetworkmap_enterprise_nodes",
1789				array("id_agent" => $id_agent));
1790			if (empty($nodes)) {
1791				$nodes = array();
1792			}
1793
1794			foreach ($nodes as $node) {
1795				db_process_delete_temp ("tnetworkmap_ent_rel_nodes",
1796					"parent", $node['id']);
1797				db_process_delete_temp ("tnetworkmap_ent_rel_nodes",
1798					"child", $node['id']);
1799			}
1800
1801			db_process_delete_temp ("tnetworkmap_enterprise_nodes",
1802				"id_agent", $id_agent);
1803		}
1804
1805		//Planned Downtime
1806		db_process_delete_temp ("tplanned_downtime_agents", "id_agent",
1807			$id_agent);
1808
1809		//The status of the module
1810		db_process_delete_temp ("tagente_estado", "id_agente", $id_agent);
1811
1812		//The actual modules, don't put anything based on
1813		// DONT Delete this, just mark for deletion
1814		// db_process_delete_temp ("tagente_modulo", "id_agente", $id_agent);
1815
1816		db_process_sql_update ('tagente_modulo',
1817			array ('delete_pending' => 1, 'disabled' => 1, 'nombre' => 'pendingdelete'),
1818			'id_agente = '. $id_agent);
1819
1820		// Access entries
1821		// Dont delete here, this records are deleted in daily script
1822		// db_process_delete_temp ("tagent_access", "id_agent", $id_agent);
1823
1824		// Delete agent policies
1825		enterprise_include_once('include/functions_policies.php');
1826		enterprise_hook('policies_delete_agent', array($id_agent));
1827
1828		// Delete agent in networkmap enterprise
1829		enterprise_include_once('include/functions_networkmap_enterprise.php');
1830		enterprise_hook('networkmap_enterprise_delete_nodes_by_agent', array($id_agent));
1831
1832		// tagente_datos_inc
1833		// Dont delete here, this records are deleted later, in database script
1834		// db_process_delete_temp ("tagente_datos_inc", "id_agente_modulo", $where_modules, true);
1835
1836		// Delete remote configuration
1837		if (enterprise_installed()) {
1838			if (isset ($config["remote_config"])) {
1839				enterprise_include_once('include/functions_config_agents.php');
1840				if (enterprise_hook('config_agents_has_remote_configuration', array($id_agent))) {
1841					$agent_name = agents_get_name($id_agent);
1842					$agent_name = io_safe_output($agent_name);
1843					$agent_md5 = md5 ($agent_name, false);
1844
1845					// Agent remote configuration editor
1846					$file_name = $config["remote_config"] . "/conf/" . $agent_md5 . ".conf";
1847
1848					$error = !@unlink ($file_name);
1849
1850					if (!$error) {
1851						$file_name = $config["remote_config"] . "/md5/" . $agent_md5 . ".md5";
1852						$error = !@unlink ($file_name);
1853					}
1854
1855					if ($error) {
1856						db_pandora_audit( "Agent management",
1857							"Error: Deleted agent '$agent_name', the error is in the delete conf or md5.");
1858					}
1859				}
1860			}
1861		}
1862
1863		//And at long last, the agent
1864		db_process_delete_temp ("tagente", "id_agente", $id_agent);
1865
1866		db_pandora_audit( "Agent management",
1867			"Deleted agent '$agent_name'");
1868
1869		// Delete the agent from the metaconsole cache
1870		enterprise_include_once('include/functions_agents.php');
1871		enterprise_hook('agent_delete_from_cache', array($id_agent));
1872
1873		/* Break the loop on error */
1874		if ($error)
1875			break;
1876	}
1877
1878
1879
1880	if ($error) {
1881		return false;
1882	}
1883	else {
1884		return true;
1885	}
1886}
1887
1888/**
1889 * This function gets the agent group for a given agent module
1890 *
1891 * @param int The agent module id
1892 *
1893 * @return int The group id
1894 */
1895function agents_get_agentmodule_group ($id_module) {
1896	$agent = (int) modules_get_agentmodule_agent ((int) $id_module);
1897	return (int) agents_get_agent_group ($agent);
1898}
1899
1900/**
1901 * This function gets the group for a given agent
1902 *
1903 * @param int The agent id
1904 *
1905 * @return int The group id
1906 */
1907function agents_get_agent_group ($id_agent) {
1908	return (int) db_get_value ('id_grupo', 'tagente', 'id_agente', (int) $id_agent);
1909}
1910
1911/**
1912 * This function gets the count of incidents attached to the agent
1913 *
1914 * @param int The agent id
1915 *
1916 * @return mixed The incidents attached or false
1917 */
1918function agents_get_count_incidents ($id_agent) {
1919	if (empty($id_agent)) {
1920		return false;
1921	}
1922
1923	return db_get_value('count(*)', 'tincidencia', 'id_agent',
1924		$id_agent);
1925}
1926
1927/**
1928 * Get critical monitors by using the status code in modules.
1929 *
1930 * @param int The agent id
1931 * @param string Additional filters
1932 *
1933 * @return mixed The incidents attached or false
1934 */
1935function agents_monitor_critical ($id_agent, $filter="") {
1936
1937	if ($filter) {
1938		$filter = " AND ".$filter;
1939	}
1940
1941	return db_get_sql ("SELECT critical_count
1942		FROM tagente
1943		WHERE id_agente = $id_agent" . $filter);
1944}
1945
1946// Get warning monitors by using the status code in modules.
1947
1948function agents_monitor_warning ($id_agent, $filter="") {
1949
1950	if ($filter) {
1951		$filter = " AND ".$filter;
1952	}
1953
1954	return db_get_sql ("SELECT warning_count
1955		FROM tagente
1956		WHERE id_agente = $id_agent" . $filter);
1957}
1958
1959// Get unknown monitors by using the status code in modules.
1960
1961function agents_monitor_unknown ($id_agent, $filter="") {
1962
1963	if ($filter) {
1964		$filter = " AND ".$filter;
1965	}
1966
1967	return db_get_sql ("SELECT unknown_count
1968		FROM tagente
1969		WHERE id_agente = $id_agent" . $filter);
1970}
1971
1972// Get ok monitors by using the status code in modules.
1973function agents_monitor_ok ($id_agent, $filter="") {
1974
1975	if ($filter) {
1976		$filter = " AND ".$filter;
1977	}
1978
1979	return db_get_sql ("SELECT normal_count
1980		FROM tagente
1981		WHERE id_agente = $id_agent" . $filter);
1982}
1983
1984/**
1985 * Get all monitors disabled of an specific agent.
1986 *
1987 * @param int The agent id
1988 * @param string Additional filters
1989 *
1990 * @return mixed Total module count or false
1991 */
1992function agents_monitor_disabled ($id_agent, $filter="") {
1993
1994	if ($filter) {
1995		$filter = " AND ".$filter;
1996	}
1997
1998	return db_get_sql("
1999		SELECT COUNT( DISTINCT tagente_modulo.id_agente_modulo)
2000		FROM tagente, tagente_modulo
2001		WHERE tagente_modulo.id_agente = tagente.id_agente
2002			AND tagente_modulo.disabled = 1
2003			AND tagente.id_agente = $id_agent".$filter);
2004}
2005
2006/**
2007 * Get all monitors notinit of an specific agent.
2008 *
2009 * @param int The agent id
2010 * @param string Additional filters
2011 *
2012 * @return mixed Total module count or false
2013 */
2014function agents_monitor_notinit ($id_agent, $filter="") {
2015
2016	if (!empty($filter)) {
2017		$filter = " AND ".$filter;
2018	}
2019
2020	return db_get_sql ("SELECT notinit_count
2021		FROM tagente
2022		WHERE id_agente = $id_agent" . $filter);
2023}
2024
2025/**
2026 * Get all monitors of an specific agent.
2027 *
2028 * @param int The agent id
2029 * @param string Additional filters
2030 * @param bool Whether to retrieve disabled modules or not
2031 *
2032 * @return mixed Total module count or false
2033 */
2034function agents_monitor_total ($id_agent, $filter = '', $disabled = false) {
2035
2036	if ($filter) {
2037		$filter = " AND ".$filter;
2038	}
2039
2040	$sql = "SELECT COUNT( DISTINCT tagente_modulo.id_agente_modulo)
2041		FROM tagente_estado, tagente, tagente_modulo
2042		WHERE tagente_modulo.id_agente_modulo = tagente_estado.id_agente_modulo
2043			AND tagente_estado.id_agente = tagente.id_agente
2044			AND tagente.id_agente = $id_agent".$filter;
2045
2046	if (!$disabled)
2047		$sql .= " AND tagente.disabled = 0 AND tagente_modulo.disabled = 0";
2048
2049	return db_get_sql ($sql);
2050}
2051
2052//Get alert fired for this agent
2053
2054function agents_get_alerts_fired ($id_agent, $filter="") {
2055
2056	$modules_agent = agents_get_modules($id_agent, "id_agente_modulo", $filter);
2057
2058	if (empty($modules_agent)) {
2059		return 0;
2060	}
2061
2062	$mod_clause = "(".implode(",", $modules_agent).")";
2063
2064	return db_get_sql ("SELECT COUNT(times_fired)
2065		FROM talert_template_modules
2066		WHERE times_fired != 0 AND id_agent_module IN ".$mod_clause);
2067}
2068
2069//Returns the alert image to display tree view
2070
2071function agents_tree_view_alert_img ($alert_fired) {
2072
2073	if ($alert_fired) {
2074		return ui_print_status_image (STATUS_ALERT_FIRED, __('Alert fired'), true);
2075	}
2076	else {
2077		return ui_print_status_image (STATUS_ALERT_NOT_FIRED, __('Alert not fired'), true);
2078	}
2079}
2080
2081//Returns the alert ball image to display tree view
2082
2083function agents_tree_view_alert_img_ball ($alert_fired) {
2084
2085	if ($alert_fired) {
2086		return ui_print_status_image (STATUS_ALERT_FIRED_BALL, __('Alert fired'), true);
2087	}
2088	else {
2089		return ui_print_status_image (STATUS_ALERT_NOT_FIRED_BALL, __('Alert not fired'), true);
2090	}
2091}
2092
2093//Returns the status image to display tree view
2094
2095function agents_tree_view_status_img ($critical, $warning, $unknown, $total, $notinit) {
2096	if ($total == 0 || $total == $notinit) {
2097		return ui_print_status_image (STATUS_AGENT_NO_MONITORS,
2098			__('No Monitors'), true);
2099	}
2100	if ($critical > 0) {
2101		return ui_print_status_image (STATUS_AGENT_CRITICAL,
2102			__('At least one module in CRITICAL status'), true);
2103	}
2104	else if ($warning > 0) {
2105		return ui_print_status_image (STATUS_AGENT_WARNING,
2106			__('At least one module in WARNING status'), true);
2107	}
2108	else if ($unknown > 0) {
2109		return ui_print_status_image (STATUS_AGENT_DOWN,
2110			__('At least one module is in UKNOWN status'), true);
2111	}
2112	else {
2113		return ui_print_status_image (STATUS_AGENT_OK,
2114			__('All Monitors OK'), true);
2115	}
2116}
2117
2118//Returns the status ball image to display tree view
2119
2120function agents_tree_view_status_img_ball ($critical, $warning, $unknown, $total, $notinit) {
2121	if ($total == 0 || $total == $notinit) {
2122		return ui_print_status_image (STATUS_AGENT_NO_MONITORS_BALL,
2123			__('No Monitors'), true);
2124	}
2125	if ($critical > 0) {
2126		return ui_print_status_image (STATUS_AGENT_CRITICAL_BALL,
2127			__('At least one module in CRITICAL status'), true);
2128	}
2129	else if ($warning > 0) {
2130		return ui_print_status_image (STATUS_AGENT_WARNING_BALL,
2131			__('At least one module in WARNING status'), true);
2132	}
2133	else if ($unknown > 0) {
2134		return ui_print_status_image (STATUS_AGENT_DOWN_BALL,
2135			__('At least one module is in UKNOWN status'), true);
2136	}
2137	else {
2138		return ui_print_status_image (STATUS_AGENT_OK_BALL,
2139			__('All Monitors OK'), true);
2140	}
2141}
2142
2143//Returns the status image to display agent detail view
2144
2145function agents_detail_view_status_img ($critical, $warning, $unknown, $total, $notinit) {
2146	if ($total == 0 || $total == $notinit) {
2147		return ui_print_status_image (STATUS_AGENT_NOT_INIT,
2148			__('No Monitors'), true, false, 'images');
2149	}
2150	else if ($critical > 0) {
2151		return ui_print_status_image (STATUS_AGENT_CRITICAL,
2152			__('At least one module in CRITICAL status'), true, false, 'images');
2153	}
2154	else if ($warning > 0) {
2155		return ui_print_status_image (STATUS_AGENT_WARNING,
2156			__('At least one module in WARNING status'), true, false, 'images');
2157	}
2158	else if ($unknown > 0) {
2159		return ui_print_status_image (STATUS_AGENT_UNKNOWN,
2160			__('At least one module is in UKNOWN status'), true, false, 'images');
2161	}
2162	else {
2163		return ui_print_status_image (STATUS_AGENT_OK,
2164			__('All Monitors OK'), true, false, 'images');
2165	}
2166}
2167
2168function agents_update_gis($idAgente, $latitude, $longitude, $altitude,
2169	$ignore_new_gis_data, $manual_placement, $start_timestamp,
2170	$end_timestamp, $number_of_packages, $description_save_history,
2171	$description_update_gis, $description_first_insert) {
2172
2173	$previusAgentGISData = db_get_row_sql("
2174		SELECT *
2175		FROM tgis_data_status
2176		WHERE tagente_id_agente = " . $idAgente);
2177
2178	db_process_sql_update('tagente',
2179		array('update_gis_data' => $updateGisData),
2180		array('id_agente' => $idAgente));
2181
2182	$return = false;
2183
2184	if ($previusAgentGISData !== false) {
2185		$return = db_process_sql_insert('tgis_data_history', array(
2186			"longitude" => $previusAgentGISData['stored_longitude'],
2187			"latitude" => $previusAgentGISData['stored_latitude'],
2188			"altitude" => $previusAgentGISData['stored_altitude'],
2189			"start_timestamp" => $previusAgentGISData['start_timestamp'],
2190			"end_timestamp" => $end_timestamp,
2191			"description" => $description_save_history,
2192			"manual_placement" => $previusAgentGISData['manual_placement'],
2193			"number_of_packages" => $previusAgentGISData['number_of_packages'],
2194			"tagente_id_agente" => $previusAgentGISData['tagente_id_agente']
2195		));
2196		$return = db_process_sql_update('tgis_data_status', array(
2197				"tagente_id_agente" => $idAgente,
2198				"current_longitude" => $longitude,
2199				"current_latitude" => $latitude,
2200				"current_altitude" => $altitude,
2201				"stored_longitude" => $longitude,
2202				"stored_latitude" => $latitude,
2203				"stored_altitude" => $altitude,
2204				"start_timestamp" => $start_timestamp,
2205				"manual_placement" => $manual_placement,
2206				"description" => $description_update_gis,
2207				"number_of_packages" => $number_of_packages),
2208			array("tagente_id_agente" => $idAgente));
2209	}
2210	else {
2211		//The table "tgis_data_status" have not a autonumeric
2212		//then the mysql_insert_id function return 0
2213
2214		$prev_count = db_get_num_rows("SELECT * FROM tgis_data_status");
2215
2216		$return = db_process_sql_insert('tgis_data_status', array(
2217			"tagente_id_agente" => $idAgente,
2218			"current_longitude" => $longitude,
2219			"current_latitude" => $latitude,
2220			"current_altitude" => $altitude,
2221			"stored_longitude" => $longitude,
2222			"stored_latitude" => $latitude,
2223			"stored_altitude" => $altitude,
2224			"start_timestamp" => $start_timestamp,
2225			"manual_placement" => $manual_placement,
2226			"description" => $description_first_insert,
2227			"number_of_packages" => $number_of_packages
2228		));
2229
2230
2231		$count = db_get_num_rows("SELECT * FROM tgis_data_status");
2232
2233		if ($return === 0) {
2234			if ($prev_count < $count) {
2235				$return = true;
2236			}
2237		}
2238	}
2239
2240	return (bool)$return;
2241}
2242
2243/**
2244 * Returns a list with network interfaces data by agent
2245 *
2246 * @param array Agents with the columns 'id_agente', 'nombre' and 'id_grupo'.
2247 * @param mixed A filter to search the agents if the first parameter is false.
2248 *
2249 * @return array A list of network interfaces information by agents.
2250 */
2251function agents_get_network_interfaces ($agents = false, $agents_filter = false) {
2252	global $config;
2253
2254	if ($agents === false) {
2255		$filter = false;
2256		if ($agents_filter !== false) {
2257			$filter = $agents_filter;
2258		}
2259		$fields = array(
2260				'id_agente',
2261				'nombre',
2262				'id_grupo'
2263			);
2264		$agents = agents_get_agents($filter, $fields);
2265	}
2266
2267	$ni_by_agents = array();
2268
2269	foreach ($agents as $agent) {
2270		$agent_id = $agent['id_agente'];
2271		$agent_group_id = $agent['id_grupo'];
2272		$agent_name = $agent['nombre'];
2273		$agent_interfaces = array();
2274
2275		$accepted_module_types = array();
2276		$remote_snmp_proc = (int) db_get_value("id_tipo", "ttipo_modulo", "nombre", "remote_snmp_proc");
2277		if ($remote_snmp_proc)
2278			$accepted_module_types[] = $remote_snmp_proc;
2279		$remote_icmp_proc = (int) db_get_value("id_tipo", "ttipo_modulo", "nombre", "remote_icmp_proc");
2280		if ($remote_icmp_proc)
2281			$accepted_module_types[] = $remote_icmp_proc;
2282		$remote_tcp_proc = (int) db_get_value("id_tipo", "ttipo_modulo", "nombre", "remote_tcp_proc");
2283		if ($remote_tcp_proc)
2284			$accepted_module_types[] = $remote_tcp_proc;
2285		$generic_proc = (int) db_get_value("id_tipo", "ttipo_modulo", "nombre", "generic_proc");
2286		if ($generic_proc)
2287			$accepted_module_types[] = $generic_proc;
2288
2289		if (empty($accepted_module_types))
2290			$accepted_module_types[] = 0; // No modules will be returned
2291
2292		$columns = array(
2293				"id_agente_modulo",
2294				"nombre",
2295				"ip_target"
2296			);
2297
2298		if ($config['dbtype'] == 'oracle')
2299			$columns[] = 'TO_CHAR(descripcion) AS descripcion';
2300		else
2301			$columns[] = 'descripcion';
2302
2303		$filter = " id_agente = $agent_id AND disabled = 0 AND id_tipo_modulo IN (".implode(",", $accepted_module_types).") AND nombre LIKE 'ifOperStatus_%'";
2304
2305		$modules = agents_get_modules($agent_id, $columns, $filter, true, false);
2306
2307		if (!empty($modules)) {
2308			$interfaces = array();
2309
2310			foreach ($modules as $module) {
2311				$module_name = (string) $module['nombre'];
2312
2313				// Trying to get the interface name from the module name
2314				if (preg_match ("/_(.+)$/", $module_name, $matches)) {
2315					if ($matches[1]) {
2316						$interface_name = $matches[1];
2317						$interface_name_escaped = str_replace("/", "\/", $interface_name);
2318
2319						if (preg_match ("/^ifOperStatus_$interface_name_escaped$/i", $module_name, $matches)) {
2320							$interfaces[$interface_name] = $module;
2321						}
2322
2323					}
2324				}
2325			}
2326			unset($modules);
2327
2328			foreach ($interfaces as $interface_name => $module) {
2329				$interface_name_escaped = str_replace("/", "\/", $interface_name);
2330
2331				$module_id = $module['id_agente_modulo'];
2332				$module_name = $module['nombre'];
2333				$module_description = $module['descripcion'];
2334				$db_status = modules_get_agentmodule_status($module_id);
2335				$module_value = modules_get_last_value ($module_id);
2336				modules_get_status($module_id, $db_status, $module_value, $status, $title);
2337				$status_image = ui_print_status_image($status, $title, true);
2338
2339				$ip_target = "--";
2340				// Trying to get something like an IP from the description
2341				if (preg_match ("/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/", $module_description, $matches)
2342						|| preg_match ("/(((?=(?>.*?(::))(?!.+\3)))\3?|([\dA-F]{1,4}(\3|:?)|\2))(?4){5}((?4){2}|(25[0-5]|
2343							(2[0-4]|1\d|[1-9])?\d)(\.(?7)){3})/i", $module_description, $matches) && $matches[0]) {
2344
2345					$ip_target = $matches[0];
2346				}
2347				// else if (isset($module['ip_target']) && !empty($module['ip_target'])) {
2348				// 	$ip_target = $module['ip_target'];
2349				// }
2350				$mac = "--";
2351				// Trying to get something like a mac from the description
2352				if (preg_match ("/([0-9a-f]{1,2}[\.:-]){5}([0-9a-f]{1,2})/i", $module_description, $matches)) {
2353					if ($matches[0]) {
2354						$mac = $matches[0];
2355					}
2356				}
2357
2358				// Get the ifInOctets and ifOutOctets modules of the interface
2359				$columns = array(
2360						"id_agente_modulo",
2361						"nombre"
2362					);
2363				$interface_traffic_modules = agents_get_modules($agent_id, $columns, "nombre LIKE 'if%Octets_$interface_name'");
2364				if (!empty($interface_traffic_modules) && count($interface_traffic_modules) >= 2) {
2365					$interface_traffic_modules_aux = array('in' => '', 'out' => '');
2366					foreach ($interface_traffic_modules as $interface_traffic_module) {
2367						$interface_name_escaped = str_replace("/", "\/", $interface_name);
2368						if (preg_match ("/^if(.+)Octets_$interface_name_escaped$/i", $interface_traffic_module['nombre'], $matches)) {
2369							if (strtolower($matches[1]) == 'in') {
2370								$interface_traffic_modules_aux['in'] = $interface_traffic_module['id_agente_modulo'];
2371							}
2372							elseif (strtolower($matches[1]) == 'out') {
2373								$interface_traffic_modules_aux['out'] = $interface_traffic_module['id_agente_modulo'];
2374							}
2375						}
2376					}
2377					if (!empty($interface_traffic_modules_aux['in']) && !empty($interface_traffic_modules_aux['out'])) {
2378						$interface_traffic_modules = $interface_traffic_modules_aux;
2379					}
2380					else {
2381						$interface_traffic_modules = false;
2382					}
2383				}
2384				else {
2385					$interface_traffic_modules = false;
2386				}
2387
2388				$agent_interfaces[$interface_name] = array();
2389				$agent_interfaces[$interface_name]['status_image'] = $status_image;
2390				$agent_interfaces[$interface_name]['status_module_id'] = $module_id;
2391				$agent_interfaces[$interface_name]['status_module_name'] = $module_name;
2392				$agent_interfaces[$interface_name]['ip'] = $ip_target;
2393				$agent_interfaces[$interface_name]['mac'] = $mac;
2394
2395				if ($interface_traffic_modules !== false) {
2396					$agent_interfaces[$interface_name]['traffic'] = array();
2397					$agent_interfaces[$interface_name]['traffic']['in'] = $interface_traffic_modules['in'];
2398					$agent_interfaces[$interface_name]['traffic']['out'] = $interface_traffic_modules['out'];
2399				}
2400			}
2401		}
2402
2403		if (!empty($agent_interfaces)) {
2404			$ni_by_agents[$agent_id] = array();
2405			$ni_by_agents[$agent_id]['name'] = $agent_name;
2406			$ni_by_agents[$agent_id]['group'] = $agent_group_id;
2407			$ni_by_agents[$agent_id]['interfaces'] = $agent_interfaces;
2408		}
2409	}
2410
2411	return $ni_by_agents;
2412}
2413?>
2414