sub Generate {
    my(@iplist) = @_;
    my($sip);
    &DEBUG("Starting");

# Create Fail, Warn, Ok hashes for requested ip numbers

    foreach (@iplist) {
      $sip = &sip($_);
      &DEBUG("Generating Site info for $sip (o = $mySite{$sip}{'status'})");
      $Site{$mySite{$sip}{'status'}}{$sip}{'ip'}       = $mySite{$sip}{'ip'};
      $Site{$mySite{$sip}{'status'}}{$sip}{'name'}     = $mySite{$sip}{'name'};
      $Site{$mySite{$sip}{'status'}}{$sip}{'alias'}    = $mySite{$sip}{'Alias_8'};
      $Site{$mySite{$sip}{'status'}}{$sip}{'ports'}    = $mySite{$sip}{'ports'};
      $Site{$mySite{$sip}{'status'}}{$sip}{'portlist'} = $mySite{$sip}{'portlist'};
      $Site{$mySite{$sip}{'status'}}{$sip}{'os'}       = $mySite{$sip}{'os'} || 'Unknown';
      $Site{$mySite{$sip}{'status'}}{$sip}{'icon'}     = $mySite{$sip}{'icon'} || 'unk';
    }
    return;
}

sub CreateHTML {
    &DEBUG("Starting");

# Create the basic, compact, or list HTML strings

    my ($o, $found, $cb, $sip, $html, $bgcolor, $txcolor);
    my $cols = $Basiccols;
    $MaxTDs = 0;

    my $sortmenu = '<form method=get action="'.$nPulseurl.'" style="padding:0;margin:0;border:0">'.
                   '<input type=hidden name=a value="display">'.
                   '<input type=hidden name=f value="'.$in{'f'}.'">'.
                   '<select name=sort style="font-size:7pt;background-color:#cccce7">';
    my $style = $in{'f'}; $style =~ s/^.*_//;
    $cols = 1 if $style eq 'list';

    my($v,$e,$s);
    my %h = eval($Templatetext); $h{'name'} = "";
    foreach $v (sort keys %h) {
      next if $v =~ /^Icon/;
      $e = uc($v); $e =~ s/_.*$//;
      $s = ($in{'sort'} eq $v)?' selected':'';
      $sortmenu .= '<option value="'.$v.'"'.$s.'>'.$e.'</option>';
    }
    $sortmenu .= '</select> '.
                 '<input type=submit value="Sort" '.
                 'style="text-decoration:underline;font-size:7pt;'.
                 'color:white;border:0;background-color:#666666"></form>';

    $html .= '<table border=0 cellspacing=0 cellpadding=0 width="100%">'.
            '<tr'.($IsNS?'':' bgcolor="#666666"').'><td><span style="'.$Fxs.
            '">Click on a site for details.</span></td>'.
            '<td nowrap><span style="'.$Fxs.
            '">Status: SITESUP ok, SITESWARN warn, SITESFAIL fail</span></td>'.
            '<td align="right"><span style="'.$Fxs.'">'.scalar(localtime()).
            '</span></td><td align="right" style="font-size:7pt;color:black"><span style="font-size:7pt">'.
            $sortmenu.
            "</span></td></tr></table>";
    $html .= "<table border=0 cellspacing=0 cellpadding=0 width=\"100%\"><tr valign=\"top\">";
    $html .= "<td align=\"left\" width=\"20%\">".&DisplayEventLog()."</td>" if $style eq 'list';
    $html .= "<td width=\"80%\"><table border=0 cellspacing=2 cellpadding=0 width=\"100%\">";

    my %NumSites;
    $NumSites{$Stat_fail} = $NumSites{$Stat_warn} = $NumSites{$Stat_ok} = 0;

    my $addselect = 1;
    foreach $o ($Stat_fail, $Stat_warn, $Stat_ok) {
      $found = $cb = 0;
      $bgcolor = ($o == $Stat_fail) ? $Color_fail : ($o == $Stat_warn) ? $Color_warn : $Color_ok;
      $txcolor = ($o == $Stat_fail) ? $Text_fail  : ($o == $Stat_warn) ? $Text_warn : $Text_ok;

      foreach $sip (&Sort4Display($o,$in{'sort'})) {
        next unless $sip;
        $html .= "<tr><td bgcolor=\"$bgcolor\" colspan=".$cols.
                 " style=\"border:1 inset;$Fsn\"><font color=\"$txcolor\">".
                 (($o == $Stat_fail) ? "Sites not responding" : ($o == $Stat_warn) ? "Sites responding with errors" : "Fully Operational Sites").
                 "</font></td></tr>" unless $found;
        $sortmenu = "";
        $html .= &Display2($o, $sip, $cb++, $style, $cols);
        $NumSites{$o}++;
        $cb = 0 if $cb >= $cols;
        $found = 1;
      }
      $html .= "</tr>" if $cb;
    }
    $MaxTDs = $cols unless $MaxTDs > $cols;
    $html   =~ s/colspan=$cols/colspan=$MaxTDs/gs;
    $html  .= "</table></td>";
    $html  .= "<td align=\"right\" width=\"20%\">".&DisplayEventLog()."</td>" unless $style eq 'list';
    $html  .= "</tr></table>";

    $html =~ s!SITESUP!$NumSites{$Stat_ok}!s;
    $html =~ s!SITESWARN!$NumSites{$Stat_warn}!s;
    $html =~ s!SITESFAIL!$NumSites{$Stat_fail}!s;

    return $html;
    
}


