Mercurial > noffle
view src/protocol.c @ 191:28488e0e3630 noffle
[svn] * src/group.h,src/group.c,src/noffle.c,src/server.c: Grp_setLastAccess is
only ever called with last param as time(NULL), so remove it and call
time() inside the implementation of Grp_setLastAccess.
* src/client.c,src/group.h,src/group.c,src/noffle.c,src/post.c: Groups are
automatically unsubscribed when the last access to the group is older
than a particular threshold. However, for very low traffic groups, the
last access may exceed the threshold simply because there has been no new
article posted. In this case, rather than unsubscribe, update the group
last access time. This means that groups are now only unsubscribed if
the last access exceeds the threshold AND articles have arrived in the
group since. Add Grp_setLastPostTime() to track the last time an article
arrived in the group.
author | bears |
---|---|
date | Sat, 20 Oct 2001 14:23:46 +0100 |
parents | fed1334d766b |
children | 76460d98b2fb |
line wrap: on
line source
/* protocol.c $Id: protocol.c 300 2001-08-05 08:24:22Z bears $ */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <ctype.h> #include <netdb.h> #include <pwd.h> #include <signal.h> #include <sys/types.h> #include <sys/utsname.h> #include <unistd.h> #include "common.h" #include "configfile.h" #include "dynamicstring.h" #include "log.h" #include "over.h" #include "util.h" #include "protocol.h" #include "portable.h" static void readAlarm( int sig ) { UNUSED( sig ); return; } Bool Prt_getLn( Str line, FILE *f, int timeoutSeconds ) { size_t len; char *ret; sig_t oldHandler = NULL; if ( timeoutSeconds >= 0 ) { oldHandler = Utl_installSignalHandler( SIGALRM, readAlarm ); if ( oldHandler == SIG_ERR ) { Log_err( "Prt_getLn: signal failed." ); return FALSE; } 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 ) { alarm( 0 ); Utl_installSignalHandler( SIGALRM, oldHandler ); } if ( ret == NULL ) return FALSE; len = strlen( line ); if ( len > 0 && line[ len - 1 ] == '\n' ) { line[ len - 1 ] = '\0'; if ( len > 1 && line[ len - 2 ] == '\r' ) line[ len - 2 ] = '\0'; } Log_dbg( LOG_DBG_PROTOCOL, "[R] %s", line ); return TRUE; } Bool Prt_getTxtLn( Str line, Bool *err, FILE *f, int timeoutSeconds ) { Str buf; if ( ! Prt_getLn( buf, f, timeoutSeconds ) ) { 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( LOG_DBG_PROTOCOL, "[S] .%s", line ); return ( fprintf( f, ".%s\r\n", line ) == (int)strlen( line ) + 3 ); } else { Log_dbg( LOG_DBG_PROTOCOL, "[S] %s", line ); return ( fprintf( f, "%s\r\n", line ) == (int)strlen( line ) + 2 ); } } Bool Prt_putEndOfTxt( FILE *f ) { Log_dbg( LOG_DBG_PROTOCOL, "[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 ) != (int)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; static Bool randSeeded = FALSE; if ( ! randSeeded ) { struct timeval tv; struct timezone tz; if ( gettimeofday( &tv, &tz ) == 0 ) srand( (unsigned int) tv.tv_usec ); randSeeded = TRUE; } getDomain( domain, from ); time( &t ); strftime( date, MAXCHAR, "%Y%m%d%H%M%S", gmtime( &t ) ); snprintf( msgId, MAXCHAR, "<%s.%X.%s@%s>", date, rand(), suffix, domain ); ASSERT( Prt_isValidMsgId( msgId ) ); } void Prt_genPathHdr( Str pathHdr, const char *from ) { getDomain( pathHdr, from ); Utl_catStr( pathHdr, "!not-for-mail" ); } Bool Prt_genFromHdr( Str fromHdr ) { Str name, domain; const char *nameval; struct passwd *pwd; /* First get the domain to use. If config empty, use FQDN */ Utl_cpyStr( domain, Cfg_fromDomain() ); if ( strlen( domain ) == 0 ) if ( ! getFQDN( domain ) ) Utl_catStr( domain, "unknown" ); /* Now get pwd for the username */ pwd = getpwuid( getuid() ); if ( pwd == NULL ) return FALSE; /* Now for their name - use env NAME if available */ nameval = getenv( "NAME" ); if ( nameval != NULL ) Utl_cpyStr( name, nameval ); else { char *p; /* Extract from GECOS field. Following the lead of the INN inews, ignore leading stuff like "23-" "stuff]-" or "stuff -" as well as trailing whitespace, or anything that comes after a comma or semicolon. */ nameval = pwd->pw_gecos; p = strchr( nameval, '-' ); if ( p != NULL && p > nameval && ( p[-1] == ']' || p[-1] == ' ' || isdigit( p[ -1 ] ) ) ) nameval = p; p = strrchr( nameval, ',' ); if ( p != NULL ) *p = '\0'; p = strchr( nameval, ';' ); if ( p != NULL ) *p = '\0'; Utl_cpyStr( name, nameval ); } /* OK, build From: contents */ Utl_cpyStr( fromHdr, pwd->pw_name ); Utl_catStr( fromHdr, "@" ); Utl_catStr( fromHdr, domain ); Utl_catStr( fromHdr, " (" ); Utl_catStr( fromHdr, name ); Utl_catStr( fromHdr, ")" ); return TRUE; }