message-part-data.c revision b674bd911aaab7e8b1a77c106a0b5bccb603439f
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2014-2017 Dovecot authors, see the included COPYING file */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenconst char *message_part_envelope_headers[] = {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "Date", "Subject", "From", "Sender", "Reply-To",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "To", "Cc", "Bcc", "In-Reply-To", "Message-ID",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenbool message_part_data_is_plain_7bit(const struct message_part *part)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const struct message_part_data *data = part->data;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* if content-type is text/xxx we don't have to check any
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen multipart stuff */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((part->flags & MESSAGE_PART_FLAG_TEXT) == 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (part->next != NULL || part->children != NULL)
46e917c9fa05cbe7bddf805d3a9838b61e3960e1Timo Sirainen return FALSE; /* shouldn't happen normally.. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* must be text/plain */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen strcasecmp(data->content_subtype, "plain") != 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* only allowed parameter is charset=us-ascii, which is also default */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (strcasecmp(data->content_type_params[0].name, "charset") != 0 ||
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (data->content_transfer_encoding != NULL &&
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen strcasecmp(data->content_transfer_encoding, "7bit") != 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* BODYSTRUCTURE checks: */
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen * Header parsing
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen/* Message part envelope */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid message_part_envelope_parse_from_header(pool_t pool,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char **str_p;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *data = p_new(pool, struct message_part_envelope, 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* wait for full value */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *addr_p = message_address_parse(pool, hdr->full_value,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Message part data */
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainenparse_mime_parameters(struct rfc822_parser_context *parser,
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainen pool_t pool, const struct message_part_param **params_r,
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainen const char *const *results;
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainen unsigned int params_count, i;
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainen params = p_new(pool, struct message_part_param, params_count);
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainen for (i = 0; i < params_count; i++) {
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainen params[i].name = p_strdup(pool, results[i*2+0]);
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainen params[i].value = p_strdup(pool, results[i*2+1]);
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainenparse_content_type(struct message_part_data *data,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen unsigned int i;
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen ret = rfc822_parse_content_type(&parser, str);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen /* Save content type and subtype */
1ee74d70bb758637e560d556c7240563967d22c8Timo Sirainen data->content_subtype = p_strdup(pool, value + i+1);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen data->content_type = p_strdup(pool, str_c(str));
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen /* Content-Type is broken, but we wanted to get it as well as
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen we could. Don't try to read the parameters anymore though.
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen We don't completely ignore a broken Content-Type, because
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen then it would be written as text/plain. This would cause a
1ee74d70bb758637e560d556c7240563967d22c8Timo Sirainen mismatch with the message_part's MESSAGE_PART_FLAG_TEXT. */
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainenparse_content_transfer_encoding(struct message_part_data *data,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (rfc822_parse_mime_token(&parser, str) >= 0 &&
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen rfc822_skip_lwsp(&parser) == 0 && str_len(str) > 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenparse_content_disposition(struct message_part_data *data,
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (rfc822_parse_mime_token(&parser, str) < 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen data->content_disposition = p_strdup(pool, str_c(str));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenparse_content_language(struct message_part_data *data,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pool_t pool, const unsigned char *value, size_t value_len)
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen /* Language-Header = "Content-Language" ":" 1#Language-tag
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen Language-Tag = Primary-tag *( "-" Subtag )
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen Primary-tag = 1*8ALPHA
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen Subtag = 1*8ALPHA */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen rfc822_parser_init(&parser, value, value_len, NULL);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen while (rfc822_parse_atom(&parser, str) >= 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char *lang = p_strdup(pool, str_c(str));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (parser.data == parser.end || *parser.data != ',')
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenparse_content_header(struct message_part_data *data,
const char *value;
switch (*name) {
bool parent_rfc822;
T_BEGIN {
} T_END;
if (parent_rfc822) {