Example #1
0
 /**
  * Check input.
  *
  * @param array  $triggers
  * @param string $method
  */
 public function checkInput(array &$triggers, $method)
 {
     $update = $method == 'update';
     // permissions
     if ($update) {
         $triggerDbFields = ['triggerid' => null];
         $dbTriggers = $this->get(['output' => API_OUTPUT_EXTEND, 'triggerids' => zbx_objectValues($triggers, 'triggerid'), 'editable' => true, 'preservekeys' => true]);
         $dbTriggers = CMacrosResolverHelper::resolveTriggerExpressions($dbTriggers);
         $updateDiscoveredValidator = new CUpdateDiscoveredValidator(['allowed' => ['triggerid', 'status'], 'messageAllowedField' => _('Cannot update "%2$s" for a discovered trigger "%1$s".')]);
         foreach ($triggers as $trigger) {
             $triggerId = $trigger['triggerid'];
             // check permissions
             if (!isset($dbTriggers[$triggerId])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
             }
             $dbTrigger = $dbTriggers[$triggerId];
             $triggerName = isset($trigger['description']) ? $trigger['description'] : $dbTrigger['description'];
             $updateDiscoveredValidator->setObjectName($triggerName);
             // discovered fields, except status, cannot be updated
             $this->checkPartialValidator($trigger, $updateDiscoveredValidator, $dbTrigger);
         }
         $triggers = $this->extendObjects($this->tableName(), $triggers, ['description']);
     } else {
         $triggerDbFields = ['description' => null, 'expression' => null, 'value' => TRIGGER_VALUE_FALSE];
     }
     foreach ($triggers as $tnum => &$trigger) {
         $currentTrigger = $triggers[$tnum];
         $this->checkNoParameters($trigger, ['templateid', 'state', 'value'], $update ? _('Cannot update "%1$s" for trigger "%2$s".') : _('Cannot set "%1$s" for trigger "%2$s".'), $trigger['description']);
         if (!check_db_fields($triggerDbFields, $trigger)) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect fields for trigger.'));
         }
         $expressionChanged = true;
         if ($update) {
             $dbTrigger = $dbTriggers[$trigger['triggerid']];
             if (array_key_exists('expression', $trigger) && $trigger['expression'] === $dbTrigger['expression']) {
                 $expressionChanged = false;
             }
             if (array_key_exists('description', $trigger) && strcmp($trigger['description'], $dbTrigger['description']) == 0) {
                 unset($trigger['description']);
             }
         }
         // if some of the properties are unchanged, no need to update them in DB
         // validating trigger expression
         if (isset($trigger['expression']) && $expressionChanged) {
             // expression permissions
             $expressionData = new CTriggerExpression(['lldmacros' => false]);
             if (!$expressionData->parse($trigger['expression'])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, $expressionData->error);
             }
             if (!isset($expressionData->expressions[0])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('Trigger expression must contain at least one host:key reference.'));
             }
             $expressionHosts = $expressionData->getHosts();
             $hosts = API::Host()->get(['output' => ['hostid', 'host', 'status'], 'filter' => ['host' => $expressionHosts], 'editable' => true, 'templated_hosts' => true, 'preservekeys' => true]);
             $hosts = zbx_toHash($hosts, 'host');
             $hostsStatusFlags = 0x0;
             foreach ($expressionHosts as $host) {
                 if (!isset($hosts[$host])) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect trigger expression. Host "%s" does not exist or you have no access to this host.', $host));
                 }
                 // find out if both templates and hosts are referenced in expression
                 $hostsStatusFlags |= $hosts[$host]['status'] == HOST_STATUS_TEMPLATE ? 0x1 : 0x2;
                 if ($hostsStatusFlags == 0x3) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect trigger expression. Trigger expression elements should not belong to a template and a host simultaneously.'));
                 }
             }
             foreach ($expressionData->expressions as $exprPart) {
                 $sql = 'SELECT i.itemid,i.value_type' . ' FROM items i,hosts h' . ' WHERE i.key_=' . zbx_dbstr($exprPart['item']) . ' AND ' . dbConditionInt('i.flags', [ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED]) . ' AND h.host=' . zbx_dbstr($exprPart['host']) . ' AND h.hostid=i.hostid';
                 if (!DBfetch(DBselect($sql))) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect item key "%1$s" provided for trigger expression on "%2$s".', $exprPart['item'], $exprPart['host']));
                 }
             }
         }
         // check existing
         $this->checkIfExistsOnHost($currentTrigger);
     }
     unset($trigger);
 }
