summaryrefslogtreecommitdiff
path: root/torrus/perllib/Torrus/Renderer/HTML.pm
diff options
context:
space:
mode:
Diffstat (limited to 'torrus/perllib/Torrus/Renderer/HTML.pm')
-rw-r--r--torrus/perllib/Torrus/Renderer/HTML.pm597
1 files changed, 597 insertions, 0 deletions
diff --git a/torrus/perllib/Torrus/Renderer/HTML.pm b/torrus/perllib/Torrus/Renderer/HTML.pm
new file mode 100644
index 000000000..6eec86d21
--- /dev/null
+++ b/torrus/perllib/Torrus/Renderer/HTML.pm
@@ -0,0 +1,597 @@
+# Copyright (C) 2002 Stanislav Sinyagin
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+# $Id: HTML.pm,v 1.14 2011-03-01 00:09:39 ivan Exp $
+# Stanislav Sinyagin <ssinyagin@yahoo.com>
+
+package Torrus::Renderer::HTML;
+
+use strict;
+
+use Torrus::ConfigTree;
+use Torrus::Search;
+use Torrus::Log;
+
+use URI::Escape;
+use Template;
+use POSIX qw(abs log floor pow);
+use Date::Parse;
+use Date::Format;
+
+Torrus::SiteConfig::loadStyling();
+
+# All our methods are imported by Torrus::Renderer;
+
+sub render_html
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $token = shift;
+ my $view = shift;
+ my $outfile = shift;
+
+ my $tmplfile = $config_tree->getParam($view, 'html-template');
+
+ my $expires = $config_tree->getParam($view, 'expires');
+
+ # Create the Template Toolkit processor once, and reuse
+ # it in subsequent render() calls
+
+ if( not defined( $self->{'tt'} ) )
+ {
+ $self->{'tt'} =
+ new Template(INCLUDE_PATH => $Torrus::Global::templateDirs,
+ TRIM => 1);
+ }
+ my $ttvars =
+ {
+ 'treeName' => $config_tree->treeName(),
+ 'token' => $token,
+ 'view' => $view,
+ 'expires' => $expires,
+ 'path' => sub { return $config_tree->path($_[0]); },
+ 'pathToken' => sub { return $config_tree->token($_[0]); },
+ 'nodeExists' => sub { return $config_tree->nodeExists($_[0]); },
+ 'children' => sub { return $config_tree->getChildren($_[0]); },
+ 'isLeaf' => sub { return $config_tree->isLeaf($_[0]); },
+ 'isAlias' => sub { return $config_tree->isAlias($_[0]); },
+ 'sortTokens' => sub { return $self->sortTokens($config_tree,
+ $_[0]); },
+ 'nodeName' => sub { return $self->nodeName($config_tree, $_[0]); },
+ 'parent' => sub { return $config_tree->getParent($_[0]); },
+ 'nodeParam' => sub { return $config_tree->getNodeParam(@_); },
+ 'param' => sub { return $config_tree->getParam(@_); },
+ 'url' => sub { return $self->makeURL($config_tree, 0, @_); },
+ 'persistentUrl' => sub { return $self->makeURL($config_tree, 1, @_); },
+ 'clearVar' => sub { delete $self->{'options'}{'variables'}{$_[0]};
+ return undef;},
+ 'plainURL' => $Torrus::Renderer::plainURL,
+ 'splitUrls' => sub { return $self->makeSplitURLs($config_tree,
+ $_[0], $_[1]); },
+ 'topURL' => ($Torrus::Renderer::rendererURL ne '' ?
+ $Torrus::Renderer::rendererURL : '/'),
+ 'rrprint' => sub { return $self->rrPrint($config_tree,
+ $_[0], $_[1]); },
+ 'scale' => sub { return $self->scale($_[0], $_[1]); },
+ 'tsetMembers' => sub { $config_tree->tsetMembers($_[0]); },
+ 'tsetList' => sub { $config_tree->getTsets(); },
+ 'style' => sub { return $self->style($_[0]); },
+ 'companyName'=> $Torrus::Renderer::companyName,
+ 'companyLogo'=> $Torrus::Renderer::companyLogo,
+ 'companyURL' => $Torrus::Renderer::companyURL,
+ 'siteInfo' => $Torrus::Renderer::siteInfo,
+ 'treeInfo' => sub { return $Torrus::Global::treeConfig{
+ $config_tree->treeName()}{'info'}; },
+ 'version' => $Torrus::Global::version,
+ 'xmlnorm' => \&Torrus::Renderer::xmlnormalize,
+ 'userAuth' => $Torrus::CGI::authorizeUsers,
+ 'uid' => $self->{'options'}->{'uid'},
+ 'userAttr' => sub { return $self->userAttribute( $_[0] ) },
+ 'mayDisplayAdmInfo' => sub {
+ return $self->may_display_adminfo( $config_tree, $_[0] ) },
+ 'adminfo' => $self->{'adminfo'},
+ 'mayDisplayReports' => sub {
+ return $self->may_display_reports($config_tree) },
+ 'reportsUrl' => sub {
+ return $self->reportsUrl($config_tree); },
+ 'timestamp' => sub { return time2str($Torrus::Renderer::timeFormat,
+ time()); },
+ 'verifyDate' => sub { return verifyDate($_[0]); },
+ 'markup' => sub{ return $self->translateMarkup( @_ ); },
+ 'searchEnabled' => $Torrus::Renderer::searchEnabled,
+ 'searchResults' => sub { return $self->doSearch($config_tree, $_[0]); },
+
+ #Freeside
+ 'freesideHeader' => sub { return $self->freesideHeader(@_); },
+ 'freesideFooter' => sub { return $self->freesideFooter(); },
+ 'freesideComponent' => sub { return $self->freesideComponent(@_); },
+ 'uri_escape' => sub { return uri_escape(@_); },
+ 'matches' => sub { return $_[0] =~ $_[1]; },
+ 'iface_underscore' => sub { $_[0] =~ s/[\/\.]/_/g; return $_[0]; },
+ 'load_nms' => sub { return $self->load_nms; },
+ 'get_serviceids' => sub { my $nms = shift;
+ my $router = shift;
+ return $nms->get_router_serviceids($router);
+ },
+ 'popup_link' => sub {
+ my $type = shift;
+
+ if($type eq 'nms-add_iface.html') {
+ my $host = shift;
+ my $iface = shift;
+ my $nms = shift;
+ my $serviceids = shift;
+
+ if ( $serviceids && $serviceids->{$iface} ) {
+
+ my $svc_port = $nms->find_svc($serviceids->{$iface});
+
+ if ($svc_port) {
+ my $url = $Torrus::Freeside::FSURL.
+ "/view/svc_port.cgi?". $svc_port->svcnum;
+ return "<A HREF='$url'>View Service</A>";
+ } else {
+ my $component =
+ $nms->find_torrus_srvderive_component($serviceids->{$iface});
+
+ if ($component) {
+ return $serviceids->{$iface}. ' combined into '.
+ $component->torrus_srvderive->serviceid;
+ } else {
+ return 'Monitored as '. $serviceids->{$iface}.
+ '; not yet provisioned or combined';
+ }
+ }
+
+ } else {
+
+ return
+ $self->freesideComponent('/elements/popup_link.html',
+ 'action' => "/freeside/misc/".
+ $type."?host=$host;iface=$iface",
+ 'label' => 'Monitor for billing',
+ 'actionlabel' => 'Monitor interface',
+ );
+
+ }
+
+ } elsif ($type eq 'nms-add_router.html') {
+ return
+ $self->freesideComponent('/elements/popup_link.html',
+ 'action' => "/freeside/misc/$type",
+ 'label' => 'Add Router',
+ 'actionlabel' => 'Add Router',
+ );
+ }
+
+ '';
+ },
+
+ };
+
+
+ # Pass the options from Torrus::Renderer::render() to Template
+ while( my( $opt, $val ) = each( %{$self->{'options'}} ) )
+ {
+ $ttvars->{$opt} = $val;
+ }
+
+ my $result = $self->{'tt'}->process( $tmplfile, $ttvars, $outfile );
+
+ undef $ttvars;
+
+ if( not $result )
+ {
+ if( $config_tree->isTset( $token ) )
+ {
+ Error("Error while rendering tokenset $token: " .
+ $self->{'tt'}->error());
+ }
+ else
+ {
+ my $path = $config_tree->path($token);
+ Error("Error while rendering $path: " .
+ $self->{'tt'}->error());
+ }
+ return undef;
+ }
+
+ return ($expires+time(), 'text/html; charset=UTF-8');
+}
+
+
+sub nodeName
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $token = shift;
+
+ my $n = $config_tree->getNodeParam($token, 'node-display-name', 1);
+ if( defined( $n ) and length( $n ) > 0 )
+ {
+ return $n;
+ }
+
+ return $config_tree->nodeName($config_tree->path($token));
+}
+
+
+sub sortTokens
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $tokenlist = shift;
+
+ my @sorted = ();
+ if( ref($tokenlist) and scalar(@{$tokenlist}) > 0 )
+ {
+ @sorted = sort
+ {
+ my $p_a = $config_tree->getNodeParam($a, 'precedence', 1);
+ $p_a = 0 unless defined $p_a;
+ my $p_b = $config_tree->getNodeParam($b, 'precedence', 1);
+ $p_b = 0 unless defined $p_b;
+ if( $p_a == $p_b )
+ {
+ my $n_a = $config_tree->path($a);
+ my $n_b = $config_tree->path($b);
+ return $n_a cmp $n_b;
+ }
+ else
+ {
+ return $p_b <=> $p_a;
+ }
+ } @{$tokenlist};
+ }
+ else
+ {
+ push(@sorted, $tokenlist);
+ }
+ return @sorted;
+}
+
+
+# compose an URL for a node.
+# $persistent defines if the link should be persistent
+# Persistent link is done with nodeid if available, or with path
+
+sub makeURL
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $persistent = shift;
+ my $token = shift;
+ my $view = shift;
+ my @add_vars = @_;
+
+ my $ret = $Torrus::Renderer::rendererURL . '/' . $config_tree->treeName();
+
+ if( $persistent )
+ {
+ my $nodeid = $config_tree->getNodeParam($token, 'nodeid', 1);
+ if( defined( $nodeid ) )
+ {
+ $ret .= '?nodeid=' .
+ uri_escape($nodeid, $Torrus::Renderer::uriEscapeExceptions);
+ }
+ else
+ {
+ $ret .= '?path=' .
+ uri_escape($config_tree->path($token),
+ $Torrus::Renderer::uriEscapeExceptions);
+ }
+ }
+ else
+ {
+ $ret .= '?token=' . uri_escape($token);
+ }
+
+ if( $view )
+ {
+ $ret .= '&amp;view=' . uri_escape($view);
+ }
+
+ my %vars = ();
+ # This could be array or a reference to array
+ my $add_vars_size = scalar( @add_vars );
+ if( $add_vars_size == 1 and ref( $add_vars[0] ) )
+ {
+ %vars = @{$add_vars[0]};
+ }
+ elsif( $add_vars_size > 0 and ($add_vars_size % 2 == 0) )
+ {
+ %vars = @add_vars;
+ }
+
+ if( ref( $self->{'options'}->{'variables'} ) )
+ {
+ foreach my $name ( sort keys %{$self->{'options'}->{'variables'}} )
+ {
+ my $val = $self->{'options'}->{'variables'}->{$name};
+ if( not defined( $vars{$name} ) )
+ {
+ $vars{$name} = $val;
+ }
+ }
+ }
+
+ foreach my $name ( sort keys %vars )
+ {
+ if( $vars{$name} ne '' )
+ {
+ $ret .= '&amp;' . $name . '=' .
+ uri_escape( $vars{$name},
+ $Torrus::Renderer::uriEscapeExceptions );
+ }
+ }
+
+ return $ret;
+}
+
+sub makeSplitURLs
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $token = shift;
+ my $view = shift;
+
+ my $ret = '';
+ while( defined( $token ) )
+ {
+ my $path = $config_tree->path($token);
+
+ my $str = '<SPAN CLASS="PathElement">';
+ $str .=
+ sprintf('<A HREF="%s">%s%s</A>',
+ $self->makeURL($config_tree, 0, $token, $view),
+ $config_tree->nodeName($path),
+ ( $config_tree->isSubtree($token) and
+ $path ne '/') ? '/':'' );
+ $str .= "</SPAN>\n";
+
+ $ret = $str . $ret;
+
+ $token = $config_tree->getParent( $token );
+ }
+
+ return $ret;
+}
+
+
+sub rrPrint
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $token = shift;
+ my $view = shift;
+
+ my @ret = ();
+ my($fname, $mimetype) = $self->render( $config_tree, $token, $view );
+
+ if( $mimetype ne 'text/plain' )
+ {
+ Error("View $view does not produce text/plain for token $token");
+ }
+ else
+ {
+ if( not open(IN, $fname) )
+ {
+ Error("Cannot open $fname for reading: $!");
+ }
+ else
+ {
+ chomp(my $values = <IN>);
+ @ret = split(':', $values);
+ close IN;
+ }
+ }
+ return @ret;
+}
+
+# This subroutine is taken from Dave Plonka's Flowscan
+
+sub scale
+{
+ my $self = shift;
+ # This is based somewhat on Tobi Oetiker's code in rrd_graph.c:
+ my $fmt = shift;
+ my $value = shift;
+ my @symbols = ("a", # 10e-18 Ato
+ "f", # 10e-15 Femto
+ "p", # 10e-12 Pico
+ "n", # 10e-9 Nano
+ "u", # 10e-6 Micro
+ "m", # 10e-3 Milli
+ " ", # Base
+ "k", # 10e3 Kilo
+ "M", # 10e6 Mega
+ "G", # 10e9 Giga
+ "T", # 10e12 Terra
+ "P", # 10e15 Peta
+ "E"); # 10e18 Exa
+
+ my $symbcenter = 6;
+ my $digits = (0 == $value)? 0 : floor(log(abs($value))/log(1000));
+ return sprintf( $fmt . " %s", $value/pow(1000, $digits),
+ $symbols[ $symbcenter+$digits ] );
+}
+
+sub style
+{
+ my $self = shift;
+ my $object = shift;
+
+ my $media;
+ if( not defined( $media = $self->{'options'}->{'variables'}->{'MEDIA'} ) )
+ {
+ $media = 'default';
+ }
+ return $Torrus::Renderer::styling{$media}{$object};
+}
+
+
+
+sub userAttribute
+{
+ my $self = shift;
+ my $attr = shift;
+
+ if( $self->{'options'}->{'uid'} and $self->{'options'}->{'acl'} )
+ {
+ $self->{'options'}->{'acl'}->
+ userAttribute( $self->{'options'}->{'uid'}, $attr );
+ }
+ else
+ {
+ return '';
+ }
+}
+
+sub hasPrivilege
+{
+ my $self = shift;
+ my $object = shift;
+ my $privilege = shift;
+
+ if( $self->{'options'}->{'uid'} and $self->{'options'}->{'acl'} )
+ {
+ $self->{'options'}->{'acl'}->
+ hasPrivilege( $self->{'options'}->{'uid'}, $object, $privilege );
+ }
+ else
+ {
+ return undef;
+ }
+}
+
+
+sub translateMarkup
+{
+ my $self = shift;
+ my @strings = @_;
+
+ my $tt = new Template( TRIM => 1 );
+
+ my $ttvars =
+ {
+ 'em' => sub { return '<em>' . $_[0] . '</em>'; },
+ 'strong' => sub { return '<strong>' . $_[0] . '</strong>'; }
+ };
+
+ my $ret = '';
+
+ foreach my $str ( @strings )
+ {
+ my $output = '';
+ my $result = $tt->process( \$str, $ttvars, \$output );
+
+ if( not $result )
+ {
+ Error('Error translating markup: ' . $tt->error());
+ }
+ else
+ {
+ $ret .= $output;
+ }
+ }
+
+ undef $tt;
+
+ return $ret;
+}
+
+
+sub verifyDate
+{
+ my $input = shift;
+
+ my $time = str2time( $input );
+ # rrdtool does not understand dates prior to 1980 (315529200)
+ if( defined( $time ) and $time > 315529200 )
+ {
+ # Present the time in format understood by rrdtool
+ return time2str('%H:%M %Y%m%d', $time);
+ }
+ else
+ {
+ return '';
+ }
+}
+
+
+sub may_display_reports
+{
+ my $self = shift;
+ my $config_tree = shift;
+
+ if( $Torrus::Renderer::displayReports )
+ {
+ if( not $Torrus::CGI::authorizeUsers )
+ {
+ return 1;
+ }
+
+ my $tree = $config_tree->treeName();
+ if( $self->hasPrivilege( $tree, 'DisplayReports' ) and
+ -r $Torrus::Global::reportsDir . '/' . $tree .
+ '/html/index.html' )
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+sub reportsUrl
+{
+ my $self = shift;
+ my $config_tree = shift;
+
+ return $Torrus::Renderer::rendererURL . '/' .
+ $config_tree->treeName() . '?htmlreport=index.html';
+}
+
+
+sub doSearch
+{
+ my $self = shift;
+ my $config_tree = shift;
+ my $string = shift;
+
+
+ my $tree = $config_tree->treeName();
+
+ my $sr = new Torrus::Search;
+ $sr->openTree( $tree );
+ my $result = $sr->searchPrefix( $string, $tree );
+ $sr->closeTree( $tree );
+
+ my $ret = [];
+ push( @{$ret}, sort {$a->[0] cmp $b->[0]} @{$result} );
+
+ return $ret;
+}
+
+
+1;
+
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# perl-indent-level: 4
+# End: