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,
return msg;
}
static mu_message_t
fetch_get_part_rfc822 (struct fetch_function_closure *ffc,
struct fetch_runtime_closure *frt)
{
mu_message_t msg = frt->msg, retmsg = NULL;
size_t i;
mu_header_t header;
const char *hval;
if (ffc->nset == 0)
{
mu_message_ref (msg);
return msg;
}
for (i = 0; i < ffc->nset; i++)
if (mu_message_get_part (msg, ffc->section_part[i], &msg))
return NULL;
if (mu_message_get_header (msg, &header))
return NULL;
if (mu_header_sget_value (header, MU_HEADER_CONTENT_TYPE, &hval) == 0)
{
struct mu_wordsplit ws;
int rc;
ws.ws_delim = " \t\r\n;=";
ws.ws_alloc_die = imap4d_ws_alloc_die;
if (mu_wordsplit (hval, &ws, IMAP4D_WS_FLAGS))
{
mu_error (_("%s failed: %s"), "mu_wordsplit",
mu_wordsplit_strerror (&ws));
return NULL;
}
rc = mu_c_strcasecmp (ws.ws_wordv[0], "MESSAGE/RFC822");
mu_wordsplit_free (&ws);
if (rc == 0)
{
mu_body_t body;
mu_stream_t str;
if (mu_message_get_body (msg, &body) ||
mu_body_get_streamref (body, &str))
return NULL;
rc = mu_stream_to_message (str, &retmsg);
mu_stream_unref (str);
}
}
return retmsg;
}
static void
fetch_send_section_part (struct fetch_function_closure *ffc,
const char *suffix, int close_bracket)
......@@ -918,7 +974,7 @@ static int
_frt_body (struct fetch_function_closure *ffc,
struct fetch_runtime_closure *frt)
{
mu_message_t msg;
mu_message_t msg = frt->msg;
mu_stream_t stream = NULL;
size_t size = 0, lines = 0;
int rc;
......@@ -928,17 +984,44 @@ _frt_body (struct fetch_function_closure *ffc,
io_sendf ("%s", ffc->name);
else
fetch_send_section_part (ffc, NULL, 1);
mu_message_get_streamref (msg, &stream);
mu_message_size (msg, &size);
mu_message_lines (msg, &lines);
rc = fetch_io (stream, ffc->start, ffc->size, size + lines);
mu_stream_destroy (&stream);
return rc;
}
/* BODY[N] */
static int
_frt_body_n (struct fetch_function_closure *ffc,
struct fetch_runtime_closure *frt)
{
mu_message_t msg;
mu_body_t body = NULL;
mu_stream_t stream = NULL;
size_t size = 0, lines = 0;
int rc;
set_seen (ffc, frt);
if (ffc->name)
io_sendf ("%s", ffc->name);
else
fetch_send_section_part (ffc, ffc->section_tag, 1);
msg = fetch_get_part (ffc, frt);
if (!msg)
{
io_sendf (" \"\"");
io_sendf (" NIL");
return RESP_OK;
}
mu_message_get_streamref (msg, &stream);
mu_message_size (msg, &size);
mu_message_lines (msg, &lines);
mu_message_get_body (msg, &body);
mu_body_size (body, &size);
mu_body_lines (body, &lines);
mu_body_get_streamref (body, &stream);
rc = fetch_io (stream, ffc->start, ffc->size, size + lines);
mu_stream_destroy (&stream);
return rc;
}
......@@ -957,10 +1040,10 @@ _frt_body_text (struct fetch_function_closure *ffc,
io_sendf ("%s", ffc->name);
else
fetch_send_section_part (ffc, ffc->section_tag, 1);
msg = fetch_get_part (ffc, frt);
msg = fetch_get_part_rfc822 (ffc, frt);
if (!msg)
{
io_sendf (" \"\"");
io_sendf (" NIL");
return RESP_OK;
}
......@@ -970,6 +1053,7 @@ _frt_body_text (struct fetch_function_closure *ffc,
mu_body_get_streamref (body, &stream);
rc = fetch_io (stream, ffc->start, ffc->size, size + lines);
mu_stream_destroy (&stream);
mu_message_unref (msg);
return rc;
}
......@@ -1002,10 +1086,42 @@ _frt_header (struct fetch_function_closure *ffc,
else
fetch_send_section_part (ffc, ffc->section_tag, 1);
msg = fetch_get_part_rfc822 (ffc, frt);
if (!msg)
{
io_sendf (" NIL");
return RESP_OK;
}
mu_message_get_header (msg, &header);
mu_header_size (header, &size);
mu_header_lines (header, &lines);
mu_header_get_streamref (header, &stream);
rc = fetch_io (stream, ffc->start, ffc->size, size + lines);
mu_stream_destroy (&stream);
mu_message_unref (msg);
return rc;
}
static int
_frt_mime (struct fetch_function_closure *ffc,
struct fetch_runtime_closure *frt)
{
mu_message_t msg;
mu_header_t header = NULL;
mu_stream_t stream = NULL;
size_t size = 0, lines = 0;
int rc;
set_seen (ffc, frt);
if (ffc->name)
io_sendf ("%s", ffc->name);
else
fetch_send_section_part (ffc, ffc->section_tag, 1);
msg = fetch_get_part (ffc, frt);
if (!msg)
{
io_sendf (" \"\"");
io_sendf (" NIL");
return RESP_OK;
}
mu_message_get_header (msg, &header);
......@@ -1014,6 +1130,7 @@ _frt_header (struct fetch_function_closure *ffc,
mu_header_get_streamref (header, &stream);
rc = fetch_io (stream, ffc->start, ffc->size, size + lines);
mu_stream_destroy (&stream);
return rc;
}
......@@ -1060,10 +1177,10 @@ _frt_header_fields (struct fetch_function_closure *ffc,
mu_list_foreach (ffc->headers, _send_header_name, &status);
io_sendf (")]");
msg = fetch_get_part (ffc, frt);
msg = fetch_get_part_rfc822 (ffc, frt);
if (!msg)
{
io_sendf (" \"\"");
io_sendf (" NIL");
return RESP_OK;
}
......@@ -1071,7 +1188,8 @@ _frt_header_fields (struct fetch_function_closure *ffc,
if (mu_message_get_header (msg, &header)
|| mu_header_get_iterator (header, &itr))
{
io_sendf (" \"\"");
mu_message_unref (msg);
io_sendf (" NIL");
return RESP_OK;
}
......@@ -1109,6 +1227,7 @@ _frt_header_fields (struct fetch_function_closure *ffc,
mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
status = fetch_io (stream, ffc->start, ffc->size, size + lines);
mu_stream_destroy (&stream);
mu_message_unref (msg);
return status;
}
......@@ -1347,7 +1466,7 @@ parse_section_text (imap4d_parsebuf_t p, struct fetch_function_closure *ffc,
else if (allow_mime && mu_c_strcasecmp (p->token, "MIME") == 0)
{
imap4d_parsebuf_next (p, 1);
ffc->fun = _frt_header;
ffc->fun = _frt_mime;
ffc->section_tag = "MIME";
}
else
......@@ -1436,6 +1555,8 @@ parse_section (imap4d_parsebuf_t p, struct fetch_function_closure *ffc)
imap4d_parsebuf_next (p, 1);
parse_section_text (p, ffc, 1);
}
else
ffc->fun = _frt_body_n;
}
else
imap4d_parsebuf_exit (p, "Syntax error");
......
......@@ -340,65 +340,6 @@ imap4d_test "FETCH 4 BODY\[2.2.1\]"\
")"\
"OK"
imap4d_test "FETCH 4 BODY\[2.2.1.TEXT\]"\
"4 FETCH (BODY\[2.2.1.TEXT\] {490}"\
-literal\
"YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBhbmQgeW91ciBqYXdzIGFyZSB0b28gd2Vh"\
"awpGb3IgYW55dGhpbmcgdG91Z2hlciB0aGFuIHN1ZXQ7CllldCB5b3UgZmluaXNoZWQgdGhlIGdv"\
"b3NlLCB3aXRoIHRoZSBib25lcyBhbmQgdGhlIGJlYWstLQpQcmF5IGhvdyBkaWQgeW91IG1hbmFn"\
"ZSB0byBkbyBpdD8nCgpgSW4gbXkgeW91dGgsJyBzYWlkIGhpcyBmYXRoZXIsIGBJIHRvb2sgdG8g"\
"dGhlIGxhdywKQW5kIGFyZ3VlZCBlYWNoIGNhc2Ugd2l0aCBteSB3aWZlOwpBbmQgdGhlIG11c2N1"\
"bGFyIHN0cmVuZ3RoLCB3aGljaCBpdCBnYXZlIHRvIG15IGphdywKSGFzIGxhc3RlZCB0aGUgcmVz"\
"dCBvZiBteSBsaWZlLicK"\
")"\
"OK"
imap4d_test "FETCH 4 BODY\[2.2.TEXT\]"\
"4 FETCH (BODY\[2.2.TEXT\] {1432}"\
-literal\
-- "------- =_aaaaaaaaaa2"\
"Content-Type: application/octet-stream; name=\"msg.23\""\
"Content-ID: <5122.1026510654.6@example.net>"\
"Content-Description: Father William Part III"\
"Content-Transfer-Encoding: base64"\
""\
"YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBhbmQgeW91ciBqYXdzIGFyZSB0b28gd2Vh"\
"awpGb3IgYW55dGhpbmcgdG91Z2hlciB0aGFuIHN1ZXQ7CllldCB5b3UgZmluaXNoZWQgdGhlIGdv"\
"b3NlLCB3aXRoIHRoZSBib25lcyBhbmQgdGhlIGJlYWstLQpQcmF5IGhvdyBkaWQgeW91IG1hbmFn"\
"ZSB0byBkbyBpdD8nCgpgSW4gbXkgeW91dGgsJyBzYWlkIGhpcyBmYXRoZXIsIGBJIHRvb2sgdG8g"\
"dGhlIGxhdywKQW5kIGFyZ3VlZCBlYWNoIGNhc2Ugd2l0aCBteSB3aWZlOwpBbmQgdGhlIG11c2N1"\
"bGFyIHN0cmVuZ3RoLCB3aGljaCBpdCBnYXZlIHRvIG15IGphdywKSGFzIGxhc3RlZCB0aGUgcmVz"\
"dCBvZiBteSBsaWZlLicK"\
""\
-- "------- =_aaaaaaaaaa2"\
"Content-Type: application/octet-stream; name=\"msg.24\""\
"Content-ID: <5122.1026510654.7@example.net>"\
"Content-Description: Father William Part IV"\
"Content-Transfer-Encoding: base64"\
""\
"YFlvdSBhcmUgb2xkLCcgc2FpZCB0aGUgeW91dGgsIGBvbmUgd291bGQgaGFyZGx5IHN1cHBvc2UK"\
"VGhhdCB5b3VyIGV5ZSB3YXMgYXMgc3RlYWR5IGFzIGV2ZXI7CllldCB5b3UgYmFsYW5jZWQgYW4g"\
"ZWVsIG9uIHRoZSBlbmQgb2YgeW91ciBub3NlLS0KV2hhdCBtYWRlIHlvdSBzbyBhd2Z1bGx5IGNs"\
"ZXZlcj8nCgpgSSBoYXZlIGFuc3dlcmVkIHRocmVlIHF1ZXN0aW9ucywgYW5kIHRoYXQgaXMgZW5v"\
"dWdoLCcKU2FpZCBoaXMgZmF0aGVyOyBgZG9uJ3QgZ2l2ZSB5b3Vyc2VsZiBhaXJzIQpEbyB5b3Ug"\
"dGhpbmsgSSBjYW4gbGlzdGVuIGFsbCBkYXkgdG8gc3VjaCBzdHVmZj8KQmUgb2ZmLCBvciBJJ2xs"\
"IGtpY2sgeW91IGRvd24gc3RhaXJzIScK"\
""\
-- "------- =_aaaaaaaaaa2--"\
")"\
"OK"
imap4d_test "FETCH 5 BODY\[1.TEXT\]"\
"5 FETCH (FLAGS (\\Seen) BODY\[1.TEXT\] \"\")"\
"OK"
imap4d_test "FETCH 5 BODY\[2.TEXT\]"\
"5 FETCH (BODY\[2.TEXT\] {2}"\
-literal\
""\
")"\
"OK"
###############
# Test RFC822 operations
......