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.
Showing
6 changed files
with
69 additions
and
20 deletions
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 | ... | ... |
-
Please register or sign in to post a comment