sub GenIPMask {
    my $portlist = shift;
    my($ip,$ipmask,$lastip,@ips);

    foreach (keys %Config) {
      push(@ips,$_) unless ($portlist and ($Config{$_}{portlist} ne $portlist));
    }
    return &OptimizeIPMask(join(' ', @ips));
}

# Class C IP optimization only

sub OptimizeIPMask {
    my $ipmask = shift || return;
    my @ips = split(/ /,$ipmask);
    return $ipmask unless $#ips > 0;

    my @list;
    
    my $ip = shift @ips;
    my @iparts = split(/\./,$ip);
    my $last = $iparts[3];

    foreach (@ips) {
      @parts = split /\./;
      if ($parts[3] == ($last + 1)) {
        $iparts[3] .= '-' unless $iparts[3] =~ /\-$/;
        $last = $parts[3];
      } else {
        $iparts[3] .= $last if $iparts[3] =~ /\-$/;
        push(@list,join('.',@iparts));
        $last = $parts[3];
        $iparts[3] = $last;
      }
    }
    
    $iparts[3] .= $last if $iparts[3] =~ /\-$/;
    push(@list,join('.',@iparts));
    
    return join(' ',@list);
}

sub GetConfigHash {
    my $ip;
    my %site = ();
    my %tmpl = ( eval($Templatetext) );

    if ($Infofile && open(I, "<$Infofile")) {
      my @info = <I>;
      close(I);
      if ($#info >= 0) {
        foreach (@info) {
          chomp;
          %site = ( eval($_) );
          foreach (keys %tmpl) { $site{$_} = $tmpl{$_} unless exists $site{$_}; }
          foreach (keys %site) { $Config{$site{'ip'}}{$_} = &Decode($site{$_}); }
        }
      }
    }
    
    if ($Configfile and (-f $Configfile)) {
      my($ipmask,$portmask);
      foreach (&ReadConfigfile()) {
        ($ipmask, $portmask) = split / /;
        foreach $ip (&GenerateSiteList($ipmask)) {
          $Config{$ip}{portlist} = join(',',&GeneratePortList($portmask));
          foreach (keys %tmpl) { $Config{$ip}{$_} = $tmpl{$_} unless exists $Config{$ip}{$_}; }
        }
      }
    }

    if ($Currentfile and open(C, "<$Currentfile")) {
      my(@p,$ports,$cf);
      while (<C>) {
        chomp;
        $cf = $_;
        $cf =~ s/ \(([^\)]*)\)\t/\tname: $1\t/;
        $cf =~ s/: / => '/g;
        $cf =~ s/\t/', /g;
        $cf .= "'";
        $cf =~ s/ //g;

        %site = ( eval($cf) );
        $ip = $site{Host};
        ($ports = $site{Ports}) =~ s/^Ports: //;
        foreach (split(/,\s*/, $ports)) {
          @p = split /\//;
          $site{ports} .= $p[0].',';
        }
        chop $site{ports};

        $Config{$ip}{status} = ($site{Status} eq "Down") ? $Stat_fail :
                                 ($site{Status} eq "Up")   ? (!$Config{$ip}{portlist} ? $Stat_ok : $Stat_fail) :
                                 ($site{ports} eq $Config{$ip}{portlist}) ? $Stat_ok :
                                 $Stat_warn;
        $Config{$ip}{name}   = $site{name} if $site{name};
        $Config{$ip}{ports}  = $site{ports};
      }
      close(C);
    }

    # Group IP's with the same portlists, also set alias, sip, and ip values
    foreach $ip ( keys %Config ) {
      $CmdArgs{$Config{$ip}{portlist}} .= ($CmdArgs{$Config{$ip}{portlist}}?',':'').$ip;
      $Config{$ip}{alias} = $Config{$ip}{Alias_8};
      $Config{$ip}{sip}   = &sip($ip);
      $Config{$ip}{ip}    = $ip;
    }
}

#sub ReadCurrentFile {
#    &DEBUG('starting');
#    my $ip = shift || return;
#    my(@p);
#
#    my $cmd = "grep '$ip ' $Currentfile";
#    my $cf = `$cmd`; chomp $cf;
#    return unless $cf;
#
#    $cf =~ s/ \(([^\)]*)\)\t/\tname: $1\t/;
#    $cf =~ s/: / => '/g;
#    $cf =~ s/\t/', /g;
#    $cf .= "'";
#    $cf =~ s/ //g;
#
#    my %site = ( eval($cf) );
#    my $ports = $site{Ports};
#    $ports =~ s/^Ports: //;
#    foreach (split(/,\s*/, $ports)) {
#      @p = split /\//;
#      $site{ports} .= $p[0].',';
#    }
#    chop $site{ports};
#
## $Configfile: (ipmask portmask)
#    my $done = 0;
#    foreach (&ReadConfigfile()) {
#      ($ipmask, $portmask) = split / /;
#      foreach (&GenerateSiteList($ipmask)) {
#        next unless $_ eq $ip;
#        $site{portlist} = join(',',&GeneratePortList($portmask));
#        $done = 1;
#        last;
#      }
#      last if $done;
#    }
#
#    my %info = &GetStoredInfo($ip);
#    foreach (keys %info) { $site{$_} = $info{$_}; }
#
#    $site{status} = ($site{Status} eq "Down") ? $Stat_fail : ($site{ports} eq $site{portlist}) ? $Stat_ok : $Stat_warn;
#    $site{ip}     = $ip;
#    $site{sip}    = &sip($ip);
#    $site{alias}  = $site{Alias_8};
#
#    return %site;
#}

