static int handle_commit_msg(struct mailinfo *mi, struct strbuf *line) { assert(!mi->filter_stage); if (mi->header_stage) { 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) { mi->header_stage = check_inbody_header(mi, line); if (mi->header_stage) return 0; } else /* Only trim the first (blank) line of the commit message * when ignoring in-body headers. */ mi->header_stage = 0; /* normalize the log message to UTF-8. */ if (convert_to_utf8(mi, line, mi->charset.buf)) return 0; /* mi->input_error already set */ if (mi->use_scissors && is_scissors_line(line->buf)) { int i; strbuf_setlen(&mi->log_message, 0); mi->header_stage = 1; /* * We may have already read "secondary headers"; purge * them to give ourselves a clean restart. */ for (i = 0; header[i]; i++) { if (mi->s_hdr_data[i]) strbuf_release(mi->s_hdr_data[i]); mi->s_hdr_data[i] = NULL; } return 0; } if (patchbreak(line)) { if (mi->message_id) strbuf_addf(&mi->log_message, "Message-Id: %s\n", mi->message_id); return 1; } strbuf_addbuf(&mi->log_message, line); return 0; }
static int check_inbody_header(struct mailinfo *mi, const struct strbuf *line) { if (mi->inbody_header_accum.len && (line->buf[0] == ' ' || line->buf[0] == '\t')) { if (mi->use_scissors && is_scissors_line(line->buf)) { /* * This is a scissors line; do not consider this line * as a header continuation line. */ flush_inbody_header_accum(mi); return 0; } strbuf_strip_suffix(&mi->inbody_header_accum, "\n"); strbuf_addbuf(&mi->inbody_header_accum, line); return 1; } flush_inbody_header_accum(mi); if (starts_with(line->buf, ">From") && isspace(line->buf[5])) return is_format_patch_separator(line->buf + 1, line->len - 1); if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) { int i; for (i = 0; header[i]; i++) if (!strcmp("Subject", header[i])) { handle_header(&mi->s_hdr_data[i], line); return 1; } return 0; } if (is_inbody_header(mi, line)) { strbuf_addbuf(&mi->inbody_header_accum, line); return 1; } return 0; }
static void handle_body(struct mailinfo *mi, struct strbuf *line) { struct strbuf prev = STRBUF_INIT; /* Skip up to the first boundary */ if (*(mi->content_top)) { if (!find_boundary(mi, line)) goto handle_body_out; } do { /* process any boundary lines */ if (*(mi->content_top) && is_multipart_boundary(mi, line)) { /* flush any leftover */ if (prev.len) { handle_filter(mi, &prev); strbuf_reset(&prev); } if (!handle_boundary(mi, line)) goto handle_body_out; } /* Unwrap transfer encoding */ decode_transfer_encoding(mi, line); switch (mi->transfer_encoding) { case TE_BASE64: case TE_QP: { struct strbuf **lines, **it, *sb; /* Prepend any previous partial lines */ strbuf_insert(line, 0, prev.buf, prev.len); strbuf_reset(&prev); /* * This is a decoded line that may contain * multiple new lines. Pass only one chunk * at a time to handle_filter() */ lines = strbuf_split(line, '\n'); for (it = lines; (sb = *it); it++) { if (*(it + 1) == NULL) /* The last line */ if (sb->buf[sb->len - 1] != '\n') { /* Partial line, save it for later. */ strbuf_addbuf(&prev, sb); break; } handle_filter(mi, sb); } /* * The partial chunk is saved in "prev" and will be * appended by the next iteration of read_line_with_nul(). */ strbuf_list_free(lines); break; } default: handle_filter(mi, line); } if (mi->input_error) break; } while (!strbuf_getwholeline(line, mi->input, '\n')); flush_inbody_header_accum(mi); handle_body_out: strbuf_release(&prev); }