]> git.etc.gen.nz Git - spong.git/commitdiff
xhtml and much more
authorMichael Arndt <scriptkiller@gmx.de>
Tue, 15 Nov 2005 10:11:43 +0000 (10:11 +0000)
committerMichael Arndt <scriptkiller@gmx.de>
Tue, 15 Nov 2005 10:11:43 +0000 (10:11 +0000)
src/www-spong.pl

index 15259697613fbde3e8752ae7dd915b251aac5409..90d076bd50a4e6f883e11ff53110bcc0b9cf1fdc 100755 (executable)
@@ -11,8 +11,9 @@
 # (2) Re-did in a more generic and OO way (Ed Hill, May 9, 1997)
 # (3) Re-did as a client which gets info from the spong-server (07/24/1997)
 # (4) Did a whole bunch of stuff (Ed Hill, 06/18/1998)
+# (5) Valid XHTML output, 2 frames output, cleanups (Michael Arndt, 11/15/2005)
 #
-# $Id: www-spong.pl,v 1.23 2003/07/27 03:40:17 sljohnson Exp $
+# $Id: www-spong.pl,v 1.24 2005/11/15 10:11:43 scriptkiller Exp $
 
 use lib "@@LIBDIR@@";
 
@@ -74,8 +75,8 @@ if( $ENV{'SCRIPT_NAME'} eq "" ) {
    if( defined $opt{'full'} )     { $view = "full"; }
 
    if( defined $opt{'problems'} ) { &problems( $opt{'problems'} ); $opt = 1; }
-   if( defined $opt{'summary'} )  { &summary( $opt{'summary'} );   $opt = 1; }
-   if( defined $opt{'history'} )  { &history( $opt{'history'} );   $opt = 1; }
+   if( defined $opt{'summary'} )  { &summary( 0, $opt{'summary'} ); $opt = 1; }
+   if( defined $opt{'history'} )  { &history( 0, $opt{'history'} ); $opt = 1; }
 
    if( defined $opt{'host'} )     { &host( $opt{'host'} );         $opt = 1; }
    if( defined $opt{'services'} ) { &services( $opt{'services'} ); $opt = 1; }
@@ -95,10 +96,10 @@ if( $ENV{'SCRIPT_NAME'} eq "" ) {
       $opt=1;
    }
 
-   if ( defined $opt{'grp-summary'} ) { &grp_summary( $opt{'grp-summary'} ); $opt= 1; } 
-   if ( defined $opt{'grp-problems'} ) { &grp_problems( $opt{'grp-problems'} ); $opt= 1; } 
+   if ( defined $opt{'grp-summary'} ) { &grp_summary( 0, $opt{'grp-summary'} ); $opt= 1; } 
+   if ( defined $opt{'grp-problems'} ) { &grp_problems( 0, $opt{'grp-problems'} ); $opt= 1; } 
 
-   if( ! $opt ) { &summary( "all" ); }
+   if( ! $opt ) { &summary( 0, "all" ); }
 
    exit(0);
 }
@@ -116,19 +117,23 @@ $cmd = $ENV{'PATH_INFO'};
 # These commands control the frame interface, etc...
 
 if( $cmd eq "" || $cmd eq "/" )   {
-   if ($WWWFRAMES == 3) { &toplevel(); }
-   else {
-      &interactive( "all" ) if $main::WWW_DEFAULT_VIEW eq "HOSTS";
-      &ovinteractive( "all" ) if $main::WWW_DEFAULT_VIEW eq "GROUPS";
-   }
-   exit;
+    toplevel_interactive($main::WWW_DEFAULT_VIEW, "all");
+    exit;
 }
+
 if ($cmd =~ m!^/title$! )          { &title(); exit; } 
 
-if( $cmd =~ m!^/group/(.*)$! )    { &interactive( $1 );    exit; }
-if( $cmd =~ m!^/bygroup/(.*)$! )    { &ovinteractive( $1 );    exit; }
+if( $cmd =~ m!^/group/(.*)$! )    { &toplevel_interactive( "HOSTS", $1 ); exit; }
+
+# note the "" as argument! this will activate "by-group" instead of "group"
+if( $cmd =~ m!^/bygroup/(.*)$! )    { &toplevel_interactive( "GROUPS", "" ); exit; }
+
 if( $cmd =~ m!^/commands/(.*)$! ) { &commands( $1 );       exit; }
 
