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 22/** 23 * @var CView $this 24 */ 25?> 26 27<script type="text/x-jquery-tmpl" id="dcheck-row-tmpl"> 28 <?= (new CRow([ 29 (new CCol( 30 (new CDiv('#{name}'))->addClass(ZBX_STYLE_WORDWRAP) 31 ))->setId('dcheckCell_#{dcheckid}'), 32 (new CHorList([ 33 (new CButton(null, _('Edit'))) 34 ->addClass(ZBX_STYLE_BTN_LINK) 35 ->setAttribute('data-action', 'edit'), 36 (new CButton(null, _('Remove'))) 37 ->addClass(ZBX_STYLE_BTN_LINK) 38 ->onClick("removeDCheckRow('#{dcheckid}');") 39 ]))->addClass(ZBX_STYLE_NOWRAP) 40 ])) 41 ->setId('dcheckRow_#{dcheckid}') 42 ->toString() 43 ?> 44</script> 45<script type="text/x-jquery-tmpl" id="unique-row-tmpl"> 46 <?= (new CListItem([ 47 (new CInput('radio', 'uniqueness_criteria', '#{dcheckid}')) 48 ->addClass(ZBX_STYLE_CHECKBOX_RADIO) 49 ->setId('uniqueness_criteria_#{dcheckid}'), 50 (new CLabel([new CSpan(), '#{name}'], 'uniqueness_criteria_#{dcheckid}'))->addClass(ZBX_STYLE_WORDWRAP) 51 ])) 52 ->setId('uniqueness_criteria_row_#{dcheckid}') 53 ->toString() 54 ?> 55</script> 56<script type="text/x-jquery-tmpl" id="host-source-row-tmpl"> 57 <?= (new CListItem([ 58 (new CInput('radio', 'host_source', '_#{dcheckid}')) 59 ->addClass(ZBX_STYLE_CHECKBOX_RADIO) 60 ->setAttribute('data-id', '#{dcheckid}') 61 ->setId('host_source_#{dcheckid}'), 62 (new CLabel([new CSpan(), '#{name}'], 'host_source_#{dcheckid}'))->addClass(ZBX_STYLE_WORDWRAP) 63 ])) 64 ->setId('host_source_row_#{dcheckid}') 65 ->toString() 66 ?> 67</script> 68<script type="text/x-jquery-tmpl" id="name-source-row-tmpl"> 69 <?= (new CListItem([ 70 (new CInput('radio', 'name_source', '_#{dcheckid}')) 71 ->addClass(ZBX_STYLE_CHECKBOX_RADIO) 72 ->setAttribute('data-id', '#{dcheckid}') 73 ->setId('name_source_#{dcheckid}'), 74 (new CLabel([new CSpan(), '#{name}'], 'name_source_#{dcheckid}'))->addClass(ZBX_STYLE_WORDWRAP) 75 ])) 76 ->setId('name_source_row_#{dcheckid}') 77 ->toString() 78 ?> 79</script> 80 81<script type="text/javascript"> 82 var ZBX_CHECKLIST = {}; 83 84 function addDCheck(list) { 85 var available_device_types = [<?= SVC_AGENT ?>, <?= SVC_SNMPv1 ?>, <?= SVC_SNMPv2c ?>, <?= SVC_SNMPv3 ?>]; 86 87 var addNewValue = function(value) { 88 ZBX_CHECKLIST[value.dcheckid] = value; 89 90 jQuery('#dcheckListFooter').before(new Template(jQuery('#dcheck-row-tmpl').html()).evaluate(value)); 91 92 for (var field_name in value) { 93 if (value.hasOwnProperty(field_name)) { 94 var $input = jQuery('<input>', { 95 name: 'dchecks[' + value.dcheckid + '][' + field_name + ']', 96 type: 'hidden', 97 value: value[field_name] 98 }); 99 100 jQuery('#dcheckCell_' + value.dcheckid).append($input); 101 } 102 } 103 } 104 105 var updateNewValue = function(value) { 106 ZBX_CHECKLIST[value.dcheckid] = value; 107 108 var ignore_names = ['druleid', 'dcheckid', 'name', 'ports', 'type', 'uniq']; 109 110 // Clean values. 111 jQuery('#dcheckCell_' + value.dcheckid + ' input').each(function(i, item) { 112 var $item = jQuery(item); 113 114 var name = $item 115 .attr('name') 116 .replace('dchecks[' + value.dcheckid + '][', ''); 117 name = name.substring(0, name.length - 1); 118 119 if (jQuery.inArray(name, ignore_names) == -1) { 120 $item.remove(); 121 } 122 }); 123 124 // Set values. 125 for (var field_name in value) { 126 if (value.hasOwnProperty(field_name)) { 127 var $obj = jQuery('input[name="dchecks[' + value.dcheckid + '][' + field_name + ']"]'); 128 129 // If the input exists, update the value or create it otherwise. 130 if ($obj.length) { 131 $obj.val(value[field_name]); 132 } 133 else { 134 var $input = jQuery('<input>', { 135 name: 'dchecks[' + value.dcheckid + '][' + field_name + ']', 136 type: 'hidden', 137 value: value[field_name] 138 }); 139 140 jQuery('#dcheckCell_' + value.dcheckid).append($input); 141 } 142 } 143 } 144 145 // Update check name. 146 jQuery('#dcheckCell_' + value.dcheckid + ' .wordwrap').text(value['name']); 147 } 148 149 for (var i = 0; i < list.length; i++) { 150 if (empty(list[i])) { 151 continue; 152 } 153 154 var value = list[i]; 155 156 if (typeof value.dcheckid === 'undefined') { 157 for (;;) { 158 value.dcheckid = getUniqueId(); 159 160 if (typeof ZBX_CHECKLIST[value.dcheckid] === 'undefined') { 161 break; 162 } 163 } 164 } 165 166 if (typeof ZBX_CHECKLIST[value.dcheckid] === 'undefined') { 167 addNewValue(value); 168 } 169 else { 170 updateNewValue(value); 171 } 172 173 var elements = { 174 uniqueness_criteria: ['ip', new Template(jQuery('#unique-row-tmpl').html()).evaluate(value)], 175 host_source: ['chk_dns', new Template(jQuery('#host-source-row-tmpl').html()).evaluate(value)], 176 name_source: ['chk_host', new Template(jQuery('#name-source-row-tmpl').html()).evaluate(value)] 177 }; 178 179 jQuery.each(elements, function(key, param) { 180 var $obj = jQuery('#' + key + '_row_' + value.dcheckid); 181 182 if (jQuery.inArray(parseInt(value.type, 10), available_device_types) > -1) { 183 var new_obj = param[1]; 184 if ($obj.length) { 185 var checked_id = jQuery('input:radio[name=' + key + ']:checked').attr('id'); 186 $obj.replaceWith(new_obj); 187 jQuery('#' + checked_id).prop('checked', true); 188 } 189 else { 190 jQuery('#' + key).append(new_obj); 191 } 192 } 193 else { 194 if ($obj.length) { 195 $obj.remove(); 196 jQuery('#' + key + '_' + param[0]).prop('checked', true); 197 } 198 } 199 }); 200 } 201 } 202 203 function removeDCheckRow(dcheckid) { 204 jQuery('#dcheckRow_' + dcheckid).remove(); 205 206 delete(ZBX_CHECKLIST[dcheckid]); 207 208 var elements = { 209 uniqueness_criteria_: 'ip', 210 host_source_: 'chk_dns', 211 name_source_: 'chk_host' 212 }; 213 214 jQuery.each(elements, function(key, def) { 215 var $obj = jQuery('#' + key + dcheckid); 216 217 if ($obj.length) { 218 if ($obj.is(':checked')) { 219 jQuery('#' + key + def).prop('checked', true); 220 } 221 jQuery('#' + key + 'row_' + dcheckid).remove(); 222 } 223 }); 224 } 225 226 jQuery(function() { 227 addDCheck(<?= json_encode(array_values($data['drule']['dchecks'])) ?>); 228 229 jQuery('input:radio[name="uniqueness_criteria"][value=<?= json_encode($data['drule']['uniqueness_criteria']) ?>]').attr('checked', 'checked'); 230 jQuery('input:radio[name="host_source"][value=<?= json_encode($data['drule']['host_source']) ?>]').attr('checked', 'checked'); 231 jQuery('input:radio[name="name_source"][value=<?= json_encode($data['drule']['name_source']) ?>]').attr('checked', 'checked'); 232 233 jQuery('#clone').click(function() { 234 jQuery('#update') 235 .text(t('Add')) 236 .val('discovery.create') 237 .attr({id: 'add'}); 238 jQuery('#druleid, #delete, #clone').remove(); 239 jQuery('#form').val('clone'); 240 jQuery('#name').focus(); 241 }); 242 243 jQuery('#host_source, #name_source').on('change', 'input', function() { 244 var $elem = jQuery(this), 245 name = $elem.attr('name'); 246 247 if ($elem.data('id')) { 248 jQuery('[name^=dchecks][name$="[' + name + ']"]') 249 .val((name === 'name_source') ? <?= ZBX_DISCOVERY_UNSPEC ?> : <?= ZBX_DISCOVERY_DNS ?>); 250 jQuery('[name="dchecks[' + $elem.data('id') + '][' + name + ']"]').val(<?= ZBX_DISCOVERY_VALUE ?>); 251 } 252 else { 253 jQuery('[name^=dchecks][name$="[' + name + ']"]').val($elem.val()); 254 } 255 }); 256 257 jQuery('#dcheckList').on('click', '[data-action]', function() { 258 var $btn = jQuery(this), 259 $rows = jQuery('#dcheckList > table > tbody > tr'), 260 params; 261 262 switch ($btn.data('action')) { 263 case 'add': 264 PopUp('popup.discovery.check', {}, null, $btn); 265 break; 266 267 case 'edit': 268 var $row = $btn.closest('tr'); 269 270 params = { 271 update: 1 272 }; 273 274 $row.find('input[type="hidden"]').each(function() { 275 var $input = jQuery(this), 276 name = $input.attr('name').match(/\[([^\]]+)]$/); 277 278 if (name) { 279 params[name[1]] = $input.val(); 280 } 281 }); 282 283 PopUp('popup.discovery.check', params, null, $btn); 284 break; 285 } 286 }); 287 }); 288 289 /** 290 * Returns a default port number for the specified discovery check type. 291 * 292 * @param {string} dcheck_type Discovery check type. 293 * 294 * @returns {string} 295 */ 296 function getDCheckDefaultPort(dcheck_type) { 297 var default_ports = { 298 <?= SVC_SSH ?>: '22', 299 <?= SVC_LDAP ?>: '389', 300 <?= SVC_SMTP ?>: '25', 301 <?= SVC_FTP ?>: '21', 302 <?= SVC_HTTP ?>: '80', 303 <?= SVC_POP ?>: '110', 304 <?= SVC_NNTP ?>: '119', 305 <?= SVC_IMAP ?>: '143', 306 <?= SVC_AGENT ?>: '10050', 307 <?= SVC_SNMPv1 ?>: '161', 308 <?= SVC_SNMPv2c ?>: '161', 309 <?= SVC_SNMPv3 ?>: '161', 310 <?= SVC_HTTPS ?>: '443', 311 <?= SVC_TELNET ?>: '23' 312 }; 313 314 return default_ports.hasOwnProperty(dcheck_type) ? default_ports[dcheck_type] : '0'; 315 } 316 317 /** 318 * Set default discovery check port to input. 319 * 320 * @return {object} 321 */ 322 function setDCheckDefaultPort() { 323 return jQuery('#ports').val(getDCheckDefaultPort(jQuery('#type-select').val())); 324 } 325 326 /** 327 * Sends discovery check form data to the server for validation before adding it to the main form. 328 * 329 * @param {Overlay} overlay 330 */ 331 function submitDCheck(overlay) { 332 var $form = overlay.$dialogue.find('form'); 333 334 $form.trimValues([ 335 '#ports', '#key_', '#snmp_community', '#snmp_oid', '#snmpv3_contextname', '#snmpv3_securityname', 336 '#snmpv3_authpassphrase', '#snmpv3_privpassphrase' 337 ]); 338 339 var data = $form 340 .find('#type, #ports, input[type=hidden], input[type=text]:visible, input[type=radio]:checked:visible') 341 .serialize(), 342 dialogueid = $form 343 .closest("[data-dialogueid]") 344 .data('dialogueid'); 345 346 if (!dialogueid) { 347 return false; 348 } 349 350 overlay.setLoading(); 351 overlay.xhr = sendAjaxData('zabbix.php', { 352 data: data, 353 dataType: 'json', 354 method: 'POST', 355 complete: function() { 356 overlay.unsetLoading(); 357 } 358 }).done(function(response) { 359 $form 360 .parent() 361 .find('.<?= ZBX_STYLE_MSG_BAD ?>') 362 .remove(); 363 364 if (typeof response.errors !== 'undefined') { 365 return jQuery(response.errors).insertBefore($form); 366 } 367 else { 368 var dcheck = response.params; 369 370 if (typeof dcheck.ports !== 'undefined' && dcheck.ports != getDCheckDefaultPort(dcheck.type)) { 371 dcheck.name += ' (' + dcheck.ports + ')'; 372 } 373 if (dcheck.key_) { 374 dcheck.name += ' "' + dcheck.key_ + '"'; 375 } 376 dcheck.host_source = jQuery('[name="host_source"]:checked:not([data-id])').val() 377 || '<?= ZBX_DISCOVERY_DNS ?>'; 378 dcheck.name_source = jQuery('[name="name_source"]:checked:not([data-id])').val() 379 || '<?= ZBX_DISCOVERY_UNSPEC ?>'; 380 381 if (hasDCheckDuplicates()) { 382 jQuery(makeMessageBox('bad', <?= json_encode(_('Check already exists.')) ?>, null, true, false)) 383 .insertBefore($form); 384 385 return false; 386 } 387 388 addDCheck([dcheck]); 389 overlayDialogueDestroy(overlay.dialogueid); 390 } 391 }); 392 } 393 394 /** 395 * Check for duplicates. 396 * 397 * @return {boolean} 398 */ 399 function hasDCheckDuplicates() { 400 var $form = jQuery(document.forms['dcheck_form']), 401 dcheckid = jQuery('#dcheckid').val(), 402 dcheck = $form 403 .find('#ports, >input[type=hidden], input[type=text]:visible, input[type=radio]:checked:visible') 404 .serializeJSON(), 405 fields = ['type', 'ports', 'snmp_community', 'key_', 'snmpv3_contextname', 'snmpv3_securityname', 406 'snmpv3_securitylevel', 'snmpv3_authprotocol', 'snmpv3_authpassphrase', 'snmpv3_privprotocol', 407 'snmpv3_privpassphrase' 408 ]; 409 410 dcheck['type'] = $form.find('z-select').val(); 411 dcheck.dcheckid = dcheckid ? dcheckid : getUniqueId(); 412 413 if (dcheck['type'] == <?= SVC_SNMPv1 ?> || dcheck['type'] == <?= SVC_SNMPv2c ?> 414 || dcheck['type'] == <?= SVC_SNMPv3 ?>) { 415 dcheck['key_'] = dcheck['snmp_oid']; 416 } 417 418 for (var zbx_dcheckid in ZBX_CHECKLIST) { 419 if (ZBX_CHECKLIST[zbx_dcheckid]['type'] !== dcheck['type']) { 420 continue; 421 } 422 423 if (typeof dcheckid === 'undefined' || dcheckid != zbx_dcheckid) { 424 var duplicate_fields = fields 425 .map(function(value) { 426 return typeof dcheck[value] === 'undefined' 427 || dcheck[value] === '' 428 || ZBX_CHECKLIST[zbx_dcheckid][value] === dcheck[value]; 429 }) 430 .filter(function(value) { 431 return !!value; 432 }); 433 434 if (duplicate_fields.length === fields.length) { 435 return true; 436 } 437 } 438 } 439 440 return false; 441 } 442 443 $(() => { 444 const $form = $(document.forms['discoveryForm']); 445 $form.on('submit', () => $form.trimValues(['#name', '#iprange', '#delay'])); 446 }); 447</script> 448