You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
5.3 KiB

<?php
/*
** Zabbix
** Copyright (C) 2001-2023 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.
**/
/**
* Class for regular expressions and Zabbix global expressions.
* Any string that begins with '@' is treated as Zabbix expression.
* Data from Zabbix expressions is taken from DB, and cached in static variable.
*
* @throws Exception
*/
class CGlobalRegexp {
const ERROR_REGEXP_NOT_EXISTS = 1;
/**
* Determine if it's Zabbix expression.
*
* @var bool
*/
protected $isZabbixRegexp;
/**
* If we create simple regular expression this contains itself as a string,
* if we create Zabbix expression this contains array of expressions taken from DB.
*
* @var array|string
*/
protected $expression;
/**
* Cache for Zabbix expressions.
*
* @var array
*/
private static $_cachedExpressions = [];
/**
* Initialize expression, gets data from db for Zabbix expressions.
*
* @param string $regExp
*
* @throws Exception
*/
public function __construct($regExp) {
if ($regExp[0] == '@') {
$this->isZabbixRegexp = true;
$regExp = substr($regExp, 1);
if (!isset(self::$_cachedExpressions[$regExp])) {
self::$_cachedExpressions[$regExp] = [];
$dbRegExps = DBselect(
'SELECT e.regexpid,e.expression,e.expression_type,e.exp_delimiter,e.case_sensitive'.
' FROM expressions e,regexps r'.
' WHERE e.regexpid=r.regexpid'.
' AND r.name='.zbx_dbstr($regExp)
);
while ($expression = DBfetch($dbRegExps)) {
self::$_cachedExpressions[$regExp][] = $expression;
}
if (empty(self::$_cachedExpressions[$regExp])) {
unset(self::$_cachedExpressions[$regExp]);
throw new Exception('Does not exist', self::ERROR_REGEXP_NOT_EXISTS);
}
}
$this->expression = self::$_cachedExpressions[$regExp];
}
else {
$this->isZabbixRegexp = false;
$this->expression = $regExp;
}
}
/**
* @param string $string
*
* @return bool
*/
public function match($string) {
if ($this->isZabbixRegexp) {
$result = true;
foreach ($this->expression as $expression) {
$result = self::matchExpression($expression, $string);
if (!$result) {
break;
}
}
}
else {
$result = (bool) @preg_match('/'.str_replace('/', '\/', $this->expression).'/', $string);
}
return $result;
}
/**
* Matches expression against test string, respecting expression type.
*
* @static
*
* @param array $expression
* @param $string
*
* @return bool
*/
public static function matchExpression(array $expression, $string) {
if ($expression['expression_type'] == EXPRESSION_TYPE_TRUE || $expression['expression_type'] == EXPRESSION_TYPE_FALSE) {
$result = self::_matchRegular($expression, $string);
}
else {
$result = self::_matchString($expression, $string);
}
return $result;
}
/**
* Matches expression as regular expression.
*
* @static
*
* @param array $expression
* @param string $string
*
* @return bool
*/
private static function _matchRegular(array $expression, $string) {
$pattern = self::buildRegularExpression($expression);
$expectedResult = ($expression['expression_type'] == EXPRESSION_TYPE_TRUE);
return preg_match($pattern, $string) == $expectedResult;
}
/**
* Combines regular expression provided as definition array into a string.
*
* @static
*
* @param array $expression
*
* @return string
*/
private static function buildRegularExpression(array $expression) {
$expression['expression'] = str_replace('/', '\/', $expression['expression']);
$pattern = '/'.$expression['expression'].'/m';
if (!$expression['case_sensitive']) {
$pattern .= 'i';
}
return $pattern;
}
/**
* Matches expression as string.
*
* @static
*
* @param array $expression
* @param string $string
*
* @return bool
*/
private static function _matchString(array $expression, $string) {
$result = true;
if ($expression['expression_type'] == EXPRESSION_TYPE_ANY_INCLUDED) {
$patterns = array_filter(explode($expression['exp_delimiter'], $expression['expression']), 'strlen');
}
else {
$patterns = [$expression['expression']];
}
$expectedResult = ($expression['expression_type'] != EXPRESSION_TYPE_NOT_INCLUDED);
if (!$expression['case_sensitive']) {
$string = mb_strtolower($string);
}
foreach ($patterns as $pattern) {
if (!$expression['case_sensitive']) {
$pattern = mb_strtolower($pattern);
}
$pos = mb_strpos($string, $pattern);
$tmp = (($pos !== false) == $expectedResult);
if ($expression['expression_type'] == EXPRESSION_TYPE_ANY_INCLUDED && $tmp) {
return true;
}
else {
$result = ($result && $tmp);
}
}
return $result;
}
}