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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.22 - (hide annotations)
Sat Jul 13 23:03:28 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.21: +2 -2 lines
File MIME type: text/plain
Correction on strncasecmp.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26