+# see sub availability, argument is target-frame
+if( $cmd =~ m!^/availability/(.*)$! ) { &availability( $1 ); exit; }
+
+
 if( $cmd =~ m!^/ovcommands/(.*)$! ) { &ovcommands( $1 );   exit; }
 if( $cmd =~ m!^/igrp-summary/(.*)$! ) { &igrp_summary( $1 );   exit; }
 if( $cmd =~ m!^/igrp-overview/(.*)$! ) { &igrp_overview( $1 );   exit; }
@@ -150,8 +155,8 @@ if( $cmd =~ m!^/standard/(.*)$! ) { $view = "standard"; $cmd = "/$1"; }
 if( $cmd =~ m!^/full/(.*)$! )     { $view = "full";     $cmd = "/$1"; }
 
 if( $cmd =~ m!^/problems/(.*)$! ) { &problems($1); exit;}
-if( $cmd =~ m!^/summary/(.*)$! )  { &summary($1);  exit;}
-if( $cmd =~ m!^/history/(.*)$! )  { &history($1);  exit;}
+if( $cmd =~ m!^/summary/(.*)$! )  { &summary(0, $1);  exit;}
+if( $cmd =~ m!^/history/(.*)$! )  { &history(0, $1);  exit;}
 
 if( $cmd =~ m!^/host/(.*)$! )     { &host($1);     exit;}
 if( $cmd =~ m!^/services/(.*)$! ) { &services($1); exit;}
@@ -163,8 +168,8 @@ if( $cmd =~ m!^/service/(.*)/(.*)$! ) { &service( $1, $2 ); exit; }
 
 if( $cmd =~ m!^/histservice/(.*)/(.*)/(.*)$! ) { &histservice( $1, "$2 $3" ); exit; }
 
-if( $cmd =~ m!^/grp-summary/(.*)$! ) { &grp_summary( $1 ); exit;}
-if( $cmd =~ m!^/grp-problems/(.*)$! ) { &grp_problems( $1 ); exit;}
+if( $cmd =~ m!^/grp-summary/(.*)$! ) { &grp_summary( 0, $1 ); exit;}
+if( $cmd =~ m!^/grp-problems/(.*)$! ) { &grp_problems( 0, $1 ); exit;}
 
 # Need to do something when an invalid request comes through...
 exit(0);
@@ -179,92 +184,172 @@ exit(0);
 # commands & error summary information is shown, and the frame for more 
 # detailed host information.
 
+# include stylesheet-link to xhtml-stream
+sub insert_stylesheet {
+    print "<link rel=\"stylesheet\" type=\"text/css\" ".
+       "href=\"$main::WWWDOCS/style.css\" />\n";
+}
 
