Merge branch 'nd/test-tool'
[git] / t / t4256 / 1 / patch
1 From: A <author@example.com>
2 Subject: [PATCH] mailinfo: support format=flowed
3 Message-ID: <aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa@example.com>
4 Date: Sat, 25 Aug 2018 22:04:50 +0200
5 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101
6  Thunderbird/60.0
7 MIME-Version: 1.0
8 Content-Type: text/plain; charset=utf-8; format=flowed
9 Content-Language: en-US
10 Content-Transfer-Encoding: 7bit
11
12 ---
13   mailinfo.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
14   1 file changed, 62 insertions(+), 2 deletions(-)
15
16 diff --git a/mailinfo.c b/mailinfo.c
17 index 3281a37d51..b395adbdf2 100644
18 --- a/mailinfo.c
19 +++ b/mailinfo.c
20 @@ -237,11 +237,22 @@ static int slurp_attr(const char *line, const char 
21 *name, struct strbuf *attr)
22         return 1;
23   }
24
25 +static int has_attr_value(const char *line, const char *name, const 
26 char *value)
27 +{
28 +       struct strbuf sb = STRBUF_INIT;
29 +       int rc = slurp_attr(line, name, &sb) && !strcasecmp(sb.buf, value);
30 +       strbuf_release(&sb);
31 +       return rc;
32 +}
33 +
34   static void handle_content_type(struct mailinfo *mi, struct strbuf *line)
35   {
36         struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
37         strbuf_init(boundary, line->len);
38
39 +       mi->format_flowed = has_attr_value(line->buf, "format=", "flowed");
40 +       mi->delsp = has_attr_value(line->buf, "delsp=", "yes");
41 +
42         if (slurp_attr(line->buf, "boundary=", boundary)) {
43                 strbuf_insert(boundary, 0, "--", 2);
44                 if (++mi->content_top >= &mi->content[MAX_BOUNDARIES]) {
45 @@ -964,6 +975,52 @@ static int handle_boundary(struct mailinfo *mi, 
46 struct strbuf *line)
47         return 1;
48   }
49
50 +static void handle_filter_flowed(struct mailinfo *mi, struct strbuf *line,
51 +                                struct strbuf *prev)
52 +{
53 +       size_t len = line->len;
54 +       const char *rest;
55 +
56 +       if (!mi->format_flowed) {
57 +               handle_filter(mi, line);
58 +               return;
59 +       }
60 +
61 +       if (line->buf[len - 1] == '\n') {
62 +               len--;
63 +               if (len && line->buf[len - 1] == '\r')
64 +                       len--;
65 +       }
66 +
67 +       /* Keep signature separator as-is. */
68 +       if (skip_prefix(line->buf, "-- ", &rest) && rest - line->buf == len) {
69 +               if (prev->len) {
70 +                       handle_filter(mi, prev);
71 +                       strbuf_reset(prev);
72 +               }
73 +               handle_filter(mi, line);
74 +               return;
75 +       }
76 +
77 +       /* Unstuff space-stuffed line. */
78 +       if (len && line->buf[0] == ' ') {
79 +               strbuf_remove(line, 0, 1);
80 +               len--;
81 +       }
82 +
83 +       /* Save flowed line for later, but without the soft line break. */
84 +       if (len && line->buf[len - 1] == ' ') {
85 +               strbuf_add(prev, line->buf, len - !!mi->delsp);
86 +               return;
87 +       }
88 +
89 +       /* Prepend any previous partial lines */
90 +       strbuf_insert(line, 0, prev->buf, prev->len);
91 +       strbuf_reset(prev);
92 +
93 +       handle_filter(mi, line);
94 +}
95 +
96   static void handle_body(struct mailinfo *mi, struct strbuf *line)
97   {
98         struct strbuf prev = STRBUF_INIT;
99 @@ -1012,7 +1069,7 @@ static void handle_body(struct mailinfo *mi, 
100 struct strbuf *line)
101                                                 strbuf_addbuf(&prev, sb);
102                                                 break;
103                                         }
104 -                               handle_filter(mi, sb);
105 +                               handle_filter_flowed(mi, sb, &prev);
106                         }
107                         /*
108                          * The partial chunk is saved in "prev" and will be
109 @@ -1022,13 +1079,16 @@ static void handle_body(struct mailinfo *mi, 
110 struct strbuf *line)
111                         break;
112                 }
113                 default:
114 -                       handle_filter(mi, line);
115 +                       handle_filter_flowed(mi, line, &prev);
116                 }
117
118                 if (mi->input_error)
119                         break;
120         } while (!strbuf_getwholeline(line, mi->input, '\n'));
121
122 +       if (prev.len)
123 +               handle_filter(mi, &prev);
124 +
125         flush_inbody_header_accum(mi);
126
127   handle_body_out:
128 -- 
129 2.18.0