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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.21 - (show annotations)
Sat Jul 13 22:40:07 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.20: +29 -33 lines
File MIME type: text/plain
Replaced unnecessary strncasecmp()'s.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26