diff -Naur amavisd-new-2.6.0.orig/amavisd amavisd-new-2.6.0/amavisd
--- amavisd-new-2.6.0.orig/amavisd	2008-05-08 11:12:34.000000000 +0200
+++ amavisd-new-2.6.0/amavisd	2008-07-18 14:36:19.000000000 +0200
@@ -271,7 +271,9 @@
   @ISA = qw(Exporter);
   %EXPORT_TAGS = (
     'dynamic_confvars' =>  # per- policy bank settings
+    # FEC: config option to enable/disable Commtouch support
     [qw(
+      $pa_ctde_enabled
       $policy_bank_name $protocol @inet_acl
       $myhostname $syslog_ident $syslog_facility $syslog_priority
       $log_level $log_templ $log_recip_templ
@@ -2253,7 +2255,19 @@
   $level = 0  if ($DEBUG || $debug_oneshot) && $level > 0;
   my($current_log_level) = c('log_level');
   $current_log_level = 0  if !defined($current_log_level);
-  write_log($level, am_id(), shift, @_)  if $level <= $current_log_level;
+  # FEC: parse log messages for generating statistics
+  my($fmt, @args) = @_;
+  my $msg = sprintf $fmt, @args;
+  if($msg =~ /^Passed SPAM/) {
+  	system("/usr/sbin/pa-statcnt inc smtpmail smtpspam_pass");
+  } elsif($msg =~ /Blocked SPAM/) {
+  	system("/usr/sbin/pa-statcnt inc smtpmail smtpspam_action");
+  } elsif($msg =~ /^\w+\sINFECTED/) {
+  	system("/usr/sbin/pa-statcnt inc smtpmail smtpvirus");
+  } elsif($msg =~ /^Passed CLEAN/) {
+  	system("/usr/sbin/pa-statcnt inc smtpmail");
+  }
+  write_log($level, am_id(), $fmt, @args)  if $level <= $current_log_level;
   1;
 }
 
@@ -8096,6 +8110,8 @@
                      # message passed during a single SMTP session
 use vars qw(@config_files);  # configuration files provided by -c or defaulted
 use vars qw($MSGINFO);
+# FEC: info string for pa-scanqd
+use vars qw($PA_QSCAN_INFO);
 use vars qw($av_output @virusname @detecting_scanners
             $banned_filename_any $banned_filename_all @bad_headers);
 
@@ -9903,7 +9919,10 @@
                         $banned_filename_any, $banned_filename_all?'Y':'N',
                         scalar(@{$msginfo->per_recip_data}));
     }
-
+    # FEC: build info string for pa-scanqd
+    $PA_QSCAN_INFO = sprintf("From: %s (%s) To: %s Message-ID: %s",
+      $builtins{"s"}(), $msginfo->client_addr, join(",", @{$msginfo->recips}),
+      $builtins{"m"}());
     if ($virus_presence_checked) {
       do_log(5, "virus_presence cached, skipping virus_scan");
     } elsif (!$extra_code_antivirus) {
@@ -11613,7 +11632,7 @@
     }
     my($hdr_edits) = Amavis::Out::EditHeader->new;
     $hdr_edits->inherit_header_edits($hdr_edits_inherited);
-    $hdr_edits->prepend_header('X-Quarantine-ID', '<'.$msginfo->mail_id.'>');
+    # FEC: we don't like this --> $hdr_edits->prepend_header('X-Quarantine-ID', '<'.$msginfo->mail_id.'>');
     if ($quarantine_method =~ /^bsmtp:/i) {  # X-Envelope-* would be redundant
     } else {
       # NOTE: RFC2821 mentions possible header flds X-SMTP-MAIL and X-SMTP-RCPT
@@ -11621,12 +11640,15 @@
       # No need with bsmtp, which preserves the envelope.
       my(@blocked_recips) = map { $_->recip_addr_smtp }
                            grep { $_->recip_done } @{$msginfo->per_recip_data};
-      $hdr_edits->prepend_header('X-Envelope-To-Blocked',
-        join(",\n ", @blocked_recips), 1);
+      # FEC: we don't want this information in the quarantined mail
+      # $hdr_edits->prepend_header('X-Envelope-To-Blocked',
+      #  join(",\n ", @blocked_recips), 1);
       $hdr_edits->prepend_header('X-Envelope-To',
         join(",\n ", map {$_->recip_addr_smtp} @{$msginfo->per_recip_data}),1);
       $hdr_edits->prepend_header('X-Envelope-From', $msginfo->sender_smtp);
     }
+    # FEC: add X-Commtouch-RefId header
+    $hdr_edits->add_header('X-Commtouch-RefId', $msginfo->{info_tag}{paCTDERefID});
 #   $hdr_edits->add_header('X-Original-To',
 #       $msginfo->get_header_field_body('to'));
 #   $hdr_edits->delete_header('To');
