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
21require_once dirname(__FILE__).'/include/config.inc.php';
22require_once dirname(__FILE__).'/include/hosts.inc.php';
23require_once dirname(__FILE__).'/include/items.inc.php';
24require_once dirname(__FILE__).'/include/forms.inc.php';
25
26$page['title'] = _('Configuration of items');
27$page['file'] = 'items.php';
28$page['scripts'] = ['class.cviewswitcher.js', 'multiselect.js', 'items.js'];
29
30require_once dirname(__FILE__).'/include/page_header.php';
31
32$paramsFieldName = getParamFieldNameByType(getRequest('type', 0));
33
34// VAR	TYPE	OPTIONAL	FLAGS	VALIDATION	EXCEPTION
35$fields = [
36	'hostid' =>					[T_ZBX_INT, O_OPT, P_SYS,	DB_ID.NOT_ZERO, 'isset({form}) && !isset({itemid})'],
37	'interfaceid' =>			[T_ZBX_INT, O_OPT, P_SYS,	DB_ID,		null, _('Interface')],
38	'copy_type' =>				[T_ZBX_INT, O_OPT, P_SYS,	IN('0,1,2'), 'isset({copy})'],
39	'copy_mode' =>				[T_ZBX_INT, O_OPT, P_SYS,	IN('0'),	null],
40	'itemid' =>					[T_ZBX_INT, O_NO,	P_SYS,	DB_ID,		'isset({form}) && {form} == "update"'],
41	'name' =>					[T_ZBX_STR, O_OPT, null,	NOT_EMPTY, 'isset({add}) || isset({update})', _('Name')],
42	'description' =>			[T_ZBX_STR, O_OPT, null,	null,		'isset({add}) || isset({update})'],
43	'key' =>					[T_ZBX_STR, O_OPT, null,	NOT_EMPTY, 'isset({add}) || isset({update})', _('Key')],
44	'delay' =>					[T_ZBX_INT, O_OPT, null,	BETWEEN(0, SEC_PER_DAY),
45		'(isset({add}) || isset({update})) && isset({type}) && {type}!='.ITEM_TYPE_TRAPPER.' && {type}!='.ITEM_TYPE_SNMPTRAP,
46		_('Update interval (in sec)')],
47	'delay_flex' =>				[T_ZBX_STR, O_OPT, null,	null,			null],
48	'history' =>				[T_ZBX_INT, O_OPT, null,	BETWEEN(0, 65535), 'isset({add}) || isset({update})',
49		_('History storage period')
50	],
51	'status' =>					[T_ZBX_INT, O_OPT, null,	IN([ITEM_STATUS_DISABLED, ITEM_STATUS_ACTIVE]), null],
52	'type' =>					[T_ZBX_INT, O_OPT, null,
53		IN([-1, ITEM_TYPE_ZABBIX, ITEM_TYPE_SNMPV1, ITEM_TYPE_TRAPPER, ITEM_TYPE_SIMPLE, ITEM_TYPE_SNMPV2C,
54			ITEM_TYPE_INTERNAL, ITEM_TYPE_SNMPV3, ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_AGGREGATE, ITEM_TYPE_EXTERNAL,
55			ITEM_TYPE_DB_MONITOR, ITEM_TYPE_IPMI, ITEM_TYPE_SSH, ITEM_TYPE_TELNET, ITEM_TYPE_JMX, ITEM_TYPE_CALCULATED, ITEM_TYPE_SNMPTRAP]), 'isset({add}) || isset({update})'],
56	'trends' =>					[T_ZBX_INT, O_OPT, null,	BETWEEN(0, 65535), '(isset({add}) || isset({update})) && isset({value_type}) && '.
57		IN(ITEM_VALUE_TYPE_FLOAT.','.ITEM_VALUE_TYPE_UINT64, 'value_type'), _('Trend storage period')
58	],
59	'value_type' =>				[T_ZBX_INT, O_OPT, null,	IN('0,1,2,3,4'), 'isset({add}) || isset({update})'],
60	'data_type' =>				[T_ZBX_INT, O_OPT, null,
61		IN(ITEM_DATA_TYPE_DECIMAL.','.ITEM_DATA_TYPE_OCTAL.','.ITEM_DATA_TYPE_HEXADECIMAL.','.ITEM_DATA_TYPE_BOOLEAN),
62		'(isset({add}) || isset({update})) && isset({value_type}) && {value_type} == '.ITEM_VALUE_TYPE_UINT64],
63	'valuemapid' =>				[T_ZBX_INT, O_OPT, null,	DB_ID,		'(isset({add}) || isset({update})) && isset({value_type}) && '.
64		IN(ITEM_VALUE_TYPE_FLOAT.','.ITEM_VALUE_TYPE_UINT64, 'value_type')],
65	'authtype' =>				[T_ZBX_INT, O_OPT, null,	IN(ITEM_AUTHTYPE_PASSWORD.','.ITEM_AUTHTYPE_PUBLICKEY),
66		'(isset({add}) || isset({update})) && isset({type}) && {type}=='.ITEM_TYPE_SSH],
67	'username' =>				[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
68		'(isset({add}) || isset({update})) && isset({type}) && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_TELNET, 'type'), _('User name')],
69	'password' =>				[T_ZBX_STR, O_OPT, null,	null,
70		'(isset({add}) || isset({update})) && isset({type}) && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_TELNET, 'type')],
71	'publickey' =>				[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
72		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SSH.' && {authtype} == '.ITEM_AUTHTYPE_PUBLICKEY],
73	'privatekey' =>				[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
74		'(isset({add}) || isset({update})) && isset({type}) && ({type}) == '.ITEM_TYPE_SSH.' && ({authtype}) == '.ITEM_AUTHTYPE_PUBLICKEY],
75	$paramsFieldName =>			[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,	'(isset({add}) || isset({update})) && isset({type}) && '.
76		IN(ITEM_TYPE_SSH.','.ITEM_TYPE_DB_MONITOR.','.ITEM_TYPE_TELNET.','.ITEM_TYPE_CALCULATED, 'type'),
77		getParamFieldLabelByType(getRequest('type', 0))],
78	'inventory_link' =>			[T_ZBX_INT, O_OPT, null,	BETWEEN(0, 65535), '(isset({add}) || isset({update})) && {value_type} != '.ITEM_VALUE_TYPE_LOG],
79	'snmp_community' =>			[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
80		'(isset({add}) || isset({update})) && isset({type}) && '.IN(ITEM_TYPE_SNMPV1.','.ITEM_TYPE_SNMPV2C, 'type'), _('SNMP community')],
81	'snmp_oid' =>				[T_ZBX_STR, O_OPT, null,	NOT_EMPTY, '(isset({add}) || isset({update})) && isset({type}) && '.IN(
82		ITEM_TYPE_SNMPV1.','.ITEM_TYPE_SNMPV2C.','.ITEM_TYPE_SNMPV3, 'type'), _('SNMP OID')],
83	'port' =>					[T_ZBX_STR, O_OPT, null,	BETWEEN(0, 65535), '(isset({add}) || isset({update})) && isset({type}) && '.IN(
84		ITEM_TYPE_SNMPV1.','.ITEM_TYPE_SNMPV2C.','.ITEM_TYPE_SNMPV3, 'type'), _('Port')],
85	'snmpv3_securitylevel' =>	[T_ZBX_INT, O_OPT, null,	IN('0,1,2'),
86		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3],
87	'snmpv3_contextname' =>	[T_ZBX_STR, O_OPT, null,	null,
88		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3],
89	'snmpv3_securityname' =>	[T_ZBX_STR, O_OPT, null,	null,
90		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3],
91	'snmpv3_authprotocol' =>	[T_ZBX_INT, O_OPT, null,	IN(ITEM_AUTHPROTOCOL_MD5.','.ITEM_AUTHPROTOCOL_SHA),
92		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3.' && ({snmpv3_securitylevel} == '.
93		ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV.' || {snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV.')'],
94	'snmpv3_authpassphrase' =>	[T_ZBX_STR, O_OPT, null,	null,
95		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3.' && ({snmpv3_securitylevel} == '.
96		ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV.' || {snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV.')'],
97	'snmpv3_privprotocol' =>	[T_ZBX_INT, O_OPT, null,	IN(ITEM_PRIVPROTOCOL_DES.','.ITEM_PRIVPROTOCOL_AES),
98		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3.' && {snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV],
99	'snmpv3_privpassphrase' =>	[T_ZBX_STR, O_OPT, null,	null,
100		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_SNMPV3.' && {snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV],
101	'ipmi_sensor' =>			[T_ZBX_STR, O_OPT, P_NO_TRIM, NOT_EMPTY,
102		'(isset({add}) || isset({update})) && isset({type}) && {type} == '.ITEM_TYPE_IPMI, _('IPMI sensor')],
103	'trapper_hosts' =>			[T_ZBX_STR, O_OPT, null,	null,		'(isset({add}) || isset({update})) && isset({type}) && {type} == 2'],
104	'units' =>					[T_ZBX_STR, O_OPT, null,	null,		'(isset({add}) || isset({update})) && isset({value_type}) && '.
105		IN('0,3', 'value_type').'isset({data_type}) && {data_type} != '.ITEM_DATA_TYPE_BOOLEAN],
106	'multiplier' =>				[T_ZBX_INT, O_OPT, null,	null,		null],
107	'delta' =>					[T_ZBX_INT, O_OPT, null,	IN('0,1,2'), '(isset({add}) || isset({update})) && isset({value_type}) && '.
108		IN('0,3', 'value_type').'isset({data_type}) && {data_type} != '.ITEM_DATA_TYPE_BOOLEAN],
109	'formula' =>				[T_ZBX_DBL_STR, O_OPT, null,
110		'({value_type} == 0 && {} != 0) || ({value_type} == 3 && {} > 0)',
111		'(isset({add}) || isset({update})) && isset({multiplier}) && {multiplier} == 1', _('Custom multiplier')
112	],
113	'logtimefmt' =>				[T_ZBX_STR, O_OPT, null,	null,
114		'(isset({add}) || isset({update})) && isset({value_type}) && {value_type} == 2'],
115	'group_itemid' =>			[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
116	'copy_targetid' =>		    [T_ZBX_INT, O_OPT, null,	DB_ID,		null],
117	'copy_groupid' =>		    [T_ZBX_INT, O_OPT, P_SYS,	DB_ID,		'isset({copy}) && (isset({copy_type}) && {copy_type} == 0)'],
118	'new_application' =>		[T_ZBX_STR, O_OPT, null,	null,		'isset({add}) || isset({update})'],
119	'visible' =>		[T_ZBX_STR, O_OPT, null,		null,		null],
120	'applications' =>			[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
121	'new_applications' =>		[T_ZBX_STR, O_OPT, null,	null,		null],
122	'del_history' =>			[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
123	// actions
124	'action' =>					[T_ZBX_STR, O_OPT, P_SYS|P_ACT,
125									IN('"item.massclearhistory","item.masscopyto","item.massdelete",'.
126										'"item.massdisable","item.massenable","item.massupdateform"'
127									),
128									null
129								],
130	'add' =>					[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
131	'update' =>					[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
132	'clone' =>					[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
133	'copy' =>					[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
134	'delete' =>					[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
135	'massupdate' =>				[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
136	'cancel' =>					[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
137	'form' =>					[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
138	'form_refresh' =>			[T_ZBX_INT, O_OPT, null,	null,		null],
139	// filter
140	'filter_set' =>				[T_ZBX_STR, O_OPT, null,	null,		null],
141	'filter_rst' =>				[T_ZBX_STR, O_OPT, null,	null,		null],
142	'filter_groupid' =>			[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
143	'filter_hostid' =>			[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
144	'filter_application' =>		[T_ZBX_STR, O_OPT, null,	null,		null],
145	'filter_name' =>			[T_ZBX_STR, O_OPT, null,	null,		null],
146	'filter_type' =>			[T_ZBX_INT, O_OPT, null,
147		IN([-1, ITEM_TYPE_ZABBIX, ITEM_TYPE_SNMPV1, ITEM_TYPE_TRAPPER, ITEM_TYPE_SIMPLE, ITEM_TYPE_SNMPV2C,
148		ITEM_TYPE_INTERNAL, ITEM_TYPE_SNMPV3, ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_AGGREGATE, ITEM_TYPE_EXTERNAL, ITEM_TYPE_DB_MONITOR,
149		ITEM_TYPE_IPMI, ITEM_TYPE_SSH, ITEM_TYPE_TELNET, ITEM_TYPE_JMX, ITEM_TYPE_CALCULATED, ITEM_TYPE_SNMPTRAP]), null],
150	'filter_key' =>				[T_ZBX_STR, O_OPT, null,	null,		null],
151	'filter_snmp_community' =>	[T_ZBX_STR, O_OPT, null,	null,		null],
152	'filter_snmpv3_securityname' => [T_ZBX_STR, O_OPT, null, null,		null],
153	'filter_snmp_oid' =>		[T_ZBX_STR, O_OPT, null,	null,		null],
154	'filter_port' =>			[T_ZBX_INT, O_OPT, P_UNSET_EMPTY, BETWEEN(0, 65535), null, _('Port')],
155	'filter_value_type' =>		[T_ZBX_INT, O_OPT, null,	IN('-1,0,1,2,3,4'), null],
156	'filter_data_type' =>		[T_ZBX_INT, O_OPT, null,	BETWEEN(-1, ITEM_DATA_TYPE_BOOLEAN), null],
157	'filter_delay' =>			[T_ZBX_INT, O_OPT, P_UNSET_EMPTY, BETWEEN(0, SEC_PER_DAY), null, _('Update interval')],
158	'filter_history' =>			[T_ZBX_INT, O_OPT, P_UNSET_EMPTY, BETWEEN(0, 65535), null,	_('History')],
159	'filter_trends' =>			[T_ZBX_INT, O_OPT, P_UNSET_EMPTY, BETWEEN(0, 65535), null, _('Trends')],
160	'filter_status' =>			[T_ZBX_INT, O_OPT, null,	IN([-1, ITEM_STATUS_ACTIVE, ITEM_STATUS_DISABLED]), null],
161	'filter_state' =>			[T_ZBX_INT, O_OPT, null,	IN([-1, ITEM_STATE_NORMAL, ITEM_STATE_NOTSUPPORTED]), null],
162	'filter_templated_items' => [T_ZBX_INT, O_OPT, null,	IN('-1,0,1'), null],
163	'filter_with_triggers' =>	[T_ZBX_INT, O_OPT, null,	IN('-1,0,1'), null],
164	'filter_ipmi_sensor' =>		[T_ZBX_STR, O_OPT, null,	null,		null],
165	// subfilters
166	'subfilter_set' =>			[T_ZBX_STR, O_OPT, null,	null,		null],
167	'subfilter_apps' =>			[T_ZBX_STR, O_OPT, null,	null,		null],
168	'subfilter_types' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
169	'subfilter_value_types' =>	[T_ZBX_INT, O_OPT, null,	null,		null],
170	'subfilter_status' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
171	'subfilter_state' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
172	'subfilter_templated_items' => [T_ZBX_INT, O_OPT, null, null,		null],
173	'subfilter_with_triggers' => [T_ZBX_INT, O_OPT, null,	null,		null],
174	'subfilter_hosts' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
175	'subfilter_interval' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
176	'subfilter_history' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
177	'subfilter_trends' =>		[T_ZBX_INT, O_OPT, null,	null,		null],
178	// sort and sortorder
179	'sort' =>					[T_ZBX_STR, O_OPT, P_SYS,
180									IN('"delay","history","key_","name","status","trends","type"'),
181									null
182								],
183	'sortorder' =>				[T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'),	null]
184];
185check_fields($fields);
186
187$_REQUEST['params'] = getRequest($paramsFieldName, '');
188unset($_REQUEST[$paramsFieldName]);
189
190$subfiltersList = ['subfilter_apps', 'subfilter_types', 'subfilter_value_types', 'subfilter_status',
191	'subfilter_state', 'subfilter_templated_items', 'subfilter_with_triggers', 'subfilter_hosts', 'subfilter_interval',
192	'subfilter_history', 'subfilter_trends'
193];
194
195/*
196 * Permissions
197 */
198$itemId = getRequest('itemid');
199if ($itemId) {
200	$item = API::Item()->get([
201		'output' => ['itemid'],
202		'itemids' => $itemId,
203		'filter' => ['flags' => [ZBX_FLAG_DISCOVERY_NORMAL]],
204		'selectHosts' => ['status'],
205		'editable' => true,
206		'preservekeys' => true
207	]);
208	if (!$item) {
209		access_deny();
210	}
211	$item = reset($item);
212	$hosts = $item['hosts'];
213}
214else {
215	$hostId = getRequest('hostid');
216	if ($hostId) {
217		$hosts = API::Host()->get([
218			'output' => ['status'],
219			'hostids' => $hostId,
220			'templated_hosts' => true,
221			'editable' => true
222		]);
223		if (!$hosts) {
224			access_deny();
225		}
226	}
227}
228
229$filterGroupId = getRequest('filter_groupid');
230if ($filterGroupId && !API::HostGroup()->isWritable([$filterGroupId])) {
231	access_deny();
232}
233
234$filterHostId = getRequest('filter_hostid');
235if ($filterHostId && !API::Host()->isWritable([$filterHostId])) {
236	access_deny();
237}
238
239if (!empty($hosts)) {
240	$host = reset($hosts);
241	$_REQUEST['filter_hostid'] = $host['hostid'];
242}
243
244/*
245 * Filter
246 */
247if (hasRequest('filter_set')) {
248	CProfile::update('web.items.filter_groupid', getRequest('filter_groupid', 0), PROFILE_TYPE_ID);
249	CProfile::update('web.items.filter_hostid', getRequest('filter_hostid', 0), PROFILE_TYPE_ID);
250	CProfile::update('web.items.filter_application', getRequest('filter_application', ''), PROFILE_TYPE_STR);
251	CProfile::update('web.items.filter_name', getRequest('filter_name', ''), PROFILE_TYPE_STR);
252	CProfile::update('web.items.filter_type', getRequest('filter_type', -1), PROFILE_TYPE_INT);
253	CProfile::update('web.items.filter_key', getRequest('filter_key', ''), PROFILE_TYPE_STR);
254	CProfile::update('web.items.filter_snmp_community', getRequest('filter_snmp_community', ''), PROFILE_TYPE_STR);
255	CProfile::update('web.items.filter_snmpv3_securityname', getRequest('filter_snmpv3_securityname', ''),
256		PROFILE_TYPE_STR
257	);
258	CProfile::update('web.items.filter_snmp_oid', getRequest('filter_snmp_oid', ''), PROFILE_TYPE_STR);
259	CProfile::update('web.items.filter_port', getRequest('filter_port', ''), PROFILE_TYPE_STR);
260	CProfile::update('web.items.filter_value_type', getRequest('filter_value_type', -1), PROFILE_TYPE_INT);
261	CProfile::update('web.items.filter_data_type', getRequest('filter_data_type', -1), PROFILE_TYPE_INT);
262	CProfile::update('web.items.filter_delay', getRequest('filter_delay', ''), PROFILE_TYPE_STR);
263	CProfile::update('web.items.filter_history', getRequest('filter_history', ''), PROFILE_TYPE_STR);
264	CProfile::update('web.items.filter_trends', getRequest('filter_trends', ''), PROFILE_TYPE_STR);
265	CProfile::update('web.items.filter_status', getRequest('filter_status', -1), PROFILE_TYPE_INT);
266	CProfile::update('web.items.filter_state', getRequest('filter_state', -1), PROFILE_TYPE_INT);
267	CProfile::update('web.items.filter_templated_items', getRequest('filter_templated_items', -1), PROFILE_TYPE_INT);
268	CProfile::update('web.items.filter_with_triggers', getRequest('filter_with_triggers', -1), PROFILE_TYPE_INT);
269	CProfile::update('web.items.filter_ipmi_sensor', getRequest('filter_ipmi_sensor', ''), PROFILE_TYPE_STR);
270
271	// subfilters
272	foreach ($subfiltersList as $name) {
273		$_REQUEST[$name] = [];
274		CProfile::update('web.items.'.$name, '', PROFILE_TYPE_STR);
275	}
276}
277elseif (hasRequest('filter_rst')) {
278	DBStart();
279	CProfile::delete('web.items.filter_groupid');
280	CProfile::delete('web.items.filter_application');
281	CProfile::delete('web.items.filter_name');
282	CProfile::delete('web.items.filter_type');
283	CProfile::delete('web.items.filter_key');
284	CProfile::delete('web.items.filter_snmp_community');
285	CProfile::delete('web.items.filter_snmpv3_securityname');
286	CProfile::delete('web.items.filter_snmp_oid');
287	CProfile::delete('web.items.filter_port');
288	CProfile::delete('web.items.filter_value_type');
289	CProfile::delete('web.items.filter_data_type');
290	CProfile::delete('web.items.filter_delay');
291	CProfile::delete('web.items.filter_history');
292	CProfile::delete('web.items.filter_trends');
293	CProfile::delete('web.items.filter_status');
294	CProfile::delete('web.items.filter_state');
295	CProfile::delete('web.items.filter_templated_items');
296	CProfile::delete('web.items.filter_with_triggers');
297	CProfile::delete('web.items.filter_ipmi_sensor');
298	DBend();
299}
300
301$_REQUEST['filter_groupid'] = CProfile::get('web.items.filter_groupid', 0);
302$_REQUEST['filter_hostid'] = CProfile::get('web.items.filter_hostid', 0);
303$_REQUEST['filter_application'] = CProfile::get('web.items.filter_application', '');
304$_REQUEST['filter_name'] = CProfile::get('web.items.filter_name', '');
305$_REQUEST['filter_type'] = CProfile::get('web.items.filter_type', -1);
306$_REQUEST['filter_key'] = CProfile::get('web.items.filter_key', '');
307$_REQUEST['filter_snmp_community'] = CProfile::get('web.items.filter_snmp_community', '');
308$_REQUEST['filter_snmpv3_securityname'] = CProfile::get('web.items.filter_snmpv3_securityname', '');
309$_REQUEST['filter_snmp_oid'] = CProfile::get('web.items.filter_snmp_oid', '');
310$_REQUEST['filter_port'] = CProfile::get('web.items.filter_port', '');
311$_REQUEST['filter_value_type'] = CProfile::get('web.items.filter_value_type', -1);
312$_REQUEST['filter_data_type'] = CProfile::get('web.items.filter_data_type', -1);
313$_REQUEST['filter_delay'] = CProfile::get('web.items.filter_delay', '');
314$_REQUEST['filter_history'] = CProfile::get('web.items.filter_history', '');
315$_REQUEST['filter_trends'] = CProfile::get('web.items.filter_trends', '');
316$_REQUEST['filter_status'] = CProfile::get('web.items.filter_status', -1);
317$_REQUEST['filter_state'] = CProfile::get('web.items.filter_state', -1);
318$_REQUEST['filter_templated_items'] = CProfile::get('web.items.filter_templated_items', -1);
319$_REQUEST['filter_with_triggers'] = CProfile::get('web.items.filter_with_triggers', -1);
320$_REQUEST['filter_ipmi_sensor'] = CProfile::get('web.items.filter_ipmi_sensor', '');
321
322// subfilters
323foreach ($subfiltersList as $name) {
324	if (isset($_REQUEST['subfilter_set'])) {
325		$_REQUEST[$name] = getRequest($name, []);
326		CProfile::update('web.items.'.$name, implode(';', $_REQUEST[$name]), PROFILE_TYPE_STR);
327	}
328	else {
329		$_REQUEST[$name] = [];
330		$subfiltersVal = CProfile::get('web.items.'.$name);
331		if (!zbx_empty($subfiltersVal)) {
332			$_REQUEST[$name] = explode(';', $subfiltersVal);
333			$_REQUEST[$name] = array_combine($_REQUEST[$name], $_REQUEST[$name]);
334		}
335	}
336}
337
338$filterHostId = getRequest('filter_hostid');
339if (!hasRequest('form') && $filterHostId) {
340	if (!isset($host)) {
341		$host = API::Host()->get([
342			'output' => ['hostid'],
343			'hostids' => $filterHostId
344		]);
345		if (!$host) {
346			$host = API::Template()->get([
347				'output' => ['templateid'],
348				'templateids' => $filterHostId
349			]);
350		}
351		$host = reset($host);
352	}
353	if ($host) {
354		$_REQUEST['hostid'] = isset($host['hostid']) ? $host['hostid'] : $host['templateid'];
355	}
356}
357
358/*
359 * Actions
360 */
361$result = false;
362if (isset($_REQUEST['delete']) && isset($_REQUEST['itemid'])) {
363	$result = false;
364	if ($item = get_item_by_itemid($_REQUEST['itemid'])) {
365		$result = API::Item()->delete([getRequest('itemid')]);
366	}
367
368	if ($result) {
369		uncheckTableRows(getRequest('hostid'));
370	}
371	unset($_REQUEST['itemid'], $_REQUEST['form']);
372	show_messages($result, _('Item deleted'), _('Cannot delete item'));
373}
374elseif (isset($_REQUEST['clone']) && isset($_REQUEST['itemid'])) {
375	unset($_REQUEST['itemid']);
376	$_REQUEST['form'] = 'clone';
377}
378elseif (hasRequest('add') || hasRequest('update')) {
379	$applications = getRequest('applications', []);
380	$application = reset($applications);
381	if (empty($application)) {
382		array_shift($applications);
383	}
384
385	DBstart();
386	$result = true;
387
388	if (!zbx_empty($_REQUEST['new_application'])) {
389		$new_appid = API::Application()->create([
390			'name' => $_REQUEST['new_application'],
391			'hostid' => getRequest('hostid')
392		]);
393		if ($new_appid) {
394			$new_appid = reset($new_appid['applicationids']);
395			$applications[$new_appid] = $new_appid;
396		}
397		else {
398			$result = false;
399		}
400	}
401
402	/*
403	 * Intially validate "delay_flex" field one by one to make sure it does not have interval separator ";".
404	 * Skip empty fields and convert "delay_flex" array to string glued with ";" which is later validated through API.
405	 */
406	$delay_flex = '';
407	$intervals = [];
408
409	if (getRequest('delay_flex')) {
410		foreach (getRequest('delay_flex') as $interval) {
411			if ($interval['type'] == ITEM_DELAY_FLEX_TYPE_FLEXIBLE) {
412				if ($interval['delay'] === '' && $interval['period'] === '') {
413					continue;
414				}
415
416				if (strpos($interval['delay'], ';') !== false) {
417					$result = false;
418					info(_s('Invalid interval "%1$s".', $interval['delay']));
419					break;
420				}
421				elseif (strpos($interval['period'], ';')  !== false) {
422					$result = false;
423					info(_s('Invalid interval "%1$s".', $interval['period']));
424					break;
425				}
426
427				$intervals[] = $interval['delay'].'/'.$interval['period'];
428			}
429			else {
430				if ($interval['schedule'] === '') {
431					continue;
432				}
433
434				if (strpos($interval['schedule'], ';') !== false) {
435					$result = false;
436					info(_s('Invalid interval "%1$s".', $interval['schedule']));
437					break;
438				}
439
440				$intervals[] = $interval['schedule'];
441			}
442		}
443
444		if ($intervals) {
445			$delay_flex = join(';', $intervals);
446		}
447	}
448
449	if ($result) {
450		$item = [
451			'name' => getRequest('name'),
452			'description' => getRequest('description'),
453			'key_' => getRequest('key'),
454			'hostid' => getRequest('hostid'),
455			'interfaceid' => getRequest('interfaceid', 0),
456			'delay' => getRequest('delay'),
457			'history' => getRequest('history'),
458			'status' => getRequest('status', ITEM_STATUS_DISABLED),
459			'type' => getRequest('type'),
460			'snmp_community' => getRequest('snmp_community'),
461			'snmp_oid' => getRequest('snmp_oid'),
462			'value_type' => getRequest('value_type'),
463			'trapper_hosts' => getRequest('trapper_hosts'),
464			'port' => getRequest('port'),
465			'units' => getRequest('units'),
466			'multiplier' => getRequest('multiplier', 0),
467			'delta' => getRequest('delta'),
468			'snmpv3_contextname' => getRequest('snmpv3_contextname'),
469			'snmpv3_securityname' => getRequest('snmpv3_securityname'),
470			'snmpv3_securitylevel' => getRequest('snmpv3_securitylevel'),
471			'snmpv3_authprotocol' => getRequest('snmpv3_authprotocol'),
472			'snmpv3_authpassphrase' => getRequest('snmpv3_authpassphrase'),
473			'snmpv3_privprotocol' => getRequest('snmpv3_privprotocol'),
474			'snmpv3_privpassphrase' => getRequest('snmpv3_privpassphrase'),
475			'formula' => getRequest('formula', '1'),
476			'trends' => getRequest('trends'),
477			'logtimefmt' => getRequest('logtimefmt'),
478			'valuemapid' => getRequest('valuemapid'),
479			'delay_flex' => $delay_flex,
480			'authtype' => getRequest('authtype'),
481			'username' => getRequest('username'),
482			'password' => getRequest('password'),
483			'publickey' => getRequest('publickey'),
484			'privatekey' => getRequest('privatekey'),
485			'params' => getRequest('params'),
486			'ipmi_sensor' => getRequest('ipmi_sensor'),
487			'data_type' => getRequest('data_type'),
488			'inventory_link' => getRequest('inventory_link')
489		];
490
491		if (hasRequest('update')) {
492			$itemId = getRequest('itemid');
493
494			$dbItem = get_item_by_itemid_limited($itemId);
495			$dbItem['applications'] = get_applications_by_itemid($itemId);
496
497			// unset snmpv3 fields
498			if ($item['snmpv3_securitylevel'] == ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV) {
499				$item['snmpv3_authprotocol'] = ITEM_AUTHPROTOCOL_MD5;
500				$item['snmpv3_privprotocol'] = ITEM_PRIVPROTOCOL_DES;
501			}
502			elseif ($item['snmpv3_securitylevel'] == ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV) {
503				$item['snmpv3_privprotocol'] = ITEM_PRIVPROTOCOL_DES;
504			}
505
506			$item = CArrayHelper::unsetEqualValues($item, $dbItem);
507			$item['itemid'] = $itemId;
508
509			// compare applications
510			natsort($dbItem['applications']);
511			natsort($applications);
512			if (array_values($dbItem['applications']) !== array_values($applications)) {
513				$item['applications'] = $applications;
514			}
515
516			$result = API::Item()->update($item);
517		}
518		else {
519			$item['applications'] = $applications;
520
521			$result = API::Item()->create($item);
522		}
523	}
524
525	$result = DBend($result);
526
527	if (hasRequest('itemid')) {
528		show_messages($result, _('Item updated'), _('Cannot update item'));
529	}
530	else {
531		show_messages($result, _('Item added'), _('Cannot add item'));
532	}
533
534	if ($result) {
535		unset($_REQUEST['itemid'], $_REQUEST['form']);
536		uncheckTableRows(getRequest('hostid'));
537	}
538}
539// cleaning history for one item
540elseif (hasRequest('del_history') && hasRequest('itemid')) {
541	$result = false;
542
543	$itemId = getRequest('itemid');
544
545	$items = API::Item()->get([
546		'output' => ['key_'],
547		'itemids' => [$itemId],
548		'selectHosts' => ['name'],
549		'editable' => true
550	]);
551
552	if ($items) {
553		DBstart();
554
555		$result = deleteHistoryByItemIds([$itemId]);
556
557		if ($result) {
558			$item = reset($items);
559			$host = reset($item['hosts']);
560
561			add_audit(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_ITEM, _('Item').' ['.$item['key_'].'] ['.$itemId.'] '.
562				_('Host').' ['.$host['name'].'] '._('History cleared')
563			);
564		}
565
566		$result = DBend($result);
567	}
568
569	show_messages($result, _('History cleared'), _('Cannot clear history'));
570}
571// mass update
572elseif (hasRequest('massupdate') && hasRequest('group_itemid')) {
573	$visible = getRequest('visible', []);
574
575	$result = true;
576
577	if (isset($visible['delay_flex'])) {
578		$delay_flex = '';
579		$intervals = [];
580
581		if (getRequest('delay_flex')) {
582			foreach (getRequest('delay_flex') as $interval) {
583				if ($interval['type'] == ITEM_DELAY_FLEX_TYPE_FLEXIBLE) {
584					if ($interval['delay'] === '' && $interval['period'] === '') {
585						continue;
586					}
587
588					if (strpos($interval['delay'], ';') !== false) {
589						$result = false;
590						info(_s('Invalid interval "%1$s".', $interval['delay']));
591						break;
592					}
593					elseif (strpos($interval['period'], ';')  !== false) {
594						$result = false;
595						info(_s('Invalid interval "%1$s".', $interval['period']));
596						break;
597					}
598
599					$intervals[] = $interval['delay'].'/'.$interval['period'];
600				}
601				else {
602					if ($interval['schedule'] === '') {
603						continue;
604					}
605
606					if (strpos($interval['schedule'], ';') !== false) {
607						$result = false;
608						info(_s('Invalid interval "%1$s".', $interval['schedule']));
609						break;
610					}
611
612					$intervals[] = $interval['schedule'];
613				}
614			}
615
616			if ($intervals) {
617				$delay_flex = join(';', $intervals);
618			}
619		}
620	}
621	else {
622		$delay_flex = null;
623	}
624
625	$formula = getRequest('formula');
626	if ($formula === null) {
627		// no changes to formula/multiplier
628		$multiplier = null;
629	}
630	elseif ($formula === '0') {
631		// for mass update "magic" value '0' means that multiplier must be disabled and formula set to default value '1'
632		$multiplier = 0;
633		$formula = '1';
634	}
635	else {
636		// otherwise multiplier must be enabled with formula value entered by user
637		$multiplier = 1;
638	}
639
640	$applications = getRequest('applications');
641	if (isset($applications[0]) && $applications[0] == '0') {
642		$applications = [];
643	}
644
645	try {
646		DBstart();
647
648		// add new or existing applications
649		if (isset($visible['new_applications']) && !empty($_REQUEST['new_applications'])) {
650			foreach ($_REQUEST['new_applications'] as $newApplication) {
651				if (is_array($newApplication) && isset($newApplication['new'])) {
652					$newApplications[] = [
653						'name' => $newApplication['new'],
654						'hostid' => getRequest('hostid')
655					];
656				}
657				else {
658					$existApplication[] = $newApplication;
659				}
660			}
661
662			if (isset($newApplications)) {
663				if (!$createdApplication = API::Application()->create($newApplications)) {
664					throw new Exception();
665				}
666				if (isset($existApplication)) {
667					$existApplication = array_merge($existApplication, $createdApplication['applicationids']);
668				}
669				else {
670					$existApplication = $createdApplication['applicationids'];
671				}
672			}
673		}
674
675		if (isset($visible['applications'])) {
676			if (isset($_REQUEST['applications'])) {
677				if (isset($existApplication)) {
678					$applications = array_unique(array_merge($_REQUEST['applications'], $existApplication));
679				}
680				else {
681					$applications = $_REQUEST['applications'];
682				}
683			}
684			else {
685				if (isset($existApplication)){
686					$applications = $existApplication;
687				}
688				else {
689					$applications = [];
690				}
691			}
692		}
693
694		$item = [
695			'interfaceid' => getRequest('interfaceid'),
696			'description' => getRequest('description'),
697			'delay' => getRequest('delay'),
698			'history' => getRequest('history'),
699			'status' => getRequest('status'),
700			'type' => getRequest('type'),
701			'snmp_community' => getRequest('snmp_community'),
702			'snmp_oid' => getRequest('snmp_oid'),
703			'value_type' => getRequest('value_type'),
704			'trapper_hosts' => getRequest('trapper_hosts'),
705			'port' => getRequest('port'),
706			'units' => getRequest('units'),
707			'multiplier' => $multiplier,
708			'delta' => getRequest('delta'),
709			'snmpv3_contextname' => getRequest('snmpv3_contextname'),
710			'snmpv3_securityname' => getRequest('snmpv3_securityname'),
711			'snmpv3_securitylevel' => getRequest('snmpv3_securitylevel'),
712			'snmpv3_authprotocol' => getRequest('snmpv3_authprotocol'),
713			'snmpv3_authpassphrase' => getRequest('snmpv3_authpassphrase'),
714			'snmpv3_privprotocol' => getRequest('snmpv3_privprotocol'),
715			'snmpv3_privpassphrase' => getRequest('snmpv3_privpassphrase'),
716			'formula' => $formula,
717			'trends' => getRequest('trends'),
718			'logtimefmt' => getRequest('logtimefmt'),
719			'valuemapid' => getRequest('valuemapid'),
720			'delay_flex' => $delay_flex,
721			'authtype' => getRequest('authtype'),
722			'username' => getRequest('username'),
723			'password' => getRequest('password'),
724			'publickey' => getRequest('publickey'),
725			'privatekey' => getRequest('privatekey'),
726			'ipmi_sensor' => getRequest('ipmi_sensor'),
727			'applications' => $applications,
728			'data_type' => getRequest('data_type')
729		];
730
731		// add applications
732		if (!empty($existApplication) && (!isset($visible['applications']) || !isset($_REQUEST['applications']))) {
733			foreach ($existApplication as $linkApp) {
734				$linkApplications[] = ['applicationid' => $linkApp];
735			}
736			foreach (getRequest('group_itemid') as $linkItem) {
737				$linkItems[] = ['itemid' => $linkItem];
738			}
739			$linkApp = [
740				'applications' => $linkApplications,
741				'items' => $linkItems
742			];
743			API::Application()->massAdd($linkApp);
744		}
745
746		foreach ($item as $key => $field) {
747			if ($field === null) {
748				unset($item[$key]);
749			}
750		}
751
752		foreach ($_REQUEST['group_itemid'] as $id) {
753			$item['itemid'] = $id;
754
755			if (!$result = API::Item()->update($item)) {
756				break;
757			}
758		}
759	}
760	catch (Exception $e) {
761		$result = false;
762	}
763
764	$result = DBend($result);
765
766	if ($result) {
767		unset($_REQUEST['group_itemid'], $_REQUEST['massupdate'], $_REQUEST['form']);
768		uncheckTableRows(getRequest('hostid'));
769	}
770	show_messages($result, _('Items updated'), _('Cannot update items'));
771}
772elseif (hasRequest('action') && str_in_array(getRequest('action'), ['item.massenable', 'item.massdisable']) && hasRequest('group_itemid')) {
773	$groupItemId = getRequest('group_itemid');
774	$enable = (getRequest('action') == 'item.massenable');
775
776	DBstart();
777	$result = $enable ? activate_item($groupItemId) : disable_item($groupItemId);
778	$result = DBend($result);
779
780	if ($result) {
781		uncheckTableRows(getRequest('hostid'));
782	}
783
784	$updated = count($groupItemId);
785
786	$messageSuccess = $enable
787		? _n('Item enabled', 'Items enabled', $updated)
788		: _n('Item disabled', 'Items disabled', $updated);
789	$messageFailed = $enable
790		? _n('Cannot enable item', 'Cannot enable items', $updated)
791		: _n('Cannot disable item', 'Cannot disable items', $updated);
792
793	show_messages($result, $messageSuccess, $messageFailed);
794}
795elseif (hasRequest('action') && getRequest('action') == 'item.masscopyto' && hasRequest('copy') && hasRequest('group_itemid')) {
796	if (hasRequest('copy_targetid') && getRequest('copy_targetid') > 0 && hasRequest('copy_type')) {
797		// hosts or templates
798		if (getRequest('copy_type') == COPY_TYPE_TO_HOST || getRequest('copy_type') == COPY_TYPE_TO_TEMPLATE) {
799			$hosts_ids = getRequest('copy_targetid');
800		}
801		// host groups
802		else {
803			$hosts_ids = [];
804			$group_ids = getRequest('copy_targetid');
805
806			$db_hosts = DBselect(
807				'SELECT DISTINCT h.hostid'.
808				' FROM hosts h,hosts_groups hg'.
809				' WHERE h.hostid=hg.hostid'.
810					' AND '.dbConditionInt('hg.groupid', $group_ids)
811			);
812			while ($db_host = DBfetch($db_hosts)) {
813				$hosts_ids[] = $db_host['hostid'];
814			}
815		}
816
817		DBstart();
818
819		$result = copyItemsToHosts(getRequest('group_itemid'), $hosts_ids);
820		$result = DBend($result);
821
822		$items_count = count(getRequest('group_itemid'));
823
824		if ($result) {
825			uncheckTableRows(getRequest('hostid'));
826			unset($_REQUEST['group_itemid']);
827		}
828		show_messages($result,
829			_n('Item copied', 'Items copied', $items_count),
830			_n('Cannot copy item', 'Cannot copy items', $items_count)
831		);
832	}
833	else {
834		show_error_message(_('No target selected.'));
835	}
836}
837// clean history for selected items
838elseif (hasRequest('action') && getRequest('action') === 'item.massclearhistory'
839		&& hasRequest('group_itemid') && is_array(getRequest('group_itemid'))) {
840	$result = false;
841
842	$itemIds = getRequest('group_itemid');
843
844	$items = API::Item()->get([
845		'output' => ['itemid', 'key_'],
846		'itemids' => $itemIds,
847		'selectHosts' => ['name'],
848		'editable' => true
849	]);
850
851	if ($items) {
852		DBstart();
853
854		$result = deleteHistoryByItemIds($itemIds);
855
856		if ($result) {
857			foreach ($items as $item) {
858				$host = reset($item['hosts']);
859
860				add_audit(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_ITEM,
861					_('Item').' ['.$item['key_'].'] ['.$item['itemid'].'] '. _('Host').' ['.$host['name'].'] '.
862						_('History cleared')
863				);
864			}
865		}
866
867		$result = DBend($result);
868
869		if ($result) {
870			uncheckTableRows(getRequest('hostid'));
871		}
872	}
873
874	show_messages($result, _('History cleared'), _('Cannot clear history'));
875}
876elseif (hasRequest('action') && getRequest('action') == 'item.massdelete' && hasRequest('group_itemid')) {
877	DBstart();
878
879	$group_itemid = getRequest('group_itemid');
880
881	$itemsToDelete = API::Item()->get([
882		'output' => ['key_', 'itemid'],
883		'selectHosts' => ['name'],
884		'itemids' => $group_itemid,
885		'preservekeys' => true
886	]);
887
888	$result = API::Item()->delete($group_itemid);
889
890	if ($result) {
891		foreach ($itemsToDelete as $item) {
892			$host = reset($item['hosts']);
893			add_audit(AUDIT_ACTION_DELETE, AUDIT_RESOURCE_ITEM,
894				_('Item').' ['.$item['key_'].'] ['.$item['itemid'].'] '._('Host').' ['.$host['name'].']'
895			);
896		}
897	}
898
899	$result = DBend($result);
900
901	if ($result) {
902		uncheckTableRows(getRequest('hostid'));
903	}
904	show_messages($result, _('Items deleted'), _('Cannot delete items'));
905}
906
907/*
908 * Display
909 */
910if (isset($_REQUEST['form']) && str_in_array($_REQUEST['form'], [_('Create item'), 'update', 'clone'])) {
911	if (hasRequest('itemid')) {
912		$items = API::Item()->get([
913			'itemids' => getRequest('itemid'),
914			'output' => [
915				'itemid', 'type', 'snmp_community', 'snmp_oid', 'hostid', 'name', 'key_', 'delay', 'history',
916				'trends', 'status', 'value_type', 'trapper_hosts', 'units', 'multiplier', 'delta',
917				'snmpv3_securityname', 'snmpv3_securitylevel', 'snmpv3_authpassphrase', 'snmpv3_privpassphrase',
918				'formula', 'logtimefmt', 'templateid', 'valuemapid', 'delay_flex', 'params', 'ipmi_sensor',
919				'data_type', 'authtype', 'username', 'password', 'publickey', 'privatekey',
920				'interfaceid', 'port', 'description', 'inventory_link', 'lifetime', 'snmpv3_authprotocol',
921				'snmpv3_privprotocol', 'snmpv3_contextname'
922			],
923			'selectHosts' => ['status']
924		]);
925		$item = $items[0];
926		$host = $item['hosts'][0];
927		unset($item['hosts']);
928	}
929	else {
930		$hosts = API::Host()->get([
931			'output' => ['status'],
932			'hostids' => getRequest('hostid'),
933			'templated_hosts' => true
934		]);
935		$item = [];
936		$host = $hosts[0];
937	}
938
939	$data = getItemFormData($item);
940	$data['inventory_link'] = getRequest('inventory_link');
941	$data['config'] = select_config();
942	$data['host'] = $host;
943
944	// Sort interfaces to be listed starting with one selected as 'main'.
945	CArrayHelper::sort($data['interfaces'], [
946		['field' => 'main', 'order' => ZBX_SORT_DOWN]
947	]);
948
949	if (hasRequest('itemid') && !getRequest('form_refresh')) {
950		$data['inventory_link'] = $item['inventory_link'];
951	}
952
953	// render view
954	$itemView = new CView('configuration.item.edit', $data);
955	$itemView->render();
956	$itemView->show();
957}
958elseif ((getRequest('action') === 'item.massupdateform' || hasRequest('massupdate')) && hasRequest('group_itemid')) {
959	$data = [
960		'form' => getRequest('form'),
961		'action' => 'item.massupdateform',
962		'hostid' => getRequest('hostid'),
963		'itemids' => getRequest('group_itemid', []),
964		'description' => getRequest('description', ''),
965		'delay' => getRequest('delay', ZBX_ITEM_DELAY_DEFAULT),
966		'delay_flex' => getRequest('delay_flex', []),
967		'history' => getRequest('history', 90),
968		'status' => getRequest('status', 0),
969		'type' => getRequest('type', 0),
970		'interfaceid' => getRequest('interfaceid', 0),
971		'snmp_community' => getRequest('snmp_community', 'public'),
972		'port' => getRequest('port', ''),
973		'value_type' => getRequest('value_type', ITEM_VALUE_TYPE_UINT64),
974		'data_type' => getRequest('data_type', ITEM_DATA_TYPE_DECIMAL),
975		'trapper_hosts' => getRequest('trapper_hosts', ''),
976		'units' => getRequest('units', ''),
977		'authtype' => getRequest('authtype', ''),
978		'username' => getRequest('username', ''),
979		'password' => getRequest('password', ''),
980		'publickey' => getRequest('publickey', ''),
981		'privatekey' => getRequest('privatekey', ''),
982		'valuemapid' => getRequest('valuemapid', 0),
983		'delta' => getRequest('delta', 0),
984		'trends' => getRequest('trends', DAY_IN_YEAR),
985		'applications' => getRequest('applications', []),
986		'snmpv3_contextname' => getRequest('snmpv3_contextname', ''),
987		'snmpv3_securityname' => getRequest('snmpv3_securityname', ''),
988		'snmpv3_securitylevel' => getRequest('snmpv3_securitylevel', 0),
989		'snmpv3_authprotocol' => getRequest('snmpv3_authprotocol', ITEM_AUTHPROTOCOL_MD5),
990		'snmpv3_authpassphrase' => getRequest('snmpv3_authpassphrase', ''),
991		'snmpv3_privprotocol' => getRequest('snmpv3_privprotocol', ITEM_PRIVPROTOCOL_DES),
992		'snmpv3_privpassphrase' => getRequest('snmpv3_privpassphrase', ''),
993		'formula' => getRequest('formula', '1'),
994		'logtimefmt' => getRequest('logtimefmt', ''),
995		'initial_item_type' => null,
996		'multiple_interface_types' => false,
997		'visible' => getRequest('visible', [])
998	];
999
1000	$data['displayApplications'] = true;
1001	$data['displayInterfaces'] = true;
1002
1003	// hosts
1004	$data['hosts'] = API::Host()->get([
1005		'output' => ['hostid'],
1006		'itemids' => $data['itemids'],
1007		'selectInterfaces' => API_OUTPUT_EXTEND
1008	]);
1009	$hostCount = count($data['hosts']);
1010
1011	if ($hostCount > 1) {
1012		$data['displayApplications'] = false;
1013		$data['displayInterfaces'] = false;
1014	}
1015	else {
1016		// get template count to display applications multiselect only for single template
1017		$templates = API::Template()->get([
1018			'output' => ['templateid'],
1019			'itemids' => $data['itemids']
1020		]);
1021		$templateCount = count($templates);
1022
1023		if ($templateCount != 0) {
1024			$data['displayInterfaces'] = false;
1025
1026			if ($templateCount == 1 && !$data['hostid']) {
1027				// if selected from filter without 'hostid'
1028				$templates = reset($templates);
1029				$data['hostid'] = $templates['templateid'];
1030			}
1031
1032			// if items belong to single template and some belong to single host, don't display application multiselect
1033			// and don't display application multiselect for multiple templates
1034			if ($hostCount == 1 && $templateCount == 1 || $templateCount > 1) {
1035				$data['displayApplications'] = false;
1036			}
1037		}
1038
1039		if ($hostCount == 1 && $data['displayInterfaces']) {
1040			$data['hosts'] = reset($data['hosts']);
1041
1042			// Sort interfaces to be listed starting with one selected as 'main'.
1043			CArrayHelper::sort($data['hosts']['interfaces'], [
1044				['field' => 'main', 'order' => ZBX_SORT_DOWN]
1045			]);
1046
1047			// if selected from filter without 'hostid'
1048			if (!$data['hostid']) {
1049				$data['hostid'] = $data['hosts']['hostid'];
1050			}
1051
1052			// set the initial chosen interface to one of the interfaces the items use
1053			$items = API::Item()->get([
1054				'itemids' => $data['itemids'],
1055				'output' => ['itemid', 'type']
1056			]);
1057			$usedInterfacesTypes = [];
1058			foreach ($items as $item) {
1059				$usedInterfacesTypes[$item['type']] = itemTypeInterface($item['type']);
1060			}
1061			$initialItemType = min(array_keys($usedInterfacesTypes));
1062			$data['type'] = (getRequest('type') !== null) ? ($data['type']) : $initialItemType;
1063			$data['initial_item_type'] = $initialItemType;
1064			$data['multiple_interface_types'] = (count(array_unique($usedInterfacesTypes)) > 1);
1065		}
1066	}
1067
1068	// item types
1069	$data['itemTypes'] = item_type2str();
1070	unset($data['itemTypes'][ITEM_TYPE_HTTPTEST]);
1071
1072	// valuemap
1073	$data['valuemaps'] = API::ValueMap()->get([
1074		'output' => ['valuemapid', 'name']
1075	]);
1076	CArrayHelper::sort($data['valuemaps'], ['name']);
1077
1078	if (!$data['delay_flex']) {
1079		$data['delay_flex'][] = ['delay' => '', 'period' => '', 'type' => ITEM_DELAY_FLEX_TYPE_FLEXIBLE];
1080	}
1081
1082	// render view
1083	$itemView = new CView('configuration.item.massupdate', $data);
1084	$itemView->render();
1085	$itemView->show();
1086}
1087elseif (hasRequest('action') && getRequest('action') == 'item.masscopyto' && hasRequest('group_itemid')) {
1088	// render view
1089	$data = getCopyElementsFormData('group_itemid', _('Items'));
1090	$data['action'] = 'item.masscopyto';
1091	$graphView = new CView('configuration.copy.elements', $data);
1092	$graphView->render();
1093	$graphView->show();
1094}
1095// list of items
1096else {
1097	$sortField = getRequest('sort', CProfile::get('web.'.$page['file'].'.sort', 'name'));
1098	$sortOrder = getRequest('sortorder', CProfile::get('web.'.$page['file'].'.sortorder', ZBX_SORT_UP));
1099
1100	CProfile::update('web.'.$page['file'].'.sort', $sortField, PROFILE_TYPE_STR);
1101	CProfile::update('web.'.$page['file'].'.sortorder', $sortOrder, PROFILE_TYPE_STR);
1102
1103	$_REQUEST['hostid'] = empty($_REQUEST['filter_hostid']) ? null : $_REQUEST['filter_hostid'];
1104
1105	$config = select_config();
1106
1107	$data = [
1108		'form' => getRequest('form'),
1109		'hostid' => getRequest('hostid'),
1110		'sort' => $sortField,
1111		'sortorder' => $sortOrder,
1112		'config' => $config
1113	];
1114
1115	// items
1116	$options = [
1117		'hostids' => $data['hostid'],
1118		'search' => [],
1119		'output' => [
1120			'itemid', 'type', 'hostid', 'name', 'key_', 'delay', 'history', 'trends', 'status', 'value_type', 'error',
1121			'templateid', 'flags', 'state'
1122		],
1123		'editable' => true,
1124		'selectHosts' => API_OUTPUT_EXTEND,
1125		'selectTriggers' => ['triggerid', 'description'],
1126		'selectApplications' => API_OUTPUT_EXTEND,
1127		'selectDiscoveryRule' => API_OUTPUT_EXTEND,
1128		'selectItemDiscovery' => ['ts_delete'],
1129		'sortfield' => $sortField,
1130		'limit' => $config['search_limit'] + 1
1131	];
1132	$preFilter = count($options, COUNT_RECURSIVE);
1133
1134	if (isset($_REQUEST['filter_groupid']) && !empty($_REQUEST['filter_groupid'])) {
1135		$options['groupids'] = $_REQUEST['filter_groupid'];
1136	}
1137	if (isset($_REQUEST['filter_hostid']) && !empty($_REQUEST['filter_hostid'])) {
1138		$data['filter_hostid'] = $_REQUEST['filter_hostid'];
1139	}
1140	if (isset($_REQUEST['filter_application']) && !zbx_empty($_REQUEST['filter_application'])) {
1141		$options['application'] = $_REQUEST['filter_application'];
1142	}
1143	if (isset($_REQUEST['filter_name']) && !zbx_empty($_REQUEST['filter_name'])) {
1144		$options['search']['name'] = $_REQUEST['filter_name'];
1145	}
1146	if (isset($_REQUEST['filter_type']) && !zbx_empty($_REQUEST['filter_type']) && $_REQUEST['filter_type'] != -1) {
1147		$options['filter']['type'] = $_REQUEST['filter_type'];
1148	}
1149	if (isset($_REQUEST['filter_key']) && !zbx_empty($_REQUEST['filter_key'])) {
1150		$options['search']['key_'] = $_REQUEST['filter_key'];
1151	}
1152	if (isset($_REQUEST['filter_snmp_community']) && !zbx_empty($_REQUEST['filter_snmp_community'])) {
1153		$options['filter']['snmp_community'] = $_REQUEST['filter_snmp_community'];
1154	}
1155	if (isset($_REQUEST['filter_snmpv3_securityname']) && !zbx_empty($_REQUEST['filter_snmpv3_securityname'])) {
1156		$options['filter']['snmpv3_securityname'] = $_REQUEST['filter_snmpv3_securityname'];
1157	}
1158	if (isset($_REQUEST['filter_snmp_oid']) && !zbx_empty($_REQUEST['filter_snmp_oid'])) {
1159		$options['filter']['snmp_oid'] = $_REQUEST['filter_snmp_oid'];
1160	}
1161	if (isset($_REQUEST['filter_port']) && !zbx_empty($_REQUEST['filter_port'])) {
1162		$options['filter']['port'] = $_REQUEST['filter_port'];
1163	}
1164	if (isset($_REQUEST['filter_value_type']) && !zbx_empty($_REQUEST['filter_value_type'])
1165			&& $_REQUEST['filter_value_type'] != -1) {
1166		$options['filter']['value_type'] = $_REQUEST['filter_value_type'];
1167	}
1168	if (isset($_REQUEST['filter_data_type']) && !zbx_empty($_REQUEST['filter_data_type'])
1169			&& $_REQUEST['filter_data_type'] != -1) {
1170		$options['filter']['data_type'] = $_REQUEST['filter_data_type'];
1171	}
1172
1173	/*
1174	 * Trapper and SNMP trap items contain zeroes in "delay" field and, if no specific type is set, look in item types
1175	 * other than trapper and SNMP trap that allow zeroes. For example, when a flexible interval is used. Since trapper
1176	 * and SNMP trap items contain zeroes, but those zeroes should not be displayed, they cannot be filtered by entering
1177	 * either zero or any other number in filter field.
1178	 */
1179	if (hasRequest('filter_delay')) {
1180		$filter_delay = getRequest('filter_delay');
1181		$filter_type = getRequest('filter_type');
1182
1183		if ($filter_delay !== '') {
1184			if ($filter_type == -1 && $filter_delay == 0) {
1185				$options['filter']['type'] = [ITEM_TYPE_ZABBIX, ITEM_TYPE_SNMPV1, ITEM_TYPE_SIMPLE,
1186					ITEM_TYPE_SNMPV2C, ITEM_TYPE_INTERNAL, ITEM_TYPE_SNMPV3, ITEM_TYPE_ZABBIX_ACTIVE,
1187					ITEM_TYPE_AGGREGATE, ITEM_TYPE_EXTERNAL, ITEM_TYPE_DB_MONITOR, ITEM_TYPE_IPMI, ITEM_TYPE_SSH,
1188					ITEM_TYPE_TELNET, ITEM_TYPE_CALCULATED, ITEM_TYPE_JMX
1189				];
1190
1191				$options['filter']['delay'] = $filter_delay;
1192			}
1193			elseif ($filter_type == ITEM_TYPE_TRAPPER || $filter_type == ITEM_TYPE_SNMPTRAP) {
1194				$options['filter']['delay'] = -1;
1195			}
1196			else {
1197				$options['filter']['delay'] = $filter_delay;
1198			}
1199		}
1200	}
1201
1202	if (isset($_REQUEST['filter_history']) && !zbx_empty($_REQUEST['filter_history'])) {
1203		$options['filter']['history'] = $_REQUEST['filter_history'];
1204	}
1205
1206	// If no specific value type is set, set a numeric value type when filtering by trends.
1207	if (hasRequest('filter_trends')) {
1208		$filter_trends = getRequest('filter_trends');
1209
1210		if ($filter_trends !== '') {
1211			$options['filter']['trends'] = $filter_trends;
1212
1213			if (getRequest('filter_value_type') == -1) {
1214				$options['filter']['value_type'] = [ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64];
1215			}
1216		}
1217	}
1218
1219	if (isset($_REQUEST['filter_status']) && !zbx_empty($_REQUEST['filter_status']) && $_REQUEST['filter_status'] != -1) {
1220		$options['filter']['status'] = $_REQUEST['filter_status'];
1221	}
1222	if (isset($_REQUEST['filter_state']) && !zbx_empty($_REQUEST['filter_state']) && $_REQUEST['filter_state'] != -1) {
1223		$options['filter']['status'] = ITEM_STATUS_ACTIVE;
1224		$options['filter']['state'] = $_REQUEST['filter_state'];
1225	}
1226	if (isset($_REQUEST['filter_templated_items']) && !zbx_empty($_REQUEST['filter_templated_items'])
1227			&& $_REQUEST['filter_templated_items'] != -1) {
1228		$options['inherited'] = $_REQUEST['filter_templated_items'];
1229	}
1230	if (isset($_REQUEST['filter_with_triggers']) && !zbx_empty($_REQUEST['filter_with_triggers'])
1231			&& $_REQUEST['filter_with_triggers'] != -1) {
1232		$options['with_triggers'] = $_REQUEST['filter_with_triggers'];
1233	}
1234	if (isset($_REQUEST['filter_ipmi_sensor']) && !zbx_empty($_REQUEST['filter_ipmi_sensor'])) {
1235		$options['filter']['ipmi_sensor'] = $_REQUEST['filter_ipmi_sensor'];
1236	}
1237
1238	$data['filterSet'] = ($options['hostids'] || $preFilter != count($options, COUNT_RECURSIVE));
1239	if ($data['filterSet']) {
1240		$data['items'] = API::Item()->get($options);
1241	}
1242	else {
1243		$data['items'] = [];
1244	}
1245
1246	// set values for subfilters, if any of subfilters = false then item shouldnt be shown
1247	if ($data['items']) {
1248		// fill template host
1249		fillItemsWithChildTemplates($data['items']);
1250
1251		$dbHostItems = DBselect(
1252			'SELECT i.itemid,h.name,h.hostid'.
1253			' FROM hosts h,items i'.
1254			' WHERE i.hostid=h.hostid'.
1255				' AND '.dbConditionInt('i.itemid', zbx_objectValues($data['items'], 'templateid'))
1256		);
1257		while ($dbHostItem = DBfetch($dbHostItems)) {
1258			foreach ($data['items'] as &$item) {
1259				if ($item['templateid'] == $dbHostItem['itemid']) {
1260					$item['template_host'] = $dbHostItem;
1261				}
1262			}
1263			unset($item);
1264		}
1265
1266		// resolve name macros
1267		$data['items'] = CMacrosResolverHelper::resolveItemNames($data['items']);
1268
1269		foreach ($data['items'] as &$item) {
1270			$item['hostids'] = zbx_objectValues($item['hosts'], 'hostid');
1271
1272			if (empty($data['filter_hostid'])) {
1273				$host = reset($item['hosts']);
1274				$item['host'] = $host['name'];
1275			}
1276
1277			// Hide trend (zero values) for non-numeric item types.
1278			if ($item['value_type'] == ITEM_VALUE_TYPE_STR || $item['value_type'] == ITEM_VALUE_TYPE_LOG
1279					|| $item['value_type'] == ITEM_VALUE_TYPE_TEXT) {
1280				$item['trends'] = '';
1281			}
1282
1283			if ($item['type'] == ITEM_TYPE_TRAPPER || $item['type'] == ITEM_TYPE_SNMPTRAP) {
1284				$item['delay'] = '';
1285			}
1286
1287			$item['subfilters'] = [
1288				'subfilter_hosts' => empty($_REQUEST['subfilter_hosts'])
1289					|| (boolean) array_intersect($_REQUEST['subfilter_hosts'], $item['hostids']),
1290				'subfilter_types' => empty($_REQUEST['subfilter_types'])
1291					|| uint_in_array($item['type'], $_REQUEST['subfilter_types']),
1292				'subfilter_value_types' => empty($_REQUEST['subfilter_value_types'])
1293					|| uint_in_array($item['value_type'], $_REQUEST['subfilter_value_types']),
1294				'subfilter_status' => empty($_REQUEST['subfilter_status'])
1295					|| uint_in_array($item['status'], $_REQUEST['subfilter_status']),
1296				'subfilter_state' => empty($_REQUEST['subfilter_state'])
1297					|| uint_in_array($item['state'], $_REQUEST['subfilter_state']),
1298				'subfilter_templated_items' => empty($_REQUEST['subfilter_templated_items'])
1299					|| ($item['templateid'] == 0 && uint_in_array(0, $_REQUEST['subfilter_templated_items'])
1300					|| ($item['templateid'] > 0 && uint_in_array(1, $_REQUEST['subfilter_templated_items']))),
1301				'subfilter_with_triggers' => empty($_REQUEST['subfilter_with_triggers'])
1302					|| (count($item['triggers']) == 0 && uint_in_array(0, $_REQUEST['subfilter_with_triggers']))
1303					|| (count($item['triggers']) > 0 && uint_in_array(1, $_REQUEST['subfilter_with_triggers'])),
1304				'subfilter_history' => empty($_REQUEST['subfilter_history'])
1305					|| uint_in_array($item['history'], $_REQUEST['subfilter_history']),
1306				'subfilter_trends' => !getRequest('subfilter_trends')
1307					|| ($item['trends'] !== '' && uint_in_array($item['trends'], getRequest('subfilter_trends'))),
1308				'subfilter_interval' => !getRequest('subfilter_interval')
1309					|| ($item['delay'] !== '' && uint_in_array($item['delay'], getRequest('subfilter_interval'))),
1310				'subfilter_apps' => empty($_REQUEST['subfilter_apps'])
1311			];
1312
1313			if (!empty($_REQUEST['subfilter_apps'])) {
1314				foreach ($item['applications'] as $application) {
1315					if (str_in_array($application['name'], $_REQUEST['subfilter_apps'])) {
1316						$item['subfilters']['subfilter_apps'] = true;
1317						break;
1318					}
1319				}
1320			}
1321
1322			if (!empty($item['applications'])) {
1323				order_result($item['applications'], 'name');
1324
1325				$applications = [];
1326				foreach ($item['applications'] as $application) {
1327					$applications[] = $application['name'];
1328				}
1329				$item['applications_list'] = implode(', ', $applications);
1330			}
1331			else {
1332				$item['applications_list'] = '';
1333			}
1334		}
1335		unset($item);
1336
1337		// disable subfilters if list is empty
1338		foreach ($data['items'] as $item) {
1339			$atLeastOne = true;
1340			foreach ($item['subfilters'] as $value) {
1341				if (!$value) {
1342					$atLeastOne = false;
1343					break;
1344				}
1345			}
1346			if ($atLeastOne) {
1347				break;
1348			}
1349		}
1350		if (!$atLeastOne) {
1351			foreach ($subfiltersList as $name) {
1352				$_REQUEST[$name] = [];
1353				CProfile::update('web.items.'.$name, '', PROFILE_TYPE_STR);
1354				foreach ($data['items'] as &$item) {
1355					$item['subfilters'][$name] = true;
1356				}
1357				unset($item);
1358			}
1359		}
1360	}
1361
1362	$data['flicker'] = getItemFilterForm($data['items']);
1363
1364	// remove subfiltered items
1365	if (!empty($data['items'])) {
1366		foreach ($data['items'] as $number => $item) {
1367			foreach ($item['subfilters'] as $value) {
1368				if (!$value) {
1369					unset($data['items'][$number]);
1370					break;
1371				}
1372			}
1373		}
1374	}
1375
1376	if ($sortField === 'status') {
1377		orderItemsByStatus($data['items'], $sortOrder);
1378	}
1379	else {
1380		order_result($data['items'], $sortField, $sortOrder);
1381	}
1382
1383	$data['paging'] = getPagingLine($data['items'], $sortOrder, new CUrl('items.php'));
1384
1385	$itemTriggerIds = [];
1386	foreach ($data['items'] as $item) {
1387		$itemTriggerIds = array_merge($itemTriggerIds, zbx_objectValues($item['triggers'], 'triggerid'));
1388	}
1389	$data['itemTriggers'] = API::Trigger()->get([
1390		'triggerids' => $itemTriggerIds,
1391		'output' => API_OUTPUT_EXTEND,
1392		'selectHosts' => ['hostid', 'name', 'host'],
1393		'selectFunctions' => API_OUTPUT_EXTEND,
1394		'preservekeys' => true
1395	]);
1396	$data['triggerRealHosts'] = getParentHostsByTriggers($data['itemTriggers']);
1397
1398	// Select writable templates IDs.
1399	$hostids = [];
1400
1401	foreach ($data['triggerRealHosts'] as $real_host) {
1402		$hostids = array_merge($hostids, zbx_objectValues($real_host, 'hostid'));
1403	}
1404
1405	foreach ($data['items'] as $item) {
1406		if (array_key_exists('template_host', $item)) {
1407			$hostids = array_merge($hostids, zbx_objectValues($item['template_host'], 'hostid'));
1408		}
1409	}
1410
1411	$data['writable_templates'] = [];
1412
1413	if ($hostids) {
1414		$data['writable_templates'] = API::Template()->get([
1415			'output' => ['templateid'],
1416			'templateids' => array_keys(array_flip($hostids)),
1417			'editable' => true,
1418			'preservekeys' => true
1419		]);
1420	}
1421
1422	// determine, show or not column of errors
1423	if (isset($hosts)) {
1424		$host = reset($hosts);
1425
1426		$data['showInfoColumn'] = ($host['status'] != HOST_STATUS_TEMPLATE);
1427	}
1428	else {
1429		$data['showInfoColumn'] = true;
1430	}
1431
1432	// render view
1433	$itemView = new CView('configuration.item.list', $data);
1434	$itemView->render();
1435	$itemView->show();
1436}
1437
1438require_once dirname(__FILE__).'/include/page_footer.php';
1439