#!/usr/bin/perl -w

#########################################################################
# clam-update script for Logwatch
# Analyzes the Clam Anti-Virus update log
#
# Version: 1.00
# Written by: Lars Skjrlund <lars@skjaerlund.dk>
#########################################################################

#########################################################################
# This script is subject to the same copyright as Logwatch itself
#########################################################################

#########################################################################
# Files - all shown with default paths:
#
# /etc/log.d/conf/logfiles/clam-update.conf
# /etc/log.d/conf/services/clam-update.conf
# /etc/log.d/scripts/services/clam-update (this file)
#
# ... and of course
#
# /var/log/clam-update.log
#########################################################################

#########################################################################
# Important note:
#
# Under normal operation - ie. a detail level of 'lo' (0), no output will
# be produced if no updates have taken place. However, if no update 
# attempt has been done, an alert will be output to inform you about this
# (which probably means that freshclam isn't running).
# 
# If you have stopped using ClamAV and would like to get rid of the 
# alert, you should delete the logfile. If there's no logfile, no alerts
# will be output - but if Logwatch finds a logfile and no update attempts
# have been made for whatever timeperiod Logwatch is analyzing, an alert
# will be output.
#########################################################################

use POSIX qw(strftime);

my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'};
my $time = time;
my $InRange       = 0;
my $MainUptodate  = undef;
my $MainUpdated   = undef;
my $DailyUptodate = undef;
my $DailyUpdated  = undef;
my $Updated       = undef;
my %Errors;
my %Unmatched;

if ( $ENV{'LOGWATCH_DATE_RANGE'} eq 'yesterday') {
   $SearchDate = strftime("%b %e", localtime($time-86400));
}
elsif ( $ENV{'LOGWATCH_DATE_RANGE'} eq 'today') {
   $SearchDate = strftime("%b %e", localtime($time));
}
elsif ( $ENV{'LOGWATCH_DATE_RANGE'} eq 'all') {
   $SearchDate = "... ..";
}

while (defined($ThisLine = <STDIN>)) {
   if (($ThisLine =~ /^\s*$/) or
       ($ThisLine =~ /^----------/)
   ) {
      # Do nothing
   } elsif (($Date) = ($ThisLine =~ /(\w\w\w [\d ]\d) ..:..:../)) {
      if ($Date =~ $SearchDate) {
         $InRange = 1;
      } else {
         $InRange = 0;
      }
   } elsif ($InRange == 1) {
      chomp($ThisLine);
      if ($ThisLine =~ /^main.cvd is up to date/) {
         $MainUptodate = $ThisLine;
      } elsif ($ThisLine =~ /^daily.cvd is up to date/) {
         $DailyUptodate = $ThisLine;
      } elsif ($ThisLine =~ /^main.cvd updated/) {
         $MainUpdated = $ThisLine;
      } elsif ($ThisLine =~ /^daily.cvd updated/) {
         $DailyUpdated = $ThisLine;
      } elsif ($ThisLine =~ /^Database updated/) {
         $Updated = $ThisLine;
      } elsif ((my $Text) = ($ThisLine =~ /^ERROR: (.*)/)) {
         $Errors{$Text}++;
      } else {
         $Unmatched{$ThisLine}++;
      }
   } else {
      if (($ThisLine =~ /^main.cvd is up to date/) or
          ($ThisLine =~ /^daily.cvd is up to date/) or
          ($ThisLine =~ /^main.cvd updated/) or
          ($ThisLine =~ /^daily.cvd updated/) or
          ($ThisLine =~ /^Database updated/) or
          ($ThisLine =~ /^ERROR: /)) {
         #
      } else {
         chomp($ThisLine);
         $Unmatched{$ThisLine}++;
      }
   }
}

if (($Detail >= 5) or ($MainUpdated or $DailyUpdated) or (!$MainUptodate and !$DailyUptodate)) {
   print "ClamAV database:\n";
}

if ($MainUpdated) {
   (my $Text, $Version) = ($MainUpdated =~ /(.*) \((.*)\)/);
   print "   $Text\n";
   if ($Detail >= 10) {
      print "      $Version\n";
   }
} else {
   if (($MainUptodate) and ($Detail >= 5)) {
      (my $Text, $Version) = ($MainUptodate =~ /(.*) \((.*)\)/);
      print "   $Text\n";
      if ($Detail >= 10) {
         print "      $Version\n";
      }
   }
}

if ($DailyUpdated) {
   (my $Text, $Version) = ($DailyUpdated =~ /(.*) \((.*)\)/);
   print "   $Text\n";
   if ($Detail >= 10) {
      print "      $Version\n";
   }
} else {
   if (($DailyUptodate) and ($Detail >= 5)) {
      (my $Text, $Version) = ($DailyUptodate =~ /(.*) \((.*)\)/);
      print "   $Text\n";
      if ($Detail >= 10) {
         print "      $Version\n";
      }
   }
}

if (($Updated) and ($Detail >= 10)) {
   (my $Text, $From) = ($Updated =~ /^(\w* \w*) \(\d* \w*\) (.*)\./);
   print "   $Text $From\n";
};

if (!$MainUptodate and !$MainUpdated and !$DailyUptodate and !$DailyUpdated) {
   print "   WARNING: Database has not been checked for updates\n";
}

if (keys %Errors) {
   print "\nERRORS:\n";
   foreach my $Text (keys %Errors) {
      print "   $Text: $Errors{$Text} Time(s)\n";
   }
}

if (keys %Unmatched) {
   print "\n**Unmatched Entries**\n";
   foreach my $Text (keys %Unmatched) {
      print "   $Text: $Unmatched{$Text} Time(s)\n";
   }
}

exit(0);
