summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-11-23 21:54:28 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-11-23 21:54:28 +0200
commit78132d34760448ad268a92908b2a75f6394f6fec (patch)
treed18ddaf794ff38bcbc0c58167c32b95e307140d3
parenta0b4f3b1203503ba7e8f8d545d16fa77d740e4e7 (diff)
downloadmailutils-78132d34760448ad268a92908b2a75f6394f6fec.tar.gz
mailutils-78132d34760448ad268a92908b2a75f6394f6fec.tar.bz2
MIME: part boundary in not required to be followed by a newlie.
* libmailutils/mime/mime.c: Part boundary can be eitherr followd by a newline, or appear at the very end of input. * testsuite/Makefile.am: Add mime01.at * testsuite/testsuite.at: Include mime01.at. * testsuite/mime01.at: New file. * testsuite/mime.at: Update expected output. Don't filter output through tr & sed. * testsuite/mimetest.c: Change output to make sure no trailing whitespace could be produced.
-rw-r--r--libmailutils/mime/mime.c134
-rw-r--r--testsuite/Makefile.am1
-rw-r--r--testsuite/mime.at109
-rw-r--r--testsuite/mime01.at130
-rw-r--r--testsuite/mimetest.c20
-rw-r--r--testsuite/testsuite.at1
6 files changed, 269 insertions, 126 deletions
diff --git a/libmailutils/mime/mime.c b/libmailutils/mime/mime.c
index e4463d307..123a8642c 100644
--- a/libmailutils/mime/mime.c
+++ b/libmailutils/mime/mime.c
@@ -260,7 +260,7 @@ _mime_append_header_line (mu_mime_t mime)
static int
_mime_parse_mpart_message (mu_mime_t mime)
{
- char *cp, *cp2;
+ char *cp;
size_t blength, mb_length, mb_offset, mb_lines;
int ret;
size_t nbytes;
@@ -294,9 +294,76 @@ _mime_parse_mpart_message (mu_mime_t mime)
&nbytes)) == 0 && nbytes)
{
cp = mime->cur_buf;
- while (nbytes)
+
+ while (1)
{
mime->cur_line[mime->line_ndx] = *cp;
+ if (mime->parser_state == MIME_STATE_SCAN_BOUNDARY
+ && (nbytes == 0 || *cp == '\n'))
+ {
+ char *cp2 = mime->cur_line[0] == '\n'
+ ? mime->cur_line + 1 : mime->cur_line;
+ if (mime->line_ndx >= blength
+ && ((memcmp (cp2, "--", 2) == 0
+ && memcmp (cp2 + 2, mime->boundary, blength) == 0)
+ || memcmp (cp2, mime->boundary, blength) == 0))
+ {
+ mime->parser_state = MIME_STATE_HEADERS;
+ mime->flags &= ~MIME_PARSER_HAVE_CR;
+ mb_length = mime->cur_offset
+ - mb_offset
+ - mime->line_ndx;
+ if (mime->header_length)
+ /* this skips the preamble */
+ {
+ /* RFC 1521 [Page 30]:
+ NOTE: The CRLF preceding the encapsulation
+ line is conceptually attached to the boundary
+ so that it is possible to have a part that
+ does not end with a CRLF (line break). Body
+ parts that must be considered to end with line
+ breaks, therefore, must have two CRLFs
+ preceding the encapsulation line, the first
+ of which is part of the preceding body part,
+ and the second of which is part of the
+ encapsulation boundary. */
+
+ if (mb_lines)
+ /* to prevent negative values in case of a
+ malformed message */
+ mb_lines--;
+
+ _mime_append_part (mime, NULL,
+ mb_offset, mb_length,
+ mb_lines);
+ }
+
+ if ((&mime->cur_line[mime->line_ndx] - cp2 - 1 > blength
+ && memcmp (cp2 + blength + 2, "--", 2) == 0)
+ || (&mime->cur_line[mime->line_ndx] - cp2 - 1 == blength
+ && memcmp (cp2 + blength, "--", 2) == 0))
+ { /* last boundary */
+ mime->parser_state = MIME_STATE_BEGIN_LINE;
+ mime->header_length = 0;
+ }
+ else
+ mime->line_ndx = -1; /* headers parsing requires
+ empty line */
+ }
+ else if (nbytes)
+ {
+ if (mime->header_length)
+ mb_lines++;
+
+ mime->line_ndx = 0;
+ mime->cur_line[0] = *cp; /* stay in this state but
+ leave '\n' at begining */
+ }
+ }
+
+ if (nbytes == 0)
+ break;
+
if (*cp == '\n')
{
switch (mime->parser_state)
@@ -308,68 +375,6 @@ _mime_parse_mpart_message (mu_mime_t mime)
break;
case MIME_STATE_SCAN_BOUNDARY:
- cp2 = mime->cur_line[0] == '\n'
- ? mime->cur_line + 1 : mime->cur_line;
- if (mime->line_ndx >= blength)
- {
- if ((!strncmp (cp2, "--", 2)
- && !mu_c_strncasecmp (cp2 + 2, mime->boundary,
- blength))
- || !mu_c_strncasecmp (cp2, mime->boundary, blength))
- {
- mime->parser_state = MIME_STATE_HEADERS;
- mime->flags &= ~MIME_PARSER_HAVE_CR;
- mb_length = mime->cur_offset
- - mb_offset
- - mime->line_ndx;
- if (mime->header_length)
- /* this skips the preamble */
- {
- /* RFC 1521 [Page 30]:
- NOTE: The CRLF preceding the encapsulation
- line is conceptually attached to the boundary
- so that it is possible to have a part that
- does not end with a CRLF (line break). Body
- parts that must be considered to end with line
- breaks, therefore, must have two CRLFs
- preceding the encapsulation line, the first
- of which is part of the preceding body part,
- and the second of which is part of the
- encapsulation boundary. */
-
- if (mb_lines)
- /* to prevent negative values in case of a
- malformed message */
- mb_lines--;
-
- _mime_append_part (mime, NULL,
- mb_offset, mb_length,
- mb_lines);
- }
-
- if ((&mime->cur_line[mime->line_ndx] - cp2 - 1 >
- blength
- && !strncmp (cp2 + blength + 2, "--", 2))
- || (&mime->cur_line[mime->line_ndx] - cp2 - 1 ==
- blength
- && !strncmp (cp2 + blength, "--", 2)))
- { /* last boundary */
- mime->parser_state = MIME_STATE_BEGIN_LINE;
- mime->header_length = 0;
- }
- else
- mime->line_ndx = -1; /* headers parsing requires
- empty line */
- break;
- }
- }
-
- if (mime->header_length)
- mb_lines++;
-
- mime->line_ndx = 0;
- mime->cur_line[0] = *cp; /* stay in this state but
- leave '\n' at begining */
break;
case MIME_STATE_HEADERS:
@@ -385,6 +390,7 @@ _mime_parse_mpart_message (mu_mime_t mime)
break;
}
}
+
mime->line_ndx++;
if (mime->line_ndx >= mime->line_size)
{
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index e0eeba031..42e73dd63 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -91,6 +91,7 @@ TESTSUITE_AT = \
lstuid02.at\
mbdel.at\
mime.at\
+ mime01.at\
smtp-msg.at\
smtp-str.at\
ufms.at\
diff --git a/testsuite/mime.at b/testsuite/mime.at
index 872002cf0..0afadec0d 100644
--- a/testsuite/mime.at
+++ b/testsuite/mime.at
@@ -18,16 +18,15 @@ AT_SETUP([mime])
# FIXME: Mimetest should probably be fixed to avoid the use of `tr'
# and `sed' here.
-AT_CHECK([mimetest -i 0 -p $abs_top_srcdir/testsuite/spool/mbox1 | dnl
- tr '\t' ' ' | sed 's/ *$//'],
+AT_CHECK([mimetest -i 0 -p $abs_top_srcdir/testsuite/spool/mbox1],
[0],
-[Message: 1
-From: Foo Bar <foobar@nonexistent.net>
-Subject: Jabberwocky
-Number of parts in message - 1
-Total message size - 1254/44
-Type of part 1 =
-Message part size - 1254/44: 317/9, 937/35
+[Message:1
+From:Foo Bar <foobar@nonexistent.net>
+Subject:Jabberwocky
+Number of parts in message:1
+Total message size:1254/44
+Type of part 1:
+Message part size:1254/44: 317/9, 937/35
Text Message
Begin
`Twas brillig, and the slithy toves
@@ -67,13 +66,13 @@ And the mome raths outgrabe.
End
-Message: 2
-From: Bar <bar@dontmailme.org>
-Subject: Re: Jabberwocky
-Number of parts in message - 1
-Total message size - 534/13
-Type of part 1 =
-Message part size - 534/13: 319/9, 215/4
+Message:2
+From:Bar <bar@dontmailme.org>
+Subject:Re: Jabberwocky
+Number of parts in message:1
+Total message size:534/13
+Type of part 1:
+Message part size:534/13: 319/9, 215/4
Text Message
Begin
It seems very pretty, but it's *rather* hard to understand!'
@@ -82,13 +81,13 @@ exactly know what they are! However, SOMEBODY killed SOMETHING:
that's clear, at any rate...
End
-Message: 3
-From: Sergey Poznyakoff <gray@example.net>
-Subject: Simple MIME
-Number of parts in message - 2
-Total message size - 1569/42
-Type of part 1 = text/plain
-Message part size - 364/13: 134/4, 230/9
+Message:3
+From:Sergey Poznyakoff <gray@example.net>
+Subject:Simple MIME
+Number of parts in message:2
+Total message size:1569/42
+Type of part 1:text/plain
+Message part size:364/13: 134/4, 230/9
Text Message
Begin
How doth the little crocodile
@@ -102,8 +101,8 @@ And welcome little fishes in
With gently smiling jaws!
End
-Type of part 2 = application/octet-stream
-Message part size - 638/11: 176/5, 462/6
+Type of part 2:application/octet-stream
+Message part size:638/11: 176/5, 462/6
Attachment - saving [[msg.21]]
Begin
`You are old, Father William,' the young man said,
@@ -118,13 +117,13 @@ Why, I do it again and again.'
End
-Message: 4
-From: Sergey Poznyakoff <gray@example.net>
-Subject: Nested MIME
-Number of parts in message - 2
-Total message size - 3399/84
-Type of part 1 = text/plain
-Message part size - 489/14: 148/4, 341/10
+Message:4
+From:Sergey Poznyakoff <gray@example.net>
+Subject:Nested MIME
+Number of parts in message:2
+Total message size:3399/84
+Type of part 1:text/plain
+Message part size:489/14: 148/4, 341/10
Text Message
Begin
`You are old, Father William,' the young man said,
@@ -139,12 +138,14 @@ Why, I do it again and again.'
End
-Type of part 2 = multipart/mixed
-Message part size - 2343/52: 107/3, 2236/49
-Encapsulated message :
+Type of part 2:multipart/mixed
+Message part size:2343/52: 107/3, 2236/49
+Encapsulated message:
+From:
+Subject:
Begin
-Type of part 1 = application/octet-stream
-Message part size - 656/12: 177/5, 479/7
+Type of part 1:application/octet-stream
+Message part size:656/12: 177/5, 479/7
Attachment - saving [[msg.22]]
Begin
`You are old,' said the youth, `as I mentioned before,
@@ -158,12 +159,14 @@ By the use of this ointment--one shilling the box--
Allow me to sell you a couple?'
End
-Type of part 2 = multipart/mixed
-Message part size - 1510/32: 107/3, 1403/29
-Encapsulated message :
+Type of part 2:multipart/mixed
+Message part size:1510/32: 107/3, 1403/29
+Encapsulated message:
+From:
+Subject:
Begin
-Type of part 1 = application/octet-stream
-Message part size - 661/12: 178/5, 483/7
+Type of part 1:application/octet-stream
+Message part size:661/12: 178/5, 483/7
Attachment - saving [[msg.23]]
Begin
`You are old,' said the youth, `and your jaws are too weak
@@ -177,8 +180,8 @@ And the muscular strength, which it gave to my jaw,
Has lasted the rest of my life.'
End
-Type of part 2 = application/octet-stream
-Message part size - 672/12: 177/5, 495/7
+Type of part 2:application/octet-stream
+Message part size:672/12: 177/5, 495/7
Attachment - saving [[msg.24]]
Begin
`You are old,' said the youth, `one would hardly suppose
@@ -196,19 +199,19 @@ End
End
End
-Message: 5
-From: Sergey Poznyakoff <gray@example.net>
-Subject: Empty MIME Parts
-Number of parts in message - 2
-Total message size - 857/27
-Type of part 1 = text/plain
-Message part size - 136/4: 136/4, 0/0
+Message:5
+From:Sergey Poznyakoff <gray@example.net>
+Subject:Empty MIME Parts
+Number of parts in message:2
+Total message size:857/27
+Type of part 1:text/plain
+Message part size:136/4: 136/4, 0/0
Text Message
Begin
End
-Type of part 2 = text/plain
-Message part size - 149/5: 148/4, 1/1
+Type of part 2:text/plain
+Message part size:149/5: 148/4, 1/1
Text Message
Begin
diff --git a/testsuite/mime01.at b/testsuite/mime01.at
new file mode 100644
index 000000000..f82a16de7
--- /dev/null
+++ b/testsuite/mime01.at
@@ -0,0 +1,130 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([mime - adjacent closing delimiters])
+AT_DATA([in.msg],
+[From foo@example.com Wed Nov 22 16:55:56 2017
+MIME-Version: 1.0
+From: Foo Bar <foo@example.com>
+Date: Wed, 22 Nov 2017 18:54:55 +0200
+Subject: MIME delimiter test
+To: Gray <gray@example.org>
+Content-Type: multipart/mixed; boundary="94eb2c190d42daa45d055e952d64"
+
+--94eb2c190d42daa45d055e952d64
+Content-Type: multipart/alternative; boundary="94eb2c190d42daa45a055e952d62"
+
+--94eb2c190d42daa45a055e952d62
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: base64
+
+SGllciBsaWVndCBlaW4gTWFubiBnYW56IG9ibmVnbGVpY2g7CkltIExlaWJlIGRpY2ssIGFuIFN1
+ZGVuIHJlaWNoLgpXaXIgaGFiZW4gaWhuIGluIGRhcyBHcmFiIGdlc3RlY2t0LCAgICAgSGVyZSBs
+aWVzIGEgbWFuIHdpdGggc3VuZHJ5IGZsYXdzCldlaWwgZXMgdW5zIGR1bmt0IGVyIHNlaSB2ZXJy
+ZWNrdC4gICAgICBBbmQgbnVtZXJvdXMgU2lucyB1cG9uIGhpcyBoZWFkOwogICAgICAgICAgICAg
+ICAgICAgICAgICAgICAgICAgICAgICAgICAgV2UgYnVyaWVkIGhpbSB0b2RheSBiZWNhdXNlCiAg
+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcyBmYXIgYXMgd2UgY2FuIHRl
+bGwsIGhlJ3MgZGVhZC4KCiAgICAgICAgICAgICAgICAtLSBQRFEgQmFjaCdzIGVwaXRhcGgsIGFz
+IHJlcXVlc3RlZCBieSBoaXMgY291c2luIEJldHR5CiAgICAgICAgICAgICAgICAgICBTdWUgQmFj
+aCBhbmQgd3JpdHRlbiBieSB0aGUgbG9jYWwgZG9nZ2VyYWwgY2F0Y2hlcjsKICAgICAgICAgICAg
+ICAgICAgICJUaGUgRGVmaW5pdGl2ZSBCaW9ncmFwaHkgb2YgUERRIEJhY2giLCBQZXRlciBTY2hp
+Y2tlbGUK
+--94eb2c190d42daa45a055e952d62
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: base64
+
+PGh0bWw+Cjxib2R5Pgo8ZGl2Pgo8ZGl2PjxwcmU+SGllciBsaWVndCBlaW4gTWFubiBnYW56IG9i
+bmVnbGVpY2g7CkltIExlaWJlIGRpY2ssIGFuIFN1ZGVuIHJlaWNoLjwvcHJlPgo8L2Rpdj4KPGRp
+dj4KIDxkaXY+CiAgIFdpciBoYWJlbiBpaG4gaW4gZGFzIEdyYWIgZ2VzdGVja3QsCiAgIFdlaWwg
+ZXMgdW5zIGR1bmt0IGVyIHNlaSB2ZXJyZWNrdC4KIDwvZGl2PgogPGRpdj4KICAgSGVyZSBsaWVz
+IGEgbWFuIHdpdGggc3VuZHJ5IGZsYXdzCiAgIEFuZCBudW1lcm91cyBTaW5zIHVwb24gaGlzIGhl
+YWQ7CiA8L2Rpdj4KPC9kaXY+CjxkaXY+CldlIGJ1cmllZCBoaW0gdG9kYXkgYmVjYXVzZQpBcyBm
+YXIgYXMgd2UgY2FuIHRlbGwsIGhlJ3MgZGVhZC4KPC9kaXY+CjxibG9ja3F1b3RlPgotLSBQRFEg
+QmFjaCdzIGVwaXRhcGgsIGFzIHJlcXVlc3RlZCBieSBoaXMgY291c2luIEJldHR5CiAgIFN1ZSBC
+YWNoIGFuZCB3cml0dGVuIGJ5IHRoZSBsb2NhbCBkb2dnZXJhbCBjYXRjaGVyOwogICAiVGhlIERl
+ZmluaXRpdmUgQmlvZ3JhcGh5IG9mIFBEUSBCYWNoIiwgUGV0ZXIgU2NoaWNrZWxlCjwvYmxvY2tx
+dW90ZT4KPC9ib2R5Pgo8L2h0bWw+Cg==
+--94eb2c190d42daa45a055e952d62--
+--94eb2c190d42daa45d055e952d64--
+])
+
+AT_CHECK([mimetest -i 0 in.msg
+],
+[0],
+[Message:1
+From:Foo Bar <foo@example.com>
+Subject:MIME delimiter test
+Number of parts in message:1
+Total message size:2189/42
+Type of part 1:multipart/alternative
+Message part size:1907/32: 78/2, 1829/30
+Encapsulated message:
+From:
+Subject:
+Begin
+Type of part 1:text/plain
+Message part size:855/13: 77/3, 778/10
+Text Message
+Begin
+Hier liegt ein Mann ganz obnegleich;
+Im Leibe dick, an Suden reich.
+Wir haben ihn in das Grab gesteckt, Here lies a man with sundry flaws
+Weil es uns dunkt er sei verreckt. And numerous Sins upon his head;
+ We buried him today because
+ As far as we can tell, he's dead.
+
+ -- PDQ Bach's epitaph, as requested by his cousin Betty
+ Sue Bach and written by the local doggeral catcher;
+ "The Definitive Biography of PDQ Bach", Peter Schickele
+
+End
+Type of part 2:text/html
+Message part size:878/13: 76/3, 802/10
+Text Message
+Begin
+<html>
+<body>
+<div>
+<div><pre>Hier liegt ein Mann ganz obnegleich;
+Im Leibe dick, an Suden reich.</pre>
+</div>
+<div>
+ <div>
+ Wir haben ihn in das Grab gesteckt,
+ Weil es uns dunkt er sei verreckt.
+ </div>
+ <div>
+ Here lies a man with sundry flaws
+ And numerous Sins upon his head;
+ </div>
+</div>
+<div>
+We buried him today because
+As far as we can tell, he's dead.
+</div>
+<blockquote>
+-- PDQ Bach's epitaph, as requested by his cousin Betty
+ Sue Bach and written by the local doggeral catcher;
+ "The Definitive Biography of PDQ Bach", Peter Schickele
+</blockquote>
+</body>
+</html>
+
+End
+
+End
+])
+AT_CLEANUP
diff --git a/testsuite/mimetest.c b/testsuite/mimetest.c
index 0f8e593aa..1f5e11bc4 100644
--- a/testsuite/mimetest.c
+++ b/testsuite/mimetest.c
@@ -130,14 +130,14 @@ main (int argc, char **argv)
from = "";
if (mu_header_sget_value (hdr, MU_HEADER_SUBJECT, &subject))
subject = "";
- printf ("Message: %lu\n", (unsigned long) i);
- printf ("From: %s\n", from);
- printf ("Subject: %s\n", subject);
+ printf ("Message:%lu\n", (unsigned long) i);
+ printf ("From:%s\n", from);
+ printf ("Subject:%s\n", subject);
MU_ASSERT (mu_message_get_num_parts (msg, &nparts));
- printf ("Number of parts in message - %lu\n",
+ printf ("Number of parts in message:%lu\n",
(unsigned long) nparts);
- printf ("Total message size - %lu/%lu\n",
+ printf ("Total message size:%lu/%lu\n",
(unsigned long) msize, (unsigned long) nlines);
message_display_parts (msg, 0);
}
@@ -163,7 +163,7 @@ print_message_part_sizes (mu_message_t part, int indent)
MU_ASSERT (mu_message_get_body (part, &body));
MU_ASSERT (mu_body_size (body, &bsize));
MU_ASSERT (mu_body_lines (body, &blines));
- printf ("%*.*sMessage part size - %lu/%lu: %lu/%lu, %lu/%lu\n",
+ printf ("%*.*sMessage part size:%lu/%lu: %lu/%lu, %lu/%lu\n",
indent, indent, "",
(unsigned long) msize, (unsigned long) mlines,
(unsigned long) hsize, (unsigned long) hlines,
@@ -214,7 +214,7 @@ message_display_parts (mu_message_t msg, int indent)
mu_error ("Cannot extract content type field: %s",
mu_strerror (status));
}
- printf ("%*.*sType of part %d = %s\n", indent, indent, "",
+ printf ("%*.*sType of part %d:%s\n", indent, indent, "",
j, mu_prstr (type));
print_message_part_sizes (part, indent);
if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING,
@@ -233,8 +233,10 @@ message_display_parts (mu_message_t msg, int indent)
from = "";
if (mu_header_sget_value (hdr, MU_HEADER_SUBJECT, &subject))
subject = "";
- printf ("%*.*sEncapsulated message : %s\t%s\n",
- indent, indent, "", from, subject);
+ printf ("%*.*sEncapsulated message:\n",
+ indent, indent, "");
+ printf ("%*.*sFrom:%s\n", indent, indent, "", from);
+ printf ("%*.*sSubject:%s\n", indent, indent, "", subject);
printf ("%*.*sBegin\n", indent, indent, "");
message_display_parts (part, indent + indent_level);
mu_message_destroy (&part, NULL);
diff --git a/testsuite/testsuite.at b/testsuite/testsuite.at
index addfed025..85d102e35 100644
--- a/testsuite/testsuite.at
+++ b/testsuite/testsuite.at
@@ -25,6 +25,7 @@ m4_include([lstuid02.at])
AT_BANNER(mimetest)
m4_include([mime.at])
+m4_include([mime01.at])
AT_BANNER(Mailbox removal)
m4_include([mbdel.at])

Return to:

Send suggestions and report system problems to the System administrator.