]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Add message_part_has_attachment
authorAki Tuomi <aki.tuomi@dovecot.fi>
Fri, 10 Nov 2017 12:32:44 +0000 (14:32 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 17 Jan 2018 13:48:00 +0000 (15:48 +0200)
src/lib-mail/message-part-data.c
src/lib-mail/message-part-data.h

index 07243ca1bad2aae49fc67c3125161b7ceed216c3..75651a2892499729f17ce6a733ff52c600433c95 100644 (file)
@@ -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;
+}
index 6a0fc4c6b4cc082d4ec6049aa4210ab8b3aafb98..5ff9ffe1bc6a8bce673da149cd675b411df07283 100644 (file)
@@ -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
  */