Example #2
0
 /**
  * Validates the input parameters for the update() method.
  *
  * @param array $hosts			hosts data array
  * @param array $db_hosts		db hosts data array
  *
  * @throws APIException if the input is invalid.
  */
 protected function validateUpdate(array $hosts, array $db_hosts)
 {
     $host_db_fields = ['hostid' => null];
     $hosts_full = [];
     foreach ($hosts as $host) {
         // Validate mandatory fields.
         if (!check_db_fields($host_db_fields, $host)) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _s('Wrong fields for host "%1$s".', array_key_exists('host', $host) ? $host['host'] : ''));
         }
         // Validate host permissions.
         if (!array_key_exists($host['hostid'], $db_hosts)) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
         }
         // Validate "groups" field.
         if (array_key_exists('groups', $host) && (!is_array($host['groups']) || !$host['groups'])) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _s('No groups for host "%1$s".', $db_hosts[$host['hostid']]['host']));
         }
         // Permissions to host groups is validated in massUpdate().
     }
     $inventory_fields = zbx_objectValues(getHostInventories(), 'db_field');
     $status_validator = new CLimitedSetValidator(['values' => [HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED], 'messageInvalid' => _('Incorrect status for host "%1$s".')]);
     $update_discovered_validator = new CUpdateDiscoveredValidator(['allowed' => ['hostid', 'status', 'inventory', 'description'], 'messageAllowedField' => _('Cannot update "%2$s" for a discovered host "%1$s".')]);
     $host_names = [];
     foreach ($hosts as &$host) {
         $db_host = $db_hosts[$host['hostid']];
         $host_name = array_key_exists('host', $host) ? $host['host'] : $db_host['host'];
         if (array_key_exists('status', $host)) {
             $status_validator->setObjectName($host_name);
             $this->checkValidator($host['status'], $status_validator);
         }
         if (array_key_exists('inventory', $host) && $host['inventory']) {
             if (array_key_exists('inventory_mode', $host) && $host['inventory_mode'] == HOST_INVENTORY_DISABLED) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot set inventory fields for disabled inventory.'));
             }
             $fields = array_keys($host['inventory']);
             foreach ($fields as $field) {
                 if (!in_array($field, $inventory_fields)) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect inventory field "%s".', $field));
                 }
             }
         }
         // cannot update certain fields for discovered hosts
         $update_discovered_validator->setObjectName($host_name);
         $this->checkPartialValidator($host, $update_discovered_validator, $db_host);
         if (array_key_exists('interfaces', $host)) {
             if (!is_array($host['interfaces']) || !$host['interfaces']) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('No interfaces for host "%s".', $host['host']));
             }
         }
         if (array_key_exists('host', $host)) {
             if (!preg_match('/^' . ZBX_PREG_HOST_FORMAT . '$/', $host['host'])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect characters used for host name "%s".', $host['host']));
             }
             if (array_key_exists('host', $host_names) && array_key_exists($host['host'], $host_names['host'])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Duplicate host. Host with the same host name "%s" already exists in data.', $host['host']));
             }
             $host_names['host'][$host['host']] = $host['hostid'];
         }
         if (array_key_exists('name', $host)) {
             // if visible name is empty replace it with host name
             if (zbx_empty(trim($host['name']))) {
                 if (!array_key_exists('host', $host)) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _s('Visible name cannot be empty if host name is missing.'));
                 }
                 $host['name'] = $host['host'];
             }
             if (array_key_exists('name', $host_names) && array_key_exists($host['name'], $host_names['name'])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Duplicate host. Host with the same visible name "%s" already exists in data.', $host['name']));
             }
             $host_names['name'][$host['name']] = $host['hostid'];
         }
         $hosts_full[] = zbx_array_merge($db_host, $host);
     }
     unset($host);
     if (array_key_exists('host', $host_names) || array_key_exists('name', $host_names)) {
         $filter = [];
         if (array_key_exists('host', $host_names)) {
             $filter['host'] = array_keys($host_names['host']);
         }
         if (array_key_exists('name', $host_names)) {
             $filter['name'] = array_keys($host_names['name']);
         }
         $hosts_exists = $this->get(['output' => ['hostid', 'host', 'name'], 'filter' => $filter, 'searchByAny' => true, 'nopermissions' => true, 'preservekeys' => true]);
         foreach ($hosts_exists as $host_exists) {
             if (array_key_exists('host', $host_names) && array_key_exists($host_exists['host'], $host_names['host']) && bccomp($host_exists['hostid'], $host_names['host'][$host_exists['host']]) != 0) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host with the same name "%s" already exists.', $host_exists['host']));
             }
             if (array_key_exists('name', $host_names) && array_key_exists($host_exists['name'], $host_names['name']) && bccomp($host_exists['hostid'], $host_names['name'][$host_exists['name']]) != 0) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Host with the same visible name "%s" already exists.', $host_exists['name']));
             }
         }
         $templates_exists = API::Template()->get(['output' => ['hostid', 'host', 'name'], 'filter' => $filter, 'searchByAny' => true, 'nopermissions' => true, 'preservekeys' => true]);
         foreach ($templates_exists as $template_exists) {
             if (array_key_exists('host', $host_names) && array_key_exists($template_exists['host'], $host_names['host']) && bccomp($template_exists['templateid'], $host_names['host'][$template_exists['host']]) != 0) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Template with the same name "%s" already exists.', $template_exists['host']));
             }
             if (array_key_exists('name', $host_names) && array_key_exists($template_exists['name'], $host_names['name']) && bccomp($template_exists['templateid'], $host_names['name'][$template_exists['name']]) != 0) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Template with the same visible name "%s" already exists.', $template_exists['name']));
             }
         }
     }
     $this->validateEncryption($hosts_full);
 }
