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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (show annotations)
Wed Jul 31 10:16:23 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.23: +1 -1 lines
File MIME type: text/plain
Namespace bug fix.

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 CAPABILITY client request.
75 */
76 int capability_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 if (!strcasestr(vbuf, "IMAP4rev1")) {
89 error("imapfilter: server does not support IMAP4rev1 protocol\n");
90 return -2;
91 }
92 if (strcasestr(vbuf, "NAMESPACE"))
93 capabilities |= CAPABILITY_NAMESPACE;
94
95 return analyze_response(buf);
96 }
97
98
99 /*
100 * Process the data that server sent due to IMAP NAMESPACE client request.
101 */
102 int namespace_response(int *sock, unsigned int tag, namesp_t * nsp)
103 {
104 char buf[RESPONSE_BUF];
105 char *c, *d;
106
107 reset_vbuf();
108
109 do {
110 receive_response(sock, buf);
111 check_vbuf(strlen(buf));
112 strncat(vbuf, buf, vbufs - strlen(vbuf));
113 } while (!strcasestr(buf, ultostr(tag, 16)));
114
115 if ((c = strcasestr(vbuf, "* NAMESPACE"))) {
116 c += 12;
117 if (strncasecmp(c, "NIL", 3)) {
118 c = strchr(c, '"') + 1;
119 d = strchr(c, '"') + 1;
120
121 strncat(nsp->prefix, c, d - c - 1);
122 nsp->delim = *(strchr(d, '"') + 1);
123 }
124 }
125 #ifdef DEBUG
126 printf("debug: namespace: '%s' '%c'\n", nsp->prefix, nsp->delim);
127 #endif
128 return analyze_response(buf);
129 }
130
131
132 /*
133 * Process the data that server sent due to IMAP STATUS client request.
134 */
135 int status_response(int *sock, unsigned int tag, char *mbox)
136 {
137 int r;
138 char buf[RESPONSE_BUF];
139 unsigned int exist, recent, unseen;
140 char *c;
141
142 exist = recent = unseen = 0;
143
144 reset_vbuf();
145
146 do {
147 receive_response(sock, buf);
148 check_vbuf(strlen(buf));
149 strncat(vbuf, buf, vbufs - strlen(vbuf));
150 } while (!strcasestr(buf, ultostr(tag, 16)));
151
152 r = analyze_response(buf);
153
154 if (r == RESPONSE_NO)
155 return -2;
156
157 if ((c = strcasestr(vbuf, "MESSAGES"))) {
158 c += 9;
159 exist = strtoul(c, NULL, 10);
160 }
161 if ((c = strcasestr(vbuf, "RECENT"))) {
162 c += 7;
163 recent = strtoul(c, NULL, 10);
164 }
165 if ((c = strcasestr(vbuf, "UNSEEN"))) {
166 c += 7;
167 unseen = strtoul(c, NULL, 10);
168 }
169 if (!exist) {
170 info("No messages in mailbox \"%s\".\n", mbox);
171 return -2;
172 }
173 info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n", exist,
174 plural(exist), recent, unseen, mbox);
175
176 return r;
177 }
178
179
180 /*
181 * Process the data that server sent due to IMAP SELECT client request.
182 */
183 int select_response(int *sock, unsigned int tag)
184 {
185 char buf[RESPONSE_BUF];
186
187 reset_vbuf();
188
189 do {
190 receive_response(sock, buf);
191 check_vbuf(strlen(buf));
192 strncat(vbuf, buf, vbufs - strlen(vbuf));
193 } while (!strcasestr(buf, ultostr(tag, 16)));
194
195 if (strcasestr(vbuf, "[READ-ONLY]"))
196 return RESPONSE_READONLY;
197
198 return analyze_response(buf);
199 }
200
201
202 /*
203 * Process the data that server sent due to IMAP SEARCH client request.
204 */
205 int search_response(int *sock, unsigned int tag, char **mesgs)
206 {
207 char buf[RESPONSE_BUF];
208 char *c, *m;
209 unsigned int blen;
210
211 reset_vbuf();
212
213 do {
214 receive_response(sock, buf);
215 check_vbuf(strlen(buf));
216 strncat(vbuf, buf, vbufs - strlen(vbuf));
217 } while (!strcasestr(buf, ultostr(tag, 16)));
218
219 if ((c = strcasestr(vbuf, "* SEARCH "))) {
220 blen = strlen(vbuf);
221
222 m = *mesgs = (char *)xmalloc(blen + 1);
223
224 c += 9;
225
226 while (*c && (isdigit(*c) || *c == ' '))
227 *(m++) = *(c++);
228
229 *m = 0;
230 }
231 return analyze_response(buf);
232 }
233
234
235 /*
236 * Process the data that server sent due to IMAP FETCH client request.
237 */
238 int fetch_response(int *sock, int reset, char *fetch, unsigned int tag)
239 {
240 char buf[RESPONSE_BUF];
241 unsigned int i;
242 static unsigned int s;
243 char *b;
244
245 if (reset) {
246 s = 0;
247 return 0;
248 }
249 i = 0;
250
251 receive_response(sock, buf);
252
253 b = buf;
254
255 if (!s) {
256 b = strchr(b, '{');
257 b++;
258 s = atoi(b) - 2;
259 b = strchr(b, '}');
260 b += 3;
261 }
262 while (*b && s--)
263 fetch[i++] = *(b++);
264
265 fetch[i] = 0;
266
267 return analyze_response(buf);
268 }
269
270
271 /*
272 * Process the data that server sent due to IMAP FETCH RFC822.SIZE client
273 * request.
274 */
275 int fetchsize_response(int *sock, unsigned int *size, unsigned int tag)
276 {
277 char buf[RESPONSE_BUF];
278 char *c;
279
280 *size = 0;
281
282 reset_vbuf();
283
284 do {
285 receive_response(sock, buf);
286 check_vbuf(strlen(buf));
287 strncat(vbuf, buf, vbufs - strlen(vbuf));
288 } while (!strcasestr(buf, ultostr(tag, 16)));
289
290 if ((c = strcasestr(vbuf, "FETCH (RFC822.SIZE "))) {
291 c += 19;
292 *size = strtoul(c, NULL, 10);
293 }
294 return analyze_response(buf);
295 }
296
297
298 /*
299 * Process the data that server sent due to IMAP APPEND client request.
300 */
301 int append_response(int *sock, unsigned int tag)
302 {
303 int r = RESPONSE_OK;
304 char buf[RESPONSE_BUF];
305
306 reset_vbuf();
307
308 do {
309 receive_response(sock, buf);
310 check_vbuf(strlen(buf));
311 strncat(vbuf, buf, vbufs - strlen(vbuf));
312 } while (!strcasestr(buf, ultostr(tag, 16)));
313
314 if ((r = analyze_response(buf)) == RESPONSE_NO &&
315 strcasestr(vbuf, "[TRYCREATE]"))
316 return RESPONSE_TRYCREATE;
317
318 return r;
319 }
320
321
322 /*
323 * Process the data that server sent due to IMAP COPY client request.
324 */
325 int copy_response(int *sock, unsigned int tag)
326 {
327 int r = RESPONSE_OK;
328 char buf[RESPONSE_BUF];
329
330 reset_vbuf();
331
332 do {
333 receive_response(sock, 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 } else
373 r = RESPONSE_NONE;
374
375 regfree(&creg);
376
377 return r;
378 }
379
380
381 /*
382 * Initialize virtual buffer.
383 */
384 void init_vbuf(void)
385 {
386 vbuf = xmalloc(4096);
387 *vbuf = 0;
388 vbufs = 4096;
389 }
390
391
392 /*
393 * Reset virtual buffer.
394 */
395 void reset_vbuf(void)
396 {
397 *vbuf = 0;
398 }
399
400
401 /*
402 * Check if virtual buffer is full and make it bigger.
403 */
404 void check_vbuf(size_t n)
405 {
406 if (n + strlen(vbuf) >= vbufs) {
407 vbufs += 4096;
408 vbuf = xrealloc(vbuf, vbufs);
409 }
410 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26