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 * Class containing methods for operations with http tests. 24 */ 25class CHttpTest extends CApiService { 26 27 public const ACCESS_RULES = [ 28 'get' => ['min_user_type' => USER_TYPE_ZABBIX_USER], 29 'create' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN], 30 'update' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN], 31 'delete' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN] 32 ]; 33 34 protected $tableName = 'httptest'; 35 protected $tableAlias = 'ht'; 36 protected $sortColumns = ['httptestid', 'name']; 37 38 /** 39 * Get data about web scenarios. 40 * 41 * @param array $options 42 * 43 * @return array 44 */ 45 public function get($options = []) { 46 $result = []; 47 48 $sqlParts = [ 49 'select' => ['httptests' => 'ht.httptestid'], 50 'from' => ['httptest' => 'httptest ht'], 51 'where' => [], 52 'group' => [], 53 'order' => [], 54 'limit' => null 55 ]; 56 57 $defOptions = [ 58 'httptestids' => null, 59 'hostids' => null, 60 'groupids' => null, 61 'templateids' => null, 62 'editable' => false, 63 'inherited' => null, 64 'templated' => null, 65 'monitored' => null, 66 'nopermissions' => null, 67 'evaltype' => TAG_EVAL_TYPE_AND_OR, 68 'tags' => null, 69 // filter 70 'filter' => null, 71 'search' => null, 72 'searchByAny' => null, 73 'startSearch' => false, 74 'excludeSearch' => false, 75 // output 76 'output' => API_OUTPUT_EXTEND, 77 'expandName' => null, 78 'expandStepName' => null, 79 'selectHosts' => null, 80 'selectSteps' => null, 81 'selectTags' => null, 82 'countOutput' => false, 83 'groupCount' => false, 84 'preservekeys' => false, 85 'sortfield' => '', 86 'sortorder' => '', 87 'limit' => null 88 ]; 89 $options = zbx_array_merge($defOptions, $options); 90 91 // editable + PERMISSION CHECK 92 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN && !$options['nopermissions']) { 93 $permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ; 94 $userGroups = getUserGroupsByUserId(self::$userData['userid']); 95 96 $sqlParts['where'][] = 'EXISTS ('. 97 'SELECT NULL'. 98 ' FROM hosts_groups hgg'. 99 ' JOIN rights r'. 100 ' ON r.id=hgg.groupid'. 101 ' AND '.dbConditionInt('r.groupid', $userGroups). 102 ' WHERE ht.hostid=hgg.hostid'. 103 ' GROUP BY hgg.hostid'. 104 ' HAVING MIN(r.permission)>'.PERM_DENY. 105 ' AND MAX(r.permission)>='.zbx_dbstr($permission). 106 ')'; 107 } 108 109 // httptestids 110 if (!is_null($options['httptestids'])) { 111 zbx_value2array($options['httptestids']); 112 113 $sqlParts['where']['httptestid'] = dbConditionInt('ht.httptestid', $options['httptestids']); 114 } 115 116 // templateids 117 if (!is_null($options['templateids'])) { 118 zbx_value2array($options['templateids']); 119 120 if (!is_null($options['hostids'])) { 121 zbx_value2array($options['hostids']); 122 $options['hostids'] = array_merge($options['hostids'], $options['templateids']); 123 } 124 else { 125 $options['hostids'] = $options['templateids']; 126 } 127 } 128 // hostids 129 if (!is_null($options['hostids'])) { 130 zbx_value2array($options['hostids']); 131 132 $sqlParts['where']['hostid'] = dbConditionInt('ht.hostid', $options['hostids']); 133 134 if ($options['groupCount']) { 135 $sqlParts['group']['hostid'] = 'ht.hostid'; 136 } 137 } 138 139 // tags 140 if ($options['tags'] !== null && $options['tags']) { 141 $sqlParts['where'][] = CApiTagHelper::addWhereCondition($options['tags'], $options['evaltype'], 'ht', 142 'httptest_tag', 'httptestid' 143 ); 144 } 145 146 // groupids 147 if (!is_null($options['groupids'])) { 148 zbx_value2array($options['groupids']); 149 150 $sqlParts['from']['hosts_groups'] = 'hosts_groups hg'; 151 $sqlParts['where'][] = dbConditionInt('hg.groupid', $options['groupids']); 152 $sqlParts['where'][] = 'hg.hostid=ht.hostid'; 153 154 if ($options['groupCount']) { 155 $sqlParts['group']['hg'] = 'hg.groupid'; 156 } 157 } 158 159 // inherited 160 if (isset($options['inherited'])) { 161 $sqlParts['where'][] = $options['inherited'] ? 'ht.templateid IS NOT NULL' : 'ht.templateid IS NULL'; 162 } 163 164 // templated 165 if (isset($options['templated'])) { 166 $sqlParts['from']['hosts'] = 'hosts h'; 167 $sqlParts['where']['ha'] = 'h.hostid=ht.hostid'; 168 if ($options['templated']) { 169 $sqlParts['where'][] = 'h.status='.HOST_STATUS_TEMPLATE; 170 } 171 else { 172 $sqlParts['where'][] = 'h.status<>'.HOST_STATUS_TEMPLATE; 173 } 174 } 175 176 // monitored 177 if (!is_null($options['monitored'])) { 178 $sqlParts['from']['hosts'] = 'hosts h'; 179 $sqlParts['where']['hht'] = 'h.hostid=ht.hostid'; 180 181 if ($options['monitored']) { 182 $sqlParts['where'][] = 'h.status='.HOST_STATUS_MONITORED; 183 $sqlParts['where'][] = 'ht.status='.ITEM_STATUS_ACTIVE; 184 } 185 else { 186 $sqlParts['where'][] = '(h.status<>'.HOST_STATUS_MONITORED.' OR ht.status<>'.ITEM_STATUS_ACTIVE.')'; 187 } 188 } 189 190 // search 191 if (is_array($options['search'])) { 192 zbx_db_search('httptest ht', $options, $sqlParts); 193 } 194 195 // filter 196 if (is_array($options['filter'])) { 197 if (array_key_exists('delay', $options['filter']) && $options['filter']['delay'] !== null) { 198 $options['filter']['delay'] = getTimeUnitFilters($options['filter']['delay']); 199 } 200 201 $this->dbFilter('httptest ht', $options, $sqlParts); 202 } 203 204 // limit 205 if (zbx_ctype_digit($options['limit']) && $options['limit']) { 206 $sqlParts['limit'] = $options['limit']; 207 } 208 209 $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); 210 $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); 211 $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); 212 while ($httpTest = DBfetch($res)) { 213 if ($options['countOutput']) { 214 if ($options['groupCount']) { 215 $result[] = $httpTest; 216 } 217 else { 218 $result = $httpTest['rowscount']; 219 } 220 } 221 else { 222 $result[$httpTest['httptestid']] = $httpTest; 223 } 224 } 225 226 if ($options['countOutput']) { 227 return $result; 228 } 229 230 if ($result) { 231 $result = $this->addRelatedObjects($options, $result); 232 233 // expandName 234 $nameRequested = (is_array($options['output']) && in_array('name', $options['output'])) 235 || $options['output'] == API_OUTPUT_EXTEND; 236 $expandName = $options['expandName'] !== null && $nameRequested; 237 238 // expandStepName 239 $stepNameRequested = $options['selectSteps'] == API_OUTPUT_EXTEND 240 || (is_array($options['selectSteps']) && in_array('name', $options['selectSteps'])); 241 $expandStepName = $options['expandStepName'] !== null && $stepNameRequested; 242 243 if ($expandName || $expandStepName) { 244 $result = resolveHttpTestMacros($result, $expandName, $expandStepName); 245 } 246 247 $result = $this->unsetExtraFields($result, ['hostid'], $options['output']); 248 } 249 250 // removing keys (hash -> array) 251 if (!$options['preservekeys']) { 252 $result = zbx_cleanHashes($result); 253 } 254 255 return $result; 256 } 257 258 /** 259 * Create web scenario. 260 * 261 * @param $httptests 262 * 263 * @return array 264 * 265 * @throws APIException 266 */ 267 public function create($httptests) { 268 $this->validateCreate($httptests); 269 270 $httptests = Manager::HttpTest()->persist($httptests); 271 272 $this->addAuditBulk(AUDIT_ACTION_ADD, AUDIT_RESOURCE_SCENARIO, $httptests); 273 274 return ['httptestids' => zbx_objectValues($httptests, 'httptestid')]; 275 } 276 277 /** 278 * @param array $httptests 279 * 280 * @throws APIException if the input is invalid. 281 */ 282 protected function validateCreate(array &$httptests): void { 283 $api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'uniq' => [['uuid'], ['hostid', 'name']], 'fields' => [ 284 'hostid' => ['type' => API_ID, 'flags' => API_REQUIRED], 285 'uuid' => ['type' => API_UUID], 286 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest', 'name')], 287 'delay' => ['type' => API_TIME_UNIT, 'flags' => API_NOT_EMPTY | API_ALLOW_USER_MACRO, 'in' => '1:'.SEC_PER_DAY], 288 'retries' => ['type' => API_INT32, 'in' => '1:10'], 289 'agent' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'agent')], 290 'http_proxy' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'http_proxy')], 291 'variables' => ['type' => API_OBJECTS, 'uniq' => [['name']], 'fields' => [ 292 'name' => ['type' => API_VARIABLE_NAME, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httptest_field', 'name')], 293 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httptest_field', 'value')] 294 ]], 295 'headers' => ['type' => API_OBJECTS, 'fields' => [ 296 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest_field', 'name')], 297 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest_field', 'value')] 298 ]], 299 'status' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_STATUS_ACTIVE, HTTPTEST_STATUS_DISABLED])], 300 'authentication' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_AUTH_NONE, HTTPTEST_AUTH_BASIC, HTTPTEST_AUTH_NTLM, HTTPTEST_AUTH_KERBEROS, HTTPTEST_AUTH_DIGEST])], 301 'http_user' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'http_user')], 302 'http_password' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'http_password')], 303 'verify_peer' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_VERIFY_PEER_OFF, HTTPTEST_VERIFY_PEER_ON])], 304 'verify_host' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_VERIFY_HOST_OFF, HTTPTEST_VERIFY_HOST_ON])], 305 'ssl_cert_file' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'ssl_cert_file')], 306 'ssl_key_file' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'ssl_key_file')], 307 'ssl_key_password' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'ssl_key_password')], 308 'steps' => ['type' => API_OBJECTS, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'uniq' => [['name'], ['no']], 'fields' => [ 309 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep', 'name')], 310 'no' => ['type' => API_INT32, 'flags' => API_REQUIRED], 311 'url' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep', 'url')], 312 'query_fields' => ['type' => API_OBJECTS, 'fields' => [ 313 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep_field', 'name')], 314 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httpstep_field', 'value')] 315 ]], 316 'posts' => ['type' => API_HTTP_POST, 'length' => DB::getFieldLength('httpstep', 'posts'), 'name-length' => DB::getFieldLength('httpstep_field', 'name'), 'value-length' => DB::getFieldLength('httpstep_field', 'value')], 317 'variables' => ['type' => API_OBJECTS, 'uniq' => [['name']], 'fields' => [ 318 'name' => ['type' => API_VARIABLE_NAME, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httpstep_field', 'name')], 319 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httpstep_field', 'value')] 320 ]], 321 'headers' => ['type' => API_OBJECTS, 'fields' => [ 322 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep_field', 'name')], 323 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep_field', 'value')] 324 ]], 325 'follow_redirects' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_STEP_FOLLOW_REDIRECTS_OFF, HTTPTEST_STEP_FOLLOW_REDIRECTS_ON])], 326 'retrieve_mode' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_STEP_RETRIEVE_MODE_CONTENT, HTTPTEST_STEP_RETRIEVE_MODE_HEADERS, HTTPTEST_STEP_RETRIEVE_MODE_BOTH])], 327 'timeout' => ['type' => API_TIME_UNIT, 'flags' => API_NOT_EMPTY | API_ALLOW_USER_MACRO, 'in' => '1:'.SEC_PER_HOUR], 328 'required' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httpstep', 'required')], 329 'status_codes' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httpstep', 'status_codes')] 330 ]], 331 'tags' => ['type' => API_OBJECTS, 'uniq' => [['tag', 'value']], 'fields' => [ 332 'tag' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest_tag', 'tag')], 333 'value' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest_tag', 'value'), 'default' => DB::getDefault('httptest_tag', 'value')] 334 ]] 335 ]]; 336 337 if (!CApiInputValidator::validate($api_input_rules, $httptests, '/', $error)) { 338 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 339 } 340 341 $names_by_hostid = []; 342 343 foreach ($httptests as $httptest) { 344 $names_by_hostid[$httptest['hostid']][] = $httptest['name']; 345 } 346 347 $this->checkAndAddUuid($httptests); 348 $this->checkHostPermissions(array_keys($names_by_hostid)); 349 $this->checkDuplicates($names_by_hostid); 350 $this->validateAuthParameters($httptests, __FUNCTION__); 351 $this->validateSslParameters($httptests, __FUNCTION__); 352 $this->validateSteps($httptests, __FUNCTION__); 353 } 354 355 /** 356 * Check that only httptests on templates have UUID. Add UUID to all httptests on templates, if it does not exists. 357 * 358 * @param array $httptests_to_create 359 * 360 * @throws APIException 361 */ 362 protected function checkAndAddUuid(array &$httptests_to_create): void { 363 $db_templateids = API::Template()->get([ 364 'output' => [], 365 'templateids' => array_column($httptests_to_create, 'hostid'), 366 'preservekeys' => true 367 ]); 368 369 foreach ($httptests_to_create as $index => &$httptest) { 370 if (!array_key_exists($httptest['hostid'], $db_templateids) && array_key_exists('uuid', $httptest)) { 371 self::exception(ZBX_API_ERROR_PARAMETERS, 372 _s('Invalid parameter "%1$s": %2$s.', '/' . ($index + 1), _s('unexpected parameter "%1$s"', 'uuid')) 373 ); 374 } 375 376 if (array_key_exists($httptest['hostid'], $db_templateids) && !array_key_exists('uuid', $httptest)) { 377 $httptest['uuid'] = generateUuidV4(); 378 } 379 } 380 unset($httptest); 381 382 $db_uuid = DB::select('httptest', [ 383 'output' => ['uuid'], 384 'filter' => ['uuid' => array_column($httptests_to_create, 'uuid')], 385 'limit' => 1 386 ]); 387 388 if ($db_uuid) { 389 self::exception(ZBX_API_ERROR_PARAMETERS, 390 _s('Entry with UUID "%1$s" already exists.', $db_uuid[0]['uuid']) 391 ); 392 } 393 } 394 395 /** 396 * @param $httptests 397 * 398 * @return array 399 */ 400 public function update($httptests) { 401 $this->validateUpdate($httptests, $db_httptests); 402 403 Manager::HttpTest()->persist($httptests); 404 405 foreach ($db_httptests as &$db_httptest) { 406 unset($db_httptest['headers'], $db_httptest['variables'], $db_httptest['steps']); 407 } 408 unset($db_httptest); 409 410 $this->addAuditBulk(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_SCENARIO, $httptests, $db_httptests); 411 412 return ['httptestids' => zbx_objectValues($httptests, 'httptestid')]; 413 } 414 415 /** 416 * @param array $httptests 417 * @param array $db_httptests 418 * 419 * @throws APIException if the input is invalid. 420 */ 421 protected function validateUpdate(array &$httptests, array &$db_httptests = null) { 422 $api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'uniq' => [['httptestid']], 'fields' => [ 423 'httptestid' => ['type' => API_ID, 'flags' => API_REQUIRED], 424 'name' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest', 'name')], 425 'delay' => ['type' => API_TIME_UNIT, 'flags' => API_NOT_EMPTY | API_ALLOW_USER_MACRO, 'in' => '1:'.SEC_PER_DAY], 426 'retries' => ['type' => API_INT32, 'in' => '1:10'], 427 'agent' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'agent')], 428 'http_proxy' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'http_proxy')], 429 'variables' => ['type' => API_OBJECTS, 'uniq' => [['name']], 'fields' => [ 430 'name' => ['type' => API_VARIABLE_NAME, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httptest_field', 'name')], 431 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httptest_field', 'value')] 432 ]], 433 'headers' => ['type' => API_OBJECTS, 'fields' => [ 434 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest_field', 'name')], 435 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest_field', 'value')] 436 ]], 437 'status' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_STATUS_ACTIVE, HTTPTEST_STATUS_DISABLED])], 438 'authentication' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_AUTH_NONE, HTTPTEST_AUTH_BASIC, HTTPTEST_AUTH_NTLM, HTTPTEST_AUTH_KERBEROS, HTTPTEST_AUTH_DIGEST])], 439 'http_user' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'http_user')], 440 'http_password' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'http_password')], 441 'verify_peer' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_VERIFY_PEER_OFF, HTTPTEST_VERIFY_PEER_ON])], 442 'verify_host' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_VERIFY_HOST_OFF, HTTPTEST_VERIFY_HOST_ON])], 443 'ssl_cert_file' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'ssl_cert_file')], 444 'ssl_key_file' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'ssl_key_file')], 445 'ssl_key_password' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest', 'ssl_key_password')], 446 'steps' => ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY, 'uniq' => [['httpstepid'], ['name'], ['no']], 'fields' => [ 447 'httpstepid' => ['type' => API_ID], 448 'name' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep', 'name')], 449 'no' => ['type' => API_INT32], 450 'url' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep', 'url')], 451 'query_fields' => ['type' => API_OBJECTS, 'fields' => [ 452 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep_field', 'name')], 453 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httpstep_field', 'value')] 454 ]], 455 'posts' => ['type' => API_HTTP_POST, 'length' => DB::getFieldLength('httpstep', 'posts'), 'name-length' => DB::getFieldLength('httpstep_field', 'name'), 'value-length' => DB::getFieldLength('httpstep_field', 'value')], 456 'variables' => ['type' => API_OBJECTS, 'uniq' => [['name']], 'fields' => [ 457 'name' => ['type' => API_VARIABLE_NAME, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httpstep_field', 'name')], 458 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('httpstep_field', 'value')] 459 ]], 460 'headers' => ['type' => API_OBJECTS, 'fields' => [ 461 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep_field', 'name')], 462 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httpstep_field', 'value')] 463 ]], 464 'follow_redirects' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_STEP_FOLLOW_REDIRECTS_OFF, HTTPTEST_STEP_FOLLOW_REDIRECTS_ON])], 465 'retrieve_mode' => ['type' => API_INT32, 'in' => implode(',', [HTTPTEST_STEP_RETRIEVE_MODE_CONTENT, HTTPTEST_STEP_RETRIEVE_MODE_HEADERS, HTTPTEST_STEP_RETRIEVE_MODE_BOTH])], 466 'timeout' => ['type' => API_TIME_UNIT, 'flags' => API_NOT_EMPTY | API_ALLOW_USER_MACRO, 'in' => '1:'.SEC_PER_HOUR], 467 'required' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httpstep', 'required')], 468 'status_codes' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httpstep', 'status_codes')] 469 ]], 470 'tags' => ['type' => API_OBJECTS, 'uniq' => [['tag', 'value']], 'fields' => [ 471 'tag' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('httptest_tag', 'tag')], 472 'value' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('httptest_tag', 'value'), 'default' => DB::getDefault('httptest_tag', 'value')] 473 ]] 474 ]]; 475 if (!CApiInputValidator::validate($api_input_rules, $httptests, '/', $error)) { 476 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 477 } 478 479 // permissions 480 $db_httptests = $this->get([ 481 'output' => ['httptestid', 'hostid', 'name', 'delay', 'retries', 'agent', 'http_proxy', 482 'status', 'authentication', 'http_user', 'http_password', 'verify_peer', 'verify_host', 483 'ssl_cert_file', 'ssl_key_file', 'ssl_key_password', 'templateid' 484 ], 485 'selectSteps' => ['httpstepid', 'name', 'no', 'url', 'timeout', 'posts', 'required', 486 'status_codes', 'follow_redirects', 'retrieve_mode', 'post_type' 487 ], 488 'httptestids' => zbx_objectValues($httptests, 'httptestid'), 489 'editable' => true, 490 'preservekeys' => true 491 ]); 492 493 foreach ($db_httptests as &$db_httptest) { 494 $db_httptest['headers'] = []; 495 $db_httptest['variables'] = []; 496 $db_httptest['steps'] = zbx_toHash($db_httptest['steps'], 'httpstepid'); 497 } 498 unset($db_httptest); 499 500 $names_by_hostid = []; 501 502 foreach ($httptests as $httptest) { 503 if (!array_key_exists($httptest['httptestid'], $db_httptests)) { 504 self::exception(ZBX_API_ERROR_PERMISSIONS, 505 _('No permissions to referred object or it does not exist!') 506 ); 507 } 508 509 $db_httptest = $db_httptests[$httptest['httptestid']]; 510 511 if (array_key_exists('name', $httptest)) { 512 if ($db_httptest['templateid'] != 0) { 513 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 514 'Cannot update a templated web scenario "%1$s": %2$s.', $httptest['name'], 515 _s('unexpected parameter "%1$s"', 'name') 516 )); 517 } 518 519 if ($httptest['name'] !== $db_httptest['name']) { 520 $names_by_hostid[$db_httptest['hostid']][] = $httptest['name']; 521 } 522 } 523 } 524 525 $httptests = $this->extendObjectsByKey($httptests, $db_httptests, 'httptestid', ['hostid', 'name']); 526 527 // uniqueness 528 foreach ($httptests as &$httptest) { 529 $db_httptest = $db_httptests[$httptest['httptestid']]; 530 531 if (array_key_exists('steps', $httptest)) { 532 // unexpected patameters for templated web scenario steps 533 if ($db_httptest['templateid'] != 0) { 534 foreach ($httptest['steps'] as $httpstep) { 535 foreach (['name', 'no'] as $field_name) { 536 if (array_key_exists($field_name, $httpstep)) { 537 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 538 'Cannot update step for a templated web scenario "%1$s": %2$s.', $httptest['name'], 539 _s('unexpected parameter "%1$s"', $field_name) 540 )); 541 } 542 } 543 } 544 } 545 546 $httptest['steps'] = 547 $this->extendObjectsByKey($httptest['steps'], $db_httptest['steps'], 'httpstepid', ['name']); 548 } 549 } 550 unset($httptest); 551 552 $api_input_rules = ['type' => API_OBJECTS, 'uniq' => [['hostid', 'name']], 'fields' => [ 553 'hostid' => ['type' => API_ID], 554 'name' => ['type' => API_STRING_UTF8], 555 'steps' => ['type' => API_OBJECTS, 'uniq' => [['name']], 'fields' => [ 556 'name' => ['type' => API_STRING_UTF8] 557 ]] 558 ]]; 559 560 if (!CApiInputValidator::validateUniqueness($api_input_rules, $httptests, '/', $error)) { 561 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 562 } 563 564 // validation 565 if ($names_by_hostid) { 566 $this->checkDuplicates($names_by_hostid); 567 } 568 $this->validateAuthParameters($httptests, __FUNCTION__, $db_httptests); 569 $this->validateSslParameters($httptests, __FUNCTION__, $db_httptests); 570 $this->validateSteps($httptests, __FUNCTION__, $db_httptests); 571 572 return $httptests; 573 } 574 575 /** 576 * Delete web scenario. 577 * 578 * @param array $httptestids 579 * @param bool $nopermissions 580 * 581 * @return array 582 */ 583 public function delete(array $httptestids, $nopermissions = false) { 584 // TODO: remove $nopermissions hack 585 586 $api_input_rules = ['type' => API_IDS, 'flags' => API_NOT_EMPTY, 'uniq' => true]; 587 if (!CApiInputValidator::validate($api_input_rules, $httptestids, '/', $error)) { 588 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 589 } 590 591 $db_httptests = $this->get([ 592 'output' => ['httptestid', 'name', 'templateid'], 593 'httptestids' => $httptestids, 594 'editable' => true, 595 'preservekeys' => true 596 ]); 597 598 if (!$nopermissions) { 599 foreach ($httptestids as $httptestid) { 600 if (!array_key_exists($httptestid, $db_httptests)) { 601 self::exception(ZBX_API_ERROR_PERMISSIONS, 602 _('No permissions to referred object or it does not exist!') 603 ); 604 } 605 606 $db_httptest = $db_httptests[$httptestid]; 607 608 if ($db_httptest['templateid'] != 0) { 609 self::exception(ZBX_API_ERROR_PARAMETERS, 610 _s('Cannot delete templated web scenario "%1$s".', $db_httptest['name']) 611 ); 612 } 613 } 614 } 615 616 $parent_httptestids = $httptestids; 617 $child_httptestids = []; 618 do { 619 $parent_httptestids = array_keys(DB::select('httptest', [ 620 'output' => [], 621 'filter' => ['templateid' => $parent_httptestids], 622 'preservekeys' => true 623 ])); 624 625 $child_httptestids = array_merge($child_httptestids, $parent_httptestids); 626 } 627 while ($parent_httptestids); 628 629 $del_httptestids = array_merge($httptestids, $child_httptestids); 630 $del_itemids = []; 631 632 $db_httptestitems = DBselect( 633 'SELECT hti.itemid'. 634 ' FROM httptestitem hti'. 635 ' WHERE '.dbConditionInt('hti.httptestid', $del_httptestids) 636 ); 637 while ($db_httptestitem = DBfetch($db_httptestitems)) { 638 $del_itemids[] = $db_httptestitem['itemid']; 639 } 640 641 $db_httpstepitems = DBselect( 642 'SELECT hsi.itemid'. 643 ' FROM httpstepitem hsi,httpstep hs'. 644 ' WHERE hsi.httpstepid=hs.httpstepid'. 645 ' AND '.dbConditionInt('hs.httptestid', $del_httptestids) 646 ); 647 while ($db_httpstepitem = DBfetch($db_httpstepitems)) { 648 $del_itemids[] = $db_httpstepitem['itemid']; 649 } 650 651 if ($del_itemids) { 652 CItemManager::delete($del_itemids); 653 } 654 655 DB::delete('httptest', ['httptestid' => $del_httptestids]); 656 657 $this->addAuditBulk(AUDIT_ACTION_DELETE, AUDIT_RESOURCE_SCENARIO, $db_httptests); 658 659 return ['httptestids' => $httptestids]; 660 } 661 662 /** 663 * Checks if the current user has access to the given hosts and templates. 664 * 665 * @param array $hostids an array of host or template IDs 666 * 667 * @throws APIException if the user doesn't have write permissions for the given hosts. 668 */ 669 private function checkHostPermissions(array $hostids) { 670 if ($hostids) { 671 $count = API::Host()->get([ 672 'countOutput' => true, 673 'hostids' => $hostids, 674 'editable' => true 675 ]); 676 677 if ($count == count($hostids)) { 678 return; 679 } 680 681 $count += API::Template()->get([ 682 'countOutput' => true, 683 'templateids' => $hostids, 684 'editable' => true 685 ]); 686 687 if ($count != count($hostids)) { 688 self::exception(ZBX_API_ERROR_PERMISSIONS, 689 _('No permissions to referred object or it does not exist!') 690 ); 691 } 692 } 693 } 694 695 /** 696 * Check for duplicated web scenarios. 697 * 698 * @param array $names_by_hostid 699 * 700 * @throws APIException if web scenario already exists. 701 */ 702 private function checkDuplicates(array $names_by_hostid) { 703 $sql_where = []; 704 foreach ($names_by_hostid as $hostid => $names) { 705 $sql_where[] = '(ht.hostid='.$hostid.' AND '.dbConditionString('ht.name', $names).')'; 706 } 707 708 $db_httptests = DBfetchArray( 709 DBselect('SELECT ht.name FROM httptest ht WHERE '.implode(' OR ', $sql_where), 1) 710 ); 711 712 if ($db_httptests) { 713 self::exception(ZBX_API_ERROR_PARAMETERS, 714 _s('Web scenario "%1$s" already exists.', $db_httptests[0]['name']) 715 ); 716 } 717 } 718 719 /** 720 * @param array $httptests 721 * @param string $method 722 * @param array $db_httptests 723 * 724 * @throws APIException 725 */ 726 protected function validateSteps(array &$httptests, $method, array $db_httptests = null) { 727 if ($method === 'validateUpdate') { 728 foreach ($httptests as $httptest) { 729 if (!array_key_exists('steps', $httptest)) { 730 continue; 731 } 732 733 $db_httptest = $db_httptests[$httptest['httptestid']]; 734 735 if ($db_httptest['templateid'] != 0) { 736 if (count($httptest['steps']) != count($db_httptest['steps'])) { 737 self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect templated web scenario step count.')); 738 } 739 740 foreach ($httptest['steps'] as $httpstep) { 741 if (!array_key_exists('httpstepid', $httpstep)) { 742 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 743 'Cannot update step for a templated web scenario "%1$s": %2$s.', $httptest['name'], 744 _s('the parameter "%1$s" is missing', 'httpstepid') 745 )); 746 } 747 elseif (!array_key_exists($httpstep['httpstepid'], $db_httptest['steps'])) { 748 self::exception(ZBX_API_ERROR_PARAMETERS, 749 _('No permissions to referred object or it does not exist!') 750 ); 751 } 752 } 753 } 754 } 755 } 756 757 $this->checkStatusCodes($httptests); 758 $this->validateRetrieveMode($httptests, $method, $db_httptests); 759 } 760 761 /** 762 * Validate http response code range. 763 * Range can be empty string or list of comma separated numeric strings or user macros. 764 * 765 * Examples: '100-199, 301, 404, 500-550, {$MACRO}-200, {$MACRO}-{$MACRO}' 766 * 767 * @param array $httptests 768 * 769 * @throws APIException if the status code range is invalid. 770 */ 771 private function checkStatusCodes(array $httptests) { 772 $ranges_parser = new CRangesParser(['usermacros' => true]); 773 774 foreach ($httptests as $httptest) { 775 if (!array_key_exists('steps', $httptest)) { 776 continue; 777 } 778 779 foreach ($httptest['steps'] as $httpstep) { 780 if (!array_key_exists('status_codes', $httpstep) || $httpstep['status_codes'] === '') { 781 continue; 782 } 783 784 if ($ranges_parser->parse($httpstep['status_codes']) != CParser::PARSE_SUCCESS) { 785 self::exception(ZBX_API_ERROR_PARAMETERS, 786 _s('Invalid response code "%1$s".', $httpstep['status_codes']) 787 ); 788 } 789 } 790 } 791 } 792 793 protected function applyQueryOutputOptions($tableName, $tableAlias, array $options, array $sqlParts) { 794 $sqlParts = parent::applyQueryOutputOptions($tableName, $tableAlias, $options, $sqlParts); 795 796 if (!$options['countOutput']) { 797 // make sure we request the hostid to be able to expand macros 798 if ($options['expandName'] !== null || $options['expandStepName'] !== null || $options['selectHosts'] !== null) { 799 $sqlParts = $this->addQuerySelect($this->fieldId('hostid'), $sqlParts); 800 } 801 } 802 803 return $sqlParts; 804 } 805 806 protected function addRelatedObjects(array $options, array $result) { 807 $result = parent::addRelatedObjects($options, $result); 808 809 $httpTestIds = array_keys($result); 810 811 // adding headers and variables 812 $fields = [ 813 ZBX_HTTPFIELD_HEADER => 'headers', 814 ZBX_HTTPFIELD_VARIABLE => 'variables' 815 ]; 816 foreach ($fields as $type => $field) { 817 if (!$this->outputIsRequested($field, $options['output'])) { 818 unset($fields[$type]); 819 } 820 } 821 822 if ($fields) { 823 $db_httpfields = DB::select('httptest_field', [ 824 'output' => ['httptestid', 'name', 'value', 'type'], 825 'filter' => [ 826 'httptestid' => $httpTestIds, 827 'type' => array_keys($fields) 828 ], 829 'sortfield' => ['httptest_fieldid'] 830 ]); 831 832 foreach ($result as &$httptest) { 833 foreach ($fields as $field) { 834 $httptest[$field] = []; 835 } 836 } 837 unset($httptest); 838 839 foreach ($db_httpfields as $db_httpfield) { 840 $result[$db_httpfield['httptestid']][$fields[$db_httpfield['type']]][] = [ 841 'name' => $db_httpfield['name'], 842 'value' => $db_httpfield['value'] 843 ]; 844 } 845 } 846 847 // adding hosts 848 if ($options['selectHosts'] !== null && $options['selectHosts'] != API_OUTPUT_COUNT) { 849 $relationMap = $this->createRelationMap($result, 'httptestid', 'hostid'); 850 $hosts = API::Host()->get([ 851 'output' => $options['selectHosts'], 852 'hostid' => $relationMap->getRelatedIds(), 853 'nopermissions' => true, 854 'templated_hosts' => true, 855 'preservekeys' => true 856 ]); 857 $result = $relationMap->mapMany($result, $hosts, 'hosts'); 858 } 859 860 // adding steps 861 if ($options['selectSteps'] !== null) { 862 if ($options['selectSteps'] != API_OUTPUT_COUNT) { 863 $fields = [ 864 ZBX_HTTPFIELD_HEADER => 'headers', 865 ZBX_HTTPFIELD_VARIABLE => 'variables', 866 ZBX_HTTPFIELD_QUERY_FIELD => 'query_fields', 867 ZBX_HTTPFIELD_POST_FIELD => 'posts' 868 ]; 869 foreach ($fields as $type => $field) { 870 if (!$this->outputIsRequested($field, $options['selectSteps'])) { 871 unset($fields[$type]); 872 } 873 } 874 875 $db_httpsteps = API::getApiService()->select('httpstep', [ 876 'output' => $this->outputExtend($options['selectSteps'], ['httptestid', 'httpstepid', 'post_type']), 877 'filter' => ['httptestid' => $httpTestIds], 878 'preservekeys' => true 879 ]); 880 $relationMap = $this->createRelationMap($db_httpsteps, 'httptestid', 'httpstepid'); 881 882 if ($fields) { 883 foreach ($db_httpsteps as &$db_httpstep) { 884 foreach ($fields as $type => $field) { 885 if ($type != ZBX_HTTPFIELD_POST_FIELD || $db_httpstep['post_type'] == ZBX_POSTTYPE_FORM) { 886 $db_httpstep[$field] = []; 887 } 888 } 889 } 890 unset($db_httpstep); 891 892 $db_httpstep_fields = DB::select('httpstep_field', [ 893 'output' => ['httpstepid', 'name', 'value', 'type'], 894 'filter' => [ 895 'httpstepid' => array_keys($db_httpsteps), 896 'type' => array_keys($fields) 897 ], 898 'sortfield' => ['httpstep_fieldid'] 899 ]); 900 901 foreach ($db_httpstep_fields as $db_httpstep_field) { 902 $db_httpstep = &$db_httpsteps[$db_httpstep_field['httpstepid']]; 903 904 if ($db_httpstep_field['type'] != ZBX_HTTPFIELD_POST_FIELD 905 || $db_httpstep['post_type'] == ZBX_POSTTYPE_FORM) { 906 $db_httpstep[$fields[$db_httpstep_field['type']]][] = [ 907 'name' => $db_httpstep_field['name'], 908 'value' => $db_httpstep_field['value'] 909 ]; 910 } 911 } 912 unset($db_httpstep); 913 } 914 915 $db_httpsteps = $this->unsetExtraFields($db_httpsteps, ['httptestid', 'httpstepid', 'post_type'], 916 $options['selectSteps'] 917 ); 918 $result = $relationMap->mapMany($result, $db_httpsteps, 'steps'); 919 } 920 else { 921 $dbHttpSteps = DBselect( 922 'SELECT hs.httptestid,COUNT(hs.httpstepid) AS stepscnt'. 923 ' FROM httpstep hs'. 924 ' WHERE '.dbConditionInt('hs.httptestid', $httpTestIds). 925 ' GROUP BY hs.httptestid' 926 ); 927 while ($dbHttpStep = DBfetch($dbHttpSteps)) { 928 $result[$dbHttpStep['httptestid']]['steps'] = $dbHttpStep['stepscnt']; 929 } 930 } 931 } 932 933 // Adding web scenario tags. 934 if ($options['selectTags'] !== null) { 935 $options['selectTags'] = ($options['selectTags'] !== API_OUTPUT_EXTEND) 936 ? (array) $options['selectTags'] 937 : ['tag', 'value']; 938 939 $options['selectTags'] = array_intersect(['tag', 'value'], $options['selectTags']); 940 $requested_output = array_flip($options['selectTags']); 941 942 $db_tags = DBselect( 943 'SELECT '.implode(',', array_merge($options['selectTags'], ['httptestid'])). 944 ' FROM httptest_tag'. 945 ' WHERE '.dbConditionInt('httptestid', $httpTestIds) 946 ); 947 948 array_walk($result, function (&$http_test) { 949 $http_test['tags'] = []; 950 }); 951 952 while ($db_tag = DBfetch($db_tags)) { 953 $result[$db_tag['httptestid']]['tags'][] = array_intersect_key($db_tag, $requested_output); 954 } 955 } 956 957 return $result; 958 } 959 960 /** 961 * @param array $httptests 962 * @param string $method 963 * @param array $db_httptests 964 * 965 * @throws APIException if auth parameters are invalid. 966 */ 967 private function validateAuthParameters(array &$httptests, $method, array $db_httptests = null) { 968 foreach ($httptests as &$httptest) { 969 if (array_key_exists('authentication', $httptest) || array_key_exists('http_user', $httptest) 970 || array_key_exists('http_password', $httptest)) { 971 $httptest += [ 972 'authentication' => ($method === 'validateUpdate') 973 ? $db_httptests[$httptest['httptestid']]['authentication'] 974 : HTTPTEST_AUTH_NONE 975 ]; 976 977 if ($httptest['authentication'] == HTTPTEST_AUTH_NONE) { 978 foreach (['http_user', 'http_password'] as $field_name) { 979 $httptest += [$field_name => '']; 980 981 if ($httptest[$field_name] !== '') { 982 self::exception(ZBX_API_ERROR_PARAMETERS, 983 _s('Incorrect value for field "%1$s": %2$s.', $field_name, _('should be empty')) 984 ); 985 } 986 } 987 } 988 } 989 } 990 unset($httptest); 991 } 992 993 /** 994 * @param array $httptests 995 * @param string $method 996 * @param array $db_httptests 997 * 998 * @throws APIException if SSL cert is present but SSL key is not. 999 */ 1000 private function validateSslParameters(array &$httptests, $method, array $db_httptests = null) { 1001 foreach ($httptests as &$httptest) { 1002 if (array_key_exists('ssl_key_password', $httptest) 1003 || array_key_exists('ssl_key_file', $httptest) 1004 || array_key_exists('ssl_cert_file', $httptest)) { 1005 if ($method === 'validateCreate') { 1006 $httptest += [ 1007 'ssl_key_password' => '', 1008 'ssl_key_file' => '', 1009 'ssl_cert_file' => '' 1010 ]; 1011 } 1012 else { 1013 $db_httptest = $db_httptests[$httptest['httptestid']]; 1014 $httptest += [ 1015 'ssl_key_password' => $db_httptest['ssl_key_password'], 1016 'ssl_key_file' => $db_httptest['ssl_key_file'], 1017 'ssl_cert_file' => $db_httptest['ssl_cert_file'] 1018 ]; 1019 } 1020 1021 if ($httptest['ssl_key_password'] != '' && $httptest['ssl_key_file'] == '') { 1022 self::exception(ZBX_API_ERROR_PARAMETERS, 1023 _s('Empty SSL key file for web scenario "%1$s".', $httptest['name']) 1024 ); 1025 } 1026 1027 if ($httptest['ssl_key_file'] != '' && $httptest['ssl_cert_file'] == '') { 1028 self::exception(ZBX_API_ERROR_PARAMETERS, 1029 _s('Empty SSL certificate file for web scenario "%1$s".', $httptest['name']) 1030 ); 1031 } 1032 } 1033 } 1034 unset($httptest); 1035 } 1036 1037 /** 1038 * @param array $httptests 1039 * @param string $method 1040 * @param array $db_httptests 1041 * 1042 * @throws APIException if parameters is invalid. 1043 */ 1044 private function validateRetrieveMode(array &$httptests, $method, array $db_httptests = null) { 1045 foreach ($httptests as &$httptest) { 1046 if (!array_key_exists('steps', $httptest)) { 1047 continue; 1048 } 1049 1050 foreach ($httptest['steps'] as &$httpstep) { 1051 if (array_key_exists('retrieve_mode', $httpstep) 1052 || array_key_exists('posts', $httpstep) 1053 || array_key_exists('required', $httpstep)) { 1054 1055 if ($method === 'validateCreate' || !array_key_exists('httpstepid', $httpstep)) { 1056 $httpstep += [ 1057 'retrieve_mode' => HTTPTEST_STEP_RETRIEVE_MODE_CONTENT, 1058 'posts' => '', 1059 'required' => '' 1060 ]; 1061 } 1062 else { 1063 $db_httptest = $db_httptests[$httptest['httptestid']]; 1064 $db_httpstep = $db_httptest['steps'][$httpstep['httpstepid']]; 1065 $httpstep += [ 1066 'retrieve_mode' => $db_httpstep['retrieve_mode'], 1067 'required' => $db_httpstep['required'], 1068 'posts' => ($db_httpstep['retrieve_mode'] != HTTPTEST_STEP_RETRIEVE_MODE_HEADERS) 1069 ? $db_httpstep['posts'] 1070 : '' 1071 ]; 1072 } 1073 1074 if ($httpstep['retrieve_mode'] == HTTPTEST_STEP_RETRIEVE_MODE_HEADERS) { 1075 if ($httpstep['posts'] !== '' && $httpstep['posts'] !== []) { 1076 $field_name = $httpstep['required'] !== '' ? 'required' : 'posts'; 1077 1078 self::exception(ZBX_API_ERROR_PARAMETERS, 1079 _s('Incorrect value for field "%1$s": %2$s.', 'posts', _('should be empty')) 1080 ); 1081 } 1082 } 1083 } 1084 } 1085 unset($httpstep); 1086 } 1087 unset($httptest); 1088 } 1089} 1090