# HG changeset patch # User bears # Date 1056534002 -3600 # Node ID 4426f4dc6e8b38fcf75c22906eba04d064f56486 # Parent aae1f2906cea24b18e100305fefc6ff2672f469a [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. diff -r aae1f2906cea -r 4426f4dc6e8b src/protocol.c --- 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