#!/usr/bin/perl -w
# cleanscore - Remove expired entrys from slrn's Scorefile.

# Copyright (c) 1999 - 2001 Felix Schueller <fschueller@netcologne.de>
# 
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#     
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc., 675
# Mass Ave, Cambridge, MA 02139, USA.
   

$score_file = "/home/felix/news/score";


####################### END OF USER CONFIGURATION ##########################

use Fcntl qw(:DEFAULT :flock);

sub help();
sub reset_vars();
sub insert_comment();
sub end_of_score();

$version="0.9.7.3";
$group= -1;
$DEBUG = 0;
$remove_comments = 0;
$VERBOSE = 0;
$keep = 0;
$test_only = 0;

require "getopts.pl"; &Getopts('df:k:hrtVv');
if (defined($opt_f)) {$score_file = $opt_f;}
if (defined($opt_d)) {$DEBUG = $opt_d;}
if (defined($opt_h)) {help(); exit(0);}
if (defined($opt_r)) {$remove_comments = $opt_r;}
if (defined($opt_t)) {$test_only = $opt_t;}
if (defined($opt_k)) {$keep = $opt_k * 86400;}
if (defined($opt_v)) {$VERBOSE = $opt_v;}
if (defined($opt_V)) {print ("cleanscore - Version: $version (bugreports to: fschueller\@netcologne.de)\n"); exit(0);}

$opt_h = $opt_V; # suppress 'perl -w' warnings.

if ($DEBUG)
  {
    print ("Version: $version\n");
    print ("Scorefile: $score_file\n");
    if (defined($opt_k)) {print ("Keep: $keep ($opt_k)\n");}
    print ("Dates: Entry / System");
    if ($keep) {print (" - $opt_k Days\n\n");}
    else {print ("\n\n");}
  }

@ak_date = localtime (time - $keep);
$ak_year = ($ak_date[5] + 1900);
$ak_month = ($ak_date[4] + 1);
$ak_day = $ak_date[3];

unless ($test_only)
  {  
    sysopen (OUT, "$score_file", O_RDWR) || die ("Can't open $score_file: $!");
    flock (OUT, LOCK_EX | LOCK_NB) || die ("Can't lock $score_file: $!");
  
    #If I use flock for locking, I can't use 'system("mv ....")'
    open (DEST, ">$score_file.bak") || die ("Can't write $score_file.bak: $!");
    while (<OUT>) {print (DEST $_);}
    close (DEST);
    seek (OUT, 0, 0) || die ("Can't rewind $score_file: $!");
    truncate (OUT, 0);
  
    open (SCORE, "$score_file.bak") || die ("Can't read $score_file.bak: $!");
  }
else
  {
    open (SCORE, "$score_file") || die ("Can't read $score_file: $!");
  }

reset_vars();
$group = -1;
@$comment = "";
$co_line = 0;

#Magic starts here
while (<SCORE>)
{
  if ($remove_comments) # Remove '%' comments
    {
      if (/^\s*%/)
        {
          if ($VERBOSE || $DEBUG) {print ($_);}
          next;
        }
    }
  
  if (/\%EOS/ || /#EOS/)
    {
      $comment[$co_line] = $_;
      $co_line++;
      insert_comment();	    
      end_of_score();
      next;
    }
  
  if (/\%BOS/ || /#BOS/)
    {
      insert_comment();
      end_of_score();
    }
  
  if (/^\s*%/ || /^\s*#/ || /^\s*$/)  # put comments in an extra array
    {
      $comment[$co_line] = $_;
      $co_line++;
      next;
    }

  if (/Expires:/i)
    {
      if (/\d{1,2}-\d{1,2}-\d{4}/)
        {
          ($day, $month, $year) = /(\d{1,2})-(\d{1,2})-(\d{4})/;
        }
      else
        {
          ($month, $day, $year) = m#(\d{1,2})/(\d{1,2})/(\d{4})#;
        }
      if ($DEBUG)
        {
          print ("Year: $year / $ak_year\n");
          print ("Month: $month / $ak_month\n");
          print ("Day: $day / $ak_day\n");
        }
      if ($year < $ak_year)
        {
          $is_expired = 1;
        }
      elsif ($year == $ak_year)
        {
          if ($month < $ak_month)
	    {
              $is_expired = 1;
            }
  	  elsif ($month == $ak_month)
  	    {
              if ($day <= $ak_day) {$is_expired = 1;}
            }
        }
      if ($DEBUG && $is_expired) {print ("Entry is expired\n");}
    }

  if (/^\S*\[.*\]\S*$/)  # Found a new groupexpression - entry ends here
    {
      end_of_score();
      insert_comment();
      $group= $sc_line;
    }
  
  if (/Score:/i)
    {
      if ($seen_score) #there was a 'Score:' before entry ends here
        {
          if ($is_expired && $group >= 0) # Save Groupexp if necessary
            {
	      unless ($test_only) {print (OUT $ak_score[$group]);}
            }
          end_of_score();
          insert_comment();
          $group = -1;
        }
      $seen_score = 1;
    }
  insert_comment();
  $ak_score[$sc_line] = $_;
  $sc_line++;
} #while (<SCORE>)

end_of_score();
insert_comment();
end_of_score();

close (SCORE);

unless ($test_only)
{
  close (OUT);
}

############################ END OF MAIN ###############################

sub end_of_score()
{
  unless ($is_expired || $test_only)
    {
      print (OUT @ak_score);
    }
  else
    {
      if ($VERBOSE || $DEBUG)
        {
          print (@ak_score);
          print ("\nNext Entry:\n\n");
        }
    }
  reset_vars();
}

sub insert_comment()
{
  if ($co_line)
    {
      for ($i=0; $i < $co_line; $i++)
        {
          $ak_score[$sc_line] = $comment[$i];
          $sc_line++;
        }
    }
  $co_line = 0;
  @comment = "";
}

sub reset_vars()
{
  @ak_score ="";
  $is_expired = 0;
  $seen_score = 0;
  $sc_line = 0;
}

sub help()
{
  print <<EOF;
cleanscore - Remove expired entries from slrn's Scorefile.

   -V              "Version."  Print Version and exit.
   -h              "Help".     Prints a help message.


   -d              "Debug."    Prints the expiry(?) date for each entry.

   -f <filename>   "File".   Chose "filename" for cleaning
                   instead of the default file.

   -k n            "Keep for N days".
                   Do not remove expired entries, but instead hold them
                   for N more days.  This allows to keep expired entries
                   so you can still edit them, eg change the expiry date.

   -r              "Remove".  Removes comment lines, i.e. lines beginning
                   with '%'. (e.g. remove slrn generated comments
                   when you use '#' for your own comments)
 
   -t              "Test".  Just check for expired entries
                   but do not change the scorefile.
                   Make sense with options -v or -d only.

   -v              "Verbose."  Prints all expired entries to stdout.
EOF
}
