diff src/configfile.c @ 128:8897b7e3b108 noffle

[svn] Add article filtering
author bears
date Wed, 09 Aug 2000 22:19:17 +0100
parents 6f681d41734c
children 7dfbb1c20a81
line wrap: on
line diff
--- a/src/configfile.c	Tue Jul 25 13:14:54 2000 +0100
+++ b/src/configfile.c	Wed Aug 09 22:19:17 2000 +0100
@@ -6,7 +6,7 @@
     SPOOLDIR
     VERSION
 
-  $Id: configfile.c 155 2000-06-24 20:28:01Z bears $
+  $Id: configfile.c 189 2000-08-09 21:19:17Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -17,6 +17,8 @@
 
 #include <ctype.h>
 #include <limits.h>
+#include <regex.h>
+#include "filter.h"
 #include "itemlist.h"
 #include "log.h"
 #include "util.h"
@@ -554,6 +556,184 @@
     config.autoSubscribeMode[ config.numAutoSubscribeMode++ ] = entry;
 }
 
+static const char *
+getToken( const char *line, Str value )
+{
+    Bool isQuoted;
+    char quoteChar;
+    Bool seenEscape;
+    char *maxVal;
+    
+    while ( *line != '\0' && isspace( *line ) )
+	line++;
+    if ( *line == '\0' )
+	return NULL;
+
+    maxVal = &value[ MAXCHAR ];
+    isQuoted = ( *line == '\'' || *line == '"' );
+    if ( isQuoted )
+    {
+	quoteChar = *line;
+	line++;
+
+	seenEscape = FALSE;
+	while ( *line != '\0'
+		&& ( *line != quoteChar || seenEscape )
+		&& value < maxVal )
+	{
+	    if ( seenEscape )
+	    {
+		*value++ = *line;
+		seenEscape = FALSE;
+	    }
+	    else
+	    {
+		if ( *line == '\\' )
+		    seenEscape = TRUE;
+		else
+		    *value++ = *line;
+	    }
+	    line++;
+	}
+
+	if ( *line == quoteChar )
+	    line++;
+    }
+    else
+    {
+	while ( *line != '\0' && ! isspace( *line ) && value < maxVal )
+	    *value++ = *line++;
+    }
+    *value = '\0';
+    return line;
+}
+
+static void
+getFilter( const char *line )
+{
+    Str ruleBuf, value;
+    const char *l;
+    char *p, *ruleName;
+    Filter *f;
+    FilterRule rule;
+    Bool seenAction;
+
+    f = new_Filter();
+    
+    /* Skip "filter" */
+    l = Utl_restOfLn( line, 1 );
+    seenAction = FALSE;
+    
+    for(;;)
+    {
+	while ( *l != '\0' && isspace( *l ) )
+	    l++;
+
+	if ( *l == '\0' )
+	    break;
+	
+	/* Get the rule title */
+	p = ruleBuf;
+	while ( *l != '\0' && *l != '=' && *l != '<' && *l != '>' )
+	    *p++ = *l++;
+	*p = '\0';
+	ruleName = Utl_stripWhiteSpace( ruleBuf );
+	Utl_toLower( ruleName );
+
+	if ( *ruleName == '\0' )
+	    goto synErr;
+
+	/* Do we know this rule? */
+	if ( strcmp( ruleName, "group" ) == 0 )
+	    rule.type = RULE_NEWSGROUP;
+	else if ( strcmp( ruleName, "subject" ) == 0 )
+	    rule.type = RULE_SUBJECT;
+	else if ( strcmp( ruleName, "from" ) == 0 )
+	    rule.type = RULE_FROM;
+	else if ( strcmp( ruleName, "msgid" ) == 0 )
+	    rule.type = RULE_MSGID;
+	else if ( strcmp( ruleName, "bytes" ) == 0 )
+	    rule.type = RULE_BYTES_LT;
+	else if ( strcmp( ruleName, "lines" ) == 0 )
+	    rule.type = RULE_LINES_LT;
+	else if ( strcmp( ruleName, "refs" ) == 0 )
+	    rule.type = RULE_NOREFS_LT;
+	else if ( strcmp( ruleName, "xposts" ) == 0 )
+	    rule.type = RULE_XPOSTS_LT;
+	else if ( strcmp( ruleName, "action" ) != 0 )
+	    goto synErr;
+
+	if ( rule.type == RULE_BYTES_LT ||
+	     rule.type == RULE_LINES_LT ||
+	     rule.type == RULE_NOREFS_LT ||
+	     rule.type == RULE_XPOSTS_LT )
+	{
+	    if ( *l == '=' )
+		rule.type += 1;
+	    else if ( *l == '>' )
+		rule.type += 2;
+	    else if ( *l != '<' )
+		goto synErr;
+	}
+	else if ( *l != '=' )
+	    goto synErr;
+
+	/* Skip past '=' (or '>' or '<') */
+	l++;
+	
+	/* OK, we now have a valid rule. What value? */
+	l = getToken( l, value );
+	if ( l == NULL )
+	    goto synErr;
+
+	if ( strcmp( ruleName, "action" ) == 0 )
+	{
+	    if ( seenAction )
+		goto synErr;
+	    
+	    Utl_toLower( value );
+	    if ( strcmp( value, "full" ) == 0 )
+		f->action = FILTER_FULL;
+	    else if ( strcmp( value, "over" ) == 0 )
+		f->action = FILTER_XOVER;
+	    else if ( strcmp( value, "thread" ) == 0 )
+		f->action = FILTER_THREAD;
+	    else if ( strcmp( value, "discard" ) == 0 )
+		f->action = FILTER_DISCARD;
+	    seenAction = TRUE;
+	}
+	else if ( rule.type == RULE_NEWSGROUP )
+	    Utl_allocAndCpy( &rule.data.grp, value );
+	else if ( rule.type >= RULE_SUBJECT && rule.type <= RULE_MSGID )
+	{
+	    if ( regcomp( &rule.data.regex, value, REG_EXTENDED ) != 0 )
+		goto synErr;
+	}
+	else
+	{
+	    char * endVal;
+
+	    rule.data.amount = strtoul( value, &endVal, 0 );
+	    if ( *endVal != '\0' && ! isspace( *endVal ) )
+		goto synErr;
+	}
+
+	if ( strcmp( ruleName, "action" ) != 0 )
+	{
+	    Log_dbg( "Adding rule type %d value %s", rule.type, value );
+	    Flt_addRule( f, rule );
+	}
+    }
+
+    Log_dbg( "Adding filter, action %d", f->action );
+    Flt_addFilter( f );
+    return;
+    
+synErr:
+    logSyntaxErr( line );
+    return;
+}
+
 void
 Cfg_read( void )
 {
@@ -573,6 +753,7 @@
 	Utl_stripComment( p );
         Utl_cpyStr( lowerLine, p );
         Utl_toLower( lowerLine );
+	p = lowerLine;
         if ( *p == '\0' )
             continue;
         if ( sscanf( p, "%s", name ) != 1 )
@@ -600,7 +781,6 @@
         else if ( strcmp( "default-auto-subscribe-mode", name ) == 0 )
         {
             getStr( s, p );
-            Utl_toLower( s );
 	    if ( ! isValidAutoSubscribeMode( s ) )
 	    {
 		logSyntaxErr( line );
@@ -609,14 +789,8 @@
             else
                 strcpy( config.defaultAutoSubscribeMode, s );
         }
-        else if ( strcmp( "server", name ) == 0 )
-            /* Server needs line not p,
-               because password may contain uppercase */
-            getServ( line );
         else if ( strcmp( "mail-to", name ) == 0 )
             getStr( config.mailTo, p );
-        else if ( strcmp( "path-header", name ) == 0 )
-            getStr( config.pathHeader, p );
         else if ( strcmp( "expire", name ) == 0 )
             getExpire( p );
         else if ( strcmp( "auto-subscribe-mode", name ) == 0 )
@@ -625,6 +799,13 @@
             getGroups( p, TRUE );
         else if ( strcmp( "omitgroups", name ) == 0 )
             getGroups( p, FALSE );
+	/* The following need line because they may have uppercase data */
+        else if ( strcmp( "server", name ) == 0 )
+            getServ( line );
+        else if ( strcmp( "path-header", name ) == 0 )
+            getStr( config.pathHeader, p );
+	else if ( strcmp( "filter", name ) == 0 )
+	    getFilter( line );
         else
             Log_err( "Unknown config option: %s", name );
     }