diff server.c @ 26:526a4c34ee2e noffle

[svn] Applied patch from Jim Hague: support for local groups / new command line options --create and --cancel.
author enz
date Sat, 29 Apr 2000 15:45:56 +0100
parents 43631b72021f
children 792eb10e936d
line wrap: on
line diff
--- a/server.c	Sat Apr 29 14:37:59 2000 +0100
+++ b/server.c	Sat Apr 29 15:45:56 2000 +0100
@@ -1,7 +1,7 @@
 /*
   server.c
 
-  $Id: server.c 18 2000-04-15 10:09:20Z enz $
+  $Id: server.c 32 2000-04-29 14:45:56Z enz $
 */
 
 #include "server.h"
@@ -16,15 +16,18 @@
 #include "common.h"
 #include "config.h"
 #include "content.h"
+#include "control.h"
 #include "database.h"
 #include "dynamicstring.h"
 #include "fetch.h"
 #include "fetchlist.h"
 #include "group.h"
+#include "itemlist.h"
 #include "lock.h"
 #include "log.h"
 #include "online.h"
 #include "outgoing.h"
+#include "post.h"
 #include "protocol.h"
 #include "pseudo.h"
 #include "request.h"
@@ -103,7 +106,7 @@
     FetchMode mode;
 
     Grp_setLastAccess( serv.grp, time( NULL ) );
