From b8b6f750110e2542a30006d1eee1fdf268c68cd5 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Fri, 8 Jan 2016 20:49:39 +0100
Subject: [PATCH] lib-sieve: message body: Amended messaage part API with some
 more access functions. Added support for getting message part information and
 content.

---
 src/lib-sieve/sieve-message.c | 74 +++++++++++++++++++++++++++++++++++
 src/lib-sieve/sieve-message.h | 28 ++++++++++++-
 2 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/src/lib-sieve/sieve-message.c b/src/lib-sieve/sieve-message.c
index f744b27f3..003249f3a 100644
--- a/src/lib-sieve/sieve-message.c
+++ b/src/lib-sieve/sieve-message.c
@@ -848,6 +848,80 @@ int sieve_message_get_header_fields
 	return SIEVE_EXEC_OK;
 }
 
+/*
+ * Message part
+ */
+
+struct sieve_message_part *sieve_message_part_parent
+(struct sieve_message_part *mpart)
+{
+	return mpart->parent;
+}
+
+struct sieve_message_part *sieve_message_part_next
+(struct sieve_message_part *mpart)
+{
+	return mpart->next;
+}
+
+struct sieve_message_part *sieve_message_part_children
+(struct sieve_message_part *mpart)
+{
+	return mpart->children;
+}
+
+const char *sieve_message_part_content_type
+(struct sieve_message_part *mpart)
+{
+	return mpart->content_type;
+}
+
+const char *sieve_message_part_content_disposition
+(struct sieve_message_part *mpart)
+{
+	return mpart->content_disposition;
+}
+
+int sieve_message_part_get_first_header
+(struct sieve_message_part *mpart, const char *field,
+	const char **value_r)
+{
+	const struct sieve_message_header *headers;
+	unsigned int i, count;
+
+	headers = array_get(&mpart->headers, &count);
+	for ( i = 0; i < count; i++ ) {
+		if ( strcasecmp( headers[i].name, field) == 0 ) {
+			i_assert( headers[i].value[headers[i].value_len] == '\0' );
+			*value_r = (const char *)headers[i].value;
+			return 1;
+		}
+	}
+
+	*value_r = NULL;
+	return 0;
+}
+
+void sieve_message_part_get_data
+(struct sieve_message_part *mpart,
+	struct sieve_message_part_data *data, bool text)
+{
+	memset(data, 0, sizeof(*data));
+	data->content_type = mpart->content_type;
+	data->content_disposition = mpart->content_disposition;
+
+	if ( !text ) {
+		data->content = mpart->decoded_body;
+		data->size = mpart->decoded_body_size;
+	} else if ( mpart->children != NULL ) {
+		data->content = "";
+		data->size = 0;
+	} else {
+		data->content = mpart->text_body;
+		data->size = mpart->text_body_size;
+	}
+}
+
 /*
  * Message body
  */
diff --git a/src/lib-sieve/sieve-message.h b/src/lib-sieve/sieve-message.h
index 09044a246..e7f283d33 100644
--- a/src/lib-sieve/sieve-message.h
+++ b/src/lib-sieve/sieve-message.h
@@ -204,9 +204,11 @@ int sieve_message_get_header_fields
 		bool mime_decode, struct sieve_stringlist **fields_r);
 
 /*
- * Message body
+ * Message part
  */
 
+struct sieve_message_part;
+
 struct sieve_message_part_data {
 	const char *content_type;
 	const char *content_disposition;
@@ -215,6 +217,30 @@ struct sieve_message_part_data {
 	unsigned long size;
 };
 
+struct sieve_message_part *sieve_message_part_parent
+	(struct sieve_message_part *mpart) ATTR_PURE;
+struct sieve_message_part *sieve_message_part_next
+	(struct sieve_message_part *mpart) ATTR_PURE;
+struct sieve_message_part *sieve_message_part_children
+	(struct sieve_message_part *mpart) ATTR_PURE;
+
+const char *sieve_message_part_content_type
+	(struct sieve_message_part *mpart) ATTR_PURE;
+const char *sieve_message_part_content_disposition
+	(struct sieve_message_part *mpart) ATTR_PURE;
+
+int sieve_message_part_get_first_header
+	(struct sieve_message_part *mpart, const char *field,
+		const char **value_r);
+
+void sieve_message_part_get_data
+	(struct sieve_message_part *mpart,
+		struct sieve_message_part_data *data, bool text);
+
+/*
+ * Message body
+ */
+
 int sieve_message_body_get_content
 	(const struct sieve_runtime_env *renv,
 		const char * const *content_types,
-- 
GitLab