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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17.2.4 - (show annotations)
Mon Jun 17 12:01:00 2002 UTC (21 years, 9 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 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <errno.h>
6 #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 extern unsigned int capabilities;
17
18 char *vbuf = NULL;
19 size_t vbufs = 0;
20
21 /*
22 * Read one packet of data that the server sent.
23 */
24 void receive_response(char *buf)
25 {
26 socket_read(buf);
27
28 #ifdef DEBUG
29 printf("\n%s\n", buf);
30 #endif
31
32 }
33
34
35 /*
36 * Get server response to client's request.
37 */
38 int server_response(unsigned int tag)
39 {
40 char buf[RESPONSE_BUF];
41
42 reset_vbuf();
43
44 do {
45 receive_response(buf);
46 check_vbuf(strlen(buf));
47 strncat(vbuf, buf, vbufs - strlen(vbuf));
48 } while (tag && !strcasestr(buf, ultostr(tag, 16)));
49
50 return analyze_response(buf);
51 }
52
53
54 /*
55 * Process the greeting that server sends during connection.
56 */
57 int greeting_response(void)
58 {
59 char buf[RESPONSE_BUF];
60
61 receive_response(buf);
62
63 if (strcasestr(buf, "BYE"))
64 return RESPONSE_BYE;
65 else if (strcasestr(buf, "PREAUTH"))
66 return RESPONSE_PREAUTH;
67
68 return RESPONSE_OK;
69 }
70
71
72 /*
73 * Process the data that server sent due to IMAP CAPABILITY client request.
74 */
75 int capability_response(unsigned int tag)
76 {
77 char buf[RESPONSE_BUF];
78
79 reset_vbuf();
80
81 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 error("imapfilter: server does not support IMAP4rev1 protocol\n");
89 return -2;
90 }
91 if (strcasestr(vbuf, "NAMESPACE"))
92 capabilities |= CAPABILITY_NAMESPACE;
93
94 return analyze_response(vbuf);
95 }
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
106 reset_vbuf();
107
108 do {
109 receive_response(buf);
110 check_vbuf(strlen(buf));
111 strncat(vbuf, buf, vbufs - strlen(vbuf));
112 } while (!strcasestr(buf, ultostr(tag, 16)));
113
114 if ((c = strcasestr(vbuf, "* NAMESPACE"))) {
115 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 return analyze_response(buf);
125 }
126
127
128 /*
129 * Process the data that server sent due to IMAP STATUS client request.
130 */
131 int status_response(unsigned int tag, char *mbox)
132 {
133 int r;
134 char buf[RESPONSE_BUF];
135 unsigned int exist, recent, unseen;
136 char *c;
137
138 exist = recent = unseen = 0;
139
140 reset_vbuf();
141
142 do {
143 receive_response(buf);
144 check_vbuf(strlen(buf));
145 strncat(vbuf, buf, vbufs - strlen(vbuf));
146 } while (!strcasestr(buf, ultostr(tag, 16)));
147
148 r = analyze_response(buf);
149
150 if (r == RESPONSE_NO)
151 return -2;
152
153 if ((c = strcasestr(vbuf, "MESSAGES"))) {
154 c += 9;
155 exist = strtoul(c, NULL, 10);
156 }
157 if ((c = strcasestr(vbuf, "RECENT"))) {
158 c += 7;
159 recent = strtoul(c, NULL, 10);
160 }
161 if ((c = strcasestr(vbuf, "UNSEEN"))) {
162 c += 7;
163 unseen = strtoul(c, NULL, 10);
164 }
165 if (!exist) {
166 info("No messages in mailbox \"%s\".\n", mbox);
167 return -2;
168 }
169 info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n", exist,
170 plural(exist), recent, unseen, mbox);
171
172 return r;
173 }
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 char buf[RESPONSE_BUF];
182
183 reset_vbuf();
184
185 do {
186 receive_response(buf);
187 check_vbuf(strlen(buf));
188 strncat(vbuf, buf, vbufs - strlen(vbuf));
189 } while (!strcasestr(buf, ultostr(tag, 16)));
190
191 if (strcasestr(vbuf, "[READ-ONLY]"))
192 return RESPONSE_READONLY;
193
194 return analyze_response(buf);
195 }
196
197
198 /*
199 * Process the data that server sent due to IMAP SEARCH client request.
200 */
201 int search_response(unsigned int tag, char **mesgs)
202 {
203 char buf[RESPONSE_BUF];
204 char *c, *m;
205 unsigned int blen;
206
207 reset_vbuf();
208
209 do {
210 receive_response(buf);
211 check_vbuf(strlen(buf));
212 strncat(vbuf, buf, vbufs - strlen(vbuf));
213 } while (!strcasestr(buf, ultostr(tag, 16)));
214
215 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 return analyze_response(buf);
229 }
230
231
232 /*
233 * Process the data that server sent due to IMAP FETCH client request.
234 */
235 int fetch_response(unsigned int tag)
236 {
237 char buf[RESPONSE_BUF];
238 char hdrs[HEADERS_BUF];
239 int f;
240 unsigned int sa, sb, i, n;
241 char s[8];
242 char *b;
243
244 hdrs[0] = 0;
245 sa = sb = i = f = 0;
246 s[0] = 0;
247
248 do {
249 receive_response(buf);
250
251 b = buf;
252
253 while (f || (b = strchr(b, '{'))) {
254 /* Headers are continued from previous packet. */
255 if (f) {
256 f = 0;
257 for (; i < HEADERS_BUF - 1 && i < sa - 2; i++) {
258 /* Continued in next packet. */
259 if (!*b) {
260 f = 1;
261 break;
262 }
263 hdrs[i] = *(b++);
264 }
265 } else {
266 /* Left bracket is last byte of buffer. */
267 if (b == buf + RESPONSE_BUF - 2) {
268 receive_response(buf);
269 b = buf;
270 } else
271 b++;
272
273 sa = atoi(b);
274
275 /* Headers length may be continued in next packet. */
276 if (!(b = strchr(b, '}'))) {
277 receive_response(buf);
278 if (buf != (b = strchr(buf, '}'))) {
279 sb = atoi(buf);
280 strncat(s, ultostr(sa, 10), 7);
281 strncat(s, ultostr(sb, 10), 7);
282 sa = atoi(s);
283 s[0] = 0;
284 }
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
318 return analyze_response(buf);
319 }
320
321
322 /*
323 * Process the data that server sent due to IMAP COPY client request.
324 */
325 int copy_response(unsigned int tag)
326 {
327 int r = RESPONSE_OK;
328 char buf[RESPONSE_BUF];
329
330 reset_vbuf();
331
332 do {
333 receive_response(buf);
334 check_vbuf(strlen(buf));
335 strncat(vbuf, buf, vbufs - strlen(vbuf));
336 } while (!strcasestr(buf, ultostr(tag, 16)));
337
338 if ((r = analyze_response(buf)) == RESPONSE_NO
339 && strcasestr(vbuf, "[TRYCREATE]"))
340 return RESPONSE_TRYCREATE;
341
342 return r;
343 }
344
345
346 /*
347 * Check if response of server to client's request was succesfully
348 * delivered or there was some kind of error.
349 */
350 int analyze_response(char *buf)
351 {
352 int r = RESPONSE_OK;
353 regex_t creg;
354 regmatch_t match[3];
355 const char *reg = "[[:xdigit:]]{6,6} ((OK|NO|BAD)[[:print:]]*)\r\n";
356 char result[RESULT_BUF];
357
358 result[0] = 0;
359
360 regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
361
362 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
366 if (!strncasecmp(buf + match[2].rm_so, "NO", 2))
367 r = RESPONSE_NO;
368 else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))
369 r = RESPONSE_BAD;
370
371 verbose("Server response: %s\n", result);
372 }
373 regfree(&creg);
374
375 return r;
376 }
377
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