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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23.2.2 - (hide annotations)
Mon Aug 26 20:20:23 2002 UTC (21 years, 7 months ago) by lefcha
Branch: release-0_8-patches
Changes since 1.23.2.1: +25 -6 lines
File MIME type: text/plain
Added logout_response() and some minor changes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26