Merge branch 'lt/mailinfo-in-body-header-continuation'
authorJunio C Hamano <gitster@pobox.com>
Thu, 20 Apr 2017 04:37:15 +0000 (21:37 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 20 Apr 2017 04:37:15 +0000 (21:37 -0700)
If a patch e-mail had its first paragraph after an in-body header
indented (even after a blank line after the in-body header line),
the indented line was mistook as a continuation of the in-body
header. This has been fixed.

* lt/mailinfo-in-body-header-continuation:
mailinfo: fix in-body header continuations

1  2 
mailinfo.c
diff --combined mailinfo.c
index a489d9d0fbcc37a1198247a8daae4b3104ebe284,1e4e28309941ae7207950e626c46932b32003c71..68037758f2f01be6edfab34b7871af68a17163eb
@@@ -54,86 -54,6 +54,86 @@@ static void parse_bogus_from(struct mai
        get_sane_name(&mi->name, &mi->name, &mi->email);
  }
  
 +static const char *unquote_comment(struct strbuf *outbuf, const char *in)
 +{
 +      int c;
 +      int take_next_litterally = 0;
 +
 +      strbuf_addch(outbuf, '(');
 +
 +      while ((c = *in++) != 0) {
 +              if (take_next_litterally == 1) {
 +                      take_next_litterally = 0;
 +              } else {
 +                      switch (c) {
 +                      case '\\':
 +                              take_next_litterally = 1;
 +                              continue;
 +                      case '(':
 +                              in = unquote_comment(outbuf, in);
 +                              continue;
 +                      case ')':
 +                              strbuf_addch(outbuf, ')');
 +                              return in;
 +                      }
 +              }
 +
 +              strbuf_addch(outbuf, c);
 +      }
 +
 +      return in;
 +}
 +
 +static const char *unquote_quoted_string(struct strbuf *outbuf, const char *in)
 +{
 +      int c;
 +      int take_next_litterally = 0;
 +
 +      while ((c = *in++) != 0) {
 +              if (take_next_litterally == 1) {
 +                      take_next_litterally = 0;
 +              } else {
 +                      switch (c) {
 +                      case '\\':
 +                              take_next_litterally = 1;
 +                              continue;
 +                      case '"':
 +                              return in;
 +                      }
 +              }
 +
 +              strbuf_addch(outbuf, c);
 +      }
 +
 +      return in;
 +}
 +
 +static void unquote_quoted_pair(struct strbuf *line)
 +{
 +      struct strbuf outbuf;
 +      const char *in = line->buf;
 +      int c;
 +
 +      strbuf_init(&outbuf, line->len);
 +
 +      while ((c = *in++) != 0) {
 +              switch (c) {
 +              case '"':
 +                      in = unquote_quoted_string(&outbuf, in);
 +                      continue;
 +              case '(':
 +                      in = unquote_comment(&outbuf, in);
 +                      continue;
 +              }
 +
 +              strbuf_addch(&outbuf, c);
 +      }
 +
 +      strbuf_swap(&outbuf, line);
 +      strbuf_release(&outbuf);
 +
 +}
 +
  static void handle_from(struct mailinfo *mi, const struct strbuf *from)
  {
        char *at;
        strbuf_init(&f, from->len);
        strbuf_addbuf(&f, from);
  
 +      unquote_quoted_pair(&f);
 +
        at = strchr(f.buf, '@');
        if (!at) {
                parse_bogus_from(mi, from);
@@@ -710,8 -628,7 +710,8 @@@ static void flush_inbody_header_accum(s
  {
        if (!mi->inbody_header_accum.len)
                return;
 -      assert(check_header(mi, &mi->inbody_header_accum, mi->s_hdr_data, 0));
 +      if (!check_header(mi, &mi->inbody_header_accum, mi->s_hdr_data, 0))
 +              die("BUG: inbody_header_accum, if not empty, must always contain a valid in-body header");
        strbuf_reset(&mi->inbody_header_accum);
  }
  
@@@ -757,8 -674,13 +757,13 @@@ static int handle_commit_msg(struct mai
        assert(!mi->filter_stage);
  
        if (mi->header_stage) {
-               if (!line->len || (line->len == 1 && line->buf[0] == '\n'))
+               if (!line->len || (line->len == 1 && line->buf[0] == '\n')) {
+                       if (mi->inbody_header_accum.len) {
+                               flush_inbody_header_accum(mi);
+                               mi->header_stage = 0;
+                       }
                        return 0;
+               }
        }
  
        if (mi->use_inbody_headers && mi->header_stage) {