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

Annotation of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (hide annotations)
Sat Dec 8 14:42:25 2001 UTC (22 years, 3 months ago) by lefcha
Branch: MAIN
Changes since 1.17: +34 -3 lines
File MIME type: text/plain
Namespace support.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26