Commit 30f0097c 30f0097c4c2a9b552323733cbc436b91d32fbce6 by Sergey Poznyakoff

Bugfixes.

* imap4d/fetch.c (fetch_send_section_part): Make sure the item tag
always reflects peek status.  All callers updated.
(fetch_io): Try to allocate as large a buffer as possible.
Use util_send_bytes where fit.
* imap4d/imap4d.h (imap4d_auth_handler_fp): Remove unused argument.
* imap4d/store.c (imap4d_store0): Take into account eventual UID
prefix.
* imap4d/util.c (util_send_bytes): New function.
(util_send): Comment out transcript.
(util_do_command): Fix coredump on invalid commands.
(imap4d_readline): Transcript only first line of the input.
Ensure entire literal is read.
1 parent 927c27f8
1 2008-08-11 Sergey Poznyakoff <gray@gnu.org.ua> 1 2008-08-11 Sergey Poznyakoff <gray@gnu.org.ua>
2 2
3 * imap4d/fetch.c (fetch_send_section_part): Make sure the item tag
4 always reflects peek status. All callers updated.
5 (fetch_io): Try to allocate as large a buffer as possible.
6 Use util_send_bytes where fit.
7 * imap4d/imap4d.h (imap4d_auth_handler_fp): Remove unused argument.
8 * imap4d/store.c (imap4d_store0): Take into account eventual UID
9 prefix.
10 * imap4d/util.c (util_send_bytes): New function.
11 (util_send): Comment out transcript.
12 (util_do_command): Fix coredump on invalid commands.
13 (imap4d_readline): Transcript only first line of the input.
14 Ensure entire literal is read.
15
3 Fix input operations and RFC-compliance in imap4d. 16 Fix input operations and RFC-compliance in imap4d.
4 17
5 * imap4d/util.c (util_getword, util_getitem, util_token) 18 * imap4d/util.c (util_getword, util_getitem, util_token)
......
...@@ -656,20 +656,24 @@ fetch_get_part (struct fetch_function_closure *ffc, ...@@ -656,20 +656,24 @@ fetch_get_part (struct fetch_function_closure *ffc,
656 656
657 static void 657 static void
658 fetch_send_section_part (struct fetch_function_closure *ffc, 658 fetch_send_section_part (struct fetch_function_closure *ffc,
659 const char *prefix, const char *suffix) 659 const char *suffix)
660 { 660 {
661 int i; 661 int i;
662 662
663 util_send ("%s", prefix); 663 util_send ("BODY%s[", ffc->peek ? ".PEEK" : "");
664 for (i = 0; i < ffc->nset; i++) 664 for (i = 0; i < ffc->nset; i++)
665 { 665 {
666 if (i) 666 if (i)
667 util_send ("."); 667 util_send (".");
668 util_send ("%lu", (unsigned long) ffc->section_part[i]); 668 util_send ("%lu", (unsigned long) ffc->section_part[i]);
669 } 669 }
670 if (i && suffix[0] != ']') 670 if (suffix)
671 {
672 if (i)
671 util_send ("."); 673 util_send (".");
672 util_send ("%s", suffix); 674 util_send ("%s", suffix);
675 }
676 util_send ("]");
673 } 677 }
674 678
675 static int 679 static int
...@@ -683,19 +687,25 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max) ...@@ -683,19 +687,25 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
683 687
684 if (start == 0 && size == (size_t) -1) 688 if (start == 0 && size == (size_t) -1)
685 { 689 {
686 char buffer[512]; 690 char *buffer;
691 size_t bufsize;
692
693 for (bufsize = max; (buffer = malloc (bufsize)) == NULL; bufsize /= 2)
694 if (bufsize < 512)
695 imap4d_bye (ERR_NO_MEM);
696
687 offset = 0; 697 offset = 0;
688 if (max) 698 if (max)
689 { 699 {
690 util_send (" {%lu}\r\n", (unsigned long) max); 700 util_send (" {%lu}\r\n", (unsigned long) max);
691 while (mu_stream_read (rfc, buffer, sizeof (buffer) - 1, offset, 701 while (mu_stream_read (rfc, buffer, bufsize, offset,
692 &n) == 0 && n > 0) 702 &n) == 0 && n > 0)
693 { 703 {
694 buffer[n] = '\0'; 704 util_send_bytes (buffer, n);
695 util_send ("%s", buffer);
696 offset += n; 705 offset += n;
697 } 706 }
698 /* FIXME: Make sure exactly max bytes were sent */ 707 /* FIXME: Make sure exactly max bytes were sent */
708 free (buffer);
699 } 709 }
700 else 710 else
701 util_send (" \"\""); 711 util_send (" \"\"");
...@@ -726,7 +736,7 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max) ...@@ -726,7 +736,7 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
726 if (total) 736 if (total)
727 { 737 {
728 util_send (" {%lu}\r\n", (unsigned long) total); 738 util_send (" {%lu}\r\n", (unsigned long) total);
729 util_send ("%s", buffer); 739 util_send_bytes (buffer, total);
730 } 740 }
731 else 741 else
732 util_send (" \"\""); 742 util_send (" \"\"");
...@@ -858,7 +868,7 @@ _frt_body (struct fetch_function_closure *ffc, ...@@ -858,7 +868,7 @@ _frt_body (struct fetch_function_closure *ffc,
858 if (ffc->name) 868 if (ffc->name)
859 util_send ("%s", ffc->name); 869 util_send ("%s", ffc->name);
860 else 870 else
861 fetch_send_section_part (ffc, "BODY[", "]"); 871 fetch_send_section_part (ffc, NULL);
862 msg = fetch_get_part (ffc, frt); 872 msg = fetch_get_part (ffc, frt);
863 if (!msg) 873 if (!msg)
864 { 874 {
...@@ -884,7 +894,7 @@ _frt_body_text (struct fetch_function_closure *ffc, ...@@ -884,7 +894,7 @@ _frt_body_text (struct fetch_function_closure *ffc,
884 if (ffc->name) 894 if (ffc->name)
885 util_send ("%s", ffc->name); 895 util_send ("%s", ffc->name);
886 else 896 else
887 fetch_send_section_part (ffc, "BODY[", "TEXT]"); 897 fetch_send_section_part (ffc, "TEXT");
888 msg = fetch_get_part (ffc, frt); 898 msg = fetch_get_part (ffc, frt);
889 if (!msg) 899 if (!msg)
890 { 900 {
...@@ -926,7 +936,7 @@ _frt_header0 (struct fetch_function_closure *ffc, ...@@ -926,7 +936,7 @@ _frt_header0 (struct fetch_function_closure *ffc,
926 if (ffc->name) 936 if (ffc->name)
927 util_send ("%s", ffc->name); 937 util_send ("%s", ffc->name);
928 else 938 else
929 fetch_send_section_part (ffc, "BODY[", suffix); 939 fetch_send_section_part (ffc, suffix);
930 940
931 msg = fetch_get_part (ffc, frt); 941 msg = fetch_get_part (ffc, frt);
932 if (!msg) 942 if (!msg)
...@@ -945,14 +955,14 @@ static int ...@@ -945,14 +955,14 @@ static int
945 _frt_header (struct fetch_function_closure *ffc, 955 _frt_header (struct fetch_function_closure *ffc,
946 struct fetch_runtime_closure *frt) 956 struct fetch_runtime_closure *frt)
947 { 957 {
948 return _frt_header0 (ffc, frt, "HEADER]"); 958 return _frt_header0 (ffc, frt, "HEADER");
949 } 959 }
950 960
951 static int 961 static int
952 _frt_mime (struct fetch_function_closure *ffc, 962 _frt_mime (struct fetch_function_closure *ffc,
953 struct fetch_runtime_closure *frt) 963 struct fetch_runtime_closure *frt)
954 { 964 {
955 return _frt_header0 (ffc, frt, "MIME]"); 965 return _frt_header0 (ffc, frt, "MIME");
956 } 966 }
957 967
958 static int 968 static int
...@@ -990,7 +1000,7 @@ _frt_header_fields (struct fetch_function_closure *ffc, ...@@ -990,7 +1000,7 @@ _frt_header_fields (struct fetch_function_closure *ffc,
990 1000
991 set_seen (ffc, frt); 1001 set_seen (ffc, frt);
992 1002
993 fetch_send_section_part (ffc, "BODY[", "HEADER.FIELDS"); 1003 fetch_send_section_part (ffc, "HEADER.FIELDS");
994 if (ffc->not) 1004 if (ffc->not)
995 util_send (".NOT"); 1005 util_send (".NOT");
996 util_send (" ("); 1006 util_send (" (");
......
...@@ -347,7 +347,7 @@ int imap4d_init_tls_server (void); ...@@ -347,7 +347,7 @@ int imap4d_init_tls_server (void);
347 #endif /* WITH_TLS */ 347 #endif /* WITH_TLS */
348 348
349 typedef int (*imap4d_auth_handler_fp) (struct imap4d_command *, 349 typedef int (*imap4d_auth_handler_fp) (struct imap4d_command *,
350 char *, char *, char **); 350 char *, char **);
351 351
352 extern void auth_add (char *name, imap4d_auth_handler_fp handler); 352 extern void auth_add (char *name, imap4d_auth_handler_fp handler);
353 extern void auth_remove (char *name); 353 extern void auth_remove (char *name);
......
...@@ -72,7 +72,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext) ...@@ -72,7 +72,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext)
72 int type = 0; 72 int type = 0;
73 73
74 pb.tok = tok; 74 pb.tok = tok;
75 pb.arg = IMAP4_ARG_1; 75 pb.arg = IMAP4_ARG_1 + !!isuid;
76 pb.err_text = NULL; 76 pb.err_text = NULL;
77 if (setjmp (pb.errjmp)) 77 if (setjmp (pb.errjmp))
78 { 78 {
......
...@@ -262,6 +262,12 @@ util_msgset (char *s, size_t ** set, int *n, int isuid) ...@@ -262,6 +262,12 @@ util_msgset (char *s, size_t ** set, int *n, int isuid)
262 } 262 }
263 263
264 int 264 int
265 util_send_bytes (const char *buf, size_t size)
266 {
267 return mu_stream_sequential_write (ostream, buf, size);
268 }
269
270 int
265 util_send (const char *format, ...) 271 util_send (const char *format, ...)
266 { 272 {
267 char *buf = NULL; 273 char *buf = NULL;
...@@ -274,8 +280,10 @@ util_send (const char *format, ...) ...@@ -274,8 +280,10 @@ util_send (const char *format, ...)
274 if (!buf) 280 if (!buf)
275 imap4d_bye (ERR_NO_MEM); 281 imap4d_bye (ERR_NO_MEM);
276 282
283 #if 0
277 if (imap4d_transcript) 284 if (imap4d_transcript)
278 mu_diag_output (MU_DIAG_DEBUG, "sent: %s", buf); 285 mu_diag_output (MU_DIAG_DEBUG, "sent: %s", buf);
286 #endif
279 287
280 status = mu_stream_sequential_write (ostream, buf, strlen (buf)); 288 status = mu_stream_sequential_write (ostream, buf, strlen (buf));
281 free (buf); 289 free (buf);
...@@ -410,7 +418,7 @@ util_do_command (imap4d_tokbuf_t tok) ...@@ -410,7 +418,7 @@ util_do_command (imap4d_tokbuf_t tok)
410 else if (argc == 1) 418 else if (argc == 1)
411 { 419 {
412 nullcommand.name = ""; 420 nullcommand.name = "";
413 nullcommand.tag = tag; 421 nullcommand.tag = imap4d_tokbuf_getarg (tok, 0);
414 return util_finish (&nullcommand, RESP_BAD, "Missing command"); 422 return util_finish (&nullcommand, RESP_BAD, "Missing command");
415 } 423 }
416 424
...@@ -1339,11 +1347,15 @@ imap4d_tokbuf_getline (struct imap4d_tokbuf *tok) ...@@ -1339,11 +1347,15 @@ imap4d_tokbuf_getline (struct imap4d_tokbuf *tok)
1339 void 1347 void
1340 imap4d_readline (struct imap4d_tokbuf *tok) 1348 imap4d_readline (struct imap4d_tokbuf *tok)
1341 { 1349 {
1350 int transcript = imap4d_transcript;
1342 tok->argc = 0; 1351 tok->argc = 0;
1352 tok->level = 0;
1343 for (;;) 1353 for (;;)
1344 { 1354 {
1345 char *last_arg; 1355 char *last_arg;
1346 size_t off = imap4d_tokbuf_getline (tok); 1356 size_t off = imap4d_tokbuf_getline (tok);
1357 if (transcript)
1358 mu_diag_output (MU_DIAG_DEBUG, "recv: %s", tok->buffer);
1347 imap4d_tokbuf_tokenize (tok, off); 1359 imap4d_tokbuf_tokenize (tok, off);
1348 last_arg = tok->buffer + tok->argp[tok->argc - 1]; 1360 last_arg = tok->buffer + tok->argp[tok->argc - 1];
1349 if (last_arg[0] == '{' && last_arg[strlen(last_arg)-1] == '}') 1361 if (last_arg[0] == '{' && last_arg[strlen(last_arg)-1] == '}')
...@@ -1354,6 +1366,9 @@ imap4d_readline (struct imap4d_tokbuf *tok) ...@@ -1354,6 +1366,9 @@ imap4d_readline (struct imap4d_tokbuf *tok)
1354 char *buf; 1366 char *buf;
1355 size_t len; 1367 size_t len;
1356 1368
1369 if (transcript)
1370 mu_diag_output (MU_DIAG_DEBUG, "(literal follows)");
1371 transcript = 0;
1357 number = strtoul (last_arg + 1, &sp, 10); 1372 number = strtoul (last_arg + 1, &sp, 10);
1358 /* Client can ask for non-synchronised literal, 1373 /* Client can ask for non-synchronised literal,
1359 if a '+' is appended to the octet count. */ 1374 if a '+' is appended to the octet count. */
...@@ -1364,7 +1379,16 @@ imap4d_readline (struct imap4d_tokbuf *tok) ...@@ -1364,7 +1379,16 @@ imap4d_readline (struct imap4d_tokbuf *tok)
1364 imap4d_tokbuf_expand (tok, number + 1); 1379 imap4d_tokbuf_expand (tok, number + 1);
1365 off = tok->level; 1380 off = tok->level;
1366 buf = tok->buffer + off; 1381 buf = tok->buffer + off;
1367 rc = mu_stream_sequential_read (istream, buf, number, &len); 1382 len = 0;
1383 while (len < number)
1384 {
1385 size_t sz;
1386 rc = mu_stream_sequential_read (istream,
1387 buf + len, number - len, &sz);
1388 if (rc || sz == 0)
1389 break;
1390 len += sz;
1391 }
1368 check_input_err (rc, len); 1392 check_input_err (rc, len);
1369 len = remove_cr (buf, len); 1393 len = remove_cr (buf, len);
1370 imap4d_tokbuf_unquote (tok, &off, &len); 1394 imap4d_tokbuf_unquote (tok, &off, &len);
...@@ -1403,6 +1427,8 @@ imap4d_getline (char **pbuf, size_t *psize, size_t *pnbytes) ...@@ -1403,6 +1427,8 @@ imap4d_getline (char **pbuf, size_t *psize, size_t *pnbytes)
1403 s[--len] = 0; 1427 s[--len] = 0;
1404 if (s && len > 0 && s[len - 1] == '\r') 1428 if (s && len > 0 && s[len - 1] == '\r')
1405 s[--len] = 0; 1429 s[--len] = 0;
1430 if (imap4d_transcript)
1431 mu_diag_output (MU_DIAG_DEBUG, "recv: %s", s);
1406 if (pnbytes) 1432 if (pnbytes)
1407 *pnbytes = len; 1433 *pnbytes = len;
1408 } 1434 }
......
...@@ -102,8 +102,8 @@ rfc822_readline (mu_filter_t filter, char *buffer, size_t buflen, ...@@ -102,8 +102,8 @@ rfc822_readline (mu_filter_t filter, char *buffer, size_t buflen,
102 } 102 }
103 103
104 /* RFC 822 converter "\n" --> "\r\n" 104 /* RFC 822 converter "\n" --> "\r\n"
105 We maintain to offset, the rfc822 offset (r_offset) and the offset of 105 We maintain two offsets, the rfc822 offset (r_offset) and the offset of
106 the stream (s_offset). If they do not match we go back as for as possible 106 the stream (s_offset). If they do not match we go back as far as possible
107 and start to read by 1 'till we reach the current offset. */ 107 and start to read by 1 'till we reach the current offset. */
108 108
109 static int 109 static int
......