[PATCH 1/2] storage: Add "filtered" option, to store based on the filter's decision

Christoph Biedl isc.cxzo at manchmal.in-ulm.de
Tue Jan 16 19:00:00 UTC 2024


---
 doc/pod/storage.conf.pod |  8 ++++++++
 frontends/cnfsstat.in    | 35 +++++++++++++++++++++++------------
 include/inn/storage.h    |  1 +
 innd/art.c               |  5 +++--
 storage/interface.c      | 11 +++++++++++
 storage/interface.h      |  1 +
 6 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/doc/pod/storage.conf.pod b/doc/pod/storage.conf.pod
index 852bf589f..52c8cc2c8 100644
--- a/doc/pod/storage.conf.pod
+++ b/doc/pod/storage.conf.pod
@@ -137,6 +137,14 @@ wildmat as described above.)  This is a boolean value; C<true>, C<yes>
 and C<on> are usable to enable this key.  The case of these values is
 not significant.  The default is false.
 
+=item I<filtered>: <bool>
+
+If this key is set to true, the article must have been rejected by the
+Perl/Python filter.  This also requires that dontfilterrejected is set
+to true in F<inn.conf>.  This is a boolean value; C<true>, C<yes> and
+C<on> are usable to enable this key.  The case of these values is not
+significant.  The default is false.
+
 =back
 
 If an article matches all of the constraints of an entry, it is stored
