/[imapfilter]/imapfilter/response.c
ViewVC logotype

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23.2.7 - (show annotations)
Sun Feb 2 17:43:21 2003 UTC (21 years, 1 month ago) by lefcha
Branch: release-0_8-patches
Changes since 1.23.2.6: +1 -1 lines
File MIME type: text/plain
Added response when the message body is null.

1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <sys/time.h>
8 #include <sys/types.h>
9 #include <regex.h>
10 #include <setjmp.h>
11
12 #include "config.h"
13 #include "imapfilter.h"
14
15
16 extern int sockpri;
17 extern unsigned int capabilities;
18 extern jmp_buf acctloop;
19
20 static char *vbuf = NULL; /* Virtual buffer. */
21 static size_t vbufs = 0; /* Virtual buffer size. */
22
23
24 /*
25 * Read one packet of data that the server sent.
26 */
27 void receive_response(int *sock, char *buf)
28 {
29 socket_read(sock, buf);
30
31 #ifdef DEBUG
32 printf("\n%s\n", buf);
33 #endif
34
35 }
36
37
38 /*
39 * Get server response to client's request.
40 */
41 int server_response(int *sock, unsigned int tag)
42 {
43 char buf[RESPONSE_BUF];
44
45 reset_vbuf();
46
47 do {
48 receive_response(sock, buf);
49 bye_response(buf);
50 check_vbuf(strlen(buf));
51 strncat(vbuf, buf, vbufs - strlen(vbuf));
52 } while (tag && !strcasestr(buf, ultostr(tag, 16)));
53
54 return analyze_response(buf);
55 }
56
57
58 /*
59 * Check if server sent a BYE response (connection is closed immediately).
60 */
61 void bye_response(char *buf)
62 {
63 if (strcasestr(buf, "* BYE"))
64 longjmp(acctloop, -1);
65 }
66
67
68 /*
69 * Process the greeting that server sends during connection.
70 */
71 int greeting_response(int *sock)
72 {
73 char buf[RESPONSE_BUF];
74
75 receive_response(sock, buf);
76 bye_response(buf);
77
78 if (strcasestr(buf, "* PREAUTH"))
79 return RESPONSE_PREAUTH;
80
81 return RESPONSE_OK;
82 }
83
84
85 /*
86 * Process the data that server sent due to IMAP LOGOUT client request.
87 */
88 int logout_response(int *sock, unsigned int tag)
89 {
90 char buf[RESPONSE_BUF];
91
92 reset_vbuf();
93
94 do {
95 receive_response(sock, buf);
96 check_vbuf(strlen(buf));
97 strncat(vbuf, buf, vbufs - strlen(vbuf));
98 } while (!strcasestr(buf, ultostr(tag, 16)));
99
100 return analyze_response(buf);
101 }
102
103
104 /*
105 * Process the data that server sent due to IMAP CAPABILITY client request.
106 */
107 int capability_response(int *sock, unsigned int tag)
108 {
109 char buf[RESPONSE_BUF];
110
111 reset_vbuf();
112
113 do {
114 receive_response(sock, buf);
115 bye_response(buf);
116 check_vbuf(strlen(buf));
117 strncat(vbuf, buf, vbufs - strlen(vbuf));
118 } while (!strcasestr(buf, ultostr(tag, 16)));
119
120 if (!strcasestr(vbuf, "IMAP4rev1")) {
121 error("imapfilter: server does not support IMAP4rev1 protocol\n");
122 return -2;
123 }
124 if (strcasestr(vbuf, "NAMESPACE"))
125 capabilities |= CAPABILITY_NAMESPACE;
126
127 return analyze_response(buf);
128 }
129
130
131 /*
132 * Process the data that server sent due to IMAP NAMESPACE client request.
133 */
134 int namespace_response(int *sock, unsigned int tag, namesp_t * nsp)
135 {
136 char buf[RESPONSE_BUF];
137 char *c, *d;
138
139 reset_vbuf();
140
141 do {
142 receive_response(sock, buf);
143 bye_response(buf);
144 check_vbuf(strlen(buf));
145 strncat(vbuf, buf, vbufs - strlen(vbuf));
146 } while (!strcasestr(buf, ultostr(tag, 16)));
147
148 if ((c = strcasestr(vbuf, "* NAMESPACE"))) {
149 c += 12;
150 if (strncasecmp(c, "NIL", 3)) {
151 c = strchr(c, '"') + 1;
152 d = strchr(c, '"') + 1;
153
154 strncat(nsp->prefix, c, d - c - 1);
155 nsp->delim = *(strchr(d, '"') + 1);
156 }
157 }
158 #ifdef DEBUG
159 printf("debug: namespace: '%s' '%c'\n", nsp->prefix, nsp->delim);
160 #endif
161 return analyze_response(buf);
162 }
163
164
165 /*
166 * Process the data that server sent due to IMAP STATUS client request.
167 */
168 int status_response(int *sock, unsigned int tag, char *mbox)
169 {
170 int r;
171 char buf[RESPONSE_BUF];
172 unsigned int exist, recent, unseen;
173 char *c;
174
175 exist = recent = unseen = 0;
176
177 reset_vbuf();
178
179 do {
180 receive_response(sock, buf);
181 bye_response(buf);
182 check_vbuf(strlen(buf));
183 strncat(vbuf, buf, vbufs - strlen(vbuf));
184 } while (!strcasestr(buf, ultostr(tag, 16)));
185
186 r = analyze_response(buf);
187
188 if (r == RESPONSE_NO)
189 return -2;
190
191 if ((c = strcasestr(vbuf, "MESSAGES"))) {
192 c += 9;
193 exist = strtoul(c, NULL, 10);
194 }
195 if ((c = strcasestr(vbuf, "RECENT"))) {
196 c += 7;
197 recent = strtoul(c, NULL, 10);
198 }
199 if ((c = strcasestr(vbuf, "UNSEEN"))) {
200 c += 7;
201 unseen = strtoul(c, NULL, 10);
202 }
203 if (!exist) {
204 info("No messages in mailbox \"%s\".\n", mbox);
205 return -2;
206 }
207 info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n", exist,
208 plural(exist), recent, unseen, mbox);
209
210 return r;
211 }
212
213
214 /*
215 * Process the data that server sent due to IMAP SELECT client request.
216 */
217 int select_response(int *sock, unsigned int tag)
218 {
219 char buf[RESPONSE_BUF];
220
221 reset_vbuf();
222
223 do {
224 receive_response(sock, buf);
225 bye_response(buf);
226 check_vbuf(strlen(buf));
227 strncat(vbuf, buf, vbufs - strlen(vbuf));
228 } while (!strcasestr(buf, ultostr(tag, 16)));
229
230 if (strcasestr(vbuf, "[READ-ONLY]"))
231 return RESPONSE_READONLY;
232
233 return analyze_response(buf);
234 }
235
236
237 /*
238 * Process the data that server sent due to IMAP SEARCH client request.
239 */
240 int search_response(int *sock, unsigned int tag, char **mesgs)
241 {
242 char buf[RESPONSE_BUF];
243 char *c, *m;
244 unsigned int blen;
245
246 reset_vbuf();
247
248 do {
249 receive_response(sock, buf);
250 bye_response(buf);
251 check_vbuf(strlen(buf));
252 strncat(vbuf, buf, vbufs - strlen(vbuf));
253 } while (!strcasestr(buf, ultostr(tag, 16)));
254
255 if ((c = strcasestr(vbuf, "* SEARCH "))) {
256 blen = strlen(vbuf);
257
258 m = *mesgs = (char *)xmalloc(blen + 1);
259
260 c += 9;
261
262 while (*c && (isdigit((unsigned char)(*c)) || *c == ' '))
263 *(m++) = *(c++);
264
265 *m = 0;
266 }
267 return analyze_response(buf);
268 }
269
270
271 /*
272 * Process the data that server sent due to IMAP FETCH client request.
273 */
274 int fetch_response(int *sock, unsigned int tag, int reset, char *fetch)
275 {
276 char buf[RESPONSE_BUF];
277 unsigned int i;
278 static unsigned int s;
279 char *b;
280
281 if (reset) {
282 s = 0;
283 return 0;
284 }
285 i = 0;
286
287 reset_vbuf();
288
289 do {
290 receive_response(sock, buf);
291 bye_response(buf);
292 check_vbuf(strlen(buf));
293 strncat(vbuf, buf, vbufs - strlen(vbuf));
294 } while (strlen(vbuf) < RESPONSE_BUF &&
295 !strcasestr(buf, ultostr(tag, 16)));
296
297 b = vbuf;
298
299 if (!s) {
300 if ((b = strstr(b, "}\r\n"))) {
301 while (b - vbuf > 0)
302 if (*--b == '{')
303 break;
304 s = atoi(++b) - 2;
305 b = strchr(b, '}');
306 b += 3;
307 } else {
308 return RESPONSE_NULLBODY; /* Null body. */
309 }
310 }
311 while (*b && s--)
312 fetch[i++] = *(b++);
313
314 fetch[i] = 0;
315
316 return analyze_response(buf);
317 }
318
319
320 /*
321 * Process the data that server sent due to IMAP FETCH RFC822.SIZE client
322 * request.
323 */
324 int fetchsize_response(int *sock, unsigned int *size, unsigned int tag)
325 {
326 char buf[RESPONSE_BUF];
327 char *c;
328
329 *size = 0;
330
331 reset_vbuf();
332
333 do {
334 receive_response(sock, buf);
335 bye_response(buf);
336 check_vbuf(strlen(buf));
337 strncat(vbuf, buf, vbufs - strlen(vbuf));
338 } while (!strcasestr(buf, ultostr(tag, 16)));
339
340 if ((c = strcasestr(vbuf, "FETCH (RFC822.SIZE "))) {
341 c += 19;
342 *size = strtoul(c, NULL, 10);
343 }
344 return analyze_response(buf);
345 }
346
347
348 /*
349 * Process the data that server sent due to IMAP APPEND client request.
350 */
351 int append_response(int *sock, unsigned int tag)
352 {
353 int r = RESPONSE_OK;
354 char buf[RESPONSE_BUF];
355
356 reset_vbuf();
357
358 do {
359 receive_response(sock, buf);
360 bye_response(buf);
361 check_vbuf(strlen(buf));
362 strncat(vbuf, buf, vbufs - strlen(vbuf));
363 } while (!strcasestr(buf, ultostr(tag, 16)));
364
365 if ((r = analyze_response(buf)) == RESPONSE_NO &&
366 strcasestr(vbuf, "[TRYCREATE]"))
367 return RESPONSE_TRYCREATE;
368
369 return r;
370 }
371
372
373 /*
374 * Process the data that server sent due to IMAP COPY client request.
375 */
376 int copy_response(int *sock, unsigned int tag)
377 {
378 int r = RESPONSE_OK;
379 char buf[RESPONSE_BUF];
380
381 reset_vbuf();
382
383 do {
384 receive_response(sock, buf);
385 bye_response(buf);
386 check_vbuf(strlen(buf));
387 strncat(vbuf, buf, vbufs - strlen(vbuf));
388 } while (!strcasestr(buf, ultostr(tag, 16)));
389
390 if ((r = analyze_response(buf)) == RESPONSE_NO &&
391 strcasestr(vbuf, "[TRYCREATE]"))
392 return RESPONSE_TRYCREATE;
393
394 return r;
395 }
396
397
398 /*
399 * Check if response of server to client's request was succesfully
400 * delivered or there was some kind of error.
401 */
402 int analyze_response(char *buf)
403 {
404 int r = RESPONSE_OK;
405 regex_t creg;
406 regmatch_t match[3];
407 const char *reg = "[[:xdigit:]]{6,6} ((OK|NO|BAD)[[:print:]]*)\r\n";
408 char result[RESULT_BUF];
409
410 result[0] = 0;
411
412 regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
413
414 if (!regexec(&creg, buf, 3, match, 0)) {
415 strncat(result, buf + match[1].rm_so,
416 min(match[1].rm_eo - match[1].rm_so, RESULT_BUF - 1));
417
418 if (!strncasecmp(buf + match[2].rm_so, "NO", 2))
419 r = RESPONSE_NO;
420 else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))
421 r = RESPONSE_BAD;
422
423 verbose("Server response: %s\n", result);
424 } else
425 r = RESPONSE_NONE;
426
427 regfree(&creg);
428
429 return r;
430 }
431
432
433 /*
434 * Initialize virtual buffer.
435 */
436 void init_vbuf(void)
437 {
438 vbuf = xmalloc(VIRTUAL_BUF);
439 *vbuf = 0;
440 vbufs = VIRTUAL_BUF;
441 }
442
443
444 /*
445 * Reset virtual buffer.
446 */
447 void reset_vbuf(void)
448 {
449 *vbuf = 0;
450 }
451
452
453 /*
454 * Check if virtual buffer is full and make it bigger.
455 */
456 void check_vbuf(size_t n)
457 {
458 if (n + strlen(vbuf) >= vbufs) {
459 vbufs += VIRTUAL_BUF;
460 vbuf = xrealloc(vbuf, vbufs);
461 }
462 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26