-sub toplevel {
+# include some meta tags to xhtml-stream
+sub insert_meta {
+    print "<meta name=\"generator\" content=\"Spong v$SPONGVER\" />\n";
+}
 
-   # Default to a reasonable value if not defined.
-   $main::WWW_TITLE_SIZE = 40 if( $main::WWW_TITLE_SIZE <= 0 ); 
+# insert 2 links, one pointing to Hosts-View and one to Groups-View
+sub insert_view_switch {
+    print "<hr />\n";
+    print "<span class=\"form_property\">Views: </span>\n";
+    print "<a href=\"$main::WWWSPONG/bygroup/\" target=\"_top\">Groups</a> || \n";
+    print "<a href=\"$main::WWWSPONG/group/all\" target=\"_top\">Hosts</a> \n";
+}
 
-   print "Content-type: text/html\n\n";
-   print "<html><head>\n";
-   print "<title>Spong v$SPONGVER - System Status Monitor</title></head>\n";
-   print "<frameset rows=\"$main::WWW_TITLE_SIZE,*\" border=5 frameboard=no>";
-   print "<frame src=\"$main::WWWSPONG/title\" marginwidth=5 ";
-   print "marginheight=5 noshade name=\"title\">\n";
-   print "<frame src=\"";
+# insert link to configure shown group and the name
+# of the currently shown group
+# call as insert_group_info($groupname)
+sub insert_group_info {
 
-   print "$main::WWWSPONG/bygroup/" if $main::WWW_DEFAULT_VIEW eq "GROUPS";
-   print "$main::WWWSPONG/group/all" if $main::WWW_DEFAULT_VIEW eq "HOSTS";
+    my $gname=shift;
+
+    print "<hr />\n";
+    print "<a href=\"$main::WWWSPONG/groups\">Group</a>:\n";
+    print "<span class=\"form_property\">$gname</span>\n";
+    print "<hr />\n";
 
-   print "\" marginwidth=10 ";
-   print "marginheight=5 noshade name=\"view\" border=1>\n";
-   print "</frameset>\n";
-   print "<noframe>\n";
-   print "Frameless version not currently available.\n";
-   print "</noframes>\n</html>\n";
 }
 
-sub interactive { 
-   my $group = shift;
+# insert a "Updated at ..." text with current time and date
+sub insert_updated_time {
 
-   print "Content-type: text/html\n\n";
-   print "<html><head>\n";
-   print "<title>Spong v$SPONGVER - System Status Monitor</title></head>\n";
-   print "<frameset cols=\"240,*\" border=5 frameboard=no>";
-   print "<frame src=\"$main::WWWSPONG/commands/$group\" marginwidth=5 ";
-   print "marginheight=5 noshade>\n";
-   print "<frame src=\"$main::WWWSPONG/isummary/$group\" marginwidth=10 ";
-   print "marginheight=5 noshade name=\"right\" border=1>\n";
-   print "</frameset>\n";
-   print "<noframe>\n";
-   print "Frameless version not currently available.\n";
-   print "</noframes>\n</html>\n";
-}
-
-sub ovinteractive { 
-   my $group = shift;
+    print "Updated at ", POSIX::strftime( "$TIMEFMTNOSEC, on $DATEFMT", localtime() ), "\n";
 
-   print "Content-type: text/html\n\n";
-   print "<html><head>\n";
-   print "<title>Spong v$SPONGVER - System Status Monitor</title></head>\n";
-   print "<frameset cols=\"240,*\" border=5 frameboard=no>";
-   print "<frame src=\"$main::WWWSPONG/ovcommands/\" marginwidth=5 ";
-   print "marginheight=5 noshade>\n";
+}
 
-   if ($main::WWW_OVERVIEW == 1) {
-      print "<frame src=\"$main::WWWSPONG/igrp-overview/\" marginwidth=10 ";
-   } else {
-      print "<frame src=\"$main::WWWSPONG/igrp-summary/\" marginwidth=10 ";
-   }
+# Generate suiting framesets according to $WWWFRAMES config value
+# in interactive mode.
+# Viewtype may be "GROUPS" or "HOSTS"
+# Viewoptions is for example "all" or a group-/hostname
+#
+# toplevel_interactive($viewtype, $viewoptions)
+sub toplevel_interactive {
+
+    my $viewtype=shift;
+    my $viewoptions=shift;
+
+
+    # build links for frameset and noframes version
+    my ($link1, $link2)=("", "");
+    
+    if($viewtype eq "HOSTS") {
+       $link1="commands/$viewoptions";
+       $link2="isummary/$viewoptions";
+    }
+    elsif($viewtype eq "GROUPS") {
+       $link1="ovcommands/"; # no viewoptions here
+       $link2="igrp-summary/$viewoptions";
+    }
+
+
+    # 1 frame
+    if($main::WWWFRAMES == 1) {
+       # we don't even need a frameset here
+
+       # redirect directly to spong-page
+       print "Location: $main::WWWSPONG/$link2\r\n";
+
+       # user should not see everything below here:
+       &header(0, "Spong Redirect");
+       print "<a href=\"$main::WWWSPONG/$link2\">Please go here ...</a>\n";
+       &footer();
+       
+    }
+    # more than 1 frame (means: 2 or 3 frames ..)
+    elsif($main::WWWFRAMES > 1) {
+       
+       # build frameset
+       print "Content-type: text/html\r\n\r\n";
+       print '<?xml version="1.0" encoding="ISO-8859-1"?>',"\n";
+       print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" '.
+           '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',"\n";
+       print '<html xmlns="http://www.w3.org/1999/xhtml">',"\n";
+       print "<head>\n";
+       &insert_stylesheet();
+       &insert_meta();
+       print "<title>Spong v$SPONGVER - System Status Monitor</title></head>\n";
+
+
+       # if we have 3 frames add outer-frameset with
+       # title-frame now
+       if($main::WWWFRAMES == 3) {
+           print "<frameset rows=\"$main::WWW_TITLE_SIZE,*\" border=\"5\"";
+           print " frameborder=\"0\">\n";
+
+           print "<frame src=\"$main::WWWSPONG/title\" marginwidth=\"5\" ";
+           print "marginheight=\"5\" noshade=\"noshade\" name=\"title\" />\n";
+
+       }
+
+       # 2 (inner-) frames
+       print " <frameset cols=\"240,*\" border=\"5\" frameborder=\"no\">\n";
+       
+       print "  <frame src=\"$main::WWWSPONG/$link1\" marginwidth=\"5\"";
+       print "   marginheight=\"5\" noshade=\"noshade\" name=\"left\" />\n";
+       
+       print "  <frame src=\"$main::WWWSPONG/$link2\" marginwidth=\"10\"";
+       print "   marginheight=\"5\" noshade=\"noshade\" name=\"right\"";
+       print "   border=\"1\" />\n";
+       
+       print " </frameset>\n";
+       
+
+       # close outer frameset if neccessary
+       if($main::WWWFRAMES == 3) {
+           print "</frameset>\n";
+       }
+
+       print "<noframe>\n";
+       print "For a frameless version set \$WWWFRAMES to 1, please!\n";
+       print "</noframes>\n";
+       print "</html>\n";
+
+
+    }
 
-   print "marginheight=5 noshade name=\"right\" border=1>\n";
-   print "</frameset>\n";
-   print "<noframe>\n";
-   print "Frameless version not currently available.\n";
-   print "</noframes>\n</html>\n";
 }
 
+
 # This function fills out the Title header. It had a command bar that changes
 # the the current View type in the 'view' frame
 
 sub title {
-   &header(0);
+
+   &header(0, "Title Frame");
 
    my $me = $main::WWWSPONG;
 
-   print "<base target=view>\n";
-#   print "<center>";
-   print "<font size=+2><b>Spong v$SPONGVER</b></font>\n";
-#   print "</center>\n";
-#   print "<br>";
-   print "<a href=\"$me/bygroup/\">Groups</a> || \n"; 
-   print "<a href=\"$me/group/all\">Hosts</a> \n"; 
+   print "<table class=\"spong_mainheader\">\n";
+   print " <tr class=\"spong_mainheader\">\n";
+   print "  <td>\n";
+   print "   <h1>Spong v$SPONGVER &nbsp;</h1>\n";
+   print "  </td>\n";
+   print "  <td>\n";
+
+
+   # TODO: combine with insert_view_switch ?
+   print "<a href=\"$me/bygroup/\" target=\"_top\">Groups</a> || \n"; 
+   print "<a href=\"$me/group/all\" target=\"_top\">Hosts</a> \n"; 
 
 #   print "<b>Extra Tool Bar Commands:</b> ";
 #   print " <a href=\"/spong-rrd/index.html\">Spong RRD Charts</a>\n";
 #   print " || <a href=\"/cgi-bin/sysquery.pl?target=showall\">System Summaries</a>\n";
 
    if ( $main::WWW_TITLE_ACTIONBAR ) { print $main::WWW_TITLE_ACTIONBAR,"\n"; }
+
+   print "  </td>\n";
+   print " </tr>\n";
+   print "</table>\n";
+
+   &footer();
+
 }
 
 
@@ -279,67 +364,110 @@ sub commands {
    my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
    $gname = "Selected Hosts" unless $gname;
     
-   &header( 1 );
+   &header( 1, "Action Bar" );
+
+
+   # why we don't use <base> here anymore:
+   # - because it is only allowed within <head></head>
 
-   print "<base target=right>\n";
 #   print "<font size=+2><b>Spong v$SPONGVER</b></font>\n";
-   print "<font size=+2><b>Hosts View</b></font>\n";
-   unless ($WWWFRAMES == 3) {
-      print "<hr>\n";
-      print "<b>Views:</b> <a href=\"$me/bygroup/\" target=_top>Groups</a>";
-      print " || \n<a href=\"$me/group/all\" target=_top>Hosts</a> \n"; 
+#   print "<font size=+2><b>Hosts View</b></font>\n";
+   print "<h2>Hosts View</h2>\n";
+
+   # If we don't have a top frame with these links, must add links here
+   # to switch between Hosts-View- and Groups-View-Mode.
+   if ($main::WWWFRAMES != 3) {
+       &insert_view_switch();
    }
-   print "<hr>\n";
 
-   print "<a href=\"$main::WWWACK/$group\">Ack</a> || \n"; 
-   print "<a href=\"$me/isummary/$group\">Summary</a> || \n"; 
-   print "<a href=\"$me/ihistory/$group\">History</a> || \n"; 
-   print "<a href=\"$me/help\">Help</a>\n";
-   print "<hr>\n<p>\n";
+   print "<hr />\n";
+
+   print "<a href=\"$main::WWWACK\" target=\"right\">Ack</a> || \n"; 
+   print "<a href=\"$me/isummary/$group\" target=\"right\">Summary</a> || \n"; 
+   print "<a href=\"$me/ihistory/$group\" target=\"right\">History</a> || \n"; 
+   print "<a href=\"$me/help\" target=\"right\">Help</a>\n";
+   print "<hr />\n";
+   print "<br />\n";
+
 
    &problems( $group );
 
-   print "<p><hr><a href=\"$me/groups\">Group</a>: <b>$gname</b>\n<hr>\n";
-   print "Updated at ", POSIX::strftime( "$TIMEFMTNOSEC, on $DATEFMT", localtime() ), "\n";
+   &insert_group_info($gname);
+   &insert_updated_time();
+
    &footer();
 }
 
+# This function generates a page that can easily included in custom projects.
+# It show all hosts with problems follewed by a list of all monitored hosts.
+#
+# Also a target-frame-name can be specified, all other spong-pages will be
+# displayed in that frame.
+sub availability {
+
+    my $target=shift;
+
+    # 1: do reload regulary
+    &header(1, "Spong availability");
+
+    print "<h2>Availability:</h2>\n";
+    print "<hr />\n";
+    print "<br />\n";
+
+    print "<h3>Problems:</h3>\n";
+
+    &problems("all");
+
+    print "<br />\n";
+    print "<hr />\n";
+
+    print "<h3>Host List:</h3>\n";
+
+    # make a query with format set to "names_only", so that there
+    # will only be a table with host-names inside beeing sent to output
+    print &query( $SPONGSERVER, "summary", "all", "html", "names_only" ); 
+
+    print "<br />\n";
+    print "<hr />\n";
+
+    &footer();
+
+}
 
 sub ovcommands {
    my $group = shift;
    my $me = $main::WWWSPONG;
 
    $group = "all" unless $group;
-#   my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
-#   $gname = "Selected Hosts" unless $gname;
+   my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
+   $gname = "Selected Hosts" unless $gname;
     
-   &header( 1 );
+   &header( 1, "Groups View" );
 
-   print "<base target=right>\n";
-#   print "<font size=+2><b>Spong v$SPONGVER</b></font>\n";
-   print "<font size=+2><b>Groups View</b></font>\n";
-   unless ($WWWFRAMES == 3) {
-      print "<hr>\n";
-      print "<b>Views: </b><a href=\"$me/bygroup/\" target=_top>Groups</a> || \n"; 
-      print "<a href=\"$me/group/all\" target=_top>Hosts</a> \n"; 
+   print "<h2>Groups View</h2>\n";
+
+   if($main::WWWFRAMES != 3) {
+       &insert_view_switch();
    }
-   print "<hr>\n";
+   print "<hr />\n";
+
+   print "<a href=\"$me/igrp-summary/\" target=\"right\">Groups</a> || \n"; 
+   print "<a href=\"$me/igrp-overview/\" target=\"right\">Group Summary</a>\n"; 
+   print "<hr />\n";
 
-   print "<a href=\"$me/igrp-summary/\">Groups</a> || \n"; 
-   print "<a href=\"$me/igrp-overview/\">Group Summary</a>\n"; 
-   print "<hr>\n";
+   print "<a href=\"$main::WWWACK\" target=\"right\">Ack</a> || \n"; 
 
-   print "<a href=\"$main::WWWACK\">Ack</a> || \n"; 
-#   print "<a href=\"$me/isummary/$group\">Summary</a> || \n"; 
-   print "<a href=\"$me/ihistory/all\">History</a> || \n"; 
-   print "<a href=\"$me/help\">Help</a>\n";
-   print "<hr>\n<p>\n";
+#   print "<a href=\"$me/isummary/$group\" target=\"right\">Summary</a> || \n"; 
 
-   &grp_problems( $group );
+   print "<a href=\"$me/ihistory/all\" target=\"right\">History</a> || \n"; 
+   print "<a href=\"$me/help\" target=\"right\">Help</a>\n";
+   print "<hr />\n";
+
+   &grp_problems( 1, $group );
+
+   &insert_group_info($gname);
+   &insert_updated_time();
 
-   print "<p><hr>";
-#   print "<a href=\"$me/groups\">Group</a>: <b>$gname</b>\n<hr>\n";
-   print "Updated at ", POSIX::strftime( "$TIMEFMTNOSEC, on $DATEFMT", localtime() ), "\n";
    &footer();
 }
 
@@ -354,9 +482,9 @@ sub isummary {
    my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
    $gname = "Selected Hosts" unless $gname;
 
-   &header( 1 );
-   print "<font size=+2><b>$gname</b></font>\n<hr>\n";
-   &summary( $group );
+   &header( 1, "$gname" );
+   print "<h2>$gname</h2>\n<hr />\n";
+   &summary( 1, $group );
    &footer();
 }
 
@@ -365,9 +493,9 @@ sub ihistory {
    my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
    $gname = "Selected Hosts" unless $gname;
 
-   &header( 1 );
-   print "<font size=+2><b>$gname</b></font>\n<hr>\n";
-   &history( $group );
+   &header( 1, "$gname" );
+   print "<h2>$gname</h2>\n<hr />\n";
+   &history( 1, $group );
    &footer();
 }
 
@@ -376,10 +504,11 @@ sub igrp_summary {
 #   my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
 #   $gname = "Selected Hosts" unless $gname;
 
-   &header( 1 );
-   print "<font size=+2><b>Host Groups</b></font>\n<hr>\n";
+   &header( 1, "Host Groups" );
+   print "<h2>Host Groups</h2>\n";
+   print "<hr />";
    $main::view = "full";
-   &grp_summary($group);
+   &grp_summary( 1, $group);
    &footer();
 }
 
@@ -388,10 +517,10 @@ sub igrp_overview {
 #   my $gname = $main::GROUPS{$group}->{'name'} if $main::GROUPS{$group};
 #   $gname = "Selected Hosts" unless $gname;
 
-   &header( 1 );
-   print "<font size=+2><b>Host Groups Summary</b></font>\n<hr>\n";
+   &header( 1, "Host Groups Summary" );
+   print "<h2>Host Groups Summary</h2>\n<hr />\n";
    $view = "standard";
-   &grp_summary($group);
+   &grp_summary( 1, $group);
    &footer();
 }
 
@@ -404,40 +533,37 @@ sub igrp_overview {
 sub groups {
    my $group;
 
-   &header( $group, "Groups", '', 0 );
-   print "<base target=view>\n";
-   print "<font size=+2><b>Spong Groups</b></font>\n<hr>\n";
+   &header( 1, "Groups");
+   print "<h2>Spong Groups</h2>\n<hr />\n";
 
-   print "You can select a specific group to show only information about ";
+   print "<p>You can select a specific group to show only information about ";
    print "those hosts.  The groups below have been defined by the spong ";
-   print "administrator.<p>\n";
+   print "administrator.</p>\n";
 
    print "<ul>\n";
    foreach $group ( @main::GROUPS_LIST ) {
       my $name    = $main::GROUPS{$group}->{'name'};
       my $summary = $main::GROUPS{$group}->{'summary'};
       
-      print "<li><a href=\"$main::WWWSPONG/group/$group\">$name</a> ";
-      print "($group)<br>\n$summary<p>\n";
+      print "<li><a href=\"$main::WWWSPONG/group/$group\" target=\"_top\">$name</a> ";
+      print "($group)<br />\n$summary<br /><br /></li>\n";
    }
-   print "</ul><p>\n";
-   print "<hr noshade>\n";
+   print "</ul><p></p>\n";
+
+   print "<hr />\n";
 
-   print "You can also build a custom group to monitor by selecting one or ";
-   print "hosts from the list below.<p>\n";
-   print "<form action=\"$WWWSPONG/groups-doit\" method=get>\n";
-   print "<center><table width=80% border=0>\n";
-   print "<tr><td width=50% valign=top align=center>\n";
-   print "<select name=\"hosts\" size=10 multiple>\n";
+   print "<p>You can also build a custom group to monitor by selecting one or ";
+   print "hosts from the list below.</p>\n";
+   print "<form action=\"$WWWSPONG/groups-doit\" method=\"get\" target=\"_top\">\n";
+   print "<select name=\"hosts\" size=\"10\" multiple=\"multiple\">\n";
 
-   foreach $host ( @main::HOSTS_LIST ) { print "<option>$host\n"; }
+   foreach $host ( @main::HOSTS_LIST ) { print "<option>$host</option>\n"; }
 
    print "</select>\n";
-   print "</td><td width=50% valign=center align=center>\n";
-   print "<input type=submit name=\" Show Hosts \" value=\" Show Hosts \">\n";
-   print "</td></tr></table>\n";
+   print "<br /><br />\n";
+   print "<input type=\"submit\" value=\" Show Hosts \" />\n";
    print "</form>\n";
-   print "<hr>\n";
+   print "<hr />\n";
    
    &footer();
 }
@@ -449,7 +575,7 @@ sub groups_doit {
    my $group = "";
    while( $ENV{'QUERY_STRING'} =~ /hosts=([^\&]+)/isg ) { $group .= "$1,"; }
    chop $group;
-   &interactive( $group );
+   &toplevel_interactive( "HOSTS", $group );
 }   
 
 
@@ -463,31 +589,37 @@ sub problems {
 
    $group = "all" unless $group;
 
-   &header( 1 );
+   # always called inline! DON'T add header and footer!
    print &query( $SPONGSERVER, "problems", $group, "html", $view );
-   &footer();
+
 }
 
+# call with 1 as first arg to ommit header/footer,
+# use 0 otherwise
 sub summary {
-   my $group = shift;
-   my $view = $main::view || "standard";
-
-   $group = "all" unless $group;
-
-   &header( 1 );
-   print &query( $SPONGSERVER, "summary", $group, "html", $view ); 
-   &footer();
+    my $inline_use = shift;
+    my $group = shift;
+    my $view = $main::view || "standard";
+    
+    $group = "all" unless $group;
+    
+    &header( 1, "Summary" ) unless $inline_use;
+    print &query( $SPONGSERVER, "summary", $group, "html", $view ); 
+    &footer() unless $inline_use;
 }
 
+# call with 1 as first arg to ommit header/footer,
+# use 0 otherwise
 sub history {
-   my $group = shift;
-   my $view = $main::view || "standard";
-
-   $group = "all" unless $group;
+    my $inline_use = shift;
+    my $group = shift;
+    my $view = $main::view || "standard";
+    
+    $group = "all" unless $group;
 
-   &header( 1 );
-   print &query( $SPONGSERVER, "history", $group, "html", $view ); 
-   &footer();
+    &header( 1, "History" ) unless $inline_use;
+    print &query( $SPONGSERVER, "history", $group, "html", $view ); 
+    &footer() unless $inline_use;
 }
 
 
@@ -495,7 +627,8 @@ sub host {
    my $host = shift;
    my $view   = $main::view || "standard";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "Host" );
    print &query( $SPONGSERVER, "host", $host, "html", $view );
    &footer();
 }
@@ -504,7 +637,8 @@ sub services {
    my $host = shift;
    my $view = $main::view || "standard";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "Services" );
    print &query( $SPONGSERVER, "services", $host, "html", $view ); 
    &footer();
 }
@@ -513,7 +647,8 @@ sub stats {
    my $host = shift;
    my $view = $main::view || "standard";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "Stats" );
    print &query( $SPONGSERVER, "stats", $host, "html", $view );    
    &footer();
 }
@@ -522,7 +657,8 @@ sub config {
    my $host = shift;
    my $view = $main::view || "standard";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "Config" );
    print &query( $SPONGSERVER, "config", $host, "html", $view ); 
    &footer();
 }
@@ -531,7 +667,8 @@ sub info {
    my $host = shift;
    my $view = $main::view || "standard";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "Info" );
    print &query( $SPONGSERVER, "info", $host, "html", $view ); 
    &footer();
 }
