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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.30 - (hide annotations)
Thu Dec 5 07:33:50 2002 UTC (21 years, 3 months ago) by lefcha
Branch: MAIN
Changes since 1.29: +1 -1 lines
File MIME type: text/plain
Added response when the message body is null.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26