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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23.2.8 - (hide annotations)
Sat Mar 8 01:37:15 2003 UTC (21 years, 1 month ago) by lefcha
Branch: release-0_8-patches
Changes since 1.23.2.7: +2 -1 lines
File MIME type: text/plain
Correct problem when server aborted the connection.

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.23.2.3 #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.23.2.3 extern jmp_buf acctloop;
19 lefcha 1.1
20 lefcha 1.20 static char *vbuf = NULL; /* Virtual buffer. */
21     static size_t vbufs = 0; /* Virtual buffer size. */
22    
23 lefcha 1.1
24     /*
25 lefcha 1.14 * Read one packet of data that the server sent.
26 lefcha 1.1 */
27 lefcha 1.20 void receive_response(int *sock, char *buf)
28 lefcha 1.1 {
29 lefcha 1.23.2.8 if (socket_read(sock, buf) == ERROR_NETWORK)
30     longjmp(acctloop, -1);
31 lefcha 1.1
32     #ifdef DEBUG
33 lefcha 1.14 printf("\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.23.2.3 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.23.2.3 * 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.23.2.3 bye_response(buf);
78 lefcha 1.9
79 lefcha 1.23.2.3 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.23.2.2 * 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.23.2.3 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     return analyze_response(buf);
129     }
130    
131    
132     /*
133     * Process the data that server sent due to IMAP NAMESPACE client request.
134     */
135 lefcha 1.21 int namespace_response(int *sock, unsigned int tag, namesp_t * nsp)
136 lefcha 1.18 {
137     char buf[RESPONSE_BUF];
138     char *c, *d;
139    
140 lefcha 1.20 reset_vbuf();
141 lefcha 1.21
142 lefcha 1.20 do {
143 lefcha 1.23.2.1 receive_response(sock, buf);
144 lefcha 1.23.2.3 bye_response(buf);
145 lefcha 1.20 check_vbuf(strlen(buf));
146 lefcha 1.21 strncat(vbuf, buf, vbufs - strlen(vbuf));
147 lefcha 1.20 } while (!strcasestr(buf, ultostr(tag, 16)));
148 lefcha 1.18
149 lefcha 1.20 if ((c = strcasestr(vbuf, "* NAMESPACE"))) {
150 lefcha 1.18 c += 12;
151     if (strncasecmp(c, "NIL", 3)) {
152     c = strchr(c, '"') + 1;
153     d = strchr(c, '"') + 1;
154    
155 lefcha 1.20 strncat(nsp->prefix, c, d - c - 1);
156     nsp->delim = *(strchr(d, '"') + 1);
157 lefcha 1.18 }
158     }
159 lefcha 1.20 #ifdef DEBUG
160     printf("debug: namespace: '%s' '%c'\n", nsp->prefix, nsp->delim);
161     #endif
162 lefcha 1.14 return analyze_response(buf);
163 lefcha 1.9 }
164    
165    
166     /*
167 lefcha 1.3 * Process the data that server sent due to IMAP STATUS client request.
168 lefcha 1.1 */
169 lefcha 1.20 int status_response(int *sock, unsigned int tag, char *mbox)
170 lefcha 1.1 {
171 lefcha 1.17 int r;
172 lefcha 1.14 char buf[RESPONSE_BUF];
173 lefcha 1.1 unsigned int exist, recent, unseen;
174 lefcha 1.9 char *c;
175 lefcha 1.1
176     exist = recent = unseen = 0;
177 lefcha 1.21
178 lefcha 1.20 reset_vbuf();
179 lefcha 1.1
180 lefcha 1.20 do {
181     receive_response(sock, buf);
182 lefcha 1.23.2.3 bye_response(buf);
183 lefcha 1.20 check_vbuf(strlen(buf));
184     strncat(vbuf, buf, vbufs - strlen(vbuf));
185     } while (!strcasestr(buf, ultostr(tag, 16)));
186 lefcha 1.13
187 lefcha 1.17 r = analyze_response(buf);
188    
189     if (r == RESPONSE_NO)
190     return -2;
191    
192 lefcha 1.20 if ((c = strcasestr(vbuf, "MESSAGES"))) {
193 lefcha 1.9 c += 9;
194     exist = strtoul(c, NULL, 10);
195     }
196 lefcha 1.20 if ((c = strcasestr(vbuf, "RECENT"))) {
197 lefcha 1.9 c += 7;
198     recent = strtoul(c, NULL, 10);
199     }
200 lefcha 1.20 if ((c = strcasestr(vbuf, "UNSEEN"))) {
201 lefcha 1.9 c += 7;
202     unseen = strtoul(c, NULL, 10);
203     }
204 lefcha 1.8 if (!exist) {
205 lefcha 1.19 info("No messages in mailbox \"%s\".\n", mbox);
206 lefcha 1.8 return -2;
207     }
208 lefcha 1.19 info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n", exist,
209 lefcha 1.18 plural(exist), recent, unseen, mbox);
210 lefcha 1.9
211 lefcha 1.17 return r;
212 lefcha 1.9 }
213    
214    
215     /*
216     * Process the data that server sent due to IMAP SELECT client request.
217     */
218 lefcha 1.20 int select_response(int *sock, unsigned int tag)
219 lefcha 1.9 {
220 lefcha 1.14 char buf[RESPONSE_BUF];
221 lefcha 1.9
222 lefcha 1.20 reset_vbuf();
223 lefcha 1.21
224 lefcha 1.20 do {
225     receive_response(sock, buf);
226 lefcha 1.23.2.3 bye_response(buf);
227 lefcha 1.20 check_vbuf(strlen(buf));
228     strncat(vbuf, buf, vbufs - strlen(vbuf));
229     } while (!strcasestr(buf, ultostr(tag, 16)));
230 lefcha 1.9
231 lefcha 1.20 if (strcasestr(vbuf, "[READ-ONLY]"))
232 lefcha 1.9 return RESPONSE_READONLY;
233 lefcha 1.1
234 lefcha 1.14 return analyze_response(buf);
235 lefcha 1.1 }
236    
237    
238     /*
239 lefcha 1.3 * Process the data that server sent due to IMAP SEARCH client request.
240 lefcha 1.1 */
241 lefcha 1.20 int search_response(int *sock, unsigned int tag, char **mesgs)
242 lefcha 1.1 {
243 lefcha 1.14 char buf[RESPONSE_BUF];
244 lefcha 1.13 char *c, *m;
245 lefcha 1.20 unsigned int blen;
246 lefcha 1.13
247 lefcha 1.20 reset_vbuf();
248 lefcha 1.21
249 lefcha 1.20 do {
250     receive_response(sock, buf);
251 lefcha 1.23.2.3 bye_response(buf);
252 lefcha 1.20 check_vbuf(strlen(buf));
253     strncat(vbuf, buf, vbufs - strlen(vbuf));
254     } while (!strcasestr(buf, ultostr(tag, 16)));
255 lefcha 1.1
256 lefcha 1.20 if ((c = strcasestr(vbuf, "* SEARCH "))) {
257     blen = strlen(vbuf);
258 lefcha 1.21
259     m = *mesgs = (char *)xmalloc(blen + 1);
260    
261 lefcha 1.20 c += 9;
262 lefcha 1.21
263 lefcha 1.23.2.2 while (*c && (isdigit((unsigned char)(*c)) || *c == ' '))
264 lefcha 1.20 *(m++) = *(c++);
265 lefcha 1.14
266 lefcha 1.20 *m = 0;
267     }
268 lefcha 1.14 return analyze_response(buf);
269 lefcha 1.1 }
270    
271    
272     /*
273 lefcha 1.3 * Process the data that server sent due to IMAP FETCH client request.
274 lefcha 1.1 */
275 lefcha 1.23.2.5 int fetch_response(int *sock, unsigned int tag, int reset, char *fetch)
276 lefcha 1.1 {
277 lefcha 1.14 char buf[RESPONSE_BUF];
278 lefcha 1.20 unsigned int i;
279     static unsigned int s;
280 lefcha 1.15 char *b;
281 lefcha 1.14
282 lefcha 1.20 if (reset) {
283     s = 0;
284     return 0;
285     }
286     i = 0;
287    
288 lefcha 1.23.2.5 reset_vbuf();
289 lefcha 1.20
290 lefcha 1.23.2.5 do {
291     receive_response(sock, buf);
292     bye_response(buf);
293     check_vbuf(strlen(buf));
294     strncat(vbuf, buf, vbufs - strlen(vbuf));
295     } while (strlen(vbuf) < RESPONSE_BUF &&
296     !strcasestr(buf, ultostr(tag, 16)));
297 lefcha 1.21
298 lefcha 1.23.2.5 b = vbuf;
299    
300 lefcha 1.23.2.6 if (!s) {
301     if ((b = strstr(b, "}\r\n"))) {
302     while (b - vbuf > 0)
303     if (*--b == '{')
304     break;
305     s = atoi(++b) - 2;
306     b = strchr(b, '}');
307     b += 3;
308     } else {
309 lefcha 1.23.2.7 return RESPONSE_NULLBODY; /* Null body. */
310 lefcha 1.23.2.6 }
311 lefcha 1.20 }
312     while (*b && s--)
313     fetch[i++] = *(b++);
314    
315     fetch[i] = 0;
316 lefcha 1.21
317 lefcha 1.20 return analyze_response(buf);
318     }
319    
320 lefcha 1.6
321 lefcha 1.20 /*
322     * Process the data that server sent due to IMAP FETCH RFC822.SIZE client
323     * request.
324     */
325     int fetchsize_response(int *sock, unsigned int *size, unsigned int tag)
326     {
327     char buf[RESPONSE_BUF];
328     char *c;
329 lefcha 1.21
330 lefcha 1.20 *size = 0;
331 lefcha 1.21
332 lefcha 1.20 reset_vbuf();
333 lefcha 1.21
334 lefcha 1.13 do {
335 lefcha 1.20 receive_response(sock, buf);
336 lefcha 1.23.2.3 bye_response(buf);
337 lefcha 1.20 check_vbuf(strlen(buf));
338     strncat(vbuf, buf, vbufs - strlen(vbuf));
339     } while (!strcasestr(buf, ultostr(tag, 16)));
340 lefcha 1.21
341 lefcha 1.20 if ((c = strcasestr(vbuf, "FETCH (RFC822.SIZE "))) {
342     c += 19;
343     *size = strtoul(c, NULL, 10);
344     }
345     return analyze_response(buf);
346     }
347 lefcha 1.13
348 lefcha 1.6
349 lefcha 1.20 /*
350     * Process the data that server sent due to IMAP APPEND client request.
351     */
352     int append_response(int *sock, unsigned int tag)
353     {
354     int r = RESPONSE_OK;
355     char buf[RESPONSE_BUF];
356 lefcha 1.21
357 lefcha 1.20 reset_vbuf();
358 lefcha 1.21
359 lefcha 1.20 do {
360     receive_response(sock, buf);
361 lefcha 1.23.2.3 bye_response(buf);
362 lefcha 1.21 check_vbuf(strlen(buf));
363 lefcha 1.20 strncat(vbuf, buf, vbufs - strlen(vbuf));
364 lefcha 1.14 } while (!strcasestr(buf, ultostr(tag, 16)));
365 lefcha 1.21
366 lefcha 1.20 if ((r = analyze_response(buf)) == RESPONSE_NO &&
367     strcasestr(vbuf, "[TRYCREATE]"))
368     return RESPONSE_TRYCREATE;
369 lefcha 1.6
370 lefcha 1.20 return r;
371 lefcha 1.1 }
372    
373    
374     /*
375 lefcha 1.3 * Process the data that server sent due to IMAP COPY client request.
376 lefcha 1.1 */
377 lefcha 1.20 int copy_response(int *sock, unsigned int tag)
378 lefcha 1.1 {
379 lefcha 1.19 int r = RESPONSE_OK;
380 lefcha 1.20 char buf[RESPONSE_BUF];
381 lefcha 1.21
382 lefcha 1.20 reset_vbuf();
383 lefcha 1.1
384 lefcha 1.20 do {
385     receive_response(sock, buf);
386 lefcha 1.23.2.3 bye_response(buf);
387 lefcha 1.21 check_vbuf(strlen(buf));
388 lefcha 1.20 strncat(vbuf, buf, vbufs - strlen(vbuf));
389     } while (!strcasestr(buf, ultostr(tag, 16)));
390 lefcha 1.1
391 lefcha 1.19 if ((r = analyze_response(buf)) == RESPONSE_NO &&
392 lefcha 1.20 strcasestr(vbuf, "[TRYCREATE]"))
393 lefcha 1.9 return RESPONSE_TRYCREATE;
394 lefcha 1.1
395 lefcha 1.19 return r;
396 lefcha 1.1 }
397    
398    
399     /*
400 lefcha 1.3 * Check if response of server to client's request was succesfully
401 lefcha 1.1 * delivered or there was some kind of error.
402     */
403 lefcha 1.14 int analyze_response(char *buf)
404 lefcha 1.1 {
405 lefcha 1.9 int r = RESPONSE_OK;
406 lefcha 1.1 regex_t creg;
407     regmatch_t match[3];
408 lefcha 1.9 const char *reg = "[[:xdigit:]]{6,6} ((OK|NO|BAD)[[:print:]]*)\r\n";
409 lefcha 1.14 char result[RESULT_BUF];
410 lefcha 1.1
411 lefcha 1.4 result[0] = 0;
412    
413 lefcha 1.9 regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
414 lefcha 1.6
415 lefcha 1.14 if (!regexec(&creg, buf, 3, match, 0)) {
416     strncat(result, buf + match[1].rm_so,
417     min(match[1].rm_eo - match[1].rm_so, RESULT_BUF - 1));
418 lefcha 1.1
419 lefcha 1.22 if (!strncasecmp(buf + match[2].rm_so, "NO", 2))
420 lefcha 1.9 r = RESPONSE_NO;
421 lefcha 1.22 else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))
422 lefcha 1.9 r = RESPONSE_BAD;
423 lefcha 1.6
424 lefcha 1.1 verbose("Server response: %s\n", result);
425 lefcha 1.20 } else
426     r = RESPONSE_NONE;
427 lefcha 1.21
428 lefcha 1.6 regfree(&creg);
429 lefcha 1.1
430     return r;
431 lefcha 1.20 }
432    
433    
434     /*
435     * Initialize virtual buffer.
436     */
437     void init_vbuf(void)
438     {
439 lefcha 1.23.2.2 vbuf = xmalloc(VIRTUAL_BUF);
440 lefcha 1.20 *vbuf = 0;
441 lefcha 1.23.2.2 vbufs = VIRTUAL_BUF;
442 lefcha 1.20 }
443    
444    
445     /*
446     * Reset virtual buffer.
447     */
448     void reset_vbuf(void)
449     {
450     *vbuf = 0;
451     }
452    
453    
454     /*
455     * Check if virtual buffer is full and make it bigger.
456     */
457     void check_vbuf(size_t n)
458     {
459     if (n + strlen(vbuf) >= vbufs) {
460 lefcha 1.23.2.2 vbufs += VIRTUAL_BUF;
461 lefcha 1.20 vbuf = xrealloc(vbuf, vbufs);
462     }
463 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26