message-parser.c revision 8a0ad174adb1eb5108511b90e97f4e5f9089b0ee
/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "istream.h"
#include "rfc822-parser.h"
#include "message-parser.h"
/* RFC-2046 requires boundaries are max. 70 chars + "--" prefix + "--" suffix.
We'll add a bit more just in case. */
struct message_boundary {
struct message_boundary *next;
struct message_part *part;
const char *boundary;
unsigned int epilogue_found:1;
};
struct message_parser_ctx {
enum message_parser_flags flags;
const char *last_boundary;
struct message_boundary *boundaries;
char last_chr;
unsigned int want_count;
struct message_header_parser_ctx *hdr_parser_ctx;
struct message_block *block_r);
unsigned int part_seen_content_type:1;
unsigned int broken:1;
};
struct message_block *block_r);
struct message_block *block_r);
struct message_block *block_r);
struct message_block *block_r);
static struct message_boundary *
{
/* As MIME spec says: search from latest one to oldest one so that we
don't break if the same boundary is used in nested parts. Also the
full message line doesn't have to match the boundary, only the
beginning. */
while (boundaries != NULL) {
return boundaries;
}
return NULL;
}
struct message_block *block)
{
unsigned int missing_cr_count = 0;
size_t i;
if (data[i] <= '\n') {
if (data[i] == '\n') {
} else if (data[i] == '\0')
}
}
}
struct message_block *block_r)
{
int ret;
}
if (ret <= 0) {
/* EOF, but we still have some data. return it. */
return 1;
}
if (ret < 0)
return ret;
return 0;
}
}
return 1;
}
static struct message_part *
{
/* set child position */
part->physical_pos =
return part;
}
{
struct message_boundary *b;
ctx->boundaries = b;
}
struct message_block *block_r)
{
}
static int
struct message_boundary **boundary_r)
{
size_t i;
*boundary_r = NULL;
if (size < 2) {
return -1;
return 0;
}
/* not a boundary, just skip this line */
return -1;
}
/* need to find the end of line */
for (i = 2; i < size; i++) {
if (data[i] == '\n')
break;
}
if (i == size && i < BOUNDARY_END_MAX_LEN &&
/* no LF found */
return 0;
}
data += 2;
size -= 2;
if (*boundary_r == NULL)
return -1;
(*boundary_r)->epilogue_found =
return 1;
}
struct message_block *block_r)
{
}
struct message_block *block_r)
{
size_t i;
int ret;
return ret;
break;
}
return 1;
}
/* found the LF */
/* a new MIME part begins */
return 1;
}
struct message_boundary *boundary,
{
struct message_part *part;
/* message ended unexpectedly */
return -1;
}
/* get back to parent MIME part, summing the child MIME part sizes
into parent's body sizes */
}
if (boundary->epilogue_found) {
/* this boundary isn't needed anymore */
else
}
/* forget about the boundaries we possibly skipped */
/* the boundary itself should already be in buffer. add that. */
(first_line ? 0 : 1));
/* [\n]--<boundary> */
return 1;
}
struct message_block *block_r)
{
const unsigned char *data;
size_t i, boundary_start;
int ret;
return ret;
/* handle boundary in first line of message. alternatively
it's an empty line. */
if (ret >= 0) {
if (ret == 0)
return 0;
}
}
/* skip to beginning of the next line. the first line was
handled already. */
if (data[i] == '\n') {
boundary_start = i;
next_line_idx = i + 1;
break;
}
}
if (boundary_start != 0) {
/* we can skip the first lines. input buffer can't be
full anymore. */
/* no linefeeds in this block. we can just skip it. */
}
&boundary);
if (ret >= 0) {
/* found / need more data */
if (ret == 0 && boundary_start == 0)
break;
}
}
/* the boundary wasn't found from this data block,
we'll need more data. */
if (eof)
ret = -1;
else {
ret = 0;
}
}
if (ret >= 0) {
/* leave CR+LF + last line to buffer */
}
return 1;
}
}
struct message_block *block_r)
{
int ret;
return ret;
return 1;
}
struct message_header_line *hdr)
{
struct rfc822_parser_context parser;
if (ctx->part_seen_content_type)
return;
(void)rfc822_skip_lwsp(&parser);
return;
}
return;
break;
}
}
}
#define MUTEX_FLAGS \
struct message_block *block_r)
{
struct message_header_line *hdr;
int ret;
}
return ret;
}
;
/* it's MIME. Content-* headers are valid */
else T_BEGIN {
} T_END;
}
return 1;
}
/* end of headers */
/* multipart type but no message boundary */
}
/* It's not MIME. Reset everything we found from
Content-Type. */
}
if (!ctx->part_seen_content_type ||
MESSAGE_PART_FLAG_MULTIPART_DIGEST) != 0) {
/* when there's no content-type specified and we're
content-type */
} else {
}
}
else
/* return empty block as end of headers */
return 1;
}
struct message_block *block_r)
{
}
{
return -1;
}
{
break;
}
}
}
struct message_block *block_r)
{
}
struct message_block *block_r)
{
int ret;
return ret;
}
return 1;
}
struct message_block *block_r)
{
}
struct message_block *block_r)
{
} else {
}
}
struct message_block *block_r)
{
struct message_header_line *hdr;
int ret;
return ret;
}
return 1;
}
/* return empty block as end of headers */
return 1;
}
struct message_block *block_r)
{
}
struct message_parser_ctx *
enum message_parser_flags flags)
{
struct message_parser_ctx *ctx;
return ctx;
}
struct message_parser_ctx *
enum message_parser_flags flags)
{
struct message_parser_ctx *ctx;
return ctx;
}
struct message_part **parts_r)
{
return ret;
}
struct message_block *block_r)
{
int ret;
if (ret == 0) {
return 0;
}
if (ret == -1) {
}
}
}
}
return ret;
}
struct message_size *hdr_size,
void *context)
{
struct message_block block;
int ret;
break;
}
if (ret < 0) {
/* well, can't return error so fake end of headers */
}
}
void *context)
{
struct message_block block;
int ret;
}
}