7 |
#include <sys/time.h> |
#include <sys/time.h> |
8 |
#include <sys/types.h> |
#include <sys/types.h> |
9 |
#include <regex.h> |
#include <regex.h> |
10 |
|
#include <setjmp.h> |
11 |
|
|
12 |
#include "config.h" |
#include "config.h" |
13 |
#include "imapfilter.h" |
#include "imapfilter.h" |
15 |
|
|
16 |
extern int sockpri; |
extern int sockpri; |
17 |
extern unsigned int capabilities; |
extern unsigned int capabilities; |
18 |
|
extern jmp_buf acctloop; |
19 |
|
|
20 |
static char *vbuf = NULL; /* Virtual buffer. */ |
static char *vbuf = NULL; /* Virtual buffer. */ |
21 |
static size_t vbufs = 0; /* Virtual buffer size. */ |
static size_t vbufs = 0; /* Virtual buffer size. */ |
26 |
*/ |
*/ |
27 |
void receive_response(int *sock, char *buf) |
void receive_response(int *sock, char *buf) |
28 |
{ |
{ |
29 |
socket_read(sock, buf); |
if (socket_read(sock, buf) == ERROR_NETWORK) |
30 |
|
longjmp(acctloop, -1); |
31 |
|
|
32 |
#ifdef DEBUG |
#ifdef DEBUG |
33 |
printf("\n%s\n", buf); |
printf("\n%s\n", buf); |
41 |
*/ |
*/ |
42 |
int server_response(int *sock, unsigned int tag) |
int server_response(int *sock, unsigned int tag) |
43 |
{ |
{ |
44 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
45 |
|
|
46 |
reset_vbuf(); |
reset_vbuf(); |
47 |
|
|
48 |
do { |
do { |
49 |
receive_response(sock, buf); |
receive_response(sock, buf); |
50 |
|
bye_response(buf); |
51 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
52 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
53 |
} while (tag && !strcasestr(buf, ultostr(tag, 16))); |
} while (tag && !strcasestr(buf, ultostr(tag, 16))); |
57 |
|
|
58 |
|
|
59 |
/* |
/* |
60 |
|
* Check if server sent a BYE response (connection is closed immediately). |
61 |
|
*/ |
62 |
|
void bye_response(char *buf) |
63 |
|
{ |
64 |
|
if (strcasestr(buf, "* BYE")) |
65 |
|
longjmp(acctloop, -1); |
66 |
|
} |
67 |
|
|
68 |
|
|
69 |
|
/* |
70 |
* Process the greeting that server sends during connection. |
* Process the greeting that server sends during connection. |
71 |
*/ |
*/ |
72 |
int greeting_response(int *sock) |
int greeting_response(int *sock) |
73 |
{ |
{ |
74 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
75 |
|
|
76 |
receive_response(sock, buf); |
receive_response(sock, buf); |
77 |
|
bye_response(buf); |
78 |
|
|
79 |
if (strcasestr(buf, "BYE")) |
if (strcasestr(buf, "* PREAUTH")) |
|
return RESPONSE_BYE; |
|
|
else if (strcasestr(buf, "PREAUTH")) |
|
80 |
return RESPONSE_PREAUTH; |
return RESPONSE_PREAUTH; |
81 |
|
|
82 |
return RESPONSE_OK; |
return RESPONSE_OK; |
84 |
|
|
85 |
|
|
86 |
/* |
/* |
87 |
|
* Process the data that server sent due to IMAP LOGOUT client request. |
88 |
|
*/ |
89 |
|
int logout_response(int *sock, unsigned int tag) |
90 |
|
{ |
91 |
|
char buf[RESPONSE_BUF + 1]; |
92 |
|
|
93 |
|
reset_vbuf(); |
94 |
|
|
95 |
|
do { |
96 |
|
receive_response(sock, buf); |
97 |
|
check_vbuf(strlen(buf)); |
98 |
|
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
99 |
|
} while (!strcasestr(buf, ultostr(tag, 16))); |
100 |
|
|
101 |
|
return analyze_response(buf); |
102 |
|
} |
103 |
|
|
104 |
|
|
105 |
|
/* |
106 |
* Process the data that server sent due to IMAP CAPABILITY client request. |
* Process the data that server sent due to IMAP CAPABILITY client request. |
107 |
*/ |
*/ |
108 |
int capability_response(int *sock, unsigned int tag) |
int capability_response(int *sock, unsigned int tag) |
109 |
{ |
{ |
110 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
111 |
|
|
112 |
reset_vbuf(); |
reset_vbuf(); |
113 |
|
|
114 |
do { |
do { |
115 |
receive_response(sock, buf); |
receive_response(sock, buf); |
116 |
|
bye_response(buf); |
117 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
118 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
119 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
134 |
*/ |
*/ |
135 |
int namespace_response(int *sock, unsigned int tag, namesp_t * nsp) |
int namespace_response(int *sock, unsigned int tag, namesp_t * nsp) |
136 |
{ |
{ |
137 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
138 |
char *c, *d; |
char *c, *d; |
139 |
|
|
140 |
reset_vbuf(); |
reset_vbuf(); |
141 |
|
|
142 |
do { |
do { |
143 |
|
receive_response(sock, buf); |
144 |
|
bye_response(buf); |
145 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
146 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
|
receive_response(sock, buf); |
|
147 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
148 |
|
|
149 |
if ((c = strcasestr(vbuf, "* NAMESPACE"))) { |
if ((c = strcasestr(vbuf, "* NAMESPACE"))) { |
169 |
int status_response(int *sock, unsigned int tag, char *mbox) |
int status_response(int *sock, unsigned int tag, char *mbox) |
170 |
{ |
{ |
171 |
int r; |
int r; |
172 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
173 |
unsigned int exist, recent, unseen; |
unsigned int exist, recent, unseen; |
174 |
char *c; |
char *c; |
175 |
|
|
179 |
|
|
180 |
do { |
do { |
181 |
receive_response(sock, buf); |
receive_response(sock, buf); |
182 |
|
bye_response(buf); |
183 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
184 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
185 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
217 |
*/ |
*/ |
218 |
int select_response(int *sock, unsigned int tag) |
int select_response(int *sock, unsigned int tag) |
219 |
{ |
{ |
220 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
221 |
|
|
222 |
reset_vbuf(); |
reset_vbuf(); |
223 |
|
|
224 |
do { |
do { |
225 |
receive_response(sock, buf); |
receive_response(sock, buf); |
226 |
|
bye_response(buf); |
227 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
228 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
229 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
240 |
*/ |
*/ |
241 |
int search_response(int *sock, unsigned int tag, char **mesgs) |
int search_response(int *sock, unsigned int tag, char **mesgs) |
242 |
{ |
{ |
243 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
244 |
char *c, *m; |
char *c, *m; |
245 |
unsigned int blen; |
unsigned int blen; |
246 |
|
|
248 |
|
|
249 |
do { |
do { |
250 |
receive_response(sock, buf); |
receive_response(sock, buf); |
251 |
|
bye_response(buf); |
252 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
253 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
254 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
260 |
|
|
261 |
c += 9; |
c += 9; |
262 |
|
|
263 |
while (*c && (isdigit(*c) || *c == ' ')) |
while (*c && (isdigit((unsigned char)(*c)) || *c == ' ')) |
264 |
*(m++) = *(c++); |
*(m++) = *(c++); |
265 |
|
|
266 |
*m = 0; |
*m = 0; |
272 |
/* |
/* |
273 |
* Process the data that server sent due to IMAP FETCH client request. |
* Process the data that server sent due to IMAP FETCH client request. |
274 |
*/ |
*/ |
275 |
int fetch_response(int *sock, int reset, char *fetch, unsigned int tag) |
int fetch_response(int *sock, unsigned int tag, int reset, char *fetch) |
276 |
{ |
{ |
277 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
278 |
unsigned int i; |
unsigned int i; |
279 |
static unsigned int s; |
static unsigned int s; |
280 |
char *b; |
char *b; |
285 |
} |
} |
286 |
i = 0; |
i = 0; |
287 |
|
|
288 |
receive_response(sock, buf); |
reset_vbuf(); |
289 |
|
|
290 |
|
do { |
291 |
|
receive_response(sock, buf); |
292 |
|
bye_response(buf); |
293 |
|
check_vbuf(strlen(buf)); |
294 |
|
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
295 |
|
} while (strlen(vbuf) < RESPONSE_BUF && |
296 |
|
!strcasestr(buf, ultostr(tag, 16))); |
297 |
|
|
298 |
b = buf; |
b = vbuf; |
299 |
|
|
300 |
if (!s) { |
if (!s) { |
301 |
b = strchr(b, '{'); |
if ((b = strstr(b, "}\r\n"))) { |
302 |
b++; |
while (b - vbuf > 0) |
303 |
s = atoi(b) - 2; |
if (*--b == '{') |
304 |
b = strchr(b, '}'); |
break; |
305 |
b += 3; |
s = atoi(++b) - 2; |
306 |
|
b = strchr(b, '}'); |
307 |
|
b += 3; |
308 |
|
} else { |
309 |
|
return RESPONSE_NULLBODY; /* Null body. */ |
310 |
|
} |
311 |
} |
} |
312 |
while (*b && s--) |
while (*b && s--) |
313 |
fetch[i++] = *(b++); |
fetch[i++] = *(b++); |
324 |
*/ |
*/ |
325 |
int fetchsize_response(int *sock, unsigned int *size, unsigned int tag) |
int fetchsize_response(int *sock, unsigned int *size, unsigned int tag) |
326 |
{ |
{ |
327 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
328 |
char *c; |
char *c; |
329 |
|
|
330 |
*size = 0; |
*size = 0; |
333 |
|
|
334 |
do { |
do { |
335 |
receive_response(sock, buf); |
receive_response(sock, buf); |
336 |
|
bye_response(buf); |
337 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
338 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
339 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
352 |
int append_response(int *sock, unsigned int tag) |
int append_response(int *sock, unsigned int tag) |
353 |
{ |
{ |
354 |
int r = RESPONSE_OK; |
int r = RESPONSE_OK; |
355 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
356 |
|
|
357 |
reset_vbuf(); |
reset_vbuf(); |
358 |
|
|
359 |
do { |
do { |
360 |
receive_response(sock, buf); |
receive_response(sock, buf); |
361 |
|
bye_response(buf); |
362 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
363 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
364 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
377 |
int copy_response(int *sock, unsigned int tag) |
int copy_response(int *sock, unsigned int tag) |
378 |
{ |
{ |
379 |
int r = RESPONSE_OK; |
int r = RESPONSE_OK; |
380 |
char buf[RESPONSE_BUF]; |
char buf[RESPONSE_BUF + 1]; |
381 |
|
|
382 |
reset_vbuf(); |
reset_vbuf(); |
383 |
|
|
384 |
do { |
do { |
385 |
receive_response(sock, buf); |
receive_response(sock, buf); |
386 |
|
bye_response(buf); |
387 |
check_vbuf(strlen(buf)); |
check_vbuf(strlen(buf)); |
388 |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
strncat(vbuf, buf, vbufs - strlen(vbuf)); |
389 |
} while (!strcasestr(buf, ultostr(tag, 16))); |
} while (!strcasestr(buf, ultostr(tag, 16))); |
436 |
*/ |
*/ |
437 |
void init_vbuf(void) |
void init_vbuf(void) |
438 |
{ |
{ |
439 |
vbuf = xmalloc(4096); |
vbuf = xmalloc(VIRTUAL_BUF); |
440 |
*vbuf = 0; |
*vbuf = 0; |
441 |
vbufs = 4096; |
vbufs = VIRTUAL_BUF; |
442 |
} |
} |
443 |
|
|
444 |
|
|
457 |
void check_vbuf(size_t n) |
void check_vbuf(size_t n) |
458 |
{ |
{ |
459 |
if (n + strlen(vbuf) >= vbufs) { |
if (n + strlen(vbuf) >= vbufs) { |
460 |
vbufs += 4096; |
vbufs += VIRTUAL_BUF; |
461 |
vbuf = xrealloc(vbuf, vbufs); |
vbuf = xrealloc(vbuf, vbufs); |
462 |
} |
} |
463 |
} |
} |