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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.40 - (hide annotations)
Thu Jul 31 15:53:19 2003 UTC (20 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.39: +7 -9 lines
File MIME type: text/plain
Broke up program files and created some new header files.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26