#!/usr/bin/perl5.00503

# RRD shared liblary
use RRDs;

# parse the command line
%p = &ParseForm(&GetQueryString);

# usage:
#  rrdgraph.cgi?f=/path/file.rrd&t=title&L=[dwmy]
#    L= daily|weekly|monthly|yearly

# get filename from 'f=/path/file.rrd'
$fname = $p{'f'};

# get title from 't=title'
if ($p{'t'} ne '') {
	$title = $p{'t'};
} else {
	$title = $fname;
	$title =~ s,.*/,,;
	$title =~ s,\.rrd,,;
}

# get length from 'L=[dwmy]'
if ($p{'L'} =~ /^\d+[hH]$/) {
	$pTitle = $p{'L'};
	chop $pTitle;
	$span = 60 * 60 * $pTitle;
	$pTitle .= "Hours";
} elsif ($p{'L'} =~ /[wW]/) {
	$pTitle = 'Weekly';
	$span = 60 * 60 * 24 * 8;    # 8 days
} elsif ($p{'L'} =~ /[mM]/) {
	$pTitle = 'Monthly';
	$span = 60 * 60 * 24 * 35;   # 35 days
} elsif ($p{'L'} =~ /[yY]/) {
	$pTitle = 'Yearly';
	$span = 60 * 60 * 24 * 400;  # 400 days
} else {
	$pTitle = 'Daily';
	$span = 60 * 60 * 33;        # 33 hours
}

if ($span <= 6 * 60 * 60) {
	$x = "MINUTE:10:HOUR:1:HOUR:1:0:%H\:00";
} elsif ($span <= 12 * 60 * 60) {
	$x = "MINUTE:15:HOUR:1:HOUR:1:0:%H";
} elsif ($span <= 33 * 60 * 60) {
	$x = "HOUR:1:HOUR:1:HOUR:2:0:%H";
} elsif ($span <= 50 * 60 * 60) {
	$x = "HOUR:2:HOUR:2:HOUR:6:0:%H";
} elsif ($span <= 8 * 24 * 60 * 60) {
	$x = "DAY:1:DAY:1:DAY:1:86400:%a";
} elsif ($span <= 35 * 24 * 60 * 60) {
	$x = "WEEK:1:WEEK:1:WEEK:1:604800:Week %W";
} elsif ($span <= 405 * 24 * 60 * 60) {
	$x = "MONTH:1:MONTH:1:MONTH:1:2592000:%b";
}

# get start from 'S=12[hdwm]'
if (defined($p{'S'})) {
	($n, $m) = $p{'S'} =~ /(\d+)([hdwm])/;
	if ($m eq "h") {
		$f = 60 * 60;
	} elsif ($m eq "d") {
		$f = 24 * 60 * 60;
	} elsif ($m eq "w") {
		$f = 7 * 24 * 60 * 60;
	} elsif ($m eq "m") {
		$f = 30 * 24 * 60 * 60;
	}
	$stime = $n * $f;
	($s, $m, $h, $d, $mon, $y) = localtime(time - $stime);
	$mon++; $y += 1900;
	$pTitle = sprintf("%02d/%02d %02d:%02d:%02d", $mon, $d, $h, $m, $s);
}

@argv = (
	"-",					# stdout
	"-a", "PNG",				# image format
	"-t", "$pTitle $title",			# title
	"-l", 0,				# minimum
	#"-u", 10,				# maximum
	"-v", "RRT [ms]"
);
if (defined($x)) {
	push(@argv, ("-x", $x));		# x-grid format
}
if (defined($stime)) {
	push(@argv, "-s", -1 * ($stime+$span));	# start
	push(@argv, "-e", -1 * $stime);		# end
} else {
	push(@argv, "-s", -1 * $span);		# start
}

# print graph in PNG image format
print "Content-type: image/png\n\n";
RRDs::graph(
	@argv,
	"DEF:ave=$fname:ping:AVERAGE",		# get data
	"DEF:max=$fname:ping:MAX",		# get data
	"DEF:min=$fname:ping:MIN",		# get data
	"CDEF:vmax=max,min,-",			# vmax = max - min
	"AREA:min:Min",				# transparent min layer
	"STACK:vmax#33CC33:Max-Min",		# stack max-min data
	"GPRINT:max:MAX:%6.2lfms -",
	"GPRINT:min:MIN:%6.2lfms",
	"GPRINT:max:LAST:Cur\\: %6.2lfms -",
	"GPRINT:min:LAST:%6.2lfms\\c",
	"LINE1:ave#CC0000:Average",		# LINE format for average
	"GPRINT:ave:AVERAGE:%6.2lfms            ",
	"GPRINT:ave:LAST:Cur\\: %6.2lfms            \\c",
	);

exit 0;

# CGI command line parser
sub GetQueryString {
	local($s);

	if ($ENV{"REQUEST_METHOD"} eq "POST") {
		read(STDIN, $s, $ENV{"CONTENT_LENGTH"});
	} else {
		$s = $ENV{"QUERY_STRING"};
	}
	$s;
}

sub ParseForm {
	local($s) = @_;
	local(%param);
	local(@sp) = split(/&/, $s);

	foreach $t (@sp) {
		local ($key, $val) = split(/=/, $t);
		$val =~ tr/+/ /;
		$val =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg;
		$param{$key} = $val;
	}
	%param;
}
