INN commit: trunk (6 files)

INN Commit Russ_Allbery at isc.org
Sat Apr 25 14:22:17 UTC 2009


    Date: Saturday, April 25, 2009 @ 07:22:17
  Author: iulius
Revision: 8431

Many improvements to checkgroups handling:

* Act on checkgroups control messages instead of sending mail;

* Add the /maxdocheckgroups/ control.ctl option to specify
  the maximum number of changes that could be made at one time
  before bailing and mailing the changes to the admin;

* Process all matching entries for a checkgroups and not the
  last matching control.ctl entry.  It especially allows to
  use "drop" commands, combined with "mail" and "doit".  To
  achieve that, controlchan uses exclusion and drop patterns;

* Fix a long-standing bug causing patterns not being properly
  handled by docheckgroups:  standard grep patterns were
  generated by controlchan instead of *egrep* patterns!

* Fix a long-standing bug causing multiple entries for the
  same checkgroups sender not to be honoured (for instance
  aus.* and canb.*) because the last one did not match the
  list of newsgroups;

* Fix two wrong log matches in innreport;

* Documentation improvements, with useful samples.

close #3, #102

Modified:
  trunk/control/controlchan.in
  trunk/control/modules/checkgroups.pl
  trunk/doc/pod/control.ctl.pod
  trunk/doc/pod/news.pod
  trunk/samples/control.ctl.local
  trunk/scripts/innreport_inn.pm

--------------------------------+
 control/controlchan.in         |  167 +++++++++++++++-----------
 control/modules/checkgroups.pl |   54 +++++++-
 doc/pod/control.ctl.pod        |  250 +++++++++++++++++++++++++++++++--------
 doc/pod/news.pod               |   13 +-
 samples/control.ctl.local      |    5 
 scripts/innreport_inn.pm       |    7 -
 6 files changed, 370 insertions(+), 126 deletions(-)

Modified: control/controlchan.in
===================================================================
--- control/controlchan.in	2009-04-25 14:13:59 UTC (rev 8430)
+++ control/controlchan.in	2009-04-25 14:22:17 UTC (rev 8431)
@@ -136,64 +136,65 @@
     $progname = $1;
 
     # Do we want to process the message?  Let's check the permissions.
-    my @charset_from;
-    my ($action, $logname, $newsgrouppats, $charset_to) =
-        ctlperm($progname, $sender, $progparams[0],
-                $token, $article, \@charset_from);
+    my (@charset_from, @maxchanges, @matches);
+    my $exclusionpats = '';
+    my $droppats = '';
+    my $charset_to = ctlperm($progname, $sender, $progparams[0],
+                             $token, $article, \@charset_from,
+                             \@maxchanges, \@matches);
 
