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 'selectUsers' => null, 72 'countOutput' => false, 73 'groupCount' => false, 74 'preservekeys' => false, 75 'sortfield' => '', 76 'sortorder' => '', 77 'limit' => null 78 ]; 79 $options = zbx_array_merge($defOptions, $options); 80 81 // permission check 82 if (self::$userData['type'] == USER_TYPE_SUPER_ADMIN) { 83 } 84 elseif (!$options['editable'] && self::$userData['type'] == USER_TYPE_ZABBIX_ADMIN) { 85 } 86 elseif ($options['editable'] || self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 87 return []; 88 } 89 90 // mediatypeids 91 if (!is_null($options['mediatypeids'])) { 92 zbx_value2array($options['mediatypeids']); 93 $sqlParts['where'][] = dbConditionInt('mt.mediatypeid', $options['mediatypeids']); 94 } 95 96 // mediaids 97 if (!is_null($options['mediaids'])) { 98 zbx_value2array($options['mediaids']); 99 100 $sqlParts['from']['media'] = 'media m'; 101 $sqlParts['where'][] = dbConditionInt('m.mediaid', $options['mediaids']); 102 $sqlParts['where']['mmt'] = 'm.mediatypeid=mt.mediatypeid'; 103 } 104 105 // userids 106 if (!is_null($options['userids'])) { 107 zbx_value2array($options['userids']); 108 109 $sqlParts['from']['media'] = 'media m'; 110 $sqlParts['where'][] = dbConditionInt('m.userid', $options['userids']); 111 $sqlParts['where']['mmt'] = 'm.mediatypeid=mt.mediatypeid'; 112 } 113 114 // filter 115 if (is_array($options['filter'])) { 116 $this->dbFilter('media_type mt', $options, $sqlParts); 117 } 118 119 // search 120 if (is_array($options['search'])) { 121 zbx_db_search('media_type mt', $options, $sqlParts); 122 } 123 124 // limit 125 if (zbx_ctype_digit($options['limit']) && $options['limit']) { 126 $sqlParts['limit'] = $options['limit']; 127 } 128 129 $sqlParts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); 130 $sqlParts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts); 131 $res = DBselect(self::createSelectQueryFromParts($sqlParts), $sqlParts['limit']); 132 while ($mediatype = DBfetch($res)) { 133 if ($options['countOutput']) { 134 if ($options['groupCount']) { 135 $result[] = $mediatype; 136 } 137 else { 138 $result = $mediatype['rowscount']; 139 } 140 } 141 else { 142 $result[$mediatype['mediatypeid']] = $mediatype; 143 } 144 } 145 146 if ($options['countOutput']) { 147 return $result; 148 } 149 150 if ($result) { 151 $result = $this->addRelatedObjects($options, $result); 152 } 153 154 // removing keys (hash -> array) 155 if (!$options['preservekeys']) { 156 $result = zbx_cleanHashes($result); 157 } 158 return $result; 159 } 160 161 /** 162 * Validates the input parameters for the create() method. 163 * 164 * @param array $mediatypes 165 * 166 * @throws APIException if the input is invalid. 167 */ 168 protected function validateCreate(array $mediatypes) { 169 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 170 self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can create media types.')); 171 } 172 173 if (!$mediatypes) { 174 self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.')); 175 } 176 177 $required_fields = ['type', 'description']; 178 179 foreach ($mediatypes as $mediatype) { 180 if (!is_array($mediatype)) { 181 self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.')); 182 } 183 184 // Check required parameters. 185 $missing_keys = array_diff($required_fields, array_keys($mediatype)); 186 187 if ($missing_keys) { 188 self::exception(ZBX_API_ERROR_PARAMETERS, 189 _s('Media type is missing parameters: %1$s', implode(', ', $missing_keys)) 190 ); 191 } 192 else { 193 foreach ($required_fields as $field) { 194 if ($mediatype[$field] === '' || $mediatype[$field] === null) { 195 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 196 'Field "%1$s" is missing a value for media type "%2$s".', 197 $field, 198 $mediatype['description'] 199 )); 200 } 201 } 202 } 203 } 204 205 // Check for duplicate names. 206 $duplicate_name = CArrayHelper::findDuplicate($mediatypes, 'description'); 207 if ($duplicate_name) { 208 self::exception(ZBX_API_ERROR_PARAMETERS, 209 _s('Duplicate "description" value "%1$s" for media type.', $duplicate_name['description']) 210 ); 211 } 212 213 $simple_interval_parser = new CSimpleIntervalParser(); 214 215 foreach ($mediatypes as $mediatype) { 216 // Check if media type already exists. 217 $db_mediatype = API::getApiService()->select('media_type', [ 218 'output' => ['description'], 219 'filter' => ['description' => $mediatype['description']], 220 'limit' => 1 221 ]); 222 223 if ($db_mediatype) { 224 self::exception(ZBX_API_ERROR_PARAMETERS, 225 _s('Media type "%1$s" already exists.', $mediatype['description']) 226 ); 227 } 228 229 // Check additional fields and values depending on media type. 230 $this->checkRequiredFieldsByType($mediatype); 231 232 switch ($mediatype['type']) { 233 case MEDIA_TYPE_EZ_TEXTING: 234 $message_text_limit_validator = new CLimitedSetValidator([ 235 'values' => [EZ_TEXTING_LIMIT_USA, EZ_TEXTING_LIMIT_CANADA] 236 ]); 237 238 if (!$message_text_limit_validator->validate($mediatype['exec_path'])) { 239 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 240 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 241 $mediatype['exec_path'], 242 'exec_path', 243 $mediatype['description'] 244 )); 245 } 246 break; 247 248 case MEDIA_TYPE_EMAIL: 249 if (array_key_exists('smtp_authentication', $mediatype)) { 250 $smtp_authentication_validator = new CLimitedSetValidator([ 251 'values' => [SMTP_AUTHENTICATION_NONE, SMTP_AUTHENTICATION_NORMAL] 252 ]); 253 254 if (!$smtp_authentication_validator->validate($mediatype['smtp_authentication'])) { 255 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 256 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 257 $mediatype['smtp_authentication'], 258 'smtp_authentication', 259 $mediatype['description'] 260 )); 261 } 262 } 263 264 // Validate optional 'smtp_port' field. 265 if (array_key_exists('smtp_port', $mediatype) && !validatePortNumber($mediatype['smtp_port'])) { 266 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 267 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 268 $mediatype['smtp_port'], 269 'smtp_port', 270 $mediatype['description'] 271 )); 272 } 273 274 // Validate optional field 'smtp_security'. 275 if (array_key_exists('smtp_security', $mediatype)) { 276 $smtp_security_validator = new CLimitedSetValidator([ 277 'values' => [ 278 SMTP_CONNECTION_SECURITY_NONE, 279 SMTP_CONNECTION_SECURITY_STARTTLS, 280 SMTP_CONNECTION_SECURITY_SSL_TLS 281 ] 282 ]); 283 284 if (!$smtp_security_validator->validate($mediatype['smtp_security'])) { 285 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 286 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 287 $mediatype['smtp_security'], 288 'smtp_security', 289 $mediatype['description'] 290 )); 291 } 292 } 293 294 // Validate optional field 'smtp_verify_peer'. 295 if (array_key_exists('smtp_verify_peer', $mediatype)) { 296 $smtp_verify_peer_validator = new CLimitedSetValidator([ 297 'values' => [0, 1] 298 ]); 299 300 if (!$smtp_verify_peer_validator->validate($mediatype['smtp_verify_peer'])) { 301 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 302 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 303 $mediatype['smtp_verify_peer'], 304 'smtp_verify_peer', 305 $mediatype['description'] 306 )); 307 } 308 } 309 310 // Validate optional field 'smtp_verify_host'. 311 if (array_key_exists('smtp_verify_host', $mediatype)) { 312 $smtp_verify_host_validator = new CLimitedSetValidator([ 313 'values' => [0, 1] 314 ]); 315 316 if (!$smtp_verify_host_validator->validate($mediatype['smtp_verify_host'])) { 317 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 318 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 319 $mediatype['smtp_verify_host'], 320 'smtp_verify_host', 321 $mediatype['description'] 322 )); 323 } 324 } 325 break; 326 327 case MEDIA_TYPE_EXEC: 328 if (array_key_exists('exec_params', $mediatype) && $mediatype['exec_params'] !== '') { 329 $pos = strrpos($mediatype['exec_params'], "\n"); 330 331 if ($pos === false || strlen($mediatype['exec_params']) != $pos + 1) { 332 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 333 'Script parameters "%1$s" are missing the last new line feed for media type "%2$s".', 334 $mediatype['exec_params'], 335 $mediatype['description'] 336 )); 337 } 338 } 339 break; 340 } 341 342 // Validate optional 'status' field. 343 if (array_key_exists('status', $mediatype)) { 344 $status_validator = new CLimitedSetValidator([ 345 'values' => [MEDIA_TYPE_STATUS_ACTIVE, MEDIA_TYPE_STATUS_DISABLED] 346 ]); 347 348 if (!$status_validator->validate($mediatype['status'])) { 349 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 350 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 351 $mediatype['status'], 352 'status', 353 $mediatype['description'] 354 )); 355 } 356 } 357 358 // Validate optional 'maxsessions' field. 359 if (array_key_exists('maxsessions', $mediatype)) { 360 if ($mediatype['maxsessions'] === '') { 361 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 362 'maxsessions', _('cannot be empty') 363 )); 364 } 365 366 $min = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 0; 367 $max = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 100; 368 369 if (!ctype_digit((string) $mediatype['maxsessions']) || $mediatype['maxsessions'] > $max 370 || $mediatype['maxsessions'] < $min) { 371 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 372 'maxsessions', _s('must be between "%1$s" and "%2$s"', $min, $max) 373 )); 374 } 375 } 376 377 // Validate optional 'maxattempts' field. 378 if (array_key_exists('maxattempts', $mediatype)) { 379 if ($mediatype['maxattempts'] === '') { 380 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 381 'maxattempts', _('cannot be empty') 382 )); 383 } 384 385 if (!ctype_digit((string) $mediatype['maxattempts']) || $mediatype['maxattempts'] > 10 386 || $mediatype['maxattempts'] < 1) { 387 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 388 'maxattempts', _s('must be between "%1$s" and "%2$s"', 1, 10) 389 )); 390 } 391 } 392 393 // Validate optional 'attempt_interval' field. 394 if (array_key_exists('attempt_interval', $mediatype)) { 395 if ($mediatype['attempt_interval'] === '') { 396 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 397 'attempt_interval', _('cannot be empty') 398 )); 399 } 400 401 if ($simple_interval_parser->parse($mediatype['attempt_interval']) == CParser::PARSE_SUCCESS) { 402 $attempt_interval = timeUnitToSeconds($mediatype['attempt_interval']); 403 404 if ($attempt_interval < 0 || $attempt_interval > 60) { 405 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 406 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 60) 407 )); 408 } 409 } 410 else { 411 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 412 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 60) 413 )); 414 } 415 } 416 } 417 } 418 419 /** 420 * Validates the input parameters for the update() method. 421 * 422 * @param array $mediatypes 423 * 424 * @throws APIException if the input is invalid. 425 */ 426 protected function validateUpdate(array $mediatypes) { 427 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 428 self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can edit media types.')); 429 } 430 431 if (!$mediatypes) { 432 self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.')); 433 } 434 435 // Validate given IDs. 436 $this->checkObjectIds($mediatypes, 'mediatypeid', 437 _('No "%1$s" given for media type.'), 438 _('Empty media type ID.'), 439 _('Incorrect media type ID.') 440 ); 441 442 $mediatypeids = zbx_objectValues($mediatypes, 'mediatypeid'); 443 444 // Check value map names. 445 $db_mediatypes = API::getApiService()->select('media_type', [ 446 'output' => ['mediatypeid', 'type', 'description', 'exec_path', 'status', 'smtp_port', 'smtp_verify_peer', 447 'smtp_verify_host', 'smtp_authentication', 'maxsessions', 'maxattempts', 'attempt_interval' 448 ], 449 'mediatypeids' => $mediatypeids, 450 'preservekeys' => true 451 ]); 452 453 $check_names = []; 454 $simple_interval_parser = new CSimpleIntervalParser(); 455 456 foreach ($mediatypes as $mediatype) { 457 // Check if this media type exists. 458 if (!array_key_exists($mediatype['mediatypeid'], $db_mediatypes)) { 459 self::exception(ZBX_API_ERROR_PERMISSIONS, 460 _('No permissions to referred object or it does not exist!') 461 ); 462 } 463 464 // Validate "description" field. 465 if (array_key_exists('description', $mediatype)) { 466 if (is_array($mediatype['description'])) { 467 self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.')); 468 } 469 elseif ($mediatype['description'] === '' || $mediatype['description'] === null 470 || $mediatype['description'] === false) { 471 self::exception(ZBX_API_ERROR_PARAMETERS, 472 _s('Incorrect value for field "%1$s": %2$s.', 'description', _('cannot be empty')) 473 ); 474 } 475 476 $check_names[$mediatype['description']] = true; 477 } 478 } 479 480 if ($check_names) { 481 $db_mediatype_names = API::getApiService()->select('media_type', [ 482 'output' => ['mediatypeid', 'description'], 483 'filter' => ['name' => array_keys($check_names)] 484 ]); 485 $db_mediatype_names = zbx_toHash($db_mediatype_names, 'description'); 486 487 foreach ($mediatypes as $mediatype) { 488 if (array_key_exists('description', $mediatype) 489 && array_key_exists($mediatype['description'], $db_mediatype_names) 490 && !idcmp($db_mediatype_names[$mediatype['description']]['mediatypeid'], 491 $mediatype['mediatypeid'])) { 492 self::exception(ZBX_API_ERROR_PARAMETERS, 493 _s('Media type "%1$s" already exists.', $mediatype['description']) 494 ); 495 } 496 } 497 } 498 499 // Populate "description" field, if not set. Type field should not be populated at this point. 500 $mediatypes = $this->extendFromObjects(zbx_toHash($mediatypes, 'mediatypeid'), $db_mediatypes, ['description']); 501 502 $duplicate_name = CArrayHelper::findDuplicate($mediatypes, 'description'); 503 if ($duplicate_name) { 504 self::exception(ZBX_API_ERROR_PARAMETERS, 505 _s('Duplicate "description" value "%1$s" for media type.', $duplicate_name['description']) 506 ); 507 } 508 509 foreach ($mediatypes as $mediatype) { 510 $db_mediatype = $db_mediatypes[$mediatype['mediatypeid']]; 511 512 // Recheck mandatory fields if type changed. 513 if (array_key_exists('type', $mediatype) && $db_mediatype['type'] != $mediatype['type']) { 514 $this->checkRequiredFieldsByType($mediatype); 515 } 516 else { 517 $optional_fields_by_type = [ 518 MEDIA_TYPE_EMAIL => ['smtp_server', 'smtp_helo', 'smtp_email'], 519 MEDIA_TYPE_EXEC => ['exec_path'], 520 MEDIA_TYPE_SMS => ['gsm_modem'], 521 MEDIA_TYPE_JABBER => ['username', 'passwd'], 522 MEDIA_TYPE_EZ_TEXTING => ['exec_path', 'username', 'passwd'] 523 ]; 524 525 foreach ($optional_fields_by_type[$db_mediatype['type']] as $field) { 526 if (array_key_exists($field, $mediatype) 527 && ($mediatype[$field] === '' || $mediatype[$field] === null)) { 528 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 529 'Field "%1$s" is missing a value for media type "%2$s".', 530 $field, 531 $mediatype['description'] 532 )); 533 } 534 } 535 536 // Populate "type" field from DB, since it is not set and is required for further validation. 537 $mediatype['type'] = $db_mediatype['type']; 538 } 539 540 switch ($mediatype['type']) { 541 case MEDIA_TYPE_EZ_TEXTING: 542 if (array_key_exists('exec_path', $mediatype)) { 543 $message_text_limit_validator = new CLimitedSetValidator([ 544 'values' => [EZ_TEXTING_LIMIT_USA, EZ_TEXTING_LIMIT_CANADA] 545 ]); 546 547 if ($db_mediatype['exec_path'] !== $mediatype['exec_path'] 548 && !$message_text_limit_validator->validate($mediatype['exec_path'])) { 549 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 550 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 551 $mediatype['exec_path'], 552 'exec_path', 553 $mediatype['description'] 554 )); 555 } 556 } 557 break; 558 559 case MEDIA_TYPE_EMAIL: 560 if (array_key_exists('smtp_authentication', $mediatype)) { 561 $smtp_authentication_validator = new CLimitedSetValidator([ 562 'values' => [SMTP_AUTHENTICATION_NONE, SMTP_AUTHENTICATION_NORMAL] 563 ]); 564 565 if (!$smtp_authentication_validator->validate($mediatype['smtp_authentication'])) { 566 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 567 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 568 $mediatype['smtp_authentication'], 569 'smtp_authentication', 570 $mediatype['description'] 571 )); 572 } 573 } 574 575 // Validate optional 'smtp_port' field. 576 if (array_key_exists('smtp_port', $mediatype) 577 && $db_mediatype['smtp_port'] != $mediatype['smtp_port'] 578 && !validatePortNumber($mediatype['smtp_port'])) { 579 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 580 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 581 $mediatype['smtp_port'], 582 'smtp_port', 583 $mediatype['description'] 584 )); 585 } 586 587 // Validate optional field 'smtp_security'. 588 if (array_key_exists('smtp_security', $mediatype)) { 589 $smtp_security_validator = new CLimitedSetValidator([ 590 'values' => [ 591 SMTP_CONNECTION_SECURITY_NONE, 592 SMTP_CONNECTION_SECURITY_STARTTLS, 593 SMTP_CONNECTION_SECURITY_SSL_TLS 594 ] 595 ]); 596 597 if (!$smtp_security_validator->validate($mediatype['smtp_security'])) { 598 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 599 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 600 $mediatype['smtp_security'], 601 'smtp_security', 602 $mediatype['description'] 603 )); 604 } 605 } 606 607 // Validate optional field 'smtp_verify_peer'. 608 if (array_key_exists('smtp_verify_peer', $mediatype) 609 && $db_mediatype['smtp_verify_peer'] != $mediatype['smtp_verify_peer']) { 610 $smtp_verify_peer_validator = new CLimitedSetValidator([ 611 'values' => [0, 1] 612 ]); 613 614 if (!$smtp_verify_peer_validator->validate($mediatype['smtp_verify_peer'])) { 615 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 616 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 617 $mediatype['smtp_verify_peer'], 618 'smtp_verify_peer', 619 $mediatype['description'] 620 )); 621 } 622 } 623 624 // Validate optional field 'smtp_verify_host'. 625 if (array_key_exists('smtp_verify_host', $mediatype) 626 && $db_mediatype['smtp_verify_host'] != $mediatype['smtp_verify_host']) { 627 $smtp_verify_host_validator = new CLimitedSetValidator([ 628 'values' => [0, 1] 629 ]); 630 631 if (!$smtp_verify_host_validator->validate($mediatype['smtp_verify_host'])) { 632 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 633 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 634 $mediatype['smtp_verify_host'], 635 'smtp_verify_host', 636 $mediatype['description'] 637 )); 638 } 639 } 640 break; 641 642 case MEDIA_TYPE_EXEC: 643 if (array_key_exists('exec_params', $mediatype) && $mediatype['exec_params'] !== '') { 644 $pos = strrpos($mediatype['exec_params'], "\n"); 645 646 if ($pos === false || strlen($mediatype['exec_params']) != $pos + 1) { 647 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 648 'Script parameters "%1$s" are missing the last new line feed for media type "%2$s".', 649 $mediatype['exec_params'], 650 $mediatype['description'] 651 )); 652 } 653 } 654 break; 655 } 656 657 // Validate optional 'status' field and only when status is changed. 658 if (array_key_exists('status', $mediatype) && $db_mediatype['status'] != $mediatype['status']) { 659 $status_validator = new CLimitedSetValidator([ 660 'values' => [MEDIA_TYPE_STATUS_ACTIVE, MEDIA_TYPE_STATUS_DISABLED] 661 ]); 662 663 if (!$status_validator->validate($mediatype['status'])) { 664 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 665 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 666 $mediatype['status'], 667 'status', 668 $mediatype['description'] 669 )); 670 } 671 } 672 673 // Validate optional 'maxsessions' field. 674 if (array_key_exists('maxsessions', $mediatype) 675 && $db_mediatype['maxsessions'] != $mediatype['maxsessions']) { 676 if ($mediatype['maxsessions'] === '') { 677 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 678 'maxsessions', _('cannot be empty') 679 )); 680 } 681 682 $min = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 0; 683 $max = ($mediatype['type'] == MEDIA_TYPE_SMS) ? 1 : 100; 684 685 if (!ctype_digit((string) $mediatype['maxsessions']) || $mediatype['maxsessions'] > $max 686 || $mediatype['maxsessions'] < $min) { 687 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 688 'maxsessions', _s('must be between "%1$s" and "%2$s"', $min, $max) 689 )); 690 } 691 } 692 elseif ($mediatype['type'] == MEDIA_TYPE_SMS && $mediatype['type'] != $db_mediatype['type'] 693 && $db_mediatype['maxsessions'] != 1) { 694 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 695 'maxsessions', _s('must be between "%1$s" and "%2$s"', 1, 1) 696 )); 697 } 698 699 // Validate optional 'maxattempts' field. 700 if (array_key_exists('maxattempts', $mediatype) 701 && $db_mediatype['maxattempts'] != $mediatype['maxattempts']) { 702 if ($mediatype['maxattempts'] === '') { 703 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 704 'maxattempts', _('cannot be empty') 705 )); 706 } 707 708 if (!ctype_digit((string) $mediatype['maxattempts']) || $mediatype['maxattempts'] > 10 709 || $mediatype['maxattempts'] < 1) { 710 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 711 'maxattempts', _s('must be between "%1$s" and "%2$s"', 1, 10) 712 )); 713 } 714 } 715 716 // Validate optional 'attempt_interval' field. 717 if (array_key_exists('attempt_interval', $mediatype) 718 && $db_mediatype['attempt_interval'] != $mediatype['attempt_interval']) { 719 if ($mediatype['attempt_interval'] === '') { 720 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 721 'attempt_interval', _('cannot be empty') 722 )); 723 } 724 725 if ($simple_interval_parser->parse($mediatype['attempt_interval']) == CParser::PARSE_SUCCESS) { 726 $attempt_interval = timeUnitToSeconds($mediatype['attempt_interval']); 727 728 if ($attempt_interval < 0 || $attempt_interval > 60) { 729 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 730 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 60) 731 )); 732 } 733 } 734 else { 735 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 736 'attempt_interval', _s('must be between "%1$s" and "%2$s"', 0, 60) 737 )); 738 } 739 } 740 } 741 } 742 743 /** 744 * Add Media types. 745 * 746 * @param array $mediatypes multidimensional array with media types data 747 * @param int $mediatypes['type'] type 748 * @param string $mediatypes['description'] description 749 * @param string $mediatypes['smtp_server'] SMTP server 750 * @param int $mediatypes['smtp_port'] SMTP port 751 * @param string $mediatypes['smtp_helo'] SMTP hello 752 * @param string $mediatypes['smtp_email'] SMTP email 753 * @param int $mediatypes['smtp_security'] SMTP connection security 754 * @param int $mediatypes['smtp_verify_peer'] SMTP verify peer 755 * @param int $mediatypes['smtp_verify_host'] SMTP verify host 756 * @param int $mediatypes['smtp_authentication'] SMTP authentication 757 * @param string $mediatypes['exec_path'] script name/message text limit 758 * @param string $mediatypes['exec_params'] script parameters 759 * @param string $mediatypes['gsm_modem'] GSM modem 760 * @param string $mediatypes['username'] username 761 * @param string $mediatypes['passwd'] password 762 * @param int $mediatypes['status'] media type status 763 * @param int $mediatypes['maxsessions'] Limit of simultaneously processed alerts. 764 * @param int $mediatypes['maxattempts'] Maximum attempts to deliver alert successfully. 765 * @param string $mediatypes['attempt_interval'] Interval between alert delivery attempts. 766 * 767 * @return array 768 */ 769 public function create($mediatypes) { 770 $mediatypes = zbx_toArray($mediatypes); 771 772 $this->validateCreate($mediatypes); 773 774 $mediatypeids = DB::insert('media_type', $mediatypes); 775 776 return ['mediatypeids' => $mediatypeids]; 777 } 778 779 /** 780 * Update Media types. 781 * 782 * @param array $mediatypes multidimensional array with media types data 783 * @param int $mediatypes['mediatypeid'] id 784 * @param int $mediatypes['type'] type 785 * @param string $mediatypes['description'] description 786 * @param string $mediatypes['smtp_server'] SMTP server 787 * @param int $mediatypes['smtp_port'] SMTP port 788 * @param string $mediatypes['smtp_helo'] SMTP hello 789 * @param string $mediatypes['smtp_email'] SMTP email 790 * @param int $mediatypes['smtp_security'] SMTP connection security 791 * @param int $mediatypes['smtp_verify_peer'] SMTP verify peer 792 * @param int $mediatypes['smtp_verify_host'] SMTP verify host 793 * @param int $mediatypes['smtp_authentication'] SMTP authentication 794 * @param string $mediatypes['exec_path'] script name/message text limit 795 * @param string $mediatypes['exec_params'] script parameters 796 * @param string $mediatypes['gsm_modem'] GSM modem 797 * @param string $mediatypes['username'] username 798 * @param string $mediatypes['passwd'] password 799 * @param int $mediatypes['status'] media type status 800 * @param int $mediatypes['maxsessions'] Limit of simultaneously processed alerts. 801 * @param int $mediatypes['maxattempts'] Maximum attempts to deliver alert successfully. 802 * @param string $mediatypes['attempt_interval'] Interval between alert delivery attempts. 803 * 804 * @return array 805 */ 806 public function update($mediatypes) { 807 $mediatypes = zbx_toArray($mediatypes); 808 809 $this->validateUpdate($mediatypes); 810 811 $update = []; 812 foreach ($mediatypes as $mediatype) { 813 $mediatypeid = $mediatype['mediatypeid']; 814 unset($mediatype['mediatypeid']); 815 816 if (!empty($mediatype)) { 817 $update[] = [ 818 'values' => $mediatype, 819 'where' => ['mediatypeid' => $mediatypeid] 820 ]; 821 } 822 } 823 824 DB::update('media_type', $update); 825 $mediatypeids = zbx_objectValues($mediatypes, 'mediatypeid'); 826 827 return ['mediatypeids' => $mediatypeids]; 828 } 829 830 /** 831 * Delete Media types. 832 * 833 * @param array $mediatypeids 834 * 835 * @return array 836 */ 837 public function delete(array $mediatypeids) { 838 if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) { 839 self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Super Admins can delete media types.')); 840 } 841 842 $actions = API::Action()->get([ 843 'mediatypeids' => $mediatypeids, 844 'output' => API_OUTPUT_EXTEND, 845 'preservekeys' => true 846 ]); 847 if (!empty($actions)) { 848 $action = reset($actions); 849 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Media types used by action "%s".', $action['name'])); 850 } 851 852 DB::delete('media_type', ['mediatypeid' => $mediatypeids]); 853 854 return ['mediatypeids' => $mediatypeids]; 855 } 856 857 /** 858 * Check required fields by type. Values for fields must not be empty. 859 * 860 * @param array $mediatype An array of media type data. 861 * @param string $mediatype['description'] Name of the media type. 862 * @param string $mediatype['type'] E-mail, Script, SMS, Jabber and Ez Texting. 863 * 864 * @throws APIException if the input is invalid. 865 */ 866 protected function checkRequiredFieldsByType(array $mediatype) { 867 $type_validator = new CLimitedSetValidator([ 868 'values' => array_keys(media_type2str()) 869 ]); 870 871 if (!$type_validator->validate($mediatype['type'])) { 872 self::exception(ZBX_API_ERROR_PARAMETERS, _s( 873 'Incorrect value "%1$s" in field "%2$s" for media type "%3$s".', 874 $mediatype['type'], 875 'type', 876 $mediatype['description'] 877 )); 878 } 879 880 $required_fields_by_type = [ 881 MEDIA_TYPE_EMAIL => ['smtp_server', 'smtp_helo', 'smtp_email'], 882 MEDIA_TYPE_EXEC => ['exec_path'], 883 MEDIA_TYPE_SMS => ['gsm_modem'], 884 MEDIA_TYPE_JABBER => ['username', 'passwd'], 885 MEDIA_TYPE_EZ_TEXTING => ['exec_path', 'username', 'passwd'] 886 ]; 887 888 foreach ($required_fields_by_type[$mediatype['type']] as $field) { 889 // Check if fields set on Create method. For update method they are checked when type is changed. 890 if (!array_key_exists($field, $mediatype)) { 891 self::exception(ZBX_API_ERROR_PARAMETERS, 892 _s('Field "%1$s" is required for media type "%2$s".', $field, $mediatype['description']) 893 ); 894 } 895 elseif (array_key_exists($field, $mediatype) 896 && ($mediatype[$field] === '' || $mediatype[$field] === null)) { 897 self::exception(ZBX_API_ERROR_PARAMETERS, 898 _s('Field "%1$s" is missing a value for media type "%2$s".', $field, $mediatype['description']) 899 ); 900 } 901 } 902 } 903 904 protected function addRelatedObjects(array $options, array $result) { 905 $result = parent::addRelatedObjects($options, $result); 906 907 // adding users 908 if ($options['selectUsers'] !== null && $options['selectUsers'] != API_OUTPUT_COUNT) { 909 $relationMap = $this->createRelationMap($result, 'mediatypeid', 'userid', 'media'); 910 $users = API::User()->get([ 911 'output' => $options['selectUsers'], 912 'userids' => $relationMap->getRelatedIds(), 913 'preservekeys' => true 914 ]); 915 $result = $relationMap->mapMany($result, $users, 'users'); 916 } 917 918 return $result; 919 } 920} 921