1<?php 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22/** 23 * A parser for function macros like "{host.item.func()}". 24 */ 25class CFunctionMacroParser extends CParser { 26 27 /** 28 * An options array. 29 * 30 * Supported options: 31 * '18_simple_checks' => true with support for old-style simple checks like "ftp,{$PORT}" 32 * 33 * @var array 34 */ 35 private $options = ['18_simple_checks' => false]; 36 37 /** 38 * Parser for item keys. 39 * 40 * @var CItemkey 41 */ 42 private $item_key_parser; 43 44 /** 45 * Parser for trigger functions. 46 * 47 * @var CFunctionParser 48 */ 49 private $function_parser; 50 51 /** 52 * Parser for host names. 53 * 54 * @var CHostNameParser 55 */ 56 private $host_name_parser; 57 58 private $host = ''; 59 private $item = ''; 60 private $function = ''; 61 62 /** 63 * @param array $options 64 */ 65 public function __construct($options = []) { 66 if (array_key_exists('18_simple_checks', $options)) { 67 $this->options['18_simple_checks'] = $options['18_simple_checks']; 68 } 69 70 $this->item_key_parser = new CItemKey(['18_simple_checks' => $this->options['18_simple_checks']]); 71 $this->function_parser = new CFunctionParser(); 72 $this->host_name_parser = new CHostNameParser(); 73 } 74 75 /** 76 * @param string $source 77 * @param int $pos 78 * 79 * @return int 80 */ 81 public function parse($source, $pos = 0) { 82 $this->length = 0; 83 $this->match = ''; 84 $this->host = ''; 85 $this->item = ''; 86 $this->function = ''; 87 88 $p = $pos; 89 90 if (!isset($source[$p]) || $source[$p] !== '{') { 91 return self::PARSE_FAIL; 92 } 93 $p++; 94 95 if (!$this->parseHost($source, $p)) { 96 return self::PARSE_FAIL; 97 } 98 99 if (!isset($source[$p]) || $source[$p] !== ':') { 100 return self::PARSE_FAIL; 101 } 102 $p++; 103 104 $p2 = $p; 105 106 if ($this->item_key_parser->parse($source, $p) == CParser::PARSE_FAIL) { 107 return self::PARSE_FAIL; 108 } 109 $p += $this->item_key_parser->getLength(); 110 111 // for instance, agent.ping.last(0) 112 if ($this->item_key_parser->getParamsNum() == 0 && isset($source[$p]) && $source[$p] == '(') { 113 for (; $p > $p2 && $source[$p] != '.'; $p--) { 114 // Code is not missing here. 115 } 116 117 if ($p == $p2) { 118 return self::PARSE_FAIL; 119 } 120 } 121 $p3 = $p; 122 123 if (!isset($source[$p]) || $source[$p] !== '.') { 124 return self::PARSE_FAIL; 125 } 126 $p++; 127 128 if ($this->function_parser->parse($source, $p) == CParser::PARSE_FAIL) { 129 return self::PARSE_FAIL; 130 } 131 $p += $this->function_parser->getLength(); 132 133 if (!isset($source[$p]) || $source[$p] !== '}') { 134 return self::PARSE_FAIL; 135 } 136 $p++; 137 138 $this->length = $p - $pos; 139 $this->match = substr($source, $pos, $this->length); 140 $this->host = substr($source, $pos + 1, $p2 - $pos - 2); 141 $this->item = substr($source, $p2, $p3 - $p2); 142 $this->function = $this->function_parser->getMatch(); 143 144 return (isset($source[$pos + $this->length]) ? self::PARSE_SUCCESS_CONT : self::PARSE_SUCCESS); 145 } 146 147 /** 148 * Parses a host in a trigger function macro constant and moves a position ($pos) on a next symbol after the host. 149 * 150 * @param string $source 151 * @param int $pos 152 * 153 * @return bool 154 */ 155 protected function parseHost($source, &$pos) { 156 if ($this->host_name_parser->parse($source, $pos) == self::PARSE_FAIL) { 157 return false; 158 } 159 160 $pos += $this->host_name_parser->getLength(); 161 162 return true; 163 } 164 165 /** 166 * Returns parsed host. 167 * 168 * @return string 169 */ 170 public function getHost() { 171 return $this->host; 172 } 173 174 /** 175 * Returns parsed item. 176 * 177 * @return string 178 */ 179 public function getItem() { 180 return $this->item; 181 } 182 183 /** 184 * Returns parsed function. 185 * 186 * @return string 187 */ 188 public function getFunction() { 189 return $this->function; 190 } 191} 192