diff --git a/frontends/cnfsstat.in b/frontends/cnfsstat.in
index 667c24ccb..953f0c266 100644
--- a/frontends/cnfsstat.in
+++ b/frontends/cnfsstat.in
@@ -159,28 +159,29 @@ if ($lastconftime < $maxtime) {
 
 my $logline;
 my $header_printed = 0;
-my ($gr, $cl, $min, $max);
+my ($gr, $cl, $min, $max, $filtered);
 if ($oclass) {
     if ($class{$oclass}) {
         if (!$header_printed) {
             if ($stor{$oclass}) {
-                ($gr, $cl, $min, $max) = split(/:/, $stor{$oclass});
+                ($gr, $cl, $min, $max, undef, $filtered) = split(/:/, $stor{$oclass});
             } else {
-                ($gr, $cl, $min, $max) = ('', $oclass, 0, 0);
+                ($gr, $cl, $min, $max, $filtered) = ('', $oclass, 0, 0, 0);
             }
             # Remove leading and trailing double quotes, if present.
+            my $filtered_s = $filtered ? ", filtered only" : "";
             $gr =~ s/"?([^"]*)"?/$1/g;
             if ($use_syslog) {
                 if ($min || $max) {
                     $logline = sprintf(
                         "Class %s for groups matching \"%s\" "
-                          . "article size min/max: %d/%d",
-                        $oclass, $gr, $min, $max,
+                          . "article size min/max: %d/%d%s",
+                        $oclass, $gr, $min, $max, $filtered_s,
                     );
                 } else {
                     $logline = sprintf(
-                        "Class %s for groups matching \"%s\"",
-                        $oclass, $gr,
+                        "Class %s for groups matching \"%s\"%s",
+                        $oclass, $gr, $filtered_s,
                     );
                 }
             } else {
@@ -189,6 +190,9 @@ if ($oclass) {
                 if ($min || $max) {
                     print STDOUT ", article size min/max: $min/$max";
                 }
+                if ($filtered) {
+                    print STDOUT ", filtered articles only";
+                }
                 print STDOUT "\n";
             }
             $header_printed = 1;
@@ -213,19 +217,20 @@ if ($oclass) {
 } else {    # Print all Classes
     my %buffDone;
     foreach my $c (@storsort) {
-        ($gr, $cl, $min, $max) = split(/:/, $stor{$c});
+        ($gr, $cl, $min, $max, undef, $filtered) = split(/:/, $stor{$c});
+        my $filtered_s = $filtered ? ", filtered only" : "";
         # Remove leading and trailing double quotes, if present.
         $gr =~ s/"?([^"]*)"?/$1/g;
         if ($use_syslog) {
             if ($min || $max) {
                 $logline = sprintf(
                     "Class %s for groups matching \"%s\" "
-                      . "article size min/max: %d/%d",
-                    $c, $gr, $min, $max,
+                      . "article size min/max: %d/%d%s",
+                    $c, $gr, $min, $max, $filtered_s,
                 );
             } else {
                 $logline
-                  = sprintf("Class %s for groups matching \"%s\"", $c, $gr);
+                  = sprintf("Class %s for groups matching \"%s\"%s", $c, $gr, $filtered_s);
             }
         } else {
             print STDOUT "Class $c";
@@ -233,6 +238,9 @@ if ($oclass) {
             if ($min || $max) {
                 print STDOUT ", article size min/max: $min/$max";
             }
+            if ($filtered) {
+                print STDOUT ", filtered articles only";
+            }
             print STDOUT "\n";
         }
         @buffers = split(/,/, $class{$c});
@@ -357,10 +365,13 @@ sub read_storageconf {
 
             $key{'SIZE'} .= ",0" unless $key{'SIZE'} =~ /,/;
             $key{'SIZE'} =~ s/,/:/;
+            $key{'FILTERED'} =
+                defined $key{'FILTERED'} ?
+                $key{'FILTERED'} =~ /^(true|yes|on)$/ ? 1 : 0 : 0;
 
             if (!defined $stor{ $key{'OPTIONS'} }) {
                 $stor{ $key{'OPTIONS'} } = "$key{'NEWSGROUPS'}:$key{'CLASS'}:"
-                  . "$key{'SIZE'}:$key{'OPTIONS'}";
+                  . "$key{'SIZE'}:$key{'OPTIONS'}:$key{'FILTERED'}";
                 push(@storsort, $key{'OPTIONS'});
             }
         }
diff --git a/include/inn/storage.h b/include/inn/storage.h
index 56230792a..2cdb1625c 100644
--- a/include/inn/storage.h
+++ b/include/inn/storage.h
@@ -50,6 +50,7 @@ typedef struct {
     void *private;            /* A pointer to method specific data */
     time_t arrived;           /* The time when the article arrived */
     time_t expires;           /* The time when the article will be expired */
+    bool filtered;            /* Article was marked by the filter */
     char *groups;             /* Where Newsgroups header field body starts */
     int groupslen;            /* Length of Newsgroups header field body */
     TOKEN *token;             /* A pointer to the article's TOKEN */
diff --git a/innd/art.c b/innd/art.c
index be51e7bf1..0ef1ac06b 100644
--- a/innd/art.c
+++ b/innd/art.c
@@ -435,7 +435,7 @@ ARTheaderpcmp(const void *p1, const void *p2)
 /* Write an article using the storage api.  Put it together in memory and
    call out to the api. */
 static TOKEN
-ARTstore(CHANNEL *cp)
+ARTstore(CHANNEL *cp, bool filtered)
 {
     struct buffer *Article = &cp->In;
     ARTDATA *data = &cp->Data;
@@ -557,6 +557,7 @@ ARTstore(CHANNEL *cp)
     arth.arrived = (time_t) 0;
     arth.token = (TOKEN *) NULL;
     arth.expires = data->Expires;
+    arth.filtered = filtered;
     if (innconf->storeonxref) {
         arth.groups = data->Replic;
         arth.groupslen = data->ReplicLength;
@@ -2576,7 +2577,7 @@ ARTpost(CHANNEL *cp)
     for (i = 0; (ngp = GroupPointers[i]) != NULL; i++)
         ngp->PostCount = 0;
 
-    token = ARTstore(cp);
+    token = ARTstore(cp, Filtered);
     /* Change trailing '\r\n' to '\0\n' of all system header fields. */
     for (i = 0; i < MAX_ARTHEADER; i++) {
         if (HDR_FOUND(i)) {
diff --git a/storage/interface.c b/storage/interface.c
index 81e7a25b4..34c0ebaec 100644
--- a/storage/interface.c
+++ b/storage/interface.c
@@ -261,6 +261,7 @@ ParseTime(char *tmbuf)
 #define SMexpire     14
 #define SMoptions    15
 #define SMexactmatch 16
+#define SMfiltered   17
 
 static CONFTOKEN smtoks[] = {
     {SMlbrace,     (char *) "{"          },
@@ -272,6 +273,7 @@ static CONFTOKEN smtoks[] = {
     {SMexpire,     (char *) "expires:"   },
     {SMoptions,    (char *) "options:"   },
     {SMexactmatch, (char *) "exactmatch:"},
+    {SMfiltered,   (char *) "filtered:"  },
     {0,            NULL                  }
 };
 
@@ -298,6 +300,7 @@ SMreadconfig(void)
     char *options = 0;
     int inbrace;
     bool exactmatch = false;
+    bool filtered = false;
 
     /* if innconf isn't already read in, do so. */
     if (innconf == NULL) {
@@ -351,6 +354,7 @@ SMreadconfig(void)
             minexpire = 0;
             maxexpire = 0;
             exactmatch = false;
+            filtered = false;
 
         } else {
             type = tok->type;
@@ -403,6 +407,11 @@ SMreadconfig(void)
                         || strcasecmp(p, "on") == 0)
                         exactmatch = true;
                     break;
+                case SMfiltered:
+                    if (strcasecmp(p, "true") == 0 || strcasecmp(p, "yes") == 0
+                        || strcasecmp(p, "on") == 0)
+                        filtered = true;
+                    break;
                 default:
                     SMseterror(SMERR_CONFIG,
                                "Unknown keyword in method declaration");
@@ -448,6 +457,7 @@ SMreadconfig(void)
             sub->minexpire = minexpire;
             sub->maxexpire = maxexpire;
             sub->exactmatch = exactmatch;
+            sub->filtered = filtered;
 
             free(method);
             method = 0;
@@ -643,6 +653,7 @@ SMgetsub(const ARTHANDLE article)
             && (!sub->maxsize || (article.len <= sub->maxsize))
             && (!sub->minexpire || article.expires >= sub->minexpire)
             && (!sub->maxexpire || (article.expires <= sub->maxexpire))
+            && (sub->filtered == article.filtered)
             && MatchGroups(article.groups, article.groupslen, sub->pattern,
                            sub->exactmatch)) {
             if (InitMethod(typetoindex[sub->type]))
diff --git a/storage/interface.h b/storage/interface.h
index b3cc35ca6..c67d1eb1e 100644
--- a/storage/interface.h
+++ b/storage/interface.h
@@ -45,6 +45,7 @@ typedef struct __S_SUB__ {
                          method */
     bool exactmatch;  /* all newsgroups to which article belongs
                          should match the patterns */
+    bool filtered;    /* article was marked by the filter */
     struct __S_SUB__ *next;
 } STORAGE_SUB;
 
-- 
2.39.2



More information about the inn-workers mailing list