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 media types. 24 */ 25class CMediatype extends CApiService { 26 27 protected $tableName = 'media_type'; 28 protected $tableAlias = 'mt'; 29 protected $sortColumns = ['mediatypeid']; 30 31 /** 32 * Get Media types data 33 * 34 * @param array $options 35 * @param array $options['mediatypeids'] filter by Mediatype IDs 36 * @param boolean $options['type'] filter by Mediatype type [ USER_TYPE_ZABBIX_USER: 1, USER_TYPE_ZABBIX_ADMIN: 2, USER_TYPE_SUPER_ADMIN: 3 ] 37 * @param boolean $options['output'] output only Mediatype IDs if not set. 38 * @param boolean $options['count'] output only count of objects in result. ( result returned in property 'rowscount' ) 39 * @param string $options['pattern'] filter by Host name containing only give pattern 40 * @param int $options['limit'] output will be limited to given number 41 * @param string $options['sortfield'] output will be sorted by given property [ 'mediatypeid', 'alias' ] 42 * @param string $options['sortorder'] output will be sorted in given order [ 'ASC', 'DESC' ] 43 * @return array 44 */ 45 public function get($options = []) { 46 $result = []; 47 48 $sqlParts = [ 49 'select' => ['media_type' => 'mt.mediatypeid'], 50 'from' => ['media_type' => 'media_type mt'], 51 'where' => [], 52 'group' => [], 53 'order' => [], 54 'limit' => null 55 ]; 56 57 $defOptions = [ 58 'mediatypeids' => null, 59 'mediaids' => null, 60 'userids' => null, 61 'editable' => false, 62 // filter 63 'filter' => null, 64 'search' => null, 65 'searchByAny' => null, 66 'startSearch' => false, 67 'excludeSearch' => false, 68 'searchWildcardsEnabled' => null, 69 // output 70 'output' => API_OUTPUT_EXTEND, 71 'selectMessageTemplates' => null, 72 'selectUsers' => null, 73 'countOutput' => false, 74 'groupCount' => false, 75 'preservekeys' => false, 76 'sortfield' => '', 77 'sortorder' => '', 78 'limit' => null 79 ]; 80 $options = zbx_array_merge($defOptions, $options); 81 82 // permission check 83 if (self::$userData['type'] == USER_TYPE_SUPER_ADMIN) { 84 } 85 elseif (!$options['editable'] && self::$userData['type'] == USER_TYPE_ZABBIX_ADMIN) { 86 } 87 elseif ($options['editable'] || self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 88 return []; 89 } 90 91 // mediatypeids 92 if (!is_null($options['mediatypeids'])) { 93 zbx_value2array($options['mediatypeids']); 94 $sqlParts['where'][] = dbConditionInt('mt.mediatypeid', $options['mediatypeids']); 95 } 96 97 // mediaids 98 if (!is_null($options['mediaids'])) { 99 zbx_value2array($options['mediaids']); 100 101 $sqlParts['from']['media'] = 'media m'; 102 $sqlParts['where'][] = dbConditionInt('m.mediaid', $options['mediaids']); 103 $sqlParts['where']['mmt'] = 'm.mediatypeid=mt.mediatypeid'; 104 } 105 106 // userids 107 if (!is_null($options['userids'])) { 108 zbx_value2array($options['userids']); 109 110 $sqlParts['from']['media'] = 'media m'; 111 $sqlParts['where'][] = dbConditionInt('m.userid', $options['userids']); 112 $sqlParts['where']['mmt'] = 'm.mediatypeid=mt.mediatypeid'; 113 } 114 115 // filter 116 if (is_array($options['filter'])) { 117 $this->dbFilter('media_type mt', $options, $sqlParts); 118 } 119 120 // search 121 if (is_array($options['search'])) { 122 zbx_db_search('media_type mt', $options, $sqlParts); 123 } 124 125 // limit 126 if (zbx_ctype_digit($options['limit']) && $options['limit']) { 127 $sqlParts['limit'] = $options['limit']; 128 } 129 130 $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); 131 $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); 132 $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); 133 while ($mediatype = DBfetch($res)) { 134 if ($options['countOutput']) { 135 if ($options['groupCount']) { 136 $result[] = $mediatype; 137 } 138 else { 139 $result = $mediatype['rowscount']; 140 } 141 } 142 else { 143 $result[$mediatype['mediatypeid']] = $mediatype; 144 } 145 } 146 147 if ($options['countOutput']) { 148 return $result; 149 } 150 151 if ($result) { 152 $result = $this->addRelatedObjects($options, $result); 153 } 154 155 // removing keys (hash -> array) 156 if (!$options['preservekeys']) { 157 $result = zbx_cleanHashes($result); 158 } 159 return $result; 160 } 161 162 /** 163 * Validates the input parameters for the create() method. 164 * 165 * @param array $mediatypes 166 * 167 * @throws APIException if the input is invalid. 168 */ 169 protected function validateCreate(array $mediatypes) { 170 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 171 self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can create media types.')); 172 } 173 174 if (!$mediatypes) { 175 self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.')); 176 } 177 178 $required_fields = ['type', 'name']; 179 180 foreach ($mediatypes as $mediatype) { 181 if (!is_array($mediatype)) { 182 self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.')); 183 } 184 185 // Check required parameters. 186 $missing_keys = array_diff($required_fields, array_keys($mediatype)); 187 188 if ($missing_keys) { 189 self::exception(ZBX_API_ERROR_PARAMETERS, 190 _s('Media type is missing parameters: %1$s', implode(', ', $missing_keys)) 191 ); 192 } 193 else { 194 foreach ($required_fields as $field) { 195 if ($mediatype[$field] === '' || $mediatype[$field] === null) { 196 self::exception(ZBX_API_ERROR_PARAMETERS, 197 _s('Field "%1$s" is missing a value for media type "%2$s".', $field, $mediatype['name']) 198 ); 199 } 200 } 201 } 202 } 203 204 // Check for duplicate names. 205 $duplicate_name = CArrayHelper::findDuplicate($mediatypes, 'name'); 206 if ($duplicate_name) { 207 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Media type "%1$s" already exists.', $duplicate_name['name'])); 208 } 209 210 $simple_interval_parser = new CSimpleIntervalParser(); 211 212 foreach ($mediatypes as $i => $mediatype) { 213 // Check if media type already exists. 214 $db_mediatype = API::getApiService()->select('media_type', [ 215 'output' => ['name'], 216 'filter' => ['name' => $mediatype['name']], 217 'limit' => 1 218 ]); 219 220 if ($db_mediatype) { 221 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Media type "%1$s" already exists.', $mediatype['name'])); 222 } 223 224 // Check additional fields and values depending on media type. 225 $this->checkRequiredFieldsByType($mediatype); 226 227 switch ($mediatype['type']) { 228 case MEDIA_TYPE_EMAIL: 229 if (array_key_exists('smtp_authentication', $mediatype)) { 230 $smtp_authentication_validator = new CLimitedSetValidator([ 231 'values' => [SMTP_AUTHENTICATION_NONE, SMTP_AUTHENTICATION_NORMAL] 232 ]); 233 234 if (!$smtp_authentication_validator->validate($mediatype['smtp_authentication'])) { 235 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 236 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 237 $mediatype['smtp_authentication'], 238 'smtp_authentication', 239 $mediatype['name'] 240 )); 241 } 242 } 243 244 // Validate optional 'smtp_port' field. 245 if (array_key_exists('smtp_port', $mediatype) && !validatePortNumber($mediatype['smtp_port'])) { 246 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 247 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 248 $mediatype['smtp_port'], 249 'smtp_port', 250 $mediatype['name'] 251 )); 252 } 253 254 // Validate optional field 'smtp_security'. 255 if (array_key_exists('smtp_security', $mediatype)) { 256 $smtp_security_validator = new CLimitedSetValidator([ 257 'values' => [ 258 SMTP_CONNECTION_SECURITY_NONE, 259 SMTP_CONNECTION_SECURITY_STARTTLS, 260 SMTP_CONNECTION_SECURITY_SSL_TLS 261 ] 262 ]); 263 264 if (!$smtp_security_validator->validate($mediatype['smtp_security'])) { 265 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 266 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 267 $mediatype['smtp_security'], 268 'smtp_security', 269 $mediatype['name'] 270 )); 271 } 272 } 273 274 // Validate optional field 'smtp_verify_peer'. 275 if (array_key_exists('smtp_verify_peer', $mediatype)) { 276 $smtp_verify_peer_validator = new CLimitedSetValidator([ 277 'values' => [0, 1] 278 ]); 279 280 if (!$smtp_verify_peer_validator->validate($mediatype['smtp_verify_peer'])) { 281 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 282 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 283 $mediatype['smtp_verify_peer'], 284 'smtp_verify_peer', 285 $mediatype['name'] 286 )); 287 } 288 } 289 290 // Validate optional field 'smtp_verify_host'. 291 if (array_key_exists('smtp_verify_host', $mediatype)) { 292 $smtp_verify_host_validator = new CLimitedSetValidator([ 293 'values' => [0, 1] 294 ]); 295 296 if (!$smtp_verify_host_validator->validate($mediatype['smtp_verify_host'])) { 297 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 298 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 299 $mediatype['smtp_verify_host'], 300 'smtp_verify_host', 301 $mediatype['name'] 302 )); 303 } 304 } 305 306 // Validate optional field 'content_type'. 307 if (array_key_exists('content_type', $mediatype)) { 308 $content_type_validator = new CLimitedSetValidator([ 309 'values' => [ 310 SMTP_MESSAGE_FORMAT_PLAIN_TEXT, 311 SMTP_MESSAGE_FORMAT_HTML 312 ] 313 ]); 314 315 if (!$content_type_validator->validate($mediatype['content_type'])) { 316 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 317 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 318 $mediatype['content_type'], 319 'content_type', 320 $mediatype['name'] 321 )); 322 } 323 } 324 break; 325 326 case MEDIA_TYPE_EXEC: 327 if (array_key_exists('exec_params', $mediatype) && $mediatype['exec_params'] !== '') { 328 $pos = strrpos($mediatype['exec_params'], "\n"); 329 330 if ($pos === false || strlen($mediatype['exec_params']) != $pos + 1) { 331 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 332 'Script parameters "%1$s" are missing the last new line feed for media type "%2$s".', 333 $mediatype['exec_params'], 334 $mediatype['name'] 335 )); 336 } 337 } 338 break; 339 } 340 341 $api_input_rules = $this->getValidationRules($mediatype['type'], 'create'); 342 $validated_data = array_intersect_key($mediatype, $api_input_rules['fields']); 343 344 if (!CApiInputValidator::validate($api_input_rules, $validated_data, '/'.($i + 1), $error)) { 345 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 346 } 347 $mediatype = $validated_data + $mediatype; 348 349 // Validate optional 'status' field. 350 if (array_key_exists('status', $mediatype)) { 351 $status_validator = new CLimitedSetValidator([ 352 'values' => [MEDIA_TYPE_STATUS_ACTIVE, MEDIA_TYPE_STATUS_DISABLED] 353 ]); 354 355 if (!$status_validator->validate($mediatype['status'])) { 356 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 357 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 358 $mediatype['status'], 359 'status', 360 $mediatype['name'] 361 )); 362 } 363 } 364 365 // Validate optional 'maxsessions' field. 366 if (array_key_exists('maxsessions', $mediatype)) { 367 if ($mediatype['maxsessions'] === '') { 368 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 369 'maxsessions', _('cannot be empty') 370 )); 371 } 372 373 $min = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 0; 374 $max = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 100; 375 376 if (!ctype_digit((string) $mediatype['maxsessions']) || $mediatype['maxsessions'] > $max 377 || $mediatype['maxsessions'] < $min) { 378 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 379 'maxsessions', _s('must be between "%1$s" and "%2$s"', $min, $max) 380 )); 381 } 382 } 383 384 // Validate optional 'maxattempts' field. 385 if (array_key_exists('maxattempts', $mediatype)) { 386 if ($mediatype['maxattempts'] === '') { 387 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 388 'maxattempts', _('cannot be empty') 389 )); 390 } 391 392 if (!ctype_digit((string) $mediatype['maxattempts']) || $mediatype['maxattempts'] > 100 393 || $mediatype['maxattempts'] < 1) { 394 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 395 'maxattempts', _s('must be between "%1$s" and "%2$s"', 1, 100) 396 )); 397 } 398 } 399 400 // Validate optional 'attempt_interval' field. 401 if (array_key_exists('attempt_interval', $mediatype)) { 402 if ($mediatype['attempt_interval'] === '') { 403 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 404 'attempt_interval', _('cannot be empty') 405 )); 406 } 407 408 if ($simple_interval_parser->parse($mediatype['attempt_interval']) == CParser::PARSE_SUCCESS) { 409 $attempt_interval = timeUnitToSeconds($mediatype['attempt_interval']); 410 411 if ($attempt_interval < 0 || $attempt_interval > 3600) { 412 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 413 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 3600) 414 )); 415 } 416 } 417 else { 418 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 419 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 3600) 420 )); 421 } 422 } 423 } 424 } 425 426 /** 427 * Validates the input parameters for the update() method. 428 * 429 * @param array $mediatypes 430 * 431 * @throws APIException if the input is invalid. 432 */ 433 protected function validateUpdate(array $mediatypes) { 434 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 435 self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can edit media types.')); 436 } 437 438 if (!$mediatypes) { 439 self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.')); 440 } 441 442 // Validate given IDs. 443 $this->checkObjectIds($mediatypes, 'mediatypeid', 444 _('No "%1$s" given for media type.'), 445 _('Empty media type ID.'), 446 _('Incorrect media type ID.') 447 ); 448 449 $mediatypeids = zbx_objectValues($mediatypes, 'mediatypeid'); 450 451 // Check value map names. 452 $db_mediatypes = API::getApiService()->select('media_type', [ 453 'output' => ['mediatypeid', 'type', 'name', 'exec_path', 'status', 'smtp_port', 'smtp_verify_peer', 454 'smtp_verify_host', 'smtp_authentication', 'maxsessions', 'maxattempts', 'attempt_interval', 455 'content_type', 'script', 'timeout', 'process_tags', 'show_event_menu', 'event_menu_url', 456 'event_menu_name' 457 ], 458 'mediatypeids' => $mediatypeids, 459 'preservekeys' => true 460 ]); 461 462 $check_names = []; 463 $simple_interval_parser = new CSimpleIntervalParser(); 464 465 foreach ($mediatypes as $mediatype) { 466 // Check if this media type exists. 467 if (!array_key_exists($mediatype['mediatypeid'], $db_mediatypes)) { 468 self::exception(ZBX_API_ERROR_PERMISSIONS, 469 _('No permissions to referred object or it does not exist!') 470 ); 471 } 472 473 // Validate "name" field. 474 if (array_key_exists('name', $mediatype)) { 475 if (is_array($mediatype['name'])) { 476 self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.')); 477 } 478 elseif ($mediatype['name'] === '' || $mediatype['name'] === null || $mediatype['name'] === false) { 479 self::exception(ZBX_API_ERROR_PARAMETERS, 480 _s('Incorrect value for field "%1$s": %2$s.', 'name', _('cannot be empty')) 481 ); 482 } 483 484 $check_names[$mediatype['name']] = true; 485 } 486 } 487 488 if ($check_names) { 489 $db_mediatype_names = API::getApiService()->select('media_type', [ 490 'output' => ['mediatypeid', 'name'], 491 'filter' => ['name' => array_keys($check_names)] 492 ]); 493 $db_mediatype_names = zbx_toHash($db_mediatype_names, 'name'); 494 495 foreach ($mediatypes as $mediatype) { 496 if (array_key_exists('name', $mediatype) 497 && array_key_exists($mediatype['name'], $db_mediatype_names) 498 && !idcmp($db_mediatype_names[$mediatype['name']]['mediatypeid'], $mediatype['mediatypeid'])) { 499 self::exception(ZBX_API_ERROR_PARAMETERS, 500 _s('Media type "%1$s" already exists.', $mediatype['name']) 501 ); 502 } 503 } 504 } 505 506 // Populate "name" field, if not set. Type field should not be populated at this point. 507 $mediatypes = $this->extendFromObjects(zbx_toHash($mediatypes, 'mediatypeid'), $db_mediatypes, ['name']); 508 509 $duplicate_name = CArrayHelper::findDuplicate($mediatypes, 'name'); 510 if ($duplicate_name) { 511 self::exception(ZBX_API_ERROR_PARAMETERS, 512 _s('Media type "%1$s" already exists.', $duplicate_name['name']) 513 ); 514 } 515 516 $i = 0; 517 foreach ($mediatypes as $mediatype) { 518 $i++; 519 $db_mediatype = $db_mediatypes[$mediatype['mediatypeid']]; 520 521 // Recheck mandatory fields if type changed. 522 if (array_key_exists('type', $mediatype) && $db_mediatype['type'] != $mediatype['type']) { 523 $this->checkRequiredFieldsByType($mediatype); 524 } 525 else { 526 $optional_fields_by_type = [ 527 MEDIA_TYPE_EMAIL => ['smtp_server', 'smtp_helo', 'smtp_email'], 528 MEDIA_TYPE_EXEC => ['exec_path'], 529 MEDIA_TYPE_WEBHOOK => [], 530 MEDIA_TYPE_SMS => ['gsm_modem'] 531 ]; 532 533 foreach ($optional_fields_by_type[$db_mediatype['type']] as $field) { 534 if (array_key_exists($field, $mediatype) 535 && ($mediatype[$field] === '' || $mediatype[$field] === null)) { 536 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 537 'Field "%1$s" is missing a value for media type "%2$s".', 538 $field, 539 $mediatype['name'] 540 )); 541 } 542 } 543 544 // Populate "type" field from DB, since it is not set and is required for further validation. 545 $mediatype['type'] = $db_mediatype['type']; 546 } 547 548 switch ($mediatype['type']) { 549 case MEDIA_TYPE_EMAIL: 550 if (array_key_exists('smtp_authentication', $mediatype)) { 551 $smtp_authentication_validator = new CLimitedSetValidator([ 552 'values' => [SMTP_AUTHENTICATION_NONE, SMTP_AUTHENTICATION_NORMAL] 553 ]); 554 555 if (!$smtp_authentication_validator->validate($mediatype['smtp_authentication'])) { 556 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 557 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 558 $mediatype['smtp_authentication'], 559 'smtp_authentication', 560 $mediatype['name'] 561 )); 562 } 563 } 564 565 // Validate optional 'smtp_port' field. 566 if (array_key_exists('smtp_port', $mediatype) 567 && $db_mediatype['smtp_port'] != $mediatype['smtp_port'] 568 && !validatePortNumber($mediatype['smtp_port'])) { 569 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 570 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 571 $mediatype['smtp_port'], 572 'smtp_port', 573 $mediatype['name'] 574 )); 575 } 576 577 // Validate optional field 'smtp_security'. 578 if (array_key_exists('smtp_security', $mediatype)) { 579 $smtp_security_validator = new CLimitedSetValidator([ 580 'values' => [ 581 SMTP_CONNECTION_SECURITY_NONE, 582 SMTP_CONNECTION_SECURITY_STARTTLS, 583 SMTP_CONNECTION_SECURITY_SSL_TLS 584 ] 585 ]); 586 587 if (!$smtp_security_validator->validate($mediatype['smtp_security'])) { 588 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 589 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 590 $mediatype['smtp_security'], 591 'smtp_security', 592 $mediatype['name'] 593 )); 594 } 595 } 596 597 // Validate optional field 'smtp_verify_peer'. 598 if (array_key_exists('smtp_verify_peer', $mediatype) 599 && $db_mediatype['smtp_verify_peer'] != $mediatype['smtp_verify_peer']) { 600 $smtp_verify_peer_validator = new CLimitedSetValidator([ 601 'values' => [0, 1] 602 ]); 603 604 if (!$smtp_verify_peer_validator->validate($mediatype['smtp_verify_peer'])) { 605 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 606 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 607 $mediatype['smtp_verify_peer'], 608 'smtp_verify_peer', 609 $mediatype['name'] 610 )); 611 } 612 } 613 614 // Validate optional field 'smtp_verify_host'. 615 if (array_key_exists('smtp_verify_host', $mediatype) 616 && $db_mediatype['smtp_verify_host'] != $mediatype['smtp_verify_host']) { 617 $smtp_verify_host_validator = new CLimitedSetValidator([ 618 'values' => [0, 1] 619 ]); 620 621 if (!$smtp_verify_host_validator->validate($mediatype['smtp_verify_host'])) { 622 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 623 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 624 $mediatype['smtp_verify_host'], 625 'smtp_verify_host', 626 $mediatype['name'] 627 )); 628 } 629 } 630 631 // Validate optional field 'content_type'. 632 if (array_key_exists('content_type', $mediatype) 633 && $db_mediatype['content_type'] != $mediatype['content_type']) { 634 $content_type_validator = new CLimitedSetValidator([ 635 'values' => [ 636 SMTP_MESSAGE_FORMAT_PLAIN_TEXT, 637 SMTP_MESSAGE_FORMAT_HTML 638 ] 639 ]); 640 641 if (!$content_type_validator->validate($mediatype['content_type'])) { 642 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 643 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 644 $mediatype['content_type'], 645 'content_type', 646 $mediatype['name'] 647 )); 648 } 649 } 650 break; 651 652 case MEDIA_TYPE_EXEC: 653 if (array_key_exists('exec_params', $mediatype) && $mediatype['exec_params'] !== '') { 654 $pos = strrpos($mediatype['exec_params'], "\n"); 655 656 if ($pos === false || strlen($mediatype['exec_params']) != $pos + 1) { 657 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 658 'Script parameters "%1$s" are missing the last new line feed for media type "%2$s".', 659 $mediatype['exec_params'], 660 $mediatype['name'] 661 )); 662 } 663 } 664 break; 665 } 666 667 $api_input_rules = $this->getValidationRules($mediatype['type'], 'update'); 668 $validated_data = array_intersect_key($mediatype, $api_input_rules['fields']); 669 670 if (!CApiInputValidator::validate($api_input_rules, $validated_data, '/'.$i, $error)) { 671 self::exception(ZBX_API_ERROR_PARAMETERS, $error); 672 } 673 $mediatype = $validated_data + $mediatype; 674 675 // Validate optional 'status' field and only when status is changed. 676 if (array_key_exists('status', $mediatype) && $db_mediatype['status'] != $mediatype['status']) { 677 $status_validator = new CLimitedSetValidator([ 678 'values' => [MEDIA_TYPE_STATUS_ACTIVE, MEDIA_TYPE_STATUS_DISABLED] 679 ]); 680 681 if (!$status_validator->validate($mediatype['status'])) { 682 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 683 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 684 $mediatype['status'], 685 'status', 686 $mediatype['name'] 687 )); 688 } 689 } 690 691 // Validate optional 'maxsessions' field. 692 if (array_key_exists('maxsessions', $mediatype) 693 && $db_mediatype['maxsessions'] != $mediatype['maxsessions']) { 694 if ($mediatype['maxsessions'] === '') { 695 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 696 'maxsessions', _('cannot be empty') 697 )); 698 } 699 700 $min = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 0; 701 $max = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 100; 702 703 if (!ctype_digit((string) $mediatype['maxsessions']) || $mediatype['maxsessions'] > $max 704 || $mediatype['maxsessions'] < $min) { 705 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 706 'maxsessions', _s('must be between "%1$s" and "%2$s"', $min, $max) 707 )); 708 } 709 } 710 elseif ($mediatype['type'] == MEDIA_TYPE_SMS && $mediatype['type'] != $db_mediatype['type'] 711 && $db_mediatype['maxsessions'] != 1) { 712 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 713 'maxsessions', _s('must be between "%1$s" and "%2$s"', 1, 1) 714 )); 715 } 716 717 // Validate optional 'maxattempts' field. 718 if (array_key_exists('maxattempts', $mediatype) 719 && $db_mediatype['maxattempts'] != $mediatype['maxattempts']) { 720 if ($mediatype['maxattempts'] === '') { 721 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 722 'maxattempts', _('cannot be empty') 723 )); 724 } 725 726 if (!ctype_digit((string) $mediatype['maxattempts']) || $mediatype['maxattempts'] > 100 727 || $mediatype['maxattempts'] < 1) { 728 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 729 'maxattempts', _s('must be between "%1$s" and "%2$s"', 1, 100) 730 )); 731 } 732 } 733 734 // Validate optional 'attempt_interval' field. 735 if (array_key_exists('attempt_interval', $mediatype) 736 && $db_mediatype['attempt_interval'] != $mediatype['attempt_interval']) { 737 if ($mediatype['attempt_interval'] === '') { 738 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 739 'attempt_interval', _('cannot be empty') 740 )); 741 } 742 743 if ($simple_interval_parser->parse($mediatype['attempt_interval']) == CParser::PARSE_SUCCESS) { 744 $attempt_interval = timeUnitToSeconds($mediatype['attempt_interval']); 745 746 if ($attempt_interval < 0 || $attempt_interval > 3600) { 747 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 748 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 3600) 749 )); 750 } 751 } 752 else { 753 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 754 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 3600) 755 )); 756 } 757 } 758 } 759 } 760 761 /** 762 * Validates the event_menu_* input parameters. 763 * 764 * @param array $mediatype 765 * @param array $db_mediatype 766 * 767 * @throws APIException if the input is invalid. 768 */ 769 private function validateEventMenu(array $mediatype, array $db_mediatype = null) { 770 if ($db_mediatype === null) { 771 $db_mediatype = DB::getDefaults('media_type'); 772 } 773 774 foreach (['show_event_menu', 'event_menu_url', 'event_menu_name'] as $field_name) { 775 if (!array_key_exists($field_name, $mediatype)) { 776 $mediatype[$field_name] = $db_mediatype[$field_name]; 777 } 778 } 779 780 foreach (['event_menu_url', 'event_menu_name'] as $field_name) { 781 if ($mediatype['show_event_menu'] == ZBX_EVENT_MENU_HIDE) { 782 if ($mediatype[$field_name] !== '') { 783 self::exception(ZBX_API_ERROR_PARAMETERS, 784 _s('Incorrect value for field "%1$s": %2$s.', $field_name, _('should be empty')) 785 ); 786 } 787 } 788 else { 789 if ($mediatype[$field_name] === '') { 790 self::exception(ZBX_API_ERROR_PARAMETERS, 791 _s('Incorrect value for field "%1$s": %2$s.', $field_name, _('cannot be empty')) 792 ); 793 } 794 } 795 } 796 } 797 798 /** 799 * Add Media types. 800 * 801 * @param array $mediatypes A multidimensional array with media types data. 802 * @param int $mediatypes[]['type'] Transport used by the media type. 803 * @param string $mediatypes[]['name'] Name of the media type. 804 * @param string $mediatypes[]['smtp_server'] SMTP server. 805 * @param int $mediatypes[]['smtp_port'] SMTP server port. 806 * @param string $mediatypes[]['smtp_helo'] SMTP HELO. 807 * @param string $mediatypes[]['smtp_email'] SMTP email. 808 * @param int $mediatypes[]['smtp_security'] SMTP connection security level. 809 * @param int $mediatypes[]['smtp_verify_peer'] SMTP verify peer. 810 * @param int $mediatypes[]['smtp_verify_host'] SMTP verify host. 811 * @param int $mediatypes[]['smtp_authentication'] SMTP authentication. 812 * @param int $mediatypes[]['content_type'] Message format. 813 * @param string $mediatypes[]['exec_path'] Script name. 814 * @param string $mediatypes[]['exec_params'] Script parameters. 815 * @param string $mediatypes[]['gsm_modem'] Serial device name of the GSM modem. 816 * @param string $mediatypes[]['username'] User name used for authentication. 817 * @param string $mediatypes[]['passwd'] Password used for authentication. 818 * @param int $mediatypes[]['status'] Media type status. 819 * @param int $mediatypes[]['maxsessions'] Limit of simultaneously processed alerts. 820 * @param int $mediatypes[]['maxattempts'] Maximum attempts to deliver alert successfully. 821 * @param string $mediatypes[]['attempt_interval'] Interval between alert delivery attempts. 822 * @param string $mediatypes[]['script'] Webhook JavaScript body. 823 * @param array $mediatypes[]['parameters'] An array of webhook parameters: 824 * ['name' => .., 'value' => ..] 825 * @param string $mediatypes[]['timeout'] Webhook JavaScript HTTP request timeout. 826 * @param string $mediatypes[]['process_tags'] Webhook HTTP response should be saved as tags. 827 * @param string $mediatypes[]['show_event_menu'] Indicates presence of entry in event.get "urls" objects list. 828 * @param string $mediatypes[]['event_menu_url'] Webhook additional info in frontend, supports received tags. 829 * @param string $mediatypes[]['event_menu_name'] Webhook 'url' visual name. 830 * @param string $mediatypes[]['description'] Media type description. 831 * @param array $mediatypes[]['message_templates'] An array of media type message templates. 832 * 833 * @return array 834 */ 835 public function create(array $mediatypes) { 836 $mediatypes = zbx_toArray($mediatypes); 837 838 $this->validateCreate($mediatypes); 839 840 $mediatypeids = DB::insert('media_type', $mediatypes); 841 $ins_media_type_param = []; 842 $ins_media_type_message = []; 843 844 foreach ($mediatypes as $i => $mediatype) { 845 $mediatypeid = $mediatypeids[$i]; 846 $mediatypes[$i]['mediatypeid'] = $mediatypeid; 847 848 if ($mediatype['type'] == MEDIA_TYPE_WEBHOOK) { 849 if (array_key_exists('parameters', $mediatype)) { 850 foreach ($mediatype['parameters'] as $parameter) { 851 $ins_media_type_param[] = ['mediatypeid' => $mediatypeid] + $parameter; 852 } 853 } 854 855 $this->validateEventMenu($mediatype); 856 } 857 858 if (array_key_exists('message_templates', $mediatype)) { 859 foreach ($mediatype['message_templates'] as $message_template) { 860 $ins_media_type_message[] = ['mediatypeid' => $mediatypeid] + $message_template; 861 } 862 } 863 } 864 865 if ($ins_media_type_param) { 866 DB::insertBatch('media_type_param', $ins_media_type_param); 867 } 868 869 if ($ins_media_type_message) { 870 DB::insert('media_type_message', $ins_media_type_message); 871 } 872 873 $this->addAuditBulk(AUDIT_ACTION_ADD, AUDIT_RESOURCE_MEDIA_TYPE, $mediatypes); 874 875 return ['mediatypeids' => $mediatypeids]; 876 } 877 878 /** 879 * Update Media types. 880 * 881 * @param array $mediatypes A multidimensional array with media types data. 882 * @param int $mediatypes[]['mediatypeid'] Media type ID. 883 * @param int $mediatypes[]['type'] Transport used by the media type. 884 * @param string $mediatypes[]['name'] Name of the media type. 885 * @param string $mediatypes[]['smtp_server'] SMTP server. 886 * @param int $mediatypes[]['smtp_port'] SMTP server port. 887 * @param string $mediatypes[]['smtp_helo'] SMTP HELO. 888 * @param string $mediatypes[]['smtp_email'] SMTP email. 889 * @param int $mediatypes[]['smtp_security'] SMTP connection security level. 890 * @param int $mediatypes[]['smtp_verify_peer'] SMTP verify peer. 891 * @param int $mediatypes[]['smtp_verify_host'] SMTP verify host. 892 * @param int $mediatypes[]['smtp_authentication'] SMTP authentication. 893 * @param int $mediatypes[]['content_type'] Message format. 894 * @param string $mediatypes[]['exec_path'] Script name. 895 * @param string $mediatypes[]['exec_params'] Script parameters. 896 * @param string $mediatypes[]['gsm_modem'] Serial device name of the GSM modem. 897 * @param string $mediatypes[]['username'] User name used for authentication. 898 * @param string $mediatypes[]['passwd'] Password used for authentication. 899 * @param int $mediatypes[]['status'] Media type status. 900 * @param int $mediatypes[]['maxsessions'] Limit of simultaneously processed alerts. 901 * @param int $mediatypes[]['maxattempts'] Maximum attempts to deliver alert successfully. 902 * @param string $mediatypes[]['attempt_interval'] Interval between alert delivery attempts. 903 * @param string $mediatypes[]['script'] Webhook JavaScript body. 904 * @param array $mediatypes[]['parameters'] An array of webhook parameters: 905 * ['name' => .., 'value' => ..] 906 * @param string $mediatypes[]['timeout'] Webhook JavaScript HTTP request timeout. 907 * @param string $mediatypes[]['process_tags'] Webhook HTTP response should be saved as tags. 908 * @param string $mediatypes[]['show_event_menu'] Indicates presence of entry in event.get "urls" objects list. 909 * @param string $mediatypes[]['event_menu_url'] Webhook additional info in frontend, supports received tags. 910 * @param string $mediatypes[]['event_menu_name'] Webhook 'url' visual name. 911 * @param string $mediatypes[]['description'] Media type description. 912 * @param array $mediatypes[]['message_templates'] An array of media type message templates. 913 * 914 * @return array 915 */ 916 public function update(array $mediatypes) { 917 $mediatypes = zbx_toArray($mediatypes); 918 919 $this->validateUpdate($mediatypes); 920 921 $update = []; 922 $webhooks_params = []; 923 $message_templates = []; 924 $default_values = DB::getDefaults('media_type'); 925 $db_mediatypes = DB::select('media_type', [ 926 'output' => ['mediatypeid', 'type', 'name', 'smtp_server', 'smtp_helo', 'smtp_email', 'exec_path', 927 'gsm_modem', 'username', 'passwd', 'status', 'smtp_port', 'smtp_security', 'smtp_verify_peer', 928 'smtp_verify_host', 'smtp_authentication', 'exec_params', 'maxsessions', 'maxattempts', 929 'attempt_interval', 'content_type', 'script', 'timeout', 'process_tags', 'show_event_menu', 930 'event_menu_url', 'event_menu_name', 'description' 931 ], 932 'filter' => ['mediatypeid' => zbx_objectValues($mediatypes, 'mediatypeid')], 933 'preservekeys' => true 934 ]); 935 936 $type_switch_fields = [ 937 MEDIA_TYPE_EMAIL => [ 938 'smtp_server', 'smtp_helo', 'smtp_email', 'smtp_port', 'smtp_security', 'smtp_verify_peer', 939 'smtp_verify_host', 'smtp_authentication', 'passwd', 'username', 'content_type' 940 ], 941 MEDIA_TYPE_EXEC => [ 942 'exec_path', 'exec_params' 943 ], 944 MEDIA_TYPE_SMS => [ 945 'gsm_modem' 946 ], 947 MEDIA_TYPE_WEBHOOK => [ 948 'script', 'timeout', 'process_tags', 'show_event_menu', 'event_menu_url', 'event_menu_name', 'parameters' 949 ] 950 ]; 951 $default_values['parameters'] = []; 952 953 foreach ($mediatypes as $mediatype) { 954 $mediatypeid = $mediatype['mediatypeid']; 955 $db_mediatype = $db_mediatypes[$mediatypeid]; 956 $db_type = $db_mediatype['type']; 957 $type = array_key_exists('type', $mediatype) ? $mediatype['type'] : $db_type; 958 unset($mediatype['mediatypeid']); 959 960 if ($type == MEDIA_TYPE_WEBHOOK) { 961 if (array_key_exists('parameters', $mediatype)) { 962 $params = []; 963 964 foreach ($mediatype['parameters'] as $param) { 965 $params[$param['name']] = $param['value']; 966 }; 967 968 $webhooks_params[$mediatypeid] = $params; 969 unset($mediatype['parameters']); 970 } 971 972 if (array_key_exists('show_event_menu', $mediatype) 973 && $mediatype['show_event_menu'] == ZBX_EVENT_MENU_HIDE) { 974 $mediatype += ['event_menu_url' => '', 'event_menu_name' => '']; 975 } 976 977 $this->validateEventMenu($mediatype, $db_mediatype); 978 } 979 else if ($db_type == MEDIA_TYPE_WEBHOOK) { 980 $webhooks_params[$mediatypeid] = []; 981 } 982 983 if (array_key_exists('message_templates', $mediatype)) { 984 $message_templates[$mediatypeid] = $mediatype['message_templates']; 985 unset($mediatype['message_templates']); 986 } 987 988 if ($type != $db_type) { 989 $mediatype = array_intersect_key($default_values, 990 array_fill_keys($type_switch_fields[$db_type], '')) + $mediatype; 991 } 992 993 if (!empty($mediatype)) { 994 $update[] = [ 995 'values' => $mediatype, 996 'where' => ['mediatypeid' => $mediatypeid] 997 ]; 998 } 999 } 1000 1001 DB::update('media_type', $update); 1002 $mediatypeids = zbx_objectValues($mediatypes, 'mediatypeid'); 1003 1004 if ($webhooks_params) { 1005 $ins_media_type_param = []; 1006 $del_media_type_param = []; 1007 $upd_media_type_param = []; 1008 $db_webhooks_params = DB::select('media_type_param', [ 1009 'output' => ['mediatype_paramid', 'mediatypeid', 'name', 'value'], 1010 'filter' => ['mediatypeid' => array_keys($webhooks_params)] 1011 ]); 1012 1013 foreach ($db_webhooks_params as $param) { 1014 $mediatypeid = $param['mediatypeid']; 1015 1016 if (!array_key_exists($param['name'], $webhooks_params[$mediatypeid])) { 1017 $del_media_type_param[] = $param['mediatype_paramid']; 1018 } 1019 elseif ($webhooks_params[$mediatypeid][$param['name']] !== $param['value']) { 1020 $upd_media_type_param[] = [ 1021 'values' => ['value' => $webhooks_params[$mediatypeid][$param['name']]], 1022 'where' => ['mediatype_paramid' => $param['mediatype_paramid']] 1023 ]; 1024 unset($webhooks_params[$mediatypeid][$param['name']]); 1025 } 1026 else { 1027 unset($webhooks_params[$mediatypeid][$param['name']]); 1028 } 1029 } 1030 1031 $webhooks_params = array_filter($webhooks_params); 1032 1033 foreach ($webhooks_params as $mediatypeid => $params) { 1034 foreach ($params as $name => $value) { 1035 $ins_media_type_param[] = compact('mediatypeid', 'name', 'value'); 1036 } 1037 } 1038 1039 if ($del_media_type_param) { 1040 DB::delete('media_type_param', ['mediatype_paramid' => array_keys(array_flip($del_media_type_param))]); 1041 } 1042 1043 if ($upd_media_type_param) { 1044 DB::update('media_type_param', $upd_media_type_param); 1045 } 1046 1047 if ($ins_media_type_param) { 1048 DB::insert('media_type_param', $ins_media_type_param); 1049 } 1050 } 1051 1052 if ($message_templates) { 1053 $db_media_type_messages = DB::select('media_type_message', [ 1054 'output' => ['mediatype_messageid', 'mediatypeid', 'eventsource', 'recovery', 'subject', 'message'], 1055 'filter' => ['mediatypeid' => array_keys($message_templates)], 1056 'preservekeys' => true 1057 ]); 1058 1059 $ins_media_type_message = []; 1060 $del_media_type_message = zbx_toHash(array_keys($db_media_type_messages)); 1061 $upd_media_type_message = []; 1062 1063 $message_template_defaults = [ 1064 'subject' => DB::getDefault('media_type_message', 'subject'), 1065 'message' => DB::getDefault('media_type_message', 'message') 1066 ]; 1067 1068 foreach ($db_media_type_messages as $mediatype_messageid => $db_message_template) { 1069 $db_mediatypeid = $db_message_template['mediatypeid']; 1070 1071 foreach ($message_templates[$db_mediatypeid] as $idx => $message_template) { 1072 if ($db_message_template['eventsource'] == $message_template['eventsource'] 1073 && $db_message_template['recovery'] == $message_template['recovery']) { 1074 $values = []; 1075 $message_template += $message_template_defaults; 1076 1077 if ($db_message_template['subject'] !== $message_template['subject']) { 1078 $values['subject'] = $message_template['subject']; 1079 } 1080 1081 if ($db_message_template['message'] !== $message_template['message']) { 1082 $values['message'] = $message_template['message']; 1083 } 1084 1085 if ($values) { 1086 $upd_media_type_message[] = [ 1087 'values' => $values, 1088 'where' => ['mediatype_messageid' => $mediatype_messageid] 1089 ]; 1090 } 1091 1092 unset($message_templates[$db_mediatypeid][$idx], $del_media_type_message[$mediatype_messageid]); 1093 } 1094 } 1095 } 1096 1097 foreach ($message_templates as $mediatypeid => $templates) { 1098 foreach ($templates as $template) { 1099 $ins_media_type_message[] = ['mediatypeid' => $mediatypeid] + $template; 1100 } 1101 } 1102 1103 if ($del_media_type_message) { 1104 DB::delete('media_type_message', ['mediatype_messageid' => $del_media_type_message]); 1105 } 1106 1107 if ($upd_media_type_message) { 1108 DB::update('media_type_message', $upd_media_type_message); 1109 } 1110 1111 if ($ins_media_type_message) { 1112 DB::insert('media_type_message', $ins_media_type_message); 1113 } 1114 } 1115 1116 $this->addAuditBulk(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_MEDIA_TYPE, $mediatypes, $db_mediatypes); 1117 1118 return ['mediatypeids' => $mediatypeids]; 1119 } 1120 1121 /** 1122 * Delete Media types. 1123 * 1124 * @param array $mediatypeids 1125 * 1126 * @return array 1127 */ 1128 public function delete(array $mediatypeids) { 1129 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 1130 self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can delete media types.')); 1131 } 1132 1133 $actions = API::Action()->get([ 1134 'mediatypeids' => $mediatypeids, 1135 'output' => API_OUTPUT_EXTEND, 1136 'preservekeys' => true 1137 ]); 1138 if (!empty($actions)) { 1139 $action = reset($actions); 1140 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Media types used by action "%1$s".', $action['name'])); 1141 } 1142 1143 $db_mediatypes = DB::select('media_type', [ 1144 'output' => ['mediatypeid', 'name'], 1145 'mediatypeids' => $mediatypeids, 1146 'preservekeys' => true 1147 ]); 1148 1149 DB::delete('media_type', ['mediatypeid' => $mediatypeids]); 1150 1151 $this->addAuditBulk(AUDIT_ACTION_DELETE, AUDIT_RESOURCE_MEDIA_TYPE, $db_mediatypes); 1152 1153 return ['mediatypeids' => $mediatypeids]; 1154 } 1155 1156 /** 1157 * Check required fields by type. Values for fields must not be empty. 1158 * 1159 * @param array $mediatype An array of media type data. 1160 * @param string $mediatype['name'] Name of the media type. 1161 * @param string $mediatype['type'] E-mail, Script and SMS. 1162 * 1163 * @throws APIException if the input is invalid. 1164 */ 1165 protected function checkRequiredFieldsByType(array $mediatype) { 1166 $type_validator = new CLimitedSetValidator([ 1167 'values' => array_keys(media_type2str()) 1168 ]); 1169 1170 if (!$type_validator->validate($mediatype['type'])) { 1171 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 1172 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 1173 $mediatype['type'], 1174 'type', 1175 $mediatype['name'] 1176 )); 1177 } 1178 1179 $required_fields_by_type = [ 1180 MEDIA_TYPE_EMAIL => ['smtp_server', 'smtp_helo', 'smtp_email'], 1181 MEDIA_TYPE_EXEC => ['exec_path'], 1182 MEDIA_TYPE_WEBHOOK => [], 1183 MEDIA_TYPE_SMS => ['gsm_modem'] 1184 ]; 1185 1186 foreach ($required_fields_by_type[$mediatype['type']] as $field) { 1187 // Check if fields set on Create method. For update method they are checked when type is changed. 1188 if (!array_key_exists($field, $mediatype)) { 1189 self::exception(ZBX_API_ERROR_PARAMETERS, 1190 _s('Field "%1$s" is required for media type "%2$s".', $field, $mediatype['name']) 1191 ); 1192 } 1193 elseif (array_key_exists($field, $mediatype) 1194 && ($mediatype[$field] === '' || $mediatype[$field] === null)) { 1195 self::exception(ZBX_API_ERROR_PARAMETERS, 1196 _s('Field "%1$s" is missing a value for media type "%2$s".', $field, $mediatype['name']) 1197 ); 1198 } 1199 } 1200 } 1201 1202 protected function addRelatedObjects(array $options, array $result) { 1203 $result = parent::addRelatedObjects($options, $result); 1204 1205 // adding message templates 1206 if ($options['selectMessageTemplates'] !== null && $options['selectMessageTemplates'] != API_OUTPUT_COUNT) { 1207 $message_templates = []; 1208 $relation_map = $this->createRelationMap($result, 'mediatypeid', 'mediatype_messageid', 1209 'media_type_message' 1210 ); 1211 $related_ids = $relation_map->getRelatedIds(); 1212 1213 if ($related_ids) { 1214 $message_templates = API::getApiService()->select('media_type_message', [ 1215 'output' => $options['selectMessageTemplates'], 1216 'mediatype_messageids' => $related_ids, 1217 'preservekeys' => true 1218 ]); 1219 $message_templates = $this->unsetExtraFields($message_templates, ['mediatype_messageid', 'mediatypeid'], 1220 [] 1221 ); 1222 } 1223 1224 $result = $relation_map->mapMany($result, $message_templates, 'message_templates'); 1225 } 1226 1227 // adding users 1228 if ($options['selectUsers'] !== null && $options['selectUsers'] != API_OUTPUT_COUNT) { 1229 $users = []; 1230 $relationMap = $this->createRelationMap($result, 'mediatypeid', 'userid', 'media'); 1231 $related_ids = $relationMap->getRelatedIds(); 1232 1233 if ($related_ids) { 1234 $users = API::User()->get([ 1235 'output' => $options['selectUsers'], 1236 'userids' => $related_ids, 1237 'preservekeys' => true 1238 ]); 1239 } 1240 1241 $result = $relationMap->mapMany($result, $users, 'users'); 1242 } 1243 1244 if ($this->outputIsRequested('parameters', $options['output'])) { 1245 foreach ($result as $mediatypeid => $mediatype) { 1246 $result[$mediatypeid]['parameters'] = []; 1247 } 1248 1249 $parameters = DB::select('media_type_param', [ 1250 'output' => ['mediatypeid', 'name', 'value'], 1251 'filter' => ['mediatypeid' => array_keys($result)] 1252 ]); 1253 1254 foreach ($parameters as $parameter) { 1255 $result[$parameter['mediatypeid']]['parameters'][] = [ 1256 'name' => $parameter['name'], 1257 'value' => $parameter['value'] 1258 ]; 1259 } 1260 } 1261 1262 return $result; 1263 } 1264 1265 /** 1266 * Get incomplete media type validation rules. 1267 * 1268 * @param int $type 1269 * @param string $method 1270 * 1271 * @return array 1272 */ 1273 protected function getValidationRules($type, $method) { 1274 $api_input_rules = ['type' => API_OBJECT, 'fields' => [ 1275 'description' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('media_type', 'description')], 1276 'message_templates' => ['type' => API_OBJECTS, 'uniq' => [['eventsource', 'recovery']], 'fields' => [ 1277 'eventsource' => ['type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(',', [EVENT_SOURCE_TRIGGERS, EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION, EVENT_SOURCE_INTERNAL])], 1278 'recovery' => ['type' => API_MULTIPLE, 'flags' => API_REQUIRED, 'rules' => [ 1279 ['if' => ['field' => 'eventsource', 'in' => EVENT_SOURCE_TRIGGERS], 'type' => API_INT32, 'in' => implode(',', [ACTION_OPERATION, ACTION_RECOVERY_OPERATION, ACTION_ACKNOWLEDGE_OPERATION])], 1280 ['if' => ['field' => 'eventsource', 'in' => implode(',', [EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION])], 'type' => API_INT32, 'in' => ACTION_OPERATION], 1281 ['if' => ['field' => 'eventsource', 'in' => EVENT_SOURCE_INTERNAL], 'type' => API_INT32, 'in' => implode(',', [ACTION_OPERATION, ACTION_RECOVERY_OPERATION])] 1282 ]], 1283 'subject' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('media_type_message', 'subject')], 1284 'message' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('media_type_message', 'message')] 1285 ]] 1286 ]]; 1287 1288 if ($type == MEDIA_TYPE_WEBHOOK) { 1289 $api_input_rules['fields'] += [ 1290 'script' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('media_type', 'script')], 1291 'timeout' => ['type' => API_TIME_UNIT, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('media_type', 'timeout'), 'in' => '1:60'], 1292 'process_tags' => ['type' => API_INT32, 'in' => implode(',', [ZBX_MEDIA_TYPE_TAGS_DISABLED, ZBX_MEDIA_TYPE_TAGS_ENABLED])], 1293 'show_event_menu' => ['type' => API_INT32, 'in' => implode(',', [ZBX_EVENT_MENU_HIDE, ZBX_EVENT_MENU_SHOW])], 1294 // Should be checked as string not as URL because it can contain macros tags. 1295 'event_menu_url' => ['type' => API_URL, 'flags' => API_ALLOW_EVENT_TAGS_MACRO, 'length' => DB::getFieldLength('media_type', 'event_menu_url')], 1296 'event_menu_name' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('media_type', 'event_menu_name')], 1297 'parameters' => ['type' => API_OBJECTS, 'uniq' => [['name']], 'fields' => [ 1298 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('media_type_param', 'name')], 1299 'value' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'length' => DB::getFieldLength('media_type_param', 'value')] 1300 ]] 1301 ]; 1302 1303 if ($method === 'create') { 1304 $api_input_rules['fields']['script']['flags'] |= API_REQUIRED; 1305 } 1306 } 1307 1308 return $api_input_rules; 1309 } 1310} 1311