Example #3
0
 /**
  * Check items data.
  *
  * Any system field passed to the function will be unset.
  *
  * @throw APIException
  *
  * @param array $items passed by reference
  * @param bool  $update
  *
  * @return void
  */
 protected function checkInput(array &$items, $update = false)
 {
     if ($update) {
         $itemDbFields = ['itemid' => null];
         $dbItemsFields = ['itemid', 'templateid'];
         foreach ($this->fieldRules as $field => $rule) {
             if (!isset($rule['system'])) {
                 $dbItemsFields[] = $field;
             }
         }
         $dbItems = $this->get(['output' => $dbItemsFields, 'itemids' => zbx_objectValues($items, 'itemid'), 'editable' => true, 'preservekeys' => true]);
         $dbHosts = API::Host()->get(['output' => ['hostid', 'status', 'name'], 'hostids' => zbx_objectValues($dbItems, 'hostid'), 'templated_hosts' => true, 'editable' => true, 'selectApplications' => ['applicationid', 'flags'], 'preservekeys' => true]);
     } else {
         $itemDbFields = ['name' => null, 'key_' => null, 'hostid' => null, 'type' => null, 'value_type' => null, 'delay' => '0', 'delay_flex' => ''];
         $dbHosts = API::Host()->get(['output' => ['hostid', 'status', 'name'], 'hostids' => zbx_objectValues($items, 'hostid'), 'templated_hosts' => true, 'editable' => true, 'selectApplications' => ['applicationid', 'flags'], 'preservekeys' => true]);
     }
     // interfaces
     $interfaces = API::HostInterface()->get(['output' => ['interfaceid', 'hostid', 'type'], 'hostids' => zbx_objectValues($dbHosts, 'hostid'), 'nopermissions' => true, 'preservekeys' => true]);
     if ($update) {
         $updateDiscoveredValidator = new CUpdateDiscoveredValidator(['allowed' => ['itemid', 'status'], 'messageAllowedField' => _('Cannot update "%2$s" for a discovered item "%1$s".')]);
         foreach ($items as $item) {
             // check permissions
             if (!isset($dbItems[$item['itemid']])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
             }
             $dbItem = $dbItems[$item['itemid']];
             $itemName = isset($item['name']) ? $item['name'] : $dbItem['name'];
             // discovered fields, except status, cannot be updated
             $updateDiscoveredValidator->setObjectName($itemName);
             $this->checkPartialValidator($item, $updateDiscoveredValidator, $dbItem);
         }
         $items = $this->extendObjects($this->tableName(), $items, ['name', 'flags']);
     }
     $item_key_parser = new CItemKey();
     foreach ($items as $inum => &$item) {
         $item = $this->clearValues($item);
         $fullItem = $items[$inum];
         if (!check_db_fields($itemDbFields, $item)) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
         }
         if ($update) {
             check_db_fields($dbItems[$item['itemid']], $fullItem);
             $this->checkNoParameters($item, ['templateid', 'state'], _('Cannot update "%1$s" for item "%2$s".'), $item['name']);
             // apply rules
             foreach ($this->fieldRules as $field => $rules) {
                 if (0 != $fullItem['templateid'] && isset($rules['template']) || isset($rules['system'])) {
                     unset($item[$field]);
                     // For templated item and fields that should not be modified, use the value from DB.
                     if (array_key_exists($field, $dbItems[$item['itemid']]) && array_key_exists($field, $fullItem)) {
                         $fullItem[$field] = $dbItems[$item['itemid']][$field];
                     }
                 }
             }
             if (!isset($item['key_'])) {
                 $item['key_'] = $fullItem['key_'];
             }
             if (!isset($item['hostid'])) {
                 $item['hostid'] = $fullItem['hostid'];
             }
             // if a templated item is being assigned to an interface with a different type, ignore it
             $itemInterfaceType = itemTypeInterface($dbItems[$item['itemid']]['type']);
             if ($fullItem['templateid'] && isset($item['interfaceid']) && isset($interfaces[$item['interfaceid']]) && $itemInterfaceType !== INTERFACE_TYPE_ANY && $interfaces[$item['interfaceid']]['type'] != $itemInterfaceType) {
                 unset($item['interfaceid']);
             }
         } else {
             if (!isset($dbHosts[$item['hostid']])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
             }
             check_db_fields($itemDbFields, $fullItem);
             $this->checkNoParameters($item, ['templateid', 'state'], _('Cannot set "%1$s" for item "%2$s".'), $item['name']);
         }
         $host = $dbHosts[$fullItem['hostid']];
         if ($fullItem['type'] == ITEM_TYPE_ZABBIX_ACTIVE) {
             $item['delay_flex'] = '';
         }
         if ($fullItem['value_type'] == ITEM_VALUE_TYPE_STR) {
             $item['delta'] = 0;
         }
         if ($fullItem['value_type'] != ITEM_VALUE_TYPE_UINT64) {
             $item['data_type'] = 0;
         }
         // For non-numeric types, whichever value was entered in trends field, is overwritten to zero.
         if ($fullItem['value_type'] == ITEM_VALUE_TYPE_STR || $fullItem['value_type'] == ITEM_VALUE_TYPE_LOG || $fullItem['value_type'] == ITEM_VALUE_TYPE_TEXT) {
             $item['trends'] = 0;
         }
         // check if the item requires an interface
         $itemInterfaceType = itemTypeInterface($fullItem['type']);
         if ($itemInterfaceType !== false && $host['status'] != HOST_STATUS_TEMPLATE) {
             if (!$fullItem['interfaceid']) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('No interface found.'));
             } elseif (!isset($interfaces[$fullItem['interfaceid']]) || bccomp($interfaces[$fullItem['interfaceid']]['hostid'], $fullItem['hostid']) != 0) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('Item uses host interface from non-parent host.'));
             } elseif ($itemInterfaceType !== INTERFACE_TYPE_ANY && $interfaces[$fullItem['interfaceid']]['type'] != $itemInterfaceType) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('Item uses incorrect interface type.'));
             }
         } else {
             $item['interfaceid'] = 0;
         }
         // item key
         if ($fullItem['type'] == ITEM_TYPE_DB_MONITOR) {
             if (!isset($fullItem['flags']) || $fullItem['flags'] != ZBX_FLAG_DISCOVERY_RULE) {
                 if (strcmp($fullItem['key_'], ZBX_DEFAULT_KEY_DB_MONITOR) == 0) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _('Check the key, please. Default example was passed.'));
                 }
             } elseif ($fullItem['flags'] == ZBX_FLAG_DISCOVERY_RULE) {
                 if (strcmp($fullItem['key_'], ZBX_DEFAULT_KEY_DB_MONITOR_DISCOVERY) == 0) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _('Check the key, please. Default example was passed.'));
                 }
             }
         } elseif ($fullItem['type'] == ITEM_TYPE_SSH && strcmp($fullItem['key_'], ZBX_DEFAULT_KEY_SSH) == 0 || $fullItem['type'] == ITEM_TYPE_TELNET && strcmp($fullItem['key_'], ZBX_DEFAULT_KEY_TELNET) == 0 || $fullItem['type'] == ITEM_TYPE_JMX && strcmp($fullItem['key_'], ZBX_DEFAULT_KEY_JMX) == 0) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('Check the key, please. Default example was passed.'));
         }
         // key
         if ($item_key_parser->parse($fullItem['key_']) != CParser::PARSE_SUCCESS) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _params($this->getErrorMsg(self::ERROR_INVALID_KEY), [$fullItem['key_'], $fullItem['name'], $host['name'], $item_key_parser->getError()]));
         }
         // parameters
         if ($fullItem['type'] == ITEM_TYPE_AGGREGATE) {
             $params_num = $item_key_parser->getParamsNum();
             if (!str_in_array($item_key_parser->getKey(), ['grpmax', 'grpmin', 'grpsum', 'grpavg']) || $params_num > 4 || $params_num < 3 || $params_num == 3 && $item_key_parser->getParam(2) !== 'last' || !str_in_array($item_key_parser->getParam(2), ['last', 'min', 'max', 'avg', 'sum', 'count'])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Key "%1$s" does not match <grpmax|grpmin|grpsum|grpavg>["Host group(s)", "Item key",' . ' "<last|min|max|avg|sum|count>", "parameter"].', $item_key_parser->getKey()));
             }
         }
         // type of information
         if ($fullItem['type'] == ITEM_TYPE_AGGREGATE && $fullItem['value_type'] != ITEM_VALUE_TYPE_UINT64 && $fullItem['value_type'] != ITEM_VALUE_TYPE_FLOAT) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('Type of information must be "Numeric (unsigned)" or "Numeric (float)" for aggregate items.'));
         }
         // update interval
         if ($fullItem['type'] != ITEM_TYPE_TRAPPER && $fullItem['type'] != ITEM_TYPE_SNMPTRAP) {
             // delay must be between 0 and 86400, if delay is 0, delay_flex interval must be set.
             if ($fullItem['delay'] < 0 || $fullItem['delay'] > SEC_PER_DAY || $fullItem['delay'] == 0 && $fullItem['delay_flex'] === '') {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('Item will not be refreshed. Please enter a correct update interval.'));
             }
             // Don't parse empty strings, they will not be valid.
             if ($fullItem['delay_flex'] === '') {
                 continue;
             }
             // Validate item delay_flex string. First check syntax with parser, then validate time ranges.
             $item_delay_flex_parser = new CItemDelayFlexParser($fullItem['delay_flex']);
             if ($item_delay_flex_parser->isValid()) {
                 $delay_flex_validator = new CItemDelayFlexValidator();
                 if ($delay_flex_validator->validate($item_delay_flex_parser->getIntervals())) {
                     // Some valid intervals exist at this point.
                     $flexible_intervals = $item_delay_flex_parser->getFlexibleIntervals();
                     // If there are no flexible intervals, skip the next check calculation.
                     if (!$flexible_intervals) {
                         continue;
                     }
                     $nextCheck = calculateItemNextCheck(0, $fullItem['delay'], $item_delay_flex_parser->getFlexibleIntervals($flexible_intervals), time());
                     if ($nextCheck == ZBX_JAN_2038) {
                         self::exception(ZBX_API_ERROR_PARAMETERS, _('Item will not be refreshed. Please enter a correct update interval.'));
                     }
                 } else {
                     self::exception(ZBX_API_ERROR_PARAMETERS, $delay_flex_validator->getError());
                 }
             } else {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _s('Invalid interval "%1$s": %2$s.', $fullItem['delay_flex'], $item_delay_flex_parser->getError()));
             }
         }
         // ssh, telnet
         if ($fullItem['type'] == ITEM_TYPE_SSH || $fullItem['type'] == ITEM_TYPE_TELNET) {
             if (zbx_empty($fullItem['username'])) {
                 self::exception(ZBX_API_ERROR_PARAMETERS, _('No authentication user name specified.'));
             }
             if ($fullItem['type'] == ITEM_TYPE_SSH && $fullItem['authtype'] == ITEM_AUTHTYPE_PUBLICKEY) {
                 if (zbx_empty($fullItem['publickey'])) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _('No public key file specified.'));
                 }
                 if (zbx_empty($fullItem['privatekey'])) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _('No private key file specified.'));
                 }
             }
         }
         // snmp trap
         if ($fullItem['type'] == ITEM_TYPE_SNMPTRAP && $fullItem['key_'] !== 'snmptrap.fallback' && $item_key_parser->getKey() !== 'snmptrap') {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('SNMP trap key is invalid.'));
         }
         // snmp oid
         if (in_array($fullItem['type'], [ITEM_TYPE_SNMPV1, ITEM_TYPE_SNMPV2C, ITEM_TYPE_SNMPV3]) && zbx_empty($fullItem['snmp_oid'])) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('No SNMP OID specified.'));
         }
         // snmp community
         if (in_array($fullItem['type'], [ITEM_TYPE_SNMPV1, ITEM_TYPE_SNMPV2C]) && zbx_empty($fullItem['snmp_community'])) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _('No SNMP community specified.'));
         }
         // snmp port
         if (isset($fullItem['port']) && !zbx_empty($fullItem['port']) && !validatePortNumberOrMacro($fullItem['port'])) {
             self::exception(ZBX_API_ERROR_PARAMETERS, _s('Item "%1$s:%2$s" has invalid port: "%3$s".', $fullItem['name'], $fullItem['key_'], $fullItem['port']));
         }
         if (isset($fullItem['snmpv3_securitylevel']) && $fullItem['snmpv3_securitylevel'] != ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV) {
             // snmpv3 authprotocol
             if (str_in_array($fullItem['snmpv3_securitylevel'], [ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV, ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV])) {
                 if (isset($fullItem['snmpv3_authprotocol']) && (zbx_empty($fullItem['snmpv3_authprotocol']) || !str_in_array($fullItem['snmpv3_authprotocol'], [ITEM_AUTHPROTOCOL_MD5, ITEM_AUTHPROTOCOL_SHA]))) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect authentication protocol for item "%1$s".', $fullItem['name']));
                 }
             }
             // snmpv3 privprotocol
             if ($fullItem['snmpv3_securitylevel'] == ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV) {
                 if (isset($fullItem['snmpv3_privprotocol']) && (zbx_empty($fullItem['snmpv3_privprotocol']) || !str_in_array($fullItem['snmpv3_privprotocol'], [ITEM_PRIVPROTOCOL_DES, ITEM_PRIVPROTOCOL_AES]))) {
                     self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect privacy protocol for item "%1$s".', $fullItem['name']));
                 }
             }
         }
         if (isset($item['applications']) && $item['applications']) {
             /*
              * 'flags' is available for update and item prototypes.
              * Don't allow discovered or any other application types for item prototypes in 'applications' option.
              */
             if (array_key_exists('flags', $fullItem) && $fullItem['flags'] == ZBX_FLAG_DISCOVERY_PROTOTYPE) {
                 foreach ($host['applications'] as $num => $application) {
                     if ($application['flags'] != ZBX_FLAG_DISCOVERY_NORMAL) {
                         unset($host['applications'][$num]);
                     }
                 }
             }
             // check that the given applications belong to the item's host
             $dbApplicationIds = zbx_objectValues($host['applications'], 'applicationid');
             foreach ($item['applications'] as $appId) {
                 if (!in_array($appId, $dbApplicationIds)) {
                     $error = _s('Application with ID "%1$s" is not available on "%2$s".', $appId, $host['name']);
                     self::exception(ZBX_API_ERROR_PARAMETERS, $error);
                 }
             }
         }
         $this->checkSpecificFields($fullItem);
     }
     unset($item);
     $this->checkExistingItems($items);
 }