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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19 - (show annotations)
Fri Jan 25 17:10:17 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.18: +6 -4 lines
File MIME type: text/plain
Merged changes from version 0.7.2.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26