comparison protocol.c @ 0:04124a4423d4 noffle

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