summaryrefslogtreecommitdiff
path: root/mailinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'mailinfo.c')
-rw-r--r--mailinfo.c79
1 files changed, 48 insertions, 31 deletions
diff --git a/mailinfo.c b/mailinfo.c
index b395adbdf2..5681d9130d 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -19,8 +19,7 @@ static void cleanup_space(struct strbuf *sb)
static void get_sane_name(struct strbuf *out, struct strbuf *name, struct strbuf *email)
{
struct strbuf *src = name;
- if (name->len < 3 || 60 < name->len || strchr(name->buf, '@') ||
- strchr(name->buf, '<') || strchr(name->buf, '>'))
+ if (name->len < 3 || 60 < name->len || strpbrk(name->buf, "@<>"))
src = email;
else if (name == out)
return;
@@ -254,7 +253,7 @@ static void handle_content_type(struct mailinfo *mi, struct strbuf *line)
mi->delsp = has_attr_value(line->buf, "delsp=", "yes");
if (slurp_attr(line->buf, "boundary=", boundary)) {
- strbuf_insert(boundary, 0, "--", 2);
+ strbuf_insertstr(boundary, 0, "--");
if (++mi->content_top >= &mi->content[MAX_BOUNDARIES]) {
error("Too many boundaries to handle");
mi->input_error = -1;
@@ -346,11 +345,17 @@ static const char *header[MAX_HDR_PARSED] = {
"From","Subject","Date",
};
-static inline int cmp_header(const struct strbuf *line, const char *hdr)
+static inline int skip_header(const struct strbuf *line, const char *hdr,
+ const char **outval)
{
- int len = strlen(hdr);
- return !strncasecmp(line->buf, hdr, len) && line->len > len &&
- line->buf[len] == ':' && isspace(line->buf[len + 1]);
+ const char *val;
+ if (!skip_iprefix(line->buf, hdr, &val) ||
+ *val++ != ':')
+ return 0;
+ while (isspace(*val))
+ val++;
+ *outval = val;
+ return 1;
}
static int is_format_patch_separator(const char *line, int len)
@@ -442,19 +447,21 @@ static int convert_to_utf8(struct mailinfo *mi,
struct strbuf *line, const char *charset)
{
char *out;
+ size_t out_len;
if (!mi->metainfo_charset || !charset || !*charset)
return 0;
if (same_encoding(mi->metainfo_charset, charset))
return 0;
- out = reencode_string(line->buf, mi->metainfo_charset, charset);
+ out = reencode_string_len(line->buf, line->len,
+ mi->metainfo_charset, charset, &out_len);
if (!out) {
mi->input_error = -1;
return error("cannot convert from %s to %s",
charset, mi->metainfo_charset);
}
- strbuf_attach(line, out, strlen(out), strlen(out));
+ strbuf_attach(line, out, out_len, out_len);
return 0;
}
@@ -543,22 +550,36 @@ release_return:
mi->input_error = -1;
}
+/*
+ * Returns true if "line" contains a header matching "hdr", in which case "val"
+ * will contain the value of the header with any RFC2047 B and Q encoding
+ * unwrapped, and optionally normalize the meta information to utf8.
+ */
+static int parse_header(const struct strbuf *line,
+ const char *hdr,
+ struct mailinfo *mi,
+ struct strbuf *val)
+{
+ const char *val_str;
+
+ if (!skip_header(line, hdr, &val_str))
+ return 0;
+ strbuf_addstr(val, val_str);
+ decode_header(mi, val);
+ return 1;
+}
+
static int check_header(struct mailinfo *mi,
const struct strbuf *line,
struct strbuf *hdr_data[], int overwrite)
{
- int i, ret = 0, len;
+ int i, ret = 0;
struct strbuf sb = STRBUF_INIT;
/* search for the interesting parts */
for (i = 0; header[i]; i++) {
- int len = strlen(header[i]);
- if ((!hdr_data[i] || overwrite) && cmp_header(line, header[i])) {
- /* Unwrap inline B and Q encoding, and optionally
- * normalize the meta information to utf8.
- */
- strbuf_add(&sb, line->buf + len + 2, line->len - len - 2);
- decode_header(mi, &sb);
+ if ((!hdr_data[i] || overwrite) &&
+ parse_header(line, header[i], mi, &sb)) {
handle_header(&hdr_data[i], &sb);
ret = 1;
goto check_header_out;
@@ -566,27 +587,17 @@ static int check_header(struct mailinfo *mi,
}
/* Content stuff */
- if (cmp_header(line, "Content-Type")) {
- len = strlen("Content-Type: ");
- strbuf_add(&sb, line->buf + len, line->len - len);
- decode_header(mi, &sb);
- strbuf_insert(&sb, 0, "Content-Type: ", len);
+ if (parse_header(line, "Content-Type", mi, &sb)) {
handle_content_type(mi, &sb);
ret = 1;
goto check_header_out;
}
- if (cmp_header(line, "Content-Transfer-Encoding")) {
- len = strlen("Content-Transfer-Encoding: ");
- strbuf_add(&sb, line->buf + len, line->len - len);
- decode_header(mi, &sb);
+ if (parse_header(line, "Content-Transfer-Encoding", mi, &sb)) {
handle_content_transfer_encoding(mi, &sb);
ret = 1;
goto check_header_out;
}
- if (cmp_header(line, "Message-Id")) {
- len = strlen("Message-Id: ");
- strbuf_add(&sb, line->buf + len, line->len - len);
- decode_header(mi, &sb);
+ if (parse_header(line, "Message-Id", mi, &sb)) {
if (mi->add_message_id)
mi->message_id = strbuf_detach(&sb, NULL);
ret = 1;
@@ -607,8 +618,9 @@ static int is_inbody_header(const struct mailinfo *mi,
const struct strbuf *line)
{
int i;
+ const char *val;
for (i = 0; header[i]; i++)
- if (!mi->s_hdr_data[i] && cmp_header(line, header[i]))
+ if (!mi->s_hdr_data[i] && skip_header(line, header[i], &val))
return 1;
return 0;
}
@@ -1126,6 +1138,11 @@ static void handle_info(struct mailinfo *mi)
else
continue;
+ if (memchr(hdr->buf, '\0', hdr->len)) {
+ error("a NUL byte in '%s' is not allowed.", header[i]);
+ mi->input_error = -1;
+ }
+
if (!strcmp(header[i], "Subject")) {
if (!mi->keep_subject) {
cleanup_subject(mi, hdr);