@@ -11765,6 +11787,13 @@
           $q = '';  # disable quarantine on behalf of this recipient
         }
       }
+      # FEC: maybe there's a bug in amavisd. If there're multiple recipients
+      # and but only for some of them the email is spam, the email will be
+      # quarantined for all recipients. This is a fix for this behaviour.
+      if ($ccat_name =~ /Spam/ && $spam_level_boosted < $kill_level &&
+        !$blacklisted) {
+        $q = '';
+      }
       $q = $rec  if $q ne '' && $q_method =~ /^bsmtp:/i; #orig.recip when BSMTP
       push(@q_addr, $q)  if defined $q && $q ne '' && !grep {$_ eq $q} @q_addr;
     }
@@ -14504,9 +14533,10 @@
     $msginfo->mail_tempdir($TEMPBASE);  # defaults to $TEMPBASE
   } else {
     local($1,$2); my($tempdir) = $attr_ref->{tempdir};
-    $tempdir =~ /^ (?: \Q$TEMPBASE\E | \Q$MYHOME\E )
-                   \/ (?! \.{1,2} \z) [A-Za-z0-9_.-]+ \z/xso
-      or die "Invalid/unexpected temporary directory name '$tempdir'";
+    # FEC: This check is a conflict with for directory structure.
+    # $tempdir =~ /^ (?: \Q$TEMPBASE\E | \Q$MYHOME\E )
+    #               \/ (?! \.{1,2} \z) [A-Za-z0-9_.-]+ \z/xso
+    #  or die "Invalid/unexpected temporary directory name '$tempdir'";
     $msginfo->mail_tempdir(untaint($tempdir));
   }
   my($quar_type);
@@ -19211,6 +19241,7 @@
   return (0,$output,\@virusnames)  if !defined($bare_fnames) || !@$bare_fnames;
   my($one_at_a_time) = ref $command ? 1 : 0;
   my($query_template) = ref $args eq 'ARRAY' ? $args->[0] : $args;
+  $query_template =~ s[{PA}][$Amavis::PA_QSCAN_INFO]g;
   my(@query_template) = $one_at_a_time ? $query_template  # treat it as one arg
                                     : split(' ',$query_template);  # shell-like
   my($bare_fnames_last) = $#{$bare_fnames};
@@ -19344,7 +19375,9 @@
       # $error_str = "unexpected $error_str, output=\"$t_output_trimmed\"";
         $error_str = "unexpected $error_str, output=\"$t_output\"";
         do_log(-2,"run_av (%s) FAILED - %s", $av_name,$error_str);
-        last;  # error, bail out
+	$scan_status = 1;
+	push(@virusnames, "Internal virus scannner error");
+	$output .= $t_output . $eol;
       }
       die "Exceeded allowed time"  if time >= $deadline;
     }
@@ -19386,6 +19419,13 @@
       } else {
         do_log(5, "Calling virus scanners, %d files to scan in %s/parts",
                   scalar(@$bare_fnames_ref), $tempdir);
+	# FEC: change permissions of files and directories to allow access
+	# for pa-scanqd
+        chmod(0755, untaint(sprintf("%s", $tempdir)));
+        chmod(0755, untaint(sprintf("%s/parts", $tempdir)));
+        foreach my $file (@$bare_fnames_ref) {
+	  chmod(0666, untaint(sprintf("%s/parts/%s", $tempdir, $file)));
+	}
       }
     }
     my($scanner_name,$command) = @$av;
@@ -20322,6 +20362,13 @@
       $spam_summary = $per_msg_status->get_report;  # taints $1 and $2 !
     # $spam_summary = $per_msg_status->get_tag('SUMMARY');
       $spam_report  = $per_msg_status->get_tag('REPORT');
+      # FEC: get Commtouch refid from SpamAssassin
+      if(c('pa_ctde_enabled')) {
+          $supplementary_info{'paCTDERefID'} =
+	    $per_msg_status->get_tag('COMMTOUCHID');
+      } else {
+          $supplementary_info{'paCTDERefID'} = '-disabled-';
+      }
       # do the fetching of a TIMING tag last:
       $supplementary_info{'TIMING'} = $per_msg_status->get_tag('TIMING');
     }
@@ -20490,6 +20537,11 @@
     # die "$eval_stat\n"  if $eval_stat !~ /timed out\b/;
     }
   # $hdr_edits->add_header('X-TESTING',$rly_trusted);
+  # FEC: add 'X-Commtouch-RedIf' header
+  if(c('pa_ctde_enabled')) {
+    $hdr_edits->add_header('X-Commtouch-RefId',
+      $supplementary_info_ref->{paCTDERefID});
+  }
   # $hdr_edits->add_header('X-Relay-Countries',$rly_country)
   #   if $rly_country ne '' && $all_local &&
   #      $allowed_hdrs && $allowed_hdrs->{lc('X-Relay-Countries')};

