#!/usr/bin/perl

use strict;
use Chart::Plot;

my $url    = 'http://www.spale.com/cgi-bin/graphping.pl';
my $images = 'http://www.spale.com/graphping';
my $imgdir = '/data/htdocs/web03/graphping';
my $maxelements = 60;

my $width = 800;
my $height = 300;

my %var;

foreach(split(/\&/,$ENV{QUERY_STRING})) {
	my ($name,$value)=split(/\=/);
	$name =~ s/\+/ /g;
	$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
	$value =~ s/\+/ /g;
	$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
	$var{$name}=$value;
}

printf("Content-type: text/html\n\n");

if ( !$var{host} || $var{host} !~ /^([a-z]|[A-Z]|\.|\-|[0-9])+$/ )
{
	print <<EOF;
<html>
 <title>GraphPING</title>
 <body>
  <form>
  <table border=0>
  <tr><td>hostname:</td><td><input name=host value="$var{host}"></td></tr>
  <tr><td>packet size:</td><td><select name=size>
   <option value=64>64 bytes</option>
   <option value=128>128 bytes</option>
   <option value=256>256 bytes</option>
   <option value=512>512 bytes</option>
   <option value=1024>1024 bytes</option>
  </select></td></tr>
  <tr><td>ping interval:</td><td><select name=sleep>
   <option value=1>1 second internal, 1 minute graph size</option>
   <option value=5>5 seconds interval, 5 minutes graph size</option>
   <option value=10>10 seconds interval, 10 minutes graph size</option>
   <option value=30>30 seconds interval, 30 minutes graph size</option>
   <option value=60>1 minute interval, 1 hour graph size</option>
  </select></td></tr>
  <tr><td colspan=2><input type=submit value=graph></td></tr>
  </table>
  </form>
 </body>
</html>
EOF

	exit;
}

if ( !$var{size} || $var{size} !~ /^\d+$/ ) { $var{size} = 64; }
if ( !$var{sleep} || $var{sleep} !~ /^\d+$/ ) { $var{sleep} = 1; }

my @xdata;
my @ydata;
my @mdata;
my @ddata;
my @adata;
my @ldata;
my @mpos;
my @dpos;
my @edata;
my @epos;

my $id = 0;
my $total = 0;
my $avg   = 0;
my $max   = 0;
my $min;

my $mpos = 0;
my $dpos = 0;

foreach(reverse(split(/\,/,$var{data})))
{
	if ( $_ > $max ) { $max = $_; $mpos = $id; }
	if ( !defined $min ) { $min = $_; }
	if ( $min > $_ ) { $min = $_; $dpos = $id; }
	push(@xdata,$id);
	push(@ydata,$_);
	$id++;
	$total += $_;
}

if ( !defined $min ) { $min = 0; }

if ( $id > $var{sleep} * $maxelements ) { pop(@ydata); pop(@xdata); $var{data} =~ s/^\d+\.\d+\,//; $id--; }

if ( $id == 0 ) { push(@xdata,0); push(@ydata,0); $id++; }

$avg = $total / $id;

push(@adata,$avg); push(@adata,$avg);
push(@mdata,$max*1.1); push(@mdata,0);
push(@ddata,$max*1.1); push(@ddata,0);
push(@edata,$max*1.1); push(@edata,0);

push(@mpos,$mpos); push(@mpos,$mpos); 
push(@dpos,$dpos); push(@dpos,$dpos); 
push(@epos,$maxelements); push(@epos,$maxelements);

push(@ldata,0); push(@ldata,$id/25);

my $img = Chart::Plot->new($width, $height);

myping($var{host});
$var{data} =~ s/^\,//;

$img->setData(\@epos,\@edata, 'nopoints') or die $img->error();
$img->setData(\@xdata,\@ydata, 'nopoints') or die $img->error();
if ( $mpos >= 0 ) { $img->setData(\@mpos,\@mdata, 'RED') or die $img->error(); }
if ( $dpos >= 0 ) { $img->setData(\@dpos,\@ddata, 'GREEN') or die $img->error(); }
$img->setData(\@ldata,\@adata, 'BLUE') or die $img->error();

my $maxf = sprintf("%0.2f",$max);
my $avgf = sprintf("%0.2f",$avg);
my $minf = sprintf("%0.2f",$min);

$img->setGraphOptions ( 'title' => "ping $var{host} - $var{size} bytes - $minf/$maxf/$avgf (min/max/avg) ms", horAxisLabel => 'samples', vertAxisLabel => 'miliseconds' );

my $time = time;

open(PNG,">$imgdir/$var{host}-$time.png");
print PNG $img->draw();
close(PNG);

printf("<html><title>GraphPING $var{host}</title>\n");
printf("<META HTTP-EQUIV=Refresh CONTENT=\"$var{sleep}; URL=$url?host=$var{host}&sleep=$var{sleep}&size=$var{size}&data=$var{data}\">\n");
printf("<img width=$width height=$height src=$images/$var{host}-$time.png><br>\n");
printf("<a href=$images/$var{host}-$time.png>Get image</a> or \n");
printf("<a href=$url>GraphPING another host</a></html>\n");

system("{ sleep 3; rm $imgdir/$var{host}-$time.png; } > /dev/null 2>&1 &");

sub myping
{
	my $host = shift;

	push(@xdata, $id);
	my $ping = 0;

	open(PING,"ping -c 1 $host |");
	while(<PING>)
	{
		if ( /^64 bytes from .* time=(\d+\.\d+) / )
		{
			$ping = $1;
		}
	}
	close(PING);
	push(@ydata,$ping);
	$var{data} .= ",$ping";
}
