Skip to content

Commit 4d03c18

Browse files
peffgitster
authored andcommitted
pretty: quote rfc822 specials in email addresses
If somebody has a name that includes an rfc822 special, we will output it literally in the "From:" header. This is usually OK, but certain characters (like ".") are supposed to be enclosed in double-quotes in a mail header. In practice, whether this matters may depend on your MUA. Some MUAs will happily take in: From: Foo B. Bar <[email protected]> without quotes, and properly quote the "." when they send the actual mail. Others may not, or may screw up harder things like: From: Foo "The Baz" Bar <[email protected]> For example, mutt will strip the quotes, thinking they are actual syntactic rfc822 quotes. So let's quote properly, and then (if necessary) we still apply rfc2047 encoding on top of that, which should make all MUAs happy. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4fec830 commit 4d03c18

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

pretty.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,58 @@ int has_non_ascii(const char *s)
208208
return 0;
209209
}
210210

211+
static int is_rfc822_special(char ch)
212+
{
213+
switch (ch) {
214+
case '(':
215+
case ')':
216+
case '<':
217+
case '>':
218+
case '[':
219+
case ']':
220+
case ':':
221+
case ';':
222+
case '@':
223+
case ',':
224+
case '.':
225+
case '"':
226+
case '\\':
227+
return 1;
228+
default:
229+
return 0;
230+
}
231+
}
232+
233+
static int has_rfc822_specials(const char *s, int len)
234+
{
235+
int i;
236+
for (i = 0; i < len; i++)
237+
if (is_rfc822_special(s[i]))
238+
return 1;
239+
return 0;
240+
}
241+
242+
static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
243+
{
244+
int i;
245+
246+
/* just a guess, we may have to also backslash-quote */
247+
strbuf_grow(out, len + 2);
248+
249+
strbuf_addch(out, '"');
250+
for (i = 0; i < len; i++) {
251+
switch (s[i]) {
252+
case '"':
253+
case '\\':
254+
strbuf_addch(out, '\\');
255+
/* fall through */
256+
default:
257+
strbuf_addch(out, s[i]);
258+
}
259+
}
260+
strbuf_addch(out, '"');
261+
}
262+
211263
static int is_rfc2047_special(char ch)
212264
{
213265
return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_'));
@@ -293,7 +345,14 @@ void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,
293345
name_tail--;
294346
display_name_length = name_tail - line;
295347
strbuf_addstr(sb, "From: ");
296-
add_rfc2047(sb, line, display_name_length, encoding);
348+
if (!has_rfc822_specials(line, display_name_length)) {
349+
add_rfc2047(sb, line, display_name_length, encoding);
350+
} else {
351+
struct strbuf quoted = STRBUF_INIT;
352+
add_rfc822_quoted(&quoted, line, display_name_length);
353+
add_rfc2047(sb, quoted.buf, quoted.len, encoding);
354+
strbuf_release(&quoted);
355+
}
297356
strbuf_add(sb, name_tail, namelen - display_name_length);
298357
strbuf_addch(sb, '\n');
299358
} else {

t/t4014-format-patch.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,4 +793,46 @@ test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
793793
test_cmp expect subject
794794
'
795795

796+
check_author() {
797+
echo content >>file &&
798+
git add file &&
799+
GIT_AUTHOR_NAME=$1 git commit -m author-check &&
800+
git format-patch --stdout -1 >patch &&
801+
grep ^From: patch >actual &&
802+
test_cmp expect actual
803+
}
804+
805+
cat >expect <<'EOF'
806+
From: "Foo B. Bar" <[email protected]>
807+
EOF
808+
test_expect_success 'format-patch quotes dot in headers' '
809+
check_author "Foo B. Bar"
810+
'
811+
812+
cat >expect <<'EOF'
813+
From: "Foo \"The Baz\" Bar" <[email protected]>
814+
EOF
815+
test_expect_success 'format-patch quotes double-quote in headers' '
816+
check_author "Foo \"The Baz\" Bar"
817+
'
818+
819+
cat >expect <<'EOF'
820+
From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <[email protected]>
821+
EOF
822+
test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
823+
check_author "Föo B. Bar"
824+
'
825+
826+
cat >expect <<'EOF'
827+
Subject: header with . in it
828+
EOF
829+
test_expect_success 'subject lines do not have 822 atom-quoting' '
830+
echo content >>file &&
831+
git add file &&
832+
git commit -m "header with . in it" &&
833+
git format-patch -k -1 --stdout >patch &&
834+
grep ^Subject: patch >actual &&
835+
test_cmp expect actual
836+
'
837+
796838
test_done

0 commit comments

Comments
 (0)