changeset 49:5ecb646acf97 noffle

[svn] Article numbering bug fixes
author bears
date Sat, 06 May 2000 17:56:50 +0100
parents 21d3102dbc37
children 378dc39b473e
files ChangeLog NEWS src/content.c src/content.h src/server.c
diffstat 5 files changed, 118 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat May 06 17:55:22 2000 +0100
+++ b/ChangeLog	Sat May 06 17:56:50 2000 +0100
@@ -3,6 +3,33 @@
 -------------------------------------------------------------------------------
 
 
+Sat May  6 12:25:39 BST 2000  Jim Hague <jim.hague@acm.org>
+
+ * src/server.c: Changed XOVER with no arg. to return info for current
+   article, not error.
+
+ * src/server.c, src/content.h, src/content.c: XHDR - added 'xref' to
+   headers recognised to keep trn happy, and recognise message ID argument.
+
+ * src/server.c, src/content.c: Ensure first/last from LIST ACTIVE and
+   GROUP agree (trn uses former). Tricky with pseudo gen info articles
+   around. Presence of these now only recorded in content and not
+   reflected in group first/last until proper article posted after
+   pseudo.
+
+ * src/client.c, NEWS: Reinstated starting article numbering from first
+   article number on server. Reasoning below is wrong except in exceptional
+   circumstances (e.g. join group, auto-subscribe, manual unsubscribe,
+   auto subscribe again, etc. to get > 2 Noffle info messages in group.
+   Bring reader up to date, remove & reinstall Noffle. Join group,
+   autosubscribe after more news arrives at server, reader thinks it has read
+   n articles it hasn't, where n is number of Noffle info messages in
+   group first time round - 2). Feature is generally useful, esp. in
+   development, so back in it goes.
+
+ * src/group.c: Forget cached group info when group database closed.
+	
+
 Sat May  6 01:31:04 CEST 2000  Uwe Hermann <uh1763@bingo-ev.de>
 
  * Makefile.in, configure, configure.in, docs/Makefile.in, src/Makefile.in:
--- a/NEWS	Sat May 06 17:55:22 2000 +0100
+++ b/NEWS	Sat May 06 17:56:50 2000 +0100
@@ -5,6 +5,8 @@
 1.0pre6
 -------
 
+ * Add support for XOVER with no argument. Also XHDR with message ID
+   argument and XHDR when 'xref' requested (trn needs this).
  * Forget cached group info when group database closed.
  * Added list of 'forbidden' newsgroup specs., as defined in draft IETF
    Newsgroup Format (C.Lindsey), tracked to replace RFC1036. This defines
@@ -18,15 +20,6 @@
    e.g. due to all articles in a very low volume group expiring. This
    would cause article numbers to be set back to 1 when a new article
    arrives.
- * New groups now always start numbering at article 1. Previously article
-   numbering would start with the first held remote article number, in an
-   attempt to avoid newsreaders noticing if noffle is deleted and
-   reinstalled. Given Noffle may well not collect the first held article
-   anyway - it only will if the default number of articles to retrieve on
-   a first connect is big enough - and the fact that Noffle's pseudo
-   articles make it impossible to keep local article numbers in lock-step
-   with the server, there is the chance this scheme would just cause
-   readers to miss new articles.
  * Record newsgroup posting status. Enforce it at posting time.
    Added --modify to change newsgroup descriptions for all groups and
    posting status for local groups.
--- a/src/content.c	Sat May 06 17:55:22 2000 +0100
+++ b/src/content.c	Sat May 06 17:56:50 2000 +0100
@@ -1,7 +1,7 @@
 /*
   content.c
 
-  $Id: content.c 51 2000-05-05 23:49:38Z uh1763 $
+  $Id: content.c 55 2000-05-06 16:56:50Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -173,11 +173,6 @@
     FILE *f;
     const Over *ov;
 
-
-    /* Move the first article no. to the first active article */
-    while ( ! Cont_validNumb( cont.first ) && cont.first <= cont.last )
-        ++cont.first;
-
     /* Save the overview */
     if ( ! ( f = fopen( cont.file, "w" ) ) )
     {
@@ -186,6 +181,7 @@
     }
     Log_dbg( "Writing %s (%lu)", cont.file, cont.size );
     anythingWritten = FALSE;
