Commit 30594fa8 30594fa89df0ffbfb40644ef7fec819511dae6eb by Sergey Poznyakoff

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.
1 parent 9a400bf9
...@@ -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
......