message-parser.c revision 5f6368ee09ba3edfb9b582199c2730a7b5517a10
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "iobuffer.h"
#include "rfc822-tokenize.h"
#include "message-content-parser.h"
#include "message-parser.h"
#include "message-size.h"
typedef struct _MessageBoundary {
struct _MessageBoundary *next;
const char *boundary;
unsigned int len;
typedef struct {
char *last_boundary;
char *last_content_type;
void *context;
{
dest->physical_size +=
dest->virtual_size +=
}
{
return part;
}
void *context)
{
const char *str;
return;
return;
}
}
}
const Rfc822Token *value,
int value_count, void *context)
{
const char *str;
return;
}
}
void *context)
{
/* call the user-defined header parser */
}
/* we need to know the boundary */
}
}
{
MessageBoundary *b;
/* multipart message. add new boundary */
parse_ctx->boundaries = b;
/* reset fields */
/* skip the data before the first boundary */
&parent_part->body_size);
/* now, parse the parts */
while (next_part == parent_part) {
/* new child */
/* set child position */
part->physical_pos =
/* update our size */
if (next_part != parent_part)
break;
/* skip the boundary */
&parent_part->body_size);
}
/* remove boundary */
return next_part;
}
{
/* when there's no content-type specified and we're
content-type */
} else {
}
}
headers again, this works pretty much the same as
} else {
/* normal message, read until the next boundary */
}
return next_part;
}
{
t_push();
t_pop();
return part;
}
/* skip over to next line increasing message size */
{
unsigned char *msg;
startpos = 0;
if (msg[i] == '\n') {
msg_size->virtual_size++;
}
break;
}
}
if (i < size) {
startpos = i+1;
break;
}
if (i > 0) {
/* leave the last character, it may be \r */
startpos = 1;
}
}
}
}
}
{
unsigned char *msg;
int ret;
if (ret == -2) {
/* overflow, line is too long. just skip it. */
startpos = line_start = 0;
continue;
}
if (size == 0) {
/* no, we never want empty buffer */
continue;
}
/* don't parse the last character, so we can always have
one character read-ahead. we never care about the last
character anyway, it's either the first character in
message body, or if there's no body for any reason, it's
the \n ending the header. */
size--;
colon_pos = i;
continue;
}
if (msg[i] != '\n')
continue;
/* missing CR */
}
/* no headers at all */
break;
}
/* \n\n or \n\r\n - end of headers */
break;
}
/* make sure the header doesn't continue to next line */
/* we have a valid header line */
/* get length of name-field */
while (end_pos > line_start &&
end_pos--;
/* get length of value field */
colon_pos++;
while (colon_pos < i &&
colon_pos++;
/* and finally call the function */
context);
}
line_start = i+1;
}
}
if (i < size) {
/* end of header */
startpos = i+1;
break;
}
if (i > 0) {
/* leave the last line to buffer */
colon_pos -= line_start;
startpos = i-line_start;
line_start = 0;
}
}
hdr_size->virtual_size +=
}
}
{
while (boundaries != NULL) {
return boundaries;
}
return NULL;
}
/* read until next boundary is found. if skip_over = FALSE, stop at the
[\r]\n before the boundary, otherwise leave it right after the known
boundary so the ending "--" can be checked. */
static MessageBoundary *
{
unsigned char *msg;
if (msg[i] != '\n')
continue;
/* possible boundary */
i - line_start - 2);
break;
}
/* missing CR */
}
line_start = i+1;
}
/* boundary found */
break;
}
if (i > 0) {
if (i - line_start > 128 &&
/* long partial line, see if it's a boundary.
RFC-2046 says that the boundaries must be
70 chars without "--" or less. We allow
a bit larger.. */
i - line_start - 2);
break;
/* nope, we can skip over the line, just
leave the last char since it may be \r */
i--;
} else {
/* leave the last line to buffer, it may be
boundary */
i = line_start;
if (i > 2) i -= 2; /* leave the \r\n too */
line_start -= i;
}
io_buffer_skip(inbuf, i);
msg_size->physical_size += i;
msg_size->virtual_size += i;
}
}
if (skip_over) {
/* leave the pointer right after the boundary */
/* leave the \r\n before the boundary */
line_start--;
line_start--;
else
}
}
return boundary;
}
{
if (boundaries == NULL) {
return NULL;
} else {
}
}
/* skip data until next boundary is found. if it's end boundary,
skip the footer as well. */
{
unsigned char *msg;
unsigned int size;
int end_boundary;
return NULL;
/* now, see if it's end boundary */
if (size >= 2) {
break;
}
}
/* skip the rest of the line */
if (end_boundary) {
/* skip the footer */
}
}