t / t4256 / 1 / patchon commit Merge branch 'en/double-semicolon-fix' (ae109a9)
   1From: A <author@example.com>
   2Subject: [PATCH] mailinfo: support format=flowed
   3Message-ID: <aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa@example.com>
   4Date: Sat, 25 Aug 2018 22:04:50 +0200
   5User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101
   6 Thunderbird/60.0
   7MIME-Version: 1.0
   8Content-Type: text/plain; charset=utf-8; format=flowed
   9Content-Language: en-US
  10Content-Transfer-Encoding: 7bit
  11
  12---
  13  mailinfo.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
  14  1 file changed, 62 insertions(+), 2 deletions(-)
  15
  16diff --git a/mailinfo.c b/mailinfo.c
  17index 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 
  26char *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, 
  46struct 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, 
 100struct 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, 
 110struct 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-- 
 1292.18.0