@@ -541,7 +678,8 @@ sub service {
    my( $host, $service ) = @_;
    my $view = $main::view || "full";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "Service" );
    print &query( $SPONGSERVER, "service", $host, "html", $view, $service );
    &footer();
 }
@@ -550,29 +688,37 @@ sub histservice {
    my ($host, $service, $time ) = @_;
    my $view = $main::view || "full";
 
-   &header( 0 );
+   # never called inline, so header() and footer() are ok here
+   &header( 0, "History" );
    print &query( $SPONGSERVER, "histservice", $host, "html", $view, $service,
                  $time );
    &footer();
 }
 
+# call with 1 as first arg to ommit header/footer,
+# use 0 otherwise
 sub grp_summary {
-   my( $other ) = @_;
-   my $view = $main::view || 'full';
+    my $inline_use = shift;
+    my( $other ) = @_;
+    my $view = $main::view || 'full';
+    
+    &header(0, "Group Summary") unless $inline_use;
+    print &query( $SPONGSERVER, "grpsummary", '', "html", $view, $other);
+    &footer() unless $inline_use;
 
-   &header(0);
-   print &query( $SPONGSERVER, "grpsummary", '', "html", $view, $other);
-   &footer();
 
 }
 
+# call with 1 as first arg to ommit header/footer,
+# use 0 otherwise
 sub grp_problems {
-   my( $other ) = @_;
-   my $view = $main::view || 'full';
-
-   &header(0);
-   print &query( $SPONGSERVER, "grpproblems", $other, "html", $view );
-   &footer();
+    my $inline_use = shift;
+    my( $other ) = @_;
+    my $view = $main::view || 'full';
+    
+    &header(0, "Problems") unless $inline_use;
+    print &query( $SPONGSERVER, "grpproblems", $other, "html", $view );
+    &footer() unless $inline_use;
 }
 
 # Just print a little message to stdout showing what valid options are to 
