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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (show annotations)
Fri Nov 9 15:52:20 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.14: +20 -9 lines
File MIME type: text/plain
Headers fetching bug fixes.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26