sub ReadHistoryFile {
    &DEBUG("Starting");
    my($ip,$startyear,$startmon,$startday,$endyear,$endmon,$endday) = @_;
    my($f) = &ip2file($ip);
    use Time::Local;
    my $starttime = timelocal( 1, 0, 0,$startday,$startmon,$startyear);
    my $endtime   = timelocal(59,59,23,$endday,  $endmon,  $endyear);

    my(%history) = ();
    my($time, $host, $status, $s, @p);
    local(*F);

    my %info = &GetStoredInfo($ip);

# $Configfile: (ipmask portmask)
    my $done = 0;
    foreach (&ReadConfigfile()) {
      ($ipmask, $portmask) = split / /;
      foreach (&GenerateSiteList($ipmask)) {
        next unless $_ eq $ip;
        $info{portlist} = join(',',&GeneratePortList($portmask));
        $done = 1;
        last;
      }
      last if $done;
    }
    $history{portlist} = $info{portlist};

	open(F, "<$f.hist") || &Error("Unable to open $f.hist for reading.");
	while (<F>) {
      chomp;
      ($time, $host, $status) = split /\t/;
      last if $time > $endtime;
      next unless $time >= $starttime;
      @ntimes = localtime($time);
      $ntime = $Months[$ntimes[4]].' '.$ntimes[3];
      push(@hkeys,$ntime) unless grep(/^$ntime$/,@hkeys);

      if ($status =~ /^Status/) {
        if ($status =~ /Down/) {
          $history{system}{$ntime}{$Stat_fail}++;
        } else {
          $history{system}{$ntime}{$Stat_ok}++;
        }
        foreach $port (split(/,/,$history{portlist})) {
          $history{portstatus}{$ntime}{$port}{$Stat_fail}++;
        }
      } else {
        undef @portok;
        $allok = $noneok = 1;
        ($s = $status) =~ s/^\s*Ports:\s*//;
        foreach (split(/,\s*/, $s)) {
          @p = split /\//;
          push(@portok,$p[0]);
        }
        foreach $port (split(/,/,$history{portlist})) {
          if (grep(/^$port$/,@portok)) {
            $history{portstatus}{$ntime}{$port}{$Stat_ok}++;
            $noneok = 0;
          } else {
            $history{portstatus}{$ntime}{$port}{$Stat_fail}++;
            $allok = 0;
          }
        }
        if ($allok) {
          $history{system}{$ntime}{$Stat_ok}++;
        } elsif ($noneok) {
          $history{system}{$ntime}{$Stat_fail}++;
        } else {
          $history{system}{$ntime}{$Stat_warn}++;
        }
      }
    }
    close(F);
    $history{keys} = join(',',@hkeys);
    return %history;
}

sub ReadConfigfile {
    &DEBUG('starting');
    local(*F);
    my(@out) = ();
	open(F, "<$Configfile") || &Error("Unable to open Configfile: $Configfile for reading.<p>Click on the Setup Button to setup your network.");
	@out = <F>; close(F);
    chomp @out;
    return wantarray ? @out : join("\n",@out);
}

sub ip2file {
    return $Basedir . '/' . join('/', split(/\./, shift));
}

sub GenerateSiteList {
    my(@sites) = ();
    my($ip1, $ip2, $ip3, $ip4, @ips);

    my($ipmask) = shift || return;
    @ips = split(/\./, $ipmask);
    return unless $#ips == 3;
    foreach $i (0..3) {
      $ips[$i] =~ s/\-/\.\./g;
      $ips[$i] =~ s/\*/0\.\.255/g;
      $ips[$i] =~ s/^00?(\d)/$1/g;
      $ips[$i] =~ s/(\D)00?(\d)/$1$2/g;
    }
    foreach $ip1 (eval($ips[0])) {
      next unless $ip1 =~ /^\d+$/;
      foreach $ip2 (eval($ips[1])) {
        next unless $ip2 =~ /^\d+$/;
        foreach $ip3 (eval($ips[2])) {
          next unless $ip3 =~ /^\d+$/;
          foreach $ip4 (eval($ips[3])) {
            next unless $ip4 =~ /^\d+$/;
            push(@sites, $ip1.'.'.$ip2.'.'.$ip3.'.'.$ip4);
          }
        }
      }
    }
            
    return wantarray ? @sites : join("\n",@sites);
}

