Parent Directory | Revision Log | Patch
--- spamassassin/trunk/spamd/spamd.raw 2005/05/18 12:19:41 170739 +++ spamassassin/trunk/spamd/spamd.raw 2005/05/18 12:29:42 170740 @@ -1047,30 +1047,6 @@ sub accept_a_conn { info(sprintf("spamd: skipped large message in %3d seconds", time - $start)); } - # COLLABREPORT must come before REPORT, since the regex is overgenerous - elsif (/(COLLABREPORT) SPAMC\/(.*)/) { - my $method = $1; - my $version = $2; - eval { - Mail::SpamAssassin::Util::trap_sigalrm_fully(sub { - die "child processing timeout"; - }); - alarm $timeout_child if ($timeout_child); - report($method, $version, $start, $remote_hostname, $remote_hostaddr); - }; - alarm 0; - - if ($@) { - if ($@ =~ /child processing timeout/) { - service_timeout("($timeout_child second timeout while trying to $method)"); - } else { - warn "spamd: $@"; - } - $client->close(); - return 0; - } - } - # It might be a CHECK message, meaning that we should just check # if it's spam or not, then return the appropriate response. # If we get the PROCESS command, the client is going to send a @@ -1098,7 +1074,7 @@ sub accept_a_conn { } } - elsif (/(LEARN) SPAMC\/(.*)/) { + elsif (/(TELL) SPAMC\/(.*)/) { my $method = $1; my $version = $2; eval { @@ -1106,7 +1082,7 @@ sub accept_a_conn { die "child processing timeout"; }); alarm $timeout_child if ($timeout_child); - learn($method, $version, $start, $remote_hostname, $remote_hostaddr); + dotell($method, $version, $start, $remote_hostname, $remote_hostaddr); }; alarm 0; @@ -1368,20 +1344,26 @@ sub check { return 1; } -sub learn { +sub dotell { my ($method, $version, $start_time, $remote_hostname, $remote_hostaddr) = @_; local ($_); my $expected_length; - my $learn_type; - my $forget = 0; - my $isspam = 1; my $hdrs = {}; return 0 unless (parse_headers($hdrs, $client)); $expected_length = $hdrs->{expected_length}; - $learn_type = $hdrs->{learn_type}; + + if ($hdrs->{set_local} && $hdrs->{remove_local}) { + protocol_error("Unable to set local and remove local in the same operation."); + return 0; + } + + if ($hdrs->{set_remote} && $hdrs->{remove_remote}) { + protocol_error("Unable to set remote and remove remote in the same operation."); + return 0; + } &handle_setuid_to_user if ($setuid_to_user && $> == 0); @@ -1413,30 +1395,6 @@ sub learn { $msgid ||= "(unknown)"; $current_user ||= "(unknown)"; - my $learn_type_desc; - my $learn_type_desc_past; - - if ($learn_type == 0) { - $learn_type_desc = "learning spam"; - $learn_type_desc_past = "learned spam"; - $isspam = 1; - } - elsif ($learn_type == 1) { - $learn_type_desc = "learning ham"; - $learn_type_desc_past = "learned ham"; - $isspam = 0; - } - elsif ($learn_type == 2) { - $learn_type_desc = "forgetting"; - $learn_type_desc_past = "forgot"; - $forget = 1; - } - - info("spamd: $learn_type_desc" - . " message $msgid" - . ( $rmsgid ? " aka $rmsgid" : "" ) - . " for ${current_user}:$>"); - # Check length if we're supposed to. if (defined $expected_length && $actual_length != $expected_length) { protocol_error("(Content-Length mismatch: Expected $expected_length bytes, got $actual_length bytes)"); @@ -1444,110 +1402,49 @@ sub learn { return 0; } - my $status = $spamtest->learn($mail, undef, $isspam, $forget); - my $hdr; - - if ($status->did_learn()) { - $hdr .= "Learned: Yes"; - } - else { - $hdr .= "Learned: No"; - } - - print $client "SPAMD/1.1 $resphash{$resp} $resp\r\n", - $hdr . "\r\n\r\n"; - - my $scantime = sprintf( "%.1f", time - $start_time ); - - info("spamd: $learn_type_desc_past message for $current_user:$> in" - . " $scantime seconds, $actual_length bytes"); - $status->finish(); # added by jm to allow GC'ing - $mail->finish(); - return 1; -} - -sub report { - my ($method, $version, $start_time, $remote_hostname, $remote_hostaddr) = @_; - local ($_); - my $expected_length; - my $report_type; - - my $hdrs = {}; - - return 0 unless (parse_headers($hdrs, $client)); - - $expected_length = $hdrs->{expected_length}; - $report_type = $hdrs->{collabreport_type}; - - &handle_setuid_to_user if ($setuid_to_user && $> == 0); + my @did_set; + my @did_remove; - if ($opt{'sql-config'} && !defined($current_user)) { - unless (handle_user_sql('nobody')) { - service_unavailable_error("Error fetching user preferences via SQL"); - return 0; - } - } + if ($hdrs->{set_local}) { + my $status = $spamtest->learn($mail, undef, ($hdrs->{message_class} eq 'spam' ? 1 : 0), 0); - if ($opt{'ldap-config'} && !defined($current_user)) { - handle_user_ldap('nobody'); + push(@did_set, 'local') if ($status->did_learn()); + $status->finish(); } - my $resp = "EX_OK"; - - # generate mail object from input - my ($mail, $actual_length) = parse_body($client, $expected_length); - - # Check length if we're supposed to. - if (defined $expected_length && $actual_length != $expected_length) { - protocol_error("(Content-Length mismatch: Expected $expected_length bytes, got $actual_length bytes)"); - $mail->finish(); - return 0; - } + if ($hdrs->{remove_local}) { + my $status = $spamtest->learn($mail, undef, undef, 1); - if ( $mail->get_header("X-Spam-Checker-Version") ) { - my $new_mail = $spamtest->parse($spamtest->remove_spamassassin_markup($mail), 1); - $mail->finish(); - $mail = $new_mail; + push(@did_remove, 'local') if ($status->did_learn()); + $status->finish(); } - # attempt to fetch the message ids - my ($msgid, $rmsgid) = parse_msgids($mail); + if ($hdrs->{set_remote}) { + require Mail::SpamAssassin::Reporter; + my $msgrpt = Mail::SpamAssassin::Reporter->new($spamtest, $mail); - $msgid ||= "(unknown)"; - $current_user ||= "(unknown)"; + push(@did_set, 'remote') if ($msgrpt->report()); + } - my $report_type_desc; - my $report_type_desc_past; + if ($hdrs->{remove_remote}) { + require Mail::SpamAssassin::Reporter; + my $msgrpt = Mail::SpamAssassin::Reporter->new($spamtest, $mail); - if ($report_type == 0) { - $report_type_desc = "reporting spam"; - $report_type_desc_past = "reported spam"; - } - elsif ($report_type == 1) { - $report_type_desc = "revoking ham"; - $report_type_desc_past = "revoked ham"; - } - - info("spamd: $report_type_desc" - . " message $msgid" - . ( $rmsgid ? " aka $rmsgid" : "" ) - . " for ${current_user}:$>"); + push(@did_remove, 'remote') if ($msgrpt->revoke()); + } my $hdr; - my $status = 1; + my $info_set_str; + my $info_remove_str; - if ($report_type) { - $status = $spamtest->revoke_as_spam($mail); - } - else { - $status = $spamtest->report_as_spam($mail); + if (scalar(@did_set)) { + $hdr .= "DidSet: " . join(',', @did_set) . "\r\n"; + $info_set_str = " Setting " . join(',', @did_set) . " "; } - if ($status) { - $hdr .= "Reported: Yes"; - } - else { - $hdr .= "Reported: No"; + if (scalar(@did_remove)) { + $hdr .= "DidRemove: " . join(',', @did_remove) . "\r\n"; + $info_remove_str = " Removing " . join(',', @did_remove) . " "; } print $client "SPAMD/1.1 $resphash{$resp} $resp\r\n", @@ -1555,7 +1452,7 @@ sub report { my $scantime = sprintf( "%.1f", time - $start_time ); - info("spamd: $report_type_desc_past message for $current_user:$> in" + info("spamd:$info_set_str$info_remove_str for $current_user:$> in" . " $scantime seconds, $actual_length bytes"); $mail->finish(); @@ -1571,6 +1468,7 @@ sub parse_headers { # max 255 headers for my $hcount ( 0 .. 255 ) { my $line = $client->getline; + unless (defined $line) { protocol_error("(EOF during headers)"); return 0; @@ -1590,11 +1488,14 @@ sub parse_headers { elsif ($header eq 'User') { return 0 unless &got_user_header($hdrs, $header, $value); } - elsif ($header eq 'Learn-type') { - return 0 unless &got_learn_type_header($hdrs, $header, $value); + elsif ($header eq 'Message-class') { + return 0 unless &got_message_class_header($hdrs, $header, $value); + } + elsif ($header eq 'Set') { + return 0 unless &got_set_header($hdrs, $header, $value); } - elsif ($header eq 'CollabReport-type') { - return 0 unless &got_collabreport_type_header($hdrs, $header, $value); + elsif ($header eq 'Remove') { + return 0 unless &got_remove_header($hdrs, $header, $value); } } @@ -1672,33 +1573,49 @@ sub got_clen_header { return 1; } -sub got_learn_type_header { +sub got_message_class_header { my ($hdrs, $header, $value) = @_; - if ($value !~ /^(\d*)$/) { - protocol_error("(Learn-type contains non-numeric bytes)"); + + unless (lc($value) ne 'spam' || lc($value) ne 'ham') { + protocol_error("(Message-class header contains invalid class)"); return 0; } - my $type = $1; - if ($type != 0 && $type != 1 && $type != 2) { - protocol_error("(Learn-type contains invalid type)"); - return 0; + $hdrs->{message_class} = $value; + + return 1; +} + +sub got_set_header { + my ($hdrs, $header, $value) = @_; + + $hdrs->{set_local} = 0; + $hdrs->{set_remote} = 0; + + if ($value =~ /local/i) { + $hdrs->{set_local} = 1; } - $hdrs->{learn_type} = $type; + + if ($value =~ /remote/i) { + $hdrs->{set_remote} = 1; + } + return 1; } -sub got_collabreport_type_header { +sub got_remove_header { my ($hdrs, $header, $value) = @_; - if ($value !~ /^(\d*)$/) { - protocol_error("(CollabReport-type contains non-numeric bytes)"); - return 0; + + $hdrs->{remove_local} = 0; + $hdrs->{remove_remote} = 0; + + if ($value =~ /local/i) { + $hdrs->{remove_local} = 1; } - my $type = $1; - if ($type != 0 && $type != 1) { - protocol_error("(CollabReport-type contains invalid type)"); - return 0; + + if ($value =~ /remote/i) { + $hdrs->{remove_remote} = 1; } - $hdrs->{collabreport_type} = $type; + return 1; }
infrastructure at apache.org | ViewVC Help |
Powered by ViewVC 1.1.26 |