#!/usr/bin/perl
# cpanel12 - spamd_y2010_fix                    Copyright(c) 1997-2009 cPanel, Inc.
#                                                           All Rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
#
#
# Version 1.0 - Initial Version
# Version 1.1 - Add check to make sure the FH_DATE_PAST_20XX rule is actually in use before we run sa-update to accomadate custom installs
# Version 1.2 - Revised the sa finder to check for -x instead of -e
# Version 1.3 - Fix name of app
# Version 1.4 - Fixed typo, added additional verification
# Version 1.5 - Adding missing exits for failures
# Version 1.6 - Updated regex test to not match older updates of the sa rules
#
use strict;
use IPC::Open3         ();
use Mail::SpamAssassin ();

my $app = 'spamd_y2010_fix';

$SIG{'ALRM'} = sub {
    die "$app: timed out";
};

alarm(3000);

$| = 1;
my $installed_version = $Mail::SpamAssassin::VERSION;

print "$app: version 1.6\n";

if ( -e '/var/lib/spamassassin/' . $installed_version . '/updates_spamassassin_org/72_active.cf' ) {
    if ( open( my $fh, '<', '/var/lib/spamassassin/' . $installed_version . '/updates_spamassassin_org/72_active.cf' ) ) {
        local $/;
        my $file_contents = readline($fh);
        close($fh);

        # It may be an updated ruleset with the old rule /^header\s*FH_DATE_PAST_20XX\s*Date\s*\=\~\s*\/20\[1/m
        # 1 changed to 2
        if ( $file_contents =~ /^header\s*FH_DATE_PAST_20XX\s*Date\s*\=\~\s*\/20\[2/m ) {
            print "$app: spamassassin rules have already been updated.\n";
            exit 0;
        }
    }
}

my @spamlocs     = find_sa_bin('spamassassin');
my $spamassassin = shift @spamlocs;

if ( !$spamassassin || !-e $spamassassin || !-x $spamassassin ) {
    print "$app: spamassassin is missing!\n";
    exit 1;
}

if ( my $pid = IPC::Open3::open3( my $spam_fh, my $spam_rdr, ">&STDERR", $spamassassin, '-L', '-t' ) ) {
    print {$spam_fh} "From: root\nDate: Sat, 2 Jan 2010 02:39:43 +0000\nSubject: test\n\ntest\n.";
    close($spam_fh);
    alarm(200);
    local $/;
    my $report = readline($spam_rdr);
    close($spam_rdr);
    waitpid( $pid, 0 );
    if ( $report !~ /FH_DATE_PAST_20XX/ ) {
        print "$app: spamassassin does not have the bad FH_DATE_PAST_20XX rule or it has already been updated!\n";
        exit 0;
    }
    else {
        print "$app: spamassassin has the FH_DATE_PAST_20XX rule, update proceeding.\n";
    }
    alarm(2900);
}
else {
    print "$app: failed to run spamassassin to test.\n";
    exit 1;
}

print "$app: spamassassin rule update has not yet run.\n";
my @locs     = find_sa_bin('sa-update');
my $saupdate = shift @locs;

if ( !$saupdate || !-e $saupdate || !-x $saupdate ) {
    print "$app: sa-update is missing!\n";
    exit 1;
}

print "Running sa-update ($saupdate).....";
system( $saupdate, '-D' );
print "Done\n";

if ($?) {
    print "$app: sa-update failed with Error code ", $? >> 8;
    exit 1;
}

system '/scripts/restartsrv_spamd';

print "$app: spamassassin rules updated successfully!\n";
exit 0;

sub find_sa_bin {
    my $bin = shift;
    print "Attempting to locate $bin scripts installed on the system ...";
    my @sabin;
    my @locations = qw( /usr/bin /usr/local/bin );
    foreach my $loc (@locations) {
        if ( -x $loc . '/' . $bin ) {
            print "Located ..$loc/$bin..";
            push @sabin, $loc . '/' . $bin;
        }
    }
    print "Done.\n";
    return @sabin;
}