-    if ( Cfg_autoSubscribe() && ! Online_true() )
+    if ( ! Grp_local ( serv.grp ) && Cfg_autoSubscribe() && ! Online_true() )
     {
         Fetchlist_read();
         if ( ! Fetchlist_contains( serv.grp ) )
@@ -219,7 +222,9 @@
 {
     Fetchlist_read();
     Cont_read( name );
-    if ( ! Fetchlist_contains( name ) && ! Online_true() )
+    if ( ! Grp_local ( name )
+	 && ! Fetchlist_contains( name )
+	 && ! Online_true() )
     { 
         Pseudo_appGeneralInfo();
         Grp_setFirstLast( name, Cont_first(), Cont_last() );
@@ -302,7 +307,7 @@
     Str serv;
 
     findServ( msgId, serv );    
-    if ( strcmp( serv, "(unknown)" ) == 0 )
+    if ( strcmp( serv, "(unknown)" ) == 0  || strcmp( serv, "(local)" ) == 0 )
         return FALSE;        
     if ( ! Client_connect( serv ) )
         return FALSE;
@@ -425,7 +430,9 @@
         findServ( msgId, serv );
         if ( Req_contains( serv, msgId ) )
             putTxtBuf( Pseudo_alreadyMarkedBody() );
-        else if ( strcmp( serv, "(unknown)" ) != 0 && Req_add( serv, msgId ) )
+        else if ( strcmp( serv, "(unknown)" ) != 0 && 
+		  strcmp( serv, "(local)" ) != 0 && 
+		  Req_add( serv, msgId ) )
             putTxtBuf( Pseudo_markedBody() );
         else
             putTxtBuf( Pseudo_markingFailedBody() );
@@ -845,38 +852,133 @@
     return TRUE;
 }
 
+/* Cancel and return TRUE if need to send cancel message on to server. */
+static Bool
+controlCancel( const char *cancelId )
+{
+    return ( Ctrl_cancel( cancelId ) == CANCEL_NEEDS_MSG );
+}
+
 /*
-  Get first group of the Newsgroups field content, which is
-  a comma separated list of groups.
-*/
-static void
-getFirstGrp( char *grpResult, const char *list )
+  It's a control message. Currently we only know about 'cancel'
+  messages; others are passed on for outside groups, and logged
+  as ignored for local groups.
+ */
+static Bool
+handleControl( ItemList *control, ItemList *newsgroups,
+	       const char *msgId, const DynStr *art )
 {
-    Str t;
-    const char *src = list;
-    char *dest = t;
-    while( TRUE )
+    const char *grp;
+    const char *op;
+    Bool err = FALSE;
+    Bool localDone = FALSE;
+
+    op = Itl_first( control );
+    if ( op == NULL )
+    {
+	Log_err( "Malformed control line." );
+	return TRUE;
+    }
+    else if ( strcasecmp( op, "cancel" ) == 0 )
+    {
+	if ( controlCancel( Itl_next( control ) ) )
+	    localDone = TRUE;
+	else
+	    return err;
+    }
+
+    /* Pass on for outside groups. */
+    for( grp = Itl_first( newsgroups );
+	 grp != NULL;
+	 grp = Itl_next( newsgroups ) )
+    {
+	if ( Grp_exists( grp ) && ! Grp_local( grp ) )
+	{
+	    if ( ! Out_add( Grp_serv( grp ), msgId, art ) )
+	    {
+		Log_err( "Cannot add posted article to outgoing directory" );
+		err = TRUE;
+	    }
+	    break;
+	}
+    }
+
+    if ( localDone )
+	return err;
+
+    /* Log 'can't do' for internal groups. */
+    for( grp = Itl_first( newsgroups );
+	 grp != NULL;
+	 grp = Itl_next( newsgroups ) )
     {
-        if ( *src == ',' )
-            *dest = ' ';
-        else
-            *dest = *src;
-        if ( *src == '\0' )
-            break;
-        ++src;
-        ++dest;
+	if ( Grp_exists( grp ) && Grp_local( grp ) )
+	    Log_inf( "Ignoring control '%s' for '%s'.", op, grp );
     }
-    *grpResult = '\0';
-    sscanf( t, "%s", grpResult );
+
+    return err;
+}
+
+static Bool
+postArticle( ItemList *newsgroups, const char *msgId, const DynStr *art )
+{
+    const char *grp;
+    Bool err;
+    Bool oneLocal;
+
+    err = oneLocal = FALSE;
+
+    /* Run round first doing all local groups. */ 
+    for( grp = Itl_first( newsgroups );
+	 grp != NULL;
+	 grp = Itl_next( newsgroups ) )
+    {
+	if ( Grp_local( grp ) )
+	{
+	    if ( ! oneLocal )
+	    {
+		if ( ! Post_open( DynStr_str( art ) ) )
+		{
+		    err = TRUE;
+		    break;
+		}
+		else
+		    oneLocal = TRUE;
+	    }
+
+	    if ( ! Post_add( grp ) )
+		err = TRUE;
+	}
+    }
+    if ( oneLocal )
+	Post_close();
+
+    /* Now look for a valid external group. */
+    for( grp = Itl_first( newsgroups );
+	 grp != NULL;
+	 grp = Itl_next( newsgroups ) )
+    {
+	if ( Grp_exists( grp ) && ! Grp_local( grp ) )
+	{
+	    if ( ! Out_add( Grp_serv( grp ), msgId, art ) )
+	    {
+		Log_err( "Cannot add posted article to outgoing directory" );
+		err = TRUE;
+	    }
+	    break;
+	}
+    }
+
+    return err;
 }
 
 static Bool
 doPost( char *arg, const Cmd *cmd )
 {
-    Bool err, replyToFound, inHeader;
+    Bool err, replyToFound, dateFound, inHeader;
     DynStr *s;
-    Str line, field, val, msgId, from, grp;
+    Str line, field, val, msgId, from;
     const char* p;
+    ItemList * newsgroups, *control;
 
     /*
       Get article and make following changes to the header:
@@ -895,8 +997,8 @@
     s = new_DynStr( 10000 );
     msgId[ 0 ] = '\0';
     from[ 0 ] = '\0';
-    grp[ 0 ] = '\0';
-    replyToFound = FALSE;
+    newsgroups = control = NULL;
+    replyToFound = dateFound = FALSE;
     inHeader = TRUE;
     while ( getTxtLn( line, &err ) )
     {
@@ -918,6 +1020,7 @@
                     else if ( msgId[ 0 ] == '\0' )
                     {
                         Prt_genMsgId( msgId, from, "NOFFLE" );
+
                         Log_inf( "Adding missing Message-ID '%s'", msgId );
                     }
                     else if ( ! Prt_isValidMsgId( msgId ) )
@@ -935,6 +1038,16 @@
                     DynStr_app( s, "Reply-To: " );
                     DynStr_appLn( s, from );
                 }
+		if ( ! dateFound )
+		{
+		    time_t t;
+
+		    time( &t );
+		    strftime( val, MAXCHAR, "%d %b %Y %H:%M:%S %Z",
+			      localtime( &t ) );
+		    DynStr_app( s, "Date: " );
+		    DynStr_appLn( s, val );
+		}
                 DynStr_appLn( s, p );
             }
             else if ( Prt_getField( field, val, p ) )
@@ -948,8 +1061,13 @@
                 }
                 else if ( strcmp( field, "newsgroups" ) == 0 )
                 {
-                    getFirstGrp( grp, val );
-                    Utl_toLower( grp );
+                    Utl_toLower( val );
+                    newsgroups = new_Itl ( val, " ," );
+                    DynStr_appLn( s, p );
+                }
+                else if ( strcmp( field, "control" ) == 0 )
+                {
+                    control = new_Itl ( val, " " );
                     DynStr_appLn( s, p );
                 }
                 else if ( strcmp( field, "reply-to" ) == 0 )
@@ -957,6 +1075,11 @@
                     replyToFound = TRUE;
                     DynStr_appLn( s, p );
                 }
+                else if ( strcmp( field, "date" ) == 0 )
+                {
+                    dateFound = TRUE;
+                    DynStr_appLn( s, p );
+                }
                 else if ( strcmp( field, "x-sender" ) == 0 )
                 {
                     DynStr_app( s, "X-NOFFLE-X-Sender: " );
@@ -975,21 +1098,41 @@
         Log_err( "Posted message has no body" );
     if ( ! err )
     {
-        if ( grp[ 0 ] == '\0' )
+        if ( newsgroups == NULL || Itl_count( newsgroups ) == 0 )
         {
-            Log_err( "Posted message has no Newsgroups header field" );
+            Log_err( "Posted message has no valid Newsgroups header field" );
             err = TRUE;
         }
-        else if ( ! Grp_exists( grp ) )
-        {    
-            Log_err( "Unknown group in Newsgroups header field" );
-            err = TRUE;
-        }
-        else if ( ! Out_add( Grp_serv( grp ), msgId, s ) )
-        {
-            Log_err( "Cannot add posted article to outgoing directory" );
-            err = TRUE;
-        }
+        else
+	{
+	    const char *grp;
+	    Bool knownGrp = FALSE;
+
+	    /* Check at least one group is known. */
+	    for( grp = Itl_first( newsgroups );
+		 grp != NULL;
+		 grp = Itl_next( newsgroups ) )
+	    {
+		if ( Grp_exists( grp ) )
+		{
+		    knownGrp = TRUE;
+		    break;
+		}
+	    }
+	    
+	    if ( ! knownGrp )
+	    {
+
+		Log_err( "No known group in Newsgroups header field" );
+		err = TRUE;
+	    }
+	    else
+	    {
+		err = ( control == NULL )
+		    ? postArticle( newsgroups, msgId, s )
+		    : handleControl( control, newsgroups, msgId, s );
+	    }	    
+	}
     }
     if ( err )
         putStat( STAT_POST_FAILED, "Posting failed" );
@@ -999,6 +1142,8 @@
         if ( Online_true() )
             postArts();
     }
+    del_Itl( newsgroups );
+    del_Itl( control );
     del_DynStr( s );
     return TRUE;
 }