patch-src::MultiCaseSensHeadersCheck-3.3.0.patch by Victor Ustugov diff -urN lib.orig/Mail/SpamAssassin/Message/Node.pm lib/Mail/SpamAssassin/Message/Node.pm --- lib.orig/Mail/SpamAssassin/Message/Node.pm Thu Jan 21 14:14:56 2010 +++ lib/Mail/SpamAssassin/Message/Node.pm Wed Mar 3 16:46:35 2010 @@ -57,6 +57,8 @@ my $self = { headers => {}, raw_headers => {}, + headers_case => {}, + raw_headers_case => {}, header_order => [] }; @@ -179,6 +181,13 @@ push @{ $self->{'raw_headers'}->{$key} }, $raw_value; + if ( !exists $self->{'headers_case'}->{$rawkey} ) { + $self->{'headers_case'}->{$rawkey} = []; + $self->{'raw_headers_case'}->{$rawkey} = []; + } + push @{ $self->{'headers_case'}->{$rawkey} }, $self->_decode_header($raw_value); + push @{ $self->{'raw_headers_case'}->{$rawkey} }, $raw_value; + return $self->{'headers'}->{$key}->[-1]; } @@ -192,6 +201,28 @@ } } +sub header_case { + my $self = shift; + my $rawkey = shift; + + return unless ( defined $rawkey ); + + my $key = $rawkey; + + # Trim whitespace off of the header keys + $key =~ s/^\s+//; + $key =~ s/\s+$//; + + if (wantarray) { + return unless exists $self->{'headers_case'}->{$key}; + return @{ $self->{'headers_case'}->{$key} }; + } + else { + return '' unless exists $self->{'headers_case'}->{$key}; + return $self->{'headers_case'}->{$key}->[-1]; + } +} + =item raw_header() Retrieves the raw version of headers from a specific MIME part. The only @@ -227,6 +258,24 @@ } } +sub raw_header_case { + my $self = shift; + my $key = shift; + + # Trim whitespace off of the header keys + $key =~ s/^\s+//; + $key =~ s/\s+$//; + + if (wantarray) { + return unless exists $self->{'raw_headers_case'}->{$key}; + return @{ $self->{'raw_headers_case'}->{$key} }; + } + else { + return '' unless exists $self->{'raw_headers_case'}->{$key}; + return $self->{'raw_headers_case'}->{$key}->[-1]; + } +} + =item add_body_part() Adds a Node child object to the current node object. @@ -555,6 +604,8 @@ foreach ( grep(/^${hdr}$/i, keys %{$self->{'headers'}}) ) { delete $self->{'headers'}->{$_}; delete $self->{'raw_headers'}->{$_}; + delete $self->{'headers_case'}->{$_}; + delete $self->{'raw_headers_case'}->{$_}; } my @neworder = grep(!/^${hdr}$/i, @{$self->{'header_order'}}); @@ -655,6 +706,35 @@ } else { return @hdrs ? $hdrs[-1] : undef; + } +} + +sub get_header_case { + my ($self, $hdr, $raw) = @_; + $raw ||= 0; + + # And now pick up all the entries into a list + # This is assumed to include a newline at the end ... + # This is also assumed to have removed continuation bits ... + + # Deal with the possibility that header() or raw_header() returns undef + my @hdrs; + if ( $raw ) { + if (@hdrs = $self->raw_header_case($hdr)) { + @hdrs = map { s/\r?\n\s+/ /g; $_; } @hdrs; + } + } + else { + if (@hdrs = $self->header_case($hdr)) { + @hdrs = map { "$_\n" } @hdrs; + } + } + + if (wantarray) { + return @hdrs; + } + else { + return @hdrs ? $hdrs[-1] : undef; } } diff -urN lib.orig/Mail/SpamAssassin/PerMsgStatus.pm lib/Mail/SpamAssassin/PerMsgStatus.pm --- lib.orig/Mail/SpamAssassin/PerMsgStatus.pm Thu Jan 21 14:15:20 2010 +++ lib/Mail/SpamAssassin/PerMsgStatus.pm Wed Mar 3 19:50:12 2010 @@ -1521,10 +1521,26 @@ sub _get { my ($self, $request) = @_; + if ($request =~ /\|/) { + my($res); + foreach my $subrequest (split(/\|/, $request)) { + my $getcase = ($subrequest =~ s/:case//); + my $getraw = ($subrequest eq 'ALL' || $subrequest =~ s/:raw$//); + if ($getcase) { + $res .= '|'.join ("\n", $self->{msg}->get_header_case($subrequest, $getraw)); + } else { + $res .= '|'.join ("\n", $self->{msg}->get_header($subrequest, $getraw)); + } + } + $res =~ s/^\|//; + return($res); + } + my $result; my $getaddr = 0; my $getname = 0; my $getraw = 0; + my $getcase = 0; # special queries - process and strip modifiers if (index($request,':') >= 0) { # triage @@ -1533,6 +1549,7 @@ if ($1 eq 'raw') { $getraw = 1 } elsif ($1 eq 'addr') { $getaddr = $getraw = 1 } elsif ($1 eq 'name') { $getname = 1 } + elsif ($1 eq 'case') { $getcase = 1 } } } @@ -1607,8 +1624,18 @@ } # a conventional header else { - my @results = $getraw ? $self->{msg}->raw_header($request) - : $self->{msg}->get_header($request); +# my @results = $getraw ? $self->{msg}->raw_header($request) +# : $self->{msg}->get_header($request); + my(@results); + if ($getcase and $getraw) { + @results = $self->{msg}->raw_header_case($request); + } elsif ($getcase and !$getraw) { + @results = $self->{msg}->get_header_case($request); + } elsif (!$getcase and $getraw) { + @results = $self->{msg}->raw_header($request); + } elsif (!$getcase and !$getraw) { + @results = $self->{msg}->get_header($request); + } # dbg("message: get(%s) = %s", $request, join(", ",@results)); if (@results) { $result = join('', @results);