+    cont.first = -1;
     for ( i = 0; i < cont.size; ++i )
     {
         if ( ( ov = cont.elem[ i ] ) )
@@ -198,7 +194,11 @@
                     break;
                 }
                 else
+		{
                     anythingWritten = TRUE;
+		    if  ( cont.first < 0 )
+			cont.first = cont.vecFirst + i;
+		}
             }
         }
     }
@@ -229,6 +229,22 @@
 int
 Cont_last( void ) { return cont.last; }
 
+int
+Cont_find( const char *msgId )
+{
+    int i;
+    const Over *ov;
+    
+    for ( i = 0; i < cont.size; i++ )
+    {
+        if ( ( ov = cont.elem[ i ] )
+	     && strcmp( Ov_msgId( ov ), msgId ) ==  0 )
+	    return i + cont.vecFirst;
+    }
+
+    return -1;
+}
+
 const char *
 Cont_grp( void ) { return cont.name; }
 
--- a/src/content.h	Sat May 06 17:55:22 2000 +0100
+++ b/src/content.h	Sat May 06 17:56:50 2000 +0100
@@ -8,7 +8,7 @@
   filename SPOOLDIR/overview/GROUPNAME. One entire overview file is read
   and cached in memory, at a time.
 
-  $Id: content.h 51 2000-05-05 23:49:38Z uh1763 $ 
+  $Id: content.h 55 2000-05-06 16:56:50Z bears $ 
 */
 
 #ifndef CONT_H
@@ -54,6 +54,9 @@
 int
 Cont_last( void );
 
+int
+Cont_find( const char *msgId );
+
 const char *
 Cont_grp( void );
 
--- a/src/server.c	Sat May 06 17:55:22 2000 +0100
+++ b/src/server.c	Sat May 06 17:56:50 2000 +0100
@@ -1,7 +1,7 @@
 /*
   server.c
 
-  $Id: server.c 51 2000-05-05 23:49:38Z uh1763 $
+  $Id: server.c 55 2000-05-06 16:56:50Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "online.h"
 #include "outgoing.h"
+#include "over.h"
 #include "post.h"
 #include "protocol.h"
 #include "pseudo.h"
@@ -224,17 +225,27 @@
         }
 }
 
+static Bool
+needsPseudoGenInfo( const char *grp )
+{
+    return ! ( Grp_local( grp )
+	       || Fetchlist_contains( grp )
+	       || Online_true() );
+}
+
 static void
 readCont( const char *name )
 {
     Fetchlist_read();
     Cont_read( name );
-    if ( ! Grp_local ( name )
-	 && ! Fetchlist_contains( name )
-	 && ! Online_true() )
+    if ( needsPseudoGenInfo( name ) )
     { 
         Pseudo_appGeneralInfo();
-        Grp_setFirstLast( name, Cont_first(), Cont_last() );
+	/* This adds the pseudo message to the overview contents
+	   but NOT to the group info. If an article gets added,
+	   the group info will get updated then from the
+	   contents, so the article number will be preserved.
+	   Otherwise it will be lost when the content is discarded. */
     }
 }
 
@@ -643,13 +654,25 @@
 static void
 printActive( Str result, const char *grp )
 {
+    int last;
+    
+    /* If there will be a pseudo gen info message waiting when we join
+       this group, fiddle the group numbers to show it. */
+    last = Grp_last( grp );
+    if ( needsPseudoGenInfo( grp ) )
+	last++;
+    
     snprintf( result, MAXCHAR, "%s %d %d %c",
-              grp, Grp_last( grp ), Grp_first( grp ), Grp_postAllow( grp ) );
+              grp, last, Grp_first( grp ), Grp_postAllow( grp ) );
 }
 
 static void
 doListActive( const char *pat )
 {
+    /* We need to read the fetchlist so we know whether a pseudo
+       gen info article needs to be faked when printing the group
+       last. */
+    Fetchlist_read();
     printGroups( pat, &printActive );
 }
 
