#!/usr/bin/perl

#
#   MailScanner - SMTP E-Mail Virus Scanner
#   Copyright (C) 2002  Julian Field
#
#   $Id: upgrade_MailScanner_conf,v 1.1.2.14 2004/12/01 16:19:32 jkf Exp $
#
#   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#   The author, Julian Field, can be contacted by email at
#      Jules@JulianField.net
#   or by paper mail at
#      Julian Field
#      Dept of Electronics & Computer Science
#      University of Southampton
#      Southampton
#      SO17 1BJ
#      United Kingdom
#

#
# This script will output the contents of a new MailScanner.conf file based
# on an old MailScanner.conf file and a default copy of the new file.
# It is designed for upgrading MailScanner.conf files from one release of
# version 4 to another release of version 4. It will not help with the upgrade
# from version 3 or earlier to version 4, you still have to do that by hand.
#

use FileHandle;
use strict;

my $config = "mailscanner";
my $filedot = "MailScanner.conf";
my $filenew = "MailScanner.new";
my $fileold = "MailScanner.old";
my $filescore = "MailScanner_conf";
if ($0 =~ /languages?.conf$/i) {
  $config = "languages";
  $filedot = "languages.conf";
  $filenew = "languages.new";
  $fileold = "languages.old";
  $filescore = "languages_conf";
}

=head1 NAME

upgrade_MailScanner_conf - upgrades MailScanner.conf config files

=head1 SYNOPSIS

upgrade_MailScanner_conf [--keep-comments] MailScanner.conf MailScanner.conf.newversion > MailScanner.conf.new

RPM
===
If you are using the RPM distributions then try this:

cd /etc/MailScanner

upgrade_MailScanner_conf MailScanner.conf MailScanner.conf.rpmnew > MailScanner.new

mv MailScanner.conf MailScanner.old

mv MailScanner.new  MailScanner.conf

TAR
===
If you are using the tar distribution so that the old version is in
/opt/MailScanner and the new one is in /opt/MailScanner.new then:

cd /opt/MailScanner.new/etc

../bin/upgrade_MailScanner_conf /opt/MailScanner/etc/MailScanner.conf /opt/MailScanner.new/etc/MailScanner.conf > MailScanner.new

mv MailScanner.conf MailScanner.old

mv MailScanner.new  MailScanner.conf

=head1 DESCRIPTION

upgrade_MailScanner_conf helps automate the conversion of older MailScanner.conf config
files to the version of MailScanner you are installing.  This takes care of adding any
new config items that need to be added, removing old deprecated items and updating the
comments, unless you specify --keep-comments to signal you want your old comments left.

=head1 OPTIONS

--keep-comments - tells the script to not update the comments that have changed.

Using --keep-comments can cause you to not realize that there are new/more options
available to you for the item that your old comment was kept with.

=head1 AUTHOR

Julian Field (mailto: Jules@JulianField.net )

=head1 SEE ALSO

perl(1), MailScanner(3)

=cut

sub Usage {
  if ($config eq "mailscanner") {
    print STDERR <<EOU;
Usage:

RPM
===
If you are using the RPM distributions then try this:

cd /etc/MailScanner
upgrade_MailScanner_conf MailScanner.conf MailScanner.conf.rpmnew > MailScanner.new
mv -f MailScanner.conf MailScanner.old
mv -f MailScanner.new  MailScanner.conf

TAR
===
If you are using the tar distribution so that the old version is in
/opt/MailScanner and the new one is in /opt/MailScanner.new then:

cd /opt/MailScanner.new/etc
../bin/upgrade_MailScanner_conf /opt/MailScanner/etc/MailScanner.conf /opt/MailScanner.new/etc/MailScanner.conf > MailScanner.new
mv -f MailScanner.conf MailScanner.old
mv -f MailScanner.new  MailScanner.conf

NOTE
====
To keep your old comments in your original file, add "--keep-comments"
to the command line.  Note that this will mean you don't get to find
out any extra new values you might be able to use in existing "improved"
configuration options.

EOU
  } else {
    print STDERR <<EOLANG;
Usage:

RPM
===
If you are using the RPM distributions then try this:

cd /etc/MailScanner/reports/en
upgrade_languages_conf languages.conf languages.conf.rpmnew > languages.new
mv -f languages.conf languages.old
mv -f languages.new  languages.conf

TAR
===
If you are using the tar distribution so that the old version is in
/opt/MailScanner and the new one is in /opt/MailScanner.new then:

cd /opt/MailScanner.new/etc/reports/en
../../../bin/upgrade_languages_conf /opt/MailScanner/etc/reports/en/languages.conf /opt/MailScanner.new/etc/reports/en/languages.conf > languages.new
mv -f languages.conf languages.old
mv -f languages.new  languages.conf

NOTE
====
To keep your old comments in your original file, add "--keep-comments"
to the command line.  Note that this will mean you don't get to find
out any extra new values you might be able to use in existing "improved"
configuration options.

EOLANG
  }
  exit 1;
}

