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