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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.42 - (hide annotations)
Fri Aug 8 00:18:45 2003 UTC (20 years, 7 months ago) by lefcha
Branch: MAIN
Changes since 1.41: +1 -0 lines
File MIME type: text/plain
Corrected header includes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26