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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.41 - (hide annotations)
Sun Aug 3 16:01:53 2003 UTC (20 years, 8 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_9
Branch point for: release-0_9-patches
Changes since 1.40: +1 -0 lines
File MIME type: text/plain
Added missing stdlib.h header.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26