format-patch: fix rfc2047 address encoding with respect to rfc822 specials
According to RFC 2047 and RFC 822, rfc2047 encoded words and and rfc822 quoted strings do not mix. Since add_rfc2047() no longer leaves RFC 822 specials behind, the quoting is also no longer necessary to create a standard-conforming mail. Remove the quoting, when RFC 2047 encoding takes place. This actually requires to refactor add_rfc2047() a bit, so that the different cases can be distinguished. With this patch, my own name gets correctly decoded as Jan H. Schönherr (without quotes) and not as "Jan H. Schönherr" (with quotes). Signed-off-by: Jan H. Schönherr <schnhrr@cs.tu-berlin.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jan H. Schönherr committed
Oct 18, 2012 at 16:43 UTC
41dd00bad3d7614be7e8a41ed3f31878af86758b
2 files changed
+33
-18
pretty.c
+32
-17
@@ -231,7 +231,7 @@ static int is_rfc822_special(char ch)
231
}
232
}
233
234
-static int has_rfc822_specials(const char *s, int len)
234
+static int needs_rfc822_quoting(const char *s, int len)
235
{
236
int i;
237
for (i = 0; i < len; i++)
@@ -329,25 +329,29 @@ static int is_rfc2047_special(char ch, enum rfc2047_type type)
329
return !(isalnum(ch) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/');
330
}
331
332
-static void add_rfc2047(struct strbuf *sb, const char *line, int len,
333
- const char *encoding, enum rfc2047_type type)
332
+static int needs_rfc2047_encoding(const char *line, int len,
333
+ enum rfc2047_type type)
334
{
335
- static const int max_length = 78; /* per rfc2822 */
336
- static const int max_encoded_length = 76; /* per rfc2047 */
335
int i;
338
- int line_len = last_line_length(sb);
336
337
for (i = 0; i < len; i++) {
338
int ch = line[i];
339
if (non_ascii(ch) || ch == '\n')
343
- goto needquote;
340
+ return 1;
341
if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
345
- goto needquote;
342
+ return 1;
343
}
347
- strbuf_add_wrapped_bytes(sb, line, len, -line_len, 1, max_length);
348
- return;
344
350
-needquote:
345
+ return 0;
346
+}
347
+
348
+static void add_rfc2047(struct strbuf *sb, const char *line, int len,
349
+ const char *encoding, enum rfc2047_type type)
350
+{
351
+ static const int max_encoded_length = 76; /* per rfc2047 */
352
+ int i;
353
+ int line_len = last_line_length(sb);
354
+
355
strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
356
strbuf_addf(sb, "=?%s?q?", encoding);
357
line_len += strlen(encoding) + 5; /* 5 for =??q? */
@@ -383,6 +387,7 @@ void pp_user_info(const struct pretty_print_context *pp,
387
const char *what, struct strbuf *sb,
388
const char *line, const char *encoding)
389
{
390
+ int max_length = 78; /* per rfc2822 */
391
char *date;
392
int namelen;
393
unsigned long time;
@@ -406,17 +411,21 @@ void pp_user_info(const struct pretty_print_context *pp,
411
name_tail--;
412
display_name_length = name_tail - line;
413
strbuf_addstr(sb, "From: ");
409
- if (!has_rfc822_specials(line, display_name_length)) {
414
+ if (needs_rfc2047_encoding(line, display_name_length, RFC2047_ADDRESS)) {
415
add_rfc2047(sb, line, display_name_length,
416
encoding, RFC2047_ADDRESS);
412
- } else {
417
+ max_length = 76; /* per rfc2047 */
418
+ } else if (needs_rfc822_quoting(line, display_name_length)) {
419
struct strbuf quoted = STRBUF_INIT;
420
add_rfc822_quoted("ed, line, display_name_length);
415
- add_rfc2047(sb, quoted.buf, quoted.len,
416
- encoding, RFC2047_ADDRESS);
421
+ strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
422
+ -6, 1, max_length);
423
strbuf_release("ed);
424
+ } else {
425
+ strbuf_add_wrapped_bytes(sb, line, display_name_length,
426
+ -6, 1, max_length);
427
}
419
- if (namelen - display_name_length + last_line_length(sb) > 78) {
428
+ if (namelen - display_name_length + last_line_length(sb) > max_length) {
429
strbuf_addch(sb, '\n');
430
if (!isspace(name_tail[0]))
431
strbuf_addch(sb, ' ');
@@ -1336,6 +1345,7 @@ void pp_title_line(const struct pretty_print_context *pp,
1345
const char *encoding,
1346
int need_8bit_cte)
1347
{
1348
+ static const int max_length = 78; /* per rfc2047 */
1349
struct strbuf title;
1350
1351
strbuf_init(&title, 80);
@@ -1345,7 +1355,12 @@ void pp_title_line(const struct pretty_print_context *pp,
1355
strbuf_grow(sb, title.len + 1024);
1356
if (pp->subject) {
1357
strbuf_addstr(sb, pp->subject);
1348
- add_rfc2047(sb, title.buf, title.len, encoding, RFC2047_SUBJECT);
1358
+ if (needs_rfc2047_encoding(title.buf, title.len, RFC2047_SUBJECT))
1359
+ add_rfc2047(sb, title.buf, title.len,
1360
+ encoding, RFC2047_SUBJECT);
1361
+ else
1362
+ strbuf_add_wrapped_bytes(sb, title.buf, title.len,
1363
+ -last_line_length(sb), 1, max_length);
1364
} else {
1365
strbuf_addbuf(sb, &title);
1366
}
t/t4014-format-patch.sh
+1
-1
@@ -839,7 +839,7 @@ test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessa
839
cat >expect <<'EOF'
840
From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
841
EOF
842
-test_expect_failure 'rfc2047-encoded from-headers leave no rfc822 specials' '
842
+test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
843
check_author "Föo B. Bar"
844
'
845