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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17.2.4 - (hide annotations)
Mon Jun 17 12:01:00 2002 UTC (21 years, 10 months ago) by lefcha
Branch: release-0_7-patches
Changes since 1.17.2.3: +100 -51 lines
File MIME type: text/plain
Bug fix related to communication with some mail servers.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26