sub GeneratePortList {
    my($portmask) = shift;
    my(@ports);
    if ($portmask =~ /\*/) {
      $portmask = '1..65535';
    } else {
      $portmask =~ s/^[^0-9\., -]//g;
      $portmask =~ s/-/../g;
    }
    foreach (eval($portmask)) {
      push(@ports, $_);
    }
    return sort {$a <=> $b} @ports;
}

sub sint {
    my($val) = shift;
    my($w) = shift || 3;
    my($c) = sprintf("%${w}d",$val);
    $c =~ s/ /0/g;
    return $c;
}

sub sip {
    my(@ips) = split(/\./, shift);
    my($ip) = &sint($ips[0]).'.'.&sint($ips[1]).'.'.&sint($ips[2]).'.'.&sint($ips[3]);
    return $ip;
}

sub rsip {
    my(@ips) = split(/\./, shift);
    my($ip) = int($ips[0]).'.'.int($ips[1]).'.'.int($ips[2]).'.'.int($ips[3]);
    return $ip;
}


sub CreateDir {
    &DEBUG('starting');
	my $filename = shift || &Error('Unable to create a null directory.');
    my @dirs = split(/\//, $filename);
    pop @dirs;     #Filename part
    unshift @dirs; #Root part
    my $dir = '';
    foreach (@dirs) {
      $dir .= "/" . $_;
      mkdir($dir,0775) unless -d $dir;
      &Error("Unable to create directory: $dir") unless -d $dir;
    }
    return 1;
}

sub colorStatus {
    my($stat) = shift;
	  if ($stat == $Stat_ok) {
	    return $Color_ok, $Text_ok, 'OK';
      } elsif ( $stat == $Stat_warn) {
        return $Color_warn, $Text_warn, 'WARN';
      } else {
	    return $Color_fail, $Text_fail, 'FAIL';
	  }
}

sub AddToStoredInfo {
    &DEBUG('starting');
    my($site,$new) = @_;

    foreach (keys %{$new}) {
      $$site{$_} = $$new{$_};
    }
    return %{$site};
}

sub GetStoredInfo {
    &DEBUG('starting');
    my($ip) = shift || return 0;
    my %site = ();

    if ($Infofile && open(I, "<$Infofile")) {
      my @info = grep(/ip => "$ip"/,<I>);
      close(I);
      if ($#info >= 0) {
        chomp $info[0];
        %site = ( eval($info[0]) );
      }
    }

    my %tmpl = ( eval($Templatetext) );
    foreach (keys %tmpl) {
      $site{$_} = $tmpl{$_} unless exists $site{$_};
    }
    $site{notes} = "" unless exists $site{notes};

    foreach (keys %site) { $site{$_} = &Decode($site{$_}); }
    return %site;
}

sub SaveStoredInfo {
    &DEBUG('starting');
    my $ip = shift || return;
    my %site = &GetStoredInfo($ip);

    delete $site{''};
    foreach (keys %site) { $site{$_} = $in{$_} if exists $in{$_}; }
    $site{ip} = $ip;

    &SaveInfo2(%site);
}

sub SaveInfo2 {
    &DEBUG('starting');
    my %site = @_;
    my $ip = $site{ip} || return;
    local(*F,*G);

    delete $site{''};
    delete $site{ip};
    my $output = 'ip => "'.$ip.'", ';

    foreach (keys %site) {
      $output .= $_ . ' => "' . &Encode($site{$_}) . '", ';
    }
    chop $output; chop $output;

    open(F, "<$Infofile");
    open(G, ">$Infofile.new");
    my $changed = 0;
    my $line;
    while (<F>) {
      chomp;
      $line = $_;
      if ($line =~ /ip => "$ip"/) {
        print G $output,"\n";
        $changed = 1;
      } else {
        print G $line,"\n";
      }
    }
    close(F);
    print G $output,"\n" unless $changed;
    close(G);
    rename "$Infofile.new", $Infofile;
}

sub Ok2Check {
  my $ip   = shift || return 0;
  my $port = shift || return 0;
  my %site = @_;
  return 1 unless $site{'port'.$port};
  
  my ($d,$h)   = split(/\s*:\s*/,$site{'port'.$port});
  my @daylist  = sort {$a <=> $b} split(/\s*,\s*/,$d);
  my @hourlist = sort {$a <=> $b} split(/\s*,\s*/,$h);

  return 1 if (($daylist[0] == -1) and ($hourlist[0] == -1));

  my($sec,$min,$hour,$dom,$mon,$year,$dow,$yday,$isdst) = localtime(time);

  if ($daylist[0] != -1) {
    return 0 unless grep(/^$dow$/,@daylist);
    if ($hourlist[0] != -1) {
      return 0 unless grep(/^$hour$/,@hourlist);
    }
  }
  return 1;
}

sub ReadServices {
    &DEBUG('starting');
    open(F, "<$Servicesfile") || &Error("Unable to open the services file: $Servicesfile");
    while (<F>) {
      $Services{$2} = $1 if m/\s*([^:\s]+)\s*:\s*(.*)$/;
    }
    $Services{0} = 'alive';
    close(F);
}

sub GetAllOS {
    my(@iplist) = @_;
    &DEBUG("Starting\n",join("\n",@iplist));
    return unless $#iplist >= 0;

    my(%OS,@result,$h,$ngo);
    foreach (@iplist) { $OS{$_} = 'Unknown'; }
    
    my $tmpfile = $Cgidir.'/ostmp'.$$;
    open(IL, ">$tmpfile") or return;
    print IL join("\n",@iplist); close(IL);

    $ngo = $nmap_general_options." ".$nmap_extra_options;
    $ngo =~ s/\-P[IBS0]//;
    $ngo =~ s/\-PT[0-9]*//;
    $ngo =~ s/\-s.//;
    my $cmd = $Nmapcmd.' '.$ngo.' -v -oM - -O '.$NmapScan." -iL $tmpfile 2>/dev/null | grep '^Host'";
    &DEBUG($cmd);
    @result = `$cmd`;

    foreach $h (@result) {
      if ($h =~ /^Host: ([0-9\.]+).*OS: ([^\t]+).*$/) {
        $ip = $1;
        $os = $2;
        chomp $os;
        $OS{$ip} = $os;
        &DEBUG("Setting $ip to $os");
      }
    }
    unlink $tmpfile;
    return %OS;
}

sub GetICON {
    &DEBUG('starting');
    my $os   = shift || return 'unk';
    my $icon = 'unk';

    if ($os =~ /Mac/) { $icon = 'mac';
    } elsif ($os =~ /print|phaser|laser|inkjet/i) { $icon = 'printr01';
    } elsif ($os =~ /Solaris|Sun/i) { $icon = 'sun';
    } elsif ($os =~ /3com/i) {        $icon = '3com';
    } elsif ($os =~ /novell/i) {      $icon = 'novell';
    } elsif ($os =~ /suse/i) {        $icon = 'suse';
    } elsif ($os =~ /beos/i) {        $icon = 'beos';
    } elsif ($os =~ /nortel/i) {      $icon = 'nortel';
    } elsif ($os =~ /juniper/i) {     $icon = 'juniper';
    } elsif ($os =~ /lucent/i) {      $icon = 'lucent';
    } elsif ($os =~ /amiga/i) {       $icon = 'amiga';
    } elsif ($os =~ /cabletron/i) {   $icon = 'cabletron';
    } elsif ($os =~ /citrix/i) {      $icon = 'citrix';
    } elsif ($os =~ /Cisco/i) {       $icon = 'cisco';
    } elsif ($os =~ /Tru64/i) {       $icon = 'tru64';
    } elsif ($os =~ /SCO/i) {         $icon = 'sco';
    } elsif ($os =~ /Linux/i) {       $icon = 'linux';
    } elsif ($os =~ /IRIX/i) {        $icon = 'irix';
    } elsif ($os =~ /BSD/) {          $icon = 'bsd';
    } elsif ($os =~ /AIX/) {          $icon = 'aix';
    } elsif ($os =~ /Windows/) {      $icon = 'windows';
    } elsif ($os =~ /Unix|Open|Net|MVS|UX|UNIX|OSF|BSD/) { $icon = 'server01';
    } elsif ($os =~ /SNMP|SMTP|Router|router|RAS|switch|Gate|Bridge/) { $icon = 'router01';
    } else {
      $icon = 'unk';
    }
    return $icon;
}

sub Error {
	my($msg) = shift;
    my($pages) = shift || 1;
    &DEBUG($msg);
    print &Header($Myname,"ERROR",0) unless $DoneHeader;
	print <<EOE;
  $msg
  <p><a href="javascript:top.history.go(-$pages)">Continue</a></p>
EOE
	print &Footer();
	exit;
}

sub DEBUG {
  return unless $ADEBUG;
  my $caller = (caller(1))[3];
  open(BUG, ">>$Vardir/debug.log") or return;
  print BUG $caller,': ',join("",@_),"\n";
  close(BUG);
}

sub WaitForLockFile {
  &DEBUG('starting');
  my $lockfile = $Vardir.'/autorecheck.lock';
  return 1 unless -f $lockfile;
  my $t = time;
  while (-f $lockfile) {
    &DEBUG("Waiting for lock to clear");
    sleep(3);
    return 0 if int(time - $t) > $RecheckTimeout;
  }
  return 1;
}

sub StartAutoCheck {
 &DEBUG('starting');
  my $cmd = shift;
  if ($cmd) {
    if (&WaitForLockFile()) {
      &DEBUG("Issuing cmd: $cmd");
      system($cmd);
      return 1;
    } else {
      return 0;
    }
  } else {
    &StopAutoCheck();
    my $pidfile = $Vardir."/autorecheck.pid";
    $Autointerval ||= 20;
    $Autointerval = abs($Autointerval);
    $cmd = $Autorecheck." ".$pidfile." ".$Autointerval;
    &DEBUG("Issuing cmd: $cmd");
    system($cmd); sleep(2);
    return (-f $pidfile)?1:0;
  }
}

sub StopAutoCheck {
 &DEBUG("Starting");
  my $pidfile = $Vardir."/autorecheck.pid";
  if (open(F, "<$pidfile")) {
    my $autopid = <F>;
    chomp $autopid;
    close(F);
    &DEBUG("Sending TERM to $autopid");
    kill 'TERM', $autopid;
    unlink $pidfile;
    $Autointerval = -abs($Autointerval);
  }
}

sub RestartAutoCheck {
  &DEBUG('starting');
  return 1 if &HUPAutoCheck();
  &DEBUG('Calling StartAutoCheck');
  return &StartAutoCheck();
}

sub HUPAutoCheck {
  &DEBUG('starting');
  return 0 if $Autointerval <= 0;
  my $pidfile = $Vardir."/autorecheck.pid";
  if (open(F, "<$pidfile")) {
    my $autopid = <F>;
    chomp $autopid;
    close(F);
    &DEBUG("Sending HUP to $autopid");
    return kill('HUP', $autopid);
  }
  return 0;
}

sub AutoCheckStatus {
  &DEBUG('starting');
  my $pidfile = $Vardir."/autorecheck.pid";
  return 0 unless -f $pidfile;
  open(F, "<$pidfile") || return 0;
  my $autopid = <F>;
  chomp $autopid;
  close(F);
  return kill(0, $autopid);
}

sub ServerCheckStatus {
  &DEBUG('starting');
  my $pidfile = $Vardir."/miniserv.pid";
  return 0 unless -f $pidfile;
  open(F, "<$pidfile") || return 0;
  my $pid = <F>;
  chomp $pid;
  close(F);
  return kill(0, $pid);
}

sub Encode {
  my $text = shift || return;
  $text =~ s/([^a-zA-Z0-9_\. -])/uc sprintf("%%%02x",ord($1))/eg;
  return $text;
}

sub Decode {
  my $text = shift || return;
  $text =~ s/%([0-9a-fA-F]{2})/chr hex($1)/ge;
  return $text;
}

sub FilterSite {
    &DEBUG('starting');
    return unless $in{f};
    my($fname,$style);
    ($fname,$style) = $in{f} =~ /^(.*)_(.*)$/;
    return unless $Filters{$fname}{$style};
    
    my @iplist;
    foreach (split(/\s*\t\s*/,$Filters{$fname}{$style})) {
      push(@iplist,&GenerateSiteList($_));
    }
    
    my($o,$sip);
    foreach $o ($Stat_ok,$Stat_warn,$Stat_fail) {
      foreach $sip (keys %{$Site{$o}}) {
        delete $Site{$o}{$sip} unless grep(/^$Site{$o}{$sip}{ip}$/,@iplist);
      }
    }
    &DEBUG('Returning ips: '.join(",",@iplist));
    return @iplist;
}

sub Header {
    my($title, $extra, $increfresh) = @_;
    &DEBUG("Starting");

    if (&AutoCheckStatus()) { $auto = 'on';  $nauto = 'off'; }
    else                    { $auto = 'off'; $nauto = 'on'; }
    my $autocheck = '<a href="'.$nPulseurl.'?a=auto&s='.$nauto.'" title="Automatic Monitoring On/Off">'.
                    '<img src="/images/serv_'.$auto.'.gif" width="26" height="43" border="0" alt="AutoCheck On/Off"></a>';

    $extra = $extra?'<table border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td align="right"><span style="'.$Fsl.'">'.$extra.'</span>&nbsp;</td></tr></table>':'';

    my $select = '<select name="f" style="font-size:7pt;color:black">';
    my($fname,$style);
    foreach $fname (sort keys %Filters) {
      foreach $style (sort keys %{$Filters{$fname}}) {
        $selected = ($in{f} eq $fname.'_'.$style) ? " selected" : "";
        $select .= '<option'.$selected.' value="'.$fname.'_'.$style.'">'.ucfirst(lc($fname)).':'.ucfirst(lc($style)).'</option>';
      }
    }
    $select .= '<option value="filter_new_filter">Edit Filters</option></select>';
    #my $demomode = $DEMO?'&nbsp;<em><span style="'.$Fxs.'">DEMO</span></em>':"$Version";
    $DoneHeader = 1;
    
    my $refresh = '';
    if ($increfresh) {
      if ($increfresh == 2) {
        $refresh = '<meta http-equiv="refresh" content="'.int($HtmlRefresh).';URL='.$HTTP.
                   $nPulseurl.'?a=status">' if int($HtmlRefresh) > 0;
      } else {
        $refresh = '<meta http-equiv="refresh" content="'.int($HtmlRefresh).';URL='.$HTTP.
                   $nPulseurl.'?a=display&f='.$in{f}.'">' if int($HtmlRefresh) > 0;
      }
    }

    my $buttons;
    if ($AdminUser) {
      $buttons = <<EOB;
         <td bgcolor="#bdbdbd"><a href="$nPulseurl?a=recheck" onMouseOver="recheck.src='images/recheck_on.gif'" onMouseOut="recheck.src='images/recheck.gif'"><img name=recheck src="images/recheck.gif" width=63 height=43 border=0 alt="Manual Recheck" title="Manual Network Rescan"></a></td>
         <td bgcolor="#bdbdbd"><a href="$nPulseurl?a=setup"   onMouseOver="setup.src='images/setup_on.gif'"     onMouseOut="setup.src='images/setup.gif'"><img     name=setup   src="images/setup.gif"   width=63 height=43 border=0 alt="Network Setup" title="Network Configuration Setup"></a></td>
         <td bgcolor="#bdbdbd"><a href="$nPulseurl?a=pref"    onMouseOver="prefs.src='images/prefs_on.gif'"     onMouseOut="prefs.src='images/prefs.gif'"><img     name=prefs   src="images/prefs.gif"   width=63 height=43 border=0 alt="Preferences" title="Preferences"></a></td>
         <td bgcolor="#bdbdbd"><a href="$nPulseurl?a=status"  onMouseOver="status.src='images/status_on.gif'"   onMouseOut="status.src='images/status.gif'"><img   name=status  src="images/status.gif"  width=63 height=43 border=0 alt="Status" title="nPulse Status Monitor"></a></td>
EOB
      $autocheck = <<EOA;
      <td>$autocheck</td>
EOA
    } else {
      $buttons   = "";
      $autocheck = "";
    }

    my $div = ($IsIE or $IsNS)?'<div style="height:50;overflow:none">':'<div>';
  
    return <<HTML;
<html>
 <head>
  <title>$title</title>
  <meta name="Keywords" content="Linux,Unix,npulse,nPulse,NPULSE,network,monitor,statistics">
  <meta name="Description" content="nPulse Network Monitoring Program for Linux and Unix.">
  <meta http-equiv="Expires" content="-1">
  $refresh
  <style language="text/css">
   BODY    {$Fsn;font-weight:normal}
   A       {font-weight:normal;text-decoration:none}
   A:hover {text-decoration:underline}
  </style>
  <script language="javascript">
  var coll = "";
  var styleObj = "";
  if (document.all) {
    coll = "all."
    styleObj = ".style"
  }
  function hilite(which,obj) {
    if (which > 0) {
      var theObj = eval("document." + coll + obj + styleObj)
      theObj.backgroundColor = (which == 1) ? "#ffd0d0" : "#000000"
      theObj = eval("document." + coll + 'a_' + obj + styleObj)
      theObj.backgroundColor = (which == 1) ? "#ffd0d0" : "#000000"
    }
  }
  </script>
 </head>
 <body bgcolor="#000000" text="#ffffff" link="#9999ff" vlink="#9999ff" alink="#ff0000" style="margin:0;" MARGINWIDTH=0 MARGINHEIGHT=0>
  $div
    <table cellspacing="0" cellpadding="0" width="100%">
    <form method="post" action="$nPulseurl" style="padding:0;margin:0;border:0">
    <input type="hidden" name="a" value="display">
     <tr>
      <td width=104><img src="images/alogo.gif" width="80" height="49" border="0" alt="nPulse"></td>
      <td width="100%" valign="bottom"><font size=1 color="#999999">$Version &nbsp;</font></td>
      <td align="right">
       <table border="1" cellspacing="0" cellpadding="0">
        <tr valign="bottom">
         <td bgcolor="#bdbdbd"><a href="$Home_url" 
                                  onMouseOver="home.src='images/home_on.gif'"
                                  onMouseOut="home.src='images/home.gif'"><img name="home"
                                  src="images/home.gif" width="63" height="43" border="0"
                                  alt="Home" title="Home Page"></a></td>
         $buttons
         <td bgcolor="#bdbdbd"><a href="$Help_url" onMouseOver="help.src='images/help_on.gif'" onMouseOut="help.src='images/help.gif'"><img name="help" src="images/help.gif" width="63" height="43" border="0" alt="Help" title="Help Page"></a></td>
         <td bgcolor="#bdbdbd" nowrap align="center"  style="font-size:7pt;color:black;text-align:center">$select<input type="submit" value="Go" style="font-size:6pt;color:black;border:0"></td>
        </tr>
       </table>
      </td>$autocheck
     </tr>
     <tr><td height="1" colspan="5" bgcolor="#a0a0a0"><img src="images/dot.gif"
         height="1" width="100"></td></tr>
    </form></table>
   </div>$extra
HTML
}

sub Footer {
  return <<HTML;
  <hr>
  <table border="0" cellspacing="0" cellpadding="0" width="100%">
    <tr><td align="left"><span style="$Fxs"><a href="$Copyright_url">Copyright</a> &copy;2001, <a href="http://www.horsburgh.com/">Horsburgh.com</a> All Rights Reserved.</td>
        <td align="right"><span style="$Fxs">User: $User [<a href="$Logout_url">Logout</a>]</td>
    </tr>
  </table>
 </body>
</html>
HTML
}

sub DisplayHTMLfile {
    &DEBUG('starting');
    my $f     = shift || return;
    my $extra = shift;
    local(*F); local($/) = undef;
    open(F, "<$f") || return;
    my $output = <F>; close(F);
    print &Header($Myname,'',$extra,0),$output,&Footer();
    exit;
}

sub GetUserCmds {
    my %Cmds;
    if (open(F, "<$Ucmdfile")) {
      my($name,$admin,$cmd);
      while (<F>) {
        chomp;
        ($name,$admin,$cmd) = split /\t/;
        if ($cmd eq "") {
          $cmd = $admin;
          $admin = 0;
        }
        $Cmds{$name}{cmd}   = $cmd;
        $Cmds{$name}{admin} = $admin?1:0;
        $name = $admin = $cmd = "";
      }
      close(F);
    }
    return %Cmds;
}

sub PingHosts {
  my $ipmask = shift;
  $ipmask =~ s/\*$/1-254/;
  my ($portmask, $cmd);
  my (@cmds, @output);
  
  if ($ipmask) {
    push(@cmds, $Nmapcmd.' '.$nmap_general_options.' '.$nmap_extra_options.' -v -oM - -sP '.$ipmask.' 2>/dev/null | grep "Host: "');
  } else {
    push(@cmds, $Nmapcmd.' '.$nmap_general_options.' '.$nmap_extra_options.' -v -oM - -sP '.
                &GenIPMask().' 2>/dev/null | grep "Host: "');
  }
  
  foreach $cmd (@cmds) {
    &DEBUG("Running cmd: $cmd");
    @out = `$cmd`;
    chomp @out;
    push(@output, @out);
  }

  my $html = '<span style="'.$Fsn.'">Ping Sweep Results</span><table border=1><tr>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">IP Address</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">Host Name</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">Alias</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">Status</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fss.'">Currently<br>Monitored?</td>'.
             '</tr>';

  my ($host,@rest,$ip,$status,$monitored,$alias,$name);
  foreach (@output) {
    ($host, @rest) = split /\t/;
    $host =~ s/^Host: //;

    ($ip, $name) = split(/ /, $host);
    $name =~ s/\(|\)//g;
    unless ($ip) { $ip = $name; $name = ''; }

    $status = ($rest[0] =~ /^Status: Down/)?'<font color="#cc0000">Down</font>'
                                           :'<font color="#00cc00">Up</font>';
    $alias = $monitored = '';
    if (exists $Config{$ip}) {
      $alias  = $Config{$ip}{alias};
      $name ||= $Config{$ip}{name};
      $monitored = 'Yes';
    }
    $alias     ||= '&nbsp;';
    $name      ||= '&nbsp;';
    $monitored ||= '<font color="#cc0000"><b>No</b></font>';

    $html .= '<tr><td align="right" style="'.$Fss.'">'.((exists $Config{$ip})?'<a href="'.$nPulseurl.'?a=detail&site='.$ip.'">'.$ip.'</a>':$ip).'</td>'.
                 '<td align="right" style="'.$Fss.'">'.$name.'</td>'.
                 '<td style="'.$Fss.'">'.$alias.'</td>'.
                 '<td align="center" style="'.$Fss.'">'.$status.'</td>'.
                 '<td align="center" style="'.$Fss.'">'.$monitored.'</td></tr>';
  }
  $html .= '</table>';
  return $html;
}

sub PortSweep {
  my($ipmask,$port) = @_;
  $port =~ s/ //gs;
  $ipmask =~ s/ //gs;
  $ipmask =~ s/\*$/1-254/;

  if (($port != int($port)) or ($port <= 0) or ($port >= 65535) or ($ipmask =~ /[^0-9\.-]/)) {
    return '<span style="'.$Fsn.'">Invalid Address ('.$ipmask.') or Port Value ('.$port.')</span>';
  }

  my ($portmask, $cmd);
  my (@cmds, @output, @ports);
  
  if ($ipmask) {
    push(@cmds, $Nmapcmd.' '.$nmap_general_options.' '.$nmap_extra_options.' -v -oM - '.$NmapScan.
                ' -p '.$port.' '.$ipmask.' 2>/dev/null | grep "Host: "');
  } else {
    push(@cmds, $Nmapcmd.' '.$nmap_general_options.' '.$nmap_extra_options.' -v -oM - '.$NmapScan.
                ' -p '.$port.' '.&GenIPMask().' 2>/dev/null | grep "Host: "');
  }
  
  foreach $cmd (@cmds) {
    &DEBUG("Running cmd: $cmd");
    @out = `$cmd`;
    chomp @out;
    push(@output, @out);
  }

  my $html = '<span style="'.$Fsn.'">Port '.$port.($Services{$port}?' ('.$Services{$port}.')':'').' Sweep Results</span><table border=1><tr>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">IP Address</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">Host Name</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">Alias</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fsn.'">Status</td>'.
             '<td bgcolor="#333399" align="center" style="'.$Fss.'" nowrap>Port Currently<br>Monitored?</td>'.
             '</tr>';

  my ($host,@rest,$ip,$name,$alias,$status,$monitored);
  my $found = 0;
  foreach $line (@output) {
    $found = 1;

    ($host, @rest) = split(/\t/,$line);
    $host =~ s/^Host: //;

    ($ip, $name) = split(/ /, $host);
    $name =~ s/\(|\)//g;
    unless ($ip) { $ip = $name; $name = ''; }

    $status = ($rest[0] =~ / $port\/open/)    ?'<font color="#00cc00">Open</font>':
              ($rest[0] =~ / $port\/filtered/)?'<font color="#cccc00">Filtered</font>':
                                               '<font color="#cc0000">Closed</font>';
    $alias = $monitored = '';
    if (exists $Config{$ip}) {
      @ports = split(/\s*,\s*/,$Config{$ip}{portlist});
      $monitored = 'Yes' if (grep(/^$port$/,@ports));
      $alias  = $Config{$ip}{alias};
      $name ||= $Config{$ip}{name};
    }
    $alias     ||= '&nbsp;';
    $name      ||= '&nbsp;';
    $monitored ||= '<font color="#cc0000"><b>No</b></font>';

    $html .= '<tr><td align="right" style="'.$Fss.'">'.((exists $Config{$ip})?'<a href="'.$nPulseurl.'?a=detail&site='.$ip.'">'.$ip.'</a>':$ip).'</td>'.
                 '<td align="right" style="'.$Fss.'">'.$name.'</td>'.
                 '<td style="'.$Fss.'">'.$alias.'</td>'.
                 '<td align="center" style="'.$Fss.'">'.$status.'</td>'.
                 '<td align="center" style="'.$Fss.'">'.$monitored.'</td></tr>';
  }
  $html = '<span style="'.$Fsn.'"><b>No hosts '.($ipmask?'('.$ipmask.')':'').' responded with port '.$port.' open.</b></span>' unless $found;
  $html .= '</table>' if $found;
  return $html;
}

sub GetKookie {
  
  $Filters{default}{list}  = $Filters{default}{basic}  = $Filters{default}{compact}  = '';
  $GFilters{default}{list} = $GFilters{default}{basic} = $GFilters{default}{compact} = 1;

  local(*K);
  local($/) = undef;

  if (open(K, "<$Htmldir/gkookie")) {
    my $kookie = <K>;
    close(K);
    chomp $kookie;
    my($k,$v,$l);
    foreach $l (split(/\n/,$kookie)) {
      ($k,$v) = $l =~ /^(.*?)=(.*)$/;
      if ($k =~ /^filter_/) {
        ($fname,$style) = $k =~ /^filter_(.*)_(.*)$/;
        $Filters{$fname}{$style} = $v;
        $GFilters{$fname}{$style} = 1;
      } else {
        $in{$k} ||= $v;
      }
    }
  }
  
  if (open(K, "<$UserDir/kookie")) {
    my $kookie = <K>;
    close(K);
    chomp $kookie;
    my($k,$v,$l);
    foreach $l (split(/\n/,$kookie)) {
      ($k,$v) = $l =~ /^(.*?)=(.*)$/;
      if ($k =~ /^filter_/) {
        ($fname,$style) = $k =~ /^filter_(.*)_(.*)$/;
        $Filters{$fname}{$style} = $v;
        $GFilters{$fname}{$style} = 0;
      } else {
        $in{$k} ||= $v;
      }
    }
  }
  
  $in{sort} ||= $DefaultSort;
}

sub WriteKookie {
  local(*K);

  if (open(K, ">$UserDir/kookie")) {
    print K 'sort=',$in{sort};
    foreach $fname (sort keys %Filters) {
      foreach $style (sort keys %{$Filters{$fname}}) {
        next if $GFilters{$fname}{$style};
        print K "\nfilter_",$fname,"_",$style,"=",$Filters{$fname}{$style};
      }
    }
    print K "\n";
    close(K);
  }

  if ($AdminUser and open(K, ">$Htmldir/gkookie")) {
    print K 'sort=',$in{sort};
    foreach $fname (sort keys %Filters) {
      foreach $style (sort keys %{$Filters{$fname}}) {
        next unless $GFilters{$fname}{$style};
        print K "\nfilter_",$fname,"_",$style,"=",$Filters{$fname}{$style};
      }
    }
    print K "\n";
    close(K);
  }

  &GetKookie();
}

1;
