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
22require_once dirname(__FILE__).'/include/config.inc.php';
23require_once dirname(__FILE__).'/include/hosts.inc.php';
24require_once dirname(__FILE__).'/include/forms.inc.php';
25
26$page['title'] = _('Host inventory');
27$page['file'] = 'hostinventories.php';
28$page['scripts'] = ['layout.mode.js', 'multiselect.js'];
29
30$hostId = getRequest('hostid', 0);
31
32if ($hostId > 0) {
33	$page['web_layout_mode'] = CViewHelper::loadLayoutMode();
34}
35
36require_once dirname(__FILE__).'/include/page_header.php';
37
38//		VAR			TYPE	OPTIONAL FLAGS	VALIDATION	EXCEPTION
39$fields = [
40	'hostid' =>				[T_ZBX_INT, O_OPT, P_SYS,	DB_ID,		null],
41	// filter
42	'filter_set' =>			[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
43	'filter_rst' =>			[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
44	'filter_field' =>		[T_ZBX_STR, O_OPT, null,	null,		null],
45	'filter_field_value' =>	[T_ZBX_STR, O_OPT, null,	null,		null],
46	'filter_exact' =>		[T_ZBX_INT, O_OPT, null,	'IN(0,1)',	null],
47	'filter_groups' =>		[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
48	// actions
49	'cancel' =>				[T_ZBX_STR, O_OPT, P_SYS,		null,	null],
50	// sort and sortorder
51	'sort' =>				[T_ZBX_STR, O_OPT, P_SYS,
52								IN('"name","pr_macaddress_a","pr_name","pr_os","pr_serialno_a","pr_tag","pr_type"'),
53								null
54							],
55	'sortorder' =>			[T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'),	null]
56];
57check_fields($fields);
58
59/*
60 * Permissions
61 */
62if (getRequest('hostid') && !isReadableHosts([getRequest('hostid')])) {
63	access_deny();
64}
65
66$sortField = getRequest('sort', CProfile::get('web.'.$page['file'].'.sort', 'name'));
67$sortOrder = getRequest('sortorder', CProfile::get('web.'.$page['file'].'.sortorder', ZBX_SORT_UP));
68
69CProfile::update('web.'.$page['file'].'.sort', $sortField, PROFILE_TYPE_STR);
70CProfile::update('web.'.$page['file'].'.sortorder', $sortOrder, PROFILE_TYPE_STR);
71
72/*
73 * Display
74 */
75if ($hostId > 0) {
76	$data = [
77		'allowed_ui_hosts' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_HOSTS),
78		'allowed_ui_problems' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_PROBLEMS),
79		'allowed_ui_latest_data' => CWebUser::checkAccess(CRoleHelper::UI_MONITORING_LATEST_DATA),
80		'allowed_ui_conf_hosts' => CWebUser::checkAccess(CRoleHelper::UI_CONFIGURATION_HOSTS)
81	];
82
83	// inventory info
84	$data['tableTitles'] = getHostInventories();
85	$data['tableTitles'] = zbx_toHash($data['tableTitles'], 'db_field');
86	$inventoryFields = array_keys($data['tableTitles']);
87
88	// overview tab
89	$data['host'] = API::Host()->get([
90		'output' => ['hostid', 'host', 'name', 'maintenance_status', 'maintenanceid', 'maintenance_type', 'description'],
91		'selectInterfaces' => API_OUTPUT_EXTEND,
92		'selectItems' => API_OUTPUT_COUNT,
93		'selectTriggers' => API_OUTPUT_COUNT,
94		'selectInventory' => $inventoryFields,
95		'selectGraphs' => API_OUTPUT_COUNT,
96		'selectDiscoveries' => API_OUTPUT_COUNT,
97		'selectHttpTests' => API_OUTPUT_COUNT,
98		'hostids' => $hostId,
99		'preservekeys' => true
100	]);
101	$data['host'] = reset($data['host']);
102	unset($data['host']['inventory']['hostid']);
103
104	// resolve macros
105	$data['host']['interfaces'] = CMacrosResolverHelper::resolveHostInterfaces($data['host']['interfaces']);
106
107	if ($data['host']['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) {
108		$data['maintenances'] = API::Maintenance()->get([
109			'maintenanceids' => [$data['host']['maintenanceid']],
110			'output' => ['name', 'description'],
111			'preservekeys' => true
112		]);
113	}
114
115	// get permissions
116	$userType = CWebUser::getType();
117	if ($userType == USER_TYPE_SUPER_ADMIN) {
118		$data['rwHost'] = true;
119	}
120	elseif ($userType == USER_TYPE_ZABBIX_ADMIN) {
121		$rwHost = API::Host()->get([
122			'output' => ['hostid'],
123			'hostids' => $hostId,
124			'editable' => true
125		]);
126
127		$data['rwHost'] = (bool) $rwHost;
128	}
129	else {
130		$data['rwHost'] = false;
131	}
132
133	// view generation
134	echo (new CView('inventory.host.view', $data))->getOutput();
135}
136else {
137	$data = [
138		'hosts' => [],
139		'sort' => $sortField,
140		'sortorder' => $sortOrder,
141		'profileIdx' => 'web.hostinventories.filter',
142		'active_tab' => CProfile::get('web.hostinventories.filter.active', 1)
143	];
144
145	/*
146	 * Filter
147	 */
148	if (hasRequest('filter_set')) {
149		CProfile::update('web.hostinventories.filter_field', getRequest('filter_field', ''), PROFILE_TYPE_STR);
150		CProfile::update('web.hostinventories.filter_field_value', getRequest('filter_field_value', ''), PROFILE_TYPE_STR);
151		CProfile::update('web.hostinventories.filter_exact', getRequest('filter_exact', 0), PROFILE_TYPE_INT);
152		CProfile::updateArray('web.hostinventories.filter_groups', getRequest('filter_groups', []), PROFILE_TYPE_ID);
153	}
154	elseif (hasRequest('filter_rst')) {
155		DBStart();
156		CProfile::delete('web.hostinventories.filter_field');
157		CProfile::delete('web.hostinventories.filter_field_value');
158		CProfile::delete('web.hostinventories.filter_exact');
159		CProfile::deleteIdx('web.hostinventories.filter_groups');
160		DBend();
161	}
162
163	$data['filter'] = [
164		'field' => CProfile::get('web.hostinventories.filter_field', ''),
165		'fieldValue' => CProfile::get('web.hostinventories.filter_field_value', ''),
166		'exact' => CProfile::get('web.hostinventories.filter_exact', 0),
167		'groups' => CProfile::getArray('web.hostinventories.filter_groups', [])
168	];
169
170	// Select filter host groups.
171	$data['filter']['groups'] = $data['filter']['groups']
172		? CArrayHelper::renameObjectsKeys(API::HostGroup()->get([
173			'output' => ['groupid', 'name'],
174			'groupids' => $data['filter']['groups'],
175			'preservekeys' => true
176		]), ['groupid' => 'id'])
177		: [];
178
179	$filter_groupids = $data['filter']['groups'] ? array_keys($data['filter']['groups']) : null;
180	if ($filter_groupids) {
181		$filter_groupids = getSubGroups($filter_groupids);
182	}
183
184	$data['host_inventories'] = zbx_toHash(getHostInventories(true), 'db_field');
185
186	if ($data['filter']['field'] === '') {
187		$data['filter']['field'] = key($data['host_inventories']);
188	}
189
190	// Checking if correct inventory field is specified for filter.
191	if ($data['filter']['fieldValue'] !== ''
192			&& !array_key_exists($data['filter']['field'], $data['host_inventories'])) {
193		error(_s('Impossible to filter by inventory field "%1$s", which does not exist.', $data['filter']['field']));
194		$filter_set = false;
195	}
196	else {
197		$filter_set = true;
198	}
199
200	/*
201	 * Select data
202	 */
203	if ($filter_set) {
204		$options = [
205			'output' => ['hostid', 'name', 'status'],
206			'selectInventory' => ['name', 'type', 'os', 'serialno_a', 'tag', 'macaddress_a', $data['filter']['field']],
207			'selectGroups' => API_OUTPUT_EXTEND,
208			'groupids' => $filter_groupids,
209			'filter' => ['inventory_mode' => [HOST_INVENTORY_MANUAL, HOST_INVENTORY_AUTOMATIC]]
210		];
211
212		if ($data['filter']['fieldValue'] !== '') {
213			$options['searchInventory'] = [
214				$data['filter']['field'] => [$data['filter']['fieldValue']]
215			];
216		}
217
218		$data['hosts'] = API::Host()->get($options);
219
220		// filter exact matches
221		if ($data['filter']['fieldValue'] !== '' && $data['filter']['exact'] != 0) {
222			$needle = mb_strtolower($data['filter']['fieldValue']);
223
224			foreach ($data['hosts'] as $num => $host) {
225				$haystack = mb_strtolower($data['hosts'][$num]['inventory'][$data['filter']['field']]);
226
227				if ($haystack !== $needle) {
228					unset($data['hosts'][$num]);
229				}
230			}
231		}
232
233		$sort_fields = [
234			'pr_name' => 'name',
235			'pr_type' => 'type',
236			'pr_os' => 'os',
237			'pr_serialno_a' => 'serialno_a',
238			'pr_tag' => 'tag',
239			'pr_macaddress_a' => 'macaddress_a'
240		];
241
242		if (array_key_exists($sortField, $sort_fields)) {
243			// copying an inventory field into the upper array level for sorting
244			foreach ($data['hosts'] as &$host) {
245				$host[$sortField] = $host['inventory'][$sort_fields[$sortField]];
246			}
247			unset($host);
248		}
249
250		$limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1;
251
252		order_result($data['hosts'], $sortField, $sortOrder);
253
254		if ($sortOrder == ZBX_SORT_UP) {
255			$data['hosts'] = array_slice($data['hosts'], 0, $limit);
256		}
257		else {
258			$data['hosts'] = array_slice($data['hosts'], -$limit, $limit);
259		}
260
261		order_result($data['hosts'], $sortField, $sortOrder);
262	}
263
264	// pager
265	if (hasRequest('page')) {
266		$page_num = getRequest('page');
267	}
268	elseif (isRequestMethod('get') && !hasRequest('cancel')) {
269		$page_num = 1;
270	}
271	else {
272		$page_num = CPagerHelper::loadPage($page['file']);
273	}
274
275	CPagerHelper::savePage($page['file'], $page_num);
276
277	$data['paging'] = CPagerHelper::paginate($page_num, $data['hosts'], $sortOrder, new CUrl('hostinventories.php'));
278
279	echo (new CView('inventory.host.list', $data))->getOutput();
280}
281
282require_once dirname(__FILE__).'/include/page_footer.php';
283