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 ) );
+}