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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.31 - (hide annotations)
Fri Feb 21 18:43:01 2003 UTC (21 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.30: +39 -2 lines
File MIME type: text/plain
Added funtion get authentication mechanisms available.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26