public function checkFunction($expression) { try { if (!isset($this->allowed['functions'][$expression['functionName']])) { throw new Exception('Unknown function.'); } if (!preg_match('/^' . ZBX_PREG_FUNCTION_FORMAT . '$/u', $expression['function'])) { throw new Exception('Incorrect function format.'); } if (is_null($this->allowed['functions'][$expression['functionName']]['args'])) { if (!zbx_empty($expression['functionParamList'][0])) { throw new Exception('Function does not expect parameters.'); } else { return true; } } if (count($this->allowed['functions'][$expression['functionName']]['args']) < count($expression['functionParamList'])) { throw new Exception('Function supports ' . count($this->allowed['functions'][$expression['functionName']]['args']) . ' parameters.'); } foreach ($this->allowed['functions'][$expression['functionName']]['args'] as $anum => $arg) { // mandatory check if (isset($arg['mandat']) && $arg['mandat'] && !isset($expression['functionParamList'][$anum])) { throw new Exception('Mandatory parameter is missing.'); } // type check if (isset($arg['type']) && isset($expression['functionParamList'][$anum])) { $userMacro = preg_match('/^' . ZBX_PREG_EXPRESSION_USER_MACROS . '$/', $expression['functionParamList'][$anum]); if ($arg['type'] == 'str' && !is_string($expression['functionParamList'][$anum]) && !$userMacro) { throw new Exception('Parameter of type string or user macro expected, "' . $expression['functionParamList'][$anum] . '" given.'); } if ($arg['type'] == 'sec' && validate_sec($expression['functionParamList'][$anum]) != 0 && !$userMacro) { throw new Exception('Parameter sec or user macro expected, "' . $expression['functionParamList'][$anum] . '" given.'); } if ($arg['type'] == 'sec_num' && validate_secnum($expression['functionParamList'][$anum]) != 0 && !$userMacro) { throw new Exception('Parameter sec or #num or user macro expected, "' . $expression['functionParamList'][$anum] . '" given.'); } if ($arg['type'] == 'num' && !is_numeric($expression['functionParamList'][$anum]) && !$userMacro) { throw new Exception('Parameter num or user macro expected, "' . $expression['functionParamList'][$anum] . '" given.'); } } } } catch (Exception $e) { $error = 'Incorrect trigger function "' . $expression['function'] . '" provided in expression. '; $error .= $e->getMessage(); throw new Exception($error); } }
function validate_expression($expression) { global $ZBX_TR_EXPR_SIMPLE_MACROS, $ZBX_TR_EXPR_REPLACE_TO, $ZBX_TR_EXPR_ALLOWED_FUNCTIONS; if (empty($expression)) { error(S_EXPRESSION_CANNOT_BE_EMPTY); return false; } $expr = $expression; $h_status = array(); $item_count = 0; // Replace all {server:key.function(param)} and {MACRO} with '$ZBX_TR_EXPR_REPLACE_TO' // while(ereg(ZBX_EREG_EXPRESSION_TOKEN_FORMAT, $expr, $arr)){ while (preg_match('/' . ZBX_PREG_EXPRESSION_TOKEN_FORMAT . '/u', $expr, $arr)) { if ($arr[ZBX_EXPRESSION_MACRO_ID] && !isset($ZBX_TR_EXPR_SIMPLE_MACROS[$arr[ZBX_EXPRESSION_MACRO_ID]])) { error('Unknown macro [' . $arr[ZBX_EXPRESSION_MACRO_ID] . ']'); return false; } else { if (!$arr[ZBX_EXPRESSION_MACRO_ID]) { $host =& $arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_HOST_ID]; $key =& $arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_KEY_ID]; $function =& $arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_FUNCTION_NAME_ID]; $parameter =& $arr[ZBX_EXPRESSION_SIMPLE_EXPRESSION_ID + ZBX_SIMPLE_EXPRESSION_FUNCTION_PARAM_ID]; // Check host $sql = 'SELECT COUNT(*) as cnt,min(status) as status,min(hostid) as hostid ' . ' FROM hosts h ' . ' WHERE h.host=' . zbx_dbstr($host) . ' AND ' . DBin_node('h.hostid', false) . ' AND status IN (' . HOST_STATUS_MONITORED . ',' . HOST_STATUS_NOT_MONITORED . ',' . HOST_STATUS_TEMPLATE . ') '; $row = DBfetch(DBselect($sql)); if ($row['cnt'] == 0) { error(S_NO_SUCH_HOST . ' (' . $host . ')'); return false; } else { if ($row['cnt'] != 1) { error(S_TOO_MANY_HOSTS . ' (' . $host . ')'); return false; } } $h_status[$row['status']][$row['hostid']] = $row['cnt']; // Check key $sql = 'SELECT i.itemid,i.value_type ' . ' FROM hosts h,items i ' . ' WHERE h.host=' . zbx_dbstr($host) . ' AND i.key_=' . zbx_dbstr($key) . ' AND h.hostid=i.hostid ' . ' AND ' . DBin_node('h.hostid', false); if (!($item = DBfetch(DBselect($sql)))) { error(S_NO_SUCH_MONITORED_PARAMETER . ' (' . $key . ') ' . S_FOR_HOST_SMALL . ' (' . $host . ')'); return false; } // Check function if (!isset($ZBX_TR_EXPR_ALLOWED_FUNCTIONS[$function])) { error(S_UNKNOWN_FUNCTION . SPACE . '[' . $function . ']'); return false; } $fnc_valid =& $ZBX_TR_EXPR_ALLOWED_FUNCTIONS[$function]; if (is_array($fnc_valid['item_types']) && !uint_in_array($item['value_type'], $fnc_valid['item_types'])) { $allowed_types = array(); foreach ($fnc_valid['item_types'] as $type) { $allowed_types[] = item_value_type2str($type); } info(S_FUNCTION . ' (' . $function . ') ' . S_AVAILABLE_ONLY_FOR_ITEMS_WITH_VALUE_TYPES_SMALL . ' [' . implode(',', $allowed_types) . ']'); error(S_INCORRECT_VALUE_TYPE . ' [' . item_value_type2str($item['value_type']) . '] ' . S_FOR_FUNCTION_SMALL . ' (' . $function . ') ' . S_OF_KEY_SMALL . ' (' . $host . ':' . $key . ')'); return false; } if (!is_null($fnc_valid['args'])) { $parameter = zbx_get_params($parameter); if (!is_array($fnc_valid['args'])) { $fnc_valid['args'] = array($fnc_valid['args']); } foreach ($fnc_valid['args'] as $pid => $params) { if (!isset($parameter[$pid])) { if (!isset($params['mandat'])) { continue; } else { error(S_MISSING_MANDATORY_PARAMETER_FOR_FUNCTION . ' (' . $function . ')'); return false; } } if (preg_match('/^' . ZBX_PREG_EXPRESSION_USER_MACROS . '$/', $parameter[$pid])) { continue; } if ('sec' == $params['type'] && validate_sec($parameter[$pid]) != 0) { error('[' . $parameter[$pid] . '] ' . S_NOT_FLOAT_OR_MACRO_FOR_FUNCTION_SMALL . ' (' . $function . ')'); return false; } if ('sec_num' == $params['type'] && validate_secnum($parameter[$pid]) != 0) { error('[' . $parameter[$pid] . '] ' . S_NOT_FLOAT_OR_MACRO_OR_COUNTER_FOR_FUNCTION_SMALL . ' (' . $function . ')'); return false; } } } $item_count++; } } $expr = $arr[ZBX_EXPRESSION_LEFT_ID] . $ZBX_TR_EXPR_REPLACE_TO . $arr[ZBX_EXPRESSION_RIGHT_ID]; } if ($item_count == 0) { error(S_ITEM_KEY_MUST_BE_USED_IN_TRIGGER_EXPRESSION); return false; } if (isset($h_status[HOST_STATUS_TEMPLATE]) && (count($h_status) > 1 || count($h_status[HOST_STATUS_TEMPLATE]) > 1)) { error(S_INCORRECT_TRIGGER_EXPRESSION . '.' . SPACE . S_YOU_CAN_NOT_USE_TEMPLATE_HOSTS_MIXED_EXPR); return false; } // Replace all calculations and numbers with '$ZBX_TR_EXPR_REPLACE_TO' $expt_number = '(' . $ZBX_TR_EXPR_REPLACE_TO . '|' . ZBX_PREG_NUMBER . '|' . ZBX_PREG_EXPRESSION_USER_MACROS . ')'; $expt_term = '((\\(' . $expt_number . '\\))|(' . $expt_number . '))'; $expr_format = '((' . $expt_term . ZBX_PREG_SPACES . ZBX_PREG_SIGN . ZBX_PREG_SPACES . $expt_term . ')|(\\(' . $expt_term . '\\)))'; $expr_full_format = '((\\(' . $expr_format . '\\))|(' . $expr_format . '))'; while ($res = preg_match('/' . $expr_full_format . '(.*)$/u', $expr, $arr)) { $expr = substr($expr, 0, zbx_strpos($expr, $arr[1])) . $ZBX_TR_EXPR_REPLACE_TO . $arr[82]; } /* OLD EREG //Replace all calculations and numbers with '$ZBX_TR_EXPR_REPLACE_TO' $expt_number = '('.$ZBX_TR_EXPR_REPLACE_TO.'|'.ZBX_EREG_NUMBER.'|'.ZBX_EREG_EXPRESSION_USER_MACROS.')'; $expt_term = '((\('.$expt_number.'\))|('.$expt_number.'))'; $expr_format = '(('.$expt_term.ZBX_EREG_SPACES.ZBX_EREG_SIGN.ZBX_EREG_SPACES.$expt_term.')|(\('.$expt_term.'\)))'; $expr_full_format = '((\('.$expr_format.'\))|('.$expr_format.'))'; while($res = ereg($expr_full_format.'([[:print:]]*)$', $expr, $arr)){ $expr = substr($expr, 0, zbx_strpos($expr, $arr[1])).$ZBX_TR_EXPR_REPLACE_TO.$arr[58]; } */ if ($ZBX_TR_EXPR_REPLACE_TO != $expr) { error(S_INCORRECT_TRIGGER_EXPRESSION . '. [' . str_replace($ZBX_TR_EXPR_REPLACE_TO, ' ... ', $expr) . ']'); return false; } return true; }