]> git.proxmox.com Git - pmg-api.git/blob - src/PMG/SACustom.pm
add SACustom Package and API Calls for custom SpamAssassin scores
[pmg-api.git] / src / PMG / SACustom.pm
1 package PMG::SACustom;
2
3 use strict;
4 use warnings;
5
6 use PVE::INotify;
7 use Digest::SHA;
8
9 my $shadow_path = "/var/cache/pmg-scores.cf";
10 my $conf_path = "/etc/mail/spamassassin/pmg-scores.cf";
11
12 sub get_shadow_path {
13 return $shadow_path;
14 }
15
16 sub apply_changes {
17 rename($shadow_path, $conf_path) if -f $shadow_path;
18 }
19
20 sub calc_digest {
21 my ($data) = @_;
22
23 my $raw = '';
24
25 foreach my $rule (sort keys %$data) {
26 my $score = $data->{$rule}->{score};
27 my $comment = $data->{$rule}->{comment} // "";
28 $raw .= "$rule$score$comment";
29 }
30
31 my $digest = Digest::SHA::sha1_hex($raw);
32 return $digest;
33 }
34
35 PVE::INotify::register_file('pmg-scores.cf', $conf_path,
36 \&read_pmg_cf,
37 \&write_pmg_cf,
38 undef,
39 always_call_parser => 1,
40 shadow => $shadow_path,
41 );
42
43 sub read_pmg_cf {
44 my ($filename, $fh) = @_;
45
46 my $scores = {};
47
48 my $comment = '';
49 if (defined($fh)) {
50 while (defined(my $line = <$fh>)) {
51 chomp $line;
52 next if $line =~ m/^\s*$/;
53 if ($line =~ m/^# ?(.*)\s*$/) {
54 $comment = $1;
55 next;
56 }
57 if ($line =~ m/^score\s+(\S+)\s+(\S+)\s*$/) {
58 my $rule = $1;
59 my $score = $2;
60 $scores->{$rule} = {
61 name => $rule,
62 score => $score,
63 comment => $comment,
64 };
65 $comment = '';
66 } else {
67 warn "parse error in '$filename': $line\n";
68 $comment = '';
69 }
70 }
71 }
72
73 return $scores;
74 }
75
76 sub write_pmg_cf {
77 my ($filename, $fh, $scores) = @_;
78
79 my $content = "";
80 foreach my $rule (sort keys %$scores) {
81 my $comment = $scores->{$rule}->{comment};
82 my $score = sprintf("%.3f", $scores->{$rule}->{score});
83 $content .= "# $comment\n" if defined($comment) && $comment !~ m/^\s*$/;
84 $content .= "score $rule $score\n";
85 }
86 PVE::Tools::safe_print($filename, $fh, $content);
87 }
88
89 1;