@@ -1210,12 +1233,18 @@
             ++(*numb);
 }
 
+/*
+  Note this only handles a subset of headers. But they are all
+  the headers any newsreader should need to work properly.
+
+  That last sentence will at some stage be proved wrong.
+ */
 static Bool
 doXhdr( char *arg, const Cmd *cmd )
 {
     int first, last, i, n, numb;
-    enum { SUBJ, FROM, DATE, MSG_ID, REF, BYTES, LINES } what;
-    const char *p;
+    enum { SUBJ, FROM, DATE, MSG_ID, REF, BYTES, LINES, XREF } what;
+    const char *p, *msgId;
     const Over *ov;
     Str whatStr;
 
@@ -1241,6 +1270,8 @@
         what = BYTES;
     else if ( strcmp( whatStr, "lines" ) == 0 )
         what = LINES;
+    else if ( strcmp( whatStr, "xref" ) == 0 )
+        what = XREF;
     else
     {
         putStat( STAT_HEAD_FOLLOWS, "Unknown header (empty list follows)" );
@@ -1248,7 +1279,14 @@
         return TRUE;
     }
     p = Utl_restOfLn( arg, 1 );
-    parseRange( p, &first, &last, &numb );
+    if ( p[ 0 ] == '<' )
+    {
+	first = last = Cont_find( p );
+	if ( first < 0 )
+	    numb = 0;
+    }
+    else
+	parseRange( p, &first, &last, &numb );
     if ( numb == 0 )
         putStat( STAT_NO_ART_SELECTED, "No articles selected" );
     else
@@ -1282,6 +1320,13 @@
                 case LINES:
                     putTxtLn( "%lu %d", n, Ov_lines( ov ) );
                     break;
+		case XREF:
+		    msgId = Ov_msgId( ov );
+		    if ( Pseudo_isGeneralInfo( msgId ) )
+			putTxtLn( "%lu %s:%lu", n, serv.grp, n );
+		    else
+			putTxtLn( "%lu %s", n, Db_xref( msgId ) );
+		    break;
                 default:
                     ASSERT( FALSE );
                 }
@@ -1405,18 +1450,15 @@
         return TRUE;
     parseRange( arg, &first, &last, &n );
     if ( n == 0 )
-        putStat( STAT_NO_ART_SELECTED, "No articles selected" );
-    else
-    {
-        putStat( STAT_OVERS_FOLLOW, "Overview %ld-%ld", first, last );
-        for ( i = first; i <= last; ++i )
-            if ( ( ov = Cont_get( i ) ) )
-                putTxtLn( "%lu\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t",
-                          Ov_numb( ov ), Ov_subj( ov ), Ov_from( ov ),
-                          Ov_date( ov ), Ov_msgId( ov ), Ov_ref( ov ),
-                          Ov_bytes( ov ), Ov_lines( ov ) );
-        putEndOfTxt();
-    }
+	first = last = serv.artPtr;
+    putStat( STAT_OVERS_FOLLOW, "Overview %ld-%ld", first, last );
+    for ( i = first; i <= last; ++i )
+	if ( ( ov = Cont_get( i ) ) )
+	    putTxtLn( "%lu\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t",
+		      Ov_numb( ov ), Ov_subj( ov ), Ov_from( ov ),
+		      Ov_date( ov ), Ov_msgId( ov ), Ov_ref( ov ),
+		      Ov_bytes( ov ), Ov_lines( ov ) );
+    putEndOfTxt();
     return TRUE;
 }