/* ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ #include "zbxexpression.h" #include "expression.h" #include "evalfunc.h" #include "datafunc.h" #include "zbxvariant.h" #include "zbxeval.h" #include "zbxdbwrap.h" #include "zbxcachevalue.h" #include "macrofunc.h" #include "zbxxml.h" #include "zbxstr.h" #include "zbxexpr.h" #include "zbxparam.h" #include "zbx_trigger_constants.h" #include "zbx_expression_constants.h" #include "zbxevent.h" #include "zbxtime.h" #include "zbxjson.h" #include "zbxalgo.h" #include "zbxinterface.h" #include "zbxip.h" /****************************************************************************** * * * Purpose: formats full user name from name, surname and alias. * * * * Parameters: name - [IN] user name, can be empty string * * surname - [IN] user surname, can be empty string * * alias - [IN] user alias * * * * Return value: the formatted user fullname. * * * ******************************************************************************/ static char *format_user_fullname(const char *name, const char *surname, const char *alias) { char *buf = NULL; size_t buf_alloc = 0, buf_offset = 0; zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, name); if ('\0' != *surname) { if (0 != buf_offset) zbx_chrcpy_alloc(&buf, &buf_alloc, &buf_offset, ' '); zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, surname); } if ('\0' != *alias) { size_t offset = buf_offset; if (0 != buf_offset) zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, " ("); zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, alias); if (0 != offset) zbx_chrcpy_alloc(&buf, &buf_alloc, &buf_offset, ')'); } return buf; } /* macros that can be indexed */ static const char *ex_macros[] = { MVAR_INVENTORY_TYPE, MVAR_INVENTORY_TYPE_FULL, MVAR_INVENTORY_NAME, MVAR_INVENTORY_ALIAS, MVAR_INVENTORY_OS, MVAR_INVENTORY_OS_FULL, MVAR_INVENTORY_OS_SHORT, MVAR_INVENTORY_SERIALNO_A, MVAR_INVENTORY_SERIALNO_B, MVAR_INVENTORY_TAG, MVAR_INVENTORY_ASSET_TAG, MVAR_INVENTORY_MACADDRESS_A, MVAR_INVENTORY_MACADDRESS_B, MVAR_INVENTORY_HARDWARE, MVAR_INVENTORY_HARDWARE_FULL, MVAR_INVENTORY_SOFTWARE, MVAR_INVENTORY_SOFTWARE_FULL, MVAR_INVENTORY_SOFTWARE_APP_A, MVAR_INVENTORY_SOFTWARE_APP_B, MVAR_INVENTORY_SOFTWARE_APP_C, MVAR_INVENTORY_SOFTWARE_APP_D, MVAR_INVENTORY_SOFTWARE_APP_E, MVAR_INVENTORY_CONTACT, MVAR_INVENTORY_LOCATION, MVAR_INVENTORY_LOCATION_LAT, MVAR_INVENTORY_LOCATION_LON, MVAR_INVENTORY_NOTES, MVAR_INVENTORY_CHASSIS, MVAR_INVENTORY_MODEL, MVAR_INVENTORY_HW_ARCH, MVAR_INVENTORY_VENDOR, MVAR_INVENTORY_CONTRACT_NUMBER, MVAR_INVENTORY_INSTALLER_NAME, MVAR_INVENTORY_DEPLOYMENT_STATUS, MVAR_INVENTORY_URL_A, MVAR_INVENTORY_URL_B, MVAR_INVENTORY_URL_C, MVAR_INVENTORY_HOST_NETWORKS, MVAR_INVENTORY_HOST_NETMASK, MVAR_INVENTORY_HOST_ROUTER, MVAR_INVENTORY_OOB_IP, MVAR_INVENTORY_OOB_NETMASK, MVAR_INVENTORY_OOB_ROUTER, MVAR_INVENTORY_HW_DATE_PURCHASE, MVAR_INVENTORY_HW_DATE_INSTALL, MVAR_INVENTORY_HW_DATE_EXPIRY, MVAR_INVENTORY_HW_DATE_DECOMM, MVAR_INVENTORY_SITE_ADDRESS_A, MVAR_INVENTORY_SITE_ADDRESS_B, MVAR_INVENTORY_SITE_ADDRESS_C, MVAR_INVENTORY_SITE_CITY, MVAR_INVENTORY_SITE_STATE, MVAR_INVENTORY_SITE_COUNTRY, MVAR_INVENTORY_SITE_ZIP, MVAR_INVENTORY_SITE_RACK, MVAR_INVENTORY_SITE_NOTES, MVAR_INVENTORY_POC_PRIMARY_NAME, MVAR_INVENTORY_POC_PRIMARY_EMAIL, MVAR_INVENTORY_POC_PRIMARY_PHONE_A, MVAR_INVENTORY_POC_PRIMARY_PHONE_B, MVAR_INVENTORY_POC_PRIMARY_CELL, MVAR_INVENTORY_POC_PRIMARY_SCREEN, MVAR_INVENTORY_POC_PRIMARY_NOTES, MVAR_INVENTORY_POC_SECONDARY_NAME, MVAR_INVENTORY_POC_SECONDARY_EMAIL, MVAR_INVENTORY_POC_SECONDARY_PHONE_A, MVAR_INVENTORY_POC_SECONDARY_PHONE_B, MVAR_INVENTORY_POC_SECONDARY_CELL, MVAR_INVENTORY_POC_SECONDARY_SCREEN, MVAR_INVENTORY_POC_SECONDARY_NOTES, /* PROFILE.* is deprecated, use INVENTORY.* instead */ MVAR_PROFILE_DEVICETYPE, MVAR_PROFILE_NAME, MVAR_PROFILE_OS, MVAR_PROFILE_SERIALNO, MVAR_PROFILE_TAG, MVAR_PROFILE_MACADDRESS, MVAR_PROFILE_HARDWARE, MVAR_PROFILE_SOFTWARE, MVAR_PROFILE_CONTACT, MVAR_PROFILE_LOCATION, MVAR_PROFILE_NOTES, MVAR_HOST_HOST, MVAR_HOSTNAME, MVAR_HOST_NAME, MVAR_HOST_DESCRIPTION, MVAR_PROXY_NAME, MVAR_PROXY_DESCRIPTION, MVAR_HOST_CONN, MVAR_HOST_DNS, MVAR_HOST_IP, MVAR_HOST_PORT, MVAR_IPADDRESS, MVAR_HOST_ID, MVAR_ITEM_ID, MVAR_ITEM_NAME, MVAR_ITEM_NAME_ORIG, MVAR_ITEM_DESCRIPTION, MVAR_ITEM_DESCRIPTION_ORIG, MVAR_ITEM_KEY, MVAR_ITEM_KEY_ORIG, MVAR_TRIGGER_KEY, MVAR_ITEM_LASTVALUE, MVAR_ITEM_STATE, MVAR_ITEM_VALUE, MVAR_ITEM_VALUETYPE, MVAR_ITEM_LOG_DATE, MVAR_ITEM_LOG_TIME, MVAR_ITEM_LOG_AGE, MVAR_ITEM_LOG_SOURCE, MVAR_ITEM_LOG_SEVERITY, MVAR_ITEM_LOG_NSEVERITY, MVAR_ITEM_LOG_EVENTID, MVAR_FUNCTION_VALUE, MVAR_FUNCTION_RECOVERY_VALUE, NULL }; /* macros that are supported in expression macro */ static const char *expr_macros[] = {MVAR_HOST_HOST, MVAR_HOSTNAME, MVAR_ITEM_KEY, NULL}; /****************************************************************************** * * * Purpose: request recovery event value by macro. * * * ******************************************************************************/ static void get_recovery_event_value(const char *macro, const zbx_db_event *r_event, char **replace_to, const char *tz) { if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_DATE)) { *replace_to = zbx_strdup(*replace_to, zbx_date2str(r_event->clock, tz)); } else if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_ID)) { *replace_to = zbx_dsprintf(*replace_to, ZBX_FS_UI64, r_event->eventid); } else if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_STATUS)) { *replace_to = zbx_strdup(*replace_to, event_value_string(r_event->source, r_event->object, r_event->value)); } else if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_TIME)) { *replace_to = zbx_strdup(*replace_to, zbx_time2str(r_event->clock, tz)); } else if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_VALUE)) { *replace_to = zbx_dsprintf(*replace_to, "%d", r_event->value); } else if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_NAME)) { *replace_to = zbx_dsprintf(*replace_to, "%s", r_event->name); } else if (EVENT_SOURCE_TRIGGERS == r_event->source || EVENT_SOURCE_INTERNAL == r_event->source || EVENT_SOURCE_SERVICE == r_event->source) { if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_TAGS)) zbx_event_get_str_tags(r_event, replace_to); else if (0 == strcmp(macro, MVAR_EVENT_RECOVERY_TAGSJSON)) zbx_event_get_json_tags(r_event, replace_to); } } /****************************************************************************** * * * Purpose: request current event value by macro. * * * ******************************************************************************/ static void get_current_event_value(const char *macro, const zbx_db_event *event, char **replace_to) { if (0 == strcmp(macro, MVAR_EVENT_STATUS)) { *replace_to = zbx_strdup(*replace_to, event_value_string(event->source, event->object, event->value)); } else if (0 == strcmp(macro, MVAR_EVENT_VALUE)) { *replace_to = zbx_dsprintf(*replace_to, "%d", event->value); } } /****************************************************************************** * * * Purpose: check if a token contains indexed macro. * * * ******************************************************************************/ static int is_indexed_macro(const char *str, const zbx_token_t *token) { const char *p; switch (token->type) { case ZBX_TOKEN_MACRO: p = str + token->loc.r - 1; break; case ZBX_TOKEN_USER_FUNC_MACRO: case ZBX_TOKEN_FUNC_MACRO: p = str + token->data.func_macro.macro.r - 1; break; default: THIS_SHOULD_NEVER_HAPPEN; return FAIL; } return '1' <= *p && *p <= '9' ? 1 : 0; } /****************************************************************************** * * * Purpose: check if a macro in string is one of the list and extract index. * * * * Parameters: str - [IN] string containing potential macro * * strloc - [IN] part of the string to check * * macros - [IN] list of allowed macros (without indices) * * N_functionid - [OUT] index of the macro in string (if valid) * * * * Return value: unindexed macro from the allowed list or NULL. * * * * Comments: example: N_functionid is untouched if function returns NULL, for * * a valid unindexed macro N_function is 1. * * * ******************************************************************************/ static const char *macro_in_list(const char *str, zbx_strloc_t strloc, const char **macros, int *N_functionid) { const char **macro, *m; size_t i; for (macro = macros; NULL != *macro; macro++) { for (m = *macro, i = strloc.l; '\0' != *m && i <= strloc.r && str[i] == *m; m++, i++) ; /* check whether macro has ended while strloc hasn't or vice-versa */ if (('\0' == *m && i <= strloc.r) || ('\0' != *m && i > strloc.r)) continue; /* strloc either fully matches macro... */ if ('\0' == *m) { if (NULL != N_functionid) *N_functionid = 1; break; } /* ...or there is a mismatch, check if it's in a pre-last character and it's an index */ if (i == strloc.r - 1 && '1' <= str[i] && str[i] <= '9' && str[i + 1] == *m && '\0' == *(m + 1)) { if (NULL != N_functionid) *N_functionid = str[i] - '0'; break; } } return *macro; } /****************************************************************************** * * * Purpose: calculate result of expression macro. * * * * Return value: upon successful completion return SUCCEED * * otherwise FAIL * * * ******************************************************************************/ static int get_expression_macro_result(const zbx_db_event *event, char *data, zbx_strloc_t *loc, zbx_timespec_t *ts, char **replace_to, char **error) { int ret = FAIL; zbx_eval_context_t ctx; const zbx_vector_uint64_t *hostids; zbx_variant_t value; zbx_expression_eval_t eval; char *expression = NULL; size_t exp_alloc = 0, exp_offset = 0; zbx_dc_um_handle_t *um_handle; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); zbx_strncpy_alloc(&expression, &exp_alloc, &exp_offset, data + loc->l, loc->r - loc->l + 1); zabbix_log(LOG_LEVEL_DEBUG, "%s() expression: '%s'", __func__, expression); um_handle = zbx_dc_open_user_macros(); if (SUCCEED != zbx_eval_parse_expression(&ctx, expression, ZBX_EVAL_PARSE_EXPRESSION_MACRO, error)) goto out; if (SUCCEED != zbx_db_trigger_get_all_hostids(&event->trigger, &hostids)) { *error = zbx_strdup(NULL, "cannot obtain host identifiers for the expression macro"); goto out; } if (SUCCEED != zbx_eval_expand_user_macros(&ctx, hostids->values, hostids->values_num, (zbx_macro_expand_func_t)zbx_dc_expand_user_and_func_macros, um_handle, NULL)) { goto out; } zbx_expression_eval_init(&eval, ZBX_EXPRESSION_NORMAL, &ctx); zbx_expression_eval_resolve_trigger_hosts_items(&eval, &event->trigger); if (SUCCEED == (ret = zbx_expression_eval_execute(&eval, ts, &value, error))) { *replace_to = zbx_strdup(NULL, zbx_variant_value_desc(&value)); zbx_variant_clear(&value); } zbx_expression_eval_clear(&eval); out: zbx_eval_clear(&ctx); zbx_free(expression); zbx_dc_close_user_macros(um_handle); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } /****************************************************************************** * * * Purpose: cache host identifier referenced by an item or a lld-rule. * * * * Parameters: hostids - [OUT] host identifier cache * * itemid - [IN] item identifier * * * ******************************************************************************/ static void cache_item_hostid(zbx_vector_uint64_t *hostids, zbx_uint64_t itemid) { if (0 == hostids->values_num) { zbx_dc_item_t item; int errcode; zbx_dc_config_get_items_by_itemids(&item, &itemid, &errcode, 1); if (SUCCEED == errcode) zbx_vector_uint64_append(hostids, item.host.hostid); zbx_dc_config_clean_items(&item, &errcode, 1); } } /****************************************************************************** * * * Purpose: resolve {EVENT.OPDATA} macro. * * * ******************************************************************************/ static void resolve_opdata(const zbx_db_event *event, char **replace_to, const char *tz, char *error, int maxerrlen) { zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if ('\0' == *event->trigger.opdata) { int i; zbx_vector_uint64_t itemids; zbx_timespec_t ts; ts.sec = time(NULL); ts.ns = 999999999; zbx_vector_uint64_create(&itemids); zbx_db_trigger_get_itemids(&event->trigger, &itemids); for (i = 0; i < itemids.values_num; i++) { char *val = NULL; if (NULL != *replace_to) *replace_to = zbx_strdcat(*replace_to, ", "); if (SUCCEED == expr_db_item_get_value(itemids.values[i], &val, 0, &ts)) { *replace_to = zbx_strdcat(*replace_to, val); zbx_free(val); } else *replace_to = zbx_strdcat(*replace_to, STR_UNKNOWN_VARIABLE); } zbx_vector_uint64_destroy(&itemids); } else { *replace_to = zbx_strdup(*replace_to, event->trigger.opdata); substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, replace_to, ZBX_MACRO_TYPE_TRIGGER_DESCRIPTION, error, maxerrlen); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } /****************************************************************************** * * * Purpose: resolve {USER.*} macros. * * * ******************************************************************************/ static void resolve_user_macros(zbx_uint64_t userid, const char *m, char **user_username, char **user_name, char **user_surname, int *user_names_found, char **replace_to) { /* use only one DB request for all occurrences of 5 macros */ if (0 == *user_names_found) { if (SUCCEED == zbx_db_get_user_names(userid, user_username, user_name, user_surname)) *user_names_found = 1; else return; } if (0 == strcmp(m, MVAR_USER_USERNAME) || 0 == strcmp(m, MVAR_USER_ALIAS)) { *replace_to = zbx_strdup(*replace_to, *user_username); } else if (0 == strcmp(m, MVAR_USER_NAME)) { *replace_to = zbx_strdup(*replace_to, *user_name); } else if (0 == strcmp(m, MVAR_USER_SURNAME)) { *replace_to = zbx_strdup(*replace_to, *user_surname); } else if (0 == strcmp(m, MVAR_USER_FULLNAME)) { zbx_free(*replace_to); *replace_to = format_user_fullname(*user_name, *user_surname, *user_username); } } static int resolve_host_target_macros(const char *m, const zbx_dc_host_t *dc_host, char **replace_to) { int ret = SUCCEED; if (NULL == dc_host) return SUCCEED; if (0 == strcmp(m, MVAR_HOST_TARGET_DNS)) { ret = expr_dc_get_interface_value(dc_host->hostid, 0, replace_to, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_TARGET_CONN)) { ret = expr_dc_get_interface_value(dc_host->hostid, 0, replace_to, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_TARGET_HOST)) { *replace_to = zbx_strdup(*replace_to, dc_host->host); } else if (0 == strcmp(m, MVAR_HOST_TARGET_IP)) { ret = expr_dc_get_interface_value(dc_host->hostid, 0, replace_to, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_TARGET_NAME)) { *replace_to = zbx_strdup(*replace_to, dc_host->name); } return ret; } /****************************************************************************** * * * Purpose: request cause event value by macro. * * * ******************************************************************************/ static int get_event_cause_value(const char *macro, char **replace_to, const zbx_db_event *event, zbx_db_event **cause_event, zbx_db_event **cause_recovery_event, const zbx_uint64_t *recipient_userid, const char *tz, char *error, int maxerrlen) { zbx_db_event *c_event; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid = " ZBX_FS_UI64 ", event name = '%s'", __func__, event->eventid, event->name); if (NULL == *cause_event) zbx_db_prepare_empty_event(zbx_db_get_cause_eventid(event->eventid), cause_event); if (0 == (*cause_event)->eventid) goto out; if (0 == strcmp(macro, MVAR_EVENT_CAUSE_DURATION) || 0 == strcmp(macro, MVAR_EVENT_CAUSE_STATUS) || 0 == strcmp(macro, MVAR_EVENT_CAUSE_VALUE) || 0 == strcmp(macro, MVAR_EVENT_CAUSE_OPDATA)) { if (NULL == *cause_recovery_event) { zbx_vector_uint64_t eventids, r_eventids; zbx_vector_uint64_pair_t dummy_event_pairs; zbx_vector_uint64_create(&eventids); zbx_vector_uint64_create(&r_eventids); zbx_vector_uint64_pair_create(&dummy_event_pairs); zbx_vector_uint64_append(&eventids, (*cause_event)->eventid); zbx_db_get_eventid_r_eventid_pairs(&eventids, &dummy_event_pairs, &r_eventids); zbx_db_prepare_empty_event(0 != r_eventids.values_num ? r_eventids.values[0] : 0, cause_recovery_event); zbx_vector_uint64_destroy(&eventids); zbx_vector_uint64_destroy(&r_eventids); zbx_vector_uint64_pair_destroy(&dummy_event_pairs); } c_event = (0 != (*cause_recovery_event)->eventid) ? *cause_recovery_event : *cause_event; } else c_event = *cause_event; zbx_db_get_event_data_core(c_event); if (0 == (ZBX_FLAGS_DB_EVENT_RETRIEVED_CORE & c_event->flags)) goto out; if (0 == strcmp(macro, MVAR_EVENT_CAUSE_UPDATE_HISTORY)) { zbx_event_db_get_history(c_event, replace_to, recipient_userid, tz); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_ACK_STATUS)) { *replace_to = zbx_strdup(*replace_to, c_event->acknowledged ? "Yes" : "No"); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_AGE)) { *replace_to = zbx_strdup(*replace_to, zbx_age2str(time(NULL) - c_event->clock)); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_DATE)) { *replace_to = zbx_strdup(*replace_to, zbx_date2str(c_event->clock, tz)); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_DURATION)) { if (NULL != cause_recovery_event && 0 != (*cause_recovery_event)->eventid) { *replace_to = zbx_strdup(*replace_to, zbx_age2str((*cause_recovery_event)->clock - c_event->clock)); } else *replace_to = zbx_strdup(*replace_to, zbx_age2str(time(NULL) - c_event->clock)); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_ID)) { *replace_to = zbx_dsprintf(*replace_to, ZBX_FS_UI64, c_event->eventid); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_NAME)) { *replace_to = zbx_strdup(*replace_to, c_event->name); } if (0 == strcmp(macro, MVAR_EVENT_CAUSE_STATUS)) { *replace_to = zbx_strdup(*replace_to, event_value_string((unsigned char)c_event->source, (unsigned char)c_event->object, (unsigned char)c_event->value)); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_TAGS)) { zbx_db_get_event_data_tags(c_event); zbx_event_get_str_tags(c_event, replace_to); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_TAGSJSON)) { zbx_db_get_event_data_tags(c_event); zbx_event_get_json_tags(c_event, replace_to); } else if (0 == strncmp(macro, MVAR_EVENT_CAUSE_TAGS_PREFIX, ZBX_CONST_STRLEN(MVAR_EVENT_CAUSE_TAGS_PREFIX))) { zbx_db_get_event_data_tags(c_event); zbx_event_get_tag(macro + ZBX_CONST_STRLEN(MVAR_EVENT_CAUSE_TAGS_PREFIX), c_event, replace_to); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_TIME)) { *replace_to = zbx_strdup(*replace_to, zbx_time2str(c_event->clock, tz)); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_VALUE)) { *replace_to = zbx_dsprintf(*replace_to, "%d", c_event->value); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_SEVERITY)) { if (FAIL == zbx_config_get_trigger_severity_name(c_event->severity, replace_to)) *replace_to = zbx_strdup(*replace_to, "unknown"); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_NSEVERITY)) { *replace_to = zbx_dsprintf(*replace_to, "%d", (int)c_event->severity); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_OBJECT)) { *replace_to = zbx_dsprintf(*replace_to, "%d", c_event->object); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_SOURCE)) { *replace_to = zbx_dsprintf(*replace_to, "%d", c_event->source); } else if (0 == strcmp(macro, MVAR_EVENT_CAUSE_OPDATA)) { zbx_db_get_event_data_tags(c_event); zbx_db_get_event_data_triggers(c_event); if (0 == (ZBX_FLAGS_DB_EVENT_RETRIEVED_TRIGGERS & c_event->flags)) goto out; resolve_opdata(c_event, replace_to, tz, error, maxerrlen); } ret = SUCCEED; out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } static int is_strict_macro(const char *macro) { const char *strict_macros[] = {MVAR_HOST_IP, MVAR_IPADDRESS, MVAR_HOST_DNS, MVAR_HOST_CONN, MVAR_HOST_TARGET_DNS, MVAR_HOST_TARGET_CONN, MVAR_HOST_TARGET_IP}; for (int i = 0; i < (int)ARRSIZE(strict_macros); i++) { if (0 == strcmp(strict_macros[i], macro)) return SUCCEED; } return FAIL; } /****************************************************************************** * * * Purpose: substitute simple macros in data string with real values. * * * ******************************************************************************/ int substitute_simple_macros_impl(const zbx_uint64_t *actionid, const zbx_db_event *event, const zbx_db_event *r_event, const zbx_uint64_t *userid, const zbx_uint64_t *hostid, const zbx_dc_host_t *dc_host, const zbx_dc_item_t *dc_item, const zbx_db_alert *alert, const zbx_db_acknowledge *ack, const zbx_service_alarm_t *service_alarm, const zbx_db_service *service, const char *tz, zbx_history_recv_item_t *history_data_item, char **data, int macro_type, char *error, int maxerrlen) { char c, *replace_to = NULL, sql[64], *m_ptr; const char *m; int N_functionid, indexed_macro, ret, res = SUCCEED, pos = 0, found, user_names_found = 0, raw_value; size_t data_alloc, data_len; zbx_dc_interface_t interface; zbx_vector_uint64_t hostids; const zbx_vector_uint64_t *phostids; zbx_token_t token, inner_token; zbx_token_search_t token_search = ZBX_TOKEN_SEARCH_BASIC; char *expression = NULL, *user_username = NULL, *user_name = NULL, *user_surname = NULL; zbx_dc_um_handle_t *um_handle; zbx_db_event *cause_event = NULL, *cause_recovery_event = NULL; if (NULL == data || NULL == *data || '\0' == **data) { zabbix_log(LOG_LEVEL_DEBUG, "In %s() data:EMPTY", __func__); return res; } zabbix_log(LOG_LEVEL_DEBUG, "In %s() data:'%s'", __func__, *data); if (0 != (macro_type & (ZBX_MACRO_TYPE_TRIGGER_DESCRIPTION | ZBX_MACRO_TYPE_EVENT_NAME))) token_search |= ZBX_TOKEN_SEARCH_REFERENCES; if (0 != (macro_type & (ZBX_MACRO_TYPE_MESSAGE_NORMAL | ZBX_MACRO_TYPE_MESSAGE_RECOVERY | ZBX_MACRO_TYPE_MESSAGE_UPDATE | ZBX_MACRO_TYPE_EVENT_NAME))) { const zbx_db_event *c_event; c_event = ((NULL != r_event) ? r_event : event); if (NULL != c_event && EVENT_SOURCE_TRIGGERS == c_event->source) token_search |= ZBX_TOKEN_SEARCH_EXPRESSION_MACRO; } if (SUCCEED != zbx_token_find(*data, pos, &token, token_search)) goto out; um_handle = zbx_dc_open_user_macros(); zbx_vector_uint64_create(&hostids); data_alloc = data_len = strlen(*data) + 1; for (found = SUCCEED; SUCCEED == res && SUCCEED == found; found = zbx_token_find(*data, pos, &token, token_search)) { indexed_macro = 0; N_functionid = 1; raw_value = 0; pos = token.loc.l; inner_token = token; ret = SUCCEED; switch (token.type) { case ZBX_TOKEN_OBJECTID: case ZBX_TOKEN_LLD_MACRO: case ZBX_TOKEN_LLD_FUNC_MACRO: /* neither lld nor {123123} macros are processed by this function, skip them */ pos = token.loc.r + 1; continue; case ZBX_TOKEN_MACRO: if (0 != is_indexed_macro(*data, &token) && NULL != (m = macro_in_list(*data, token.loc, ex_macros, &N_functionid))) { indexed_macro = 1; } else { m = *data + token.loc.l; c = (*data)[token.loc.r + 1]; (*data)[token.loc.r + 1] = '\0'; } break; case ZBX_TOKEN_USER_FUNC_MACRO: case ZBX_TOKEN_FUNC_MACRO: raw_value = 1; indexed_macro = is_indexed_macro(*data, &token); if (NULL == (m_ptr = func_get_macro_from_func(*data, &token.data.func_macro, &N_functionid)) || SUCCEED != zbx_token_find(*data, token.data.func_macro.macro.l, &inner_token, token_search)) { /* Ignore functions with macros not supporting them, but do not skip the */ /* whole token, nested macro should be resolved in this case. */ pos++; ret = FAIL; } m = m_ptr; break; case ZBX_TOKEN_USER_MACRO: /* To avoid *data modification user macro resolver should be replaced with a function */ /* that takes initial *data string and token.data.user_macro instead of m as params. */ m = *data + token.loc.l; c = (*data)[token.loc.r + 1]; (*data)[token.loc.r + 1] = '\0'; break; case ZBX_TOKEN_REFERENCE: case ZBX_TOKEN_EXPRESSION_MACRO: /* These macros (and probably all other in the future) must be resolved using only */ /* information stored in token.data union. For now, force crash if they rely on m. */ m = NULL; break; default: THIS_SHOULD_NEVER_HAPPEN; res = FAIL; continue; } if (SUCCEED == ret) { if (0 != (macro_type & (ZBX_MACRO_TYPE_MESSAGE_NORMAL | ZBX_MACRO_TYPE_MESSAGE_RECOVERY | ZBX_MACRO_TYPE_MESSAGE_UPDATE | ZBX_MACRO_TYPE_SCRIPT_NORMAL | ZBX_MACRO_TYPE_SCRIPT_RECOVERY))) /* ZBX_MACRO_TYPE_SCRIPT_NORMAL and ZBX_MACRO_TYPE_SCRIPT_RECOVERY behave pretty similar to */ /* ZBX_MACRO_TYPE_MESSAGE_NORMAL and ZBX_MACRO_TYPE_MESSAGE_RECOVERY. Therefore the code is not duplicated */ /* but few conditions are added below where behavior differs. */ { const zbx_db_event *c_event; c_event = ((NULL != r_event) ? r_event : event); if (EVENT_SOURCE_TRIGGERS == c_event->source) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (NULL == dc_host) { if (SUCCEED == zbx_db_trigger_get_all_hostids(&c_event->trigger, &phostids)) { zbx_dc_get_user_macro(um_handle, m, phostids->values, phostids->values_num, &replace_to); } } else zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (ZBX_TOKEN_EXPRESSION_MACRO == inner_token.type) { zbx_timespec_t ts; char *errmsg = NULL; zbx_timespec(&ts); if (SUCCEED != (ret = get_expression_macro_result(event, *data, &inner_token.data.expression_macro.expression, &ts, &replace_to, &errmsg))) { *errmsg = tolower(*errmsg); zabbix_log(LOG_LEVEL_DEBUG, "%s() cannot evaluate" " expression macro: %s", __func__, errmsg); zbx_strlcpy(error, errmsg, maxerrlen); zbx_free(errmsg); } } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (NULL != actionid && 0 == strcmp(m, MVAR_ESC_HISTORY)) { expr_db_get_escalation_history(*actionid, event, r_event, &replace_to, userid, tz); } else if (0 == strncmp(m, MVAR_EVENT_RECOVERY, ZBX_CONST_STRLEN(MVAR_EVENT_RECOVERY))) { if (NULL != r_event) get_recovery_event_value(m, r_event, &replace_to, tz); } else if (0 == strncmp(m, MVAR_EVENT_CAUSE, ZBX_CONST_STRLEN(MVAR_EVENT_CAUSE))) { ret = get_event_cause_value(m, &replace_to, event, &cause_event, &cause_recovery_event, userid, tz, error, maxerrlen); } else if (0 == strcmp(m, MVAR_EVENT_SYMPTOMS)) { ret = expr_db_get_event_symptoms(event, &replace_to); } else if (0 == strcmp(m, MVAR_EVENT_STATUS) || 0 == strcmp(m, MVAR_EVENT_VALUE)) { get_current_event_value(m, c_event, &replace_to); } else if (0 == strcmp(m, MVAR_EVENT_NAME)) { replace_to = zbx_strdup(replace_to, event->name); } else if (0 == strcmp(m, MVAR_EVENT_OPDATA)) { resolve_opdata(c_event, &replace_to, tz, error, maxerrlen); } else if (0 == strcmp(m, MVAR_ACK_MESSAGE) || 0 == strcmp(m, MVAR_EVENT_UPDATE_MESSAGE)) { if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != ack) replace_to = zbx_strdup(replace_to, ack->message); } else if (0 == strcmp(m, MVAR_ACK_TIME) || 0 == strcmp(m, MVAR_EVENT_UPDATE_TIME)) { if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != ack) replace_to = zbx_strdup(replace_to, zbx_time2str(ack->clock, tz)); } else if (0 == strcmp(m, MVAR_ACK_DATE) || 0 == strcmp(m, MVAR_EVENT_UPDATE_DATE)) { if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != ack) replace_to = zbx_strdup(replace_to, zbx_date2str(ack->clock, tz)); } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_ACTION)) { if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != ack) { zbx_problem_get_actions(ack, ZBX_PROBLEM_UPDATE_ACKNOWLEDGE | ZBX_PROBLEM_UPDATE_UNACKNOWLEDGE | ZBX_PROBLEM_UPDATE_CLOSE | ZBX_PROBLEM_UPDATE_MESSAGE | ZBX_PROBLEM_UPDATE_SEVERITY | ZBX_PROBLEM_UPDATE_SUPPRESS | ZBX_PROBLEM_UPDATE_UNSUPPRESS, tz, &replace_to); } } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_STATUS)) { if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != ack) replace_to = zbx_strdup(replace_to, "1"); else replace_to = zbx_strdup(replace_to, "0"); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT))) { zbx_event_get_macro_value(m, event, &replace_to, userid, r_event, tz); } else if (0 == strcmp(m, MVAR_HOST_ID)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_DESCRIPTION)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DESCRIPTION); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_PORT); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)) || 0 == strncmp(m, MVAR_PROFILE, ZBX_CONST_STRLEN(MVAR_PROFILE))) { ret = expr_dc_get_host_inventory(m, &c_event->trigger, &replace_to, N_functionid); } else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION); } else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION_ORIG)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_ID)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_ID); } else if (0 == strcmp(m, MVAR_ITEM_KEY) || 0 == strcmp(m, MVAR_TRIGGER_KEY)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_KEY); } else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_KEY_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE)) { ret = expr_db_item_lastvalue(&c_event->trigger, &replace_to, N_functionid, raw_value); } else if (0 == strcmp(m, MVAR_ITEM_NAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_NAME); } else if (0 == strcmp(m, MVAR_ITEM_NAME_ORIG)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_NAME_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_VALUE)) { ret = expr_db_item_value(&c_event->trigger, &replace_to, N_functionid, c_event->clock, c_event->ns, raw_value); } else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG))) { ret = expr_get_history_log_value(m, &c_event->trigger, &replace_to, N_functionid, c_event->clock, c_event->ns, tz); } else if (0 == strcmp(m, MVAR_ITEM_VALUETYPE)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_VALUETYPE); } else if (0 == strcmp(m, MVAR_PROXY_NAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_PROXY_NAME); } else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_PROXY_DESCRIPTION); } else if (0 == indexed_macro && 0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_TRIGGER_DESCRIPTION) || 0 == strcmp(m, MVAR_TRIGGER_COMMENT)) { replace_to = zbx_strdup(replace_to, c_event->trigger.comments); substitute_simple_macros_impl(NULL, c_event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_COMMENTS, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_EVENTS_ACK)) { ret = zbx_event_db_count_from_trigger(c_event->objectid, &replace_to, 0, 1); } else if (0 == strcmp(m, MVAR_TRIGGER_EVENTS_PROBLEM_ACK)) { ret = zbx_event_db_count_from_trigger(c_event->objectid, &replace_to, 1, 1); } else if (0 == strcmp(m, MVAR_TRIGGER_EVENTS_PROBLEM_UNACK)) { ret = zbx_event_db_count_from_trigger(c_event->objectid, &replace_to, 1, 0); } else if (0 == strcmp(m, MVAR_TRIGGER_EVENTS_UNACK)) { ret = zbx_event_db_count_from_trigger(c_event->objectid, &replace_to, 0, 0); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION)) { zbx_db_trigger_get_expression(&c_event->trigger, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_RECOVERY)) { if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == c_event->trigger.recovery_mode) { zbx_db_trigger_get_recovery_expression(&c_event->trigger, &replace_to); } else replace_to = zbx_strdup(replace_to, ""); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_EXPLAIN)) { zbx_db_trigger_explain_expression(&c_event->trigger, &replace_to, evaluate_function, 0); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_RECOVERY_EXPLAIN)) { if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == c_event->trigger.recovery_mode) { zbx_db_trigger_explain_expression(&c_event->trigger, &replace_to, evaluate_function, 1); } else replace_to = zbx_strdup(replace_to, ""); } else if (0 == strcmp(m, MVAR_FUNCTION_VALUE)) { zbx_db_trigger_get_function_value(&c_event->trigger, N_functionid, &replace_to, evaluate_function, 0); } else if (0 == strcmp(m, MVAR_FUNCTION_RECOVERY_VALUE)) { zbx_db_trigger_get_function_value(&c_event->trigger, N_functionid, &replace_to, evaluate_function, 1); } else if (0 == strcmp(m, MVAR_TRIGGER_HOSTGROUP_NAME)) { ret = expr_db_get_trigger_hostgroup_name(c_event->objectid, userid, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, c_event->objectid); } else if (0 == strcmp(m, MVAR_TRIGGER_NAME)) { replace_to = zbx_strdup(replace_to, c_event->trigger.description); substitute_simple_macros_impl(NULL, c_event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_DESCRIPTION, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_NAME_ORIG)) { replace_to = zbx_strdup(replace_to, c_event->trigger.description); } else if (0 == strcmp(m, MVAR_TRIGGER_NSEVERITY)) { replace_to = zbx_dsprintf(replace_to, "%d", (int)c_event->trigger.priority); } else if (0 == strcmp(m, MVAR_TRIGGER_STATUS) || 0 == strcmp(m, MVAR_STATUS)) { replace_to = zbx_strdup(replace_to, trigger_value_string(c_event->trigger.value)); } else if (0 == strcmp(m, MVAR_TRIGGER_SEVERITY)) { ret = zbx_config_get_trigger_severity_name(c_event->trigger.priority, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_TEMPLATE_NAME)) { ret = expr_db_get_trigger_template_name(c_event->objectid, userid, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_URL)) { replace_to = zbx_strdup(replace_to, event->trigger.url); substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_URL, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_URL_NAME)) { replace_to = zbx_strdup(replace_to, event->trigger.url_name); substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_URL, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_VALUE)) { replace_to = zbx_dsprintf(replace_to, "%d", c_event->trigger.value); } else if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != ack && 0 == strcmp(m, MVAR_USER_FULLNAME)) { const char *user_name1; if (SUCCEED == zbx_check_user_permissions(&ack->userid, userid)) user_name1 = zbx_user_string(ack->userid); else user_name1 = "Inaccessible user"; replace_to = zbx_strdup(replace_to, user_name1); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } else if (0 != (macro_type & (ZBX_MACRO_TYPE_SCRIPT_NORMAL | ZBX_MACRO_TYPE_SCRIPT_RECOVERY)) && NULL != userid && (0 == strcmp(m, MVAR_USER_USERNAME) || 0 == strcmp(m, MVAR_USER_NAME) || 0 == strcmp(m, MVAR_USER_SURNAME) || 0 == strcmp(m, MVAR_USER_FULLNAME) || 0 == strcmp(m, MVAR_USER_ALIAS))) { resolve_user_macros(*userid, m, &user_username, &user_name, &user_surname, &user_names_found, &replace_to); } else if (0 == (macro_type & (ZBX_MACRO_TYPE_SCRIPT_NORMAL | ZBX_MACRO_TYPE_SCRIPT_RECOVERY))) { ret = resolve_host_target_macros(m, dc_host, &replace_to); } } else if (EVENT_SOURCE_INTERNAL == c_event->source && EVENT_OBJECT_TRIGGER == c_event->object) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (SUCCEED == zbx_db_trigger_get_all_hostids(&c_event->trigger, &phostids)) { zbx_dc_get_user_macro(um_handle, m, phostids->values, phostids->values_num, &replace_to); } pos = token.loc.r; } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (NULL != actionid && 0 == strcmp(m, MVAR_ESC_HISTORY)) { expr_db_get_escalation_history(*actionid, event, r_event, &replace_to, userid, tz); } else if (0 == strncmp(m, MVAR_EVENT_RECOVERY, ZBX_CONST_STRLEN(MVAR_EVENT_RECOVERY))) { if (NULL != r_event) get_recovery_event_value(m, r_event, &replace_to, tz); } else if (0 == strcmp(m, MVAR_EVENT_STATUS) || 0 == strcmp(m, MVAR_EVENT_VALUE)) { get_current_event_value(m, c_event, &replace_to); } else if (0 == strcmp(m, MVAR_EVENT_NAME)) { replace_to = zbx_strdup(replace_to, event->name); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT))) { zbx_event_get_macro_value(m, event, &replace_to, userid, r_event, tz); } else if (0 == strcmp(m, MVAR_HOST_ID)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_DESCRIPTION)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DESCRIPTION); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_PORT); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)) || 0 == strncmp(m, MVAR_PROFILE, ZBX_CONST_STRLEN(MVAR_PROFILE))) { ret = expr_dc_get_host_inventory(m, &c_event->trigger, &replace_to, N_functionid); } else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION); } else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION_ORIG)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_ID)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_ID); } else if (0 == strcmp(m, MVAR_ITEM_KEY) || 0 == strcmp(m, MVAR_TRIGGER_KEY)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_KEY); } else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_KEY_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_NAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_NAME); } else if (0 == strcmp(m, MVAR_ITEM_NAME_ORIG)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_NAME_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_VALUETYPE)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_ITEM_VALUETYPE); } else if (0 == strcmp(m, MVAR_PROXY_NAME)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_PROXY_NAME); } else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION)) { ret = expr_db_get_trigger_value(&c_event->trigger, &replace_to, N_functionid, ZBX_REQUEST_PROXY_DESCRIPTION); } else if (0 == indexed_macro && 0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_TRIGGER_DESCRIPTION) || 0 == strcmp(m, MVAR_TRIGGER_COMMENT)) { replace_to = zbx_strdup(replace_to, c_event->trigger.comments); substitute_simple_macros_impl(NULL, c_event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_COMMENTS, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION)) { zbx_db_trigger_get_expression(&c_event->trigger, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_RECOVERY)) { if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == c_event->trigger.recovery_mode) { zbx_db_trigger_get_recovery_expression(&c_event->trigger, &replace_to); } else replace_to = zbx_strdup(replace_to, ""); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_EXPLAIN)) { zbx_db_trigger_explain_expression(&c_event->trigger, &replace_to, evaluate_function, 0); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_RECOVERY_EXPLAIN)) { if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == c_event->trigger.recovery_mode) { zbx_db_trigger_explain_expression(&c_event->trigger, &replace_to, evaluate_function, 1); } else replace_to = zbx_strdup(replace_to, ""); } else if (0 == strcmp(m, MVAR_FUNCTION_VALUE)) { zbx_db_trigger_get_function_value(&c_event->trigger, N_functionid, &replace_to, evaluate_function, 0); } else if (0 == strcmp(m, MVAR_FUNCTION_RECOVERY_VALUE)) { zbx_db_trigger_get_function_value(&c_event->trigger, N_functionid, &replace_to, evaluate_function, 1); } else if (0 == strcmp(m, MVAR_TRIGGER_HOSTGROUP_NAME)) { ret = expr_db_get_trigger_hostgroup_name(c_event->objectid, userid, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, c_event->objectid); } else if (0 == strcmp(m, MVAR_TRIGGER_NAME)) { replace_to = zbx_strdup(replace_to, c_event->trigger.description); substitute_simple_macros_impl(NULL, c_event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_DESCRIPTION, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_NAME_ORIG)) { replace_to = zbx_strdup(replace_to, c_event->trigger.description); } else if (0 == strcmp(m, MVAR_TRIGGER_NSEVERITY)) { replace_to = zbx_dsprintf(replace_to, "%d", (int)c_event->trigger.priority); } else if (0 == strcmp(m, MVAR_TRIGGER_SEVERITY)) { ret = zbx_config_get_trigger_severity_name(c_event->trigger.priority, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_STATE)) { replace_to = zbx_strdup(replace_to, trigger_state_string(c_event->value)); } else if (0 == strcmp(m, MVAR_TRIGGER_STATE_ERROR)) { ret = expr_db_get_trigger_error(&event->trigger, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_TEMPLATE_NAME)) { ret = expr_db_get_trigger_template_name(c_event->objectid, userid, &replace_to); } else if (0 == strcmp(m, MVAR_TRIGGER_URL)) { replace_to = zbx_strdup(replace_to, event->trigger.url); substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_URL, error, maxerrlen); } else if (0 == strcmp(m, MVAR_TRIGGER_URL_NAME)) { replace_to = zbx_strdup(replace_to, event->trigger.url_name); substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tz, NULL, &replace_to, ZBX_MACRO_TYPE_TRIGGER_URL, error, maxerrlen); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } } else if (0 == indexed_macro && EVENT_SOURCE_DISCOVERY == c_event->source) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (NULL == dc_host) zbx_dc_get_user_macro(um_handle, m, NULL, 0, &replace_to); else zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT)) && 0 != strcmp(m, MVAR_EVENT_DURATION)) { zbx_event_get_macro_value(m, event, &replace_to, userid, NULL, tz); } else if (0 == strcmp(m, MVAR_DISCOVERY_DEVICE_IPADDRESS)) { ret = zbx_event_db_get_dhost(c_event, &replace_to, "s.ip"); } else if (0 == strcmp(m, MVAR_DISCOVERY_DEVICE_DNS)) { ret = zbx_event_db_get_dhost(c_event, &replace_to, "s.dns"); } else if (0 == strcmp(m, MVAR_DISCOVERY_DEVICE_STATUS)) { if (SUCCEED == (ret = zbx_event_db_get_dhost(c_event, &replace_to, "h.status"))) { replace_to = zbx_strdup(replace_to, zbx_dobject_status2str(atoi(replace_to))); } } else if (0 == strcmp(m, MVAR_DISCOVERY_DEVICE_UPTIME)) { zbx_snprintf(sql, sizeof(sql), "case when h.status=%d then h.lastup else h.lastdown end", DOBJECT_STATUS_UP); if (SUCCEED == (ret = zbx_event_db_get_dhost(c_event, &replace_to, sql))) { replace_to = zbx_strdup(replace_to, zbx_age2str(time(NULL) - atoi(replace_to))); } } else if (0 == strcmp(m, MVAR_DISCOVERY_RULE_NAME)) { ret = zbx_event_db_get_drule(c_event, &replace_to, "name"); } else if (0 == strcmp(m, MVAR_DISCOVERY_SERVICE_NAME)) { if (SUCCEED == (ret = zbx_event_db_get_dchecks(c_event, &replace_to, "c.type"))) { replace_to = zbx_strdup(replace_to, zbx_dservice_type_string(atoi(replace_to))); } } else if (0 == strcmp(m, MVAR_DISCOVERY_SERVICE_PORT)) { ret = zbx_event_db_get_dservice(c_event, &replace_to, "s.port"); } else if (0 == strcmp(m, MVAR_DISCOVERY_SERVICE_STATUS)) { if (SUCCEED == (ret = zbx_event_db_get_dservice(c_event, &replace_to, "s.status"))) { replace_to = zbx_strdup(replace_to, zbx_dobject_status2str(atoi(replace_to))); } } else if (0 == strcmp(m, MVAR_DISCOVERY_SERVICE_UPTIME)) { zbx_snprintf(sql, sizeof(sql), "case when s.status=%d then s.lastup else s.lastdown end", DOBJECT_STATUS_UP); if (SUCCEED == (ret = zbx_event_db_get_dservice(c_event, &replace_to, sql))) { replace_to = zbx_strdup(replace_to, zbx_age2str(time(NULL) - atoi(replace_to))); } } else if (0 == strcmp(m, MVAR_PROXY_NAME)) { if (SUCCEED == (ret = zbx_event_db_get_dhost(c_event, &replace_to, "r.proxyid"))) { zbx_uint64_t proxyid = 0; ZBX_DBROW2UINT64(proxyid, replace_to); if (0 == proxyid) replace_to = zbx_strdup(replace_to, ""); else ret = expr_db_get_proxy_value(proxyid, &replace_to, "name"); } } else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION)) { if (SUCCEED == (ret = zbx_event_db_get_dhost(c_event, &replace_to, "r.proxyid"))) { zbx_uint64_t proxyid = 0; ZBX_DBROW2UINT64(proxyid, replace_to); if (0 == proxyid) { replace_to = zbx_strdup(replace_to, ""); } else { ret = expr_db_get_proxy_value(proxyid, &replace_to, "description"); } } } else if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } else { ret = resolve_host_target_macros(m, dc_host, &replace_to); } } else if (0 == indexed_macro && EVENT_SOURCE_AUTOREGISTRATION == c_event->source) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (NULL == dc_host) zbx_dc_get_user_macro(um_handle, m, NULL, 0, &replace_to); else zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT)) && 0 != strcmp(m, MVAR_EVENT_DURATION)) { zbx_event_get_macro_value(m, event, &replace_to, userid, NULL, tz); } else if (0 == strcmp(m, MVAR_HOST_METADATA)) { ret = zbx_event_db_get_autoreg(c_event, &replace_to, "host_metadata"); } else if (0 == strcmp(m, MVAR_HOST_HOST)) { ret = zbx_event_db_get_autoreg(c_event, &replace_to, "host"); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = zbx_event_db_get_autoreg(c_event, &replace_to, "listen_ip"); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = zbx_event_db_get_autoreg(c_event, &replace_to, "listen_port"); } else if (0 == strcmp(m, MVAR_PROXY_NAME)) { if (SUCCEED == (ret = zbx_event_db_get_autoreg(c_event, &replace_to, "proxyid"))) { zbx_uint64_t proxyid = 0; ZBX_DBROW2UINT64(proxyid, replace_to); if (0 == proxyid) replace_to = zbx_strdup(replace_to, ""); else ret = expr_db_get_proxy_value(proxyid, &replace_to, "name"); } } else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION)) { if (SUCCEED == (ret = zbx_event_db_get_autoreg(c_event, &replace_to, "proxyid"))) { zbx_uint64_t proxyid = 0; ZBX_DBROW2UINT64(proxyid, replace_to); if (0 == proxyid) { replace_to = zbx_strdup(replace_to, ""); } else { ret = expr_db_get_proxy_value(proxyid, &replace_to, "description"); } } } else if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } else { ret = resolve_host_target_macros(m, dc_host, &replace_to); } } else if (0 == indexed_macro && EVENT_SOURCE_INTERNAL == c_event->source && EVENT_OBJECT_ITEM == c_event->object) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { cache_item_hostid(&hostids, c_event->objectid); zbx_dc_get_user_macro(um_handle, m, hostids.values, hostids.values_num, &replace_to); pos = token.loc.r; } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (NULL != actionid && 0 == strcmp(m, MVAR_ESC_HISTORY)) { expr_db_get_escalation_history(*actionid, event, r_event, &replace_to, userid, tz); } else if (0 == strncmp(m, MVAR_EVENT_RECOVERY, ZBX_CONST_STRLEN(MVAR_EVENT_RECOVERY))) { if (NULL != r_event) get_recovery_event_value(m, r_event, &replace_to, tz); } else if (0 == strcmp(m, MVAR_EVENT_STATUS) || 0 == strcmp(m, MVAR_EVENT_VALUE)) { get_current_event_value(m, c_event, &replace_to); } else if (0 == strcmp(m, MVAR_EVENT_NAME)) { replace_to = zbx_strdup(replace_to, event->name); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT))) { zbx_event_get_macro_value(m, event, &replace_to, userid, r_event, tz); } else if (0 == strcmp(m, MVAR_HOST_ID)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_DESCRIPTION)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_DESCRIPTION); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_PORT); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)) || 0 == strncmp(m, MVAR_PROFILE, ZBX_CONST_STRLEN(MVAR_PROFILE))) { ret = expr_dc_get_host_inventory_by_itemid(m, c_event->objectid, &replace_to); } else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_DESCRIPTION); } else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION_ORIG)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_DESCRIPTION_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, c_event->objectid); } else if (0 == strcmp(m, MVAR_ITEM_KEY) || 0 == strcmp(m, MVAR_TRIGGER_KEY)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_KEY); } else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_KEY_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_NAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_NAME); } else if (0 == strcmp(m, MVAR_ITEM_NAME_ORIG)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_NAME_ORIG); } else if (0 == strcmp(m, MVAR_ITEM_STATE)) { replace_to = zbx_strdup(replace_to, item_state_string(c_event->value)); } else if (0 == strcmp(m, MVAR_ITEM_VALUETYPE)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_VALUETYPE); } else if (0 == strcmp(m, MVAR_PROXY_NAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_PROXY_NAME); } else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_PROXY_DESCRIPTION); } else if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } else if (0 == strcmp(m, MVAR_ITEM_STATE_ERROR)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_ERROR); } } else if (0 == indexed_macro && EVENT_SOURCE_INTERNAL == c_event->source && EVENT_OBJECT_LLDRULE == c_event->object) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { cache_item_hostid(&hostids, c_event->objectid); zbx_dc_get_user_macro(um_handle, m, hostids.values, hostids.values_num, &replace_to); pos = token.loc.r; } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (NULL != actionid && 0 == strcmp(m, MVAR_ESC_HISTORY)) { expr_db_get_escalation_history(*actionid, event, r_event, &replace_to, userid, tz); } else if (0 == strncmp(m, MVAR_EVENT_RECOVERY, ZBX_CONST_STRLEN(MVAR_EVENT_RECOVERY))) { if (NULL != r_event) get_recovery_event_value(m, r_event, &replace_to, tz); } else if (0 == strcmp(m, MVAR_EVENT_STATUS) || 0 == strcmp(m, MVAR_EVENT_VALUE)) { get_current_event_value(m, c_event, &replace_to); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT))) { zbx_event_get_macro_value(m, event, &replace_to, userid, r_event, tz); } else if (0 == strcmp(m, MVAR_HOST_ID)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_DESCRIPTION)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_DESCRIPTION); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_HOST_PORT); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)) || 0 == strncmp(m, MVAR_PROFILE, ZBX_CONST_STRLEN(MVAR_PROFILE))) { ret = expr_dc_get_host_inventory_by_itemid(m, c_event->objectid, &replace_to); } else if (0 == strcmp(m, MVAR_LLDRULE_DESCRIPTION)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_DESCRIPTION); } else if (0 == strcmp(m, MVAR_LLDRULE_DESCRIPTION_ORIG)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_DESCRIPTION_ORIG); } else if (0 == strcmp(m, MVAR_LLDRULE_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, c_event->objectid); } else if (0 == strcmp(m, MVAR_LLDRULE_KEY)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_KEY); } else if (0 == strcmp(m, MVAR_LLDRULE_KEY_ORIG)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_KEY_ORIG); } else if (0 == strcmp(m, MVAR_LLDRULE_NAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_NAME); } else if (0 == strcmp(m, MVAR_LLDRULE_NAME_ORIG)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_NAME_ORIG); } else if (0 == strcmp(m, MVAR_LLDRULE_STATE)) { replace_to = zbx_strdup(replace_to, item_state_string(c_event->value)); } else if (0 == strcmp(m, MVAR_PROXY_NAME)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_PROXY_NAME); } else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_PROXY_DESCRIPTION); } else if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } else if (0 == strcmp(m, MVAR_LLDRULE_STATE_ERROR)) { ret = expr_db_get_item_value(c_event->objectid, &replace_to, ZBX_REQUEST_ITEM_ERROR); } } else if (0 == indexed_macro && EVENT_SOURCE_SERVICE == c_event->source) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (NULL == dc_host) zbx_dc_get_user_macro(um_handle, m, NULL, 0, &replace_to); else zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (NULL != actionid && 0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION))) { ret = expr_db_get_action_value(m, *actionid, &replace_to); } else if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_DATE)) { replace_to = zbx_strdup(replace_to, zbx_date2str(time(NULL), tz)); } else if (NULL != actionid && 0 == strcmp(m, MVAR_ESC_HISTORY)) { expr_db_get_escalation_history(*actionid, event, r_event, &replace_to, userid, tz); } else if (0 == strncmp(m, MVAR_EVENT_RECOVERY, ZBX_CONST_STRLEN(MVAR_EVENT_RECOVERY))) { if (NULL != r_event) get_recovery_event_value(m, r_event, &replace_to, tz); } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_NSEVERITY)) { if (NULL != service_alarm) replace_to = zbx_dsprintf(replace_to, "%d", (int)service_alarm->value); } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_SEVERITY)) { if (NULL != service_alarm) { if (FAIL == zbx_config_get_trigger_severity_name(service_alarm->value, &replace_to)) { replace_to = zbx_strdup(replace_to, "unknown"); } } } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_DATE)) { if (NULL != service_alarm) { replace_to = zbx_strdup(replace_to, zbx_date2str(service_alarm->clock, tz)); } } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_TIME)) { if (NULL != service_alarm) { replace_to = zbx_strdup(replace_to, zbx_time2str(service_alarm->clock, tz)); } } else if (0 == strcmp(m, MVAR_EVENT_UPDATE_STATUS)) { if (0 != (macro_type & ZBX_MACRO_TYPE_MESSAGE_UPDATE) && NULL != service_alarm) replace_to = zbx_strdup(replace_to, "1"); else replace_to = zbx_strdup(replace_to, "0"); } else if (0 == strcmp(m, MVAR_EVENT_STATUS) || 0 == strcmp(m, MVAR_EVENT_VALUE)) { get_current_event_value(m, c_event, &replace_to); } else if (0 == strcmp(m, MVAR_EVENT_NAME)) { replace_to = zbx_strdup(replace_to, event->name); } else if (0 == strncmp(m, MVAR_EVENT, ZBX_CONST_STRLEN(MVAR_EVENT))) { zbx_event_get_macro_value(m, event, &replace_to, userid, r_event, tz); } else if (0 == strcmp(m, MVAR_SERVICE_NAME)) { replace_to = zbx_strdup(replace_to, service->name); } else if (0 == strcmp(m, MVAR_SERVICE_DESCRIPTION)) { replace_to = zbx_strdup(replace_to, service->description); } else if (0 == strcmp(m, MVAR_SERVICE_ROOTCAUSE)) { expr_db_get_rootcause(service, &replace_to); } else if (0 == strcmp(m, MVAR_SERVICE_TAGS)) { zbx_event_get_str_tags(event, &replace_to); } else if (0 == strcmp(m, MVAR_SERVICE_TAGSJSON)) { zbx_event_get_json_tags(event, &replace_to); } else if (0 == strncmp(m, MVAR_SERVICE_TAGS_PREFIX, ZBX_CONST_STRLEN(MVAR_SERVICE_TAGS_PREFIX))) { zbx_event_get_tag(m + ZBX_CONST_STRLEN(MVAR_SERVICE_TAGS_PREFIX), event, &replace_to); } else if (0 == strcmp(m, MVAR_ALERT_SENDTO)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->sendto); } else if (0 == strcmp(m, MVAR_ALERT_SUBJECT)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->subject); } else if (0 == strcmp(m, MVAR_ALERT_MESSAGE)) { if (NULL != alert) replace_to = zbx_strdup(replace_to, alert->message); } } } else if (0 != (macro_type & (ZBX_MACRO_TYPE_TRIGGER_DESCRIPTION | ZBX_MACRO_TYPE_TRIGGER_COMMENTS | ZBX_MACRO_TYPE_EVENT_NAME))) { if (EVENT_OBJECT_TRIGGER == event->object) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids)) { zbx_dc_get_user_macro(um_handle, m, phostids->values, phostids->values_num, &replace_to); } pos = token.loc.r; } else if (ZBX_TOKEN_REFERENCE == token.type) { if (SUCCEED != zbx_db_trigger_get_constant(&event->trigger, token.data.reference.index, &replace_to)) { /* expansion failed, reference substitution is impossible */ token_search &= ~ZBX_TOKEN_SEARCH_REFERENCES; continue; } } else if (ZBX_TOKEN_EXPRESSION_MACRO == inner_token.type) { if (0 != (macro_type & ZBX_MACRO_TYPE_EVENT_NAME)) { zbx_timespec_t ts; char *errmsg = NULL; ts.sec = event->clock; ts.ns = event->ns; if (SUCCEED != (ret = get_expression_macro_result(event, *data, &inner_token.data.expression_macro.expression, &ts, &replace_to, &errmsg))) { *errmsg = tolower(*errmsg); zabbix_log(LOG_LEVEL_DEBUG, "%s() cannot evaluate" " expression macro: %s", __func__, errmsg); zbx_strlcpy(error, errmsg, maxerrlen); zbx_free(errmsg); } } } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_PORT); } else if (0 == strcmp(m, MVAR_ITEM_VALUE)) { ret = expr_db_item_value(&event->trigger, &replace_to, N_functionid, event->clock, event->ns, raw_value); } else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG))) { ret = expr_get_history_log_value(m, &event->trigger, &replace_to, N_functionid, event->clock, event->ns, tz); } else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE)) { ret = expr_db_item_lastvalue(&event->trigger, &replace_to, N_functionid, raw_value); } else if (0 != (macro_type & ZBX_MACRO_TYPE_EVENT_NAME)) { if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } else if (0 == strcmp(m, MVAR_TRIGGER_EXPRESSION_EXPLAIN)) { zbx_db_trigger_explain_expression(&event->trigger, &replace_to, evaluate_function, 0); } else if (0 == strcmp(m, MVAR_FUNCTION_VALUE)) { zbx_db_trigger_get_function_value(&event->trigger, N_functionid, &replace_to, evaluate_function, 0); } } } } else if (0 != (macro_type & ZBX_MACRO_TYPE_TRIGGER_EXPRESSION)) { if (EVENT_OBJECT_TRIGGER == event->object) { if (0 == strcmp(m, MVAR_TRIGGER_VALUE)) replace_to = zbx_dsprintf(replace_to, "%d", event->value); } } else if (0 != (macro_type & ZBX_MACRO_TYPE_TRIGGER_URL)) { if (EVENT_OBJECT_TRIGGER == event->object) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids)) { zbx_dc_get_user_macro(um_handle, m, phostids->values, phostids->values_num, &replace_to); } pos = token.loc.r; } else if (0 == strcmp(m, MVAR_HOST_ID)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_IP)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_PORT); } else if (0 == strcmp(m, MVAR_TRIGGER_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, event->objectid); } else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE)) { ret = expr_db_item_lastvalue(&event->trigger, &replace_to, N_functionid, raw_value); } else if (0 == strcmp(m, MVAR_ITEM_VALUE)) { ret = expr_db_item_value(&event->trigger, &replace_to, N_functionid, event->clock, event->ns, raw_value); } else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG))) { ret = expr_get_history_log_value(m, &event->trigger, &replace_to, N_functionid, event->clock, event->ns, tz); } else if (0 == strcmp(m, MVAR_EVENT_ID)) { zbx_event_get_macro_value(m, event, &replace_to, userid, NULL, NULL); } } } else if (0 == indexed_macro && 0 != (macro_type & (ZBX_MACRO_TYPE_ITEM_KEY | ZBX_MACRO_TYPE_PARAMS_FIELD | ZBX_MACRO_TYPE_LLD_FILTER | ZBX_MACRO_TYPE_ALLOWED_HOSTS | ZBX_MACRO_TYPE_SCRIPT_PARAMS_FIELD | ZBX_MACRO_TYPE_QUERY_FILTER))) { zbx_uint64_t c_hostid, c_itemid; const char *host, *name; const zbx_dc_interface_t *c_interface; if (NULL != history_data_item) { c_hostid = history_data_item->host.hostid; c_itemid = history_data_item->itemid; host = history_data_item->host.host; name = history_data_item->host.name; c_interface = &history_data_item->interface; } else { c_hostid = dc_item->host.hostid; c_itemid = dc_item->itemid; host = dc_item->host.host; name = dc_item->host.name; c_interface = &dc_item->interface; } if ((ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type)) && 0 == (ZBX_MACRO_TYPE_QUERY_FILTER & macro_type)) { zbx_dc_get_user_macro(um_handle, m, &c_hostid, 1, &replace_to); pos = token.loc.r; } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { replace_to = zbx_strdup(replace_to, host); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { replace_to = zbx_strdup(replace_to, name); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { if (INTERFACE_TYPE_UNKNOWN != c_interface->type) { if ('\0' != *c_interface->ip_orig && FAIL == zbx_is_ip(c_interface->ip_orig)) { ret = FAIL; } else replace_to = zbx_strdup(replace_to, c_interface->ip_orig); } else { ret = expr_dc_get_interface_value(c_hostid, c_itemid, &replace_to, ZBX_REQUEST_HOST_IP); } } else if (0 == strcmp(m, MVAR_HOST_DNS)) { if (INTERFACE_TYPE_UNKNOWN != c_interface->type) { if ('\0' != *c_interface->dns_orig && FAIL == zbx_is_ip(c_interface->dns_orig) && FAIL == zbx_validate_hostname(c_interface->dns_orig)) { ret = FAIL; } else replace_to = zbx_strdup(replace_to, c_interface->dns_orig); } else { ret = expr_dc_get_interface_value(c_hostid, c_itemid, &replace_to, ZBX_REQUEST_HOST_DNS); } } else if (0 == strcmp(m, MVAR_HOST_CONN)) { if (INTERFACE_TYPE_UNKNOWN != c_interface->type) { if (FAIL == zbx_is_ip(c_interface->addr) && FAIL == zbx_validate_hostname(c_interface->addr)) { ret = FAIL; } else replace_to = zbx_strdup(replace_to, c_interface->addr); } else { ret = expr_dc_get_interface_value(c_hostid, c_itemid, &replace_to, ZBX_REQUEST_HOST_CONN); } } else if (0 != (macro_type & ZBX_MACRO_TYPE_SCRIPT_PARAMS_FIELD)) { if (0 == strcmp(m, MVAR_ITEM_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, dc_item->itemid); } else if (0 == strcmp(m, MVAR_ITEM_KEY)) { replace_to = zbx_strdup(replace_to, dc_item->key); } else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG)) { replace_to = zbx_strdup(replace_to, dc_item->key_orig); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY))) { ret = expr_dc_get_host_inventory_by_itemid(m, dc_item->itemid, &replace_to); } } } else if (0 != (macro_type & (ZBX_MACRO_TYPE_COMMON | ZBX_MACRO_TYPE_SNMP_OID))) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (NULL != hostid) zbx_dc_get_user_macro(um_handle, m, hostid, 1, &replace_to); else zbx_dc_get_user_macro(um_handle, m, NULL, 0, &replace_to); pos = token.loc.r; } } else if (0 == indexed_macro && 0 != (macro_type & ZBX_MACRO_TYPE_SCRIPT)) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) replace_to = zbx_strdup(replace_to, dc_host->host); else if (0 == strcmp(m, MVAR_HOST_NAME)) replace_to = zbx_strdup(replace_to, dc_host->name); else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { ret = expr_dc_get_interface_value(dc_host->hostid, 0, &replace_to, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_dc_get_interface_value(dc_host->hostid, 0, &replace_to, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_dc_get_interface_value(dc_host->hostid, 0, &replace_to, ZBX_REQUEST_HOST_CONN); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY))) { ret = expr_dc_get_host_inventory_by_hostid(m, dc_host->hostid, &replace_to); } else if (NULL != userid) { if (0 == strcmp(m, MVAR_USER_USERNAME) || 0 == strcmp(m, MVAR_USER_NAME) || 0 == strcmp(m, MVAR_USER_SURNAME) || 0 == strcmp(m, MVAR_USER_FULLNAME) || 0 == strcmp(m, MVAR_USER_ALIAS)) { resolve_user_macros(*userid, m, &user_username, &user_name, &user_surname, &user_names_found, &replace_to); } } } else if (0 == indexed_macro && 0 != (macro_type & ZBX_MACRO_TYPE_HTTPTEST_FIELD)) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) replace_to = zbx_strdup(replace_to, dc_host->host); else if (0 == strcmp(m, MVAR_HOST_NAME)) replace_to = zbx_strdup(replace_to, dc_host->name); else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { if (SUCCEED == (ret = zbx_dc_config_get_interface(&interface, dc_host->hostid, 0))) replace_to = zbx_strdup(replace_to, interface.ip_orig); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { if (SUCCEED == (ret = zbx_dc_config_get_interface(&interface, dc_host->hostid, 0))) replace_to = zbx_strdup(replace_to, interface.dns_orig); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { if (SUCCEED == (ret = zbx_dc_config_get_interface(&interface, dc_host->hostid, 0))) replace_to = zbx_strdup(replace_to, interface.addr); } } else if (0 == indexed_macro && (0 != (macro_type & (ZBX_MACRO_TYPE_HTTP_RAW | ZBX_MACRO_TYPE_HTTP_JSON | ZBX_MACRO_TYPE_HTTP_XML)))) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { zbx_dc_get_user_macro(um_handle, m, &dc_host->hostid, 1, &replace_to); pos = token.loc.r; } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { replace_to = zbx_strdup(replace_to, dc_host->host); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { replace_to = zbx_strdup(replace_to, dc_host->name); } else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { if (SUCCEED == (ret = zbx_dc_config_get_interface(&interface, dc_host->hostid, 0))) replace_to = zbx_strdup(replace_to, interface.ip_orig); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { if (SUCCEED == (ret = zbx_dc_config_get_interface(&interface, dc_host->hostid, 0))) replace_to = zbx_strdup(replace_to, interface.dns_orig); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { if (SUCCEED == (ret = zbx_dc_config_get_interface(&interface, dc_host->hostid, 0))) replace_to = zbx_strdup(replace_to, interface.addr); } else if (0 == strcmp(m, MVAR_ITEM_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, dc_item->itemid); } else if (0 == strcmp(m, MVAR_ITEM_KEY)) { replace_to = zbx_strdup(replace_to, dc_item->key); } else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG)) { replace_to = zbx_strdup(replace_to, dc_item->key_orig); } } else if (0 == indexed_macro && 0 != (macro_type & ZBX_MACRO_TYPE_ALERT_EMAIL) && (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type))) { if ((EVENT_SOURCE_INTERNAL == event->source && EVENT_OBJECT_TRIGGER == event->object) || EVENT_SOURCE_TRIGGERS == event->source) { if (NULL != event->trigger.expression && NULL != event->trigger.recovery_expression && SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids)) { zbx_dc_get_user_macro(um_handle, m, phostids->values, phostids->values_num, &replace_to); } } else if (EVENT_SOURCE_INTERNAL == event->source && (EVENT_OBJECT_ITEM == event->object || EVENT_OBJECT_LLDRULE == event->object)) { cache_item_hostid(&hostids, event->objectid); zbx_dc_get_user_macro(um_handle, m, hostids.values, hostids.values_num, &replace_to); } else zbx_dc_get_user_macro(um_handle, m, NULL, 0, &replace_to); pos = token.loc.r; } else if (0 == indexed_macro && 0 != (macro_type & ZBX_MACRO_TYPE_JMX_ENDPOINT)) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { zbx_dc_get_user_macro(um_handle, m, &dc_item->host.hostid, 1, &replace_to); pos = token.loc.r; } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) replace_to = zbx_strdup(replace_to, dc_item->host.host); else if (0 == strcmp(m, MVAR_HOST_NAME)) replace_to = zbx_strdup(replace_to, dc_item->host.name); else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS)) { if (INTERFACE_TYPE_UNKNOWN != dc_item->interface.type) { replace_to = zbx_strdup(replace_to, dc_item->interface.ip_orig); } else { ret = expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_IP); } } else if (0 == strcmp(m, MVAR_HOST_DNS)) { if (INTERFACE_TYPE_UNKNOWN != dc_item->interface.type) { replace_to = zbx_strdup(replace_to, dc_item->interface.dns_orig); } else { ret = expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_DNS); } } else if (0 == strcmp(m, MVAR_HOST_CONN)) { if (INTERFACE_TYPE_UNKNOWN != dc_item->interface.type) { replace_to = zbx_strdup(replace_to, dc_item->interface.addr); } else { ret = expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_CONN); } } else if (0 == strcmp(m, MVAR_HOST_PORT)) { if (INTERFACE_TYPE_UNKNOWN != dc_item->interface.type) { replace_to = zbx_dsprintf(replace_to, "%u", dc_item->interface.port); } else { ret = expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_PORT); } } } else if (0 != (macro_type & ZBX_MACRO_TYPE_TRIGGER_TAG)) { if (EVENT_SOURCE_TRIGGERS == event->source || EVENT_SOURCE_INTERNAL == event->source) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { if (SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids)) { zbx_dc_get_user_macro(um_handle, m, phostids->values, phostids->values_num, &replace_to); } pos = token.loc.r; } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY))) { ret = expr_dc_get_host_inventory(m, &event->trigger, &replace_to, N_functionid); } else if (0 == strcmp(m, MVAR_HOST_ID)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_IP)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { ret = expr_db_get_trigger_value(&event->trigger, &replace_to, N_functionid, ZBX_REQUEST_HOST_PORT); } if (EVENT_SOURCE_TRIGGERS == event->source) { if (0 == strcmp(m, MVAR_ITEM_LASTVALUE)) { ret = expr_db_item_lastvalue(&event->trigger, &replace_to, N_functionid, raw_value); } else if (0 == strcmp(m, MVAR_ITEM_VALUE)) { ret = expr_db_item_value(&event->trigger, &replace_to, N_functionid, event->clock, event->ns, raw_value); } else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG))) { ret = expr_get_history_log_value(m, &event->trigger, &replace_to, N_functionid, event->clock, event->ns, tz); } else if (0 == strcmp(m, MVAR_TRIGGER_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, event->objectid); } } } } else if (0 == indexed_macro && 0 != (macro_type & ZBX_MACRO_TYPE_ITEM_TAG)) { /* Using dc_item to pass itemid and hostid only, all other fields are not initialized! */ if (EVENT_SOURCE_TRIGGERS == event->source && 0 == strcmp(m, MVAR_TRIGGER_ID)) { replace_to = zbx_dsprintf(replace_to, ZBX_FS_UI64, event->objectid); } else if (EVENT_SOURCE_TRIGGERS == event->source || EVENT_SOURCE_INTERNAL == event->source) { if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_USER_FUNC_MACRO == token.type && 0 == strncmp(m, MVAR_USER_MACRO, ZBX_CONST_STRLEN(MVAR_USER_MACRO)))) { zbx_dc_get_user_macro(um_handle, m, &dc_item->host.hostid, 1, &replace_to); } else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY))) { expr_dc_get_host_inventory_by_hostid(m, dc_item->host.hostid, &replace_to); } else if (0 == strcmp(m, MVAR_HOST_ID)) { expr_dc_get_host_value(dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_ID); } else if (0 == strcmp(m, MVAR_HOST_HOST)) { expr_dc_get_host_value(dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_HOST); } else if (0 == strcmp(m, MVAR_HOST_NAME)) { expr_dc_get_host_value(dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_NAME); } else if (0 == strcmp(m, MVAR_HOST_IP)) { expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_IP); } else if (0 == strcmp(m, MVAR_HOST_DNS)) { expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_DNS); } else if (0 == strcmp(m, MVAR_HOST_CONN)) { expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_CONN); } else if (0 == strcmp(m, MVAR_HOST_PORT)) { expr_dc_get_interface_value(dc_item->host.hostid, dc_item->itemid, &replace_to, ZBX_REQUEST_HOST_PORT); } } } else if (0 == indexed_macro && 0 != (macro_type & ZBX_MACRO_TYPE_REPORT)) { if (0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } } if (0 != (macro_type & ZBX_MACRO_TYPE_HTTP_JSON) && NULL != replace_to) { zbx_json_escape(&replace_to); } if (0 != (macro_type & ZBX_MACRO_TYPE_QUERY_FILTER) && NULL != replace_to) { char *esc; esc = zbx_dyn_escape_string(replace_to, "\\"); zbx_free(replace_to); replace_to = esc; } if ((ZBX_TOKEN_FUNC_MACRO == token.type || ZBX_TOKEN_USER_FUNC_MACRO == token.type) && NULL != replace_to) { if (SUCCEED != (ret = zbx_calculate_macro_function(*data, &token.data.func_macro, &replace_to))) zbx_free(replace_to); } } if (FAIL == ret) { zabbix_log(LOG_LEVEL_DEBUG, "cannot resolve macro '%.*s'", (int)(token.loc.r - token.loc.l + 1), *data + token.loc.l); if (ZBX_TOKEN_MACRO == token.type && SUCCEED == is_strict_macro(m)) { if (NULL != error) { /* return error if strict macro resolving failed */ zbx_snprintf(error, maxerrlen, "Invalid macro '%.*s' value", (int)(token.loc.r - token.loc.l + 1), *data + token.loc.l); res = FAIL; } } replace_to = zbx_strdup(replace_to, STR_UNKNOWN_VARIABLE); } if (ZBX_TOKEN_USER_MACRO == token.type || (ZBX_TOKEN_MACRO == token.type && 0 == indexed_macro)) (*data)[token.loc.r + 1] = c; if (NULL != replace_to) { pos = token.loc.r; pos += zbx_replace_mem_dyn(data, &data_alloc, &data_len, token.loc.l, token.loc.r - token.loc.l + 1, replace_to, strlen(replace_to)); zbx_free(replace_to); } if (ZBX_TOKEN_FUNC_MACRO == token.type || ZBX_TOKEN_USER_FUNC_MACRO == token.type) zbx_free(m_ptr); pos++; } zbx_vc_flush_stats(); zbx_free(user_username); zbx_free(user_name); zbx_free(user_surname); zbx_free(expression); zbx_vector_uint64_destroy(&hostids); zbx_dc_close_user_macros(um_handle); if (NULL != cause_event) zbx_db_free_event(cause_event); if (NULL != cause_recovery_event) zbx_db_free_event(cause_recovery_event); out: zabbix_log(LOG_LEVEL_DEBUG, "End %s() data:'%s'", __func__, *data); return res; } typedef struct { zbx_uint64_t *hostid; zbx_dc_item_t *dc_item; const struct zbx_json_parse *jp_row; const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths; int macro_type; } replace_key_param_data_t; /****************************************************************************** * * * Comments: auxiliary function for substitute_key_macros(). * * * ******************************************************************************/ static int replace_key_param_cb(const char *data, int key_type, int level, int num, int quoted, void *cb_data, char **param) { replace_key_param_data_t *replace_key_param_data = (replace_key_param_data_t *)cb_data; zbx_uint64_t *hostid = replace_key_param_data->hostid; zbx_dc_item_t *dc_item = replace_key_param_data->dc_item; const struct zbx_json_parse *jp_row = replace_key_param_data->jp_row; const zbx_vector_lld_macro_path_ptr_t *lld_macros = replace_key_param_data->lld_macro_paths; int macro_type = replace_key_param_data->macro_type, ret = SUCCEED; ZBX_UNUSED(num); if (ZBX_KEY_TYPE_ITEM == key_type && 0 == level) return ret; if (NULL == strchr(data, '{')) return ret; *param = zbx_strdup(NULL, data); if (0 != level) zbx_unquote_key_param(*param); if (NULL == jp_row) substitute_simple_macros_impl(NULL, NULL, NULL, NULL, hostid, NULL, dc_item, NULL, NULL, NULL, NULL, NULL, NULL, param, macro_type, NULL, 0); else zbx_substitute_lld_macros(param, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0); if (0 != level) { if (FAIL == (ret = zbx_quote_key_param(param, quoted))) zbx_free(*param); } return ret; } /****************************************************************************** * * * Purpose: safely substitutes macros in parameters of an item key and OID. * * * * Example: key | macro | result | return * * -------------------------+--------+-------------------+--------- * * echo.sh[{$MACRO}] | a | echo.sh[a] | SUCCEED * * echo.sh[{$MACRO}] | a\ | echo.sh[a\] | SUCCEED * * echo.sh["{$MACRO}"] | a | echo.sh["a"] | SUCCEED * * echo.sh["{$MACRO}"] | a\ | undefined | FAIL * * echo.sh[{$MACRO}] | a | echo.sh[" a"] | SUCCEED * * echo.sh[{$MACRO}] | a\ | undefined | FAIL * * echo.sh["{$MACRO}"] | a | echo.sh[" a"] | SUCCEED * * echo.sh["{$MACRO}"] | a\ | undefined | FAIL * * echo.sh[{$MACRO}] | "a" | echo.sh["\"a\""] | SUCCEED * * echo.sh[{$MACRO}] | "a"\ | undefined | FAIL * * echo.sh["{$MACRO}"] | "a" | echo.sh["\"a\""] | SUCCEED * * echo.sh["{$MACRO}"] | "a"\ | undefined | FAIL * * echo.sh[{$MACRO}] | a,b | echo.sh["a,b"] | SUCCEED * * echo.sh[{$MACRO}] | a,b\ | undefined | FAIL * * echo.sh["{$MACRO}"] | a,b | echo.sh["a,b"] | SUCCEED * * echo.sh["{$MACRO}"] | a,b\ | undefined | FAIL * * echo.sh[{$MACRO}] | a] | echo.sh["a]"] | SUCCEED * * echo.sh[{$MACRO}] | a]\ | undefined | FAIL * * echo.sh["{$MACRO}"] | a] | echo.sh["a]"] | SUCCEED * * echo.sh["{$MACRO}"] | a]\ | undefined | FAIL * * echo.sh[{$MACRO}] | [a | echo.sh["a]"] | SUCCEED * * echo.sh[{$MACRO}] | [a\ | undefined | FAIL * * echo.sh["{$MACRO}"] | [a | echo.sh["[a"] | SUCCEED * * echo.sh["{$MACRO}"] | [a\ | undefined | FAIL * * ifInOctets.{#SNMPINDEX} | 1 | ifInOctets.1 | SUCCEED * * * ******************************************************************************/ int substitute_key_macros_impl(char **data, zbx_uint64_t *hostid, zbx_dc_item_t *dc_item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, int macro_type, char *error, size_t maxerrlen) { replace_key_param_data_t replace_key_param_data; int key_type, ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() data:'%s'", __func__, *data); replace_key_param_data.hostid = hostid; replace_key_param_data.dc_item = dc_item; replace_key_param_data.jp_row = jp_row; replace_key_param_data.lld_macro_paths = lld_macro_paths; replace_key_param_data.macro_type = macro_type; switch (macro_type) { case ZBX_MACRO_TYPE_ITEM_KEY: key_type = ZBX_KEY_TYPE_ITEM; break; case ZBX_MACRO_TYPE_SNMP_OID: key_type = ZBX_KEY_TYPE_OID; break; default: THIS_SHOULD_NEVER_HAPPEN; exit(EXIT_FAILURE); } ret = zbx_replace_key_params_dyn(data, key_type, replace_key_param_cb, &replace_key_param_data, error, maxerrlen); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s data:'%s'", __func__, zbx_result_string(ret), *data); return ret; } #ifdef HAVE_LIBXML2 /****************************************************************************** * * * Comments: auxiliary function for substitute_macros_xml(). * * * ******************************************************************************/ static void substitute_macros_in_xml_elements(const zbx_dc_item_t *item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, xmlNode *node) { xmlChar *value; xmlAttr *attr; char *value_tmp; for (;NULL != node; node = node->next) { switch (node->type) { case XML_TEXT_NODE: if (NULL == (value = xmlNodeGetContent(node))) break; value_tmp = zbx_strdup(NULL, (const char *)value); if (NULL != item) { substitute_simple_macros_impl(NULL, NULL, NULL, NULL, NULL, &item->host, item, NULL, NULL, NULL, NULL, NULL, NULL, &value_tmp, ZBX_MACRO_TYPE_HTTP_XML, NULL, 0); } else { zbx_substitute_lld_macros(&value_tmp, jp_row, lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); } xmlNodeSetContent(node, NULL); xmlNodeAddContent(node, (xmlChar *)value_tmp); zbx_free(value_tmp); xmlFree(value); break; case XML_CDATA_SECTION_NODE: if (NULL == (value = xmlNodeGetContent(node))) break; value_tmp = zbx_strdup(NULL, (const char *)value); if (NULL != item) { substitute_simple_macros_impl(NULL, NULL, NULL, NULL, NULL, &item->host, item, NULL, NULL, NULL, NULL, NULL, NULL, &value_tmp, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); } else { zbx_substitute_lld_macros(&value_tmp, jp_row, lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); } xmlNodeSetContent(node, NULL); xmlNodeAddContent(node, (xmlChar *)value_tmp); zbx_free(value_tmp); xmlFree(value); break; case XML_ELEMENT_NODE: for (attr = node->properties; NULL != attr; attr = attr->next) { if (NULL == attr->name || NULL == (value = xmlGetProp(node, attr->name))) continue; value_tmp = zbx_strdup(NULL, (const char *)value); if (NULL != item) { substitute_simple_macros_impl(NULL, NULL, NULL, NULL, NULL, &item->host, item, NULL, NULL, NULL, NULL, NULL, NULL, &value_tmp, ZBX_MACRO_TYPE_HTTP_XML, NULL, 0); } else { zbx_substitute_lld_macros(&value_tmp, jp_row, lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); } xmlSetProp(node, attr->name, (xmlChar *)value_tmp); zbx_free(value_tmp); xmlFree(value); } break; default: break; } substitute_macros_in_xml_elements(item, jp_row, lld_macro_paths, node->children); } } #endif /****************************************************************************** * * * Purpose: Substitutes simple or LLD macros in XML text nodes, attributes of * * a node or in CDATA section, validates XML. * * * * Parameters: data - [IN/OUT] pointer to buffer that contains xml * * item - [IN] item for simple macro substitution * * jp_row - [IN] discovery data for lld macro * * substitution * * lld_macro_paths - [IN] lld macro paths * * error - [OUT] reason for xml parsing failure * * maxerrlen - [IN] size of error buffer * * * * Return value: SUCCEED or FAIL if XML validation has failed. * * * ******************************************************************************/ static int substitute_macros_xml_impl(char **data, const zbx_dc_item_t *item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, char *error, int maxerrlen) { #ifndef HAVE_LIBXML2 ZBX_UNUSED(data); ZBX_UNUSED(item); ZBX_UNUSED(jp_row); ZBX_UNUSED(lld_macro_paths); zbx_snprintf(error, maxerrlen, "Support for XML was not compiled in"); return FAIL; #else xmlDoc *doc; xmlNode *root_element; xmlChar *mem; int size, ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (FAIL == zbx_open_xml(*data, 0, maxerrlen, (void **)&doc, (void **)&root_element, &error)) { if (NULL == doc) goto exit; if (NULL == root_element) goto clean; } substitute_macros_in_xml_elements(item, jp_row, lld_macro_paths, root_element); xmlDocDumpMemory(doc, &mem, &size); if (FAIL == zbx_check_xml_memory((char *)mem, maxerrlen, &error)) goto clean; zbx_free(*data); *data = zbx_malloc(NULL, size + 1); memcpy(*data, (const char *)mem, size + 1); xmlFree(mem); ret = SUCCEED; clean: xmlFreeDoc(doc); exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; #endif } /****************************************************************************** * * * Purpose: substitute_simple_macros with masked secret macros * * (default setting). * * * ******************************************************************************/ int zbx_substitute_simple_macros(const zbx_uint64_t *actionid, const zbx_db_event *event, const zbx_db_event *r_event, const zbx_uint64_t *userid, const zbx_uint64_t *hostid, const zbx_dc_host_t *dc_host, const zbx_dc_item_t *dc_item, const zbx_db_alert *alert, const zbx_db_acknowledge *ack, const zbx_service_alarm_t *service_alarm, const zbx_db_service *service, const char *tz, char **data, int macro_type, char *error, int maxerrlen) { return substitute_simple_macros_impl(actionid, event, r_event, userid, hostid, dc_host, dc_item, alert, ack, service_alarm, service, tz, NULL, data, macro_type, error, maxerrlen); } void zbx_substitute_simple_macros_allowed_hosts(zbx_history_recv_item_t *item, char **allowed_peers) { substitute_simple_macros_impl(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, item, allowed_peers, ZBX_MACRO_TYPE_ALLOWED_HOSTS, NULL, 0); } /****************************************************************************** * * * Purpose: substitute_simple_macros with unmasked secret macros. * * * ******************************************************************************/ int zbx_substitute_simple_macros_unmasked(const zbx_uint64_t *actionid, const zbx_db_event *event, const zbx_db_event *r_event, const zbx_uint64_t *userid, const zbx_uint64_t *hostid, const zbx_dc_host_t *dc_host, const zbx_dc_item_t *dc_item, const zbx_db_alert *alert, const zbx_db_acknowledge *ack, const zbx_service_alarm_t *service_alarm, const zbx_db_service *service, const char *tz, char **data, int macro_type, char *error, int maxerrlen) { int ret; zbx_dc_um_handle_t *um_handle; um_handle = zbx_dc_open_user_macros_secure(); ret = substitute_simple_macros_impl(actionid, event, r_event, userid, hostid, dc_host, dc_item, alert, ack, service_alarm, service, tz, NULL, data, macro_type, error, maxerrlen); zbx_dc_close_user_macros(um_handle); return ret; } /****************************************************************************** * * * Purpose: substitute_macros_xml with masked secret macros. * * * ******************************************************************************/ int zbx_substitute_macros_xml(char **data, const zbx_dc_item_t *item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, char *error, int maxerrlen) { return substitute_macros_xml_impl(data, item, jp_row, lld_macro_paths, error, maxerrlen); } /****************************************************************************** * * * Purpose: substitute_macros_xml with unmasked secret macros. * * * ******************************************************************************/ int zbx_substitute_macros_xml_unmasked(char **data, const zbx_dc_item_t *item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, char *error, int maxerrlen) { int ret; zbx_dc_um_handle_t *um_handle; um_handle = zbx_dc_open_user_macros_secure(); ret = substitute_macros_xml_impl(data, item, jp_row, lld_macro_paths, error, maxerrlen); zbx_dc_close_user_macros(um_handle); return ret; } /****************************************************************************** * * * Purpose: substitute_key_macros with masked secret macros. * * * ******************************************************************************/ int zbx_substitute_key_macros(char **data, zbx_uint64_t *hostid, zbx_dc_item_t *dc_item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, int macro_type, char *error, size_t maxerrlen) { return substitute_key_macros_impl(data, hostid, dc_item, jp_row, lld_macro_paths, macro_type, error, maxerrlen); } /****************************************************************************** * * * Purpose: substitute_key_macros with unmasked secret macros. * * * ******************************************************************************/ int zbx_substitute_key_macros_unmasked(char **data, zbx_uint64_t *hostid, zbx_dc_item_t *dc_item, const struct zbx_json_parse *jp_row, const zbx_vector_lld_macro_path_ptr_t *lld_macro_paths, int macro_type, char *error, size_t maxerrlen) { int ret; zbx_dc_um_handle_t *um_handle; um_handle = zbx_dc_open_user_macros_secure(); ret = substitute_key_macros_impl(data, hostid, dc_item, jp_row, lld_macro_paths, macro_type, error, maxerrlen); zbx_dc_close_user_macros(um_handle); return ret; } /****************************************************************************** * * * Purpose: extract index from valid indexed host or item key macro. * * * * Return value: the index or -1 if it was not valid indexed host or item key * * macro. * * * ******************************************************************************/ int zbx_expr_macro_index(const char *macro) { zbx_strloc_t loc; int func_num; loc.l = 0; loc.r = strlen(macro) - 1; if (NULL != macro_in_list(macro, loc, expr_macros, &func_num)) return func_num; return -1; }