comparison 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
comparison
equal deleted inserted replaced
42:2467ff423c15 43:2842f50feb55
1 /*
2 protocol.c
3
4 $Id: protocol.c 49 2000-05-05 21:45:56Z uh1763 $
5 */
6
7 #if HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <netdb.h>
14 #include <sys/types.h>
15 #include <sys/utsname.h>
16 #include "common.h"
17 #include "dynamicstring.h"
18 #include "log.h"
19 #include "over.h"
20 #include "util.h"
21
22 Bool
23 Prt_getLn( Str line, FILE *f )
24 {
25 size_t len;
26
27 /*
28 We also accept lines ending with "\n" instead of "\r\n", some
29 clients wrongly send such lines.
30 */
31 if ( ! fgets( line, MAXCHAR, f ) )
32 {
33 Log_dbg( "Prt_getLine failed" );
34 return FALSE;
35 }
36 len = strlen( line );
37 if ( line[ len - 1 ] == '\n' )
38 {
39 line[ len - 1 ] = '\0';
40 if ( line[ len - 2 ] == '\r' )
41 line[ len - 2 ] = '\0';
42 }
43 Log_dbg( "[R] %s", line );
44 return TRUE;
45 }
46
47 Bool
48 Prt_getTxtLn( Str line, Bool *err, FILE *f )
49 {
50 Str buf;
51
52 if ( ! Prt_getLn( buf, f ) )
53 {
54 Log_err( "Cannot get text line" );
55 *err = TRUE;
56 return FALSE;
57 }
58 *err = FALSE;
59 if ( buf[ 0 ] == '.' )
60 {
61 if ( buf[ 1 ] == 0 )
62 return FALSE;
63 else
64 strcpy( line, buf + 1 );
65 }
66 else
67 strcpy( line, buf );
68 return TRUE;
69 }
70
71 Bool
72 Prt_putTxtLn( const char* line, FILE *f )
73 {
74 if ( line[ 0 ] == '.' )
75 {
76 Log_dbg( "[S] .%s", line );
77 return ( fprintf( f, ".%s\r\n", line ) == strlen( line ) + 3 );
78 }
79 else
80 {
81 Log_dbg( "[S] %s", line );
82 return ( fprintf( f, "%s\r\n", line ) == strlen( line ) + 2 );
83 }
84 }
85
86 Bool
87 Prt_putEndOfTxt( FILE *f )
88 {
89 Log_dbg( "[S] ." );
90 return ( fprintf( f, ".\r\n" ) == 3 );
91 }
92
93 /*
94 Write text buffer of lines each ending with '\n'.
95 Replace '\n' by "\r\n".
96 */
97 Bool
98 Prt_putTxtBuf( const char *buf, FILE *f )
99 {
100 Str line;
101 const char *pBuf;
102 char *pLn;
103
104 pBuf = buf;
105 pLn = line;
106 while ( *pBuf != '\0' )
107 {
108 if ( *pBuf == '\n' )
109 {
110 *pLn = '\0';
111 if ( ! Prt_putTxtLn( line, f ) )
112 return FALSE;
113 pLn = line;
114 ++pBuf;
115 }
116 else if ( pLn - line >= MAXCHAR - 1 )
117 {
118 /* Put it out raw to prevent String overflow */
119 Log_err( "Writing VERY long line" );
120 *pLn = '\0';
121 if ( fprintf( f, "%s", line ) != strlen( line ) )
122 return FALSE;
123 pLn = line;
124 }
125 else
126 *(pLn++) = *(pBuf++);
127 }
128 return TRUE;
129 }
130
131 Bool
132 Prt_getField( Str resultField, Str resultValue, const char* line )
133 {
134 char *dst;
135 const char *p;
136 Str lineLower, t;
137
138 Utl_cpyStr( lineLower, line );
139 Utl_toLower( lineLower );
140 p = Utl_stripWhiteSpace( lineLower );
141 dst = resultField;
142 while ( ! isspace( *p ) && *p != ':' && *p != '\0' )
143 *(dst++) = *(p++);
144 *dst = '\0';
145 while ( isspace( *p ) )
146 ++p;
147 if ( *p == ':' )
148 {
149 ++p;
150 strcpy( t, line + ( p - lineLower ) );
151 p = Utl_stripWhiteSpace( t );
152 strcpy( resultValue, p );
153 return TRUE;
154 }
155 return FALSE;
156 }
157
158 Bool
159 Prt_searchHeader( const char *artTxt, const char *which, Str result )
160 {
161 const char *src, *p;
162 char *dst;
163 Str line, whichLower, field;
164 int len;
165
166 Utl_cpyStr( whichLower, which );
167 Utl_toLower( whichLower );
168 src = artTxt;
169 while ( TRUE )
170 {
171 dst = line;
172 len = 0;
173 while ( *src != '\n' && len < MAXCHAR )
174 {
175 if ( *src == '\0' )
176 return FALSE;
177 *(dst++) = *(src++);
178 ++len;
179 }
180 if ( *src == '\n' )
181 ++src;
182 *dst = '\0';
183 p = Utl_stripWhiteSpace( line );
184 if ( *p == '\0' )
185 break;
186 if ( Prt_getField( field, result, line )
187 && strcmp( field, whichLower ) == 0 )
188 return TRUE;
189 }
190 return FALSE;
191 }
192
193 static Bool
194 getFQDN( Str result )
195 {
196 struct hostent *myHostEnt;
197 struct utsname myName;
198
199 if ( uname( &myName ) >= 0
200 && ( myHostEnt = gethostbyname( myName.nodename ) ) )
201 {
202 Utl_cpyStr( result, myHostEnt->h_name );
203 return TRUE;
204 }
205 return FALSE;
206 }
207
208 static void
209 getDomain( Str domain, const char *from )
210 {
211 const char *addTopLevel, *p1, *p2, *p, *domainStart;
212 Str myDomain;
213
214 if ( getFQDN( myDomain ) )
215 {
216 p = strstr( myDomain, "." );
217 if ( p != NULL )
218 domainStart = p + 1;
219 else
220 domainStart = myDomain;
221 }
222 else /* Take domain of From field */
223 {
224 myDomain[ 0 ] = '\0';
225 p1 = strstr( from, "@" );
226 if ( p1 != NULL )
227 {
228 p2 = strstr( p1, ">" );
229 if ( p2 != NULL )
230 Utl_cpyStrN( myDomain, p1 + 1, p2 - p1 - 1 );
231 }
232 if ( myDomain[ 0 ] == '\0' )
233 Utl_cpyStr( myDomain, "unknown" );
234 domainStart = myDomain;
235 }
236 /*
237 If domain contains no dot (and is probably invalid anyway),
238 we add ".local", because some servers insist on domainnames with dot
239 in message ID.
240 */
241 addTopLevel = strstr( domainStart, "." ) == NULL ? ".local" : "";
242 snprintf( domain, MAXCHAR, "%s%s", myDomain, addTopLevel );
243 }
244
245 /* See RFC 850, section 2.1.7 */
246 Bool
247 Prt_isValidMsgId( const char *msgId )
248 {
249 Str head, domain;
250 int len, headLen;
251 const char *p;
252
253 len = strlen( msgId );
254 p = strstr( msgId, "@" );
255 if ( msgId[ 0 ] != '<' || msgId[ len - 1 ] != '>' || p == NULL )
256 return FALSE;
257 strcpy( domain, p + 1 );
258 domain[ strlen( domain ) - 1 ] = '\0';
259 headLen = p - msgId - 1;
260 Utl_cpyStrN( head, msgId + 1, headLen );
261 head[ headLen ] = '\0';
262 /*
263 To do: check for special characters in head and domain (non-printable
264 or '@', '<', '>'). Maybe compare domain with a config option
265 and replace it by the config option, if not equal.
266 */
267 if ( strstr( domain, "." ) == NULL )
268 return FALSE;
269 return TRUE;
270 }
271
272 void
273 Prt_genMsgId( Str msgId, const char *from, const char *suffix )
274 {
275 Str domain, date;
276 time_t t;
277
278 getDomain( domain, from );
279 time( &t );
280 strftime( date, MAXCHAR, "%Y%m%d%H%M%S", gmtime( &t ) );
281 srand( time( NULL ) );
282 snprintf( msgId, MAXCHAR, "<%s.%X.%s@%s>", date, rand(), suffix, domain );
283 ASSERT( Prt_isValidMsgId( msgId ) );
284 }