1 # Copyright (C) 2002 Stanislav Sinyagin
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17 # $Id: HTML.pm,v 1.15 2011-10-26 02:44:16 ivan Exp $
18 # Stanislav Sinyagin <ssinyagin@yahoo.com>
20 package Torrus::Renderer::HTML;
24 use Torrus::ConfigTree;
30 use POSIX qw(abs log floor pow);
34 Torrus::SiteConfig::loadStyling();
36 # All our methods are imported by Torrus::Renderer;
41 my $config_tree = shift;
46 my $tmplfile = $config_tree->getParam($view, 'html-template');
48 my $expires = $config_tree->getParam($view, 'expires');
50 # Create the Template Toolkit processor once, and reuse
51 # it in subsequent render() calls
53 if( not defined( $self->{'tt'} ) )
56 new Template(INCLUDE_PATH => $Torrus::Global::templateDirs,
61 'treeName' => $config_tree->treeName(),
64 'expires' => $expires,
65 'path' => sub { return $config_tree->path($_[0]); },
66 'pathToken' => sub { return $config_tree->token($_[0]); },
67 'nodeExists' => sub { return $config_tree->nodeExists($_[0]); },
68 'children' => sub { return $config_tree->getChildren($_[0]); },
69 'isLeaf' => sub { return $config_tree->isLeaf($_[0]); },
70 'isAlias' => sub { return $config_tree->isAlias($_[0]); },
71 'sortTokens' => sub { return $self->sortTokens($config_tree,
73 'nodeName' => sub { return $self->nodeName($config_tree, $_[0]); },
74 'parent' => sub { return $config_tree->getParent($_[0]); },
75 'nodeParam' => sub { return $config_tree->getNodeParam(@_); },
76 'param' => sub { return $config_tree->getParam(@_); },
77 'url' => sub { return $self->makeURL($config_tree, 0, @_); },
78 'persistentUrl' => sub { return $self->makeURL($config_tree, 1, @_); },
79 'clearVar' => sub { delete $self->{'options'}{'variables'}{$_[0]};
81 'plainURL' => $Torrus::Renderer::plainURL,
82 'splitUrls' => sub { return $self->makeSplitURLs($config_tree,
84 'topURL' => ($Torrus::Renderer::rendererURL ne '' ?
85 $Torrus::Renderer::rendererURL : '/'),
86 'rrprint' => sub { return $self->rrPrint($config_tree,
88 'scale' => sub { return $self->scale($_[0], $_[1]); },
89 'tsetMembers' => sub { $config_tree->tsetMembers($_[0]); },
90 'tsetList' => sub { $config_tree->getTsets(); },
91 'style' => sub { return $self->style($_[0]); },
92 'companyName'=> $Torrus::Renderer::companyName,
93 'companyLogo'=> $Torrus::Renderer::companyLogo,
94 'companyURL' => $Torrus::Renderer::companyURL,
95 'siteInfo' => $Torrus::Renderer::siteInfo,
96 'treeInfo' => sub { return $Torrus::Global::treeConfig{
97 $config_tree->treeName()}{'info'}; },
98 'version' => $Torrus::Global::version,
99 'xmlnorm' => \&Torrus::Renderer::xmlnormalize,
100 'userAuth' => $Torrus::CGI::authorizeUsers,
101 'uid' => $self->{'options'}->{'uid'},
102 'userAttr' => sub { return $self->userAttribute( $_[0] ) },
103 'mayDisplayAdmInfo' => sub {
104 return $self->may_display_adminfo( $config_tree, $_[0] ) },
105 'adminfo' => $self->{'adminfo'},
106 'mayDisplayReports' => sub {
107 return $self->may_display_reports($config_tree) },
108 'reportsUrl' => sub {
109 return $self->reportsUrl($config_tree); },
110 'timestamp' => sub { return time2str($Torrus::Renderer::timeFormat,
112 'verifyDate' => sub { return verifyDate($_[0]); },
113 'markup' => sub{ return $self->translateMarkup( @_ ); },
114 'searchEnabled' => $Torrus::Renderer::searchEnabled,
115 'searchResults' => sub { return $self->doSearch($config_tree, $_[0]); },
118 'freesideHeader' => sub { return $self->freesideHeader(@_); },
119 'freesideFooter' => sub { return $self->freesideFooter(); },
120 'freesideComponent' => sub { return $self->freesideComponent(@_); },
121 'uri_escape' => sub { return uri_escape(@_); },
122 'matches' => sub { return $_[0] =~ $_[1]; },
124 #false laziness w/Torrus_Internal::add_interface, update both
125 'iface_underscore' => sub { $_[0] =~ s/[\/\.\-]/_/g; return $_[0]; },
127 'load_nms' => sub { return $self->load_nms; },
128 'get_serviceids' => sub { my $nms = shift;
130 return $nms->get_router_serviceids($router);
132 'popup_link' => sub {
135 if($type eq 'nms-add_iface.html') {
137 my $interface = shift;
139 my $serviceids = shift;
141 if ( $serviceids && $serviceids->{$interface} ) {
143 my $serviceid = $serviceids->{$interface};
145 my $svc_port = $nms->find_svc($serviceid);
148 my $url = $Torrus::Freeside::FSURL.
149 "/view/svc_port.cgi?". $svc_port->svcnum;
150 return "<A HREF='$url'>View Service</A>";
153 $nms->find_torrus_srvderive_component($serviceid);
156 return "$serviceid combined into ".
157 $component->torrus_srvderive->serviceid;
159 return "Monitored as $serviceid".
160 '; not yet provisioned or combined';
167 $self->freesideComponent('/elements/popup_link.html',
168 'action' => "/freeside/misc/".
169 $type."?host=$host;iface=$interface",
170 'label' => 'Monitor for billing',
171 'actionlabel' => 'Monitor interface',
176 } elsif ($type eq 'nms-add_router.html') {
178 $self->freesideComponent('/elements/popup_link.html',
179 'action' => "/freeside/misc/$type",
180 'label' => 'Add Router',
181 'actionlabel' => 'Add Router',
191 # Pass the options from Torrus::Renderer::render() to Template
192 while( my( $opt, $val ) = each( %{$self->{'options'}} ) )
194 $ttvars->{$opt} = $val;
197 my $result = $self->{'tt'}->process( $tmplfile, $ttvars, $outfile );
203 if( $config_tree->isTset( $token ) )
205 Error("Error while rendering tokenset $token: " .
206 $self->{'tt'}->error());
210 my $path = $config_tree->path($token);
211 Error("Error while rendering $path: " .
212 $self->{'tt'}->error());
217 return ($expires+time(), 'text/html; charset=UTF-8');
224 my $config_tree = shift;
227 my $n = $config_tree->getNodeParam($token, 'node-display-name', 1);
228 if( defined( $n ) and length( $n ) > 0 )
233 return $config_tree->nodeName($config_tree->path($token));
240 my $config_tree = shift;
241 my $tokenlist = shift;
244 if( ref($tokenlist) and scalar(@{$tokenlist}) > 0 )
248 my $p_a = $config_tree->getNodeParam($a, 'precedence', 1);
249 $p_a = 0 unless defined $p_a;
250 my $p_b = $config_tree->getNodeParam($b, 'precedence', 1);
251 $p_b = 0 unless defined $p_b;
254 my $n_a = $config_tree->path($a);
255 my $n_b = $config_tree->path($b);
256 return $n_a cmp $n_b;
260 return $p_b <=> $p_a;
266 push(@sorted, $tokenlist);
272 # compose an URL for a node.
273 # $persistent defines if the link should be persistent
274 # Persistent link is done with nodeid if available, or with path
279 my $config_tree = shift;
280 my $persistent = shift;
285 my $ret = $Torrus::Renderer::rendererURL . '/' . $config_tree->treeName();
289 my $nodeid = $config_tree->getNodeParam($token, 'nodeid', 1);
290 if( defined( $nodeid ) )
293 uri_escape($nodeid, $Torrus::Renderer::uriEscapeExceptions);
298 uri_escape($config_tree->path($token),
299 $Torrus::Renderer::uriEscapeExceptions);
304 $ret .= '?token=' . uri_escape($token);
309 $ret .= '&view=' . uri_escape($view);
313 # This could be array or a reference to array
314 my $add_vars_size = scalar( @add_vars );
315 if( $add_vars_size == 1 and ref( $add_vars[0] ) )
317 %vars = @{$add_vars[0]};
319 elsif( $add_vars_size > 0 and ($add_vars_size % 2 == 0) )
324 if( ref( $self->{'options'}->{'variables'} ) )
326 foreach my $name ( sort keys %{$self->{'options'}->{'variables'}} )
328 my $val = $self->{'options'}->{'variables'}->{$name};
329 if( not defined( $vars{$name} ) )
336 foreach my $name ( sort keys %vars )
338 if( $vars{$name} ne '' )
340 $ret .= '&' . $name . '=' .
341 uri_escape( $vars{$name},
342 $Torrus::Renderer::uriEscapeExceptions );
352 my $config_tree = shift;
357 while( defined( $token ) )
359 my $path = $config_tree->path($token);
361 my $str = '<SPAN CLASS="PathElement">';
363 sprintf('<A HREF="%s">%s%s</A>',
364 $self->makeURL($config_tree, 0, $token, $view),
365 $config_tree->nodeName($path),
366 ( $config_tree->isSubtree($token) and
367 $path ne '/') ? '/':'' );
372 $token = $config_tree->getParent( $token );
382 my $config_tree = shift;
387 my($fname, $mimetype) = $self->render( $config_tree, $token, $view );
389 if( $mimetype ne 'text/plain' )
391 Error("View $view does not produce text/plain for token $token");
395 if( not open(IN, $fname) )
397 Error("Cannot open $fname for reading: $!");
401 chomp(my $values = <IN>);
402 @ret = split(':', $values);
409 # This subroutine is taken from Dave Plonka's Flowscan
414 # This is based somewhat on Tobi Oetiker's code in rrd_graph.c:
417 my @symbols = ("a", # 10e-18 Ato
432 my $digits = (0 == $value)? 0 : floor(log(abs($value))/log(1000));
433 return sprintf( $fmt . " %s", $value/pow(1000, $digits),
434 $symbols[ $symbcenter+$digits ] );
443 if( not defined( $media = $self->{'options'}->{'variables'}->{'MEDIA'} ) )
447 return $Torrus::Renderer::styling{$media}{$object};
457 if( $self->{'options'}->{'uid'} and $self->{'options'}->{'acl'} )
459 $self->{'options'}->{'acl'}->
460 userAttribute( $self->{'options'}->{'uid'}, $attr );
472 my $privilege = shift;
474 if( $self->{'options'}->{'uid'} and $self->{'options'}->{'acl'} )
476 $self->{'options'}->{'acl'}->
477 hasPrivilege( $self->{'options'}->{'uid'}, $object, $privilege );
491 my $tt = new Template( TRIM => 1 );
495 'em' => sub { return '<em>' . $_[0] . '</em>'; },
496 'strong' => sub { return '<strong>' . $_[0] . '</strong>'; }
501 foreach my $str ( @strings )
504 my $result = $tt->process( \$str, $ttvars, \$output );
508 Error('Error translating markup: ' . $tt->error());
526 my $time = str2time( $input );
527 # rrdtool does not understand dates prior to 1980 (315529200)
528 if( defined( $time ) and $time > 315529200 )
530 # Present the time in format understood by rrdtool
531 return time2str('%H:%M %Y%m%d', $time);
540 sub may_display_reports
543 my $config_tree = shift;
545 if( $Torrus::Renderer::displayReports )
547 if( not $Torrus::CGI::authorizeUsers )
552 my $tree = $config_tree->treeName();
553 if( $self->hasPrivilege( $tree, 'DisplayReports' ) and
554 -r $Torrus::Global::reportsDir . '/' . $tree .
567 my $config_tree = shift;
569 return $Torrus::Renderer::rendererURL . '/' .
570 $config_tree->treeName() . '?htmlreport=index.html';
577 my $config_tree = shift;
581 my $tree = $config_tree->treeName();
583 my $sr = new Torrus::Search;
584 $sr->openTree( $tree );
585 my $result = $sr->searchPrefix( $string, $tree );
586 $sr->closeTree( $tree );
589 push( @{$ret}, sort {$a->[0] cmp $b->[0]} @{$result} );
600 # indent-tabs-mode: nil
601 # perl-indent-level: 4