EVENT_GROUP_REP_ALL];
}
switch ($filter['group_rep']) {
case EVENT_GROUP_REP_ALL:
case EVENT_GROUP_REP_AGENTS:
default:
// No groups option direct update.
$delete_sql = sprintf(
'DELETE FROM tevento
WHERE id_evento = %d',
$id_evento
);
break;
case EVENT_GROUP_REP_EVENTS:
case EVENT_GROUP_REP_EXTRAIDS:
// Group by events.
$sql = events_get_all(
['te.*'],
$filter,
// Offset.
null,
// Limit.
null,
// Order.
null,
// Sort_field.
null,
// Historical table.
$history,
// Return_sql.
true
);
if ((int) $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) {
$sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.id_extra = tf.id_extra
AND tf.max_id_evento = %d',
$sql,
$id_evento
);
} else {
$sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.estado = tf.estado
AND tu.evento = tf.evento
AND tu.id_agente = tf.id_agente
AND tu.id_agentmodule = tf.id_agentmodule
AND tf.max_id_evento = %d',
$sql,
$id_evento
);
}
$target_ids = db_get_all_rows_sql($sql);
// Try to avoid deadlock while updating full set.
if ($target_ids !== false && count($target_ids) > 0) {
$target_ids = array_reduce(
$target_ids,
function ($carry, $item) {
$carry[] = $item['id_evento'];
return $carry;
}
);
$delete_sql = sprintf(
'DELETE FROM tevento WHERE id_evento IN (%s)',
join(', ', $target_ids)
);
}
break;
}
return db_process_sql($delete_sql);
}
/**
* Validates all events matching target filter.
*
* @param integer $id_evento Master event.
* @param integer $status Target status.
* @param array $filter Optional. Filter options.
*
* @return integer Events validated or false if error.
*/
function events_update_status($id_evento, $status, $filter=null)
{
global $config;
if (!$status) {
return false;
}
if (isset($id_evento) === false || $id_evento <= 0) {
return false;
}
if (isset($filter) === false || is_array($filter) === false) {
$filter = ['group_rep' => EVENT_GROUP_REP_ALL];
}
switch ($filter['group_rep']) {
case EVENT_GROUP_REP_ALL:
case EVENT_GROUP_REP_AGENTS:
default:
// No groups option direct update.
$update_sql = sprintf(
'UPDATE tevento
SET estado = %d,
ack_utimestamp = %d,
id_usuario = "%s"
WHERE id_evento = %d',
$status,
time(),
$config['id_user'],
$id_evento
);
break;
case EVENT_GROUP_REP_EVENTS:
case EVENT_GROUP_REP_EXTRAIDS:
// Group by events.
$sql = events_get_all(
['te.*'],
$filter,
// Offset.
null,
// Limit.
null,
// Order.
null,
// Sort_field.
null,
// Historical table.
false,
// Return_sql.
true
);
if ((int) $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) {
$sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.id_extra = tf.id_extra
AND tf.max_id_evento = %d',
$sql,
$id_evento
);
} else {
$sql = sprintf(
'SELECT tu.id_evento FROM tevento tu INNER JOIN ( %s ) tf
ON tu.estado = tf.estado
AND tu.evento = tf.evento
AND tu.id_agente = tf.id_agente
AND tu.id_agentmodule = tf.id_agentmodule
AND tf.max_id_evento = %d',
$sql,
$id_evento
);
}
$target_ids = db_get_all_rows_sql($sql);
// Try to avoid deadlock while updating full set.
if ($target_ids !== false && count($target_ids) > 0) {
$target_ids = array_reduce(
$target_ids,
function ($carry, $item) {
$carry[] = $item['id_evento'];
return $carry;
}
);
$update_sql = sprintf(
'UPDATE tevento
SET estado = %d,
ack_utimestamp = %d,
id_usuario = "%s"
WHERE id_evento IN (%s)',
$status,
time(),
$config['id_user'],
join(',', $target_ids)
);
}
break;
}
$result = db_process_sql($update_sql);
if ($result !== false) {
switch ($status) {
case EVENT_STATUS_NEW:
$status_string = 'New';
break;
case EVENT_STATUS_VALIDATED:
events_change_owner(
$id_evento,
$config['id_user'],
false
);
$status_string = 'Validated';
break;
case EVENT_STATUS_INPROCESS:
$status_string = 'In process';
break;
default:
$status_string = '';
break;
}
events_comment(
$id_evento,
'',
'Change status to '.$status_string
);
}
return $result;
}
/**
* Retrieve all events filtered.
*
* @param array $fields Fields to retrieve.
* @param array $filter Filters to be applied.
* @param integer $offset Offset (pagination).
* @param integer $limit Limit (pagination).
* @param string $order Sort order.
* @param string $sort_field Sort field.
* @param boolean $history Apply on historical table.
* @param boolean $return_sql Return SQL (true) or execute it (false).
* @param string $having Having filter.
* @param boolean $validatedEvents If true, evaluate validated events.
* @param boolean $recursiveGroups If true, filtered groups and their children
* will be search.
* @param boolean $nodeConnected Already connected to node (uses tevento).
*
* Available filters:
* [
* 'date_from'
* 'time_from'
* 'date_to'
* 'time_to'
* 'event_view_hr'
* 'id_agent'
* 'event_type'
* 'severity'
* 'id_group_filter'
* 'status'
* 'agent_alias'
* 'search'
* 'not_search'
* 'id_extra'
* 'id_source_event'
* 'user_comment'
* 'source'
* 'id_user_ack'
* 'owner_user'
* 'tag_with'
* 'tag_without'
* 'filter_only_alert'
* 'search_secondary_groups'
* 'search_recursive_groups'
* 'module_search'
* 'group_rep'
* 'server_id'
* ].
*
* @return array Events.
* @throws Exception On error.
*/
function events_get_all(
$fields,
array $filter,
$offset=null,
$limit=null,
$order=null,
$sort_field=null,
$history=false,
$return_sql=false,
$having='',
$validatedEvents=false,
$recursiveGroups=true,
$nodeConnected=false
) {
global $config;
$user_is_admin = users_is_admin();
if (is_array($filter) === false) {
error_log('[events_get_all] Filter must be an array.');
throw new Exception('[events_get_all] Filter must be an array.');
}
$count = false;
if (is_array($fields) === false && $fields === 'count'
|| (is_array($fields) === true && $fields[0] === 'count')
) {
$fields = ['te.*'];
$count = true;
} else if (is_array($fields) === false) {
error_log('[events_get_all] Fields must be an array or "count".');
throw new Exception(
'[events_get_all] Fields must be an array or "count".'
);
}
if (isset($filter['date_from']) === true
&& empty($filter['date_from']) === false
&& $filter['date_from'] !== '0000-00-00'
) {
$date_from = $filter['date_from'];
}
if (isset($filter['time_from']) === true) {
$time_from = (empty($filter['time_from']) === true) ? '00:00:00' : $filter['time_from'];
}
if (isset($date_from) === true) {
if (isset($time_from) === false) {
$time_from = '00:00:00';
}
$from = $date_from.' '.$time_from;
$sql_filters[] = sprintf(
' AND te.utimestamp >= %d',
strtotime($from)
);
}
if (isset($filter['date_to']) === true
&& empty($filter['date_to']) === false
&& $filter['date_to'] !== '0000-00-00'
) {
$date_to = $filter['date_to'];
}
if (isset($filter['time_to']) === true) {
$time_to = (empty($filter['time_to']) === true) ? '23:59:59' : $filter['time_to'];
}
if (isset($date_to) === true) {
if (isset($time_to) === false) {
$time_to = '23:59:59';
}
$to = $date_to.' '.$time_to;
$sql_filters[] = sprintf(
' AND te.utimestamp <= %d',
strtotime($to)
);
}
if (isset($from) === false) {
if (isset($filter['event_view_hr']) === true && ($filter['event_view_hr'] > 0)) {
$sql_filters[] = sprintf(
' AND utimestamp > UNIX_TIMESTAMP(now() - INTERVAL %d HOUR) ',
$filter['event_view_hr']
);
}
}
if (isset($filter['id_agent']) === true && $filter['id_agent'] > 0) {
$sql_filters[] = sprintf(
' AND te.id_agente = %d ',
$filter['id_agent']
);
}
if (isset($filter['id_agentmodule']) === true && $filter['id_agentmodule'] > 0) {
$sql_filters[] = sprintf(
' AND te.id_agentmodule = %d ',
$filter['id_agentmodule']
);
}
if (empty($filter['event_type']) === false && $filter['event_type'] !== 'all') {
if (is_array($filter['event_type']) === true) {
$type = [];
if (in_array('all', $filter['event_type']) === false) {
foreach ($filter['event_type'] as $event_type) {
if ($event_type != '') {
// If normal, warning, could be several
// (going_up_warning, going_down_warning... too complex.
// Shown to user only "warning, critical and normal".
if ($event_type == 'warning' || $event_type == 'critical' || $event_type == 'normal') {
$type[] = " event_type LIKE '%".$event_type."%' ";
} else if ($event_type == 'not_normal') {
$type[] = " (event_type LIKE '%warning%' OR event_type LIKE '%critical%' OR event_type LIKE '%unknown%') ";
} else if ($event_type != 'all') {
$type[] = " event_type = '".$event_type."'";
}
}
}
$sql_filters[] = ' AND ('.implode(' OR ', $type).')';
}
} else {
if ($filter['event_type'] === 'warning'
|| $filter['event_type'] === 'critical'
|| $filter['event_type'] === 'normal'
) {
$sql_filters[] = ' AND event_type LIKE "%'.$filter['event_type'].'%"';
} else if ($filter['event_type'] === 'not_normal') {
$sql_filters[] = ' AND (event_type LIKE "%warning%"
OR event_type LIKE "%critical%"
OR event_type LIKE "%unknown%")';
} else {
$sql_filters[] = ' AND event_type = "'.$filter['event_type'].'"';
}
}
}
if (isset($filter['severity']) === true && $filter['severity'] !== '' && (int) $filter['severity'] > -1) {
if (is_array($filter['severity']) === true) {
if (in_array(-1, $filter['severity']) === false) {
$not_normal = array_search(EVENT_CRIT_NOT_NORMAL, $filter['severity']);
if ($not_normal !== false) {
unset($filter['severity'][$not_normal]);
$sql_filters[] = sprintf(
' AND criticity != %d',
EVENT_CRIT_NORMAL
);
} else {
$critical_warning = array_search(EVENT_CRIT_WARNING_OR_CRITICAL, $filter['severity']);
if ($critical_warning !== false) {
unset($filter['severity'][$critical_warning]);
$filter['severity'][] = EVENT_CRIT_WARNING;
$filter['severity'][] = EVENT_CRIT_CRITICAL;
}
$critical_normal = array_search(EVENT_CRIT_OR_NORMAL, $filter['severity']);
if ($critical_normal !== false) {
unset($filter['severity'][$critical_normal]);
$filter['severity'][] = EVENT_CRIT_NORMAL;
$filter['severity'][] = EVENT_CRIT_CRITICAL;
}
if (empty($filter['severity']) === false) {
$filter['severity'] = implode(',', $filter['severity']);
$sql_filters[] = sprintf(
' AND criticity IN (%s)',
$filter['severity']
);
}
}
}
} else {
switch ($filter['severity']) {
case EVENT_CRIT_MAINTENANCE:
case EVENT_CRIT_INFORMATIONAL:
case EVENT_CRIT_NORMAL:
case EVENT_CRIT_MINOR:
case EVENT_CRIT_WARNING:
case EVENT_CRIT_MAJOR:
case EVENT_CRIT_CRITICAL:
default:
$sql_filters[] = sprintf(
' AND criticity = %d ',
$filter['severity']
);
break;
case EVENT_CRIT_WARNING_OR_CRITICAL:
$sql_filters[] = sprintf(
' AND (criticity = %d OR criticity = %d)',
EVENT_CRIT_WARNING,
EVENT_CRIT_CRITICAL
);
break;
case EVENT_CRIT_NOT_NORMAL:
$sql_filters[] = sprintf(
' AND criticity != %d',
EVENT_CRIT_NORMAL
);
break;
case EVENT_CRIT_OR_NORMAL:
$sql_filters[] = sprintf(
' AND (criticity = %d OR criticity = %d)',
EVENT_CRIT_NORMAL,
EVENT_CRIT_CRITICAL
);
break;
}
}
}
$groups = (isset($filter['id_group_filter']) === true) ? $filter['id_group_filter'] : null;
if ((bool) $user_is_admin === false
&& isset($groups) === false
) {
// Not being filtered by group but not an admin, limit results.
$groups = array_keys(users_get_groups(false, 'AR'));
}
if (isset($groups) === true
&& (is_array($groups) === true || ($groups > 0))
) {
if ($recursiveGroups === true
|| (isset($filter['search_recursive_groups']) === true
&& (bool) $filter['search_recursive_groups'] === true)
) {
// Add children groups.
$children = [];
if (is_array($groups) === true) {
foreach ($groups as $g) {
$children = array_merge(
groups_get_children($g),
$children
);
}
} else {
$children = groups_get_children($groups);
}
if (is_array($groups) === true) {
$_groups = $groups;
} else {
$_groups = [ $groups ];
}
if (empty($children) === false) {
foreach ($children as $child) {
$_groups[] = (int) $child['id_grupo'];
}
}
if ((bool) $user_is_admin === false) {
$user_groups = users_get_groups(false, 'AR');
$_groups = array_intersect(
$_groups,
array_keys($user_groups)
);
}
$groups = $_groups;
}
if (is_array($groups) === false) {
$groups = [ $groups ];
}
if ((bool) $filter['search_secondary_groups'] === true) {
$sql_filters[] = sprintf(
' AND (te.id_grupo IN (%s) OR tasg.id_group IN (%s))',
join(',', $groups),
join(',', $groups)
);
} else {
$sql_filters[] = sprintf(
' AND te.id_grupo IN (%s)',
join(',', $groups)
);
}
}
// Skip system messages if user is not PM.
if (!check_acl($config['id_user'], 0, 'PM')) {
$sql_filters[] = ' AND te.id_grupo != 0 ';
}
if (isset($filter['status']) === true) {
if (is_array($filter['status']) === true) {
$status_all = 0;
foreach ($filter['status'] as $key => $value) {
switch ($value) {
case EVENT_ALL:
$status_all = 1;
break;
case EVENT_NO_VALIDATED:
$filter['status'][$key] = (EVENT_NEW.', '.EVENT_PROCESS);
default:
// Ignore.
break;
}
}
if ($status_all === 0) {
$sql_filters[] = sprintf(
' AND estado IN (%s)',
implode(', ', $filter['status'])
);
}
} else {
switch ($filter['status']) {
case EVENT_ALL:
default:
// Do not filter.
break;
case EVENT_NEW:
case EVENT_VALIDATE:
case EVENT_PROCESS:
$sql_filters[] = sprintf(
' AND estado = %d',
$filter['status']
);
break;
case EVENT_NO_VALIDATED:
// Show comments in validated events.
$validatedState = '';
if ($validatedEvents === true) {
$validatedState = sprintf(
'OR estado = %d',
EVENT_VALIDATE
);
}
$sql_filters[] = sprintf(
' AND (estado = %d OR estado = %d %s)',
EVENT_NEW,
EVENT_PROCESS,
$validatedState
);
break;
}
}
}
if (!$user_is_admin && users_can_manage_group_all('ER') === false) {
$ER_groups = users_get_groups($config['id_user'], 'ER', true);
$EM_groups = users_get_groups($config['id_user'], 'EM', true, true);
$EW_groups = users_get_groups($config['id_user'], 'EW', true, true);
// Get groups where user have ER grants.
if ((bool) $filter['search_secondary_groups'] === true) {
$sql_filters[] = sprintf(
' AND (te.id_grupo IN ( %s ) OR tasg.id_group IN (%s))',
join(', ', array_keys($ER_groups)),
join(', ', array_keys($ER_groups))
);
} else {
$sql_filters[] = sprintf(
' AND te.id_grupo IN ( %s )',
join(', ', array_keys($ER_groups))
);
}
}
// Prepare agent join sql filters.
$table = 'tevento';
$tevento = 'tevento te';
$tagente_table = 'tagente';
$tagente_field = 'id_agente';
$conditionMetaconsole = '';
// Agent alias.
if (empty($filter['agent_alias']) === false) {
$sql_filters[] = sprintf(
' AND ta.alias = "%s" ',
$filter['agent_alias']
);
}
// Free search.
if (empty($filter['search']) === false) {
if (isset($config['dbconnection']->server_version) === true
&& $config['dbconnection']->server_version > 50600
) {
// Use "from_base64" requires mysql 5.6 or greater.
$custom_data_search = 'from_base64(te.custom_data)';
} else {
// Custom data is JSON encoded base64, if 5.6 or lower,
// user is condemned to use plain search.
$custom_data_search = 'te.custom_data';
}
$not_search = '';
$nexo = 'OR';
$array_search = [
'te.id_evento',
'lower(te.evento)',
'lower(te.user_comment)',
'lower(te.id_extra)',
'lower(te.source)',
'lower('.$custom_data_search.')',
];
if (isset($filter['not_search']) === true
&& empty($filter['not_search']) === false
) {
$not_search = 'NOT';
$nexo = 'AND';
} else {
$array_search[] = 'lower(ta.alias)';
}
$sql_search = ' AND (';
foreach ($array_search as $key => $field) {
$sql_search .= sprintf(
'%s %s %s like lower("%%%s%%")',
($key === 0) ? '' : $nexo,
$field,
$not_search,
$filter['search']
);
$sql_search .= ' ';
}
$sql_search .= ' )';
$sql_filters[] = $sql_search;
}
// Free search exclude.
if (empty($filter['search_exclude']) === false) {
$sql_filters[] = vsprintf(
' AND (lower(ta.alias) not like lower("%%%s%%")
AND te.id_evento not like "%%%s%%"
AND lower(te.evento) not like lower("%%%s%%")
AND lower(te.user_comment) not like lower("%%%s%%")
AND lower(te.id_extra) not like lower("%%%s%%")
AND lower(te.source) not like lower("%%%s%%") )',
array_fill(0, 6, $filter['search_exclude'])
);
}
// Id extra.
if (empty($filter['id_extra']) === false) {
$sql_filters[] = sprintf(
' AND lower(te.id_extra) like lower("%%%s%%") ',
$filter['id_extra']
);
}
// User comment.
if (empty($filter['user_comment']) === false) {
// For filter field.
$sql_filters[] = sprintf(
' AND lower(te.user_comment) like lower("%%%s%%") ',
io_safe_input($filter['user_comment'])
);
// For show comments on event details.
$sql_filters[] = sprintf(
' OR lower(te.user_comment) like lower("%%%s%%") ',
$filter['user_comment']
);
}
// Source.
if (empty($filter['source']) === false) {
$sql_filters[] = sprintf(
' AND lower(te.source) like lower("%%%s%%") ',
$filter['source']
);
}
// Custom data.
if (empty($filter['custom_data']) === false) {
if (isset($config['dbconnection']->server_version) === true
&& $config['dbconnection']->server_version > 80000
) {
if ($filter['custom_data_filter_type'] === '1') {
$sql_filters[] = sprintf(
' AND JSON_VALID(custom_data) = 1
AND (JSON_EXTRACT(custom_data, "$.*") LIKE lower("%%%s%%") COLLATE utf8mb4_0900_ai_ci) ',
io_safe_output_html($filter['custom_data'])
);
} else {
$sql_filters[] = sprintf(
' AND JSON_VALID(custom_data) = 1
AND (JSON_SEARCH(JSON_KEYS(custom_data), "all", lower("%%%s%%") COLLATE utf8mb4_0900_ai_ci) IS NOT NULL) ',
io_safe_output_html($filter['custom_data'])
);
}
} else {
if ($filter['custom_data_filter_type'] === '1') {
$sql_filters[] = sprintf(
' AND JSON_VALID(custom_data) = 1
AND cast(JSON_EXTRACT(custom_data, "$.*") as CHAR) LIKE lower("%%%s%%") ',
io_safe_output($filter['custom_data'])
);
} else {
$sql_filters[] = sprintf(
' AND JSON_VALID(custom_data) = 1
AND cast(JSON_KEYS(custom_data) as CHAR) REGEXP "%s" ',
io_safe_output($filter['custom_data'])
);
}
}
}
// Validated or in process by.
if (empty($filter['id_user_ack']) === false) {
$sql_filters[] = sprintf(
' AND te.id_usuario like lower("%%%s%%") ',
$filter['id_user_ack']
);
}
// Owner by.
if (empty($filter['owner_user']) === false) {
$sql_filters[] = sprintf(
' AND te.owner_user like lower("%%%s%%") ',
$filter['owner_user']
);
}
$tag_names = [];
// With following tags.
if (empty($filter['tag_with']) === false) {
$tag_with = base64_decode($filter['tag_with']);
$tags = json_decode($tag_with, true);
if (is_array($tags) === true && in_array('0', $tags) === false) {
if (!$user_is_admin) {
$getUserTags = tags_get_tags_for_module_search();
// Prevent false value for array_flip.
if ($getUserTags === false) {
$getUserTags = [];
}
$user_tags = array_flip($getUserTags);
if ($user_tags != null) {
foreach ($tags as $id_tag) {
// User cannot filter with those tags.
if (array_search($id_tag, $user_tags) === false) {
return false;
}
}
}
}
$_tmp = '';
foreach ($tags as $id_tag) {
if (isset($tags_names[$id_tag]) === false) {
$tags_names[$id_tag] = tags_get_name($id_tag);
}
if ($tags[0] === $id_tag) {
$_tmp .= ' AND (( ';
} else {
$_tmp .= ' OR ( ';
}
$_tmp .= sprintf(
' tags LIKE "%s" OR',
$tags_names[$id_tag]
);
$_tmp .= sprintf(
' tags LIKE "%s,%%" OR',
$tags_names[$id_tag]
);
$_tmp .= sprintf(
' tags LIKE "%%,%s" OR',
$tags_names[$id_tag]
);
$_tmp .= sprintf(
' tags LIKE "%%,%s,%%" ',
$tags_names[$id_tag]
);
if ($tags[0] === $id_tag) {
$_tmp .= ')) ';
} else {
$_tmp .= ') ';
}
}
$sql_filters[] = $_tmp;
}
}
// Without following tags.
if (empty($filter['tag_without']) === false) {
$tag_without = base64_decode($filter['tag_without']);
$tags = json_decode($tag_without, true);
if (is_array($tags) === true && in_array('0', $tags) === false) {
if (!$user_is_admin) {
$tags_module_search = tags_get_tags_for_module_search();
if ($tags_module_search === false) {
$tags_module_search = [];
}
$user_tags = array_flip($tags_module_search);
if ($user_tags != null) {
foreach ($tags as $key_tag => $id_tag) {
// User cannot filter with those tags.
if (!array_search($id_tag, $user_tags)) {
unset($tags[$key_tag]);
continue;
}
}
}
}
foreach ($tags as $id_tag) {
if (isset($tags_names[$id_tag]) === false) {
$tags_names[$id_tag] = tags_get_name($id_tag);
}
$_tmp .= sprintf(
' AND tags NOT LIKE "%s" ',
$tags_names[$id_tag]
);
$_tmp .= sprintf(
' AND tags NOT LIKE "%s,%%" ',
$tags_names[$id_tag]
);
$_tmp .= sprintf(
' AND tags NOT LIKE "%%,%s" ',
$tags_names[$id_tag]
);
$_tmp .= sprintf(
' AND tags NOT LIKE "%%,%s,%%" ',
$tags_names[$id_tag]
);
}
$sql_filters[] = $_tmp;
}
}
// Filter/ Only alerts.
if (isset($filter['filter_only_alert']) === true) {
if ($filter['filter_only_alert'] == 0) {
$sql_filters[] = ' AND event_type NOT LIKE "%alert%"';
} else if ($filter['filter_only_alert'] == 1) {
$sql_filters[] = ' AND event_type LIKE "%alert%"';
}
}
$user_admin_group_all = ($user_is_admin && $groups == 0) ? '' : 'tasg.';
// TAgs ACLS.
if (check_acl($config['id_user'], 0, 'ER')) {
$tags_acls_condition = tags_get_acl_tags(
// Id_user.
$config['id_user'],
// Id_group.
($ER_groups ?? ''),
// Access.
'ER',
// Return_mode.
'event_condition',
// Query_prefix.
'AND',
// Query_table.
'',
// Meta.
is_metaconsole() && $nodeConnected === false,
// Childrens_ids.
[],
// Force_group_and_tag.
true,
// Table tag for id_grupo.
'te.',
// Alt table tag for id_grupo.
$user_admin_group_all,
(bool) (isset($filter['search_secondary_groups']) === true) ? $filter['search_secondary_groups'] : false
);
// FORCE CHECK SQL "(TAG = tag1 AND id_grupo = 1)".
} else if (check_acl($config['id_user'], 0, 'EW')) {
$tags_acls_condition = tags_get_acl_tags(
// Id_user.
$config['id_user'],
// Id_group.
$EW_groups,
// Access.
'EW',
// Return_mode.
'event_condition',
// Query_prefix.
'AND',
// Query_table.
'',
// Meta.
is_metaconsole() && $nodeConnected === false,
// Childrens_ids.
[],
// Force_group_and_tag.
true,
// Table tag for id_grupo.
'te.',
// Alt table tag for id_grupo.
$user_admin_group_all,
(bool) (isset($filter['search_secondary_groups']) === true) ? $filter['search_secondary_groups'] : false
);
// FORCE CHECK SQL "(TAG = tag1 AND id_grupo = 1)".
} else if (check_acl($config['id_user'], 0, 'EM')) {
$tags_acls_condition = tags_get_acl_tags(
// Id_user.
$config['id_user'],
// Id_group.
$EM_groups,
// Access.
'EM',
// Return_mode.
'event_condition',
// Query_prefix.
'AND',
// Query_table.
'',
// Meta.
is_metaconsole() && $nodeConnected === false,
// Childrens_ids.
[],
// Force_group_and_tag.
true,
// Table tag for id_grupo.
'te.',
// Alt table tag for id_grupo.
$user_admin_group_all,
(bool) (isset($filter['search_secondary_groups']) === true) ? $filter['search_secondary_groups'] : false
);
// FORCE CHECK SQL "(TAG = tag1 AND id_grupo = 1)".
}
if (($tags_acls_condition != ERR_WRONG_PARAMETERS)
&& ($tags_acls_condition != ERR_ACL)
) {
$sql_filters[] = $tags_acls_condition;
}
// Module search.
$agentmodule_join = 'LEFT JOIN tagente_modulo am ON te.id_agentmodule = am.id_agente_modulo';
if (empty($filter['module_search']) === false) {
$agentmodule_join = 'INNER JOIN tagente_modulo am ON te.id_agentmodule = am.id_agente_modulo';
$sql_filters[] = sprintf(
' AND am.nombre = "%s" ',
$filter['module_search']
);
}
// Order.
$order_by = '';
if (isset($order, $sort_field) === true) {
if (isset($filter['group_rep']) === true
&& $filter['group_rep'] === EVENT_GROUP_REP_EVENTS
&& $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS
) {
$order_by = events_get_sql_order('MAX('.$sort_field.')', $order);
} else {
$order_by = events_get_sql_order($sort_field, $order);
}
}
// Id server.
$id_server = 0;
if (empty($filter['id_server']) === false) {
$id_server = $filter['id_server'];
} else if (empty($filter['server_id']) === false) {
$id_server = $filter['server_id'];
}
// Pagination.
$pagination = '';
if (is_metaconsole() === true
&& (empty($id_server) === true || is_array($id_server) === true)
&& isset($filter['csv_all']) === false
) {
// TODO: XXX TIP. captura el error.
$pagination = sprintf(
' LIMIT %d',
$config['max_number_of_events_per_node']
);
} else if (isset($limit, $offset) === true && $limit > 0) {
$pagination = sprintf(' LIMIT %d OFFSET %d', $limit, $offset);
}
// Group by.
$group_by = 'GROUP BY ';
$tagente_join = 'LEFT';
if (isset($filter['group_rep']) === false) {
$filter['group_rep'] = EVENT_GROUP_REP_ALL;
}
switch ($filter['group_rep']) {
case EVENT_GROUP_REP_ALL:
default:
// All events.
$group_by = '';
break;
case EVENT_GROUP_REP_EVENTS:
// Group by events.
$group_by .= 'te.evento, te.id_agente, te.id_agentmodule';
break;
case EVENT_GROUP_REP_AGENTS:
// Group by agents.
$tagente_join = 'INNER';
$group_by = '';
$order_by = events_get_sql_order('te.id_agente', 'asc');
if (isset($order, $sort_field) === true) {
$order_by .= ','.events_get_sql_order(
$sort_field,
$order,
0,
true
);
}
break;
case EVENT_GROUP_REP_EXTRAIDS:
// Group by events and ignore null.
$sql_filters[] = 'AND te.id_extra IS NOT NULL AND te.id_extra <> ""';
$group_by .= 'te.id_extra';
break;
}
$tgrupo_join = 'LEFT';
$tgrupo_join_filters = [];
if (isset($groups) === true
&& (is_array($groups) === true
|| $groups > 0)
) {
$tgrupo_join = 'INNER';
if (is_array($groups) === true) {
if ((bool) $filter['search_secondary_groups'] === true) {
$tgrupo_join_filters[] = sprintf(
' (te.id_grupo = tg.id_grupo AND tg.id_grupo IN (%s))
OR (tg.id_grupo = tasg.id_group AND tasg.id_group IN (%s))',
join(', ', $groups),
join(', ', $groups)
);
} else {
$tgrupo_join_filters[] = sprintf(
' (te.id_grupo = tg.id_grupo AND tg.id_grupo IN (%s))',
join(', ', $groups)
);
}
} else {
if ((bool) $filter['search_secondary_groups'] === true) {
$tgrupo_join_filters[] = sprintf(
' (te.id_grupo = tg.id_grupo AND tg.id_grupo = %s)
OR (tg.id_grupo = tasg.id_group AND tasg.id_group = %s)',
$groups,
$groups
);
} else {
$tgrupo_join_filters[] = sprintf(
' (te.id_grupo = tg.id_grupo AND tg.id_grupo = %s)',
$groups
);
}
}
} else {
$tgrupo_join_filters[] = ' te.id_grupo = tg.id_grupo';
}
// Secondary groups.
$event_lj = '';
if (!$user_is_admin || ($user_is_admin && isset($groups) === true && $groups > 0)) {
if ((bool) $filter['search_secondary_groups'] === true) {
$event_lj = events_get_secondary_groups_left_join($table);
}
}
$group_selects = '';
if ($group_by != '') {
if ($count === false) {
$idx = array_search('te.user_comment', $fields);
if ($idx !== false) {
unset($fields[$idx]);
}
db_process_sql('SET group_concat_max_len = 9999999');
$group_selects = sprintf(
',COUNT(id_evento) AS event_rep,
%s
MAX(utimestamp) as timestamp_last,
MIN(utimestamp) as timestamp_first,
MAX(id_evento) as max_id_evento',
($idx !== false) ? 'GROUP_CONCAT(DISTINCT user_comment SEPARATOR "
") AS comments,' : ''
);
$group_selects_trans = sprintf(
',tmax_event.event_rep,
%s
tmax_event.timestamp_last,
tmax_event.timestamp_first,
tmax_event.max_id_evento',
($idx !== false) ? 'tmax_event.comments,' : ''
);
}
} else {
$idx = array_search('te.user_comment', $fields);
if ($idx !== false) {
$fields[$idx] = 'te.user_comment AS comments';
}
}
if (((int) $filter['group_rep'] === EVENT_GROUP_REP_EVENTS
|| (int) $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) && $count === false
) {
$sql = sprintf(
'SELECT %s
%s
FROM %s
INNER JOIN (
SELECT te.id_evento %s
FROM %s
%s
%s
%s JOIN %s ta
ON ta.%s = te.id_agente
%s
%s JOIN tgrupo tg
ON %s
WHERE 1=1
%s
%s
%s
%s
%s
) tmax_event
ON te.id_evento = tmax_event.max_id_evento
%s
%s
%s JOIN %s ta
ON ta.%s = te.id_agente
%s
%s JOIN tgrupo tg
ON %s
%s
%s',
join(',', $fields),
$group_selects_trans,
$tevento,
$group_selects,
$tevento,
$event_lj,
$agentmodule_join,
$tagente_join,
$tagente_table,
$tagente_field,
$conditionMetaconsole,
$tgrupo_join,
join(' ', $tgrupo_join_filters),
join(' ', $sql_filters),
$group_by,
$order_by,
$pagination,
$having,
$event_lj,
$agentmodule_join,
$tagente_join,
$tagente_table,
$tagente_field,
$conditionMetaconsole,
$tgrupo_join,
join(' ', $tgrupo_join_filters),
join(' ', $sql_filters),
$order_by
);
} else {
$sql = sprintf(
'SELECT %s
%s
FROM %s
%s
%s
%s JOIN %s ta
ON ta.%s = te.id_agente
%s
%s JOIN tgrupo tg
ON %s
WHERE 1=1
%s
%s
%s
%s
%s
',
join(',', $fields),
$group_selects,
$tevento,
$event_lj,
$agentmodule_join,
$tagente_join,
$tagente_table,
$tagente_field,
$conditionMetaconsole,
$tgrupo_join,
join(' ', $tgrupo_join_filters),
join(' ', $sql_filters),
$group_by,
$order_by,
$pagination,
$having
);
}
if ($return_sql === true) {
return $sql;
}
if (!$user_is_admin && users_can_manage_group_all('ER') === false) {
$can_manage = '0 as user_can_manage';
if (empty($EM_groups) === false) {
$can_manage = sprintf(
'(tbase.id_grupo IN (%s)) as user_can_manage',
join(', ', array_keys($EM_groups))
);
}
$can_write = '0 as user_can_write';
if (empty($EW_groups) === false) {
$can_write = sprintf(
'(tbase.id_grupo IN (%s)) as user_can_write',
join(', ', array_keys($EW_groups))
);
}
$sql = sprintf(
'SELECT
tbase.*,
%s,
%s
FROM
(',
$can_manage,
$can_write
).$sql.') tbase';
} else {
$sql = 'SELECT
tbase.*,
1 as user_can_manage,
1 as user_can_write
FROM
('.$sql.') tbase';
}
if ($count === true
&& (is_metaconsole() === false
|| (is_metaconsole() === true
&& empty($filter['server_id']) === false
&& is_array($filter['server_id']) === false))
) {
$sql = 'SELECT count(*) as nitems FROM ('.$sql.') tt';
}
if (is_metaconsole() === true) {
$result_meta = [];
$metaconsole_connections = metaconsole_get_names(['disabled' => 0]);
if (isset($metaconsole_connections) === true
&& is_array($metaconsole_connections) === true
) {
try {
if (empty($id_server) === true) {
$metaconsole_connections = array_flip($metaconsole_connections);
$metaconsole_connections['meta'] = 0;
} else {
if (is_array($id_server) === false) {
$only_id_server[$metaconsole_connections[$id_server]] = $id_server;
$metaconsole_connections = $only_id_server;
} else {
$metaConnections = [];
foreach ($id_server as $idser) {
if ((int) $idser === 0) {
$metaConnections['meta'] = 0;
} else {
$metaConnections[$metaconsole_connections[$idser]] = $idser;
}
}
$metaconsole_connections = $metaConnections;
}
}
$result_meta = Promise\wait(
parallelMap(
$metaconsole_connections,
function ($node_int) use ($sql, $history) {
try {
if (is_metaconsole() === true
&& (int) $node_int > 0
) {
$node = new Node($node_int);
$node->connect();
}
$res = db_get_all_rows_sql($sql, $history);
if ($res === false) {
$res = [];
}
} catch (\Exception $e) {
// Unexistent agent.
if (is_metaconsole() === true
&& $node_int > 0
) {
$node->disconnect();
}
error_log('[events_get_all]'.$e->getMessage());
return __('Could not connect: %s', $e->getMessage());
} finally {
if (is_metaconsole() === true
&& $node_int > 0
) {
$node->disconnect();
}
}
return $res;
}
)
);
} catch (\Exception $e) {
$e->getReasons();
}
}
$data = [];
$buffers = [
'settings' => [
'total' => $config['max_number_of_events_per_node'],
],
'data' => [],
'error' => [],
];
if (empty($result_meta) === false) {
foreach ($result_meta as $node => $value) {
if (is_array($value) === false) {
$buffers['error'][$node] = $value;
$buffers['data'][$node] = 0;
} else {
$buffers['data'][$node] = count($value);
if (empty($value) === false) {
foreach ($value as $k => $v) {
$value[$k]['server_id'] = $metaconsole_connections[$node];
$value[$k]['server_name'] = $node;
}
$data = array_merge($data, $value);
}
}
}
}
if ($count === false) {
if ($sort_field !== 'agent_name'
&& $sort_field !== 'server_name'
&& $sort_field !== 'timestamp'
) {
$sort_field = explode('.', $sort_field)[1];
if ($sort_field === 'user_comment') {
$sort_field = 'comments';
}
}
usort(
$data,
function ($a, $b) use ($sort_field, $order) {
switch ($sort_field) {
default:
case 'utimestamp':
case 'criticity':
case 'estado':
if ($a[$sort_field] === $b[$sort_field]) {
$res = 0;
} else if ($a[$sort_field] > $b[$sort_field]) {
$res = ($order === 'asc') ? 1 : (-1);
} else {
$res = ($order === 'asc') ? (-1) : 1;
}
break;
case 'evento':
case 'agent_name':
case 'timestamp':
case 'tags':
case 'comments':
case 'server_name':
if ($order === 'asc') {
$res = strcasecmp($a[$sort_field], $b[$sort_field]);
} else {
$res = strcasecmp($b[$sort_field], $a[$sort_field]);
}
break;
}
return $res;
}
);
if (isset($limit, $offset) === true
&& (int) $limit !== 0
&& isset($filter['csv_all']) === false
) {
$count = count($data);
// -1 For pagination 'All'.
((int) $limit === -1)
? $end = count($data)
: $end = ((int) $offset !== 0) ? ($offset + $limit) : $limit;
$finally = array_slice($data, $offset, $end, true);
$return = [
'buffers' => $buffers,
'data' => $finally,
'total' => $count,
];
} else {
$return = array_slice(
$data,
0,
($config['max_number_of_events_per_node'] * count($metaconsole_connections)),
true
);
}
return $return;
} else {
return ['count' => count($data)];
}
}
return db_get_all_rows_sql($sql, $history);
}
/**
* @deprecated Use events_get_all instead.
*
* Get all rows of events from the database, that
* pass the filter, and can get only some fields.
*
* @param mixed $filter Filters elements. It can be an indexed array
* (keys would be the field name and value the expected
* value, and would be joined with an AND operator) or a
* string, including any SQL clause (without the WHERE
* keyword). Example:
*
* Both are similars:
* db_get_all_rows_filter ('table', ['disabled', 0]);
* db_get_all_rows_filter ('table', 'disabled = 0');
* Both are similars:
* db_get_all_rows_filter (
* 'table',
* [
* 'disabled' => 0,
* 'history_data' => 0
* ],
* 'name',
* 'OR'
* );
* db_get_all_rows_filter (
* 'table',
* 'disabled = 0 OR history_data = 0', 'name'
* );
*
.
* @param mixed $fields Fields of the table to retrieve. Can be an array or a
* coma separated string. All fields are retrieved by
* default.
*
* @return mixed False in case of error or invalid values passed.
* Affected rows otherwise
*/
function events_get_events($filter=false, $fields=false)
{
if (isset($filter['criticity']) === true
&& (int) $filter['criticity'] === EVENT_CRIT_WARNING_OR_CRITICAL
) {
$filter['criticity'] = [
EVENT_CRIT_WARNING,
EVENT_CRIT_CRITICAL,
];
}
return db_get_all_rows_filter('tevento', $filter, $fields);
}
/**
* Get the event with the id pass as parameter.
*
* @param integer $id Event id.
* @param mixed $fields The fields to show or by default all with false.
* @param boolean $meta Metaconsole environment or not.
* @param boolean $history Retrieve also historical data.
*
* @return mixed False in case of error or invalid values passed.
* Event row otherwise.
*/
function events_get_event($id, $fields=false, $meta=false, $history=false)
{
if (empty($id) === true) {
return false;
}
global $config;
if (is_array($fields) === true) {
if (in_array('id_grupo', $fields) === false) {
$fields[] = 'id_grupo';
}
}
$event = db_get_row('tevento', 'id_evento', $id, $fields);
if ((bool) check_acl($config['id_user'], $event['id_grupo'], 'ER') === false) {
return false;
}
return $event;
}
/**
* Change the status of one or multiple events.
*
* @param mixed $id_event Event ID or array of events.
* @param integer $new_status New status of the event.
*
* @return boolean Whether or not it was successful
*/
function events_change_status(
$id_event,
$new_status
) {
global $config;
// Cleans up the selection for all unwanted
// values also casts any single values as an array.
$id_event = (array) safe_int($id_event, 1);
// Update ack info if the new status is validated.
$ack_utimestamp = 0;
$ack_user = $config['id_user'];
if ((int) $new_status === EVENT_STATUS_VALIDATED || (int) $new_status === EVENT_STATUS_INPROCESS) {
$ack_utimestamp = time();
}
switch ($new_status) {
case EVENT_STATUS_NEW:
$status_string = 'New';
break;
case EVENT_STATUS_VALIDATED:
$status_string = 'Validated';
break;
case EVENT_STATUS_INPROCESS:
$status_string = 'In process';
break;
default:
$status_string = '';
break;
}
$alerts = [];
foreach ($id_event as $k => $id) {
$event_group = events_get_group($id);
$event = events_get_event($id);
if ($event['id_alert_am'] > 0
&& in_array($event['id_alert_am'], $alerts) === false
) {
$alerts[] = $event['id_alert_am'];
}
if (check_acl($config['id_user'], $event_group, 'EW') == 0) {
db_pandora_audit(
AUDIT_LOG_ACL_VIOLATION,
'Attempted updating event #'.$id
);
unset($id_event[$k]);
}
}
if (empty($id_event) === true) {
return false;
}
$values = [
'estado' => $new_status,
'id_usuario' => $ack_user,
'ack_utimestamp' => $ack_utimestamp,
];
$ret = db_process_sql_update(
'tevento',
$values,
['id_evento' => $id_event]
);
if (($ret === false) || ($ret === 0)) {
return false;
}
if ($new_status === EVENT_STATUS_VALIDATED) {
events_change_owner(
$id_event,
$config['id_user'],
false
);
}
events_comment(
$id_event,
'',
'Change status to '.$status_string
);
// Put the alerts in standby or not depends the new status.
if (empty($alerts) === false) {
foreach ($alerts as $alert) {
switch ($new_status) {
case EVENT_NEW:
case EVENT_VALIDATE:
alerts_agent_module_standby($alert, 0);
break;
case EVENT_PROCESS:
alerts_agent_module_standby($alert, 1);
break;
default:
// Ignore.
break;
}
}
}
return true;
}
/**
* Change the owner of an event if the event hasn't owner.
*
* @param mixed $id_event Event ID or array of events.
* @param string $new_owner Id_user of the new owner. If is false, the current
* owner will be set, if empty, will be cleaned.
* @param boolean $force Flag to force the change or not (not force is
* change only when it hasn't owner).
*
* @return boolean Whether or not it was successful.
*/
function events_change_owner(
$id_event,
$new_owner=false,
$force=false
) {
global $config;
// Cleans up the selection for all unwanted values also casts any single
// values as an array.
$id_event = (array) safe_int($id_event, 1);
foreach ($id_event as $k => $id) {
$event_group = events_get_group($id);
if (check_acl($config['id_user'], $event_group, 'EW') == 0) {
db_pandora_audit(
AUDIT_LOG_ACL_VIOLATION,
'Attempted updating event #'.$id
);
unset($id_event[$k]);
}
}
if (empty($id_event) === true) {
return false;
}
if ($new_owner === false) {
$new_owner = $config['id_user'];
}
// Only generate comment when is forced
// (sometimes is owner changes when comment).
if ($force === true) {
events_comment(
$id_event,
'',
'Change owner to '.get_user_fullname($new_owner).' ('.$new_owner.')'
);
}
$values = ['owner_user' => $new_owner];
$where = ['id_evento' => $id_event];
// If not force, add to where if owner_user = ''.
if ($force === false) {
$where['owner_user'] = '';
}
$ret = db_process_sql_update(
'tevento',
$values,
$where,
'AND',
false
);
if (($ret === false) || ($ret === 0)) {
return false;
}
return true;
}
/**
* Comment events in a transresponse
*
* @param mixed $id_event Event ID or array of events.
* @param string $comment Comment to be registered.
* @param string $action Action performed with comment. By default just add
* a comment.
*
* @return boolean Whether or not it was successful
*/
function events_comment(
$id_event,
$comment='',
$action='Added comment'
) {
global $config;
// Cleans up the selection for all unwanted values also casts any single
// values as an array.
$id_event = (array) safe_int($id_event, 1);
// Check ACL.
foreach ($id_event as $k => $id) {
$event_group = events_get_group($id);
if (check_acl($config['id_user'], $event_group, 'EW') == 0) {
db_pandora_audit(
AUDIT_LOG_ACL_VIOLATION,
'Attempted updating event #'.$id
);
unset($id_event[$k]);
}
}
if (empty($id_event) === true) {
return false;
}
// Get the current event comments.
$first_event = $id_event;
if (is_array($id_event) === true) {
$first_event = reset($id_event);
}
$sql = sprintf(
'SELECT user_comment
FROM tevento
WHERE id_evento = %d',
$first_event
);
$event_comments = db_get_all_rows_sql($sql);
$event_comments_array = [];
if ($event_comments[0]['user_comment'] == '') {
$comments_format = 'new';
} else {
// If comments are not stored in json, the format is old.
$event_comments[0]['user_comment'] = str_replace(
[
"\n",
'
',
],
'
',
$event_comments[0]['user_comment']
);
$event_comments_array = json_decode($event_comments[0]['user_comment']);
if (empty($event_comments_array) === true) {
$comments_format = 'old';
} else {
$comments_format = 'new';
}
}
switch ($comments_format) {
case 'new':
$comment_for_json['comment'] = io_safe_input($comment);
$comment_for_json['action'] = $action;
$comment_for_json['id_user'] = $config['id_user'];
$comment_for_json['utimestamp'] = time();
$comment_for_json['event_id'] = $first_event;
$event_comments_array[] = $comment_for_json;
$event_comments = io_json_mb_encode($event_comments_array);
// Update comment.
$ret = db_process_sql_update(
'tevento',
['user_comment' => $event_comments],
['id_evento' => implode(',', $id_event)]
);
break;
case 'old':
// Give old ugly format to comment.
// Change this method for aux table or json.
$comment = str_replace(["\r\n", "\r", "\n"], '
', $comment);
if ($comment !== '') {
$commentbox = '
'.stripslashes(str_replace(['\n', '\r'], '
', $c['comment'])).'