Mercurial > noffle
diff src/protocol.c @ 43:2842f50feb55 noffle
[svn] * client.c, client.h, common.h, config.c, config.h, content.c, content.h,
control.c, control.h, database.c, database.h, dynamicstring.c,
dynamicstring.h, fetch.c, fetch.h, fetchlist.c, fetchlist.h, group.c,
group.h, itemlist.c, itemlist.h, lock.c, lock.h, log.c, log.h, noffle.c,
online.c, online.h, outgoing.c, outgoing.h, over.c, over.h, post.c, post.h,
protocol.c, protocol.h, pseudo.c, pseudo.h, request.c, request.h, server.c,
server.h, util.c, util.h, wildmat.c, wildmat.h: Moved files to the
subdirectory src/
* Makefile.am, acconfig.h, configure.in, docs/Makefile.am, src/Makefile.am,
Makefile.in, aclocal.m4, config.h.in, configure, install-sh, missing,
mkinstalldirs, stamp-h.in, docs/Makefile.in, src/Makefile.in: Added files.
They are used by aclocal, autoheader, autoconf and automake.
* src/config.c, src/config.h: Renamed to configfile.c and configfile.h,
because configure will generate a config.h file itself.
* src/client.c, src/content.c, src/database.c, src/fetch.c, src/fetchlist.c,
src/group.c, src/lock.c, src/noffle.c, src/online.c, src/outgoing.c,
src/over.c, src/pseudo.c, src/request.c, src/server.c, src/util.c:
Changed '#include "config.h"' to '#include "configfile.h"'.
* src/client.c, src/content.c, src/database.c, src/fetch.c, src/fetchlist.c,
src/group.c, src/lock.c, src/online.c, src/outgoing.c, src/post.c,
src/protocol.c, src/request.c, src/server.c: Files now #include <config.h>.
Added missing <stdio.h>. This removes the warnings about snprintf() not
being declared.
* Makefile: Removed. This is now generated by configure.
author | uh1763 |
---|---|
date | Fri, 05 May 2000 22:45:56 +0100 |
parents | |
children | 32ba1198c6fa |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocol.c Fri May 05 22:45:56 2000 +0100 @@ -0,0 +1,284 @@ +/* + protocol.c + + $Id: protocol.c 49 2000-05-05 21:45:56Z uh1763 $ +*/ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include "common.h" +#include "dynamicstring.h" +#include "log.h" +#include "over.h" +#include "util.h" + +Bool +Prt_getLn( Str line, FILE *f ) +{ + size_t len; + + /* + We also accept lines ending with "\n" instead of "\r\n", some + clients wrongly send such lines. + */ + if ( ! fgets( line, MAXCHAR, f ) ) + { + Log_dbg( "Prt_getLine failed" ); + return FALSE; + } + len = strlen( line ); + if ( line[ len - 1 ] == '\n' ) + { + line[ len - 1 ] = '\0'; + if ( line[ len - 2 ] == '\r' ) + line[ len - 2 ] = '\0'; + } + Log_dbg( "[R] %s", line ); + return TRUE; +} + +Bool +Prt_getTxtLn( Str line, Bool *err, FILE *f ) +{ + Str buf; + + if ( ! Prt_getLn( buf, f ) ) + { + Log_err( "Cannot get text line" ); + *err = TRUE; + return FALSE; + } + *err = FALSE; + if ( buf[ 0 ] == '.' ) + { + if ( buf[ 1 ] == 0 ) + return FALSE; + else + strcpy( line, buf + 1 ); + } + else + strcpy( line, buf ); + return TRUE; +} + +Bool +Prt_putTxtLn( const char* line, FILE *f ) +{ + if ( line[ 0 ] == '.' ) + { + Log_dbg( "[S] .%s", line ); + return ( fprintf( f, ".%s\r\n", line ) == strlen( line ) + 3 ); + } + else + { + Log_dbg( "[S] %s", line ); + return ( fprintf( f, "%s\r\n", line ) == strlen( line ) + 2 ); + } +} + +Bool +Prt_putEndOfTxt( FILE *f ) +{ + Log_dbg( "[S] ." ); + return ( fprintf( f, ".\r\n" ) == 3 ); +} + +/* + Write text buffer of lines each ending with '\n'. + Replace '\n' by "\r\n". +*/ +Bool +Prt_putTxtBuf( const char *buf, FILE *f ) +{ + Str line; + const char *pBuf; + char *pLn; + + pBuf = buf; + pLn = line; + while ( *pBuf != '\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 ) != strlen( line ) ) + return FALSE; + pLn = line; + } + else + *(pLn++) = *(pBuf++); + } + return TRUE; +} + +Bool +Prt_getField( Str resultField, Str resultValue, const char* line ) +{ + char *dst; + const char *p; + Str lineLower, t; + + Utl_cpyStr( lineLower, line ); + Utl_toLower( lineLower ); + p = Utl_stripWhiteSpace( lineLower ); + dst = resultField; + while ( ! isspace( *p ) && *p != ':' && *p != '\0' ) + *(dst++) = *(p++); + *dst = '\0'; + while ( isspace( *p ) ) + ++p; + if ( *p == ':' ) + { + ++p; + strcpy( t, line + ( p - lineLower ) ); + p = Utl_stripWhiteSpace( t ); + strcpy( resultValue, p ); + return TRUE; + } + return FALSE; +} + +Bool +Prt_searchHeader( const char *artTxt, const char *which, Str result ) +{ + const char *src, *p; + char *dst; + Str line, whichLower, field; + int len; + + Utl_cpyStr( whichLower, which ); + Utl_toLower( whichLower ); + src = artTxt; + while ( TRUE ) + { + dst = line; + len = 0; + while ( *src != '\n' && len < MAXCHAR ) + { + if ( *src == '\0' ) + return FALSE; + *(dst++) = *(src++); + ++len; + } + if ( *src == '\n' ) + ++src; + *dst = '\0'; + p = Utl_stripWhiteSpace( line ); + if ( *p == '\0' ) + break; + if ( Prt_getField( field, result, line ) + && strcmp( field, whichLower ) == 0 ) + return TRUE; + } + return FALSE; +} + +static Bool +getFQDN( Str result ) +{ + struct hostent *myHostEnt; + struct utsname myName; + + if ( uname( &myName ) >= 0 + && ( myHostEnt = gethostbyname( myName.nodename ) ) ) + { + Utl_cpyStr( result, myHostEnt->h_name ); + return TRUE; + } + return FALSE; +} + +static void +getDomain( Str domain, const char *from ) +{ + const char *addTopLevel, *p1, *p2, *p, *domainStart; + Str myDomain; + + if ( getFQDN( myDomain ) ) + { + p = strstr( myDomain, "." ); + if ( p != NULL ) + domainStart = p + 1; + else + domainStart = myDomain; + } + else /* Take domain of From field */ + { + myDomain[ 0 ] = '\0'; + p1 = strstr( from, "@" ); + if ( p1 != NULL ) + { + p2 = strstr( p1, ">" ); + if ( p2 != NULL ) + Utl_cpyStrN( myDomain, p1 + 1, p2 - p1 - 1 ); + } + if ( myDomain[ 0 ] == '\0' ) + Utl_cpyStr( myDomain, "unknown" ); + domainStart = myDomain; + } + /* + If domain contains no dot (and is probably invalid anyway), + we add ".local", because some servers insist on domainnames with dot + in message ID. + */ + addTopLevel = strstr( domainStart, "." ) == NULL ? ".local" : ""; + snprintf( domain, MAXCHAR, "%s%s", myDomain, addTopLevel ); +} + +/* See RFC 850, section 2.1.7 */ +Bool +Prt_isValidMsgId( const char *msgId ) +{ + Str head, domain; + int len, headLen; + const char *p; + + len = strlen( msgId ); + p = strstr( msgId, "@" ); + if ( msgId[ 0 ] != '<' || msgId[ len - 1 ] != '>' || p == NULL ) + return FALSE; + strcpy( domain, p + 1 ); + domain[ strlen( domain ) - 1 ] = '\0'; + headLen = p - msgId - 1; + Utl_cpyStrN( head, msgId + 1, headLen ); + head[ headLen ] = '\0'; + /* + To do: check for special characters in head and domain (non-printable + or '@', '<', '>'). Maybe compare domain with a config option + and replace it by the config option, if not equal. + */ + if ( strstr( domain, "." ) == NULL ) + return FALSE; + return TRUE; +} + +void +Prt_genMsgId( Str msgId, const char *from, const char *suffix ) +{ + Str domain, date; + time_t t; + + getDomain( domain, from ); + time( &t ); + strftime( date, MAXCHAR, "%Y%m%d%H%M%S", gmtime( &t ) ); + srand( time( NULL ) ); + snprintf( msgId, MAXCHAR, "<%s.%X.%s@%s>", date, rand(), suffix, domain ); + ASSERT( Prt_isValidMsgId( msgId ) ); +}