@@ -677,13 +823,30 @@ sub load_config_files {
 
 sub header { 
    my( $reload ) = shift;
+   my( $title ) = shift || "Spong Page";
+
+   # $header_printed should not be necessary anymore
+   #   if( $main::header_printed == 1 ) { return; }
+   #   $main::header_printed = 1;
+
+   print "Content-type: text/html\r\n\r\n"; 
+
+   print '<?xml version="1.0" encoding="ISO-8859-1"?>',"\n";
+   print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '.
+       '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',"\n";
+   print '<html xmlns="http://www.w3.org/1999/xhtml">',"\n";
+   print "<head>\n";
 
-   if( $main::header_printed == 1 ) { return; }
-   $main::header_printed = 1;
+   print "<title>$title</title>\n";
+
+   &insert_stylesheet();
+   &insert_meta();
 
-   print "Content-type: text/html\n\n"; 
    if( $reload == 1 && &can_reload() ) {
-      print "<meta http-equiv=\"REFRESH\" content=\"$main::SPONGSLEEP\">\n"; }
+      print "<meta http-equiv=\"refresh\" content=\"$main::SPONGSLEEP\" />\n"; }
+
+   print "</head>\n";
+   print "<body>\n";
 
    &show( "header", 1 ) if -f "$main::WWWHTML/header.html"; 
 }
