]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mailinfo: unescape quoted-pair in header fields
authorKevin Daudt <me@ikke.info>
Wed, 28 Sep 2016 19:52:32 +0000 (21:52 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 28 Sep 2016 20:21:18 +0000 (13:21 -0700)
rfc2822 has provisions for quoted strings in structured header fields,
but also allows for escaping these with so-called quoted-pairs.

The only thing git currently does is removing exterior quotes, but
quotes within are left alone.

Remove exterior quotes and remove escape characters so that they don't
show up in the author field.

Signed-off-by: Kevin Daudt <me@ikke.info>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
mailinfo.c
t/t5100-mailinfo.sh
t/t5100/comment.expect [new file with mode: 0644]
t/t5100/comment.in [new file with mode: 0644]
t/t5100/quoted-string.expect [new file with mode: 0644]
t/t5100/quoted-string.in [new file with mode: 0644]

index e19abe3cb93e24aed8848cadec8ddf8a8767f303..b4118a02757212871e3402532ab5c422a5ba043f 100644 (file)
@@ -54,6 +54,86 @@ static void parse_bogus_from(struct mailinfo *mi, const struct strbuf *line)
        get_sane_name(&mi->name, &mi->name, &mi->email);
 }
 
+static const char *unquote_comment(struct strbuf *outbuf, const char *in)
+{
+       int c;
+       int take_next_litterally = 0;
+
+       strbuf_addch(outbuf, '(');
+
+       while ((c = *in++) != 0) {
+               if (take_next_litterally == 1) {
+                       take_next_litterally = 0;
+               } else {
+                       switch (c) {
+                       case '\\':
+                               take_next_litterally = 1;
+                               continue;
+                       case '(':
+                               in = unquote_comment(outbuf, in);
+                               continue;
+                       case ')':
+                               strbuf_addch(outbuf, ')');
+                               return in;
+                       }
+               }
+
+               strbuf_addch(outbuf, c);
+       }
+
+       return in;
+}
+
+static const char *unquote_quoted_string(struct strbuf *outbuf, const char *in)
+{
+       int c;
+       int take_next_litterally = 0;
+
+       while ((c = *in++) != 0) {
+               if (take_next_litterally == 1) {
+                       take_next_litterally = 0;
+               } else {
+                       switch (c) {
+                       case '\\':
+                               take_next_litterally = 1;
+                               continue;
+                       case '"':
+                               return in;
+                       }
+               }
+
+               strbuf_addch(outbuf, c);
+       }
+
+       return in;
+}
+
+static void unquote_quoted_pair(struct strbuf *line)
+{
+       struct strbuf outbuf;
+       const char *in = line->buf;
+       int c;
+
+       strbuf_init(&outbuf, line->len);
+
+       while ((c = *in++) != 0) {
+               switch (c) {
+               case '"':
+                       in = unquote_quoted_string(&outbuf, in);
+                       continue;
+               case '(':
+                       in = unquote_comment(&outbuf, in);
+                       continue;
+               }
+
+               strbuf_addch(&outbuf, c);
+       }
+
+       strbuf_swap(&outbuf, line);
+       strbuf_release(&outbuf);
+
+}
+
 static void handle_from(struct mailinfo *mi, const struct strbuf *from)
 {
        char *at;
@@ -63,6 +143,8 @@ static void handle_from(struct mailinfo *mi, const struct strbuf *from)
        strbuf_init(&f, from->len);
        strbuf_addbuf(&f, from);
 
+       unquote_quoted_pair(&f);
+
        at = strchr(f.buf, '@');
        if (!at) {
                parse_bogus_from(mi, from);
index 56988b7116e7d3951f53ddb202570af2ea60a09e..45d228ebc81ed13c83d24f90895e9a374af5a87e 100755 (executable)
@@ -144,4 +144,18 @@ test_expect_success 'mailinfo unescapes with --mboxrd' '
        test_cmp expect mboxrd/msg
 '
 
+test_expect_success 'mailinfo handles rfc2822 quoted-string' '
+       mkdir quoted-string &&
+       git mailinfo /dev/null /dev/null <"$DATA/quoted-string.in" \
+               >quoted-string/info &&
+       test_cmp "$DATA/quoted-string.expect" quoted-string/info
+'
+
+test_expect_success 'mailinfo handles rfc2822 comment' '
+       mkdir comment &&
+       git mailinfo /dev/null /dev/null <"$DATA/comment.in" \
+               >comment/info &&
+       test_cmp "$DATA/comment.expect" comment/info
+'
+
 test_done
diff --git a/t/t5100/comment.expect b/t/t5100/comment.expect
new file mode 100644 (file)
index 0000000..7228177
--- /dev/null
@@ -0,0 +1,5 @@
+Author: A U Thor (this is (really) a comment (honestly))
+Email: somebody@example.com
+Subject: testing comments
+Date: Sun, 25 May 2008 00:38:18 -0700
+
diff --git a/t/t5100/comment.in b/t/t5100/comment.in
new file mode 100644 (file)
index 0000000..c53a192
--- /dev/null
@@ -0,0 +1,9 @@
+From 1234567890123456789012345678901234567890 Mon Sep 17 00:00:00 2001
+From: "A U Thor" <somebody@example.com> (this is \(really\) a comment (honestly))
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] testing comments
+
+
+
+---
+patch
diff --git a/t/t5100/quoted-string.expect b/t/t5100/quoted-string.expect
new file mode 100644 (file)
index 0000000..cab1bce
--- /dev/null
@@ -0,0 +1,5 @@
+Author: Author "The Author" Name
+Email: somebody@example.com
+Subject: testing quoted-pair
+Date: Sun, 25 May 2008 00:38:18 -0700
+
diff --git a/t/t5100/quoted-string.in b/t/t5100/quoted-string.in
new file mode 100644 (file)
index 0000000..e2e627a
--- /dev/null
@@ -0,0 +1,9 @@
+From 1234567890123456789012345678901234567890 Mon Sep 17 00:00:00 2001
+From: "Author \"The Author\" Name" <somebody@example.com>
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] testing quoted-pair
+
+
+
+---
+patch