| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # <@LICENSE> | 
| 2 |  |  |  |  |  |  | # Licensed to the Apache Software Foundation (ASF) under one or more | 
| 3 |  |  |  |  |  |  | # contributor license agreements.  See the NOTICE file distributed with | 
| 4 |  |  |  |  |  |  | # this work for additional information regarding copyright ownership. | 
| 5 |  |  |  |  |  |  | # The ASF licenses this file to you under the Apache License, Version 2.0 | 
| 6 |  |  |  |  |  |  | # (the "License"); you may not use this file except in compliance with | 
| 7 |  |  |  |  |  |  | # the License.  You may obtain a copy of the License at: | 
| 8 |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  | #     http://www.apache.org/licenses/LICENSE-2.0 | 
| 10 |  |  |  |  |  |  | # | 
| 11 |  |  |  |  |  |  | # Unless required by applicable law or agreed to in writing, software | 
| 12 |  |  |  |  |  |  | # distributed under the License is distributed on an "AS IS" BASIS, | 
| 13 |  |  |  |  |  |  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 14 |  |  |  |  |  |  | # See the License for the specific language governing permissions and | 
| 15 |  |  |  |  |  |  | # limitations under the License. | 
| 16 |  |  |  |  |  |  | # </@LICENSE> | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | =head1 NAME | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | Mail::SpamAssassin::Plugin::WhiteListSubject - whitelist by Subject header | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | loadplugin Mail::SpamAssassin::Plugin::WhiteListSubject | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | header SUBJECT_IN_WHITELIST eval:check_subject_in_whitelist() | 
| 27 |  |  |  |  |  |  | header SUBJECT_IN_BLACKLIST eval:check_subject_in_blacklist() | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | score SUBJECT_IN_WHITELIST -100 | 
| 30 |  |  |  |  |  |  | score SUBJECT_IN_BLACKLIST 100 | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | whitelist_subject [Bug *] | 
| 33 |  |  |  |  |  |  | blacklist_subject Make Money Fast | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | This SpamAssassin plugin module provides eval tests for whitelisting and | 
| 38 |  |  |  |  |  |  | blacklisting particular strings in the Subject header. String will match | 
| 39 |  |  |  |  |  |  | anywhere in the subject. The value for whitelist_subject or blacklist_subject | 
| 40 |  |  |  |  |  |  | are strings which may contain file -glob -style patterns, similar to the | 
| 41 |  |  |  |  |  |  | other whitelist_* config options. Note that each subject/string must be a | 
| 42 |  |  |  |  |  |  | separate *_subject command, all whitespace is included in the string. | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | =cut | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | use Mail::SpamAssassin::Plugin; | 
| 48 | 22 |  |  | 22 |  | 163 | use strict; | 
|  | 22 |  |  |  |  | 58 |  | 
|  | 22 |  |  |  |  | 625 |  | 
| 49 | 22 |  |  | 22 |  | 119 | use warnings; | 
|  | 22 |  |  |  |  | 58 |  | 
|  | 22 |  |  |  |  | 498 |  | 
| 50 | 22 |  |  | 22 |  | 138 | # use bytes; | 
|  | 22 |  |  |  |  | 64 |  | 
|  | 22 |  |  |  |  | 683 |  | 
| 51 |  |  |  |  |  |  | use re 'taint'; | 
| 52 | 22 |  |  | 22 |  | 126 |  | 
|  | 22 |  |  |  |  | 46 |  | 
|  | 22 |  |  |  |  | 14191 |  | 
| 53 |  |  |  |  |  |  | our @ISA = qw(Mail::SpamAssassin::Plugin); | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | # constructor: register the eval rule | 
| 56 |  |  |  |  |  |  | my $class = shift; | 
| 57 |  |  |  |  |  |  | my $mailsaobject = shift; | 
| 58 | 63 |  |  | 63 | 1 | 208 |  | 
| 59 | 63 |  |  |  |  | 131 | $class = ref($class) || $class; | 
| 60 |  |  |  |  |  |  | my $self = $class->SUPER::new($mailsaobject); | 
| 61 | 63 |  | 33 |  |  | 361 | bless ($self, $class); | 
| 62 | 63 |  |  |  |  | 329 |  | 
| 63 | 63 |  |  |  |  | 169 | $self->register_eval_rule ("check_subject_in_whitelist"); | 
| 64 |  |  |  |  |  |  | $self->register_eval_rule ("check_subject_in_blacklist"); | 
| 65 | 63 |  |  |  |  | 277 |  | 
| 66 | 63 |  |  |  |  | 189 | $self->set_config($mailsaobject->{conf}); | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 63 |  |  |  |  | 242 | return $self; | 
| 69 |  |  |  |  |  |  | } | 
| 70 | 63 |  |  |  |  | 551 |  | 
| 71 |  |  |  |  |  |  | my ($self, $conf) = @_; | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | my @cmds; | 
| 74 | 63 |  |  | 63 | 0 | 148 |  | 
| 75 |  |  |  |  |  |  | push(@cmds, { | 
| 76 | 63 |  |  |  |  | 132 | setting => 'whitelist_subject', | 
| 77 |  |  |  |  |  |  | default => {}, | 
| 78 |  |  |  |  |  |  | type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST, | 
| 79 |  |  |  |  |  |  | code => sub { | 
| 80 |  |  |  |  |  |  | my ($self, $key, $value, $line) = @_; | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | $value = lc $value; | 
| 83 | 0 |  |  | 0 |  | 0 | my $re = $value; | 
| 84 |  |  |  |  |  |  | $re =~ s/[\000\\\(]/_/gs;                   # paranoia | 
| 85 | 0 |  |  |  |  | 0 | $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g;        # escape any possible metachars | 
| 86 | 0 |  |  |  |  | 0 | $re =~ tr/?/./;                             # "?" -> "." | 
| 87 | 0 |  |  |  |  | 0 | $re =~ s/\*+/\.\*/g;                        # "*" -> "any string" | 
| 88 | 0 |  |  |  |  | 0 | $conf->{$key}->{$value} = ${re}; | 
| 89 | 0 |  |  |  |  | 0 | }}); | 
| 90 | 0 |  |  |  |  | 0 |  | 
| 91 | 0 |  |  |  |  | 0 | push(@cmds, { | 
| 92 | 63 |  |  |  |  | 685 | setting => 'blacklist_subject', | 
| 93 |  |  |  |  |  |  | default => {}, | 
| 94 |  |  |  |  |  |  | type => $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST, | 
| 95 |  |  |  |  |  |  | code => sub { | 
| 96 |  |  |  |  |  |  | my ($self, $key, $value, $line) = @_; | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | $value = lc $value; | 
| 99 | 0 |  |  | 0 |  | 0 | my $re = $value; | 
| 100 |  |  |  |  |  |  | $re =~ s/[\000\\\(]/_/gs;                   # paranoia | 
| 101 | 0 |  |  |  |  | 0 | $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g;        # escape any possible metachars | 
| 102 | 0 |  |  |  |  | 0 | $re =~ tr/?/./;                             # "?" -> "." | 
| 103 | 0 |  |  |  |  | 0 | $re =~ s/\*+/\.\*/g;                        # "*" -> "any string" | 
| 104 | 0 |  |  |  |  | 0 | $conf->{$key}->{$value} = ${re}; | 
| 105 | 0 |  |  |  |  | 0 | }}); | 
| 106 | 0 |  |  |  |  | 0 |  | 
| 107 | 0 |  |  |  |  | 0 | $conf->{parser}->register_commands(\@cmds); | 
| 108 | 63 |  |  |  |  | 472 | } | 
| 109 |  |  |  |  |  |  |  | 
| 110 | 63 |  |  |  |  | 287 | my ($self, $permsgstatus) = @_; | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | my $subject = $permsgstatus->get('Subject'); | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 81 |  |  | 81 | 0 | 181 | return 0 unless $subject ne ''; | 
| 115 |  |  |  |  |  |  |  | 
| 116 | 81 |  |  |  |  | 238 | return $self->_check_subject($permsgstatus->{conf}->{whitelist_subject}, $subject); | 
| 117 |  |  |  |  |  |  | } | 
| 118 | 81 | 100 |  |  |  | 851 |  | 
| 119 |  |  |  |  |  |  | my ($self, $permsgstatus) = @_; | 
| 120 | 42 |  |  |  |  | 201 |  | 
| 121 |  |  |  |  |  |  | my $subject = $permsgstatus->get('Subject'); | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | return 0 unless $subject ne ''; | 
| 124 | 81 |  |  | 81 | 0 | 176 |  | 
| 125 |  |  |  |  |  |  | return $self->_check_subject($permsgstatus->{conf}->{blacklist_subject}, $subject); | 
| 126 | 81 |  |  |  |  | 223 | } | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 81 | 100 |  |  |  | 827 | my ($self, $list, $subject) = @_; | 
| 129 |  |  |  |  |  |  |  | 
| 130 | 42 |  |  |  |  | 201 | $subject = lc $subject; | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | return 1 if defined($list->{$subject}); | 
| 133 |  |  |  |  |  |  |  | 
| 134 | 84 |  |  | 84 |  | 214 | study $subject;  # study is a no-op since perl 5.16.0, eliminating bugs | 
| 135 |  |  |  |  |  |  | foreach my $regexp (values %{$list}) { | 
| 136 | 84 |  |  |  |  | 161 | if ($subject =~ qr/$regexp/i) { | 
| 137 |  |  |  |  |  |  | return 1; | 
| 138 | 84 | 50 |  |  |  | 258 | } | 
| 139 |  |  |  |  |  |  | } | 
| 140 | 84 |  |  |  |  | 137 |  | 
| 141 | 84 |  |  |  |  | 142 | return 0; | 
|  | 84 |  |  |  |  | 273 |  | 
| 142 | 0 | 0 |  |  |  | 0 | } | 
| 143 | 0 |  |  |  |  | 0 |  | 
| 144 |  |  |  |  |  |  | 1; |