filter_innd: Add missing module.
[usenet/INN.git] / filter / cleanfeed.local
1 # vim: set tabstop=4 shiftwidth=4 expandtab syntax=perl:
2
3 use MIME::Base64();
4 use Digest::SHA();
5 use Digest::MD5();
6
7 #
8 # local_filter_cancel
9 #
10 sub local_filter_cancel {
11    unless($hdr{Control} =~ m/^cancel\s+(<[^>]+>)/i) {
12       return "Cancel with broken target ID";
13    }
14    return verify_cancel(\%hdr, $1, 'Cancel');
15 }
16
17 sub local_filter_after_emp {
18    if (exists( $hdr{'Supersedes'} )) {
19       #return verify_cancel(\%hdr, $hdr{'Supersedes'}, 'Supersedes');
20       # verify_cancel is called, but not returned, so the
21       # posting is unconditionally accepted
22       # verify_cancel calls INN:cancel() if verification suceeds
23       verify_cancel(\%hdr, $hdr{'Supersedes'}, 'Supersedes');
24    }
25
26    return undef;
27 }
28
29 sub verify_cancel($$$) {
30    my $r_hdr = shift || die;
31    my $target = shift;
32    my $descr = shift;
33
34    my $headers = INN::head($target) || return "$descr of non-existing ID $target";
35
36    my %headers;
37    for my $line(split(/\s*\n/, $headers))    {
38       if ($line =~ m/^([[:alnum:]-]+):\s+(.*)/) {
39          $headers{$1} = $2;
40          $lastkey = $1;
41       } elsif ($line =~ m/^\s+(.*)/ and defined($lastkey)) {
42          $headers{$lastkey} .= ' ' . $1;
43       }
44    }
45    my $lock = $headers{'Cancel-Lock'};
46
47    if (defined($lock)) {
48       my $key = $r_hdr->{'Cancel-Key'} || return "$descr of $target without Cancel-Key";
49       #return verify_cancel_key($key, $lock, ' target=' . $target);
50       return verify_cancel_key($key, $lock, $target);
51    } else {
52     # -thh
53     # no cancel-lock: go ahead and cancel anyway!
54     INN::cancel($target);
55    }
56
57    return undef;
58 }
59
60 sub verify_cancel_key($$$) {
61    my $cancel_key = shift;
62    my $cancel_lock = shift;
63    my $msg = shift;
64
65    $msg = '' unless(defined($msg));
66    # -thh
67    my $target = $msg;
68    $msg = ' target=' . $msg;
69
70    my %lock;
71    for my $l(split(/\s+/, $cancel_lock))   {
72       next unless($l =~ m/^(sha512|sha256|sha1|md5):(\S+)/);
73       $lock{$2} = $1;
74    }
75
76    for my $k(split(/\s+/, $cancel_key))    {
77       unless($k =~ m/^(sha512|sha256|sha1|md5):(\S+)/) { 
78         INN::syslog('notice', "Invalid Cancel-Key syntax '$k'.$msg");
79         next;
80       }
81
82       my $key;
83       if ($1 eq 'sha512') {
84         $key = Digest::SHA::sha512($2);
85       } elsif ($1 eq 'sha256') {
86          $key = Digest::SHA::sha256($2);
87       } elsif($1 eq 'sha1') {
88          $key = Digest::SHA::sha1($2);
89       } elsif ($1 eq 'md5') {
90          $key = Digest::MD5::md5($2);
91       }
92       $key = MIME::Base64::encode_base64($key, '');
93
94       if (exists($lock{$key})) { 
95          # INN::syslog('notice', "Valid Cancel-Key $key found.$msg");
96          # -thh
97          # article is canceled now
98          INN::cancel($target) if ($target);
99          return undef;
100       }
101    }
102
103    INN::syslog('notice',
104       "No Cancel-Key[$cancel_key] matches Cancel-Lock[$cancel_lock]$msg"
105    );
106    return "No Cancel-Key matches Cancel-Lock.$msg";
107 }
108
109 1;
This page took 0.013281 seconds and 4 git commands to generate.