Show changes to 5 files +248 −1
t/t5100-mailinfo.sh, t/t5100/info0009, t/t5100/msg0009, t/t5100/patch0009, t/t5100/sample.mbox
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index 9b1a745..d6c55c1 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -11,7 +11,7 @@ test_expect_success 'split sample box' \
'git mailsplit -o. ../t5100/sample.mbox >last &&
last=`cat last` &&
echo total is $last &&
- test `cat last` = 8'
+ test `cat last` = 9'
for mail in `echo 00*`
do
diff --git a/t/t5100/info0009 b/t/t5100/info0009
new file mode 100644
index 0000000..63369be
--- /dev/null
+++ b/t/t5100/info0009
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: mailinfo: support rfc3676 (format=flowed) text/plain messages
+Date: Thu, 14 Feb 2008 20:56:34 -0500
+
diff --git a/t/t5100/msg0009 b/t/t5100/msg0009
new file mode 100644
index 0000000..eb9c7f8
--- /dev/null
+++ b/t/t5100/msg0009
@@ -0,0 +1,8 @@
+RFC 3676 establishes two parameters (Format and DelSP) to be used with
+the Text/Plain media type. In the presence of these parameters, trailing
+whitespace is used to indicate flowed lines and a canonical quote
+indicator is used to indicate quoted lines.
+
+mailinfo now unfolds, unquotes, and un-space-stuffs such messages.
+
+Signed-off-by: A U Thor <a.u.thor@example.com.com
diff --git a/t/t5100/patch0009 b/t/t5100/patch0009
new file mode 100644
index 0000000..a167e73
--- /dev/null
+++ b/t/t5100/patch0009
@@ -0,0 +1,98 @@
+---
+The next line will test space stuffing
+From A U Thor <a.u.thor@example.com.com>
+
+The next line will test space stuffing also, and force Mail.app to send this as quoted-printable. This line will be flowed.
+> Märchen
+
+A flowed quoted paragraph follows:
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+And again with deeper quoting depth:
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+
+builtin-mailinfo.c | 40 ++++++++++++++++++++++++++++++++++++++++
+1 files changed, 40 insertions(+), 0 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 2600847..deaf92b 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -20,6 +20,13 @@ static enum {
+static enum {
+ TYPE_TEXT, TYPE_OTHER,
+} message_type;
++/* RFC 3676 Text/Plain Format and DelSp Parameters */
++static enum {
++ FORMAT_NONE, FORMAT_FIXED, FORMAT_FLOWED,
++} tp_format;
++static enum {
++ DELSP_NONE, DELSP_YES, DELSP_NO,
++} tp_delsp;
+
+static char charset[256];
+static int patch_lines;
+@@ -193,6 +200,18 @@ static int handle_content_type(char *line)
+
+ if (strcasestr(line, "text/") == NULL)
+ message_type = TYPE_OTHER;
++ else if (strcasestr(line, "text/plain")) {
++ char attr[256];
++ if (slurp_attr(line, "format=", attr) && !strcasecmp(attr, "flowed")) {
++ tp_format = FORMAT_FLOWED;
++ if (slurp_attr(line, "delsp=", attr) && !strcasecmp(attr, "yes"))
++ tp_delsp = DELSP_YES;
++ else
++ tp_delsp = DELSP_NO;
++ }
++ else
++ tp_format = FORMAT_FIXED;
++ }
+ if (slurp_attr(line, "boundary=", boundary + 2)) {
+ memcpy(boundary, "--", 2);
+ if (content_top++ >= &content[MAX_BOUNDARIES]) {
+@@ -681,6 +700,8 @@ again:
+ transfer_encoding = TE_DONTCARE;
+ charset[0] = 0;
+ message_type = TYPE_TEXT;
++ tp_format = FORMAT_NONE;
++ tp_delsp = DELSP_NONE;
+
+ /* slurp in this section's info */
+ while (read_one_header_line(line, sizeof(line), fin))
+@@ -770,6 +791,24 @@ static int handle_filter(char *line, unsigned linesize)
+{
+ static int filter = 0;
+
++ if (tp_format == FORMAT_FLOWED && !!strcmp(line, "-- \n")) {
++ char *cp = line;
++ while (*cp == '>' && *cp != 0)
++ cp++;
++ if (*cp == ' ')
++ cp++;
++ line = cp;
++ if (!!strcmp(line, "-- \n")) {
++ while (*cp != '\n' && *cp !=0)
++ cp++;
++ if (cp > line && *cp == '\n' && *(cp-1) == ' ') {
++ if (tp_delsp == DELSP_YES)
++ *(cp-1) = '\0';
++ else
++ *cp = '\0';
++ }
++ }
++ }
+ /* filter tells us which part we left off on
+ * a non-zero return indicates we hit a filter point
+ */
+@@ -818,6 +857,7 @@ static void handle_body(void)
+
+ switch (transfer_encoding) {
+ case TE_BASE64:
++ case TE_QP:
+ {
+ char *op = line;
+
+--
+1.5.4.1.1281.g75df
diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox
index 070c166..a1f9833 100644
--- a/t/t5100/sample.mbox
+++ b/t/t5100/sample.mbox
@@ -407,3 +407,141 @@ Subject: [PATCH] another patch
Hey you forgot the patch!
+From nobody Thu Feb 14 21:02:08 2008
+Message-Id: <FCDFE42A-6A58-4F77-AEF2-E94C5373B14F@soffian.org>
+From: A U Thor <a.u.thor@example.com>
+To: A U Thor <a.u.thor@example.com>
+Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes
+Content-Transfer-Encoding: quoted-printable
+Mime-Version: 1.0 (Apple Message framework v919.2)
+Subject: [PATCH] mailinfo: support rfc3676 (format=flowed) text/plain messages
+Date: Thu, 14 Feb 2008 20:56:34 -0500
+X-Mailer: Apple Mail (2.919.2)
+
+RFC 3676 establishes two parameters (Format and DelSP) to be used with
+the Text/Plain media type. In the presence of these parameters, trailing
+whitespace is used to indicate flowed lines and a canonical quote
+indicator is used to indicate quoted lines.
+
+mailinfo now unfolds, unquotes, and un-space-stuffs such messages.
+
+Signed-off-by: A U Thor <a.u.thor@example.com.com
+---
+The next line will test space stuffing
+ =46rom A U Thor <a.u.thor@example.com.com>
+
+The next line will test space stuffing also, and force Mail.app to =20
+send this as quoted-printable. This line will be flowed.
+ > M=C3=A4rchen
+
+A flowed quoted paragraph follows:
+> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do =20
+> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim =20=
+
+> ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut =20
+> aliquip ex ea commodo consequat. Duis aute irure dolor in =20
+> reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla =20=
+
+> pariatur. Excepteur sint occaecat cupidatat non proident, sunt in =20
+> culpa qui officia deserunt mollit anim id est laborum.
+
+And again with deeper quoting depth:
+>>> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do =20
+>>> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut =20
+>>> enim ad minim veniam, quis nostrud exercitation ullamco laboris =20
+>>> nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in =20=
+
+>>> reprehenderit in voluptate velit esse cillum dolore eu fugiat =20
+>>> nulla pariatur. Excepteur sint occaecat cupidatat non proident, =20
+>>> sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+
+builtin-mailinfo.c | 40 ++++++++++++++++++++++++++++++++++++++++
+1 files changed, 40 insertions(+), 0 deletions(-)
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 2600847..deaf92b 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -20,6 +20,13 @@ static enum {
+static enum {
+ TYPE_TEXT, TYPE_OTHER,
+} message_type;
++/* RFC 3676 Text/Plain Format and DelSp Parameters */
++static enum {
++ FORMAT_NONE, FORMAT_FIXED, FORMAT_FLOWED,
++} tp_format;
++static enum {
++ DELSP_NONE, DELSP_YES, DELSP_NO,
++} tp_delsp;
+
+static char charset[256];
+static int patch_lines;
+@@ -193,6 +200,18 @@ static int handle_content_type(char *line)
+
+ if (strcasestr(line, "text/") =3D=3D NULL)
+ message_type =3D TYPE_OTHER;
++ else if (strcasestr(line, "text/plain")) {
++ char attr[256];
++ if (slurp_attr(line, "format=3D", attr) && =
+!strcasecmp(attr, =20
+"flowed")) {
++ tp_format =3D FORMAT_FLOWED;
++ if (slurp_attr(line, "delsp=3D", attr) && =
+!strcasecmp(attr, "yes"))
++ tp_delsp =3D DELSP_YES;
++ else
++ tp_delsp =3D DELSP_NO;
++ }
++ else
++ tp_format =3D FORMAT_FIXED;
++ }
+ if (slurp_attr(line, "boundary=3D", boundary + 2)) {
+ memcpy(boundary, "--", 2);
+ if (content_top++ >=3D &content[MAX_BOUNDARIES]) {
+@@ -681,6 +700,8 @@ again:
+ transfer_encoding =3D TE_DONTCARE;
+ charset[0] =3D 0;
+ message_type =3D TYPE_TEXT;
++ tp_format =3D FORMAT_NONE;
++ tp_delsp =3D DELSP_NONE;
+
+ /* slurp in this section's info */
+ while (read_one_header_line(line, sizeof(line), fin))
+@@ -770,6 +791,24 @@ static int handle_filter(char *line, unsigned =20
+linesize)
+{
+ static int filter =3D 0;
+
++ if (tp_format =3D=3D FORMAT_FLOWED && !!strcmp(line, "-- \n")) {
++ char *cp =3D line;
++ while (*cp =3D=3D '>' && *cp !=3D 0)
++ cp++;
++ if (*cp =3D=3D ' ')
++ cp++;
++ line =3D cp;
++ if (!!strcmp(line, "-- \n")) {
++ while (*cp !=3D '\n' && *cp !=3D0)
++ cp++;
++ if (cp > line && *cp =3D=3D '\n' && *(cp-1) =3D=3D=
+ ' ') {
++ if (tp_delsp =3D=3D DELSP_YES)
++ *(cp-1) =3D '\0';
++ else
++ *cp =3D '\0';
++ }
++ }
++ }
+ /* filter tells us which part we left off on
+ * a non-zero return indicates we hit a filter point
+ */
+@@ -818,6 +857,7 @@ static void handle_body(void)
+
+ switch (transfer_encoding) {
+ case TE_BASE64:
++ case TE_QP:
+ {
+ char *op =3D line;
+
+--=20
+1.5.4.1.1281.g75df