@@ -691,8 +854,13 @@ sub header {
 sub footer { 
    if ($main::footer_printer == 1 ) { return; }
    $main::footer_printer = 1;
-   &show( "footer", 1 ) if -f "$main::WWWHTML/footer.html"; }
 
+   &show( "footer", 1 ) if -f "$main::WWWHTML/footer.html";
+
+   print "</body>\n";
+   print "</html>\n";
+
+}
 
 # This just takes a HTML template with a given name, and sends it to STDOUT.
 # This is used primarily for the help documentation.
@@ -702,7 +870,7 @@ sub show {
    my $show = $main::WWWSPONG . "/help";
 
    if( -f "$main::WWWHTML/$file.html" ) {
-      &header( '', "Help", '', 0 ) unless $hf; 
+      &header( 0, "Help" ) unless $hf; 
       open( FILE, "$main::WWWHTML/$file.html" );
       while( <FILE> ) {
          s/!!WWWSHOW!!/$show/g;
@@ -712,8 +880,8 @@ sub show {
       close( FILE );
       &footer() unless $hf;
    } else {
-      &header( '', "Help", '', 0 ) unless $hf; 
-      print "<h1>Help Not Available</h1>\n";
+      &header( 0, "Help" ) unless $hf; 
+      print "<h2>Help Not Available</h2>\n";
       print "Sorry, but no help has been provided for that topic.\n";
       &footer() unless $hf;
    }
@@ -793,6 +961,7 @@ _EOM_
    alarm(0);
    
    return $msg if $ok;
-   return "<font color=red><b>Can't connect to spong server!</b></font>";
+   return "<span class=\"error\">Error:</span>\n".
+       "<span class=\"error_text\">Can't connect to spong server!</span>\n";
 }