sub Afterwards {
  print STDERR "\nOnce you have checked that MailScanner.new contains what\n";
  print STDERR "you want, you can then save your old one and move the new\n";
  print STDERR "one into place, using commands like these:\n";
  print STDERR "  mv -f $filedot $fileold\n";
  print STDERR "  mv -f $filenew  $filedot\n";
}


my $keepcomments = 0;
my $i = 0;
while($i<@ARGV) {
  #print STDERR "Option $i is " . $ARGV[$i] . "\n";
  # Match anything vaguely like the correct option
  if ($ARGV[$i] =~ /keep-?com+ent/i) {
    #print STDERR "Found it\n";
    splice @ARGV, $i, 1;
    $keepcomments = 1;
    next;
  }
  $i++;
}


my $oldfname = shift;
my $newfname = shift;

Usage() unless $oldfname && $newfname && -f $oldfname && -f $newfname;

# Read in the old file to get all their current settings
my $oldfh = new FileHandle;
$oldfh->open($oldfname)
  or die "Cannot read old $filedot file $oldfname, $!";
my($key, $value, $origkey, $origline, %oldsettings, $ReadOldValue, %oldkeys);
my(%oldcomments, $comments);
$ReadOldValue = 0;
$comments = "";
while(<$oldfh>) {
  chomp;
  $origline = $_;
  s/#.*$//;
  s/^\s+//;
  s/\s+$//;
  ($comments .= "$origline\n"),next if /^$/;

  undef $origkey;
  undef $key;
  undef $value;
  /^(.*?)\s*=/; # \s*(.*)$/;
  $origkey = $1;
  $origline =~ /=\s*(.*)$/;
  $value = $1;

  # Exception cases
  next if $origkey =~ /MailScannerVersionNumber/i;

  $key = lc($origkey);
  $key =~ s/[^a-z0-9%]//g; # Leave numbers and letters and % only

  $oldsettings{$key} = $value;
  $oldkeys{$key} = $origkey;
  $oldcomments{$key} = $comments;
  $comments = "";
  $ReadOldValue++;
}
$oldfh->close();

# Read in the new file to get all the default settings and new key names
my $newfh = new FileHandle;
$newfh->open($newfname)
  or die "Cannot read new default $filedot file $newfname, $!";
my($defaultvalue, $UsedOldValue, $UsedDefaultValue, $nonpercent, $donepercents);
$UsedOldValue = 0;
$UsedDefaultValue = 0;
$comments = "";
$nonpercent = 0;
$donepercents = 0;
while(<$newfh>) {
  chomp;
  $origline = $_;
  s/#.*$//;
  s/^\s+//;
  s/\s+$//;
  ($comments .= "$origline\n"),next if /^$/;

  undef $origkey;
  undef $key;
  undef $defaultvalue;
  /^(.*?)\s*=/; # \s*(.*)$/;
  $origkey = $1;
  /=\s*(.*)$/;
  $defaultvalue = $1;
  $nonpercent = 1 unless $origkey =~ /^%/;

  # Retain all their %variable% settings
  if ($nonpercent && !$donepercents) {
    # We have hit the first non-%variable% so output all the remaining %%
    my $firstvalue = 1;
    foreach $origkey (keys %oldsettings) {
      next unless $origkey =~ /^%/;
      if ($firstvalue) {
        print "\n";
        $firstvalue = 0;
      }
      print $oldcomments{$origkey};
      print "$origkey = $oldsettings{$origkey}\n";
      delete $oldsettings{$origkey};
      $UsedOldValue++;
    }
    $donepercents = 1;
  }

  $key = lc($origkey);
  $key =~ s/[^a-z0-9%]//g; # Leave numbers and letters and % only

  if (exists $oldsettings{$key}) {
    # They previously had a setting for this parameter
    print $keepcomments?$oldcomments{$key}:$comments;
    print "$origkey = $oldsettings{$key}\n";
    delete $oldsettings{$key};
    $comments = "";
    $UsedOldValue++;
  } else {
    # they are using the new default value for this parameter
    print $comments;
    print "$origline\n";

    # Exception cases
    print STDERR "Added new: $origline\n"
      unless $key =~ /MailScannerVersionNumber/i;

    sleep(2);
    $comments = "";
    $UsedDefaultValue++;
  }
}
$newfh->close();
while (($key, $value) = each %oldsettings) {
  print STDERR "Removed old: $oldkeys{$key} = $value\n";
  sleep(2);
}

print STDERR <<EOL;

Summary
-------
Read $ReadOldValue settings from old $oldfname
Used $UsedOldValue settings from old $oldfname
Used $UsedDefaultValue default settings from new $newfname

Notes
-----
I would advise you to check on any parameters which are different between
the default new conf file and the conf file you just created, so that you
find any parameters whose default values have changed.
If you ran this with a command like this
  upgrade_$filescore $filedot $filedot.rpmnew > $filenew
then you should do
  diff $filedot.rpmnew $filenew
and check for any differences in values you have not changed yourself.

EOL
sleep(5);
Afterwards();
exit 0;

