1#!/usr/bin/perl
2#vim:ts=4
3#
4# graphxml3.cgi : Steve Shipway www.steveshipway.org
5#
6# Produce XML for slickboard/swfgauge, based on contents of MRTG .cfg file
7#
8# v1.0 : Link in graph image from Routers2
9#  1.1 : improve legend
10#  1.2 : more legend errors
11
12use strict;
13use CGI;
14use FileHandle;
15use Text::ParseWords;
16
17my($VERSION) = "v1.2";
18my($REGISTERED) = ""; # Set this to blank or your license key
19########################################################################
20# If my url matches this regexp, we're in public mode
21my($PUBLICURL) = 'public';
22# If in public mode, requested cfg must match this regexp
23my($PUBLICCFG) = '^other-summary\/';
24# This is the URL for routers2.cgi, if you have it
25my($ROUTERSCGI) = "https://monitor.auckland.ac.nz/cgi-bin/routers2-open.cgi";
26# The location of CFG files
27my($CFGDIR) = '/u01/mrtg/conf';
28# Use 1 for SLICKBOARD.SWF, 0 for GAUGE.SWF
29my($MODE) = 1;
30# Default workdir for RRD files if not set in cfg file
31my($workdir) = "/u01/rrdtool";
32########################################################################
33# Not a good idea to change below here
34my($DEBUG) = 0;
35my($q) = new CGI;
36my($URL) = $q->url();
37my($debugmessage) = '';
38my($pathsep) = "/";
39my($interval) = 5;
40my($workdir) = '';
41my($curdiv);
42my($links) = "";
43my($TARGET) = "";
44my($DEVICE) = "";
45my($WIDTH) = 600; # actually 575x223
46my($HEIGHT) = 250;
47my($OBJECT) = 0;  # generates embeddable XML if 1
48my($XOFF,$YOFF) = (0,0); # offset for generated objects
49my(%interfaces) = ();
50my(@defcolours) = (
51         "0000ff","00ff00","ff0000","00cccc","cccc00","cc00cc",
52        "8800ff", "88ff00", "ff8800", "0088ff", "ff0088", "00ff88" );
53
54$DEBUG = 1 if( $q->url() =~ /localhost/ );
55
56#############################################################################
57# Utility functions
58sub roundoff($) { # this is rather ugly
59	my($a) = $_[0];
60	my($b) = $a;
61	return $a if( $a =~/^\d5?0*$/ );
62	$a = int(($a*1.1)+0.99);
63	$b = substr($a,0,1); $b += 1 if ( $a !~ /^\d0*$/ );
64	$b += 1 if( $b>1 and ($b % 5) ne 0 );
65	$b = 5 if($b>1 and $b<5 and $a<10);
66	$b .= '0' x (length($a)-1);
67	print "Rounding off ".$_[0]." ==110%=> $a ==choose=> $b\n" if($DEBUG);
68	return $b;
69}
70sub doformat($) {
71	my($sfx)="";
72	return "" if($_[0] eq "U");
73	if($_[0]=~ /([^\d]+)$/) { $sfx = $1; }
74	return ((int(100*$_[0]/$curdiv)/100).$sfx);
75}
76sub dokmgformat($$) {
77	my($v,$u) = @_;
78	my($s) = doformat($v);
79
80	$s .= 'k' if($curdiv == 1000);
81	$s .= 'M' if($curdiv == 1000000);
82	$s .= 'G' if($curdiv == 1000000000);
83	$s .= 'T' if($curdiv == 1000000000000);
84	$s .= $u if($u);
85
86	return $s;
87}
88sub getunits($$$) {
89	my($m,$u,$f) = @_;
90
91	$curdiv = "1";
92	$u =~ s/&nbsp;//g; $u =~ s/\s*$//;
93
94	if($m > 2000000000000 ) { $curdiv = 1000000000000; return "T$u" if($u and !$f);
95return "x1e12" ; }
96	if($m > 2000000000 ) { $curdiv = 1000000000; return "G$u" if($u and !$f);
97return "x1e9" ; }
98	if($m > 2000000 ) { $curdiv = 1000000; return "M$u" if($u and !$f);
99return "x1,000,000" ; }
100	if($m > 2000 ) { $curdiv = 1000; return "k$u" if($u and !$f);
101return "x1,000" ; }
102	$curdiv = 1; return $u if(!$f); return "";
103}
104sub inlist($@)
105{
106    my($pat) = shift @_;
107    return 0 if(!defined $pat or !$pat or !@_);
108    foreach (@_) { return 1 if( $_ and /$pat/i ); }
109    return 0;
110}
111sub calcstep($) {
112	my($m) = $_[0];
113	my($a);
114	$a = int($m/10);
115	$a = 1 if($a < 1);
116
117	return 0.1 if($m == 1);
118	return 0.25 if($m < 3);
119	return 0.5 if($m < 5);
120	return $a if( $a =~ /^[125]/ ) ;
121	$a =~ s/^./2/ if( $a =~ /^3/ ) ;
122	$a =~ s/^./5/ if( $a =~ /^[467]/ ) ;
123	$a =~ s/^./10/ if( $a =~ /^[89]/ ) ;
124
125	return $a;
126}
127
128#############################################################################
129# Read MRTG .cfg file.  Modified from function in routers2.cgi
130
131sub readcfg($) {
132	my($cfgfile,$makespecial) = @_;
133	my($opts, $graph, $key, $k, $fd, $buf, $curif, @myifs, $arg, $argb, $rrd);
134	my($ifcnt, @ifarr, $t, $desc, $url, $icon, $targ, $newfile, $targfile);
135	my( $lasthostname, $lastcommunity ) = ("","");
136	my($level, $insec, $noop, $logdir);
137
138	my( $inpagetop, $inpagefoot ) = (0,0);
139
140	return if(!$cfgfile);
141
142	$debugmessage .= "$cfgfile ";
143
144	$fd = new FileHandle ;
145
146	if(! $fd->open( "<$cfgfile" )) {
147		$interfaces{$cfgfile} = {
148			shdesc=>"Error", desc=>"Cannot open file $cfgfile", inmenu=>0,
149			rrd=>"", insummary=>0, inout=>0, incompact=>0, mode=>"ERROR",
150			icon=>"alert-sm.gif" };
151		return;
152	}
153
154	print "Processing $cfgfile\n" if($DEBUG);
155
156	$key = ""; $curif = ""; @myifs = ();
157	while ( $buf = <$fd> ) {
158		next if( $buf =~ /^\s*#/ );
159		next if( $buf =~ /^\s*$/ ); # bit more efficient
160		if( $inpagefoot ) {
161			if( $curif and $buf =~ /^\s+\S/ ) {
162				$interfaces{$curif}{pagefoot} .= $buf;
163				next;
164			}
165			$inpagefoot = 0;
166		}
167		if( $inpagetop ) {
168			if( $curif and $buf =~ /^\s+\S/ ) {
169				$interfaces{$curif}{pagetop} .= $buf;
170				next;
171			}
172			$inpagetop = 0;
173		}
174		if( $buf =~ /^\s*(routers2?\.cgi\*)?Target\[(.+?)\]\s*:\s*(.+)/i ) {
175			$curif = $2; $arg = $3;
176			push @myifs, $curif;
177			# This ***MIGHT*** save people who put their .cfg files
178			# out of sequence?
179			if(!defined $interfaces{$curif}) {
180			$interfaces{$curif} = { file=>$cfgfile, target=>$curif,
181					insummary=>1, incompact=>1, inmenu=>1, isif=>0,
182					interval=>$interval, nomax=>0, noabsmax=>0  };
183			} else {
184			$interfaces{$curif} = { file=>$cfgfile, target=>$curif,
185					insummary=>1, incompact=>1, inmenu=>1, isif=>0,
186					interval=>$interval, nomax=>0, noabsmax=>0,
187					%{$interfaces{$curif}}  };
188			}
189			if(defined $interfaces{_}{directory}) {
190				$interfaces{$curif}{rrd} =
191					$workdir.$pathsep.$interfaces{_}{directory}
192					.$pathsep.(lc $curif).".rrd";
193			} else {
194				$interfaces{$curif}{rrd} = $workdir.$pathsep.(lc $curif).".rrd";
195			}
196			if( $arg =~ /^-?(\d+):([^\@:\s]+)\@([\w\-\.]+)/ ) {
197				# interface number
198				$interfaces{$curif}{isif} = 1;
199				$interfaces{$curif}{ifno} = $1;
200				$interfaces{$curif}{community} = $2;
201				$interfaces{$curif}{hostname} = $3;
202				$interfaces{$curif}{mode} = "interface";
203			} elsif( $arg =~ /^-?\/(\d+\.\d+\.\d+\.\d+):([^\@:\s]+)\@([\w\-\.]+)/ ) {
204				# IP address
205				$interfaces{$curif}{isif} = 1;
206				$interfaces{$curif}{ipaddress} = $1;
207				$interfaces{$curif}{community} = $2;
208				$interfaces{$curif}{hostname} = $3;
209				$interfaces{$curif}{mode} = "interface";
210			} elsif( $arg =~ /^-?[\\#!](\S.*?):([^\@:\s]+)\@([\w\-\.]+)/ ) {
211				$interfaces{$curif}{isif} = 1;
212				$interfaces{$curif}{ifdesc} = $1;
213				$interfaces{$curif}{community} = $2;
214				$interfaces{$curif}{hostname} = $3;
215				$interfaces{$curif}{mode} = "interface";
216				$interfaces{$curif}{ifdesc} =~ s/\\(.)/$1/g ;
217			} elsif( $arg =~ /&\w*[\d\.]+:(\S+)\@([\w\-\.]+)/ ) {
218				# explicit OIDs
219				$interfaces{$curif}{community} = $1;
220				$interfaces{$curif}{hostname} = $2;
221			} elsif( $arg =~ /mrtg.ping.probe/ ) {
222				# special for the mrtg-ping-probe.pl
223				$interfaces{$curif}{mode} = "ping";
224				$interfaces{$curif}{graphstyle} = "range";
225				$interfaces{$curif}{incompact} = 1;
226				$interfaces{$curif}{ifdesc} = "Response time" ;
227			} elsif( $arg =~ /`/ ) {
228				# external program
229				$interfaces{$curif}{insummary} = 1;
230				$interfaces{$curif}{incompact} = 1;
231			} else { # a target of some sort we dont yet know
232				$interfaces{$curif}{insummary} = 0;
233				$interfaces{$curif}{incompact} = 0;
234			}
235			$interfaces{$curif}{inout} = $interfaces{$curif}{isif};
236			foreach $k ( qw/isif inout incompact insummary inmenu/ ) {
237				$interfaces{$curif}{$k} = $interfaces{'_'}{$k}
238					if(defined $interfaces{'_'}{$k});
239			}
240			$lasthostname = $interfaces{$curif}{hostname}
241				if(defined $interfaces{$curif}{hostname});
242			$lastcommunity= $interfaces{$curif}{community}
243				if(defined $interfaces{$curif}{community});
244#			print "Added interface $curif\n" if($DEBUG);
245			next;
246		}
247		if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*)?(Title|Descr?|Description)\[(.+?)\]\s*:\s*(\S.*)/i ) {
248			$curif = $3; $arg = $4;
249			if(!defined $interfaces{$curif}) {
250				if(defined $interfaces{"_$curif"}) {
251					$curif = "_$curif";
252				} else {
253					$interfaces{$curif} = {note=>"Out of sequence"};
254				}
255			}
256			$interfaces{$curif}{desc} = $arg;
257			next;
258		}
259		if( $buf =~ /^\s*Options\[(.+?)\]\s*:\s*(\S.*)/i ) {
260			$curif = $1;
261			next if(!defined $interfaces{$curif});
262			$interfaces{$curif}{options} = "" if(!$interfaces{$curif}{options});
263			$interfaces{$curif}{options} .= ' '.$2;
264			next;
265		}
266		if( $buf =~ /^\s*SetEnv\[(.+?)\]\s*:\s*(\S.*)/i ) {
267			$curif = $1; $arg = $2;
268			next if(!defined $interfaces{$curif});
269			foreach $k ( quotewords('\s+',0,$arg) ) {
270				if( $k =~ /MRTG_INT_IP=\s*(\d+\.\d+\.\d+\.\d+)/ ) {
271					$interfaces{$curif}{ipaddress}=$1
272					if(!defined $interfaces{$curif}{ipaddress});
273					next;
274				}
275				if( $k =~ /MRTG_INT_DESCR?=\s*(\S.*)/ ) {
276					$interfaces{$curif}{shdesc}=$1
277					if(!defined $interfaces{$curif}{shdesc});
278					next;
279				}
280			}
281			next;
282		}
283		if( $buf =~ /^\s*routers2?\.cgi\*Short(Name|Descr?|Description)\[(.+?)\]\s*:\s*(\S.*)/i ) {
284			$curif = $2; $arg = $3;
285			$curif = "_$curif" if(!defined $interfaces{$curif});
286			next if(!defined $interfaces{$curif});
287			$interfaces{$curif}{shdesc} = $arg if($arg);
288			next;
289		}
290		if(( $buf =~ /^\s*(routers2?\.cgi|g[au][ua]gexml3?|slickboard|swfgauge)\*Options\[(.+?)\]\s*:\s*(\S.*)/i )
291			or ( $buf =~ /^\s*g[au][ua]ge\.(swf|cgi)\*Options\[(.+?)\]\s*:\s*(\S.*)/i )) {
292			$curif = $2; $arg = $3;
293			next if(!defined $interfaces{$curif});
294			$interfaces{$curif}{cgioptions}="" if(!$interfaces{$curif}{cgioptions});
295			$interfaces{$curif}{cgioptions} .= " ".$arg;
296			next;
297		}
298		if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*)?MaxBytes\[(.+?)\]\s*:\s*(\d+)/i ) {
299			next if(!defined $interfaces{$2});
300			$interfaces{$2}{maxbytes} = $3;
301			next;
302		}
303		if($buf=~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*|g[au][ua]gexml3?\.cgi|g[au][ua]ge\.swf\*|slickboard|swfgauge)?Unscaled\[(.+?)\]\s*:\s*([6dwmy]*)/i){
304			next if(!defined $interfaces{$2});
305			$interfaces{$2}{unscaled} = $3;
306			next;
307		}
308		if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*)?YLegend\[(.+?)\]\s*:\s*(\S.*)/i ) {
309			$curif = $2;
310			$curif = "_$curif" if(!defined $interfaces{$curif});
311			next if(!defined $interfaces{$curif});
312			$interfaces{$curif}{ylegend} = $3;
313			next;
314		}
315		if($buf=~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*)?ShortLegend\[(.+?)\]\s*:\s*(.*)/i){
316			$curif = $2;
317			$curif = "_$curif" if(!defined $interfaces{$curif});
318			next if(!defined $interfaces{$curif});
319			$interfaces{$curif}{unit} = $3;
320			$interfaces{$curif}{unit} =~ s/&nbsp;/ /g;
321			next;
322		}
323		if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*)?(Legend[IO1234TA][IO]?)\[(.+?)\]\s*:\s*(\S.*)/i ) {
324			$curif = $3; $key = lc $2; $arg = $4;
325			$curif = "_$curif" if(!defined $interfaces{$curif});
326			next if(!defined $interfaces{$curif});
327			$arg =~ s/&nbsp;/ /;
328			$interfaces{$curif}{$key} = $arg;
329			next;
330		}
331		if( $buf =~ /^\s*routers2?\.cgi\*Mode\[(.+?)\]\s*:\s*(\S+)/i ) {
332			next if(!defined $interfaces{$1});
333			$interfaces{$1}{mode} = $2;
334			next;
335		}
336		if( $buf =~ /^\s*routers2?\.cgi\*(Graph|Summary)\[(.+?)\]\s*:\s*(\S.*)/i ) {
337			$curif = $2; $arg = $3; $argb = (lc $1);
338			next if( $curif eq '_' ); # not allowed
339			if(!defined $interfaces{$curif}) {
340				if( $argb eq "summary") {
341					$curif = "_$curif" ;
342				} else {
343					# Create a dummy target...
344					$interfaces{$curif} = { file=>$cfgfile, target=>$curif,
345					insummary=>0, incompact=>0, inmenu=>0, isif=>0,
346					interval=>$interval, nomax=>0, noabsmax=>0  };
347					if(defined $interfaces{_}{directory}) {
348						$interfaces{$curif}{rrd} =
349							$workdir.$pathsep.$interfaces{_}{directory}
350							.$pathsep.(lc $curif).".rrd";
351					} else {
352						$interfaces{$curif}{rrd}
353							= $workdir.$pathsep.(lc $curif).".rrd";
354					}
355				}
356			}
357			next if(!defined $interfaces{$curif});
358			if( $arg =~ /^"/ ) {
359				$arg =~ /^"([^"]+)"\s*:?(.*)/;
360				$opts = $2; $graph = $1;
361			} else {
362				$arg =~ /^(\S+)\s*:?(.*)/;
363				$opts = $2; $graph = $1;
364			}
365			next if(!$graph);
366			$interfaces{$curif}{usergraphs} = []
367				if(!defined $interfaces{$curif}{usergraphs});
368			push @{$interfaces{$curif}{usergraphs}}, $graph;
369			if( defined $interfaces{"_$graph"} ) {
370				push @{$interfaces{"_$graph"}{targets}}, $curif
371					if(!inlist("^$curif\$",@{$interfaces{"_$graph"}{targets}}));
372				$interfaces{"_$graph"}{cgioptions} .= " $opts";
373			} else {
374				if( $argb eq "summary" ) {
375					$interfaces{"_$graph"} = {
376						shdesc=>$graph,  targets=>[$curif],
377						cgioptions=>$opts, mode=>"\177_USERSUMMARY",
378						usergraph=>1, icon=>"summary-sm.gif",
379						inout=>0, incompact=>0, withtotal=>0, withaverage=>0,
380						insummary=>0, inmenu=>1, desc=>"Summary $graph",
381						issummary=>1
382					};
383				} else {
384					$interfaces{"_$graph"} = {
385						shdesc=>$graph,  targets=>[$curif],
386						cgioptions=>$opts, mode=>"\177_USER",
387					usergraph=>1, icon=>"cog-sm.gif", inout=>0, incompact=>0,
388					insummary=>0, inmenu=>1, desc=>"User defined graph $graph",
389						withtotal=>0, withaverage=>0, issummary=>0
390					};
391					$interfaces{"_$graph"}{unit} = $interfaces{$curif}{unit}
392						if($interfaces{$curif}{unit});
393					$interfaces{"_$graph"}{rrd} = $interfaces{$curif}{rrd};
394				}
395#				$interfaces{"_$graph"}{withtotal} = 1
396#					if( defined $config{'routers.cgi-showtotal'}
397#						and $config{'routers.cgi-showtotal'}=~/y/i);
398				push @myifs, "_$graph";
399			}
400			next;
401		}
402		if( $buf =~ /^\s*routers2?\.cgi\*Ignore\[(.+?)\]\s*:\s*(\S+)/i ) {
403			$curif = $1; $arg = $2;
404			$curif = "_$curif" if(!defined $interfaces{$curif});
405			next if(!defined $interfaces{$curif});
406			if( $arg =~ /y/i ) {
407				$interfaces{$curif}{insummary} = 0;
408				$interfaces{$curif}{inmenu} = 0;
409				$interfaces{$curif}{inout} = 0;
410				$interfaces{$curif}{isif} = 0;
411			}
412			next;
413		}
414		if( $buf =~ /^\s*routers2?\.cgi\*InSummary\[(.+?)\]\s*:\s*(\S+)/i ) {
415			$curif = $1; $arg = $2;
416			$curif = "_$curif" if(!defined $interfaces{$curif});
417			next if(!defined $interfaces{$curif});
418			if( $arg =~ /[1y]/i ) {  $interfaces{$curif}{insummary} = 1; }
419			else { $interfaces{$curif}{insummary} = 0; }
420			next;
421		}
422		if( $buf =~ /^\s*(g[au][ua]ge\.swf|g[au][ua]gexml3?|swfgauge|slickboard)\*Hide\[(.+?)\]\s*:\s*(\S+)/i ) {
423			$curif = $2; $arg = $3;
424			$curif = "_$curif" if(!defined $interfaces{$curif});
425			next if(!defined $interfaces{$curif});
426			if( $arg =~ /[1y]/i ) {  $interfaces{$curif}{inmenu} = 0; }
427			else { $interfaces{$curif}{inmenu} = 1; }
428			next;
429		}
430		if( $buf =~ /^\s*(g[au][ua]ge\.swf|g[au][ua]gexml3?|swfgauge|slickboard)\*Max(Bytes)?\[(.+?)\]\s*:\s*(\S+)/i ) {
431			$curif = $3; $arg = $4;
432			$curif = "_$curif" if(!defined $interfaces{$curif});
433			next if(!defined $interfaces{$curif});
434			$interfaces{$curif}{maxbytes} = $2;
435			$interfaces{$curif}{unscaled} = "none";
436			next;
437		}
438		if( $buf =~ /^\s*routers2?\.cgi\*InMenu\[(.+?)\]\s*:\s*(\S+)/i ) {
439			$curif = $1; $arg = $2;
440			$curif = "_$curif" if(!defined $interfaces{$curif});
441			next if(!defined $interfaces{$curif});
442			if( $arg =~ /[1y]/i ) {  $interfaces{$curif}{inmenu} = 1; }
443			else { $interfaces{$curif}{inmenu} = 0; }
444			next;
445		}
446		if( $buf =~ /^\s*routers2?\.cgi\*InOut\[(.+?)\]\s*:\s*(\S+)/i ) {
447			$curif = $1; $arg = $2;
448			next if(!defined $interfaces{$curif});
449			if( $arg =~ /[1y]/i ) {  $interfaces{$curif}{inout} = 1; }
450			else { $interfaces{$curif}{inout} = 0; }
451			next;
452		}
453		if( $buf =~ /^\s*routers2?\.cgi\*InCompact\[(.+?)\]\s*:\s*(\S+)/i ) {
454			$curif = $1; $arg = $2;
455			next if(!defined $interfaces{$curif});
456			if( $arg =~ /[1y]/i ) {  $interfaces{$curif}{incompact} = 2; }
457			else { $interfaces{$curif}{incompact} = 0; }
458			next;
459		}
460		if( $buf =~ /^\s*Directory\[(.+?)\]\s*:\s*(\S.*)/i ) {
461			$curif = $1; $arg = $2;
462			next if(!defined $interfaces{$curif});
463			$arg =~ s/[\s\\\/]+$//; # trim trailing spaces and path separators!
464			$interfaces{$curif}{rrd} =
465				$workdir.$pathsep.$arg.$pathsep.(lc $curif).".rrd";
466			$interfaces{$curif}{directory} = $arg;
467			next;
468		}
469		if( $buf =~ /^\s*Logdir\s*:\s*(\S+)/i ) {
470			$logdir = $1; $logdir =~ s/[\\\/]+$//; $workdir = $logdir; next; }
471		if( $buf =~ /^\s*Workdir\s*:\s*(\S+)/i and !$logdir ) {
472			$workdir = $1; $workdir =~ s/[\\\/]+$//; next; }
473		if( $buf =~ /^\s*Interval\s*:\s*(\d+)/i ) { $interval = $1; next; }
474		if( $buf =~ /^\s*Include\s*:\s*(\S+)/i ) {
475			readcfg($1);
476			next;
477		}
478		if( $buf =~ /^\s*LibAdd\s*:\s*(\S+)/i ) { push @INC, $1; next; }
479		if($buf=~ /^\s*(routers2?\.cgi\*)?MaxBytes(\d)\[(.+?)\]\s*:\s*(\d+)/i ){
480			$curif = $3; $arg = $4;
481			next if(!defined $interfaces{$curif});
482			$interfaces{$curif}{"maxbytes$2"} = $arg;
483			$interfaces{$curif}{maxbytes} = $arg
484				if(!$interfaces{$curif}{maxbytes});
485			next;
486		}
487#		# the regexp from hell
488#		if( $buf =~ /^\s*(routers2?\.cgi\*)?Colou?rs\[(.+?)\]\s*:\s*[^#]*(#[\da-f]{6})[\s,]+[^#]*(#[\da-f]{6})[\s,]+[^#]*(#[\da-f]{6})[\s,]+[^#]*(#[\da-f]{6})/i ) {
489#			$curif = $2;
490#			$curif = "_$curif" if(!defined $interfaces{$curif});
491#			next if(!defined $interfaces{$curif});
492#			$interfaces{$curif}{colours} = [ $3,$4,$5,$6 ];
493#			next;
494#		}
495        if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?|swfgauge|gauge\.swf|slickboard)?Colou?rs\[(.+?)\]\s*:\s*(.*)/i ) {
496            $curif = $2; $arg = $3;
497            $curif = "_$curif" if(!defined $interfaces{$curif});
498            next if(!defined $interfaces{$curif});
499            $interfaces{$curif}{colours} = []; # null array
500            while( $arg =~ s/^[\s,]*[^#]*(#[\da-fA-F]{6})[\s,]*// ) {
501                push @{$interfaces{$curif}{colours}},$1;
502            }
503            $interfaces{$curif}{colours} = [ '#00ff00','#0000ff' ]
504                if($#{$interfaces{$curif}{colours}}<0);
505            next;
506        }
507		if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*|swfgauge\*|gauge\.swf\*|slickboard\*)?AbsMax\[(.+?)\]\s*:\s*(\d+)/i ) {
508			next if(!defined $interfaces{$2});
509			$interfaces{$2}{absmaxbytes} = $3;
510			next;
511		}
512		if( $buf =~ /^\s*(routers2?\.cgi\*)?Factor\[(.+?)\]\s*:\s*(-?[\d\.]+)/i ) {
513			$curif = $2; $arg = $3;
514			next if(!defined $interfaces{$curif});
515			$interfaces{$curif}{factor} = $arg if($arg != 0);
516			next;
517		}
518		if( $buf =~ /^\s*(routers2?\.cgi\*)?Supp?ress?\[(.+?)\]\s*:\s*(\S+)/i ) {
519			$curif = $2; $arg = $3;
520			$curif = "_$curif" if(!defined $interfaces{$curif});
521			next if(!defined $interfaces{$curif});
522			$interfaces{$curif}{suppress} = $arg;
523			next;
524		}
525		if( $buf =~ /^\s*(routers2?\.cgi|g[au][ua]gexml3?|swfgauge|slickboard|g[au][ua]ge\.swf)\*UpperLimit\[(.+?)\]\s*:\s*(\d+)/i ) {
526			$curif = $2; $arg = $3;
527			$curif = "_$curif" if(!defined $interfaces{$curif});
528			next if(!defined $interfaces{$curif});
529			$interfaces{$curif}{upperlimit} = $arg;
530			next;
531		}
532		if( $buf =~ /^\s*routers2?\.cgi\*LowerLimit\[(.+?)\]\s*:\s*(\d+)/i ) {
533			$curif = $1; $arg = $2;
534			$curif = "_$curif" if(!defined $interfaces{$curif});
535			next if(!defined $interfaces{$curif});
536			$interfaces{$curif}{lowerlimit} = $arg;
537			next;
538		}
539		if( $buf =~ /^\s*(routers2?\.cgi\*|g[au][ua]gexml3?\*|swfgauge\*|gauge\.swf\*|slickboard\*)?(Thresh(Max|Min)[IO])\[(.+?)\]\s*:\s*([\d%]+)/i ) {
540			$curif = $4; $arg = $5;
541			$curif = "_$curif" if(!defined $interfaces{$curif});
542			next if(!defined $interfaces{$curif});
543			$interfaces{$curif}{(lc $2)} = $arg;
544			next;
545		}
546		if( $buf =~ /^\s*routers2?\.cgi\*FixUnits?\[(.+?)\]\s*:\s*(\d+)/i ) {
547			$curif = $1; $arg = $2;
548			$curif = "_$curif" if(!defined $interfaces{$curif});
549			next if(!defined $interfaces{$curif});
550			$interfaces{$curif}{exponent} = $arg;
551			$interfaces{$curif}{fixunits} = 1; # Implied
552			next;
553		}
554	}
555	$fd->close;
556
557	# now take the current file defaults
558	foreach $key ( keys %{$interfaces{'_'}} ) {
559		foreach $curif ( @myifs ) {
560			$interfaces{$curif}{$key} = $interfaces{'_'}{$key}
561				if(!defined $interfaces{$curif}{$key});
562		}
563	}
564	foreach $key ( keys %{$interfaces{'^'}} ) {
565		foreach $curif ( @myifs ) {
566			$interfaces{$curif}{$key} = $interfaces{'^'}{$key}.' '.$interfaces{$curif}{$key};
567		}
568	}
569	foreach $key ( keys %{$interfaces{'$'}} ) {
570		foreach $curif ( @myifs ) {
571			$interfaces{$curif}{$key} .= ' '.$interfaces{'$'}{$key};
572		}
573	}
574
575	# now process the options
576	foreach $curif ( @myifs ) {
577		next if(!$curif);
578#		print "Processing interface $curif options (isif=".$interfaces{$curif}{isif}."...\n" if($DEBUG);
579		if(defined $interfaces{$curif}{options} ) {
580		foreach $k ( split /[\s,]+/,$interfaces{$curif}{options} ) {
581#			print "Option: $k\n" if($DEBUG);
582			if( $k eq "unknaszero") { $interfaces{$curif}{unknaszero} = 1; }
583			$interfaces{$curif}{noo} = 1 if( $k eq "noo");
584			$interfaces{$curif}{noi} = 1 if( $k eq "noi");
585			if( $k eq "bits") {
586				$interfaces{$curif}{bytes} = 0;
587				$interfaces{$curif}{bits} = 1; }
588			if( $k eq "perminute") {
589				$interfaces{$curif}{perminute} = 1
590					if(!defined $interfaces{$curif}{perhour}
591						and !defined $interfaces{$curif}{perminute});
592			}
593			if( $k eq "perhour") {
594				$interfaces{$curif}{perhour} = 1
595					if(!defined $interfaces{$curif}{perhour}
596						and !defined $interfaces{$curif}{perminute});
597			}
598			if( $k eq "nopercent") {
599				$interfaces{$curif}{percent} = 0 ;
600				# default incompact to NO if target has nopercent set
601				$interfaces{$curif}{incompact} = 0
602					if($interfaces{$curif}{incompact} == 1);
603			}
604			if( $k eq "dorelpercent") {
605				 $interfaces{$curif}{noo} = 1;
606				 $interfaces{$curif}{dorelpercent} = 1;
607				 $interfaces{$curif}{fixunits} = 1;
608				 $interfaces{$curif}{percent} = 0;
609				 $interfaces{$curif}{bytes} = 1;
610				 $interfaces{$curif}{bits} = 0;
611				 $interfaces{$curif}{total} = 0;
612				 $interfaces{$curif}{percentile} = 0;
613				 $interfaces{$curif}{perminute} = 0;
614				 $interfaces{$curif}{perhour} = 0;
615				 $interfaces{$curif}{withtotal} = 0;
616				 $interfaces{$curif}{noabsmax} = 1;
617				 $interfaces{$curif}{nomax} = 0;
618				 $interfaces{$curif}{mblegend} = 'Equality';
619				 $interfaces{$curif}{unit} = '%';
620				 $interfaces{$curif}{totunit} = '';
621				 $interfaces{$curif}{ylegend} = 'percentage';
622				 $interfaces{$curif}{mode} = 'relpercent';
623			}
624			$interfaces{$curif}{integer} = 1 if( $k eq "integer");
625		} } # if defined options
626		if ( defined $interfaces{$curif}{cgioptions} ) {
627		  foreach $k ( split /[\s,]+/,$interfaces{$curif}{cgioptions} ) {
628			# print "Extended Option: $k\n" if($DEBUG);
629			$interfaces{$curif}{available} = 1 if( $k eq "available");
630			$interfaces{$curif}{available} = 0 if( $k eq "noavailable");
631			$interfaces{$curif}{noo} = 1 if( $k eq "noo");
632			$interfaces{$curif}{noi} = 1 if( $k eq "noi");
633			$interfaces{$curif}{noo} = 0 if( $k eq "o");
634			$interfaces{$curif}{noi} = 0 if( $k eq "i");
635			$interfaces{$curif}{c2fi} = 1 if( $k eq "c2fi");
636			$interfaces{$curif}{c2fo} = 1 if( $k eq "c2fo");
637			if( $k eq "bytes") { $interfaces{$curif}{bytes} = 1;
638				$interfaces{$curif}{bits} = 0; next; }
639			if( $k eq "bits") { $interfaces{$curif}{bits} = 1;
640				$interfaces{$curif}{bytes} = 0; next;  }
641			if( $k eq "unknaszero") { $interfaces{$curif}{unknaszero} = 1; }
642			if( $k eq "perminute") {
643				$interfaces{$curif}{perminute} = 1
644					if(!defined $interfaces{$curif}{perhour}
645						and !defined $interfaces{$curif}{perminute});
646				next;
647			}
648			if( $k eq "perhour") {
649				$interfaces{$curif}{perhour} = 1
650					if(!defined $interfaces{$curif}{perhour}
651						and !defined $interfaces{$curif}{perminute});
652				next;
653			}
654			$interfaces{$curif}{isif} = 1 if($k eq "interface");
655			if( $k eq "ignore") {
656				$interfaces{$curif}{inmenu} = 0 ;
657				$interfaces{$curif}{insummary} = 0 ;
658				$interfaces{$curif}{inout} = 0 ;
659				$interfaces{$curif}{incompact} = 0 ;
660				next;
661			}
662			$interfaces{$curif}{unscaled} = "" if( $k eq "scaled");
663			if( $k eq "nototal") {
664				if($interfaces{$curif}{usergraph}) {
665					$interfaces{$curif}{withtotal} = 0 ;
666				} else {
667					$interfaces{$curif}{total} = 0 ;
668				}
669				next;
670			}
671			$interfaces{$curif}{percentile} = 0 if( $k eq "nopercentile");
672			if( $k eq "summary" ) {
673				$interfaces{$curif}{summary} = 1;
674				$interfaces{$curif}{compact} = 0;
675				$interfaces{$curif}{withtotal} = 0;
676				$interfaces{$curif}{withaverage} = 0;
677				$interfaces{$curif}{insummary} = 0 ;
678				$interfaces{$curif}{incompact} = 0 ;
679				next;
680			}
681			if( $k eq "compact" ) {
682				$interfaces{$curif}{summary} = 0;
683				$interfaces{$curif}{compact} = 1;
684				$interfaces{$curif}{withtotal} = 0;
685				$interfaces{$curif}{withaverage} = 0;
686				$interfaces{$curif}{insummary} = 0;
687				$interfaces{$curif}{incompact} = 0;
688				next;
689			}
690			if( $k eq "total") {
691				if($interfaces{$curif}{usergraph}) {
692					$interfaces{$curif}{withtotal} = 1 ;
693				} else {
694					$interfaces{$curif}{total} = 1 ;
695				}
696				next;
697			}
698			if( $k eq "aspercent") {
699				 $interfaces{$curif}{aspercent} = 1;
700				 $interfaces{$curif}{fixunits} = 1;
701				 $interfaces{$curif}{percent} = 0;
702				 $interfaces{$curif}{bytes} = 1;
703				 $interfaces{$curif}{bits} = 0;
704				 $interfaces{$curif}{total} = 0;
705				 $interfaces{$curif}{percentile} = 0;
706				 $interfaces{$curif}{perminute} = 0;
707				 $interfaces{$curif}{perhour} = 0;
708				 $interfaces{$curif}{withtotal} = 0;
709				 $interfaces{$curif}{noabsmax} = 1;
710				 $interfaces{$curif}{mblegend} = '';
711				 $interfaces{$curif}{unit} = '%';
712				 $interfaces{$curif}{totunit} = '';
713				 $interfaces{$curif}{ylegend} = 'percentage';
714				 $interfaces{$curif}{mode} = 'percent';
715				next;
716			}
717			$interfaces{$curif}{withaverage} = 1 if( $k eq "average");
718			$interfaces{$curif}{nolegend} = 1 if( $k eq "nolegend");
719			$interfaces{$curif}{nodetails} = 1 if( $k eq "nodetails");
720			$interfaces{$curif}{nomax} = 1 if( $k eq "nomax");
721			$interfaces{$curif}{noabsmax} = 1 if( $k eq "noabsmax");
722			$interfaces{$curif}{percent} = 0 if( $k eq "nopercent");
723			$interfaces{$curif}{integer} = 1 if( $k eq "integer");
724			$interfaces{$curif}{'reverse'} = 1 if( $k eq "reverse");
725			$interfaces{$curif}{rigid} = 1 if( $k eq "rigid");
726			if( $k =~ /^#[\da-fA-F]{6}$/ ) {
727				$interfaces{$curif}{colours} = []
728					if(!defined $interfaces{$curif}{colours});
729				push @{$interfaces{$curif}{colours}}, $k;
730				next;
731			}
732			$interfaces{$curif}{fixunits} = 1
733				if( $k =~ /^fixunits?/i or $k =~ /^nounits?/i );
734		  }
735		}
736		# fix the mult
737		if($interfaces{$curif}{bytes}) {
738			$interfaces{$curif}{mult} = 1;
739		} elsif($interfaces{$curif}{bits} ) {
740			$interfaces{$curif}{mult} = 8;
741		}
742		if( $interfaces{$curif}{isif} and !$interfaces{$curif}{mult} ) {
743			$interfaces{$curif}{mult} = 8;
744		}
745		if($interfaces{$curif}{perminute}) {
746			$interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult});
747			$interfaces{$curif}{mult} *= 60;
748		} elsif($interfaces{$curif}{perhour}) {
749			$interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult});
750			$interfaces{$curif}{mult} *= 3600;
751		}
752		# sanity check
753		if( $interfaces{$curif}{incompact} and !$interfaces{$curif}{maxbytes}){
754			$interfaces{$curif}{incompact} = 0;
755		}
756		$interfaces{$curif}{mult}=1 if(!$interfaces{$curif}{mult});
757		$interfaces{$curif}{factor}=1 if(!$interfaces{$curif}{factor});
758		# calculate RRD filename
759		if(!$interfaces{$curif}{usergraph}) {
760			$rrd = $workdir;
761			$rrd .= $pathsep.$interfaces{$curif}{directory}
762				if($interfaces{$curif}{directory});
763			$rrd .= $pathsep.lc($interfaces{$curif}{target}).".rrd";
764			$interfaces{$curif}{rrd} = $rrd;
765		}
766	}
767
768	# now read the corresponding .ok file, if it exists
769	$cfgfile =~ s/\.conf$/.ok/;
770	$cfgfile =~ s/\.cfg$/.ok/;
771	if( open OK, "<$cfgfile" )  {
772		my( %ifdesc ) = ();
773		my( %ifip ) = ();
774		while( <OK> ) {
775			if( /\tDescr\t(.+)\t(\d+)/ ) {
776				$ifdesc{$2} = $1; $ifdesc{$1} = $2;
777			}
778			if( /\tIp\t(.+)\t(\d+)/ ) {
779				$ifip{$2} = $1; $ifip{$1} = $2;
780			}
781		}
782		close OK;
783
784		foreach $curif ( @myifs ) {
785		if(!defined $interfaces{$curif}{ifno}) {
786			$interfaces{$curif}{ifno} = $ifdesc{$interfaces{$curif}{ifdesc}}
787			if(defined $interfaces{$curif}{ifdesc}
788				and defined $ifdesc{$interfaces{$curif}{ifdesc}});
789			$interfaces{$curif}{ifno} = $ifip{$interfaces{$curif}{ipaddress}}
790			if(defined $interfaces{$curif}{ipaddress}
791				and defined $ifip{$interfaces{$curif}{ipaddress}});
792		}
793		if(defined $interfaces{$curif}{ifno}) {
794			$key = $interfaces{$curif}{ifno};
795			$interfaces{$curif}{ifdesc} = $ifdesc{$key}
796			if(defined $ifdesc{$key} and !defined $interfaces{$curif}{ifdesc});
797			$interfaces{$curif}{ipaddress} = $ifip{$key}
798			if(defined $ifip{$key} and !defined $interfaces{$curif}{ipaddress});
799		}
800		}
801	} # ok file exists
802}
803
804#############################################################################
805
806#############################################################################
807
808sub slidexml($) {
809	my($dwmy) = $_[0];
810	my($refresh) = 300;
811
812	print "<object>";
813	print "<image url='$ROUTERSCGI?rtr=$DEVICE&if=$TARGET&page=image&xgtype=".$dwmy."s&xgstyle=x3D' fill='center' x='0' y='15' width='$WIDTH' height='".($HEIGHT-15)."' state='hit' />\n";
814	print "<slide duration='10' /><transition_in type='fade' /><transition_out type='fade' />\n" if(!$OBJECT);
815
816	print "<action>";
817	print "<item type='link' url='$ROUTERSCGI?if=$TARGET&rtr=$DEVICE&xgtype=$dwmy' target='mrtgwindow' target_shift='_blank' />\n";
818	print "</action>\n";
819	print "<tooltip fill_alpha='0.7' >Click for MRTG</tooltip>\n";
820
821	$refresh = 300 if($dwmy eq 'd');
822	$refresh = 1800 if($dwmy eq 'w');
823	$refresh = 7200 if($dwmy eq 'm');
824
825	print "<update url='$URL?cfg=$DEVICE&target=$TARGET"
826		.($OBJECT?"&object=1&x=$XOFF&y=$YOFF":"")
827		.($REGISTERED?"&license=$REGISTERED":"")
828		."&width=$WIDTH&dwmy=$dwmy&t=".time
829		."' delay='$refresh' ".($MODE?"":"delay_type='1'")
830		." retry='2' timeout='15' />\n" if($refresh);
831	print "</object>";
832}
833
834sub outputxml() {
835	my($x,$c);
836	my($curif);
837	my(@subifs);
838	my($legend) = '';
839	my($legendxml) = '';
840	my($clr,@clr);
841	my($ypos);
842
843	if($MODE) {
844		if(!$OBJECT) {
845			print "<slickboard>\n";
846			if($REGISTERED) {
847				print "<license><string>$REGISTERED</string></license>\n";
848				print "<context_menu>
849<item label_a='Version' />
850<item label_a='About graphxml' />
851<item label_a='About MRTG' />
852<item label_a='About SlickBoard' />
853<item type='separator' />
854<item label_a='Full Screen' label_b='Normal view' type='toggle_screen' />
855<item label_a='Print Gauge' />
856</context_menu>\n";
857				print "<action>
858<item event='context_1' type='alert' text='gaugexml3.cgi $VERSION%0DMore information at:%0Dhttp://www.steveshipway.org/graphxml'  />
859<item event='context_2' type='link' url='http://www.steveshipway.org/graphxml' target='_self' target_shift='_new' />
860<item event='context_3' type='link' url='http://www.mrtg.org/' target='_self' target_shift='_new' />
861<item event='context_4' type='link' url='http://www.maani.us/slickboard' target='_self' target_shift='_new' />
862<item event='context_6' type='toggle_screen'  />
863<item event='context_7' type='print'  />
864</action>";
865			}
866		} else {
867			print "<object>\n";
868		}
869#		print "<object>\n"; # slideshow doesnt work within object
870        print "<rect x='$XOFF' y='$YOFF' width='".($WIDTH-1)."' height='".($HEIGHT-1)."' state='hit' fill_alpha='0.5' fill_color='cccccc' line_alpha='1' line_thickness='1' />\n" if($OBJECT);
871
872	} else { print "<gauge>\n"; }
873
874	# Graphs
875	foreach ( qw/d w m y/ ) {
876		next if($interfaces{$TARGET}{suppress}
877			and $interfaces{$TARGET}{suppress}=~/$_/);
878		slidexml($_);
879		last if($OBJECT); # we only have one in this case
880	}
881
882	print "<text x='$x' y='0' width='$WIDTH' height='15' size='12' align_h='center' >".$interfaces{$TARGET}{desc}."</text>\n";
883
884	# Controller drawers
885	if(!$OBJECT) {
886	$x=10; $c=1;
887	foreach ( qw/daily weekly monthly yearly/ ) {
888		next if($interfaces{$TARGET}{suppress} and /^([dwmy])/
889			and $interfaces{$TARGET}{suppress}=~/$1/);
890		print "<object>";
891		print "<rect x='$x' y='-20' width='50' height='25' fill_color='FF6600' corner_bl='5' corner_br='5' state='hit' /> \n";
892		print "<text x='$x' y='-20' width='50' height='20' size='10' alpha='.6' align_h='center' shadow='low' >$_</text>\n";
893		print "<drawer type='down' depth='20' handle_back='5' handle_front='15' />\n";
894		print "<action>";
895		print "<item event='click' type='slideshow_jump' slide='$c' instant='false'  />\n";
896#		print "<item event='click' type='slideshow_pause' />";
897		print "</action>\n";
898		print "</object>\n";
899		$x += 55; $c += 1;
900	}
901	print "<object id='play' >";
902	print "<rect x='$x' y='-20' width='50' height='25' fill_color='FF0066' corner_bl='5' corner_br='5' state='hit' /> \n";
903	print "<text x='$x' y='-20' width='50' height='20' size='10' alpha='.6' align_h='center' shadow='low' state='checked' >Cycle</text>\n";
904	print "<text x='$x' y='-20' width='50' height='20' size='10' alpha='.6' align_h='center' shadow='low' state='unchecked' >Pause</text>\n";
905	print "<drawer type='down' depth='20' handle_back='5' handle_front='15' />\n";
906	print "<action>";
907	print "<item event='click' type='slideshow_toggle' />";
908	print "</action>\n";
909	print "</object>\n"; #play button
910	} # not embedded
911
912	# now the legend drawer
913	$curif = $TARGET;
914    if( !defined $interfaces{$curif}
915        and defined $interfaces{"_$curif"} )  {
916        $curif = "_$curif";
917    }
918	if($interfaces{$curif}{usergraph}) {
919        @subifs = @{$interfaces{$curif}{targets}};
920        $interfaces{$curif}{ylegend} = $interfaces{$interfaces{$curif}{targets}[0]}{ylegend} if(!$interfaces{$curif}{ylegend});
921    } else { @subifs = ( $curif ); }
922    $interfaces{$curif}{colours} = [ @defcolours ]
923        if(!defined $interfaces{$curif}{colours});
924	$ypos = 25;
925	foreach my $subif ( @subifs ) {
926			if(! $interfaces{$subif}{noi} and !$interfaces{$curif}{noi} ) {
927				@clr = @{$interfaces{$curif}{colours}} if(!@clr); # reset
928				$clr = shift @clr; $clr =~ s/#//g;
929				print "This Colour=$clr\n" if($DEBUG);
930				if($interfaces{$curif}{usergraph}) {
931					$legend = $interfaces{$subif}{shdesc};
932					if(! $interfaces{$subif}{noo} and !$interfaces{$curif}{noo}) {
933						$legend = $interfaces{$subif}{shdesc};
934						$legend = $interfaces{$subif}{desc} if(!$legend);
935						$legend = $subif if(!$legend);
936						$legend .= "(".($interfaces{$subif}{legend1}?$interfaces{$subif}{legend1}:"Inbound").")";
937					} else {
938						$legend = $interfaces{$subif}{desc};
939						$legend = $interfaces{$subif}{shdesc} if(!$legend);
940						$legend = $subif if(!$legend);
941					}
942				} elsif( $interfaces{$subif}{noo} or $interfaces{$curif}{noo}){
943					$legend = "";
944				} else {
945					$legend = $interfaces{$subif}{legend1};
946					$legend = "Inbound traffic" if(!$legend);
947				}
948				if($legend) {
949					$legendxml .= "<circle x='".($WIDTH+10)."' y='".($ypos+10)."' radius='5' fill_color='$clr' line_thickness='1' />";
950					$legendxml .= "<text x='".($WIDTH+15)."' y='$ypos' width='".($WIDTH/2-20)."' height='10' align_h='left' bold='false' word_wrap='false' >$legend</text>\n";
951					$ypos += 15;
952				}
953			}
954			if(! $interfaces{$subif}{noo} and !$interfaces{$curif}{noo} ) {
955				@clr = @{$interfaces{$curif}{colours}} if(!@clr); # reset
956				$clr = shift @clr; $clr =~ s/#//g;
957				if($interfaces{$curif}{usergraph}) {
958					if(! $interfaces{$subif}{noi} and !$interfaces{$curif}{noi} ) {
959						$legend = $interfaces{$subif}{shdesc};
960						$legend = $interfaces{$subif}{desc} if(!$legend);
961						$legend = $subif if(!$legend);
962						$legend .= "(".($interfaces{$subif}{legend2}?$interfaces{$subif}{legend2}:"Outbound").")";
963					} else {
964						$legend = $interfaces{$subif}{desc};
965						$legend = $interfaces{$subif}{shdesc} if(!$legend);
966						$legend = $subif if(!$legend);
967					}
968				} elsif( $interfaces{$subif}{noi} or $interfaces{$curif}{noi}){
969					$legend = "";
970				} else {
971					$legend = $interfaces{$subif}{legend2};
972					$legend = "Outbound traffic $TARGET $curif $subif -" if(!$legend);
973				}
974				if($legend) {
975					$legendxml .= "<circle x='".($WIDTH+10)."' y='".($ypos+10)."' radius='5' fill_color='$clr' line_thickness='1' />";
976					$legendxml .= "<text x='".($WIDTH+15)."' y='$ypos' width='".($WIDTH/2-20)."' height='10' align_h='left' bold='false' word_wrap='false' >$legend</text>\n";
977					$ypos += 12;
978				}
979			}
980	}
981
982	print "<object>";
983	print "<rect x='".($WIDTH-15)."' y='20' width='".($WIDTH/2 + 20)."' height='".($HEIGHT-40)."' fill_color='FFFFFF' line_thickness='1' corner_tl='5' corner_bl='5' /> \n";
984	print "<text x='".($WIDTH-15)."' y='".($HEIGHT-20)."' height='15' width='".($HEIGHT-40)."' size='10' alpha='.6' align_h='center' shadow='low' rotation='-90' >Legend</text>\n";
985	print $legendxml;
986	print "<drawer type='left' depth='".($WIDTH/2)."' handle_back='15' handle_front='20' />\n";
987	print "</object>\n";
988	print "<rect x='$WIDTH' y='20' width='".($WIDTH/2 + 20)."' height='".($HEIGHT-40)."' fill_color='cccccc' line_thickness='0' /> \n";
989
990	if($MODE) {
991#		print "<update url='$URL?cfg=$DEVICE&target=$TARGET"
992#			.($OBJECT?"&object=1&x=$XOFF&y=$YOFF":"")
993#			.($REGISTERED?"&license=$REGISTERED":"")
994#			."&width=$WIDTH&dwmy=$dwmy&t=".time
995#			."' delay='300' ".($MODE?"":"delay_type='1'")
996#			." retry='2' timeout='15' />\n";
997		print "</object>\n" if($OBJECT);
998		print "</slickboard>\n" if(!$OBJECT);
999	} else {
1000		print "<gauge>\n";
1001	}
1002}
1003sub blankgauge {
1004	my($msg) = $_[0];
1005	$msg = "Error" if(!$msg);
1006	print $q->header(-expires=>"now",-type=>"text/xml",-pragma=>"nocache");
1007	if($MODE) {
1008		print "<slickboard>\n" if(!$OBJECT);
1009		print "<object><text x='0' y='0' word_wrap='1' width='$WIDTH' >$msg</text></object>\n";
1010		print "</slickboard>\n" if(!$OBJECT);
1011	} else {
1012		print "<gauge>\n<comment value='$msg' />\n</gauge>\n";
1013	}
1014
1015}
1016# Test for approved cfg files.
1017sub cfgok($) {
1018	my($c) = $_[0];
1019	return 1 if($c =~ /$PUBLICCFG/);
1020	return 0;
1021}
1022sub justobject($) {
1023	slidexml($_[0]);
1024}
1025#############################################################################
1026# MAIN
1027
1028$REGISTERED=$q->param('license') if($q->param('license'));
1029$DEVICE=$q->param('cfg');
1030$TARGET=$q->param('target')   if($q->param('target'));
1031$WIDTH=$q->param('width')     if($q->param('width'));
1032$URL    = $q->param('url')    if($q->param('url'));
1033$OBJECT = $q->param('object') if($q->param('object'));
1034
1035if( ($q->url() =~ /$PUBLICURL/) and !cfgok($DEVICE)) {
1036	blankgauge("Illegal request");
1037	exit(0);
1038}
1039if( ! -f $CFGDIR.$pathsep.$DEVICE ) {
1040	blankgauge("File $CFGDIR$pathsep$DEVICE does not exist");
1041	exit(0);
1042}
1043readcfg( $CFGDIR.$pathsep.$DEVICE );
1044delete $interfaces{'$'};
1045delete $interfaces{'_'};
1046delete $interfaces{'^'};
1047$TARGET = (sort keys %interfaces)[0] if(!$TARGET);
1048print $q->header(-expires=>"now",-type=>"text/xml",-pragma=>"nocache");
1049if($q->param('dwmy')) { # for refresh of graph object
1050	justobject($q->param('dwmy'));
1051} else {
1052	outputxml;
1053}
1054exit(0);
1055