Mercurial > noffle
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 } |