bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen#include "lib.h"
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen#include "buffer.h"
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen#include "message-parser.h"
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen#include "message-part-serialize.h"
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen/*
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen root part
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen root's first children
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen children's first children
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen ...
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen root's next children
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen ...
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen part
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen unsigned int flags
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen (not root part)
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen uoff_t physical_pos
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen uoff_t header_physical_size
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen uoff_t header_virtual_size
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen uoff_t body_physical_size
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen uoff_t body_virtual_size
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen (flags & (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_MESSAGE_RFC822))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen unsigned int body_lines
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen (flags & (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_MESSAGE_RFC822))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen unsigned int children_count
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen*/
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen#define MINIMUM_SERIALIZED_SIZE \
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen (sizeof(unsigned int) + sizeof(uoff_t) * 4)
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainenstruct deserialize_context {
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen pool_t pool;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen const unsigned char *data, *end;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen uoff_t pos;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen const char *error;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen};
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainenstatic void part_serialize(struct message_part *part, buffer_t *dest,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen unsigned int *children_count_r)
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen{
38499bb33c74acc6d725204e893cfc02a5890ec7Timo Sirainen unsigned int count, children_count;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen size_t children_offset;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool root = part->parent == NULL;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
38499bb33c74acc6d725204e893cfc02a5890ec7Timo Sirainen count = 0;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen while (part != NULL) {
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen /* create serialized part */
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->flags, sizeof(part->flags));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (root)
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen root = FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen else {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->physical_pos,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->physical_pos));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->header_size.physical_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->header_size.physical_size));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->header_size.virtual_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->header_size.virtual_size));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->body_size.physical_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->body_size.physical_size));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->body_size.virtual_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->body_size.virtual_size));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if ((part->flags & (MESSAGE_PART_FLAG_TEXT |
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &part->body_size.lines,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->body_size.lines));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
38499bb33c74acc6d725204e893cfc02a5890ec7Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if ((part->flags & (MESSAGE_PART_FLAG_MULTIPART |
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
2d5d7890bd9b282eb1092fc788a2432a6c79a7adTimo Sirainen children_offset = dest->used;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen children_count = 0;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_append(dest, &children_count,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(children_count));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (part->children != NULL) {
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen part_serialize(part->children, dest,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen &children_count);
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen buffer_write(dest, children_offset,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen &children_count,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(children_count));
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen } else {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen i_assert(part->children == NULL);
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen }
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen count++;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen part = part->next;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen }
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen *children_count_r = count;
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen}
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid message_part_serialize(struct message_part *part, buffer_t *dest)
900d1f655065fa0cfe601f537142eb212ef5c011Timo Sirainen{
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen unsigned int children_count;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen part_serialize(part, dest, &children_count);
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen}
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool read_next(struct deserialize_context *ctx,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen void *buffer, size_t buffer_size)
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen{
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (ctx->data + buffer_size > ctx->end) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx->error = "Not enough data";
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen memcpy(buffer, ctx->data, buffer_size);
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx->data += buffer_size;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return TRUE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen}
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic bool ATTR_NULL(2)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenmessage_part_deserialize_part(struct deserialize_context *ctx,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct message_part *parent,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen unsigned int siblings,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct message_part **part_r)
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen{
6b8d5b8d02bd888609f06366ffb5a5a1e6e7d251Timo Sirainen struct message_part *p, *part, *first_part, **next_part;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen unsigned int children_count;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen uoff_t pos;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool root = parent == NULL;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen first_part = NULL;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen next_part = NULL;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen while (siblings > 0) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen siblings--;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen part = p_new(ctx->pool, struct message_part, 1);
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen part->parent = parent;
6b8d5b8d02bd888609f06366ffb5a5a1e6e7d251Timo Sirainen for (p = parent; p != NULL; p = p->parent)
6b8d5b8d02bd888609f06366ffb5a5a1e6e7d251Timo Sirainen p->children_count++;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->flags, sizeof(part->flags)))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (root)
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen root = FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen else {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->physical_pos,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->physical_pos)))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen if (part->physical_pos < ctx->pos) {
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen ctx->error = "physical_pos less than expected";
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->header_size.physical_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->header_size.physical_size)))
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->header_size.virtual_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->header_size.virtual_size)))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (part->header_size.virtual_size <
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen part->header_size.physical_size) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx->error = "header_size.virtual_size too small";
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->body_size.physical_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->body_size.physical_size)))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->body_size.virtual_size,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->body_size.virtual_size)))
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if ((part->flags & (MESSAGE_PART_FLAG_TEXT |
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &part->body_size.lines,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(part->body_size.lines)))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (part->body_size.virtual_size <
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen part->body_size.physical_size) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx->error = "body_size.virtual_size too small";
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if ((part->flags & (MESSAGE_PART_FLAG_MULTIPART |
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!read_next(ctx, &children_count,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen sizeof(children_count)))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen } else {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen children_count = 0;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0) {
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen /* Only one child is possible */
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (children_count == 0) {
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen ctx->error =
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen "message/rfc822 part has no children";
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (children_count != 1) {
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen ctx->error = "message/rfc822 part "
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen "has multiple children";
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return FALSE;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (children_count > 0) {
a4f588460ae94749573097e04392780e17f7fcb2Timo Sirainen /* our children must be after our physical_pos+header
a4f588460ae94749573097e04392780e17f7fcb2Timo Sirainen and the last child must be within our size. */
a4f588460ae94749573097e04392780e17f7fcb2Timo Sirainen ctx->pos = part->physical_pos +
a4f588460ae94749573097e04392780e17f7fcb2Timo Sirainen part->header_size.physical_size;
a4f588460ae94749573097e04392780e17f7fcb2Timo Sirainen pos = ctx->pos + part->body_size.physical_size;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (!message_part_deserialize_part(ctx, part,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen children_count,
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen &part->children))
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (ctx->pos > pos) {
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx->error =
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen "child part location exceeds our size";
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen return FALSE;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx->pos = pos; /* save it for above check for parent */
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen }
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen if (first_part == NULL)
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen first_part = part;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen if (next_part != NULL)
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen *next_part = part;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen next_part = &part->next;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen }
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen *part_r = first_part;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen return TRUE;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen}
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
10da1ab399797ce44d37e0c464966e0a7cd5ff01Timo Sirainenstruct message_part *
10da1ab399797ce44d37e0c464966e0a7cd5ff01Timo Sirainenmessage_part_deserialize(pool_t pool, const void *data, size_t size,
10da1ab399797ce44d37e0c464966e0a7cd5ff01Timo Sirainen const char **error_r)
749c1abc1804e227afa6bae2d5ddf8bcc96e7cc4Timo Sirainen{
749c1abc1804e227afa6bae2d5ddf8bcc96e7cc4Timo Sirainen struct deserialize_context ctx;
749c1abc1804e227afa6bae2d5ddf8bcc96e7cc4Timo Sirainen struct message_part *part;
749c1abc1804e227afa6bae2d5ddf8bcc96e7cc4Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen ctx.pool = pool;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx.data = data;
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen ctx.end = ctx.data + size;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen if (!message_part_deserialize_part(&ctx, NULL, 1, &part)) {
10da1ab399797ce44d37e0c464966e0a7cd5ff01Timo Sirainen *error_r = ctx.error;
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen return NULL;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
ab170d6cf8aeb515bac7c07b37e525cbad96c299Timo Sirainen
a9c63bb1197ca14d17e081626df510b23d617899Timo Sirainen if (ctx.data != ctx.end) {
10da1ab399797ce44d37e0c464966e0a7cd5ff01Timo Sirainen *error_r = "Too much data";
6697a923d6768bf8d71f87f80b90747cf6870753Timo Sirainen return NULL;
2efe6c8cb2773ac6316638fd9a61d7e8c908153fTimo Sirainen }
6697a923d6768bf8d71f87f80b90747cf6870753Timo Sirainen
10da1ab399797ce44d37e0c464966e0a7cd5ff01Timo Sirainen return part;
80f6bd661f984145cd262445aba08a628758cde1Timo Sirainen}