From: Aki Tuomi Date: Fri, 10 Nov 2017 12:32:44 +0000 (+0200) Subject: lib-mail: Add message_part_has_attachment X-Git-Tag: 2.3.1~365 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ce0a94fd329051c288e8cdcc0228a869c5d2fc23;p=thirdparty%2Fdovecot%2Fcore.git lib-mail: Add message_part_has_attachment --- diff --git a/src/lib-mail/message-part-data.c b/src/lib-mail/message-part-data.c index 07243ca1ba..75651a2892 100644 --- a/src/lib-mail/message-part-data.c +++ b/src/lib-mail/message-part-data.c @@ -2,6 +2,7 @@ #include "lib.h" #include "str.h" +#include "wildcard-match.h" #include "array.h" #include "rfc822-parser.h" #include "rfc2231-parser.h" @@ -498,3 +499,65 @@ void message_part_data_parse_from_header(pool_t pool, message_part_envelope_parse_from_header(pool, &part_data->envelope, hdr); } } + +bool message_part_has_content_types(struct message_part *part, + const char *const *types) +{ + struct message_part_data *data = part->data; + bool ret = TRUE; + const char *const *ptr; + const char *content_type; + + if (data->content_type == NULL) + return FALSE; + else if (data->content_subtype == NULL) + content_type = t_strdup_printf("%s/", data->content_type); + else + content_type = t_strdup_printf("%s/%s", data->content_type, + data->content_subtype); + for(ptr = types; *ptr != NULL; ptr++) { + bool exclude = (**ptr == '!'); + if (wildcard_match_icase(content_type, (*ptr)+(exclude?1:0))) + ret = !exclude; + } + + return ret; +} + +bool message_part_has_parameter(struct message_part *part, const char *parameter, + bool has_value) +{ + struct message_part_data *data = part->data; + + for (unsigned int i = 0; i < data->content_disposition_params_count; i++) { + const struct message_part_param *param = + &data->content_disposition_params[i]; + if (strcasecmp(param->name, parameter) == 0 && + (!has_value || *param->value != '\0')) { + return TRUE; + } + } + return FALSE; +} + +bool message_part_is_attachment(struct message_part *part, + const struct message_part_attachment_settings *set) +{ + struct message_part_data *data = part->data; + + i_assert(data != NULL); + + /* see if the content-type is excluded */ + if (set->content_type_filter != NULL && + !message_part_has_content_types(part, set->content_type_filter)) + return FALSE; + + /* accept any attachment, or any inlined attachment with filename, + unless inlined ones are excluded */ + if (null_strcasecmp(data->content_disposition, "attachment") == 0 || + (!set->exclude_inlined && + null_strcasecmp(data->content_disposition, "inline") == 0 && + message_part_has_parameter(part, "filename", FALSE))) + return TRUE; + return FALSE; +} diff --git a/src/lib-mail/message-part-data.h b/src/lib-mail/message-part-data.h index 6a0fc4c6b4..5ff9ffe1bc 100644 --- a/src/lib-mail/message-part-data.h +++ b/src/lib-mail/message-part-data.h @@ -38,6 +38,25 @@ struct message_part_data { struct message_part_envelope *envelope; }; +struct message_part_attachment_settings { + /* By default, all attachments with content-disposition=attachment + or content-disposition=inline;filename=... are consired as an + attachment. + + If content_type_filter is set to an array of masks, then + anything starting with ! is excluded, and anything without + is considered negating exclusion. Setting foo/bar alone will */ +// not do anything, but setting !foo/*, foo/bar, will exclude + /* all attachments with foo/anything content type, but will + accept foo/bar. + + Setting exclude_inlined, will exclude **any** inlined attachment + regardless of what content_type_filter is. + */ + const char *const *content_type_filter; + bool exclude_inlined; +}; + extern const char *message_part_envelope_headers[]; /* @@ -54,6 +73,17 @@ bool message_part_data_is_plain_7bit(const struct message_part *part) bool message_part_data_get_filename(const struct message_part *part, const char **filename_r); +/* See message_part_attachment_settings */ +bool message_part_has_content_types(struct message_part *part, const char *const *types); + +/* Returns TRUE if message part has given parameter, and has non-empty + value if has_value is TRUE. */ +bool message_part_has_parameter(struct message_part *part, const char *parameter, + bool has_value); + +/* Check if part is attachment according to given settings */ +bool message_part_is_attachment(struct message_part *part, + const struct message_part_attachment_settings *set); /* * Header parsing */