chiark / gitweb /
dump control command
[inn-innduct.git] / samples / filter_innd.pl
1 #
2 # $Id: filter_innd.pl 7860 2008-06-07 12:46:49Z iulius $
3 #
4 # Sample Perl filtering file for the innd hooks.
5
6
7 # This file gets loaded at innd process startup, and everytime a
8 # "ctlinnd reload filter.perl 'reason'" or a
9 # "ctlinnd reload all 'reason'" is done.
10 #
11 # Before this file is loaded, the perl routine `filter_before_reload' is
12 # called, and after it's finished loading, the perl routine
13 # `filter_after_reload' is called. See startup_innd.pl for more details.
14 #
15 # The following routines can be defined here for use by innd:
16 #
17 #       sub filter_art { ... }
18 #
19 #               This routine is called before every article is accepted for
20 #               posting. Is is called with no arguments, but has access to
21 #               all the non-empty standard headers of the article via the
22 #               global associative array `%hdr.'  If it returns the empty
23 #               string ("") then the article is accepted. If it returns any
24 #               non-null string value, then the article is rejected and the
25 #               returned string value is logged as the reason why.
26 #
27 #               The standard headers are:
28 #
29 #                       Approved, Control, Date, Distribution, Expires,
30 #                       From, Lines, Message-ID, Newsgroups, Path,
31 #                       Reply-To, Sender, Subject, Supersedes, Bytes,
32 #                       Also-Control, References
33 #
34 #       sub filter_mode { ... }
35 #
36 #               This routine is called every time `go', `pause', or
37 #               `throttle' is called. It is called with no arguments and
38 #               returns no value. The global associative array `%mode' has
39 #               three keyed values stored in it:
40 #
41 #                       'Mode'          The current mode
42 #                                          ("running", "paused", "throttled") 
43 #                       'NewMode"       The new mode
44 #                       'reason'        The reason given.
45 #
46 #               For example:    %mode = ('Mode', 'running', 
47 #                                       'NewMode', 'throttled', 
48 #                                       'reason', 'doing nightly backups')
49 #
50 # If filter_art is not defined when this file is done loading, then
51 # filtering is disabled. If any syntax error occurs when loading the file,
52 # then filtering is disabled.
53 #
54 #       sub filter_messageid { ... }
55 #
56 #               This routine is called when each article (in streaming
57 #               mode only) is checked to see if INN wants to accept the
58 #               article.  If it returns the empty string, the article
59 #               is accepted. If it returns a non-empty value, the
60 #               article is refused.  It is called with one argument,
61 #               the message-id to check.
62
63
64
65 #
66 # Called on each article innd receives from a peer. Return "" to accept,
67 # and any other non-null string to reject. If rejecting the string returned
68 # will be part of the logged reason.
69 #
70
71 sub filter_art {
72         my $rval = "" ; # Assume we'll accept. Cannot be `0'
73
74 ### Remove two leading '##' from the following section (and then
75 ### "ctlinnd reload filter.perl 'reason'" and the filter will reject articles that
76 ### have "make money" in the subject, or are posted to more than 10
77 ### newsgroups. 
78
79 ##      my ($maxgroups) = 10 ;
80 ##
81 ### Normally this output would be lost, but if you run innd with '-d -f' you
82 ### can see what's going on.
83 ###
84 ###     foreach $key (sort keys %hdr) {
85 ###             print "Header:\t$key Value:\t $hdr{$key}\n" ;
86 ###     }
87 ##
88 ##      if ($hdr{"Subject"} =~ /\$*make.*money.*\$*/i ) {
89 ##              $rval = "no money requests here"
90 ##      } elsif ( ( @_ = split(",",$hdr{'Newsgroups'}) ) > $maxgroups ) {
91 ##              $rval = "too many groups" ;
92 ###     Kill article with "Re: " but no References:
93 ##      } elsif ($hdr{'Subject'} =~ /^Re: /o and $hdr{'References'} eq "") {
94 ##       $rval = "Followup without References:";
95 ###     Kill article with invalid From:
96 ##      } elsif ($hdr{'From'} =~ /^\w*$/o or
97 ##          $hdr{'From'} !~ /^(.+?)\@([-\w\d]+\.)*([-\w\d]+)\.([-\w\d]{2,})$/o) {
98 ##       $rval = "From: is invalid, must be user\@[host.]domain.tld";
99 ##   }
100 ###
101 ###     print "Accepting\n" if ! $rval ;
102
103         $rval ;
104 }
105
106 sub filter_mode {
107         if ($mode{'NewMode'} eq "throttled" || $mode{'NewMode'} eq "paused") {
108 #               print "Closing spam database\n" ; # won't kill server.
109 #               &close_spam_database ;
110         } else {
111 #               print "Opening spam database\n" ; # won't kill server
112 #               &open_spam_database ;
113         }
114 }
115
116 sub filter_messageid {
117     my ($messageid) = @_;
118     $rval = '';
119 #    $rval = 'No' if ($messageid =~ /a\.spam\.domain>?/i);
120      $rval;
121 }
122
123
124
125
126
127 ###########################################################################
128 ##
129 ## Another sample. More elaborate, but cleaner... from Christophe
130 ## Wolfhugel <wolf@pasteur.fr>.
131 ##
132
133
134 #### Regular expressions we reject.
135 #### Format : Header => regexp => reason
136 ##%reject = (
137 ##   'Subject'  => {
138 ##      'make.*money.*fast'             =>      'MMF rejected',
139 ##      'cash.*cash.*cash'              =>      'Cash rejected'
140 ##   },
141 ##);
142 ##
143 ##sub filter_art {
144 ##   my($rval) = '';
145 ##   my(@ng, $i, $j, $k, $l);
146 ##
147 ##   if ($hdr{'From'} !~ /\@/o) {
148 ##      $rval = 'Invalid From';
149 ##   } else {
150 ##      while (($i, $j) = each %reject) {
151 ##         while (($k, $l) = each %{$j}) {
152 ##            if ($hdr{$i} =~ /$k/i) {
153 ##               $rval = $l;
154 ##               goto the_end;
155 ##            }
156 ##         }
157 ##      }
158 ##   }
159 ##   @ng = split(/,/, $hdr{'Newsgroups'});
160 ##   if ($#ng > 10) {
161 ##     $rval = 'ECP rejected';
162 ##   }
163 ##the_end:
164 ##   undef %hdr;
165 ##   return $rval
166 ##}
167 ##
168 ##sub filter_mode {
169 ##}
170 ##
171 ###%hdr = (
172 ###     'Subject'       =>      'Make money fast',
173 ###     'From'          =>      'bozo@gov.org'
174 ###);
175 ###&filter_art;
176
177
178
179 ###########################################################################
180 ##
181 ## From Chrisophe Wolfhugel again (wolf@pasteur.fr). This is not 
182 ## standalone code. 
183 ##
184
185 ##Just for the fun, I've added following code to filter_innd.pl :
186 ##
187 ##   ## Keep track of the From and subject.
188 ##   $i = "$hdr{'From'} $hdr{'Subject'}";
189 ##   push(@history, $i);
190 ##   $history{$i}++;
191 ##
192 ##   ## Reject the EMP.
193 ##   if ($history{$i} > 10) {
194 ##      $rval = "EMP rejected (appeared $history{$i} times): $i";
195 ##   }
196 ##
197 ##   ## Remove too old things.
198 ##   while ($#history > 1000) {
199 ##      delete($history{shift(@history)});
200 ##   }
201 ##
202 ##It is pretty successfull in detecting and refusing excessive multi-posting.
203 ##Same sender, same subject, appearing more than 10 times without the last
204 ##1000 articles gets junked.
205 ##
206 ##Already catched a few hundreds :
207 ##
208 ##Nov 20 08:27:23.175 - vishnu.jussieu.fr <3292ac9a.4064710@nntp.cts.com> 437 EMP rejected (btr@trenet.com Be a Beta Tester!)
209 ##
210 ##That was just for the pleasure. It is still sucking a non significant CPU
211 ##time on my slow Alpha.
212