bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "lib.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "str.h"
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi#include "wildcard-match.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "array.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "rfc822-parser.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "rfc2231-parser.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "message-address.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "message-header-parser.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch#include "message-part-data.h"
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
042a58438dc324c6d4de18e4c8a68044d6328e66Stephan Boschconst char *message_part_envelope_headers[] = {
042a58438dc324c6d4de18e4c8a68044d6328e66Stephan Bosch "Date", "Subject", "From", "Sender", "Reply-To",
042a58438dc324c6d4de18e4c8a68044d6328e66Stephan Bosch "To", "Cc", "Bcc", "In-Reply-To", "Message-ID",
042a58438dc324c6d4de18e4c8a68044d6328e66Stephan Bosch NULL
042a58438dc324c6d4de18e4c8a68044d6328e66Stephan Bosch};
042a58438dc324c6d4de18e4c8a68044d6328e66Stephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch/*
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch *
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschbool message_part_data_is_plain_7bit(const struct message_part *part)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const struct message_part_data *data = part->data;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch i_assert(part->parent == NULL);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* if content-type is text/xxx we don't have to check any
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch multipart stuff */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if ((part->flags & MESSAGE_PART_FLAG_TEXT) == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (part->next != NULL || part->children != NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE; /* shouldn't happen normally.. */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* must be text/plain */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (data->content_subtype != NULL &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch strcasecmp(data->content_subtype, "plain") != 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* only allowed parameter is charset=us-ascii, which is also default */
89bc31f70e51f4a69e0444c4f893831f6e96456eTimo Sirainen if (data->content_type_params_count == 0) {
89bc31f70e51f4a69e0444c4f893831f6e96456eTimo Sirainen /* charset defaults to us-ascii */
89bc31f70e51f4a69e0444c4f893831f6e96456eTimo Sirainen } else if (data->content_type_params_count != 1 ||
89bc31f70e51f4a69e0444c4f893831f6e96456eTimo Sirainen strcasecmp(data->content_type_params[0].name, "charset") != 0 ||
89bc31f70e51f4a69e0444c4f893831f6e96456eTimo Sirainen strcasecmp(data->content_type_params[0].value,
89bc31f70e51f4a69e0444c4f893831f6e96456eTimo Sirainen MESSAGE_PART_DEFAULT_CHARSET) != 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (data->content_id != NULL ||
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_description != NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (data->content_transfer_encoding != NULL &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch strcasecmp(data->content_transfer_encoding, "7bit") != 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* BODYSTRUCTURE checks: */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (data->content_md5 != NULL ||
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_disposition != NULL ||
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_language != NULL ||
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_location != NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return FALSE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return TRUE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Boschbool message_part_data_get_filename(const struct message_part *part,
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch const char **filename_r)
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch{
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch const struct message_part_data *data = part->data;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch const struct message_part_param *params;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch unsigned int params_count, i;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch params = data->content_disposition_params;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch params_count = data->content_disposition_params_count;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch if (data->content_disposition != NULL &&
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch strcasecmp(data->content_disposition, "attachment") != 0) {
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch return FALSE;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch }
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch for (i = 0; i < params_count; i++) {
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch if (strcasecmp(params[i].name, "filename") == 0 &&
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch params[i].value != NULL) {
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch *filename_r = params[i].value;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch return TRUE;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch }
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch }
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch return FALSE;
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch}
6407243c0b7340dd7b53b96bcb8e6b0e1acdb104Stephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch/*
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch * Header parsing
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch/* Message part envelope */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschenum envelope_field {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_DATE = 0,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_SUBJECT,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_FROM,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_SENDER,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_REPLY_TO,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_TO,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_CC,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_BCC,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_IN_REPLY_TO,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_MESSAGE_ID,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ENVELOPE_FIELD_UNKNOWN
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch};
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic enum envelope_field
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschenvelope_get_field(const char *name)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch switch (*name) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'B':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'b':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Bcc") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_BCC;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'C':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'c':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Cc") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_CC;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'D':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'd':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Date") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_DATE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'F':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'f':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "From") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_FROM;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'I':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'i':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "In-reply-to") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_IN_REPLY_TO;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'M':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'm':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Message-id") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_MESSAGE_ID;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'R':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'r':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Reply-to") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_REPLY_TO;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'S':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 's':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Subject") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_SUBJECT;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Sender") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_SENDER;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'T':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 't':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "To") == 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_TO;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return ENVELOPE_FIELD_UNKNOWN;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschvoid message_part_envelope_parse_from_header(pool_t pool,
b674bd911aaab7e8b1a77c106a0b5bccb603439fStephan Bosch struct message_part_envelope **data,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct message_header_line *hdr)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
b674bd911aaab7e8b1a77c106a0b5bccb603439fStephan Bosch struct message_part_envelope *d;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch enum envelope_field field;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct message_address **addr_p;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const char **str_p;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (*data == NULL) {
b674bd911aaab7e8b1a77c106a0b5bccb603439fStephan Bosch *data = p_new(pool, struct message_part_envelope, 1);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (hdr == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch field = envelope_get_field(hdr->name);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (field == ENVELOPE_FIELD_UNKNOWN)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (hdr->continues) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* wait for full value */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch hdr->use_full_value = TRUE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch d = *data;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = NULL; str_p = NULL;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch switch (field) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_DATE:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str_p = &d->date;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_SUBJECT:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str_p = &d->subject;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_MESSAGE_ID:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str_p = &d->message_id;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_IN_REPLY_TO:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str_p = &d->in_reply_to;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_CC:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = &d->cc;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_BCC:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = &d->bcc;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_FROM:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = &d->from;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_SENDER:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = &d->sender;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_TO:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = &d->to;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_REPLY_TO:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch addr_p = &d->reply_to;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case ENVELOPE_FIELD_UNKNOWN:
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch i_unreached();
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (addr_p != NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch *addr_p = message_address_parse(pool, hdr->full_value,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch hdr->full_value_len,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch UINT_MAX, TRUE);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch } else if (str_p != NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch *str_p = p_strndup(pool,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch hdr->full_value, hdr->full_value_len);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch/* Message part data */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic void
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschparse_mime_parameters(struct rfc822_parser_context *parser,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch pool_t pool, const struct message_part_param **params_r,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch unsigned int *params_count_r)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const char *const *results;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct message_part_param *params;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch unsigned int params_count, i;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc2231_parse(parser, &results);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch params_count = str_array_length(results);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch i_assert((params_count % 2) == 0);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch params_count /= 2;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (params_count > 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch params = p_new(pool, struct message_part_param, params_count);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch for (i = 0; i < params_count; i++) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch params[i].name = p_strdup(pool, results[i*2+0]);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch params[i].value = p_strdup(pool, results[i*2+1]);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch *params_r = params;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch *params_count_r = params_count;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic void
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschparse_content_type(struct message_part_data *data,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch pool_t pool, struct message_header_line *hdr)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct rfc822_parser_context parser;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch string_t *str;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const char *value;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch unsigned int i;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch int ret;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_skip_lwsp(&parser);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str = t_str_new(256);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ret = rfc822_parse_content_type(&parser, str);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* Save content type and subtype */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch value = str_c(str);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch for (i = 0; value[i] != '\0'; i++) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (value[i] == '/') {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_subtype = p_strdup(pool, value + i+1);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str_truncate(str, i);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_type = p_strdup(pool, str_c(str));
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (ret < 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* Content-Type is broken, but we wanted to get it as well as
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch we could. Don't try to read the parameters anymore though.
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch We don't completely ignore a broken Content-Type, because
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch then it would be written as text/plain. This would cause a
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch mismatch with the message_part's MESSAGE_PART_FLAG_TEXT. */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_mime_parameters(&parser, pool,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch &data->content_type_params,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch &data->content_type_params_count);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic void
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschparse_content_transfer_encoding(struct message_part_data *data,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch pool_t pool, struct message_header_line *hdr)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct rfc822_parser_context parser;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch string_t *str;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_skip_lwsp(&parser);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str = t_str_new(256);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (rfc822_parse_mime_token(&parser, str) >= 0 &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_skip_lwsp(&parser) == 0 && str_len(str) > 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_transfer_encoding =
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch p_strdup(pool, str_c(str));
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic void
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschparse_content_disposition(struct message_part_data *data,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch pool_t pool, struct message_header_line *hdr)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct rfc822_parser_context parser;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch string_t *str;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_skip_lwsp(&parser);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str = t_str_new(256);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (rfc822_parse_mime_token(&parser, str) < 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_disposition = p_strdup(pool, str_c(str));
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_mime_parameters(&parser, pool,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch &data->content_disposition_params,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch &data->content_disposition_params_count);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic void
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschparse_content_language(struct message_part_data *data,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch pool_t pool, const unsigned char *value, size_t value_len)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct rfc822_parser_context parser;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch ARRAY_TYPE(const_string) langs;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch string_t *str;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* Language-Header = "Content-Language" ":" 1#Language-tag
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch Language-Tag = Primary-tag *( "-" Subtag )
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch Primary-tag = 1*8ALPHA
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch Subtag = 1*8ALPHA */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_parser_init(&parser, value, value_len, NULL);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch t_array_init(&langs, 16);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str = t_str_new(128);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_skip_lwsp(&parser);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch while (rfc822_parse_atom(&parser, str) >= 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const char *lang = p_strdup(pool, str_c(str));
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch array_append(&langs, &lang, 1);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch str_truncate(str, 0);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (parser.data == parser.end || *parser.data != ',')
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parser.data++;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch rfc822_skip_lwsp(&parser);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (array_count(&langs) > 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch array_append_zero(&langs);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_language =
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch p_strarray_dup(pool, array_idx(&langs, 0));
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschstatic void
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschparse_content_header(struct message_part_data *data,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch pool_t pool, struct message_header_line *hdr)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const char *name = hdr->name + strlen("Content-");
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch const char *value;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (hdr->continues) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch hdr->use_full_value = TRUE;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch value = t_strndup(hdr->full_value, hdr->full_value_len);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch switch (*name) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'i':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'I':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "ID") == 0 && data->content_id == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_id = p_strdup(pool, value);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'm':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'M':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "MD5") == 0 && data->content_md5 == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_md5 = p_strdup(pool, value);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 't':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'T':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Type") == 0 && data->content_type == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_content_type(data, pool, hdr);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch else if (strcasecmp(name, "Transfer-Encoding") == 0 &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_transfer_encoding == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_content_transfer_encoding(data, pool, hdr);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'l':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'L':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Language") == 0 &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_language == NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_content_language(data, pool,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch hdr->full_value, hdr->full_value_len);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch } else if (strcasecmp(name, "Location") == 0 &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_location == NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_location = p_strdup(pool, value);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'd':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch case 'D':
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strcasecmp(name, "Description") == 0 &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_description == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_description = p_strdup(pool, value);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch else if (strcasecmp(name, "Disposition") == 0 &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch data->content_disposition_params == NULL)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_content_disposition(data, pool, hdr);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch break;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch}
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Boschvoid message_part_data_parse_from_header(pool_t pool,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct message_part *part,
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct message_header_line *hdr)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch{
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch struct message_part_data *part_data;
b674bd911aaab7e8b1a77c106a0b5bccb603439fStephan Bosch struct message_part_envelope *envelope;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch bool parent_rfc822;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (hdr == NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (part->data == NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* no Content-* headers. add an empty context
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch structure anyway. */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch part->data = part_data =
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch p_new(pool, struct message_part_data, 1);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch } else if ((part->flags & MESSAGE_PART_FLAG_IS_MIME) == 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* If there was no Mime-Version, forget all
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch the Content-stuff */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch part_data = part->data;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch envelope = part_data->envelope;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch i_zero(part_data);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch part_data->envelope = envelope;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (hdr->eoh)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parent_rfc822 = part->parent != NULL &&
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch (part->parent->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (!parent_rfc822 && strncasecmp(hdr->name, "Content-", 8) != 0)
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch return;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (part->data == NULL) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* initialize message part data */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch part->data = part_data =
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch p_new(pool, struct message_part_data, 1);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch part_data = part->data;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (strncasecmp(hdr->name, "Content-", 8) == 0) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch T_BEGIN {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch parse_content_header(part_data, pool, hdr);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch } T_END;
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch if (parent_rfc822) {
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch /* message/rfc822, we need the envelope */
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch message_part_envelope_parse_from_header(pool, &part_data->envelope, hdr);
57e3b63a75335f45cf6cf9cd89317e2e6cec249dStephan Bosch }
cbf6592b0d839a93d0e09a2018ba1d1a661b5c57Timo Sirainen}
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomibool message_part_has_content_types(struct message_part *part,
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi const char *const *types)
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi{
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi struct message_part_data *data = part->data;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi bool ret = TRUE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi const char *const *ptr;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi const char *content_type;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi if (data->content_type == NULL)
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return FALSE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi else if (data->content_subtype == NULL)
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi content_type = t_strdup_printf("%s/", data->content_type);
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi else
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi content_type = t_strdup_printf("%s/%s", data->content_type,
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi data->content_subtype);
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi for(ptr = types; *ptr != NULL; ptr++) {
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi bool exclude = (**ptr == '!');
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi if (wildcard_match_icase(content_type, (*ptr)+(exclude?1:0)))
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi ret = !exclude;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi }
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return ret;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi}
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomibool message_part_has_parameter(struct message_part *part, const char *parameter,
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi bool has_value)
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi{
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi struct message_part_data *data = part->data;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi for (unsigned int i = 0; i < data->content_disposition_params_count; i++) {
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi const struct message_part_param *param =
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi &data->content_disposition_params[i];
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi if (strcasecmp(param->name, parameter) == 0 &&
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi (!has_value || *param->value != '\0')) {
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return TRUE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi }
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi }
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return FALSE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi}
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomibool message_part_is_attachment(struct message_part *part,
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi const struct message_part_attachment_settings *set)
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi{
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi struct message_part_data *data = part->data;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi i_assert(data != NULL);
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi /* see if the content-type is excluded */
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi if (set->content_type_filter != NULL &&
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi !message_part_has_content_types(part, set->content_type_filter))
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return FALSE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi /* accept any attachment, or any inlined attachment with filename,
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi unless inlined ones are excluded */
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi if (null_strcasecmp(data->content_disposition, "attachment") == 0 ||
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi (!set->exclude_inlined &&
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi null_strcasecmp(data->content_disposition, "inline") == 0 &&
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi message_part_has_parameter(part, "filename", FALSE)))
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return TRUE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi return FALSE;
bc41d811809ca144922697333b78a857b97546c9Aki Tuomi}