changeset 22780:a982d52a740b

lib-mail: Add message_part_has_attachment
author Aki Tuomi <aki.tuomi@dovecot.fi>
date Fri, 10 Nov 2017 14:32:44 +0200
parents ecbd87187f4f
children 4b60d9bdc1a7
files src/lib-mail/message-part-data.c src/lib-mail/message-part-data.h
diffstat 2 files changed, 93 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-mail/message-part-data.c	Mon Jan 22 13:33:29 2018 +0200
+++ b/src/lib-mail/message-part-data.c	Fri Nov 10 14:32:44 2017 +0200
@@ -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 @@
 		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;
+}
--- a/src/lib-mail/message-part-data.h	Mon Jan 22 13:33:29 2018 +0200
+++ b/src/lib-mail/message-part-data.h	Fri Nov 10 14:32:44 2017 +0200
@@ -38,6 +38,25 @@
 	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_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
  */