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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (hide 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 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.14 if (strcasestr(buf, "BYE"))
65 lefcha 1.9 return RESPONSE_BYE;
66 lefcha 1.14 else if (strcasestr(buf, "PREAUTH"))
67     return RESPONSE_PREAUTH;
68 lefcha 1.9
69     return RESPONSE_OK;
70     }
71    
72 lefcha 1.13
73 lefcha 1.9 /*
74     * Process the data that server sent due to IMAP CAPABILITY client request.
75     */
76 lefcha 1.20 int capability_response(int *sock, unsigned int tag)
77 lefcha 1.9 {
78 lefcha 1.14 char buf[RESPONSE_BUF];
79 lefcha 1.21
80 lefcha 1.20 reset_vbuf();
81 lefcha 1.9
82 lefcha 1.20 do {
83 lefcha 1.21 receive_response(sock, buf);
84 lefcha 1.20 check_vbuf(strlen(buf));
85     strncat(vbuf, buf, vbufs - strlen(vbuf));
86     } while (!strcasestr(buf, ultostr(tag, 16)));
87 lefcha 1.9
88 lefcha 1.20 if (!strcasestr(vbuf, "IMAP4rev1")) {
89 lefcha 1.9 error("imapfilter: server does not support IMAP4rev1 protocol\n");
90     return -2;
91     }
92 lefcha 1.20 if (strcasestr(vbuf, "NAMESPACE"))
93 lefcha 1.18 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 lefcha 1.21 int namespace_response(int *sock, unsigned int tag, namesp_t * nsp)
103 lefcha 1.18 {
104     char buf[RESPONSE_BUF];
105     char *c, *d;
106    
107 lefcha 1.20 reset_vbuf();
108 lefcha 1.21
109 lefcha 1.20 do {
110 lefcha 1.24 receive_response(sock, buf);
111 lefcha 1.20 check_vbuf(strlen(buf));
112 lefcha 1.21 strncat(vbuf, buf, vbufs - strlen(vbuf));
113 lefcha 1.20 } while (!strcasestr(buf, ultostr(tag, 16)));
114 lefcha 1.18
115 lefcha 1.20 if ((c = strcasestr(vbuf, "* NAMESPACE"))) {
116 lefcha 1.18 c += 12;
117     if (strncasecmp(c, "NIL", 3)) {
118     c = strchr(c, '"') + 1;
119     d = strchr(c, '"') + 1;
120    
121 lefcha 1.20 strncat(nsp->prefix, c, d - c - 1);
122     nsp->delim = *(strchr(d, '"') + 1);
123 lefcha 1.18 }
124     }
125 lefcha 1.20 #ifdef DEBUG
126     printf("debug: namespace: '%s' '%c'\n", nsp->prefix, nsp->delim);
127     #endif
128 lefcha 1.14 return analyze_response(buf);
129 lefcha 1.9 }
130    
131    
132     /*
133 lefcha 1.3 * Process the data that server sent due to IMAP STATUS client request.
134 lefcha 1.1 */
135 lefcha 1.20 int status_response(int *sock, unsigned int tag, char *mbox)
136 lefcha 1.1 {
137 lefcha 1.17 int r;
138 lefcha 1.14 char buf[RESPONSE_BUF];
139 lefcha 1.1 unsigned int exist, recent, unseen;
140 lefcha 1.9 char *c;
141 lefcha 1.1
142     exist = recent = unseen = 0;
143 lefcha 1.21
144 lefcha 1.20 reset_vbuf();
145 lefcha 1.1
146 lefcha 1.20 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 lefcha 1.13
152 lefcha 1.17 r = analyze_response(buf);
153    
154     if (r == RESPONSE_NO)
155     return -2;
156    
157 lefcha 1.20 if ((c = strcasestr(vbuf, "MESSAGES"))) {
158 lefcha 1.9 c += 9;
159     exist = strtoul(c, NULL, 10);
160     }
161 lefcha 1.20 if ((c = strcasestr(vbuf, "RECENT"))) {
162 lefcha 1.9 c += 7;
163     recent = strtoul(c, NULL, 10);
164     }
165 lefcha 1.20 if ((c = strcasestr(vbuf, "UNSEEN"))) {
166 lefcha 1.9 c += 7;
167     unseen = strtoul(c, NULL, 10);
168     }
169 lefcha 1.8 if (!exist) {
170 lefcha 1.19 info("No messages in mailbox \"%s\".\n", mbox);
171 lefcha 1.8 return -2;
172     }
173 lefcha 1.19 info("%d message%s, %d recent, %d unseen, in mailbox \"%s\".\n", exist,
174 lefcha 1.18 plural(exist), recent, unseen, mbox);
175 lefcha 1.9
176 lefcha 1.17 return r;
177 lefcha 1.9 }
178    
179    
180     /*
181     * Process the data that server sent due to IMAP SELECT client request.
182     */
183 lefcha 1.20 int select_response(int *sock, unsigned int tag)
184 lefcha 1.9 {
185 lefcha 1.14 char buf[RESPONSE_BUF];
186 lefcha 1.9
187 lefcha 1.20 reset_vbuf();
188 lefcha 1.21
189 lefcha 1.20 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 lefcha 1.9
195 lefcha 1.20 if (strcasestr(vbuf, "[READ-ONLY]"))
196 lefcha 1.9 return RESPONSE_READONLY;
197 lefcha 1.1
198 lefcha 1.14 return analyze_response(buf);
199 lefcha 1.1 }
200    
201    
202     /*
203 lefcha 1.3 * Process the data that server sent due to IMAP SEARCH client request.
204 lefcha 1.1 */
205 lefcha 1.20 int search_response(int *sock, unsigned int tag, char **mesgs)
206 lefcha 1.1 {
207 lefcha 1.14 char buf[RESPONSE_BUF];
208 lefcha 1.13 char *c, *m;
209 lefcha 1.20 unsigned int blen;
210 lefcha 1.13
211 lefcha 1.20 reset_vbuf();
212 lefcha 1.21
213 lefcha 1.20 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 lefcha 1.1
219 lefcha 1.20 if ((c = strcasestr(vbuf, "* SEARCH "))) {
220     blen = strlen(vbuf);
221 lefcha 1.21
222     m = *mesgs = (char *)xmalloc(blen + 1);
223    
224 lefcha 1.20 c += 9;
225 lefcha 1.21
226 lefcha 1.20 while (*c && (isdigit(*c) || *c == ' '))
227     *(m++) = *(c++);
228 lefcha 1.14
229 lefcha 1.20 *m = 0;
230     }
231 lefcha 1.14 return analyze_response(buf);
232 lefcha 1.1 }
233    
234    
235     /*
236 lefcha 1.3 * Process the data that server sent due to IMAP FETCH client request.
237 lefcha 1.1 */
238 lefcha 1.20 int fetch_response(int *sock, int reset, char *fetch, unsigned int tag)
239 lefcha 1.1 {
240 lefcha 1.14 char buf[RESPONSE_BUF];
241 lefcha 1.20 unsigned int i;
242     static unsigned int s;
243 lefcha 1.15 char *b;
244 lefcha 1.14
245 lefcha 1.20 if (reset) {
246     s = 0;
247     return 0;
248     }
249     i = 0;
250    
251     receive_response(sock, buf);
252    
253     b = buf;
254 lefcha 1.21
255 lefcha 1.20 if (!s) {
256     b = strchr(b, '{');
257     b++;
258 lefcha 1.21 s = atoi(b) - 2;
259 lefcha 1.20 b = strchr(b, '}');
260     b += 3;
261     }
262     while (*b && s--)
263     fetch[i++] = *(b++);
264    
265     fetch[i] = 0;
266 lefcha 1.21
267 lefcha 1.20 return analyze_response(buf);
268     }
269    
270 lefcha 1.6
271 lefcha 1.20 /*
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 lefcha 1.21
280 lefcha 1.20 *size = 0;
281 lefcha 1.21
282 lefcha 1.20 reset_vbuf();
283 lefcha 1.21
284 lefcha 1.13 do {
285 lefcha 1.20 receive_response(sock, buf);
286     check_vbuf(strlen(buf));
287     strncat(vbuf, buf, vbufs - strlen(vbuf));
288     } while (!strcasestr(buf, ultostr(tag, 16)));
289 lefcha 1.21
290 lefcha 1.20 if ((c = strcasestr(vbuf, "FETCH (RFC822.SIZE "))) {
291     c += 19;
292     *size = strtoul(c, NULL, 10);
293     }
294     return analyze_response(buf);
295     }
296 lefcha 1.13
297 lefcha 1.6
298 lefcha 1.20 /*
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 lefcha 1.21
306 lefcha 1.20 reset_vbuf();
307 lefcha 1.21
308 lefcha 1.20 do {
309     receive_response(sock, buf);
310 lefcha 1.21 check_vbuf(strlen(buf));
311 lefcha 1.20 strncat(vbuf, buf, vbufs - strlen(vbuf));
312 lefcha 1.14 } while (!strcasestr(buf, ultostr(tag, 16)));
313 lefcha 1.21
314 lefcha 1.20 if ((r = analyze_response(buf)) == RESPONSE_NO &&
315     strcasestr(vbuf, "[TRYCREATE]"))
316     return RESPONSE_TRYCREATE;
317 lefcha 1.6
318 lefcha 1.20 return r;
319 lefcha 1.1 }
320    
321    
322     /*
323 lefcha 1.3 * Process the data that server sent due to IMAP COPY client request.
324 lefcha 1.1 */
325 lefcha 1.20 int copy_response(int *sock, unsigned int tag)
326 lefcha 1.1 {
327 lefcha 1.19 int r = RESPONSE_OK;
328 lefcha 1.20 char buf[RESPONSE_BUF];
329 lefcha 1.21
330 lefcha 1.20 reset_vbuf();
331 lefcha 1.1
332 lefcha 1.20 do {
333     receive_response(sock, buf);
334 lefcha 1.21 check_vbuf(strlen(buf));
335 lefcha 1.20 strncat(vbuf, buf, vbufs - strlen(vbuf));
336     } while (!strcasestr(buf, ultostr(tag, 16)));
337 lefcha 1.1
338 lefcha 1.19 if ((r = analyze_response(buf)) == RESPONSE_NO &&
339 lefcha 1.20 strcasestr(vbuf, "[TRYCREATE]"))
340 lefcha 1.9 return RESPONSE_TRYCREATE;
341 lefcha 1.1
342 lefcha 1.19 return r;
343 lefcha 1.1 }
344    
345    
346     /*
347 lefcha 1.3 * Check if response of server to client's request was succesfully
348 lefcha 1.1 * delivered or there was some kind of error.
349     */
350 lefcha 1.14 int analyze_response(char *buf)
351 lefcha 1.1 {
352 lefcha 1.9 int r = RESPONSE_OK;
353 lefcha 1.1 regex_t creg;
354     regmatch_t match[3];
355 lefcha 1.9 const char *reg = "[[:xdigit:]]{6,6} ((OK|NO|BAD)[[:print:]]*)\r\n";
356 lefcha 1.14 char result[RESULT_BUF];
357 lefcha 1.1
358 lefcha 1.4 result[0] = 0;
359    
360 lefcha 1.9 regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
361 lefcha 1.6
362 lefcha 1.14 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 lefcha 1.1
366 lefcha 1.22 if (!strncasecmp(buf + match[2].rm_so, "NO", 2))
367 lefcha 1.9 r = RESPONSE_NO;
368 lefcha 1.22 else if (!strncasecmp(buf + match[2].rm_so, "BAD", 3))
369 lefcha 1.9 r = RESPONSE_BAD;
370 lefcha 1.6
371 lefcha 1.1 verbose("Server response: %s\n", result);
372 lefcha 1.20 } else
373     r = RESPONSE_NONE;
374 lefcha 1.21
375 lefcha 1.6 regfree(&creg);
376 lefcha 1.1
377     return r;
378 lefcha 1.20 }
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 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26