✏️ 正在编辑: CTextTriggerConstructor.php
路径:
/usr/share/zabbix/include/classes/triggers/CTextTriggerConstructor.php
提示:
您可以编辑任何文件(包括二进制文件),但请注意不当修改可能导致文件损坏。
<?php /* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ /** * A class for implementing conversions used by the trigger wizard. */ class CTextTriggerConstructor { const EXPRESSION_TYPE_MATCH = 0; const EXPRESSION_TYPE_NO_MATCH = 1; /** * Parser used for parsing trigger expressions. * * @var CTriggerExpression */ protected $triggerExpression; /** * @param CTriggerExpression $triggerExpression trigger expression parser */ public function __construct(CTriggerExpression $triggerExpression) { $this->triggerExpression = $triggerExpression; } /** * Create a trigger expression from the given expression parts. * * Most of this function was left unchanged to preserve the current behavior of the constructor. * Feel free to rewrite and correct it if necessary. * * @param string $host host name * @param string $itemKey item key * @param array $expressions array of expression parts * @param string $expressions[]['value'] expression string * @param int $expressions[]['type'] whether the string should match the expression; supported values: * self::EXPRESSION_TYPE_MATCH and self::EXPRESSION_TYPE_NO_MATCH * * @return bool|string */ public function getExpressionFromParts($host, $itemKey, array $expressions) { $result = ''; $prefix = $host.':'.$itemKey.'.'; if (empty($expressions)) { error(_('Expression cannot be empty')); return false; } // regexp used to split an expressions into tokens $ZBX_PREG_EXPESSION_FUNC_FORMAT = '^(['.ZBX_PREG_PRINT.']*) (and|or) (not )?(-)? ?[(]*(([a-zA-Z_.\$]{6,7})(\\((['.ZBX_PREG_PRINT.']+?){0,1}\\)))(['.ZBX_PREG_PRINT.']*)$'; $functions = ['regexp' => 1, 'iregexp' => 1]; $expr_array = []; $cexpor = 0; $startpos = -1; foreach ($expressions as $expression) { if ($expression['type'] == self::EXPRESSION_TYPE_MATCH) { if (!empty($result)) { $result.=' or '; } if ($cexpor == 0) { $startpos = mb_strlen($result); } $cexpor++; $eq_global = '<>0'; } else { if (($cexpor > 1) & ($startpos >= 0)) { $head = mb_substr($result, 0, $startpos); $tail = mb_substr($result, $startpos); $result = $head.'('.$tail.')'; } $cexpor = 0; $eq_global = '=0'; if (!empty($result)) { $result.=' and '; } } $expr = ' and '.$expression['value']; // strip extra spaces around "and" and "or" operators $expr = preg_replace('/\s+(and|or)\s+/U', ' $1 ', $expr); $expr_array = []; $sub_expr_count=0; $sub_expr = ''; $multi = preg_match('/.+(and|or).+/', $expr); // split an expression into separate tokens // start from the first part of the expression, then move to the next one while (preg_match('/'.$ZBX_PREG_EXPESSION_FUNC_FORMAT.'/i', $expr, $arr)) { $arr[6] = strtolower($arr[6]); if (!isset($functions[$arr[6]])) { error(_('Incorrect function is used').'. ['.$expression['value'].']'); return false; } $expr_array[$sub_expr_count]['eq'] = trim($arr[2]); $expr_array[$sub_expr_count]['not'] = trim($arr[3]); $expr_array[$sub_expr_count]['minus'] = trim($arr[4]); $expr_array[$sub_expr_count]['regexp'] = $arr[6].$arr[7]; $sub_expr_count++; $expr = $arr[1]; } if (empty($expr_array)) { error(_('Incorrect trigger expression').'. ['.$expression['value'].']'); return false; } $expr_array[$sub_expr_count-1]['eq'] = ''; $sub_eq = ''; if ($multi > 0) { $sub_eq = $eq_global; } foreach ($expr_array as $id => $expr) { $eq = ($expr['eq'] === '') ? '' : ' '.$expr['eq'].' '; $not = ($expr['not'] === '') ? '' : $expr['not'].' '; if ($multi > 0) { $sub_expr = $eq.'('.$not.$expr['minus'].'{'.$prefix.$expr['regexp'].'})'.$sub_eq.$sub_expr; } else { $sub_expr = $eq.$expr['eq'].$not.$expr['minus'].'{'.$prefix.$expr['regexp'].'}'.$sub_eq.$sub_expr; } } if ($multi > 0) { $result .= '('.$sub_expr.')'; } else { $result .= '(('.$sub_expr.')'.$eq_global.')'; } } if (($cexpor > 1) & ($startpos >= 0)) { $head = mb_substr($result, 0, $startpos); $tail = mb_substr($result, $startpos); $result = $head.'('.$tail.')'; } return $result; } /** * Break a trigger expression generated by the constructor. * * To be successfully parsed, each item function macro must be wrapped in additional parentheses, for example, * (({item.item.regex(param)})=0) * * Most of this function was left unchanged to preserve the current behavior of the constructor. * Feel free to rewrite and correct it if necessary. * * @param string $expression trigger expression * * @return array an array of expression parts, see self::getExpressionFromParts() for the structure of the part * array */ public function getPartsFromExpression($expression) { // strip extra parentheses $expression = preg_replace('/\(\(\((.+?)\)\) and/i', '(($1) and', $expression); $expression = preg_replace('/\(\(\((.+?)\)\)$/i', '(($1)', $expression); $parseResult = $this->triggerExpression->parse($expression); $expressions = []; $splitTokens = $this->splitTokensByFirstLevel($parseResult->getTokens()); foreach($splitTokens as $key => $tokens) { $expr = []; // replace whole function macros with their functions foreach ($tokens as $token) { $value = $token['value']; switch ($token['type']) { case CTriggerExprParserResult::TOKEN_TYPE_FUNCTION_MACRO: $value = $token['data']['function']; break; case CTriggerExprParserResult::TOKEN_TYPE_OPERATOR: if ($token['value'] === 'and' || $token['value'] === 'or' || $token['value'] === 'not') { $value = ' '.$token['value'].' '; } break; } $expr[] = $value; } $expr = implode($expr); // trim surrounding parentheses $expr = preg_replace('/^\((.*)\)$/u', '$1', $expr); // trim parentheses around item function macros $value = preg_replace('/\((.*)\)(=|<>)0/U', '$1', $expr); // trim surrounding parentheses $value = preg_replace('/^\((.*)\)$/u', '$1', $value); $expressions[$key]['value'] = trim($value); $expressions[$key]['type'] = (strpos($expr, '<>0', mb_strlen($expr) - 4) === false) ? self::EXPRESSION_TYPE_NO_MATCH : self::EXPRESSION_TYPE_MATCH; } return $expressions; } /** * Split the trigger expression tokens into separate arrays. * * The tokens are split at the first occurrence of the "and" or "or" operators with respect to parentheses. * * @param array $tokens an array of tokens from the CTriggerExprParserResult * * @return array an array of token arrays grouped by expression */ protected function splitTokensByFirstLevel(array $tokens) { $expressions = []; $currentExpression = []; $level = 0; foreach ($tokens as $token) { switch ($token['type']) { case CTriggerExprParserResult::TOKEN_TYPE_OPERATOR: // look for an "or" or "and" operator on the top parentheses level // if such an expression is found, save all of the tokens before it as a separate expression if ($level == 0 && ($token['value'] === 'or' || $token['value'] === 'and')) { $expressions[] = $currentExpression; $currentExpression = []; // continue to the next token continue 2; } break; case CTriggerExprParserResult::TOKEN_TYPE_OPEN_BRACE: $level++; break; case CTriggerExprParserResult::TOKEN_TYPE_CLOSE_BRACE: $level--; break; } $currentExpression[] = $token; } $expressions[] = $currentExpression; return $expressions; } }
💾 保存文件
← 返回文件管理器