sub Display2 {
    my($o, $sip, $cb, $style, $cols) = @_;
    my($html);

    my($color)     = ($o == $Stat_fail) ? $Color_fail : ($o == $Stat_warn) ? $Color_warn : $Color_ok;
    my($textcolor) = ($o == $Stat_fail) ? $Text_fail  : ($o == $Stat_warn) ? $Text_warn  : $Text_ok;

    my($name)      = $Site{$o}{$sip}{'name'};
    my($ip)        = $Site{$o}{$sip}{'ip'};
    my($icon)      = $Site{$o}{$sip}{'icon'};
    my($alias)     = $Site{$o}{$sip}{'alias'};

    $html = "<tr valign=\"middle\" align=\"center\">\n" unless $cb;

    if ($style eq 'compact') {
      $html .= "<td style=\"background-color:".$color."\"><a title=\"".$name."(".($ip eq $name?"":$ip).
               ")\" style=\"text-decoration:none;".$Fxs.";color:".
               $textcolor."\" href=\"".$nPulseurl."?a=detail&site=".$ip."\">".
               ($UseAliases ? &Cname($ip,$name,$alias,$CustomName) : $ip).
               "</a></td>";

    } elsif ($style eq 'list') {
      $href = "title=\"".$name."(".($ip eq $name?"":$ip).
               ")\" style=\"text-decoration:none;".$Fxs.";color:".
               $textcolor."\" href=\"".$nPulseurl."?a=detail&site=".$ip."\"";
      $html .= "<td align=\"right\" style=\"background-color:".$color."\"><a ".$href.">".
               ($UseAliases ? &Cname($ip,$name,$alias,$CustomName) : $ip).'</a></td>'.
               &PortStats($o,$sip,$href);

    } else {
      $html .= "<td style=\"".$Fss.";border:1 solid black\"><a style=\"".$Fxs.";color:".$textcolor.
               ";text-decoration:none;\" href=\"".
               $nPulseurl."?a=detail&site=".$ip."\">".
               "<img border=0 width=32 height=32 src=\"/images/icons/".$icon.".gif\"><br>".
               "<span style=\"background-color:".$color."\">".
               ($UseAliases ? &Cname($ip,$name,$alias,$CustomName) : $ip).
               "</span></a></td>\n";
    }

    $html .= "</tr>\n" if $cb > $cols;

	return $html;
}

