1<?php 2 3/* ************************************************************************ 4 amavis-stats.php - build rrd graphs from amavis-stats collected data. 5 6 Copyright (C) 2003,2004 Mark Lawrence (nomad@null.net) 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License with 19 the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL; 20 if not, write to the Free Software Foundation, Inc., 59 Temple Place, 21 Suite 330, Boston, MA 02111-1307 USA 22 23 On Debian systems, the complete text of the GNU General Public 24 License, version 2, can be found in /usr/share/common-licenses/GPL-2. 25 26************************************************************************ */ 27 28/* 29* 30* This script depends on rrdtool|php4-rrdtool There are three ways to use it: 31* 32* 1. Directly from the command line as "php4 amavis-stats.php". 33* This allows you to generate graphs without having to have a full-blown 34* apache or other webserver environment running on your virus/smtp host. 35* 36* If you would like regular graphs generated you could put something 37* like this in /etc/cron.d/virus-graphs: 38* 39* # 40* # cron job to generate and move graphs every hour 41* # 42* 0 * * * * amavis cd /var/tmp && php4 /usr/share/.../amavis-stats.php \ 43* && rsync -avz /var/tmp/*.png remotehost: 44* 45* 2. Copy the script to somewhere in your web root (eg /var/www) and 46* call it directly as a url (eg http://server/amavis-stats.php). 47* 48* 2. Include it from another php script. In this case no html will be 49* generated directly by amavis-stats.php. However you then have the 50* ability to call the as[V|P]Graph() functions (after a call to 51* asLoadStats()) directly from within your script with your desired 52* parameters. Then build your own html to display the graphs. 53* 54* Hopefully the function names are unique enough to not clash 55* with your own namespace. 56* 57*/ 58 59global $asVersion; 60$asVersion = "0.1.12"; 61 62// The rrdstep value MUST match that which is used by the perl script. 63// don't change one without the other. 64$rrdstep = 300; 65 66// //////////////////////////////////////////////////////////////////////// 67// 68// //////////////////////////////////////////////////////////////////////// 69 70/* 71* php version of the RRDTool::rrd_graph extention using shell executable. 72* This needs to come first in the file otherwise the php pre-compiler 73* thinks we don't exist... 74*/ 75 76$rrd = "shared-library"; 77 78if (!function_exists('rrd_graph') && !@dl('rrdtool.so')) { 79 $rrd = "command-line"; 80 81 function rrd_graph ($img, $opts, $count) { 82 global $rrd_error_val; 83 84 unset($output); 85 86 $cmd = "rrdtool graph $img '". implode("' \\\n'",$opts) . "'" . 87 " 2>&1"; 88 asDbg($cmd, 1); 89 $out = exec($cmd, $output, $rrd_error_val); 90 91 if ($rrd_error_val) { 92 if (!is_numeric($rrd_error_val)) { 93 $rrd_error_val = $output[0]; 94 } 95 return false; 96 } 97 98 asDbg($output); 99 100 if (preg_match("/(\d+)x(\d+)/", $output[0], $matches)) { 101 $retval["xsize"] = $matches[1]; 102 $retval["ysize"] = $matches[2]; 103 } else { 104 $rrd_error_val = $output[0]; 105 return false; 106 } 107 108 array_shift($output); 109 110 foreach ($output as $index => $value) { 111 $retval[calcpr][$index] = $value; 112 } 113 return $retval; 114 } 115 116 function rrd_error() { 117 global $rrd_error_val; 118 return $rrd_error_val; 119 } 120} 121 122 123/* 124* Timing function to work out how long things take 125*/ 126function elapsed($start) 127{ 128 $end = microtime(); 129 list($start2, $start1) = explode(" ", $start); 130 list($end2, $end1) = explode(" ", $end); 131 $diff1 = $end1 - $start1; 132 $diff2 = $end2 - $start2; 133 if( $diff2 < 0 ){ 134 $diff1 -= 1; 135 $diff2 += 1.0; 136 } 137 return $diff2 + $diff1; 138} 139 140 141 142if (isset($_SERVER["REQUEST_URI"])) { // web environment 143 $fullpage = true; 144 $outdir = "img"; 145 146} else { // Stand-alone command line usage 147 $cmd = true; 148 $outdir = $_SERVER["PWD"]; 149 150} 151 152if (isset($GLOBALS["rate"])) { 153 $rate = $GLOBALS["rate"]; 154} else { 155 $rate = 60; 156} 157 158 159if (isset($fullpage) || isset($cmd)) { 160 asHtmlStart(); 161 162 if (asLoadStats()) { 163 164 $minsec = 60; 165 $hoursec = 60 * $minsec; 166 $daysec = 24 * $hoursec; 167 $weeksec = 7 * $daysec; 168 169 $now = time(); 170 171 print "<h2>Daily Graphs</h2>\n"; 172 print asPGraph("$outdir/passed-day.png", $now, $daysec, "by day"); 173 print asVGraph("$outdir/virus-day.png", $now, $daysec, "by day"); 174 175 print "<h2>Weekly Graphs</h2>\n"; 176 print asPGraph("$outdir/passed-week.png", $now, 7*$daysec, "by week"); 177 print asVGraph("$outdir/virus-week.png", $now, 7*$daysec, "by week"); 178 179 print "<h2>Monthly Graphs</h2>\n"; 180 print asPGraph("$outdir/passed-month.png", $now, 31*$daysec, "by month"); 181 print asVGraph("$outdir/virus-month.png", $now, 31*$daysec, "by month"); 182 183 print "<h2>Yearly Graphs</h2>\n"; 184 print asPGraph("$outdir/passed-year.png", $now, 365*$daysec, "by year"); 185 print asVGraph("$outdir/virus-year.png", $now, 365*$daysec, "by year"); 186 187 } else { 188 asMsg("No statistics available."); 189 } 190 191 asHtmlEnd(); 192} 193 194function asDbg($txt = "", $pre = 0) { 195 if ($GLOBALS["debug"]) { 196 if ($pre) { 197 print "<pre>\n"; 198 } 199 print "amavis-stats::debug: $txt\n"; 200 if (is_array($txt)) { 201 print "<pre>\n"; 202 print_r($txt); 203 print "</pre>\n"; 204 } 205 if ($pre) { 206 print "</pre>\n"; 207 } 208 print "<br>\n"; 209 210 } 211} 212 213function asMsg($txt = "") { 214 print "amavis-stats: $txt<br>\n"; 215} 216 217function asErr($txt = "") { 218 print "amavis-stats::error: $txt<br>\n"; 219} 220 221 222function asHtmlStart() { 223 print ' 224<!DOCTYPE HTML PUBLIC \-//W3C//DTD HTML 3.2 Final//EN\> 225<html> 226<head> 227<style> 228 body { 229 font-size: x-small; 230 font-family: sans-serif; 231 margin: 1em; 232 } 233 img { 234 margin-bottom: 1em; 235 text-align: center; 236 clear: both; 237 } 238</style> 239</head> 240<body> 241 242<h1>Amavis Detection Statistics</h1>'; 243 244 245} 246 247 248function asHtmlEnd() { 249 global $asVersion, $rrd; 250 print '<br> 251<span style=\"font-size:x-small\">[Generated by <a 252href="http://rekudos.net/amavis-stats/">amavis-stats</a> 253 version ' . $asVersion . ' using ' . $rrd . ' rrdtool ['; 254 255 if (!$GLOBALS["debug"]) { 256 print '<a href="' . $GLOBALS["REQUEST_URI"] . 257 '?debug=1">debug</a>'; 258 } else { 259 print '<a href="' . 260 str_replace("?debug=1", "", $GLOBALS["REQUEST_URI"]) . 261 '">nodebug</a>'; 262 } 263 print "].\n"; 264 265 if (!$GLOBALS["rate"] || ($GLOBALS["rate"] == 60)) { 266 print 'Rate per <a href="' . $GLOBALS["REQUEST_URI"] . 267 '?rate=3600">hour</a>'; 268 } else { 269 print 'Rate per <a href="' . 270 str_replace("?rate=3600", "", $GLOBALS["REQUEST_URI"]) . 271 '">minute</a>'; 272 } 273 274 275 print ']</span> 276</body> 277</html> 278 '; 279} 280 281 282 283/* 284* 285*/ 286function asLoadStats () { 287 global $as_libdir, $virus, $pid, $psid, $iid, $bid,$nid,$nsid, $lastupdate, $maxi; 288 289 $as_libdir = "/usr/local/www/amavis-stats"; 290 $as_statefile = $as_libdir . "/amavis-stats.state"; 291 $as_namefile = $as_libdir . "/amavis-stats.names"; 292 $as_seenfile = $as_libdir . "/amavis-stats.seen"; 293 294 $readfile = @file($as_namefile); 295 if (!is_array($readfile)) { 296 asErr("Couldn't open id => name mappings file."); 297 } 298 asDbg("$as_namefile"); 299 asDbg($readfile); 300 301 $virus = array(); 302 $pid = -1; 303 $iid = -1; 304 $bid = -1; 305 $sid = -1; 306 307 for ($k = 0; $k <= (count($readfile) - 1); $k++) { 308 $fields = preg_split("/\s+/",$readfile[$k], 2, PREG_SPLIT_NO_EMPTY); 309 310 $fields[0] = trim($fields[0]); 311 $fields[1] = trim($fields[1]); 312 313 $virus[$fields[0]]["id"] = $fields[0]; 314 $virus[$fields[0]]["name"] = $fields[1]; 315 if ($fields[1] == "Passed") { 316 $pid = $fields[0]; 317 } 318 elseif ($fields[1] == "Passed(SPAM)") { 319 $psid = $fields[0]; 320 } 321 elseif ($fields[1] == "Infected") { 322 $iid = $fields[0]; 323 } 324 elseif ($fields[1] == "Banned") { 325 $bid = $fields[0]; 326 } 327 elseif ($fields[1] == "Not-Delivered") { 328 $nid = $fields[0]; 329 } 330 elseif ($fields[1] == "Not-Delivered(SPAM)") { 331 $nsid = $fields[0]; 332 } 333 } 334 335 $readfile = @file($as_seenfile); 336 if (!is_array($readfile)) { 337 asErr("Couldn't open first/last seen file."); 338 } 339 asDbg("$as_seenfile"); 340 asDbg($readfile); 341 342 for ($k = 0; $k <= (count($readfile) - 1); $k++) { 343 $fields = preg_split("/\s+/",$readfile[$k], -1, PREG_SPLIT_NO_EMPTY); 344 $virus[$fields[0]]["firstseen"] = $fields[1]; 345 $virus[$fields[0]]["lastseen"] = $fields[2]; 346 } 347 348 $readfile = @file($as_statefile); 349 if (!is_array($readfile)) { 350 asErr("Couldn't open state file."); 351 } 352 asDbg("$as_statefile"); 353 asDbg($readfile); 354 355 for ($k = 0; $k <= (count($readfile) - 1); $k++) { 356 $fields = preg_split("/\s+/",$readfile[$k], -1, PREG_SPLIT_NO_EMPTY); 357 if ($fields[0] == "lastupdate:" && is_numeric($fields[1])) { 358 $lastupdate = $fields[1]; 359 } elseif ($fields[0] == "LC_TIME:") { 360 setlocale(LC_TIME, $fields[1]); 361 } 362 } 363 364 if (!isset($lastupdate)) { 365 asErr("lastupdate not defined."); 366 return false; 367 } 368 elseif ($lastupdate == 0) { 369 asErr("last update was at 0 seconds."); 370 return false; 371 } 372 373 as_col(); 374 return true; 375} 376 377 378 379function as_col() { 380 global $as_colors; 381 $as_colors = array( 382 "#00BFFF", /* DeepSkyBlue */ 383 "#FFD700", /* gold */ 384 "#FA8072", /* salmon */ 385 "#006400", /* DarkGreen */ 386 "#FF1493", /* DeepPink */ 387 "#00CED1", /* DarkTurquoise */ 388 "#FF00FF", /* magenta */ 389 "#00FF7F", /* SpringGreen */ 390 "#FF0000", /* red */ 391 "#228B22", /* ForestGreen */ 392 "#F0E68C", /* khaki */ 393 "#FFFF00", /* yellow */ 394 "#0000FF", /* blue */ 395 "#CD5C5C", /* IndianRed */ 396 "#6A5ACD", /* SlateBlue */ 397 "#F4A460", /* SandyBrown */ 398 "#FFA500", /* orange */ 399 "#FF8C00", /* DarkOrange */ 400 "#000080", /* NavyBlue */ 401 "#FF69B4", /* HotPink */ 402 "#2E8B57", /* SeaGreen */ 403 "#A020F0", /* purple */ 404 "#FFB6C1", /* LightPink */ 405 "#0000CD", /* MediumBlue */ 406 "#B22222", /* firebrick */ 407 "#7CFC00", /* LawnGreen */ 408 "#D02090", /* VioletRed */ 409 "#6495ED" /* CornflowerBlue */ 410 ); 411} 412 413 414 415 416/* 417* 418*/ 419function addopts(&$opts, $type, $id, $vcount, $virus, $length) { 420 global $as_libdir, $as_colors, $rate, $maxi; 421 422 $name = sprintf("%-".$maxi."s", $virus[$id]["name"]); 423 $count = $vcount[$id]; 424 $count = sprintf("%8d", $count); 425// $col = $as_colors[md5($name) % (count($as_colors) - 1)]; 426 $col = substr(md5($name),7,6); 427// print "COL: $col<br>\n"; 428 429 $opts[] = "DEF:v$id=$as_libdir/$id.rrd:hits:AVERAGE"; 430 $opts[] = "CDEF:gv$id=v$id,$rate,*"; 431// $opts[] = "CDEF:gv$id=v$id,UN,0,v$id,IF,$rate,*"; 432 $opts[] = "$type:gv$id#$col:$name $count"; 433 434 return $opts; 435} 436 437 438/* 439* asVGraph (file, - name of the png to generate 440* endtime, - end time in seconds (defaults to 'now') 441* length, - length of time in seconds 442* timetext,- human-readable description of length (eg: 'by day') 443* hostname,- hostname of amavis server (defaults to localhost) 444* ) 445* 446* Build a graph of Virus infected emails. 447* Returns either a html-valid <img> tag which can be printed, or the 448* boolean "false" if something went wrong. 449*/ 450function asVGraph($img, $end = 0, $length, $timetext = "", $host = "") { 451 global $as_libdir, $virus, $pid, $psid, $iid, $bid, $nid, $nsid, $lastupdate, $maxi, $rate, $asVersion, $rrdstep; 452 453 /* 454 * Options... when do we start, end, graph title text etc. 455 */ 456 if ($end == 0) { 457 $end = time(); 458 } 459 460 // make the end time an even multiple of the rrdstep 461 $end = floor($end/$rrdstep) * $rrdstep; 462 463 464 $start = $end - $length; 465 466 $startdate = strftime("%c", $start); 467 $enddate = strftime("%c", $end); 468 $nowdate = strftime("%c", time()); 469 470 471 if ($timetext == "") { 472 $timetext = "$length seconds"; 473 } 474 475 if ($host == "") { 476 $host = eregi_replace("\n", "", `hostname`); 477 } 478 479 480 /* 481 * It is a two-step process to build the final graph. The average over 482 * a specific time period seems to be impossible to get without actually 483 * building a graph. Ie, rrd fetch will not calculate the values we 484 * need - we would have to sum and average manually. 485 * 486 * However the PRINT function of a graph will return what we want 487 * in an array. So first of all build a graph that PRINTs the average 488 * of every virus over the selected time period. 489 */ 490 491 $opts = array(); 492 $opts[] = "--start=$start"; 493 $opts[] = "--end=$end"; 494 495 foreach ($virus as $id => $rest) { 496 $opts[] = "DEF:v$id=$as_libdir/$id.rrd:hits:AVERAGE"; 497 $opts[] = "CDEF:gv$id=v$id,UN,0,v$id,IF"; 498 $opts[] = "CDEF:gvt$id=gv$id,$length,*"; 499 $opts[] = "PRINT:gvt$id:AVERAGE:%.0lf"; 500 } 501 502 $ret = rrd_graph($img, $opts, count($opts)); 503 504 /* 505 * debugging - graph definitions 506 */ 507 asDbg($ret); 508 509 $infected = 0; 510 if (is_array($ret)) { 511 /* 512 * All results from PRINT commands are in the array $ret[calcpr][..] 513 */ 514 $maxi = 0; 515 $i = 0; 516 foreach ($virus as $id => $rest) { 517 /* 518 * We don't have enough resolution in the rrds 519 * to calculate the correct counts at low averages, 520 * so we just don't display them 521 */ 522 if ($ret[calcpr][$i] != 0) { 523 $vcount[$id] = $ret[calcpr][$i]; 524 $maxi = max($maxi, strlen($virus[$id]["name"])); 525 } 526 $i++; 527 /* asDbg("Id: $id = $vcount[$id]"); */ 528 } 529 $maxi++; 530 531 /* 532 * We usually always have the infected.rrd and passed.rrd 'viruses'. 533 * Take them out of the array (saving the totals) because we don't 534 * really want to graph them. 535 */ 536 if (count($vcount) >= 1) { 537 arsort($vcount); 538 if ($vcount[$iid]) { 539 $infected = $vcount[$iid]; 540 unset ($vcount[$iid]); 541 } 542 if ($vcount[$pid]) { 543 unset ($vcount[$pid]); 544 } 545 if ($vcount[$psid]) { 546 unset ($vcount[$psid]); 547 } 548 if ($vcount[$bid]) { 549 unset ($vcount[$bid]); 550 } 551 if ($vcount[$nid]) { 552 unset ($vcount[$nid]); 553 } 554 if ($vcount[$nsid]) { 555 unset ($vcount[$nsid]); 556 } 557 558 } 559 else { 560 asDbg("vcount is an empty array"); 561 $vcount = array(); 562 } 563 564 } 565 else 566 { 567 $msg = rrd_error(); 568 asErr("rrd_graph(): $msg"); 569 return false; 570 } 571 572 if ($rate == 3600) { 573 $ratemsg = "hour"; 574 } else { 575 $rate = 60; 576 $ratemsg = "min"; 577 } 578 579 580 /* 581 * Now that we have the counts of each virus over the time period 582 * we can build the actual graph 583 */ 584 $opts = array(); 585 $opts[] = "--start=$start"; 586 $opts[] = "--end=$end"; 587 $opts[] = "--title=Virus Detection on $host ($timetext)"; 588 $opts[] = "--width=520"; 589 $opts[] = "--vertical-label=viruses/$ratemsg"; 590// $opts[] = "COMMENT:$infected viruses detected from $startdate\g"; 591// $opts[] = "COMMENT: to $enddate"; 592// $opts[] = "COMMENT:\\n"; 593// $opts[] = "COMMENT:\\n"; 594 595 596 /* 597 * The tricky part, building rrd rows but ordering the elements by 598 * columns... 599 */ 600 601 if ($maxi > 20) { 602 $width = 2; 603 } else { 604 $width = 3; 605 } 606 $total = count($vcount); 607 $depth = ceil($total / $width); 608 609 $mod = $total % $width; 610 611 if ($infected > 0) { 612 613 $keyarray = array_keys ($vcount); 614 615 for ($d = 1; $d <= $depth; $d++) { 616 for ($col = 1; $col <= $width; $col++) { 617 618 if ($col == 1) { 619 $index = $d; 620 } 621 elseif ($d != $depth || $mod == 0 || $mod >= $col) { 622 if (($mod == 0) || ($col - $mod) < 2) { 623 $index = ($col - 1) * $depth + $d; 624 } else { 625 $index = $mod * $depth + 626 ($col - $mod - 1)*($depth - 1) + $d ; 627 } 628 } 629 else { 630 continue; 631 } 632 633 $id = $keyarray[$index - 1]; 634 635 if ($d == 1 && $col == 1) { 636 addopts($opts, "AREA", $id, $vcount, $virus, $length); 637 } 638 else { 639 addopts($opts, "STACK", $id, $vcount, $virus, $length); 640 } 641 } 642 $opts[] = "COMMENT:\\n"; 643 } 644 } 645 646 $opts[] = "COMMENT:\\n"; 647 $opts[] = "COMMENT:amavis-stats v$asVersion "; 648 $opts[] = "COMMENT:$enddate \\r"; 649 650 asDbg($opts); 651 $ret = rrd_graph($img, $opts, count($opts)); 652 653 if (!is_array($ret)) { 654 $err = rrd_error(); 655 asErr("rrd_graph(): $err"); 656 return false; 657 } 658 659 return "<img src=\"$img\" alt=\"[image: $timetext]\">\n\n"; 660} 661 662 663 664 665 666/* 667* asPGraph ( file, - name of the png to generate 668* endtime, - end time in seconds (defaults to 'now') 669* length, - length of time in seconds 670* timetext,- human-readable description of length (eg: 'by day') 671* hostname,- hostname of amavis server (defaults to localhost) 672* ) 673* 674* Build a graph of clean or "Passed" emails. 675* Returns either a html-valid <img> tag which can be printed, or the 676* boolean "false" if something went wrong. 677*/ 678function asPGraph($img, $end = 0, $length, $timetext = "", $host = "") { 679 global $as_libdir, $virus, $pid, $psid, $iid, $bid, $nid, $nsid, $lastupdate, $maxi, $rate, $asVersion, $rrdstep; 680 681 /* 682 * Options... when do we start, end, graph title text etc. 683 */ 684 if ($end == 0) { 685 $end = time(); 686 } 687 688 // make the end time an even multiple of the rrdstep 689 $end = floor($end/$rrdstep) * $rrdstep; 690 $start = $end - $length; 691 692 $startdate = strftime("%c", $start); 693 $enddate = strftime("%c", $end); 694 $nowdate = strftime("%c", time()); 695 696 if ($timetext == "") { 697 $timetext = "$length seconds"; 698 } 699 700 if ($host == "") { 701 $host = eregi_replace("\n", "", `hostname`); 702 } 703 704 if ($rate == 3600) { 705 $ratemsg = "hour"; 706 } else { 707 $rate = 60; 708 $ratemsg = "min"; 709 } 710 711 $opts = array(); 712 $opts[] = "--start=$start"; 713 $opts[] = "--end=$end"; 714 $opts[] = "--title=Messages Scanned on $host ($timetext)"; 715 $opts[] = "--width=520"; 716 $opts[] = "--vertical-label=msgs/$ratemsg"; 717 718 $arr = array($pid, $psid, $bid, $iid, $nid, $nsid); 719 $arrcol = array("6A5ACD", "fA5ACD", "cc9900", "ffdd00", "9900aa", "ff3a3d"); 720 721 $type = "AREA"; 722 foreach ($arr as $idx => $id) { 723 if ($id > 0) { 724 $name = sprintf("%-21s", $virus[$id]["name"]); 725 $col = $arrcol[$idx]; 726// print "$col<br>\n"; 727 $opts[] = "DEF:v$id=$as_libdir/$id.rrd:hits:AVERAGE"; 728 $opts[] = "CDEF:gv$id=v$id,UN,0,v$id,IF"; 729 $opts[] = "CDEF:gvt$id=gv$id,$length,*"; 730 $opts[] = "CDEF:gtvt$id=gv$id,$rate,*"; 731 $opts[] = "$type:gtvt$id#$col:$name "; 732 $opts[] = "GPRINT:gvt$id:AVERAGE:%.0lf"; 733 $opts[] = "COMMENT:\\n"; 734 $type = "STACK"; 735 } 736 } 737/* 738 739 if ($iid >= 0) { 740 $opts[] = "DEF:v$iid=$as_libdir/$iid.rrd:hits:AVERAGE"; 741 $opts[] = "CDEF:gv$iid=v$iid,UN,0,v$iid,IF"; 742 $opts[] = "CDEF:gvt$iid=gv$iid,$length,*"; 743 $opts[] = "CDEF:gtvt$iid=gv$iid,$rate,*"; 744 $opts[] = "$type:gtvt$iid#FFD700:Infected\: "; 745 $opts[] = "GPRINT:gvt$iid:AVERAGE:%.0lf"; 746 $opts[] = "COMMENT:\\n"; 747 $type = "STACK"; 748 } 749 750 if ($bid >= 0) { 751 $opts[] = "DEF:v$bid=$as_libdir/$bid.rrd:hits:AVERAGE"; 752 $opts[] = "CDEF:gv$bid=v$bid,UN,0,v$bid,IF"; 753 $opts[] = "CDEF:gvt$bid=gv$bid,$length,*"; 754 $opts[] = "CDEF:gtvt$bid=gv$bid,$rate,*"; 755 $opts[] = "$type:gtvt$bid#FFA500:Banned\: "; 756 $opts[] = "GPRINT:gvt$bid:AVERAGE:%.0lf"; 757 $opts[] = "COMMENT:\\n"; 758 $type = "STACK"; 759 } 760 761 if ($sid >= 0) { 762 $opts[] = "DEF:v$sid=$as_libdir/$sid.rrd:hits:AVERAGE"; 763 $opts[] = "CDEF:gv$sid=v$sid,UN,0,v$sid,IF"; 764 $opts[] = "CDEF:gvt$sid=gv$sid,$length,*"; 765 $opts[] = "CDEF:gtvt$sid=gv$sid,$rate,*"; 766 $opts[] = "$type:gtvt$sid#FF1493:Spam\: "; 767 $opts[] = "GPRINT:gvt$sid:AVERAGE:%.0lf"; 768 $opts[] = "COMMENT:\\n"; 769 } 770*/ 771 $opts[] = "COMMENT:amavis-stats v$asVersion "; 772 $opts[] = "COMMENT:$enddate \\r"; 773 774 /* 775 * debugging - graph definitions 776 */ 777 asDbg($opts); 778 779 $start = microtime(); 780 $ret = rrd_graph($img, $opts, count($opts)); 781 $t = elapsed($start); 782 if (!is_array($ret)) { 783 $err = rrd_error(); 784 asErr("rrd_graph(): $err"); 785 return false; 786 } 787 788 return "<img src=\"$img\" alt=\"[image: $timetext]\">\n\n"; 789} 790 791 792?> 793