changeset 436:4426f4dc6e8b noffle

[svn] * src/protocol.c: Reading of long lines broken in Prt_getLn(). Fix and change to split long lines rather than truncate. Also change Prt_putTxtBuf() to work properly with long lines by removing all fixed buffer dependencies.
author bears
date Wed, 25 Jun 2003 10:40:02 +0100
parents aae1f2906cea
children 5687083b6f9a
files src/protocol.c
diffstat 1 files changed, 56 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocol.c	Tue Jun 24 10:28:18 2003 +0100
+++ b/src/protocol.c	Wed Jun 25 10:40:02 2003 +0100
@@ -1,7 +1,7 @@
 /*
   protocol.c
 
-  $Id: protocol.c 419 2003-01-10 23:11:43Z bears $
+  $Id: protocol.c 579 2003-06-25 09:40:02Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -31,13 +31,33 @@
     return;
 }
 
+/*
+ * Read and return the next line from f.
+ *
+ * The line is considered terminated by '\n' or '\r\n'. If present,
+ * these are removed before the line is returned to the caller. NNTP
+ * says text should be terminated by '\r\n', but just '\n' is
+ * not unknown in the wild.
+ *
+ * Should the line be longer than can fit into the fixed MAXCHAR
+ * buffer of a Str, then return the first MAXCHAR - 2 characters (so
+ * the rest of the system can deal with that line plus a '\n') and
+ * push back the last character, leaving it to be read as the first
+ * character of a subsequent new 'next' line. This is a Bad Thing -
+ * news transports shouldn't bugger around with even pathalogical
+ * articles - but we'll have to live with it for now until someone
+ * gets round to FIXME.
+ *
+ * Lines that are terminated by EOF are returned as normal. Only if
+ * EOF occurs before any characters are read will this routine return
+ * FALSE.
+ */
 Bool
 Prt_getLn( Str line, FILE *f, int timeoutSeconds )
 {
     size_t len;
     char *ret;
     SignalHandler oldHandler = NULL;
-    int line_too_long;
 
     if ( timeoutSeconds >= 0 )
     {
@@ -50,10 +70,7 @@
         if ( alarm( timeoutSeconds ) != 0 )
             Log_err( "Prt_getLn: Alarm was already set." );
     }
-    /*
-      We also accept lines ending with "\n" instead of "\r\n", some
-      clients wrongly send such lines.
-    */
+    
     ret = fgets( line, MAXCHAR, f );
     if ( timeoutSeconds >= 0 )
     {
@@ -63,34 +80,19 @@
     if ( ret == NULL )
         return FALSE;
     len = strlen( line );
-    if ( len > 0 )
+    if ( len > 0 && line[ len - 1 ] == '\n' )
     {
-        if ( line[ len - 1 ] == '\n' )
-        {
-            line[ len - 1 ] = '\0';
-            if ( len > 1 && line[ len - 2 ] == '\r' )
-                line[ len - 2 ] = '\0';
-        }
-        else
-        {
-        /* line too long, skip the rest */
-            if( len == MAXCHAR )
-            {
-                Log_err( "Line too long:" );
-                do
-                {
-                    line_too_long = fgetc( f );
-                }
-                while( line_too_long == EOF || line_too_long == '\n' );
-            }
-            else
-            /* EOF occured in line, skip line. */
-            {
-                Log_err( "Ignoring incomplete line %s", line);
-                return FALSE;
-            }
-        }
+	line[ len - 1 ] = '\0';
+	if ( len > 1 && line[ len - 2 ] == '\r' )
+	    line[ len - 2 ] = '\0';
     }
+    else if ( len >= MAXCHAR - 1 )
+    {
+	ungetc( line[ len - 1 ], f );
+	line[ len - 1 ] = '\0';
+	Log_err( "Prt_getLn: Input line too long, splitting." );
+    }    
+    
     Log_dbg( LOG_DBG_PROTOCOL, "[R] %s", line );
     return TRUE;
 }
@@ -148,35 +150,31 @@
 Bool
 Prt_putTxtBuf( const char *buf, FILE *f )
 {
-    Str line;
-    const char *pBuf;
-    char *pLn;
+    DynStr *line;
+    const char *eol;
+    Bool res = TRUE;
 
-    pBuf = buf;
-    pLn = line;
-    while ( *pBuf != '\0' )
+    line = new_DynStr(MAXCHAR);
+
+    while ( res && *buf != '\0' )
     {
-        if ( *pBuf == '\n' )
-        {
-            *pLn = '\0';
-            if ( ! Prt_putTxtLn( line, f ) )
-                return FALSE;
-            pLn = line;
-            ++pBuf;
-        }
-        else if ( pLn - line >= MAXCHAR - 1 )
-        {
-            /* Put it out raw to prevent String overflow */
-            Log_err( "Writing VERY long line" );
-            *pLn = '\0';
-            if ( fprintf( f, "%s", line ) != (int)strlen( line ) )
-                return FALSE;
-            pLn = line;
-        }   
-        else
-            *(pLn++) = *(pBuf++);
+	eol = strchr( buf, '\n' );
+	if ( eol != NULL )
+	{
+	    DynStr_appN( line, buf, eol - buf );
+	    buf = eol + 1;
+	    res = Prt_putTxtLn( DynStr_str( line ), f );
+	    DynStr_clear( line );
+	}
+	else
+	{
+	    res = Prt_putTxtLn( buf, f );
+	    break;
+	}
     }
-    return TRUE;
+
+    del_DynStr( line );
+    return res;
 }
 
 Bool