RRD::CGI::Image - accept CGI-style rrdgraph args to build and print image


RRD-CGI-Image documentation Contained in the RRD-CGI-Image distribution.

Index


Code Index:

NAME

Top

RRD::CGI::Image - accept CGI-style rrdgraph args to build and print image

NOTICE

Top

This is development code - the API may change!

SYNOPSIS

Top

    use RRD::CGI::Image;
	use CGI qw[Vars header];

    my $image = RRD::CGI::Image->new(
		rrd_base  => '/var/rrd',
		error_img => '/var/www/.../path/to/graphing_error.png',
	);

	print header( 'image/png' );
	$image->print_graph( Vars() );

METHODS

Top

new() - create new object to handle your bidding

Behaves like any other new(), really.

output_file() - where will the new graph be created?

Defaults to STDOUT (-).

rrd_base() - pathname to your RRD files.

Users will be able to specify partial paths to the RRDs beneath this directory in their DEF declarations but they will be sandboxed into this directory. Don't be too permissive - it's a security risk.

Must end with "/".

error_img() - pathname (not URL) to an image that says "an error happened".

Check your webserver's logs to see what went wrong.

tz() - get/set the timezone for the graph.

Pertinent if you have RRDs in different timezones.

normalize_params() - clean up and reassemble the input params

Called internally.

logging() - if true, will print the normalized (processed) params to log

AUTHOR

Top

Joshua Keroes, <joshua at cpan.org>

BUGS

Top

Please report any bugs or feature requests to bug-rrd-cgi-image at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=RRD-CGI-Image. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

Top

You can find documentation for this module with the perldoc command.

    perldoc RRD::CGI::Image

You can also look for information at:

* RT: CPAN's request tracker

http://rt.cpan.org/NoAuth/Bugs.html?Dist=RRD-CGI-Image

* AnnoCPAN: Annotated CPAN documentation

http://annocpan.org/dist/RRD-CGI-Image

* CPAN Ratings

http://cpanratings.perl.org/d/RRD-CGI-Image

* Search CPAN

http://search.cpan.org/dist/RRD-CGI-Image

SEE ALSO

Top

RRDs

COPYRIGHT & LICENSE

Top


RRD-CGI-Image documentation Contained in the RRD-CGI-Image distribution.

package RRD::CGI::Image;

use warnings;
use strict;
use Spiffy '-base';
use RRDs;
use Carp;
use HTML::Entities;
use URI::Escape;
use POSIX 'tzset';

our $VERSION = '0.01';

field 'output_file'		=> '-';  # STDOUT
field 'params'			=> ();
field 'rrd_base'  		=> '/var/rrd/';
field 'error_img' 		=> '/var/www/graphing_error.png';
field 'logging'			=> 0;

sub print_graph {
	my $self = shift;
	carp "print_graph( %cgi_params_with_values ) called without args" unless @_;
	croak "rrd_base: " . $self->rrd_base . " does not exist." unless -d $self->rrd_base;

	$self->params( \@_ );
	$self->normalize_params;

	WWW $self if $self->logging;
		
	RRDs::graph( $self->output_file, @{ $self->params } );
	$self->print_error_img if RRDs::error();
}

sub normalize_params {
	my $self = shift;

	# User is not allowed to submit an output filename via query string. 
	# It must be set using output_file() instead.
	#
	$self->print_error_img( "Bad first argument" ) unless $self->params->[0] =~ /^\s*--?\w/;

	my @rrd_args;
 	my @params = @{ $self->params };

	while ( my ($k, $v) = splice @params, 0, 2 ) {		
		# translate &nbsp; &#230, etc.
		$k = decode_entities( $k );
		$v = decode_entities( $v ) if defined $v;

		# translate %20, %3a, etc.
		$k = uri_unescape( $k );
		$v = uri_unescape( $v ) if defined $v;

		# User not allowed to poke around above the rrd_base() dir.
		$self->print_error_img( "Bad DEF path" ) if $k =~ /^DEF .* \.\./x;
		$self->print_error_img( "Bad DEF path" ) if defined $v && $v =~ /^DEF .* \.\./x;

		# Insert rrd_base() into the DEF statement
		if ( $k =~ /^DEF/ ) {
			$v = $self->rrd_base . $v;
		}

		# Set and strip any timezone params - it's not a valid RRDs::graph() argument
		if ( $k =~ /tz/i ) {
			$self->tz( $v );
			next;
		}
		
		# Some of the keypair args will be split by CGI's param handler. We need to join the
		# args like "DEF:ds0=..." back together.
		#
		# Args like --height=120 should turn into a Perl key-value tuple instead. 
		if ( $k =~ /^-/ ) {
			push @rrd_args, defined $v && $v ne '' ? ( $k => $v ) : $k;
		}
		else {
			push @rrd_args, defined $v && $v ne '' ? "$k=$v" : $k;
		}
	}

	return $self->params( \@rrd_args );
}

sub tz {
	my $self = shift;
	$self->{tz} = shift if $_[0];

	if ( $self->{tz} ) {
		$ENV{TZ} = $self->{tz};
		tzset();
	}

	return $self->{tz};
}

sub print_error_img {
	my $self = shift;
	
	my $errmsg = shift || RRDs::error() || "Unknown error";
	warn $errmsg;
	
	open F, $self->error_img or warn "error_img: " . $self->error_img . " not found";
	print <F>;
	close F;
}

1; # End of RRD::CGI::Image

__END__