about summary refs log tree commit diff
path: root/t/t4256/1/patch
blob: bd0d8b0251453844eb5768e017af7448e7c0cc2a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From: A <author@example.com>
Subject: [PATCH] mailinfo: support format=flowed
Message-ID: <aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa@example.com>
Date: Sat, 25 Aug 2018 22:04:50 +0200
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101
 Thunderbird/60.0
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit

---
  mailinfo.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
  1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/mailinfo.c b/mailinfo.c
index 3281a37d51..b395adbdf2 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -237,11 +237,22 @@ static int slurp_attr(const char *line, const char 
*name, struct strbuf *attr)
  	return 1;
  }

+static int has_attr_value(const char *line, const char *name, const 
char *value)
+{
+	struct strbuf sb = STRBUF_INIT;
+	int rc = slurp_attr(line, name, &sb) && !strcasecmp(sb.buf, value);
+	strbuf_release(&sb);
+	return rc;
+}
+
  static void handle_content_type(struct mailinfo *mi, struct strbuf *line)
  {
  	struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
  	strbuf_init(boundary, line->len);

+	mi->format_flowed = has_attr_value(line->buf, "format=", "flowed");
+	mi->delsp = has_attr_value(line->buf, "delsp=", "yes");
+
  	if (slurp_attr(line->buf, "boundary=", boundary)) {
  		strbuf_insert(boundary, 0, "--", 2);
  		if (++mi->content_top >= &mi->content[MAX_BOUNDARIES]) {
@@ -964,6 +975,52 @@ static int handle_boundary(struct mailinfo *mi, 
struct strbuf *line)
  	return 1;
  }

+static void handle_filter_flowed(struct mailinfo *mi, struct strbuf *line,
+				 struct strbuf *prev)
+{
+	size_t len = line->len;
+	const char *rest;
+
+	if (!mi->format_flowed) {
+		handle_filter(mi, line);
+		return;
+	}
+
+	if (line->buf[len - 1] == '\n') {
+		len--;
+		if (len && line->buf[len - 1] == '\r')
+			len--;
+	}
+
+	/* Keep signature separator as-is. */
+	if (skip_prefix(line->buf, "-- ", &rest) && rest - line->buf == len) {
+		if (prev->len) {
+			handle_filter(mi, prev);
+			strbuf_reset(prev);
+		}
+		handle_filter(mi, line);
+		return;
+	}
+
+	/* Unstuff space-stuffed line. */
+	if (len && line->buf[0] == ' ') {
+		strbuf_remove(line, 0, 1);
+		len--;
+	}
+
+	/* Save flowed line for later, but without the soft line break. */
+	if (len && line->buf[len - 1] == ' ') {
+		strbuf_add(prev, line->buf, len - !!mi->delsp);
+		return;
+	}
+
+	/* Prepend any previous partial lines */
+	strbuf_insert(line, 0, prev->buf, prev->len);
+	strbuf_reset(prev);
+
+	handle_filter(mi, line);
+}
+
  static void handle_body(struct mailinfo *mi, struct strbuf *line)
  {
  	struct strbuf prev = STRBUF_INIT;
@@ -1012,7 +1069,7 @@ static void handle_body(struct mailinfo *mi, 
struct strbuf *line)
  						strbuf_addbuf(&prev, sb);
  						break;
  					}
-				handle_filter(mi, sb);
+				handle_filter_flowed(mi, sb, &prev);
  			}
  			/*
  			 * The partial chunk is saved in "prev" and will be
@@ -1022,13 +1079,16 @@ static void handle_body(struct mailinfo *mi, 
struct strbuf *line)
  			break;
  		}
  		default:
-			handle_filter(mi, line);
+			handle_filter_flowed(mi, line, &prev);
  		}

  		if (mi->input_error)
  			break;
  	} while (!strbuf_getwholeline(line, mi->input, '\n'));

+	if (prev.len)
+		handle_filter(mi, &prev);
+
  	flush_inbody_header_accum(mi);

  handle_body_out:
-- 
2.18.0