sub PortStats {
  my($o,$sip,$href) = @_;
  my($bg,$fg,%ports);
  my $td = "";

  foreach (split(/,\s*/,$Site{$o}{$sip}{'ports'}))    { $ports{$_} = 1; }
  foreach (split(/,\s*/,$Site{$o}{$sip}{'portlist'})) {
    if ($o == $Stat_fail) {
      ($bg, $fg) = ($Color_fail, $Text_fail);
    } else {
      ($bg, $fg) = exists $ports{$_} ? ($Color_ok, $Text_ok) : ($Color_fail, $Text_fail);
    }    
    $td .= "<td nowrap style=\"background-color:$bg\">".
           "<a $href><span style=\"$Fxs;color:$fg;background-color:$bg\">".
           (($ListStyle == 1)?($Services{$_}?$Services{$_}:$_):
            ($ListStyle == 2)?$_:($Services{$_}?$Services{$_}." (".$_.")":$_)).
           "</span></a></td>";
    $MaxTDs++;
  }
  return $td;
}

sub Cname {
    my($ip,$name,$alias,$type) = @_;
    my(@parts, $i);
    return $ip unless ($name or $alias);
    return ($name?$name:$ip) if (($type <= -1) or ($type > 9));
    return $alias if ($alias and ($type == 0));
    return $ip unless $name;

    @parts = split(/\./, $name);

    if ($type == 9) {
      pop   @parts unless $#parts <= 0;
      shift @parts unless $#parts <= 0;
    } else {
      $name = $alias || $name;
      for ($i = 1; $i <= $type; $i++) { pop @parts unless $#parts <= 0; }
    }
    return join('.', @parts);
}

sub Sort4Display {
  my ($o,$sortby) = @_;
  my (@list,$ip,$i,$os,$value);
  &DEBUG("Sorting by $sortby with o = $o");

  my @iplist = ();
  @iplist = sort keys %{$Site{$o}};

  &DEBUG("start ip list:\n ",join("\n ",@iplist));

  if ($sortby ne 'ip') {
    $sortby = "alias" if $sortby =~ /^Alias/i;
    
    foreach $ip (@iplist) {
      ($value = $Site{$o}{$ip}{$sortby}) =~ s/\n/ /gs;
      push(@list, $value.' => '.$ip);
    }
    &DEBUG("List elements:\n ",join("\n ",@list));
    undef @iplist;
    foreach $i (sort @list) {
      ($os,$ip) = $i =~ /^(.*) => (.*)$/;
      push(@iplist,$ip);
    }
    &DEBUG("end ip list:\n ",join("\n ",@iplist));
  }

  return @iplist;
}

sub ClearEventLog {
  &DEBUG("Starting");
  return unless $AdminUser;
  if ($in{'site'}) {
    open(E, "<$Eventlogfile") or return;
    open(EE, ">$Eventlogfile.clr") or return;
    print EE join("",grep(!/\t$in{'site'}\t/, <E>));
    close(EE);
    close(E);
    rename "$Eventlogfile.clr", $Eventlogfile;
  } else {
    unlink $Eventlogfile;
  }
}

sub DisplayEventLog {
  &DEBUG("Starting");
  my $noauto = shift;
  return unless ($AdminUser or $Events4Users);
  return unless ($Eventlogfile and (-f $Eventlogfile) and ($MaxEvents > 0));
  local($/) = "\n";
  open(E, "<$Eventlogfile") or return;
  my @events = <E>;
  close(E);
  my $out = '<table border=0 cellspacing=0 cellpadding=0><tr><td height=2><img src="images/dot.gif" height=2 width=50></td></tr><tr>'.
            '<td nowrap><b><span style="'.$Fss.';color:black;background-color:#999999">Event Log</span></b>'.
            '<font size=1><span style="'.$Fxs.'"> (last '.$MaxEvents.' events)</span></font>';
  $out .=   '<font size=2><span style="'.$Fxs.'"> <a href="'.$nPulseurl.'?action=display&f='.
            $in{'f'}.'&s=cleareventlog" onClick="return confirm('.
            "'Are you sure you want to delete the ENTIRE Event Log?'".
            ')">Delete Log</a></span></font>' if ($AdminUser and (!$noauto));
  $out .=   '<font size=2><span style="'.$Fxs.'"> <a href="'.$nPulseurl.'?action=display&f='.
            $in{'f'}.'&s=cleareventlog&site='.$AllowedIPs[0].'" onClick="return confirm('.
            "'Are you sure you want to delete ALL events logged for this device?'".
            ')">Delete Log</a></span></font>' if ($AdminUser and $noauto);
  $out .=   '</td></tr><tr><td bgcolor="#333333">';

  my($time,$ip,$type,$event,$sip,$name,$isauto);
  my $count = 0;
  foreach (reverse @events) {
    ($time,$ip,$type,$event) = split /\t/;
    $isauto = (lc($ip) eq 'auto')?1:0;
    next if (($isauto and $noauto) or (($EventSeverity > 0) and $isauto));
    next unless $type >= $EventSeverity;
    if ($#AllowedIPs >= 0) {
      next unless grep(/^$ip$/,@AllowedIPs,'Auto');
    }
    $name = '';
    unless ($isauto) {
      $sip = &sip($ip);
      foreach ($Stat_ok, $Stat_warn, $Stat_fail) {
        if (defined $Site{$_}{$sip}) {
          $name = $Site{$_}{$sip}{'name'};
          last;
        }
      }
 #     $name = $Site{$Stat_fail}{$sip}{'name'} || $Site{$Stat_warn}{$sip}{'name'} || $Site{$Stat_ok}{$sip}{'name'} || '';
      $name = '' if $name eq $ip;
      $name = ' ('.$name.')' if $name;
    }
    $out .= '<font size=1><span style="'.$Fxs.'">'.$time.':<br>'.
            ($isauto?$ip:'<a href="'.$nPulseurl.'?a=detail&site='.$ip.'">'.$ip.'</a>').
            $name.':<br></span></font>';
    $out .= '<font size=2 color="#'.
            (($type == $Stat_fail)?'cc0000':($type == $Stat_warn)?'cccc00':'00cc00').'">'.
            '<span style="'.$Fss.'">'.$event.'<p></span></font>';
    last if ++$count >= $MaxEvents;
  }
  $out .= 'No Events Logged</td></tr></table>' unless $count;
  $out .= "</td></tr></table>";
  return $out;
}

sub CREATE {
    my $flag = shift;
    local(*F);
    my(%s, $sip, $host, $status, $line, $ip, $name, @p, $ipmask, $portmask, $portlist, @cfglist, @iplist);

    &DEBUG("starting");

# $Infofile: (key => val, ... format)

    if (-f $Infofile) {
      open(F, "<$Infofile") || &Error("Infofile error");
      while (<F>) {
        %s = ( eval ($_) );
        $sip = &sip($s{'ip'});
        foreach $k (keys %s) {
          $mySite{$sip}{$k} = &Decode($s{$k});
        }
      }
      close(F);
    }

# $Configfile: (ipmask portmask)
    @cfglist = &ReadConfigfile();
    foreach (@cfglist) {
      ($ipmask, $portmask) = split / /;
      $portlist = join(',',&GeneratePortList($portmask));
      foreach (&GenerateSiteList($ipmask)) {
        $sip = &sip($_);
        $mySite{$sip}{'portlist'} = $portlist;
        $mySite{$sip}{'ip'} = $_;
        $mySite{$sip}{'status'} = $Stat_fail;
      }
    }

# $Currentfile:
# Host: 192.168.10.1 ()\tStatus: Down
# or
# Host: 192.168.10.1 ()\tStatus: Up
# or
# Host: 192.168.10.1 (pwawpz.localdomain)\tPorts: 21/open/tcp//ftp///, ....

    open(F, "<$Currentfile") || return;
    while (<F>) {
      chomp;
      ($host, $status) = split /\t/;
      $line = $_;
      ($ip, $name) = $line =~ /^Host: ([\d\.]+) \((.*?)\).*$/;
      $sip = &sip($ip);
      $mySite{$sip}{'line'}   = $line;
      $mySite{$sip}{'ip'}     = $ip;
      $mySite{$sip}{'name'}   = $name;
      if ($status =~ /^Status/) {
        $mySite{$sip}{'status'} = ($status =~ /Up/) ? $Stat_ok : $Stat_fail;
        $mySite{$sip}{'ports'}  = "";
      } else {
        $status =~ s/^Ports: //;
        foreach (split(/,\s*/, $status)) {
          @p = split /\//;
          $mySite{$sip}{'ports'} .= $p[0].',';
        }
        chop $mySite{$sip}{'ports'};
        $mySite{$sip}{'status'} = ($mySite{$sip}{'ports'} eq $mySite{$sip}{'portlist'}) ? $Stat_ok : $Stat_warn;
      }
      $mySite{$sip}{'status'} = $Stat_warn if (($mySite{$sip}{'status'} == $Stat_ok) and 
                                               ($mySite{$sip}{'ports'} ne $mySite{$sip}{'portlist'}));
    }
    close(F);

    foreach (keys %mySite) { push(@iplist,&rsip($_)) unless ($mySite{$_}{'os'} or ($mySite{$_}{'status'} == $Stat_fail)); }
    &DEBUG("Found ",($#iplist+1)," ip(s) without os values\n",join("\n",@iplist));
    if ($#iplist >= 0) {
      my %OS;
      %OS = &GetAllOS(@iplist);
      foreach (keys %OS) {
        $sip = &sip($_);
        $mySite{$sip}{'os'} = $OS{$_};
        $mySite{$sip}{'icon'} = &GetICON($OS{$_});
        $in{'os'}   = $OS{$_};
        $in{'icon'} = $mySite{$sip}{'icon'};
        &SaveStoredInfo($_);
      }
    }

    foreach (@cfglist) {
      ($ipmask, $portmask) = split / /;
      &Generate(&GenerateSiteList($ipmask));
    }

    @AllowedIPs = &FilterSite();

    &DEBUG("Generating HTML");
    my $html = "";
    $html = &CreateHTML unless $flag;
    return $html;
}

sub AdminHeaderInfo {
    &DEBUG("Starting");
    my $cb = 0; my $inf = $in{'f'};
    my($fname,%seen,@iplist,$sip,$num,$num_ok,$num_warn,$num_fail,$color,$tcolor);
    my $numcols = $Basiccols - 2;
    $numcols = 2 if $numcols < 2;
    my $html = '<table border=1 cellspacing=0 cellpadding=0><tr><td bgcolor="#333399" align="center">'.
               '<span style="'.$Fsn.'">Overview of Current Filters</span></td></tr><tr><td align="center">'.
               '<table border=0 width="100%">';

    foreach $fname (sort keys %Filters) {
      next unless $fname;
      next if $seen{$fname}++;

      $in{'f'} = $fname.'_'.(($Filters{$fname}{'basic'}||($fname eq 'default'))?'basic':$Filters{$fname}{'compact'}?'compact':'list');
      undef %Site; undef %mySite;
      &CREATE(1);
      $num = $num_ok = $num_warn = $num_fail = 0;
      
      foreach (keys %{$Site{$Stat_fail}}) { $num_fail++; $num++; }
      foreach (keys %{$Site{$Stat_warn}}) { $num_warn++; $num++; }
      foreach (keys %{$Site{$Stat_ok}})   { $num_ok++;   $num++; }

      $color = ($num == $num_fail)?$Color_fail:((($num_fail == 0) and ($num_warn == 0))?$Color_ok:$Color_warn);
      $tcolor = ($num == $num_fail)?$Text_fail:((($num_fail == 0) and ($num_warn == 0))?$Text_ok:$Text_warn);
      $html .= '<tr valign="middle" align="center">' unless $cb;
      $html .= '<td nowrap><a href="'.$nPulseurl.'?a=display&f='.$in{'f'}.'"><img src="images/icons/network.gif" width=32 height=32 border=0><br>'.
               '<span style="'.$Fss.';color:'.$tcolor.';background-color:'.$color.'">'.$fname.'</span>'.
               '<br><span style="'.$Fxs.'">ok: '.int($num_ok).', warn: '.int($num_warn).', fail: '.int($num_fail).
               '</span></a></td>';
      if ($cb++ > $numcols) {
        $html .= "</tr>\n";
        $cb = 0;
      }
    }
    $html .= "</tr>\n" if $cb;
    $in{'f'} = 'default_basic';
    undef %Site; undef %mySite;
    undef @AllowedIPs;
    return $html.'</table></td></tr></table>';
}

1;
