1<?php 2/* 3 +-------------------------------------------------------------------------+ 4 | Copyright (C) 2004-2021 The Cacti Group | 5 | | 6 | This program is free software; you can redistribute it and/or | 7 | modify it under the terms of the GNU General Public License | 8 | as published by the Free Software Foundation; either version 2 | 9 | of the License, or (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 | Cacti: The Complete RRDtool-based Graphing Solution | 17 +-------------------------------------------------------------------------+ 18 | This code is designed, written, and maintained by the Cacti Group. See | 19 | about.php and/or the AUTHORS file for specific developer information. | 20 +-------------------------------------------------------------------------+ 21 | http://www.cacti.net/ | 22 +-------------------------------------------------------------------------+ 23*/ 24 25function clog_get_datasource_titles($local_data_ids) { 26 if (!is_array($local_data_ids)) { 27 $local_data_ids = array($local_data_ids); 28 } 29 30 $titles = array(); 31 foreach ($local_data_ids as $local_data_id) { 32 if (!array_key_exists($local_data_id, $titles)) { 33 $titles[$local_data_id] = get_data_source_title($local_data_id); 34 } 35 } 36 37 return $titles; 38} 39 40function clog_get_graphs_from_datasource($local_data_id) { 41 return array_rekey(db_fetch_assoc_prepared('SELECT DISTINCT 42 gtg.local_graph_id AS id, 43 gtg.title_cache AS name 44 FROM graph_templates_graph AS gtg 45 INNER JOIN graph_templates_item AS gti 46 ON gtg.local_graph_id=gti.local_graph_id 47 INNER JOIN data_template_rrd AS dtr 48 ON gti.task_item_id=dtr.id 49 WHERE gtg.local_graph_id>0 50 AND dtr.local_data_id = ?', 51 array($local_data_id)), 'id', 'name'); 52} 53 54function clog_validate_filename(&$file, &$filepath, &$filename, $filecheck = false) { 55 global $config; 56 57 $logfile = read_config_option('path_cactilog'); 58 if ($logfile == '') { 59 $logfile = '/var/log/cacti/log'; 60 } 61 62 $errfile = read_config_option('path_stderrlog'); 63 $errbase = basename($errfile); 64 65 $file = basename($file); 66 $logbase = basename($logfile); 67 68 $filepath = ''; 69 $filename = ''; 70 $filefull = ''; 71 72 if (!empty($errfile) && strpos($file, $errbase) === 0) { 73 $filepath = dirname($errfile); 74 $filename = $errbase; 75 $filefull = $filepath . '/' . $file; 76 } elseif (!empty($logfile) && strpos($file, $logbase) === 0) { 77 $filepath = dirname($logfile); 78 $filename = $logbase; 79 $filefull = $filepath . '/' . $file; 80 } 81 82 return ($filecheck ? file_exists($filefull) : !empty($filefull)); 83} 84 85function clog_purge_logfile() { 86 global $config; 87 88 $filename = get_nfilter_request_var('filename'); 89 90 if (!clog_validate_filename($filename, $logpath, $logname)) { 91 raise_message('clog_invalid'); 92 header('Location: ' . get_current_page()); 93 exit(0); 94 } 95 96 $purgefile = $logpath . '/' . $filename; 97 $logfile = $logpath . '/'. $logname; 98 99 if (file_exists($purgefile)) { 100 if (is_writable($purgefile)) { 101 if ($logfile != $purgefile) { 102 unlink($purgefile); 103 raise_message('clog_remove'); 104 } else { 105 /* fill in the current date for printing in the log */ 106 if (defined('CACTI_DATE_TIME_FORMAT')) { 107 $date = date(CACTI_DATE_TIME_FORMAT); 108 } else { 109 $date = date('Y-m-d H:i:s'); 110 } 111 112 $log_fh = fopen($logfile, 'w'); 113 fwrite($log_fh, __('%s - WEBUI NOTE: Cacti Log Cleared from Web Management Interface.', $date) . PHP_EOL); 114 fclose($log_fh); 115 raise_message('clog_purged'); 116 } 117 118 cacti_log('NOTE: Cacti Log file ' . $purgefile . ', Removed by user ' . get_username($_SESSION['sess_user_id']), false, 'WEBUI'); 119 } else { 120 raise_message('clog_permissions'); 121 } 122 } else { 123 raise_message('clog_missing'); 124 } 125} 126 127function clog_view_logfile() { 128 global $config; 129 130 $exclude_reported = false; 131 132 $clogAdmin = clog_admin(); 133 134 /* ================= input validation and session storage ================= */ 135 $filters = array( 136 'page' => array( 137 'filter' => FILTER_VALIDATE_INT, 138 'default' => '1' 139 ), 140 'tail_lines' => array( 141 'filter' => FILTER_VALIDATE_INT, 142 'default' => read_config_option('num_rows_log'), 143 'pageset' => true 144 ), 145 'message_type' => array( 146 'filter' => FILTER_VALIDATE_INT, 147 'default' => '-1', 148 'pageset' => true 149 ), 150 'filename' => array( 151 'filter' => FILTER_CALLBACK, 152 'default' => read_config_option('path_cactilog'), 153 'pageset' => true, 154 'options' => array('options' => 'sanitize_search_string') 155 ), 156 'refresh' => array( 157 'filter' => FILTER_VALIDATE_INT, 158 'default' => read_config_option('log_refresh_interval') 159 ), 160 'reverse' => array( 161 'filter' => FILTER_VALIDATE_INT, 162 'default' => '1' 163 ), 164 'rfilter' => array( 165 'filter' => FILTER_VALIDATE_IS_REGEX, 166 'default' => '', 167 'pageset' => true 168 ) 169 ); 170 171 validate_store_request_vars($filters, 'sess_clog'); 172 /* ================= input validation ================= */ 173 174 /* enable page refreshes */ 175 kill_session_var('custom'); 176 177 set_request_var('page_referrer', 'view_logfile'); 178 load_current_session_value('page_referrer', 'page_referrer', 'view_logfile'); 179 180 $logfile = basename(get_nfilter_request_var('filename')); 181 $logname = ''; 182 183 if (!clog_validate_filename($logfile, $logpath, $logname, true)) { 184 $logfile = read_config_option('path_cactilog'); 185 } else { 186 $logfile = $logpath . '/' . $logfile; 187 } 188 189 if ($clogAdmin && isset_request_var('purge_continue')) { 190 clog_purge_logfile(); 191 $logfile = read_config_option('path_cactilog'); 192 } 193 194 $page_nr = get_request_var('page'); 195 196 $page = $config['url_path'] . 'clog' . (!$clogAdmin ? '_user' : '') . '.php?header=false'; 197 $page .= '&filename=' . basename($logfile) . '&page=' . $page_nr; 198 199 $refresh = array( 200 'seconds' => get_request_var('refresh'), 201 'page' => $page, 202 'logout' => 'false' 203 ); 204 205 set_page_refresh($refresh); 206 207 general_header(); 208 209 if ($clogAdmin && isset_request_var('purge')) { 210 form_start('clog.php'); 211 212 html_start_box(__('Purge'), '50%', '', '3', 'center', ''); 213 214 print "<tr> 215 <td class='textArea'> 216 <p>" . __('Click \'Continue\' to purge the Log File.<br><br><br>Note: If logging is set to both Cacti and Syslog, the log information will remain in Syslog.') . "</p> 217 </td> 218 </tr> 219 <tr class='saveRow'> 220 <td colspan='2' class='right'> 221 <input type='button' class='ui-button ui-corner-all ui-widget' id='cancel' value='" . __esc('Cancel') . "'>  222 <input type='button' class='ui-button ui-corner-all ui-widget' id='pc' name='purge_continue' value='" . __esc('Continue') . "' title='" . __esc('Purge Log') . "'> 223 <script type='text/javascript'> 224 $('#pc').click(function() { 225 strURL = location.pathname+'?purge_continue=1&header=false&filename=" . basename($logfile) . "'; 226 loadPageNoHeader(strURL); 227 }); 228 229 $('#cancel').click(function() { 230 strURL = location.pathname+'?header=false'; 231 loadPageNoHeader(strURL); 232 }); 233 234 $(function() { 235 applySkin(); 236 }); 237 </script> 238 </td> 239 </tr>\n"; 240 241 html_end_box(); 242 243 return; 244 } 245 246 html_start_box(__('Log Filters'), '100%', '', '3', 'center', ''); 247 filter($clogAdmin, basename($logfile)); 248 html_end_box(); 249 250 /* read logfile into an array and display */ 251 $total_rows = 0; 252 $number_of_lines = get_request_var('tail_lines') < 0 ? read_config_option('max_display_rows') : get_request_var('tail_lines'); 253 254 $logcontents = tail_file($logfile, $number_of_lines, get_request_var('message_type'), get_request_var('rfilter'), $page_nr, $total_rows); 255 256 if (get_request_var('reverse') == 1) { 257 $logcontents = array_reverse($logcontents); 258 } 259 260 if (!$clogAdmin) { 261 $exclude_regex = read_config_option('clog_exclude', true); 262 if ($exclude_regex != '') { 263 $ad_filter = __(' - Admin Filter active'); 264 } else { 265 $ad_filter = __(' - Admin Unfiltered'); 266 } 267 } else { 268 $ad_filter = __(' - Admin view'); 269 $exclude_regex = ''; 270 } 271 272 if (get_request_var('message_type') > 0 || get_request_var('rfilter') != '') { 273 $start_string = __('Log [Total Lines: %d %s - Filter active]', $total_rows, $ad_filter); 274 } else { 275 $start_string = __('Log [Total Lines: %d %s - Unfiltered]', $total_rows, $ad_filter); 276 } 277 278 $rfilter = get_request_var('rfilter'); 279 $reverse = get_request_var('reverse'); 280 $refreshTime = get_request_var('refresh'); 281 $message_type = get_request_var('message_type'); 282 $tail_lines = get_request_var('tail_lines'); 283 $base_url = $config['url_path'] . 'clog.php'; 284 285 $nav = html_nav_bar($base_url, MAX_DISPLAY_PAGES, $page_nr, $number_of_lines, $total_rows, 1, __('Entries'), 'page', 'main'); 286 287 print $nav; 288 289 html_start_box($start_string, '100%', '', '3', 'center', ''); 290 291 $linecolor = false; 292 293 $hosts = db_fetch_assoc('SELECT id, description 294 FROM host 295 WHERE disabled = "" 296 AND deleted = ""'); 297 298 $hostDescriptions = array(); 299 foreach ($hosts as $host) { 300 $hostDescriptions[$host['id']] = html_escape($host['description']); 301 } 302 303 $regex_array = clog_get_regex_array(); 304 foreach ($logcontents as $item) { 305 $new_item = html_escape($item); 306 307 $new_item = preg_replace_callback($regex_array['complete'],'clog_regex_parser',$new_item); 308 309 /* respect the exclusion filter */ 310 if ($exclude_regex != '' && !$clogAdmin) { 311 if (validate_is_regex($exclude_regex)) { 312 if (preg_match($exclude_regex, $new_item)) { 313 continue; 314 } 315 } elseif (!$exclude_reported) { 316 cacti_log('Cacti Log Exclude Regex "' . $exclude_regex . '" is Invalid. Update your Exclude Regex to be valid!'); 317 $exclude_reported = true; 318 } 319 } 320 321 /* get the background color */ 322 if (strpos($new_item, 'ERROR') !== false || strpos($new_item, 'FATAL') !== false) { 323 $class = 'clogError'; 324 } elseif (strpos($new_item, 'WARN') !== false) { 325 $class = 'clogWarning'; 326 } elseif (strpos($new_item, ' SQL ') !== false) { 327 $class = 'clogSQL'; 328 } elseif (strpos($new_item, 'DEBUG') !== false) { 329 $class = 'clogDebug'; 330 } elseif (strpos($new_item, 'STATS') !== false) { 331 $class = 'clogStats'; 332 } else { 333 if ($linecolor) { 334 $class = 'odd'; 335 } else { 336 $class = 'even'; 337 } 338 $linecolor = !$linecolor; 339 } 340 341 ?> 342 <tr class='<?php print $class;?>'> 343 <td> 344 <?php print $new_item;?> 345 </td> 346 </tr> 347 <?php 348 } 349 350 html_end_box(false); 351 352 if ($total_rows) { 353 print $nav; 354 } 355 356 bottom_footer(); 357} 358 359function filter_sort($a, $b) { 360 $a_parts = explode('-', $a); 361 $b_parts = explode('-', $b); 362 363 $a_date = '99999999'; 364 if (cacti_count($a_parts) > 1) { 365 $a_date = $a_parts[1]; 366 } 367 368 $b_date = '99999999'; 369 if (cacti_count($b_parts) > 1) { 370 $b_date = $b_parts[1]; 371 } 372 373 // Invert the order, replace _'s with +'s to make them sort after .'s, prefix the date 374 // This makes cacti_stderr.log appear after cacti.log in date descending order with 375 // no date files first 376 return strcmp($b_date . '-' . str_replace('_','+',$b_parts[0]), $a_date . '-' . str_replace('_','+',$a_parts[0])); 377} 378 379function clog_get_logfiles() { 380 global $config; 381 382 $stdFileArray = $stdLogFileArray = $stdErrFileArray = array(); 383 $configLogPath = read_config_option('path_cactilog'); 384 $configLogBase = basename($configLogPath); 385 $stderrLogPath = read_config_option('path_stderrlog'); 386 $stderrLogBase = basename($stderrLogPath); 387 388 if ($configLogPath == '') { 389 $logPath = $config['base_path'] . '/log/'; 390 } else { 391 $logPath = dirname($configLogPath); 392 } 393 394 if (is_readable($logPath)) { 395 $files = @scandir($logPath); 396 } else { 397 $files = array('cacti.log'); 398 } 399 400 // Defaults go first and second 401 $stdFileArray[] = basename($configLogPath); 402 403 // After Defaults, do Cacti log first (of archived) 404 if (cacti_sizeof($files)) { 405 $stdLogFileArray = array(); 406 foreach ($files as $logFile) { 407 if (in_array($logFile, array('.', '..', '.htaccess', $configLogBase, $stderrLogBase))) { 408 continue; 409 } 410 411 $explode = explode('.', $logFile); 412 if (substr($explode[max(array_keys($explode))], 0, 3) != 'log') { 413 continue; 414 } 415 416 if (!clog_validate_filename($logFile, $logPath, $logName)) { 417 continue; 418 } 419 420 if (!empty($stderrlogbase) && strpos($logFile, $stderrLogBase) === 0){ 421 $stdErrFileArray[] = $logFile; 422 } else { 423 $stdLogFileArray[] = $logFile; 424 } 425 } 426 427 $stdErrFileArray = array_unique($stdErrFileArray); 428 $stdLogFileArray = array_unique($stdLogFileArray); 429 } 430 431 // Defaults go first and second 432 if (!empty($stderrLogPath)) { 433 $stdFileArray[] = basename($stderrLogPath); 434 435 // After Defaults, do Cacti StdErr log second (of archived) 436 if (dirname($stderrLogPath) != $logPath) { 437 $errFiles = @scandir(dirname($stderrLogPath)); 438 $files = $errFiles; 439 if (cacti_sizeof($files)) { 440 $stdErrFileArray = array(); 441 foreach ($files as $logFile) { 442 if (in_array($logFile, array('.', '..', '.htaccess', $configLogBase, $stderrLogBase))) { 443 continue; 444 } 445 446 $explode = explode('.', $logFile); 447 if (substr($explode[max(array_keys($explode))], 0, 3) != 'log') { 448 continue; 449 } 450 451 if (!clog_validate_filename($logFile, $logPath, $logName)) { 452 continue; 453 } 454 455 $stdErrFileArray[] = $logFile; 456 } 457 458 $stdErrFileArray = array_unique($stdErrFileArray); 459 } 460 } 461 } 462 463 arsort($stdLogFileArray, SORT_NATURAL); 464 arsort($stdErrFileArray, SORT_NATURAL); 465 466 return array_unique(array_merge($stdFileArray, $stdLogFileArray, $stdErrFileArray)); 467} 468 469function filter($clogAdmin, $selectedFile) { 470 global $page_refresh_interval, $log_tail_lines, $config; 471 ?> 472 <tr class='even'> 473 <td> 474 <form id='logfile'> 475 <table class='filterTable'> 476 <tr> 477 <td> 478 <?php print __('File');?> 479 </td> 480 <td> 481 <select id='filename'> 482 <?php 483 $logFileArray = clog_get_logfiles(); 484 485 if (cacti_sizeof($logFileArray)) { 486 foreach ($logFileArray as $logFile) { 487 print "<option value='" . $logFile . "'"; 488 489 if ($selectedFile == $logFile) { 490 print ' selected'; 491 } 492 493 $logParts = explode('-', $logFile); 494 495 $logDate = cacti_count($logParts) < 2 ? '' : $logParts[1] . (isset($logParts[2]) ? '-' . $logParts[2]:''); 496 $logName = $logParts[0]; 497 498 print '>' . $logName . ($logDate != '' ? ' [' . substr($logDate,4) . ']':'') . "</option>\n"; 499 } 500 } 501 ?> 502 </select> 503 </td> 504 <td> 505 <?php print __('Tail Lines');?> 506 </td> 507 <td> 508 <select id='tail_lines'> 509 <?php 510 foreach($log_tail_lines AS $tail_lines => $display_text) { 511 print "<option value='" . $tail_lines . "'"; 512 if (get_request_var('tail_lines') == $tail_lines) { 513 print ' selected'; 514 } 515 print '>' . $display_text . "</option>\n"; 516 } 517 ?> 518 </select> 519 </td> 520 <td> 521 <span> 522 <input type='submit' class='ui-button ui-corner-all ui-widget' id='go' value='<?php print __esc('Go');?>'> 523 <input type='button' class='ui-button ui-corner-all ui-widget' id='clear' value='<?php print __esc('Clear');?>'> 524 <?php if ($clogAdmin) {?><input type='button' class='ui-button ui-corner-all ui-widget' id='purge' value='<?php print __esc('Purge');?>'><?php }?> 525 </span> 526 </td> 527 </tr> 528 </table> 529 <table class='filterTable'> 530 <tr> 531 <td> 532 <?php print __('Type');?> 533 </td> 534 <td> 535 <select id='message_type'> 536 <option value='-1'<?php if (get_request_var('message_type') == '-1') {?> selected<?php }?>><?php print __('All');?></option> 537 <option value='1'<?php if (get_request_var('message_type') == '1') {?> selected<?php }?>><?php print __('Stats');?></option> 538 <option value='2'<?php if (get_request_var('message_type') == '2') {?> selected<?php }?>><?php print __('Warnings');?></option> 539 <option value='3'<?php if (get_request_var('message_type') == '3') {?> selected<?php }?>><?php print __('Errors');?></option> 540 <option value='4'<?php if (get_request_var('message_type') == '4') {?> selected<?php }?>><?php print __('Debug');?></option> 541 <option value='5'<?php if (get_request_var('message_type') == '5') {?> selected<?php }?>><?php print __('SQL Calls');?></option> 542 </select> 543 </td> 544 <td> 545 <?php print __('Display Order');?> 546 </td> 547 <td> 548 <select id='reverse'> 549 <option value='1'<?php if (get_request_var('reverse') == '1') {?> selected<?php }?>><?php print __('Newest First');?></option> 550 <option value='2'<?php if (get_request_var('reverse') == '2') {?> selected<?php }?>><?php print __('Oldest First');?></option> 551 </select> 552 </td> 553 <td> 554 <?php print __('Refresh');?> 555 </td> 556 <td> 557 <select id='refresh'> 558 <?php 559 foreach($page_refresh_interval AS $seconds => $display_text) { 560 print "<option value='" . $seconds . "'"; 561 if (get_request_var('refresh') == $seconds) { 562 print ' selected'; 563 } 564 print '>' . $display_text . '</option>'; 565 } 566 ?> 567 </select> 568 </td> 569 </tr> 570 </table> 571 <table class='filterTable'> 572 <tr> 573 <td> 574 <?php print __('Search');?> 575 </td> 576 <td> 577 <input type='text' class='ui-state-default ui-corner-all' id='rfilter' size='75' value='<?php print html_escape_request_var('rfilter');?>'> 578 </td> 579 </tr> 580 </table> 581 </form> 582 <script type='text/javascript'> 583 584 $(function() { 585 $('#rfilter, #reverse, #refresh, #message_type, #filename, #tail_lines').unbind().change(function() { 586 applyFilter(); 587 }); 588 589 $('#clear').unbind().click(function() { 590 strURL = basename(location.pathname) + '?clear=true&header=false'; 591 loadPageNoHeader(strURL); 592 }); 593 594 $('#purge').unbind().click(function() { 595 strURL = basename(location.pathname) + '?purge=true&header=false&filename=' + $('#filename').val(); 596 loadPageNoHeader(strURL); 597 }); 598 599 $('#logfile').submit(function(event) { 600 event.preventDefault(); 601 applyFilter(); 602 }); 603 }); 604 605 function applyFilter() { 606 refreshMSeconds=$('#refresh').val()*1000; 607 608 strURL = basename(location.pathname)+ 609 '?rfilter=' + base64_encode($('#rfilter').val())+ 610 '&reverse='+$('#reverse').val()+ 611 '&refresh='+$('#refresh').val()+ 612 '&message_type='+$('#message_type').val()+ 613 '&tail_lines='+$('#tail_lines').val()+ 614 '&filename='+$('#filename').val()+ 615 '&header=false'; 616 617 loadPageNoHeader(strURL); 618 } 619 </script> 620 </td> 621 </tr> 622 <?php 623} 624 625function clog_get_regex_array() { 626 static $regex_array = array(); 627 628 if (!cacti_sizeof($regex_array)) { 629 $regex_array = array( 630 1 => array('name' => 'DS', 'regex' => '( DS\[)([, \d]+)(\])', 'func' => 'clog_regex_datasource'), 631 2 => array('name' => 'DQ', 'regex' => '( DQ\[)([, \d]+)(\])', 'func' => 'clog_regex_dataquery'), 632 3 => array('name' => 'Device', 'regex' => '( Device\[)([, \d]+)(\])', 'func' => 'clog_regex_device'), 633 4 => array('name' => 'Poller', 'regex' => '( Poller\[)([, \d]+)(\])', 'func' => 'clog_regex_poller'), 634 5 => array('name' => 'RRA', 'regex' => "([_\/])(\d+)(\.rrd')", 'func' => 'clog_regex_rra'), 635 6 => array('name' => 'GT', 'regex' => '( GT\[)([, \d]+)(\])', 'func' => 'clog_regex_graphtemplates'), 636 7 => array('name' => 'Graph', 'regex' => '( Graph\[)([, \d]+)(\])', 'func' => 'clog_regex_graphs'), 637 8 => array('name' => 'Graphs', 'regex' => '( Graphs\[)([, \d]+)(\])', 'func' => 'clog_regex_graphs'), 638 9 => array('name' => 'User', 'regex' => '( User\[)([, \d]+)(\])', 'func' => 'clog_regex_users'), 639 10 => array('name' => 'User', 'regex' => '( Users\[)([, \d]+)(\])', 'func' => 'clog_regex_users'), 640 11 => array('name' => 'Rule', 'regex' => '( Rule\[)([, \d]+)(\])', 'func' => 'clog_regex_rule'), 641 ); 642 643 $regex_array = api_plugin_hook_function('clog_regex_array',$regex_array); 644 $regex_complete = ''; 645 foreach ($regex_array as $regex_key => $regex_setting) { 646 $regex_complete .= (strlen($regex_complete)?')|(':'').$regex_setting['regex']; 647 } 648 $regex_complete = '~('.$regex_complete.')~'; 649 $regex_array['complete'] = $regex_complete; 650 } 651 652 return $regex_array; 653} 654 655function clog_regex_parser($matches) { 656 $result = $matches[0]; 657 $match = $matches[0]; 658 659 $key_match = -1; 660 for ($index = 1; $index < cacti_sizeof($matches); $index++) { 661 if ($match == $matches[$index]) { 662 $key_match = $index; 663 break; 664 } 665 } 666 667 if ($key_match != -1) { 668 $key_setting = ($key_match - 1) / 4 + 1; 669 $regex_array = clog_get_regex_array(); 670 671 if (cacti_sizeof($regex_array)) { 672 if (array_key_exists($key_setting, $regex_array)) { 673 $regex_setting = $regex_array[$key_setting]; 674 675 $rekey_array = array(); 676 for ($j = 0; $j < 4; $j++) { 677 $rekey_array[$j] = $matches[$key_match + $j]; 678 } 679 680 if (function_exists($regex_setting['func'])) { 681 $result=call_user_func_array($regex_setting['func'],array($rekey_array)); 682 } else { 683 $result=$match; 684 } 685 } 686 } 687 } 688 689 return $result; 690} 691 692function clog_regex_device($matches) { 693 global $config; 694 695 $result = $matches[0]; 696 697 $dev_ids = explode(',',str_replace(" ","",$matches[2])); 698 if (cacti_sizeof($dev_ids)) { 699 $result = ''; 700 $hosts = db_fetch_assoc('SELECT id, description 701 FROM host 702 WHERE id in (' . implode(',',$dev_ids) . ')'); 703 704 $hostDescriptions = array(); 705 if (cacti_sizeof($hosts)) { 706 foreach ($hosts as $host) { 707 $hostDescriptions[$host['id']] = html_escape($host['description']); 708 } 709 } 710 711 foreach ($dev_ids as $host_id) { 712 $result .= $matches[1].'<a href=\'' . html_escape($config['url_path'] . 'host.php?action=edit&id=' . $host_id) . '\'>' . (isset($hostDescriptions[$host_id]) ? $hostDescriptions[$host_id]:$host_id) . '</a>' . $matches[3]; 713 } 714 } 715 716 return $result; 717} 718 719function clog_regex_datasource($matches) { 720 global $config; 721 722 $result = $matches[0]; 723 724 $ds_ids = explode(',',str_replace(" ","",$matches[2])); 725 if (cacti_sizeof($ds_ids)) { 726 $result = ''; 727 728 $graph_rows = array_rekey(db_fetch_assoc('SELECT DISTINCT 729 gtg.local_graph_id AS id 730 FROM graph_templates_graph AS gtg 731 INNER JOIN graph_templates_item AS gti 732 ON gtg.local_graph_id=gti.local_graph_id 733 INNER JOIN data_template_rrd AS dtr 734 ON gti.task_item_id=dtr.id 735 WHERE gtg.local_graph_id>0 736 AND dtr.local_data_id IN (' . $matches[2] . ')'),'id','id'); 737 738 $graph_results = ''; 739 if (cacti_sizeof($graph_rows)) { 740 $graph_ids = implode(',',$graph_rows); 741 $graph_array = array( 0 => '', 1 => ' Graphs[', 2 => $graph_ids, 3 => ']'); 742 743 $graph_results = clog_regex_graphs($graph_array); 744 } 745 746 $result .= $matches[1]; 747 $i = 0; 748 749 $ds_ids = array_unique($ds_ids); 750 $ds_titles = clog_get_datasource_titles($ds_ids); 751 if (!isset($ds_titles)) { 752 $ds_titles = array(); 753 } 754 755 foreach($ds_ids as $ds_id) { 756 $ds_title = $ds_id; 757 if (array_key_exists($ds_id, $ds_titles)) { 758 $ds_title = $ds_titles[$ds_id]; 759 } 760 $result .= ($i == 0 ? '':', ') . "<a href='" . html_escape($config['url_path'] . 'data_sources.php?action=ds_edit&id=' . $ds_id) . "'>" . html_escape($ds_title) . '</a>'; 761 762 $i++; 763 } 764 765 $result .= $matches[3] . $graph_results; 766 } 767 768 return $result; 769} 770 771function clog_regex_poller($matches) { 772 global $config; 773 774 $result = $matches[0]; 775 776 $poller_ids = explode(',',str_replace(" ","",$matches[2])); 777 if (cacti_sizeof($poller_ids)) { 778 $result = ''; 779 $pollers = db_fetch_assoc_prepared('SELECT id, name 780 FROM poller 781 WHERE id in (' . implode(',',$poller_ids) . ')'); 782 783 $pollerDescriptions = array(); 784 if (cacti_sizeof($pollers)) { 785 foreach ($pollers as $poller) { 786 $pollerDescriptions[$poller['id']] = html_escape($poller['name']); 787 } 788 } 789 790 foreach ($poller_ids as $poller_id) { 791 $result .= $matches[1].'<a href=\'' . html_escape($config['url_path'] . 'pollers.php?action=edit&id=' . $poller_id) . '\'>' . (isset($pollerDescriptions[$poller_id]) ? $pollerDescriptions[$poller_id]:$poller_id) . '</a>' . $matches[3]; 792 } 793 } 794 795 return $result; 796} 797 798function clog_regex_dataquery($matches) { 799 global $config; 800 801 $result = $matches[0]; 802 803 $query_ids = explode(',',str_replace(" ","",$matches[2])); 804 if (cacti_sizeof($query_ids)) { 805 $result = ''; 806 $querys = db_fetch_assoc('SELECT id, name 807 FROM snmp_query 808 WHERE id in (' . implode(',',$query_ids) . ')'); 809 810 $queryDescriptions = array(); 811 if (cacti_sizeof($querys)) { 812 foreach ($querys as $query) { 813 $queryDescriptions[$query['id']] = html_escape($query['name']); 814 } 815 } 816 817 foreach ($query_ids as $query_id) { 818 $result .= $matches[1].'<a href=\'' . html_escape($config['url_path'] . 'data_queries.php?action=edit&id=' . $query_id) . '\'>' . (isset($queryDescriptions[$query_id]) ? $queryDescriptions[$query_id]:$query_id) . '</a>' . $matches[3]; 819 } 820 } 821 822 return $result; 823} 824 825function clog_regex_rra($matches) { 826 global $config; 827 828 $result = $matches[0]; 829 830 $local_data_ids = $matches[2]; 831 if (strlen($local_data_ids)) { 832 $datasource_array = array( 0 => '', 1 => ' DS[', 2 => $local_data_ids, 3 => ']'); 833 $datasource_result = clog_regex_datasource($datasource_array); 834 if (strlen($datasource_result)) { 835 $result .= ' '. $datasource_result; 836 } 837 } 838 839 return $result; 840} 841 842function clog_regex_graphs($matches) { 843 global $config; 844 845 $result = $matches[0]; 846 847 $query_ids = explode(',',str_replace(" ","",$matches[2])); 848 if (cacti_sizeof($query_ids)) { 849 $result = ''; 850 $graph_add = $config['url_path'] . 'graph_view.php?page=1&style=selective&action=preview&graph_add='; 851 852 $title = ''; 853 $i = 0; 854 855 $querys = db_fetch_assoc('SELECT DISTINCT 856 gtg.local_graph_id AS id, 857 gtg.title_cache AS title 858 FROM graph_templates_graph AS gtg 859 INNER JOIN graph_templates_item AS gti 860 ON gtg.local_graph_id=gti.local_graph_id 861 INNER JOIN data_template_rrd AS dtr 862 ON gti.task_item_id=dtr.id 863 WHERE gtg.local_graph_id in (' . implode(',',$query_ids) . ')'); 864 865 $result .= $matches[1] . "<a href='"; 866 867 $queryDescriptions = array(); 868 if (cacti_sizeof($querys)) { 869 foreach ($querys as $query) { 870 $queryDescriptions[$query['id']] = html_escape($query['title']); 871 } 872 } 873 874 $i=0; 875 foreach ($query_ids as $query_id) { 876 $graph_add .= ($i > 0 ? '%2C' : '') . $query_id; 877 $title .= ($title != '' ? ', ':'') . html_escape((isset($queryDescriptions[$query_id]) ? $queryDescriptions[$query_id]:$query_id)); 878 $i++; 879 } 880 881 $result .= html_escape($graph_add) . '\'>' . $title . '</a>' . $matches[3]; 882 } 883 return $result; 884} 885 886function clog_regex_graphtemplates($matches) { 887 global $config; 888 889 $result = $matches[0]; 890 891 $query_ids = explode(',',str_replace(" ","",$matches[2])); 892 if (cacti_sizeof($query_ids)) { 893 $result = ''; 894 $querys = db_fetch_assoc('SELECT id, name 895 FROM graph_templates 896 WHERE id in (' . implode(',',$query_ids) . ')'); 897 898 $queryDescriptions = array(); 899 if (cacti_sizeof($querys)) { 900 foreach ($querys as $query) { 901 $queryDescriptions[$query['id']] = html_escape($query['name']); 902 } 903 } 904 905 foreach ($query_ids as $query_id) { 906 $result .= $matches[1].'<a href=\'' . html_escape($config['url_path'] . 'graph_templates.php?action=template_edit&id=' . $query_id) . '\'>' . (isset($queryDescriptions[$query_id]) ? $queryDescriptions[$query_id]:$query_id) . '</a>' . $matches[3]; 907 } 908 } 909 910 return $result; 911} 912 913function clog_regex_users($matches) { 914 global $config; 915 916 $result = $matches[0]; 917 918 $query_ids = explode(',',str_replace(" ","",$matches[2])); 919 if (cacti_sizeof($query_ids)) { 920 $result = ''; 921 922 $querys = db_fetch_assoc('SELECT DISTINCT 923 id, username 924 FROM user_auth 925 WHERE id in (' . implode(',',$query_ids) . ')'); 926 927 $queryDescriptions = array(); 928 if (cacti_sizeof($querys)) { 929 foreach ($querys as $query) { 930 $queryDescriptions[$query['id']] = html_escape($query['username']); 931 } 932 } 933 934 foreach ($query_ids as $query_id) { 935 $result .= $matches[1]; 936 if (isset($queryDescriptions[$query_id])) { 937 $result .= '<a href=\'' . html_escape($config['url_path'] . 'user_admin.php?action=user_edit&tab=general&id=' . $query_id) . '\'>' . $queryDescriptions[$query_id] . '</a>'; 938 } else { 939 $result .= $query_id; 940 } 941 $result .= $matches[3]; 942 } 943 } 944 return $result; 945} 946 947function clog_regex_rule($matches) { 948 global $config; 949 950 $result = $matches[0]; 951 952 $dev_ids = explode(',',str_replace(" ","",$matches[2])); 953 if (cacti_sizeof($dev_ids)) { 954 $result = ''; 955 $rules = db_fetch_assoc('SELECT id, name 956 FROM automation_graph_rules 957 WHERE id in (' . implode(',',$dev_ids) . ')'); 958 959 $ruleNames = array(); 960 if (cacti_sizeof($rules)) { 961 foreach ($rules as $rule) { 962 $ruleNames[$rule['id']] = html_escape($rule['name']); 963 } 964 } 965 966 foreach ($dev_ids as $rule_id) { 967 $result .= $matches[1].'<a href=\'' . html_escape($config['url_path'] . 'automation_graph_rules.php?action=edit&id=' . $rule_id) . '\'>' . (isset($ruleNames[$rule_id]) ? $ruleNames[$rule_id]:$rule_id) . '</a>' . $matches[3]; 968 } 969 } 970 971 return $result; 972} 973