# <@LICENSE>
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to you under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at:
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# </@LICENSE>

# Author:  Steve Freegard <steve.freegard@fsl.com>

package Mail::SpamAssassin::Plugin::SaveHits;
my $VERSION = 0.1;

use strict;
use Mail::SpamAssassin::Plugin;
use Digest::SHA1 qw{sha1_hex};
use File::Path;
use File::Basename;
use vars qw(@ISA);
@ISA = qw(Mail::SpamAssassin::Plugin);

sub dbg {
  Mail::SpamAssassin::Plugin::dbg ("SaveHits: @_");
}

sub new {
  my ($class, $mailsa) = @_;

  $class = ref($class) || $class;
  my $self = $class->SUPER::new($mailsa);
  bless ($self, $class);
  return $self;
}

sub parse_config {
 my ($self,$params) = @_;
 return 0 unless ($params->{key} =~ /^savehits_(\S+)$/i);
 my $key = $1;
 if($key =~ /^rule$/i) {
  my(@split) = split(/\s+/,$params->{value});
  foreach my $rule (@split) {
   $self->{main}->{conf}->{'savehits_rules'}->{$rule} = 1 if $rule;
   dbg("Added rule $rule to save list");
  }
 }
 if($key =~ /^dir$/i) {
  $self->{main}->{conf}->{$params->{key}} = $params->{value};
 }
 $self->inhibit_further_callbacks();
 return 1;
}


sub check_end {
 my ($self, $params) = @_; 
 my ($pms) = $params->{permsgstatus};
 my ($saverules) = $self->{main}->{conf}->{'savehits_rules'};
 my ($savedir) = $self->{main}->{conf}->{'savehits_dir'};
 return 0 if not $savedir;
 my ($msg) = $pms->get_message();
 my ($pristine) = $msg->get_pristine();
 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
 my ($date) = sprintf("%d%02d%02d",$year+1900,$mon+1,$mday);
 my(@hits) = split(',',($pms->get_names_of_tests_hit.','.$pms->get_names_of_subtests_hit));
 my(%rules);
 map { $rules{$_}++ } @hits;
 foreach my $rule (keys %rules) {
  if(defined($saverules->{$rule})) {
   dbg("Got hit: $rule");
   my $hash = sha1_hex($pristine);
   my $filename = "$savedir/msgs/$date/$hash";
   my $linkname = "$savedir/rules/$rule/$date/$hash";
   # Untaint
   $filename =~ /^([\/-\@\w.]+)$/;
   $filename = $1;
   $linkname =~ /^([\/-\@\w.]+)$/;
   $linkname = $1;
   eval { mkpath(dirname($filename)); };
   if ($@) {
    dbg("error: $@");
    return 0;
   }
   eval { mkpath(dirname($linkname)); };
   if ($@) {
    dbg("error: $@");
    return 0;
   }
   if (! -f $filename) {
    dbg("Saving message to $filename");
    eval { open(FILE, ">$filename"); };
    if ($@) {
     dbg("error: $@");
     return 0;
    }
    print FILE $pristine;
    close(FILE);
   }
   if ((! -f $linkname) && (-f $filename)) {
    dbg("Creating symlink $linkname to $filename");
    eval { symlink($filename, $linkname); };
    if ($@) {
     dbg("error: $@");
     return 0;
    }
  }
  }
 }
 return 1;
}

1;
