This file is indexed.

/usr/lib/debbugs/spamscan-sa is in debbugs 2.6.0.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#! /usr/bin/perl
# spamassassin handling split from spamscan
#

# unfortunatly we can't use strict;

use warnings;
use strict;
use Mail::CrossAssassin;
use Mail::SpamAssassin;

use Debbugs::Config qw(:config);
# New versions of debbugs will not allow use in /etc/debbugs/config
use POSIX qw(strftime);
my $spam_mailbox = strftime($config{spam_mailbox},gmtime);
my $cross_mailbox = strftime($config{spam_crossassassin_mailbox},gmtime);

umask 002;
$| = 1;
STDOUT->autoflush(1);

sub header_or_empty ($$) {
    my ($mail, $hdr) = @_;
    my $value = $mail->get_header($hdr);
    if (defined $value) {
	chomp $value;
        # replace newlines with '\n'
	$value =~ s/\n/\\n/g;
	return $value;
    }
    return '';
}

my $spam = Mail::SpamAssassin->new({
        dont_copy_prefs => 1,
        site_rules_filename => $config{spam_rules_dir},
        userprefs_filename => $config{spam_user_prefs},
        	local_tests_only => ($config{spam_local_tests_only} || 0),
        	debug => ($ENV{DEBBUGS_SPAM_DEBUG} || 0),
});
$spam->compile_now(1); # use all user preferences

while (my $id = <STDIN>) {
    chomp $id;
    my $nf = <STDIN>;
    if (not defined $nf) {
	 die "Could not read nf: $!";
    }
    chomp $nf;
    unless (rename "incoming/S$id", "incoming/R$id") {
	die "Could not rename incoming/S$id: $!";
    }
    my $out = "[$nf] $id scanning ...\n";
    open MESSAGE, "< incoming/R$id" or die "open incoming/R$id: $!";
    # Kludge to work around Received: then From_ weirdness in receive;
    # remove when receive is fixed? We may continue to need it for
    # reprocessing old messages.
    my @textarray = <MESSAGE>;
    if ($textarray[0] !~ /^From /) {
	($textarray[0], $textarray[1]) = ($textarray[1], $textarray[0]);
    }
    close MESSAGE;
    my $mail = $spam->parse(\@textarray);
    
    my $messageid = header_or_empty($mail, 'Message-Id');
    $out .= "  From: " . header_or_empty($mail, 'From') . "\n";
    $out .= "  Subject: ". header_or_empty($mail, 'Subject') . "\n";
    $out .= "  Date: " . header_or_empty($mail, 'Date') . "\n";
    $out .= "  Message-Id: $messageid\n";
    my $keys = ca_keys($mail->get_body);
    print  "$keys\n$messageid\n"
	or die "Could not send keys: $!";
    my $ca_score = <STDIN>;
    die "Could not read ca_score: $!" if not defined $ca_score;
    chomp $ca_score;
    my $todo = 0;
    my ($headers, $body);
    my $seen = <STDIN>;
    die "Child could not read seen: $!" if not defined $seen;
    chomp $seen;
    my $status;
    my $nseen = $seen;
    if ($seen) {
	$todo = 1;
	$headers = join('',$mail->get_all_headers());
	$body = join('', @{$mail->get_body()});
	$out .= "  spam $seen duplicate\n";
    } else {
	$status = $spam->check($mail);
	($headers, $body) = split /\n\n/, $status->rewrite_mail(), 2;
	$headers .= "\n";
	$body .= "\n";
	
	if ($status->is_spam()) {
	    $todo = 1;
	    my $score = sprintf "%.1f/%.1f %d",
	            $status->get_score(), $status->get_required_score(),
	            $ca_score;
	    $out .= "  spam $score\n";
	    $nseen = $score;
	} elsif ($status->get_score() > 0 && $ca_score >= $config{spam_max_cross}) {
	    $todo = 2;
	    my $score = sprintf "%.1f/%.1f %d",
	    $status->get_score(), $status->get_required_score(), $ca_score;
	    $out .= "  spam $score\n";
	    $nseen = $score;
	} else {
	    my ($before, $received, $after) = $headers =~
		/(^.*?)(^Received\: \(at .*?\n)(.*$)/ms;
	    open OUT, "> incoming/I$id" or die "open incoming/I$id: $!";
	    print OUT $received . $before . $after
		or die "print incoming/I$id: $!";
	    if ($ca_score > 1) {
		print OUT "X-CrossAssassin-Score: $ca_score\n"
		    or die "print incoming/I$id: $!";
	    }
	    print OUT "\n" or die "print incoming/I$id: $!";
	    print OUT $body or die "print incoming/I$id: $!";
	    close OUT or die "close incoming/I$id: $!";
	    unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
	    $out .= sprintf "  ok %.1f/%.1f %d\n",
	    $status->get_score(), $status->get_required_score(),
	            $ca_score;
	}
    }
    print "$todo\n";
    <STDIN>;
    if ($todo) {
	open OUT, '>>', ($todo == 1) ? $spam_mailbox : $cross_mailbox
	    or die "Could not open assassinated: $!";
	print OUT $headers or die "print assassinated: $!";
	if ($ca_score > 1) {
	    print OUT "X-CrossAssassin-Score: $ca_score\n"
		or die "print assassinated: $!";
	}
	print OUT "\n" or die "print assassinated: $!";
	$body =~ s/^From />From /gm;
	print OUT $body or die "print assassinated: $!";
	close OUT or die "Close assassinated: $!";
	unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
    }
    $out =~ tr/\n/\r/;
    print "$nseen\n$out\n";
    $status->finish() unless($seen);
    $mail->finish();
}