-    if ($action eq 'drop') {
-        $parser->filer->purge;
-        next;
-    }
+    foreach my $i (0..$#matches) {
+        my $action = $matches[$i][0] if $matches[$i][0];
+        my $logname = $matches[$i][1] if $matches[$i][1];
+        $progparams[0] = $matches[$i][2] if $matches[$i][2];
 
-    if ($action eq '_pgpfail') {
-        my $type = '';
-        if ($progname and $progname eq 'newgroup') {
-            if ($progparams[1] and $progparams[1] eq 'moderated') {
-                $type = 'm ';
+        if ($action eq '_pgpfail') {
+            my $type = '';
+            if ($progname and $progname eq 'newgroup') {
+                if ($progparams[1] and $progparams[1] eq 'moderated') {
+                    $type = 'm ';
+                } else {
+                    $type = 'y ';
+                }
+            }
+            logmsg("skipping $progname $type$sender"
+                . " (pgpverify failed) in $curmsgid");
+            next;
+        }
+
+        # Find the appropriate module and call it.
+        my $subname = "control_$progname";
+        my $subfind = \&$subname;
+        if (not defined &$subfind) {
+            if ($logname) {
+                logger($logname, "Unknown control message by $sender",
+                    $article);
             } else {
-                $type = 'y ';
+                logmsg("Unknown \"$progname\" control by $sender");
             }
+            next;
         }
-        logmsg("skipping $progname $type$sender"
-            . "(pgpverify failed) in $curmsgid");
-        $parser->filer->purge;
-        next;
-    }
 
-    # used by checkgroups. Convert from perl regexp to grep regexp.
-    if (local $_ = $newsgrouppats) {
-        s/\$\|/|/g;
-        s/[^\\]\.[^*]/?/g;
-        s/\$//;
-        s/\.\*/*/g;
-        s/\\([\$\+\.])/$1/g;
-        $progparams[0] = $_;
-    }
+        my $approved = $hdr{'approved'} ? 1 : 0;
+        logmsg("$subname, " . join(' ', @progparams)
+            . " $sender $replyto $token, $exclusionpats, $droppats,"
+            . " $charset_to, $sitepath, $action"
+            . ($logname ? "=$logname" : '') .", $approved");
 
-    # find the appropriate module and call it
-    my $subname = "control_$progname";
-    my $subfind = \&$subname;
-    if (not defined &$subfind) {
-        if ($logname) {
-            logger($logname, "Unknown control message by $sender",
-                $article);
+        if ($action ne 'drop') {
+            &$subfind(\@progparams, $sender, $replyto,
+                $sitepath, $action, $logname, $approved, $article,
+                \@charset_from, $charset_to, $exclusionpats, $droppats,
+                \@maxchanges);
+
+            $exclusionpats .= '|' if $exclusionpats;
+            $exclusionpats .= $progparams[0];
         } else {
-            logmsg("Unknown \"$progname\" control by $sender");
+            $droppats .= '|' if $droppats;
+            $droppats .= $progparams[0];
         }
-        $parser->filer->purge;
-        next;
     }
 
-    my $approved = $hdr{'approved'} ? 1 : 0;
-    logmsg("$subname, " . join(' ', @progparams)
-        . " $sender $replyto $token, $sitepath, $action"
-        . ($logname ? "=$logname" : '') .", $approved");
-
-    &$subfind(\@progparams, $sender, $replyto, $sitepath,
-        $action, $logname, $approved, $article,
-        \@charset_from, $charset_to);
-
     $parser->filer->purge;
 }
 
@@ -270,6 +271,7 @@
             next if not /^(\s+)?[^\#]/ or /^$/;
 
             if (not /^\/(?:local)?encoding\/:/ and
+                not /^\/maxdocheckgroups\/:/ and
                 not /:(?:doit|doifarg|drop|log|mail|verify-.*)(?:=.*)?$/) {
                 s/.*://;
                 logmsg("$_ is not a valid action for control.ctl", 'err');
@@ -297,17 +299,19 @@
 
 # Parse a control message's permissions.
 sub ctlperm {
-    my ($type, $sender, $newsgroup, $token, $article, $charset_from) = @_;
+    my ($type, $sender, $newsgroup, $token, $article, $charset_from,
+        $maxchanges, $matches) = @_;
 
-    my $action = 'drop';       # Default action.
-    my ($logname, $hier, $charset_to);
+    my %keyresults = ();
+    my ($action, $maxdocheckgroups, $logname, $charset_to);
 
     # newgroup and rmgroup require newsgroup names; check explicitly for that
     # here and return drop if the newsgroup is missing (to avoid a bunch of
     # warnings from undefined values later on in permission checking).
     if ($type eq 'newgroup' or $type eq 'rmgroup') {
         unless ($newsgroup) {
-            return ('drop', undef, undef, undef);
+            push (@$matches, [ 'drop', undef, undef ]);
+            return ('UTF-8');
         }
     }
 
@@ -323,10 +327,15 @@
                 $action = $ctlline[3];
                 $action =~ s/\^(.+)\$/$1/;
                 $action =~ s/\\//g;
-                $hier = $ctlline[2] if $type eq 'checkgroups';
-                # @ctllist is a reversed list so the first match is the last
-                # one in control.ctl followed by control.ctl.local.
-                $matchedaction = 1;
+                ($action, $logname) = split(/=/, $action);
+                if ($type eq 'checkgroups') {
+                    push (@$matches, [ $action, $logname, $ctlline[2] ]);
+                } else {
+                    push (@$matches, [ $action, $logname, undef ]);
+                    # @ctllist is a reversed list so the first match is the last
+                    # one in control.ctl followed by control.ctl.local.
+                    $matchedaction = 1;
+                }
             }
         }
         # 0: /localencoding/  1: encoding
@@ -344,6 +353,14 @@
                 push (@$charset_from, $ctlline[2].':'.$ctlline[3]);
             }
         }
+        # 0: /maxdocheckgroups/  1: from at addr  2: group.*  3: number
+        if ($ctlline[0] eq '^\/maxdocheckgroups\/$') {
+            if ($sender =~ /$ctlline[1]/i) {
+                $maxdocheckgroups = $ctlline[3];
+                $maxdocheckgroups =~ s/\^(.+)\$/$1/;
+                push (@$maxchanges, $ctlline[2].':'.$maxdocheckgroups);
+            }
+        }
     }
 
     if (not defined $charset_to
@@ -351,24 +368,36 @@
         $charset_to = 'UTF-8';  # Default local encoding.
     }
 
-    ($action, $logname) = split(/=/, $action);
+    # Default value when nothing matches the control article.
+    if ($#$matches < 0) {
+        push (@$matches, [ 'drop', undef, undef ]);
+    }
 
-    if ($action =~ /^verify-(.+)/) {
-        my $keyowner = $1;
-        if ($INN::Config::pgpverify and $INN::Config::pgpverify =~ /^(?:true|on|yes)$/i) {
-            my $pgpresult = defined &local_pgpverify ?
-                local_pgpverify($token, $article) : pgpverify($token);
-            if ($keyowner eq $pgpresult) {
-                $action = 'doit';
-            } else {
-                $action = '_pgpfail';
-            }
-        } else {
-            $action = 'mail';
+    # Default value appended to the end of @maxchanges.
+    push (@$maxchanges, '^.*$:10');
+
+    foreach my $i (0..$#$matches) {
+        if ($$matches[$i][0] =~ /^verify-(.+)/) {
+            my $keyowner = $1;
+
+            if (!exists($keyresults{$keyowner})) {
+                if ($INN::Config::pgpverify and $INN::Config::pgpverify =~ /^(?:true|on|yes)$/i) {
+                    my $pgpresult = defined &local_pgpverify ?
+                        local_pgpverify($token, $article) : pgpverify($token);
+                    if ($keyowner eq $pgpresult) {
+                        $keyresults{$keyowner} = 'doit';
+                    } else {
+                        $keyresults{$keyowner} = '_pgpfail';
+                    }
+                } else {
+                    $keyresults{$keyowner} = 'mail';
+                }
+           }
+           $$matches[$i][0] = $keyresults{$keyowner};
         }
     }
 
-    return ($action, $logname, $hier, $charset_to);
+    return ($charset_to);
 }
 
 # Write stuff to a log or send mail to the news admin.

Modified: control/modules/checkgroups.pl
===================================================================
--- control/modules/checkgroups.pl	2009-04-25 14:13:59 UTC (rev 8430)
+++ control/modules/checkgroups.pl	2009-04-25 14:22:17 UTC (rev 8431)
@@ -19,7 +19,8 @@
 
 sub control_checkgroups {
     my ($par, $sender, $replyto, $site, $action, $log, $approved,
-        $article, $charset_from, $charset_to) = @_;
+        $article, $charset_from, $charset_to, $exclusionpats,
+        $droppats, $maxchanges) = @_;
     my ($newsgrouppats) = @$par;
     my $head = $article->head;
     my @headers = split(/\r?\n/, $head->stringify);
@@ -35,6 +36,8 @@
         my ($ngname, $ngdesc) = split(/\s+/, $_, 2);
         my $charset_newsgroup = $charset_message;
 
+        next if ($ngname =~ /$exclusionpats/ or $ngname =~ /$droppats/);
+
         # Find the right charset if absent or forced by control.ctl.
         foreach (@$charset_from) {
             my ($group, $charset) = split /:/;
@@ -59,7 +62,7 @@
         push(@newbody, $ngname."\t".$ngdesc);
     }
 
-    if ($action eq 'mail') {
+    if ($action eq 'mail' and $#newbody >= 0) {
         my $mail = sendmail("checkgroups by $sender");
         print $mail "$sender posted the following checkgroups message:\n\n";
         print $mail map { s/^~/~~/; "$_\n" } @headers;
@@ -69,7 +72,7 @@
 of the message to docheckgroups while logged
 in as user ID "$INN::Config::newsuser":
 
-$INN::Config::pathbin/docheckgroups -u '$newsgrouppats' <<zRbJ
+$INN::Config::pathbin/docheckgroups -u '$newsgrouppats' '$exclusionpats' <<zRbJ
 END
         print $mail map { s/^~/~~/; "$_\n" } @newbody;
         print $mail "zRbJ\n";
@@ -83,15 +86,17 @@
         }
     } elsif ($action eq 'doit') {
         if (defined &local_docheckgroups) {
-            local_docheckgroups(\@newbody, $newsgrouppats, $log, $sender);
+            local_docheckgroups(\@newbody, $newsgrouppats, $exclusionpats,
+                                $maxchanges, $log, $sender);
         } else {
-            docheckgroups(\@newbody, $newsgrouppats, $log, $sender);
+            docheckgroups(\@newbody, $newsgrouppats, $exclusionpats,
+                          $maxchanges, $log, $sender);
         }
     }
 }
 
 sub docheckgroups {
-    my ($body, $newsgrouppats, $log, $sender) = @_;
+    my ($body, $newsgrouppats, $exclusionpats, $maxchanges, $log, $sender) = @_;
 
     my $tempfile = "$INN::Config::tmpdir/checkgroups.$$";
     open(TEMPART, ">$tempfile.art")
@@ -103,7 +108,8 @@
     open(OLDOUT, '>&STDOUT') or die $!;
     open(STDIN, "$tempfile.art") or die $!;
     open(STDOUT, ">$tempfile") or die $!;
-    my $st = system("$INN::Config::pathbin/docheckgroups", "-u", $newsgrouppats);
+    my $st = system("$INN::Config::pathbin/docheckgroups", "-u",
+                    $newsgrouppats, $exclusionpats);
     logdie('Cannot run docheckgroups: ' . $!) if $st == -1;
     logdie('docheckgroups returned status ' . ($st & 255)) if $st > 0;
     close(STDIN);
@@ -116,7 +122,39 @@
     chop @output;
     # There is no need to send an empty mail.
     if ($#output > 0) {
-        logger($log || 'mail', "checkgroups by $sender", \@output);
+        my $dochanges = 1;
+        my @newmaxchanges = @$maxchanges;
+        foreach my $line (@output) {
+            last if !$dochanges;
+            if ($line =~ /^\s*\S*ctlinnd \S+ (\S+)/) {
+                my $ngname = $1;
+                foreach my $i (0..$#newmaxchanges) {
+                    my ($group, $value) = split (/:/, $newmaxchanges[$i]);
+                    if ($ngname =~ /$group/) {
+                        $value--;
+                        if ($value < 0) {
+                            $dochanges = 0;
+                        }
+                        $newmaxchanges[$i] = "$group:$value";
+                        last;
+                    }
+                }
+            }
+        }
+
+        if ($dochanges) {
+            if ($log) {
+                logger($log, "checkgroups by $sender processed (changes applied)",
+                       \@output);
+            }
+            my $st = system("$INN::Config::pathbin/mod-active",
+                            $tempfile);
+            logdie('Cannot run mod-active: ' . $!) if $st == -1;
+            logdie('mod-active returned status ' . ($st & 255)) if $st > 0;
+        } else {
+            logger($log || 'mail', "checkgroups by $sender *not* processed (too many changes)",
+                   \@output);
+        }
     } else {
         logmsg("checkgroups by $sender processed (no change)");
     }

Modified: doc/pod/control.ctl.pod
===================================================================
--- doc/pod/control.ctl.pod	2009-04-25 14:13:59 UTC (rev 8430)
+++ doc/pod/control.ctl.pod	2009-04-25 14:22:17 UTC (rev 8431)
@@ -21,23 +21,92 @@
 
     <type>:<from>:<newsgroups>:<action>
 
-Lines are matched in order and the last matching line in the file will be used.
+Lines are matched in order and the last matching line in the file will
+be used, except for checkgroups messages which are handled differently
+(every matching line is used).
 
 The first field, <type>, is the type of control message for which this
 line is valid.  It should either be the name of a control message or the
-word C<all> to indicate that it applies to all control messages.
+word C<all> to indicate that it applies to all control messages.  Besides,
+the following special types are understood:
 
+=over 4
+
+=item B</encoding/>
+
+This type specifies the encoding of newgroup and checkgroups control
+messages so that new descriptions could be decoded the right way.
+
+    /encoding/:*:cn.*:gb18030
+
+means that a description for a newsgroup in the Chinese cn.*
+hierarchy will be decoded as though it were encoded in GB18030,
+unless a charset is specified in the control message (in such a case,
+the charset mentioned in the message is used).  However, it is possible
+to override the mentioned charset if C<=force> is appended after
+the encoding.  For instance,
+
+    /encoding/:*:scout.forum.chinese:big5=force
+
+means that the description for scout.forum.chinese will always
+be decoded as though it were encoded in Big5, no matter the charset
+of the corresponding control message.
+
+The default value when no encoding is mentioned (or when the
+specified encoding is unknown) is C<CP1252>.
+
+The last matching line for a given newsgroup name in F<control.ctl>
+will be used.
+
+=item B</localencoding/>
+
+When this type is used, the line consist of only two fields.  The default
+value when this type does not appear in F<control.ctl> (or when the
+specified charset is unknown) is equivalent to:
+
+    /localencoding/:utf-8
+
+It means that new descriptions in the F<newsgroups> file will be written
+using UTF-8.  And B<controlchan> will try to read existing descriptions,
+so as to see whether they should be updated, as though they were encoded
+in UTF-8.
+
+The last matching line in F<control.ctl> will be used.
+
+=item B</maxdocheckgroups/>
+
+This type specifies the maximum number of changes that could be made
+at one time by a checkgroups before bailing and mailing the changes
+to the admin if no log file was specified.  The default value is C<10>.
+
+    /maxdocheckgroups/:*:*:10
+    /maxdocheckgroups/:*:fr.*:20
+
+Such a configuration means that a checkgroups containing 15 changes
+for the French fr.* hierarchy (newgroups to add, remove or change
+the status) will be automatically honoured whereas a checkgroups
+containing 15 changes for france.* will only have the required
+changes mailed or logged.
+
+The last matching line for a given newsgroup name in F<control.ctl>
+will be used.
+
+=back
+
 The second field, <from>, is a shell-style pattern that matches the e-mail
 address of the person posting the message (with the address first
 converted to lowercase).  The matching is done with rules equivalent to
 those of the shell's I<case> statement; see sh(1) for more details.
 
 If the control message is a newgroup or rmgroup, the third field,
-<newsgroups>, is a shell-style pattern matching the newsgroup affected by
-the control message.  If the control message is a checkgroups, the third
-field is a shell-style pattern matching the newsgroups that should be
-processed for checking.  If the control message is of any other type, the
-third field is ignored.
+<newsgroups>, is a shell-style pattern matching the newsgroup affected
+by the control message (especially C<?> matches exactly one character,
+C<*> matches zero or more characters and C<|> permits to match several
+patterns on the same line S<-- for> instance C<comp.*|humanities.*>
+matches every newsgroup whose name begins with C<comp.> or C<humanities.>).
+If the control message is a checkgroups, the third field is a shell-style
+pattern matching the newsgroups that should be processed for checking.
+If the control message is of any other type, the third field is ignored.
 
 The fourth field, <action>, specifies what action to take with control
 messages that match this line.  The following actions are understood:
@@ -46,14 +115,16 @@
 
 =item B<doit>
 
-The action requested by the control message should be performed.  For
-checkgroups messages, this means that the shell commands that should
-be run will be mailed to the news administrator (the argument to
-B<--with-news-master> given at configure time, C<usenet> by default); for
-other commands, this means that the change will be silently performed.  If
-you always want notification of actions taken, use C<doit=mail> instead (see
-below).
+The action requested by the control message should be performed.  It
+means that the change will be silently performed.  For checkgroups messages,
+depending on the value of B</maxdocheckgroups/>, the shell commands that
+should be run may be mailed to the news administrator (the argument to
+B<--with-news-master> given at configure time, C<usenet> by default)
+instead of being performed.
 
+If you always want notification of actions taken, use C<doit=mail> instead
+(see below).
+
 =item B<doifarg>
 
 If the control message has an argument, this is equivalent to B<doit>.  If
@@ -78,13 +149,21 @@
 
 If I<file> starts with a slash, it is taken as the absolute filename to
 use for the log file.  Otherwise, the filename is formed by prepending
-I<pathlog> and a slash and appending C<.log>.  In other words, an action
+I<pathlog> and a slash, and appending C<.log>.  In other words, an action
 of C<doit=newgroup> will log to I<pathlog>/newgroup.log.
 
 =item B<drop>
 
-No action is taken and the message is ignored.
+No action is taken and the message is ignored.  For checkgroups messages,
+it means that the newsgroups mentioned will be considered as not existent
+in the checkgroups for its subsequent process.
 
+    checkgroups:*:comp.*:doit
+    checkgroups:*:*binaries*:drop
+
+will for instance remove every newsgroup whose name contains C<binaries>
+in the comp.* hierarchy, even though mentioned in the checkgroups.
+
 =item B<verify-*>
 
 If the action starts with the string C<verify->, as in:
@@ -106,7 +185,9 @@
 notification of successful newgroup and rmgroup control messages and the
 output of checkgroups messages will be mailed to the news administrator.
 (In the case of checkgroups messages, this means that the shell script that
-should be run will be mailed to the administrator.)
+should be run will be mailed to the administrator.  The subject of the
+mail will contain information on whether the script has already been run,
+depending on the value of B</maxdocheckgroups/>.)
 
 =item B<verify-*>=I<file>
 
@@ -114,7 +195,9 @@
 and a log entry is written to the specified file as described in
 B<doit>=I<file> above.  (In the case of checkgroups messages, this means
 that the shell script output of the checkgroups message will be written to
-that file.)
+that file.  The initial line of the log will contain information on whether
+the script has already been run, depending on the value of
+B</maxdocheckgroups/>.)
 
 =item B<log>
 
@@ -133,17 +216,13 @@
 
 =back
 
-Processing of a checkgroups message will never actually change the
-F<active> file (the list of groups carried by the server).  The difference
-between a B<doit> or B<verify> action and a B<mail> action for a
-checkgroups control message lies only in what e-mail is sent; B<doit> or
-B<verify> will mail the news administrator a shell script to create,
-delete, or modify newsgroups to match the checkgroups message, whereas
-B<mail> will just mail the entire message.  In either case, the news
-administrator will have to take action to implement the checkgroups
-message, and if that mail is ignored, nothing will be changed.
+The difference between a B<doit> or B<verify> action and a B<mail> action
+for a checkgroups control message lies only in what e-mail is sent; B<doit>
+or B<verify> will mail the news administrator a shell script (which may
+have already been run) to create, delete, or modify newsgroups to match
+the checkgroups message, whereas B<mail> will just mail the entire message.
 
-Use of the B<verify> action for processing newgroup, rmgroup, and
+Use of the B<verify> action for processing newgroup, rmgroup and
 checkgroups messages is STRONGLY recommended.  Abuse of control messages
 is rampant, and authentication via PGP signature is currently the only
 reliable way to be sure that a control message comes from who it claims to
@@ -152,14 +231,14 @@
 
 In order to use B<verify> actions, the PGP key ring of the news user must
 be populated with the PGP keys of the hierarchy maintainers whose control
-messages you want to honor.  For more details on PGP-authenticated control
+messages you want to honour.  For more details on PGP-authenticated control
 messages and the URL for downloading the PGP keys of major hierarchies,
 see pgpverify(8).
 
 Control messages of type cancel are handled internally by B<innd> and
 cannot be affected by any of the mechanisms described here.
 
-=head1 EXAMPLE
+=head1 EXAMPLES
 
 With the following three lines in F<control.ctl>:
 
@@ -167,36 +246,114 @@
     newgroup:group-admin at isc.org:comp.*:verify-news.announce.newgroups
     newgroup:kre at munnari.oz.au:aus.*:mail
 
-a newgroup coming from C<group-admin at isc.org> will be honored if it is for
+a newgroup coming from C<group-admin at isc.org> will be honoured if it is for
 a newsgroup in the comp.* hierarchy and if it has a valid signature
 corresponding to the PGP key with a user ID of C<news.announce.newgroups>.
 If any newgroup claiming to be from C<kre at munnari.oz.au> for a newsgroup
-in the aus.* hierarchy is received, it too will be honored.  All other
+in the aus.* hierarchy is received, it too will be honoured.  All other
 newgroup messages will be ignored.
 
 Besides, if a F<control.ctl.local> file exists and contains:
 
     newgroup:*:comp.lang.*:drop
 
-then a newgroup control article for comp.lang.awk will not be honored
+then a newgroup control article for comp.lang.awk will not be honoured
 even though it comes from C<group-admin at isc.org> with a valid signature.
 
-=head1 WARNINGS
+As for checkgroups, suppose your news server contains these groups for foo.*,
+all of them being unmoderated (C<y> flag in the F<active> file):
 
-The third argument for a line affecting checkgroups does B<not> affect
-whether the line matches.  It is only used after a matching line is found,
-to filter out which newsgroups listed in the checkgroups will be
-processed.  This means that a line like:
+    foo.bar1
+    foo.bar2.first
+    foo.bar2.second
+    foo.bar2.third
+    foo.bar3
+    foo.bar3.first
+    foo.bar3.second
+    foo.bar5
 
-    checkgroups:*:*binaries*:drop
+and you receive the following checkgroups by <foo at bar.com> for foo.*:
 
-will cause B<all> checkgroups control messages to be dropped unless they
-match a line after this one in F<control.ctl>, not just ignore newsgroups
-containing C<binaries> in the name.  The general rule is to never use C<*>
-in the second field for a line matching checkgroups messages.  There is
-unfortunately no way to do what the author of a line like the above
-probably intended to do (yet).
+    foo.bar1          A valid newsgroup.
+    foo.bar3.first    Only one newsgroup in foo.bar3.*.
+    foo.bar4          A newsgroup you want.
+    foo.bar5          A newsgroup you do not want.
+    foo.bar5.first    Another newsgroup you do not want.
 
+with the following F<control.ctl> entries:
+
+    /maxdocheckgroups/:*:foo.*:2
+
+    checkgroups:foo at bar.com:foo.*:verify-key-foo
+    checkgroups:foo at bar.com:foo.bar2.*:doit
+    checkgroups:foo at bar.com:foo.bar3.*:mail
+    checkgroups:foo at bar.com:foo.bar4|foo.bar4.*:doit
+    checkgroups:foo at bar.com:foo.bar5|foo.bar5.*:drop
+
+Then, as F<control.ctl> is processed from bottom, here is what happens:
+
+=over 4
+
+=item 1.
+
+The newsgroups foo.bar5 and foo.bar5.first are marked as unwanted.  But
+nothing is done yet:  other F<control.ctl> entries have to be processed
+with a real action and a set of newsgroups containing foo.bar5 and
+foo.bar5.first.
+
+=item 2.
+
+The newsgroup foo.bar4 is silently created on the news server, with
+the description "A newsgroup you want." added to the F<newsgroups>
+file.  In the absence of encoding values (either in the checkgroups
+message or in B</encoding/> and B</localencoding>), the default is
+to decode the sentence as CP1242 and reencode it as UTF-8.
+
+If C<doit=mail> was used, a mail would be sent to the news administrator
+to inform him that foo.bar4 was successfully created.
+
+=item 3.
+
+The newsgroup foo.bar3.second is no longer present.  A mail is sent
+to the news administrator with a shell script to execute.  When it is
+manually executed, foo.bar3.second will be removed.
+
+Note that the descriptions are handled differently and have already
+been updated without any manual intervention (foo.bar3.first now
+has the description "Only one newsgroup in foo.bar3.*." and
+foo.bar3.second no longer has a description).
+
+=item 4.
+
+The newsgroups foo.bar2.first, foo.bar2.second and foo.bar2.third
+are no longer present.  However, as the maximum number of changes
+that could be made at one time by a checkgroups before bailing
+and mailing the changes to the news administrator is 2, these
+newsgroups are not removed.  A mail is sent with a shell script
+to manually execute in order to remove these groups from
+the news server.
+
+Note that their descriptions are removed from the F<newsgroups> file,
+as well as any other possible descriptions for obsolete newsgroups
+in foo.bar2.*.
+
+=item 5.
+
+The remaining entry is executed if the PGP verification of the
+checkgroups message is successful.  Otherwise, nothing is done
+(especially, foo.bar5 remains on the news server).
+
+In case the PGP signature is verified, foo.bar3 and foo.bar5 are
+removed from the news server.  This entry acts upon newsgroups
+marked as dropped in its scope and newsgroups not already dealt
+with by previous F<control.ctl> entries (like foo.bar3 because
+only foo.bar3.* was previously checked).
+
+Note that if you had wanted to keep foo.bar3 or foo.bar5, you
+could have added them to the F<localgroups> file in I<pathetc>.
+
+=back
+
 =head1 HISTORY
 
 Written by Rich $alz <rsalz at uunet.uu.net> for InterNetNews.  Rewritten in
@@ -206,6 +363,7 @@
 
 =head1 SEE ALSO
 
-controlchan(8), inn.conf(5), innd(8), newsfeeds(5), pgpverify(8), sh(1).
+controlchan(8), inn.conf(5), innd(8), newsfeeds(5), newsgroups(5),
+pgpverify(8), sh(1).
 
 =cut

Modified: doc/pod/news.pod
===================================================================
--- doc/pod/news.pod	2009-04-25 14:13:59 UTC (rev 8430)
+++ doc/pod/news.pod	2009-04-25 14:22:17 UTC (rev 8431)
@@ -22,6 +22,15 @@
 
 =item *
 
+Checkgroups control messages are now differently handled by B<controlchan>:
+all matching lines in F<control.ctl> will be used for a given checkgroups
+and a B<doit> action will really be executed (adding, removing and changing
+the status of newsgroups).  You should make sure that your local
+configuration does not rely on the previous behaviour of only mailing
+changes, without actually performing them.
+
+=item *
+
 You should use the new F<control.ctl.local> file shipped with INN in
 I<pathetc> and, at the same time, update your F<control.ctl> and
 F<moderators> files.  Also make sure that your F<active.times>,
@@ -172,7 +181,9 @@
 descriptions.  The C<MIME::Parser> and C<Encode> modules are used.
 Processing control messages has been greatly improved, especially
 checkgroups:  the F<active> and F<newsgroups> files are now properly
-updated when they are processed.
+updated when they are processed, and all matching lines in F<control.ctl>
+for a given checkgroups are honoured (which for instance allows to use
+both B<drop> and B<doit> actions for the same checkgroups message).
 
 A new F<control.ctl.local> file has also been added in I<pathetc>.  Rules
 set in that file override rules in F<control.ctl>, allowing administrators

Modified: samples/control.ctl.local
===================================================================
--- samples/control.ctl.local	2009-04-25 14:13:59 UTC (rev 8430)
+++ samples/control.ctl.local	2009-04-25 14:22:17 UTC (rev 8431)
@@ -13,6 +13,11 @@
 ##  Output encoding for the newsgroups file.
 /localencoding/:utf-8
 
+##  Maximum number of changes that could be made at one time
+##  by a checkgroups before bailing and mailing the changes
+##  to the admin if no log file was specified.
+/maxdocheckgroups/:*:*:10
+
 ##  Incoming encodings in newgroup and checkgroups control articles.
 
 # Default (for any description).

Modified: scripts/innreport_inn.pm
===================================================================
--- scripts/innreport_inn.pm	2009-04-25 14:13:59 UTC (rev 8430)
+++ scripts/innreport_inn.pm	2009-04-25 14:22:17 UTC (rev 8431)
@@ -2014,6 +2014,9 @@
                   \s(\S+)             # e-mail
                   \s\S+               # e-mail
                   \s\S+,              # filename
+                  \s(?:\S+)?,         # exclusion pattern
+                  \s(?:\S+)?,         # drop pattern
+                  \s\S+,              # local encoding
                   \s\S+,              # server
                   \s([^=,]+(?:=\S+)?),            # action
                   \s*(.*)             # code
@@ -2033,8 +2036,8 @@
       $controlchan_doit{$email}++ if $action eq 'doit';
       return 1;
     }
-    # checkgroups processed (no change or not)
-    return 1 if $left =~ /^checkgroups by \S+ processed/o;
+    # checkgroups processed or not (with no change or not)
+    return 1 if $left =~ /^checkgroups by \S+/o;
   }
 
   ###########




More information about the inn-committers mailing list