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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.25 - (show annotations)
Mon Aug 26 20:35:17 2002 UTC (21 years, 7 months ago) by lefcha
Branch: MAIN
Changes since 1.24: +25 -6 lines
File MIME type: text/plain
Added logout_response() and some minor changes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26