message-part-serialize.c revision a9c63bb1197ca14d17e081626df510b23d617899
/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
#include "message-parser.h"
#include "message-part-serialize.h"
/*
root part
root's first children
children's first children
...
root's next children
...
part
unsigned int flags
(not root part)
uoff_t physical_pos
uoff_t header_physical_size
uoff_t header_virtual_size
uoff_t body_physical_size
uoff_t body_virtual_size
(flags & (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_MESSAGE_RFC822))
unsigned int body_lines
(flags & (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_MESSAGE_RFC822))
unsigned int children_count
*/
#define MINIMUM_SERIALIZED_SIZE \
(sizeof(unsigned int) + sizeof(uoff_t) * 4)
struct deserialize_context {
const char *error;
};
static unsigned int
{
unsigned int count, children_count;
count = 0;
/* create serialized part */
if (root)
else {
sizeof(part->physical_pos));
}
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
}
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
children_count = 0;
sizeof(children_count));
dest);
sizeof(children_count));
}
} else {
}
count++;
}
return count;
}
{
}
{
return FALSE;
}
return TRUE;
}
struct message_part *parent,
unsigned int siblings,
struct message_part **part_r)
{
unsigned int children_count;
first_part = NULL;
while (siblings > 0) {
siblings--;
return FALSE;
if (root)
else {
sizeof(part->physical_pos)))
return FALSE;
}
return FALSE;
}
return FALSE;
return FALSE;
return FALSE;
}
return FALSE;
return FALSE;
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
return FALSE;
}
return FALSE;
}
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0) {
sizeof(children_count)))
return FALSE;
} else {
children_count = 0;
}
/* Only one child is possible */
if (children_count == 0) {
return FALSE;
}
if (children_count != 1) {
"has multiple children";
return FALSE;
}
}
if (children_count > 0) {
/* our children must be after our physical_pos and
the last child must be within our size. */
return FALSE;
"child part location exceeds our size";
return FALSE;
}
}
if (first_part == NULL)
first_part = part;
}
*part_r = first_part;
return TRUE;
}
{
struct deserialize_context ctx;
struct message_part *part;
return NULL;
}
*error = "Too much data";
return NULL;
}
return part;
}
{
if ((flags & (MESSAGE_PART_FLAG_TEXT |
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0)
size += sizeof(unsigned int);
if ((flags & (MESSAGE_PART_FLAG_MULTIPART |
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0)
size += sizeof(unsigned int);
return size;
}
struct message_size *hdr_size,
const char **error)
{
unsigned int flags;
if (size < MINIMUM_SERIALIZED_SIZE) {
*error = "Not enough data";
return FALSE;
}
if (uofft_size > OFF_T_MAX) {
*error = "Invalid physical_size";
return FALSE;
}
if (pos_diff != 0) {
/* have to update all positions, but skip the root */
*error = "Not enough data";
return FALSE;
}
sizeof(uoff_t));
/* invalid offset, might cause overflow */
*error = "Invalid offset";
return FALSE;
}
uofft_size += pos_diff;
sizeof(uoff_t));
}
*error = "Invalid size";
return FALSE;
}
}
return TRUE;
}
struct message_size *hdr_size,
struct message_size *body_size)
{
unsigned int flags;
/* make sure it looks valid */
if (size < MINIMUM_SERIALIZED_SIZE)
return FALSE;
if ((flags & (MESSAGE_PART_FLAG_TEXT |
MESSAGE_PART_FLAG_MESSAGE_RFC822)) == 0)
else {
if (size < MINIMUM_SERIALIZED_SIZE + sizeof(unsigned int))
return FALSE;
}
return TRUE;
}