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

Contents of /imapfilter/response.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (show annotations)
Tue Nov 6 17:41:27 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.12: +147 -69 lines
File MIME type: text/plain
Dynamically allocate response buffer.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26