imap4d: Fix the functionality of FETCH BODY sections HEADER, TEXT and MIME.
According to RFC 3501 HEADER, HEADER.FIELDS, and HEADER.FIELDS.NOT part specifiers refer to the RFC-2822 header of the message or of an encapsulated MESSAGE/RFC822 message. They return NILs if applied to a MIME part other than MESSAGE/RFC822. * imap4d/fetch.c (fetch_get_part_rfc822): New function. (_frt_body): Used only for BODY[]. Consequently, do not try to resolve message part, use the message itself instead. (_frt_body_n): New function. (_frt_mime): New function. (_frt_body_text,_frt_header,_frt_header_fields): Use fetch_get_part_rfc822. Unref the retrieved message when through. (parse_section_text): Use _frt_mime for BODY[<n>.MIME] (parse_section): Use _frt_body_n for BODY[<n>]. * imap4d/testsuite/imap4d/fetch.exp: Remove incorrect tests.
Showing
2 changed files
with
133 additions
and
71 deletions
... | @@ -685,6 +685,62 @@ fetch_get_part (struct fetch_function_closure *ffc, | ... | @@ -685,6 +685,62 @@ fetch_get_part (struct fetch_function_closure *ffc, |
685 | return msg; | 685 | return msg; |
686 | } | 686 | } |
687 | 687 | ||
688 | static mu_message_t | ||
689 | fetch_get_part_rfc822 (struct fetch_function_closure *ffc, | ||
690 | struct fetch_runtime_closure *frt) | ||
691 | { | ||
692 | mu_message_t msg = frt->msg, retmsg = NULL; | ||
693 | size_t i; | ||
694 | mu_header_t header; | ||
695 | const char *hval; | ||
696 | |||
697 | if (ffc->nset == 0) | ||
698 | { | ||
699 | mu_message_ref (msg); | ||
700 | return msg; | ||
701 | } | ||
702 | |||
703 | for (i = 0; i < ffc->nset; i++) | ||
704 | if (mu_message_get_part (msg, ffc->section_part[i], &msg)) | ||
705 | return NULL; | ||
706 | |||
707 | if (mu_message_get_header (msg, &header)) | ||
708 | return NULL; | ||
709 | |||
710 | if (mu_header_sget_value (header, MU_HEADER_CONTENT_TYPE, &hval) == 0) | ||
711 | { | ||
712 | struct mu_wordsplit ws; | ||
713 | int rc; | ||
714 | |||
715 | ws.ws_delim = " \t\r\n;="; | ||
716 | ws.ws_alloc_die = imap4d_ws_alloc_die; | ||
717 | if (mu_wordsplit (hval, &ws, IMAP4D_WS_FLAGS)) | ||
718 | { | ||
719 | mu_error (_("%s failed: %s"), "mu_wordsplit", | ||
720 | mu_wordsplit_strerror (&ws)); | ||
721 | return NULL; | ||
722 | } | ||
723 | |||
724 | rc = mu_c_strcasecmp (ws.ws_wordv[0], "MESSAGE/RFC822"); | ||
725 | mu_wordsplit_free (&ws); | ||
726 | |||
727 | if (rc == 0) | ||
728 | { | ||
729 | mu_body_t body; | ||
730 | mu_stream_t str; | ||
731 | |||
732 | if (mu_message_get_body (msg, &body) || | ||
733 | mu_body_get_streamref (body, &str)) | ||
734 | return NULL; | ||
735 | |||
736 | rc = mu_stream_to_message (str, &retmsg); | ||
737 | mu_stream_unref (str); | ||
738 | } | ||
739 | } | ||
740 | |||
741 | return retmsg; | ||
742 | } | ||
743 | |||
688 | static void | 744 | static void |
689 | fetch_send_section_part (struct fetch_function_closure *ffc, | 745 | fetch_send_section_part (struct fetch_function_closure *ffc, |
690 | const char *suffix, int close_bracket) | 746 | const char *suffix, int close_bracket) |
... | @@ -918,7 +974,7 @@ static int | ... | @@ -918,7 +974,7 @@ static int |
918 | _frt_body (struct fetch_function_closure *ffc, | 974 | _frt_body (struct fetch_function_closure *ffc, |
919 | struct fetch_runtime_closure *frt) | 975 | struct fetch_runtime_closure *frt) |
920 | { | 976 | { |
921 | mu_message_t msg; | 977 | mu_message_t msg = frt->msg; |
922 | mu_stream_t stream = NULL; | 978 | mu_stream_t stream = NULL; |
923 | size_t size = 0, lines = 0; | 979 | size_t size = 0, lines = 0; |
924 | int rc; | 980 | int rc; |
... | @@ -928,17 +984,44 @@ _frt_body (struct fetch_function_closure *ffc, | ... | @@ -928,17 +984,44 @@ _frt_body (struct fetch_function_closure *ffc, |
928 | io_sendf ("%s", ffc->name); | 984 | io_sendf ("%s", ffc->name); |
929 | else | 985 | else |
930 | fetch_send_section_part (ffc, NULL, 1); | 986 | fetch_send_section_part (ffc, NULL, 1); |
987 | mu_message_get_streamref (msg, &stream); | ||
988 | mu_message_size (msg, &size); | ||
989 | mu_message_lines (msg, &lines); | ||
990 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); | ||
991 | mu_stream_destroy (&stream); | ||
992 | return rc; | ||
993 | } | ||
994 | |||
995 | /* BODY[N] */ | ||
996 | static int | ||
997 | _frt_body_n (struct fetch_function_closure *ffc, | ||
998 | struct fetch_runtime_closure *frt) | ||
999 | { | ||
1000 | mu_message_t msg; | ||
1001 | mu_body_t body = NULL; | ||
1002 | mu_stream_t stream = NULL; | ||
1003 | size_t size = 0, lines = 0; | ||
1004 | int rc; | ||
1005 | |||
1006 | set_seen (ffc, frt); | ||
1007 | if (ffc->name) | ||
1008 | io_sendf ("%s", ffc->name); | ||
1009 | else | ||
1010 | fetch_send_section_part (ffc, ffc->section_tag, 1); | ||
931 | msg = fetch_get_part (ffc, frt); | 1011 | msg = fetch_get_part (ffc, frt); |
932 | if (!msg) | 1012 | if (!msg) |
933 | { | 1013 | { |
934 | io_sendf (" \"\""); | 1014 | io_sendf (" NIL"); |
935 | return RESP_OK; | 1015 | return RESP_OK; |
936 | } | 1016 | } |
937 | mu_message_get_streamref (msg, &stream); | 1017 | |
938 | mu_message_size (msg, &size); | 1018 | mu_message_get_body (msg, &body); |
939 | mu_message_lines (msg, &lines); | 1019 | mu_body_size (body, &size); |
1020 | mu_body_lines (body, &lines); | ||
1021 | mu_body_get_streamref (body, &stream); | ||
940 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); | 1022 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); |
941 | mu_stream_destroy (&stream); | 1023 | mu_stream_destroy (&stream); |
1024 | |||
942 | return rc; | 1025 | return rc; |
943 | } | 1026 | } |
944 | 1027 | ||
... | @@ -957,10 +1040,10 @@ _frt_body_text (struct fetch_function_closure *ffc, | ... | @@ -957,10 +1040,10 @@ _frt_body_text (struct fetch_function_closure *ffc, |
957 | io_sendf ("%s", ffc->name); | 1040 | io_sendf ("%s", ffc->name); |
958 | else | 1041 | else |
959 | fetch_send_section_part (ffc, ffc->section_tag, 1); | 1042 | fetch_send_section_part (ffc, ffc->section_tag, 1); |
960 | msg = fetch_get_part (ffc, frt); | 1043 | msg = fetch_get_part_rfc822 (ffc, frt); |
961 | if (!msg) | 1044 | if (!msg) |
962 | { | 1045 | { |
963 | io_sendf (" \"\""); | 1046 | io_sendf (" NIL"); |
964 | return RESP_OK; | 1047 | return RESP_OK; |
965 | } | 1048 | } |
966 | 1049 | ||
... | @@ -970,6 +1053,7 @@ _frt_body_text (struct fetch_function_closure *ffc, | ... | @@ -970,6 +1053,7 @@ _frt_body_text (struct fetch_function_closure *ffc, |
970 | mu_body_get_streamref (body, &stream); | 1053 | mu_body_get_streamref (body, &stream); |
971 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); | 1054 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); |
972 | mu_stream_destroy (&stream); | 1055 | mu_stream_destroy (&stream); |
1056 | mu_message_unref (msg); | ||
973 | return rc; | 1057 | return rc; |
974 | } | 1058 | } |
975 | 1059 | ||
... | @@ -1002,10 +1086,42 @@ _frt_header (struct fetch_function_closure *ffc, | ... | @@ -1002,10 +1086,42 @@ _frt_header (struct fetch_function_closure *ffc, |
1002 | else | 1086 | else |
1003 | fetch_send_section_part (ffc, ffc->section_tag, 1); | 1087 | fetch_send_section_part (ffc, ffc->section_tag, 1); |
1004 | 1088 | ||
1089 | msg = fetch_get_part_rfc822 (ffc, frt); | ||
1090 | if (!msg) | ||
1091 | { | ||
1092 | io_sendf (" NIL"); | ||
1093 | return RESP_OK; | ||
1094 | } | ||
1095 | mu_message_get_header (msg, &header); | ||
1096 | mu_header_size (header, &size); | ||
1097 | mu_header_lines (header, &lines); | ||
1098 | mu_header_get_streamref (header, &stream); | ||
1099 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); | ||
1100 | mu_stream_destroy (&stream); | ||
1101 | mu_message_unref (msg); | ||
1102 | return rc; | ||
1103 | } | ||
1104 | |||
1105 | static int | ||
1106 | _frt_mime (struct fetch_function_closure *ffc, | ||
1107 | struct fetch_runtime_closure *frt) | ||
1108 | { | ||
1109 | mu_message_t msg; | ||
1110 | mu_header_t header = NULL; | ||
1111 | mu_stream_t stream = NULL; | ||
1112 | size_t size = 0, lines = 0; | ||
1113 | int rc; | ||
1114 | |||
1115 | set_seen (ffc, frt); | ||
1116 | if (ffc->name) | ||
1117 | io_sendf ("%s", ffc->name); | ||
1118 | else | ||
1119 | fetch_send_section_part (ffc, ffc->section_tag, 1); | ||
1120 | |||
1005 | msg = fetch_get_part (ffc, frt); | 1121 | msg = fetch_get_part (ffc, frt); |
1006 | if (!msg) | 1122 | if (!msg) |
1007 | { | 1123 | { |
1008 | io_sendf (" \"\""); | 1124 | io_sendf (" NIL"); |
1009 | return RESP_OK; | 1125 | return RESP_OK; |
1010 | } | 1126 | } |
1011 | mu_message_get_header (msg, &header); | 1127 | mu_message_get_header (msg, &header); |
... | @@ -1014,6 +1130,7 @@ _frt_header (struct fetch_function_closure *ffc, | ... | @@ -1014,6 +1130,7 @@ _frt_header (struct fetch_function_closure *ffc, |
1014 | mu_header_get_streamref (header, &stream); | 1130 | mu_header_get_streamref (header, &stream); |
1015 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); | 1131 | rc = fetch_io (stream, ffc->start, ffc->size, size + lines); |
1016 | mu_stream_destroy (&stream); | 1132 | mu_stream_destroy (&stream); |
1133 | |||
1017 | return rc; | 1134 | return rc; |
1018 | } | 1135 | } |
1019 | 1136 | ||
... | @@ -1060,10 +1177,10 @@ _frt_header_fields (struct fetch_function_closure *ffc, | ... | @@ -1060,10 +1177,10 @@ _frt_header_fields (struct fetch_function_closure *ffc, |
1060 | mu_list_foreach (ffc->headers, _send_header_name, &status); | 1177 | mu_list_foreach (ffc->headers, _send_header_name, &status); |
1061 | io_sendf (")]"); | 1178 | io_sendf (")]"); |
1062 | 1179 | ||
1063 | msg = fetch_get_part (ffc, frt); | 1180 | msg = fetch_get_part_rfc822 (ffc, frt); |
1064 | if (!msg) | 1181 | if (!msg) |
1065 | { | 1182 | { |
1066 | io_sendf (" \"\""); | 1183 | io_sendf (" NIL"); |
1067 | return RESP_OK; | 1184 | return RESP_OK; |
1068 | } | 1185 | } |
1069 | 1186 | ||
... | @@ -1071,7 +1188,8 @@ _frt_header_fields (struct fetch_function_closure *ffc, | ... | @@ -1071,7 +1188,8 @@ _frt_header_fields (struct fetch_function_closure *ffc, |
1071 | if (mu_message_get_header (msg, &header) | 1188 | if (mu_message_get_header (msg, &header) |
1072 | || mu_header_get_iterator (header, &itr)) | 1189 | || mu_header_get_iterator (header, &itr)) |
1073 | { | 1190 | { |
1074 | io_sendf (" \"\""); | 1191 | mu_message_unref (msg); |
1192 | io_sendf (" NIL"); | ||
1075 | return RESP_OK; | 1193 | return RESP_OK; |
1076 | } | 1194 | } |
1077 | 1195 | ||
... | @@ -1109,6 +1227,7 @@ _frt_header_fields (struct fetch_function_closure *ffc, | ... | @@ -1109,6 +1227,7 @@ _frt_header_fields (struct fetch_function_closure *ffc, |
1109 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 1227 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); |
1110 | status = fetch_io (stream, ffc->start, ffc->size, size + lines); | 1228 | status = fetch_io (stream, ffc->start, ffc->size, size + lines); |
1111 | mu_stream_destroy (&stream); | 1229 | mu_stream_destroy (&stream); |
1230 | mu_message_unref (msg); | ||
1112 | 1231 | ||
1113 | return status; | 1232 | return status; |
1114 | } | 1233 | } |
... | @@ -1347,7 +1466,7 @@ parse_section_text (imap4d_parsebuf_t p, struct fetch_function_closure *ffc, | ... | @@ -1347,7 +1466,7 @@ parse_section_text (imap4d_parsebuf_t p, struct fetch_function_closure *ffc, |
1347 | else if (allow_mime && mu_c_strcasecmp (p->token, "MIME") == 0) | 1466 | else if (allow_mime && mu_c_strcasecmp (p->token, "MIME") == 0) |
1348 | { | 1467 | { |
1349 | imap4d_parsebuf_next (p, 1); | 1468 | imap4d_parsebuf_next (p, 1); |
1350 | ffc->fun = _frt_header; | 1469 | ffc->fun = _frt_mime; |
1351 | ffc->section_tag = "MIME"; | 1470 | ffc->section_tag = "MIME"; |
1352 | } | 1471 | } |
1353 | else | 1472 | else |
... | @@ -1436,6 +1555,8 @@ parse_section (imap4d_parsebuf_t p, struct fetch_function_closure *ffc) | ... | @@ -1436,6 +1555,8 @@ parse_section (imap4d_parsebuf_t p, struct fetch_function_closure *ffc) |
1436 | imap4d_parsebuf_next (p, 1); | 1555 | imap4d_parsebuf_next (p, 1); |
1437 | parse_section_text (p, ffc, 1); | 1556 | parse_section_text (p, ffc, 1); |
1438 | } | 1557 | } |
1558 | else | ||
1559 | ffc->fun = _frt_body_n; | ||
1439 | } | 1560 | } |
1440 | else | 1561 | else |
1441 | imap4d_parsebuf_exit (p, "Syntax error"); | 1562 | imap4d_parsebuf_exit (p, "Syntax error"); | ... | ... |
... | @@ -340,65 +340,6 @@ imap4d_test "FETCH 4 BODY\[2.2.1\]"\ | ... | @@ -340,65 +340,6 @@ imap4d_test "FETCH 4 BODY\[2.2.1\]"\ |
340 | ")"\ | 340 | ")"\ |
341 | "OK" | 341 | "OK" |
342 | 342 | ||
343 | imap4d_test "FETCH 4 BODY\[2.2.1.TEXT\]"\ | ||
344 | "4 FETCH (BODY\[2.2.1.TEXT\] {490}"\ | ||
345 | -literal\ | ||
346 | "YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBhbmQgeW91ciBqYXdzIGFyZSB0b28gd2Vh"\ | ||
347 | "awpGb3IgYW55dGhpbmcgdG91Z2hlciB0aGFuIHN1ZXQ7CllldCB5b3UgZmluaXNoZWQgdGhlIGdv"\ | ||
348 | "b3NlLCB3aXRoIHRoZSBib25lcyBhbmQgdGhlIGJlYWstLQpQcmF5IGhvdyBkaWQgeW91IG1hbmFn"\ | ||
349 | "ZSB0byBkbyBpdD8nCgpgSW4gbXkgeW91dGgsJyBzYWlkIGhpcyBmYXRoZXIsIGBJIHRvb2sgdG8g"\ | ||
350 | "dGhlIGxhdywKQW5kIGFyZ3VlZCBlYWNoIGNhc2Ugd2l0aCBteSB3aWZlOwpBbmQgdGhlIG11c2N1"\ | ||
351 | "bGFyIHN0cmVuZ3RoLCB3aGljaCBpdCBnYXZlIHRvIG15IGphdywKSGFzIGxhc3RlZCB0aGUgcmVz"\ | ||
352 | "dCBvZiBteSBsaWZlLicK"\ | ||
353 | ")"\ | ||
354 | "OK" | ||
355 | |||
356 | imap4d_test "FETCH 4 BODY\[2.2.TEXT\]"\ | ||
357 | "4 FETCH (BODY\[2.2.TEXT\] {1432}"\ | ||
358 | -literal\ | ||
359 | -- "------- =_aaaaaaaaaa2"\ | ||
360 | "Content-Type: application/octet-stream; name=\"msg.23\""\ | ||
361 | "Content-ID: <5122.1026510654.6@example.net>"\ | ||
362 | "Content-Description: Father William Part III"\ | ||
363 | "Content-Transfer-Encoding: base64"\ | ||
364 | ""\ | ||
365 | "YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBhbmQgeW91ciBqYXdzIGFyZSB0b28gd2Vh"\ | ||
366 | "awpGb3IgYW55dGhpbmcgdG91Z2hlciB0aGFuIHN1ZXQ7CllldCB5b3UgZmluaXNoZWQgdGhlIGdv"\ | ||
367 | "b3NlLCB3aXRoIHRoZSBib25lcyBhbmQgdGhlIGJlYWstLQpQcmF5IGhvdyBkaWQgeW91IG1hbmFn"\ | ||
368 | "ZSB0byBkbyBpdD8nCgpgSW4gbXkgeW91dGgsJyBzYWlkIGhpcyBmYXRoZXIsIGBJIHRvb2sgdG8g"\ | ||
369 | "dGhlIGxhdywKQW5kIGFyZ3VlZCBlYWNoIGNhc2Ugd2l0aCBteSB3aWZlOwpBbmQgdGhlIG11c2N1"\ | ||
370 | "bGFyIHN0cmVuZ3RoLCB3aGljaCBpdCBnYXZlIHRvIG15IGphdywKSGFzIGxhc3RlZCB0aGUgcmVz"\ | ||
371 | "dCBvZiBteSBsaWZlLicK"\ | ||
372 | ""\ | ||
373 | -- "------- =_aaaaaaaaaa2"\ | ||
374 | "Content-Type: application/octet-stream; name=\"msg.24\""\ | ||
375 | "Content-ID: <5122.1026510654.7@example.net>"\ | ||
376 | "Content-Description: Father William Part IV"\ | ||
377 | "Content-Transfer-Encoding: base64"\ | ||
378 | ""\ | ||
379 | "YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBvbmUgd291bGQgaGFyZGx5IHN1cHBvc2UK"\ | ||
380 | "VGhhdCB5b3VyIGV5ZSB3YXMgYXMgc3RlYWR5IGFzIGV2ZXI7CllldCB5b3UgYmFsYW5jZWQgYW4g"\ | ||
381 | "ZWVsIG9uIHRoZSBlbmQgb2YgeW91ciBub3NlLS0KV2hhdCBtYWRlIHlvdSBzbyBhd2Z1bGx5IGNs"\ | ||
382 | "ZXZlcj8nCgpgSSBoYXZlIGFuc3dlcmVkIHRocmVlIHF1ZXN0aW9ucywgYW5kIHRoYXQgaXMgZW5v"\ | ||
383 | "dWdoLCcKU2FpZCBoaXMgZmF0aGVyOyBgZG9uJ3QgZ2l2ZSB5b3Vyc2VsZiBhaXJzIQpEbyB5b3Ug"\ | ||
384 | "dGhpbmsgSSBjYW4gbGlzdGVuIGFsbCBkYXkgdG8gc3VjaCBzdHVmZj8KQmUgb2ZmLCBvciBJJ2xs"\ | ||
385 | "IGtpY2sgeW91IGRvd24gc3RhaXJzIScK"\ | ||
386 | ""\ | ||
387 | -- "------- =_aaaaaaaaaa2--"\ | ||
388 | ")"\ | ||
389 | "OK" | ||
390 | |||
391 | imap4d_test "FETCH 5 BODY\[1.TEXT\]"\ | ||
392 | "5 FETCH (FLAGS (\\Seen) BODY\[1.TEXT\] \"\")"\ | ||
393 | "OK" | ||
394 | |||
395 | imap4d_test "FETCH 5 BODY\[2.TEXT\]"\ | ||
396 | "5 FETCH (BODY\[2.TEXT\] {2}"\ | ||
397 | -literal\ | ||
398 | ""\ | ||
399 | ")"\ | ||
400 | "OK" | ||
401 | |||
402 | ############### | 343 | ############### |
403 | # Test RFC822 operations | 344 | # Test RFC822 operations |
404 | 345 | ... | ... |
-
Please register or sign in to post a comment