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/maps.inc.php'; 24require_once dirname(__FILE__).'/include/forms.inc.php'; 25 26$page['title'] = _('Configuration of network maps'); 27$page['file'] = 'sysmaps.php'; 28$page['type'] = detect_page_type(PAGE_TYPE_HTML); 29$page['scripts'] = ['multiselect.js', 'class.tab-indicators.js']; 30 31require_once dirname(__FILE__).'/include/page_header.php'; 32 33// VAR TYPE OPTIONAL FLAGS VALIDATION EXCEPTION 34$fields = [ 35 'maps' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 36 'sysmapid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, 37 'isset({form}) && ({form} === "update" || {form} === "full_clone")' 38 ], 39 'name' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, 'isset({add}) || isset({update})', _('Name')], 40 'width' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 65535), 'isset({add}) || isset({update})', _('Width')], 41 'height' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 65535), 'isset({add}) || isset({update})', _('Height')], 42 'backgroundid' => [T_ZBX_INT, O_OPT, null, DB_ID, 'isset({add}) || isset({update})'], 43 'iconmapid' => [T_ZBX_INT, O_OPT, null, DB_ID, 'isset({add}) || isset({update})'], 44 'expandproblem' => [T_ZBX_INT, O_OPT, null, 45 IN([SYSMAP_PROBLEMS_NUMBER, SYSMAP_SINGLE_PROBLEM, SYSMAP_PROBLEMS_NUMBER_CRITICAL]), null 46 ], 47 'markelements' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 1), null], 48 'show_unack' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 2), null], 49 'highlight' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 1), null], 50 'label_format' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 1), null], 51 'label_type_host' => [T_ZBX_INT, O_OPT, null, BETWEEN(MAP_LABEL_TYPE_LABEL, MAP_LABEL_TYPE_CUSTOM), 'isset({add}) || isset({update})'], 52 'label_type_hostgroup' => [T_ZBX_INT, O_OPT, null, BETWEEN(MAP_LABEL_TYPE_LABEL, MAP_LABEL_TYPE_CUSTOM), 'isset({add}) || isset({update})'], 53 'label_type_trigger' => [T_ZBX_INT, O_OPT, null, BETWEEN(MAP_LABEL_TYPE_LABEL, MAP_LABEL_TYPE_CUSTOM), 'isset({add}) || isset({update})'], 54 'label_type_map' => [T_ZBX_INT, O_OPT, null, BETWEEN(MAP_LABEL_TYPE_LABEL, MAP_LABEL_TYPE_CUSTOM), 'isset({add}) || isset({update})'], 55 'label_type_image' => [T_ZBX_INT, O_OPT, null, BETWEEN(MAP_LABEL_TYPE_LABEL, MAP_LABEL_TYPE_CUSTOM), 'isset({add}) || isset({update})'], 56 'label_string_host' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'], 57 'label_string_hostgroup' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'], 58 'label_string_trigger' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'], 59 'label_string_map' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'], 60 'label_string_image' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'], 61 'label_type' => [T_ZBX_INT, O_OPT, null, BETWEEN(MAP_LABEL_TYPE_LABEL,MAP_LABEL_TYPE_CUSTOM), 'isset({add}) || isset({update})'], 62 'label_location' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 3), 'isset({add}) || isset({update})'], 63 'urls' => [T_ZBX_STR, O_OPT, null, null, null], 64 'severity_min' => [T_ZBX_INT, O_OPT, null, IN('0,1,2,3,4,5'), null], 65 'show_suppressed' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 1), null], 66 'userid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 67 'private' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 1), null], 68 'users' => [T_ZBX_INT, O_OPT, null, null, null], 69 'userGroups' => [T_ZBX_INT, O_OPT, null, null, null], 70 // actions 71 'action' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, IN('"map.export","map.massdelete"'), null], 72 'add' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 73 'update' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 74 'delete' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 75 'cancel' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 76 // form 77 'form' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 78 'form_refresh' => [T_ZBX_INT, O_OPT, null, null, null], 79 // filter 80 'filter_set' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 81 'filter_rst' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 82 'filter_name' => [T_ZBX_STR, O_OPT, null, null, null], 83 // sort and sortorder 84 'sort' => [T_ZBX_STR, O_OPT, P_SYS, IN('"height","name","width"'), null], 85 'sortorder' => [T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'), null] 86]; 87check_fields($fields); 88 89/* 90 * Permissions 91 */ 92if (hasRequest('sysmapid')) { 93 $sysmap = API::Map()->get([ 94 'sysmapids' => getRequest('sysmapid'), 95 'editable' => true, 96 'output' => API_OUTPUT_EXTEND, 97 'selectUrls' => API_OUTPUT_EXTEND, 98 'selectUsers' => ['userid', 'permission'], 99 'selectUserGroups' => ['usrgrpid', 'permission'] 100 ]); 101 if (empty($sysmap)) { 102 access_deny(); 103 } 104 else { 105 $sysmap = reset($sysmap); 106 } 107} 108else { 109 $sysmap = []; 110} 111 112$allowed_edit = CWebUser::checkAccess(CRoleHelper::ACTIONS_EDIT_MAPS); 113 114/* 115 * Actions 116 */ 117if (hasRequest('add') || hasRequest('update')) { 118 if (!$allowed_edit) { 119 access_deny(ACCESS_DENY_PAGE); 120 } 121 122 $map = [ 123 'name' => getRequest('name'), 124 'width' => getRequest('width'), 125 'height' => getRequest('height'), 126 'backgroundid' => getRequest('backgroundid'), 127 'iconmapid' => getRequest('iconmapid'), 128 'highlight' => getRequest('highlight', 0), 129 'markelements' => getRequest('markelements', 0), 130 'expandproblem' => getRequest('expandproblem', DB::getDefault('sysmaps', 'expandproblem')), 131 'label_format' => getRequest('label_format', 0), 132 'label_type_host' => getRequest('label_type_host', 2), 133 'label_type_hostgroup' => getRequest('label_type_hostgroup', 2), 134 'label_type_trigger' => getRequest('label_type_trigger', 2), 135 'label_type_map' => getRequest('label_type_map', 2), 136 'label_type_image' => getRequest('label_type_image', 2), 137 'label_string_host' => getRequest('label_string_host', ''), 138 'label_string_hostgroup' => getRequest('label_string_hostgroup', ''), 139 'label_string_trigger' => getRequest('label_string_trigger', ''), 140 'label_string_map' => getRequest('label_string_map', ''), 141 'label_string_image' => getRequest('label_string_image', ''), 142 'label_type' => getRequest('label_type'), 143 'label_location' => getRequest('label_location'), 144 'show_unack' => getRequest('show_unack', 0), 145 'severity_min' => getRequest('severity_min', TRIGGER_SEVERITY_NOT_CLASSIFIED), 146 'show_suppressed' => getRequest('show_suppressed', 0), 147 'urls' => getRequest('urls', []), 148 'userid' => getRequest('userid', ''), 149 'private' => getRequest('private', PRIVATE_SHARING), 150 'users' => getRequest('users', []), 151 'userGroups' => getRequest('userGroups', []) 152 ]; 153 154 foreach ($map['urls'] as $unum => $url) { 155 if (zbx_empty($url['name']) && zbx_empty($url['url'])) { 156 unset($map['urls'][$unum]); 157 } 158 } 159 160 DBstart(); 161 162 if (hasRequest('update')) { 163 // TODO check permission by new value. 164 $map['sysmapid'] = getRequest('sysmapid'); 165 166 // Only administrators can set map owner. 167 if (CWebUser::getType() == USER_TYPE_ZABBIX_USER) { 168 unset($map['userid']); 169 } 170 // Map update with inaccessible user. 171 elseif (CWebUser::getType() == USER_TYPE_ZABBIX_ADMIN && $map['userid'] === '') { 172 $user_exist = API::User()->get([ 173 'output' => ['userid'], 174 'userids' => [$sysmap['userid']] 175 ]); 176 177 if (!$user_exist) { 178 unset($map['userid']); 179 } 180 } 181 182 $result = API::Map()->update($map); 183 184 $messageSuccess = _('Network map updated'); 185 $messageFailed = _('Cannot update network map'); 186 $auditAction = AUDIT_ACTION_UPDATE; 187 } 188 else { 189 if (getRequest('form') === 'full_clone') { 190 $maps = API::Map()->get([ 191 'output' => [], 192 'selectSelements' => ['selementid', 'elements', 'elementtype', 'iconid_off', 'iconid_on', 'label', 193 'label_location', 'x', 'y', 'iconid_disabled', 'iconid_maintenance', 'elementsubtype', 'areatype', 194 'width', 'height', 'viewtype', 'use_iconmap', 'urls', 'tags', 'evaltype' 195 ], 196 'selectShapes' => ['type', 'x', 'y', 'width', 'height', 'text', 'font', 'font_size', 'font_color', 197 'text_halign', 'text_valign', 'border_type', 'border_width', 'border_color', 'background_color', 198 'zindex' 199 ], 200 'selectLines' => ['x1', 'y1', 'x2', 'y2', 'line_type', 'line_width', 'line_color', 'zindex'], 201 'selectLinks' => ['selementid1', 'selementid2', 'drawtype', 'color', 'label', 'linktriggers'], 202 'sysmapids' => $sysmap['sysmapid'] 203 ]); 204 205 if ($maps) { 206 $map['selements'] = $maps[0]['selements']; 207 $map['shapes'] = $maps[0]['shapes']; 208 $map['lines'] = $maps[0]['lines']; 209 $map['links'] = $maps[0]['links']; 210 } 211 } 212 213 $result = API::Map()->create($map); 214 215 $messageSuccess = _('Network map added'); 216 $messageFailed = _('Cannot add network map'); 217 $auditAction = AUDIT_ACTION_ADD; 218 } 219 220 if ($result) { 221 add_audit($auditAction, AUDIT_RESOURCE_MAP, 'Name ['.$map['name'].']'); 222 unset($_REQUEST['form']); 223 } 224 225 $result = DBend($result); 226 227 if ($result) { 228 uncheckTableRows(); 229 } 230 show_messages($result, $messageSuccess, $messageFailed); 231} 232elseif ((hasRequest('delete') && hasRequest('sysmapid')) 233 || (hasRequest('action') && getRequest('action') == 'map.massdelete')) { 234 if (!$allowed_edit) { 235 access_deny(ACCESS_DENY_PAGE); 236 } 237 238 $sysmapIds = getRequest('maps', []); 239 240 if (hasRequest('sysmapid')) { 241 $sysmapIds[] = getRequest('sysmapid'); 242 } 243 244 DBstart(); 245 246 $maps = API::Map()->get([ 247 'sysmapids' => $sysmapIds, 248 'output' => ['sysmapid', 'name'], 249 'editable' => true 250 ]); 251 $result = API::Map()->delete($sysmapIds); 252 253 if ($result) { 254 unset($_REQUEST['form']); 255 256 foreach ($maps as $map) { 257 add_audit_ext(AUDIT_ACTION_DELETE, AUDIT_RESOURCE_MAP, $map['sysmapid'], $map['name'], null, null, null); 258 } 259 } 260 261 $result = DBend($result); 262 263 if ($result) { 264 uncheckTableRows(); 265 } 266 else { 267 uncheckTableRows(null, zbx_objectValues($maps, 'sysmapid')); 268 } 269 show_messages($result, _('Network map deleted'), _('Cannot delete network map')); 270} 271 272/* 273 * Display 274 */ 275if (hasRequest('form')) { 276 if (!$allowed_edit) { 277 access_deny(ACCESS_DENY_PAGE); 278 } 279 280 $current_userid = CWebUser::$data['userid']; 281 $userids[$current_userid] = $current_userid; 282 $user_groupids = []; 283 284 if (!hasRequest('sysmapid') || hasRequest('form_refresh')) { 285 // Map owner 286 $map_owner = getRequest('userid', $current_userid); 287 $userids[$map_owner] = $map_owner; 288 289 foreach (getRequest('users', []) as $user) { 290 $userids[$user['userid']] = $user['userid']; 291 } 292 293 foreach (getRequest('userGroups', []) as $user_group) { 294 $user_groupids[$user_group['usrgrpid']] = $user_group['usrgrpid']; 295 } 296 } 297 else { 298 // Map owner. 299 $userids[$sysmap['userid']] = $sysmap['userid']; 300 301 foreach ($sysmap['users'] as $user) { 302 $userids[$user['userid']] = $user['userid']; 303 } 304 305 foreach ($sysmap['userGroups'] as $user_group) { 306 $user_groupids[$user_group['usrgrpid']] = $user_group['usrgrpid']; 307 } 308 } 309 310 $data['users'] = API::User()->get([ 311 'output' => ['userid', 'username', 'name', 'surname'], 312 'userids' => $userids, 313 'preservekeys' => true 314 ]); 315 316 $data['user_groups'] = API::UserGroup()->get([ 317 'output' => ['usrgrpid', 'name'], 318 'usrgrpids' => $user_groupids, 319 'preservekeys' => true 320 ]); 321 322 if (!hasRequest('sysmapid') || hasRequest('form_refresh')) { 323 $data['sysmap'] = [ 324 'sysmapid' => getRequest('sysmapid'), 325 'name' => getRequest('name', ''), 326 'width' => getRequest('width', 800), 327 'height' => getRequest('height', 600), 328 'backgroundid' => getRequest('backgroundid', 0), 329 'iconmapid' => getRequest('iconmapid', 0), 330 'label_format' => getRequest('label_format', 0), 331 'label_type_host' => getRequest('label_type_host', 2), 332 'label_type_hostgroup' => getRequest('label_type_hostgroup', 2), 333 'label_type_trigger' => getRequest('label_type_trigger', 2), 334 'label_type_map' => getRequest('label_type_map', 2), 335 'label_type_image' => getRequest('label_type_image', 2), 336 'label_string_host' => getRequest('label_string_host', ''), 337 'label_string_hostgroup' => getRequest('label_string_hostgroup', ''), 338 'label_string_trigger' => getRequest('label_string_trigger', ''), 339 'label_string_map' => getRequest('label_string_map', ''), 340 'label_string_image' => getRequest('label_string_image', ''), 341 'label_type' => getRequest('label_type', 0), 342 'label_location' => getRequest('label_location', 0), 343 'highlight' => getRequest('highlight', 0), 344 'markelements' => getRequest('markelements', 0), 345 'expandproblem' => getRequest('expandproblem', DB::getDefault('sysmaps', 'expandproblem')), 346 'show_unack' => getRequest('show_unack', 0), 347 'severity_min' => getRequest('severity_min', TRIGGER_SEVERITY_NOT_CLASSIFIED), 348 'show_suppressed' => getRequest('show_suppressed', 0), 349 'urls' => getRequest('urls', []), 350 'userid' => getRequest('userid', hasRequest('form_refresh') ? '' : $current_userid), 351 'private' => getRequest('private', PRIVATE_SHARING), 352 'users' => getRequest('users', []), 353 'userGroups' => getRequest('userGroups', []) 354 ]; 355 } 356 else { 357 $data['sysmap'] = $sysmap; 358 } 359 360 $data['current_user_userid'] = $current_userid; 361 $data['form_refresh'] = getRequest('form_refresh'); 362 363 // advanced labels 364 $data['labelTypes'] = sysmapElementLabel(); 365 $data['labelTypesLimited'] = $data['labelTypes']; 366 unset($data['labelTypesLimited'][MAP_LABEL_TYPE_IP]); 367 $data['labelTypesImage'] = $data['labelTypesLimited']; 368 unset($data['labelTypesImage'][MAP_LABEL_TYPE_STATUS]); 369 370 // images 371 $data['images'] = API::Image()->get([ 372 'output' => ['imageid', 'name'], 373 'filter' => ['imagetype' => IMAGE_TYPE_BACKGROUND] 374 ]); 375 order_result($data['images'], 'name'); 376 377 // icon maps 378 $data['iconMaps'] = API::IconMap()->get([ 379 'output' => ['iconmapid', 'name'], 380 'preservekeys' => true 381 ]); 382 order_result($data['iconMaps'], 'name'); 383 384 // render view 385 echo (new CView('monitoring.sysmap.edit', $data))->getOutput(); 386} 387else { 388 CProfile::delete('web.maps.sysmapid'); 389 390 $sortField = getRequest('sort', CProfile::get('web.'.$page['file'].'.sort', 'name')); 391 $sortOrder = getRequest('sortorder', CProfile::get('web.'.$page['file'].'.sortorder', ZBX_SORT_UP)); 392 393 CProfile::update('web.'.$page['file'].'.sort', $sortField, PROFILE_TYPE_STR); 394 CProfile::update('web.'.$page['file'].'.sortorder', $sortOrder, PROFILE_TYPE_STR); 395 396 if (hasRequest('filter_set')) { 397 CProfile::update('web.sysmapconf.filter_name', getRequest('filter_name', ''), PROFILE_TYPE_STR); 398 } 399 elseif (hasRequest('filter_rst')) { 400 DBStart(); 401 CProfile::delete('web.sysmapconf.filter_name'); 402 DBend(); 403 } 404 405 $data = [ 406 'filter' => [ 407 'name' => CProfile::get('web.sysmapconf.filter_name', '') 408 ], 409 'sort' => $sortField, 410 'sortorder' => $sortOrder, 411 'profileIdx' => 'web.sysmapconf.filter', 412 'active_tab' => CProfile::get('web.sysmapconf.filter.active', 1), 413 'allowed_edit' => $allowed_edit 414 ]; 415 416 // get maps 417 $limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1; 418 $data['maps'] = API::Map()->get([ 419 'output' => ['sysmapid', 'name', 'width', 'height'], 420 'sortfield' => $sortField, 421 'limit' => $limit, 422 'search' => [ 423 'name' => ($data['filter']['name'] === '') ? null : $data['filter']['name'] 424 ], 425 'preservekeys' => true 426 ]); 427 428 order_result($data['maps'], $sortField, $sortOrder); 429 430 // pager 431 if (hasRequest('page')) { 432 $data['page'] = getRequest('page'); 433 } 434 elseif (isRequestMethod('get') && !hasRequest('cancel')) { 435 $data['page'] = 1; 436 } 437 else { 438 $data['page'] = CPagerHelper::loadPage($page['file']); 439 } 440 441 CPagerHelper::savePage($page['file'], $data['page']); 442 443 $data['paging'] = CPagerHelper::paginate($data['page'], $data['maps'], $sortOrder, new CUrl('sysmaps.php')); 444 445 if (CWebUser::getType() != USER_TYPE_SUPER_ADMIN) { 446 $editable_maps = API::Map()->get([ 447 'output' => [], 448 'sysmapids' => array_keys($data['maps']), 449 'editable' => true, 450 'preservekeys' => true 451 ]); 452 453 foreach ($data['maps'] as &$map) { 454 $map['editable'] = array_key_exists($map['sysmapid'], $editable_maps); 455 } 456 unset($map); 457 } 458 459 // render view 460 echo (new CView('monitoring.sysmap.list', $data))->getOutput(); 461} 462 463require_once dirname(__FILE__).'/include/page_footer.php'; 464