git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] mailinfo: unescape quoted-pair in header fields

From
Kevin Daudt <me@ikke.info>
Date
Sep 16, 2016, 21:02 UTC
Message-ID
<20160916210204.31282-1-me@ikke.info>

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.

Tell mailinfo to remove exterior quotes and remove escape characters from the author so that they don't show up in the commits author field.

Signed-off-by: Kevin Daudt <me@ikke.info>
---
The only thing I could not easily fix is the prevent git am from removing any quotes around the author. This is done in fmt_ident, which calls `strbuf_addstr_without_crud`. 
 mailinfo.c                 | 54 ++++++++++++++++++++++++++++++++++++++++++++++
 t/t5100-mailinfo.sh        |  6 ++++++
 t/t5100/quoted-pair.expect |  5 +++++
 t/t5100/quoted-pair.in     |  9 ++++++++
 4 files changed, 74 insertions(+)
 create mode 100644 t/t5100/quoted-pair.expect
 create mode 100644 t/t5100/quoted-pair.in
diff --git a/mailinfo.c b/mailinfo.c
index e19abe3..04036f3 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -54,15 +54,69 @@ static void parse_bogus_from(struct mailinfo *mi, const struct strbuf *line)
 	get_sane_name(&mi->name, &mi->name, &mi->email);
 }
 
+static int unquote_quoted_string(struct strbuf *line)
+{
+	struct strbuf outbuf;
+	const char *in = line->buf;
+	int c, take_next_literally = 0;
+	int found_error = 0;
+	char escape_context=0;
+
+	strbuf_init(&outbuf, line->len);
+
+	while ((c = *in++) != 0) {
+		if (take_next_literally) {
+			take_next_literally = 0;
+		} else {
+			switch (c) {
+			case '"':
+				if (!escape_context)
+					escape_context = '"';
+				else if (escape_context == '"')
+					escape_context = 0;
+				continue;
+			case '\\':
+				if (escape_context) {
+					take_next_literally = 1;
+					continue;
+				}
+				break;
+			case '(':
+				if (!escape_context)
+					escape_context = '(';
+				else if (escape_context == '(')
+					found_error = 1;
+				break;
+			case ')':
+				if (escape_context == '(')
+					escape_context = 0;
+				break;
+			}
+		}
+
+		strbuf_addch(&outbuf, c);
+	}
+
+	strbuf_reset(line);
+	strbuf_addbuf(line, &outbuf);
+	strbuf_release(&outbuf);
+
+	return found_error;
+
+}
+
 static void handle_from(struct mailinfo *mi, const struct strbuf *from)
 {
 	char *at;
 	size_t el;
 	struct strbuf f;
 
+
 	strbuf_init(&f, from->len);
 	strbuf_addbuf(&f, from);
 
+	unquote_quoted_string(&f);
+
 	at = strchr(f.buf, '@');
 	if (!at) {
 		parse_bogus_from(mi, from);
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index 1a5a546..d0c21fc 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -142,4 +142,10 @@ test_expect_success 'mailinfo unescapes with --mboxrd' '
 	test_cmp expect mboxrd/msg
 '
 
+test_expect_success 'mailinfo unescapes rfc2822 quoted-string' '
+    mkdir quoted-pair &&
+    git mailinfo /dev/null /dev/null <"$TEST_DIRECTORY"/t5100/quoted-pair.in >quoted-pair/info &&
+    test_cmp "$TEST_DIRECTORY"/t5100/quoted-pair.expect quoted-pair/info
+'
+
 test_done
diff --git a/t/t5100/quoted-pair.expect b/t/t5100/quoted-pair.expect
new file mode 100644
index 0000000..cab1bce
--- /dev/null
+++ b/t/t5100/quoted-pair.expect
@@ -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-pair.in b/t/t5100/quoted-pair.in
new file mode 100644
index 0000000..e2e627a
--- /dev/null
+++ b/t/t5100/quoted-pair.in
@@ -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
-- 
2.10.0.86.g6ffa4f1.dirty
Next: Jeff King
Message 1 of 32 in “mailinfo: unescape quoted-pair in header fields”
  1. mailinfo: unescape quoted-pair in header fieldsKevin Daudt, Sep 16, 2016
  2. Jeff KingSep 16, 2016
  3. Kevin DaudtSep 19, 2016
  4. Jeff KingSep 20, 2016
  5. Junio C HamanoSep 21, 2016
  6. 0/2 Handle escape characters in From field.Kevin Daudt, Sep 19, 2016
  7. 2/2 mailinfo: unescape quoted-pair in header fieldsKevin Daudt, Sep 19, 2016
  8. Junio C HamanoSep 19, 2016
  9. Junio C HamanoSep 19, 2016
  10. Jeff KingSep 20, 2016
  11. Jeff KingSep 21, 2016
  12. Junio C HamanoSep 22, 2016
  13. Jeff KingSep 23, 2016
  14. Kevin DaudtSep 25, 2016
  15. Jakub NarębskiSep 25, 2016
  16. Kevin DaudtSep 26, 2016
  17. 1/2 t5100-mailinfo: replace common path prefix with variableKevin Daudt, Sep 19, 2016
  18. Junio C HamanoSep 19, 2016
  19. Jeff KingSep 20, 2016
  20. 1/2 t5100-mailinfo: replace common path prefix with variableKevin Daudt, Sep 25, 2016
  21. 2/2 mailinfo: unescape quoted-pair in header fieldsKevin Daudt, Sep 25, 2016
  22. Junio C HamanoSep 26, 2016
  23. Junio C HamanoSep 26, 2016
  24. Kevin DaudtSep 26, 2016
  25. Junio C HamanoSep 26, 2016
  26. Kevin DaudtSep 27, 2016
  27. Junio C HamanoSep 26, 2016
  28. 0/2 Handle RFC2822 quoted-pairs in From headerKevin Daudt, Sep 28, 2016
  29. 1/2 t5100-mailinfo: replace common path prefix with variableKevin Daudt, Sep 28, 2016
  30. Junio C HamanoSep 28, 2016
  31. Kevin DaudtSep 28, 2016
  32. 2/2 mailinfo: unescape quoted-pair in header fieldsKevin Daudt, Sep 28, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.