Skip to content

Commit

Permalink
lib-mail: Added message_parser_deinit_from_parts()
Browse files Browse the repository at this point in the history
The returned error strings could still be improved to give more details,
especially give an approximate offset of where the problem is.
  • Loading branch information
sirainen committed Feb 28, 2016
1 parent 6de6ec2 commit 3ef9cfc
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
33 changes: 22 additions & 11 deletions src/lib-mail/message-parser.c
Expand Up @@ -26,6 +26,7 @@ struct message_parser_ctx {
pool_t parser_pool, part_pool;
struct istream *input;
struct message_part *parts, *part;
const char *broken_reason;

enum message_header_parser_flags hdr_flags;
enum message_parser_flags flags;
Expand All @@ -44,7 +45,6 @@ struct message_parser_ctx {
struct message_block *block_r);

unsigned int part_seen_content_type:1;
unsigned int broken:1;
unsigned int eof:1;
};

Expand Down Expand Up @@ -748,7 +748,7 @@ static int preparsed_parse_prologue_more(struct message_parser_ctx *ctx,

/* [\r]\n--boundary[\r]\n */
if (block_r->size < 5 || *cur != '\n') {
ctx->broken = TRUE;
ctx->broken_reason = "Prologue boundary end not at expected position";
return -1;
}

Expand All @@ -761,7 +761,7 @@ static int preparsed_parse_prologue_more(struct message_parser_ctx *ctx,
}

if (cur[0] != '\n' || cur[1] != '-' || cur[2] != '-') {
ctx->broken = TRUE;
ctx->broken_reason = "Prologue boundary beginning not at expected position";
return -1;
}

Expand Down Expand Up @@ -822,7 +822,7 @@ static int preparsed_parse_epilogue_boundary(struct message_parser_ctx *ctx,
int ret;

if (end_offset - ctx->input->v_offset < 7) {
ctx->broken = TRUE;
ctx->broken_reason = "Epilogue position is wrong";
return -1;
}

Expand All @@ -842,15 +842,15 @@ static int preparsed_parse_epilogue_boundary(struct message_parser_ctx *ctx,
if (*cur == '\r') cur++;

if (cur[0] != '\n' || cur[1] != '-' || data[2] != '-') {
ctx->broken = TRUE;
ctx->broken_reason = "Epilogue boundary start not at expected position";
return -1;
}

/* find the end of the line */
cur += 3;
if ((cur = memchr(cur, '\n', size - (cur-data))) == NULL) {
if (end_offset < ctx->input->v_offset + size) {
ctx->broken = TRUE;
ctx->broken_reason = "Epilogue boundary end not at expected position";
return -1;
} else if (ctx->input->v_offset + size < end_offset &&
size < BOUNDARY_END_MAX_LEN &&
Expand All @@ -874,7 +874,7 @@ static int preparsed_parse_body_init(struct message_parser_ctx *ctx,

if (offset < ctx->input->v_offset) {
/* header was actually larger than the cached size suggested */
ctx->broken = TRUE;
ctx->broken_reason = "Header larger than its cached size";
return -1;
}
i_stream_skip(ctx->input, offset - ctx->input->v_offset);
Expand All @@ -901,7 +901,7 @@ static int preparsed_parse_epilogue_init(struct message_parser_ctx *ctx,
if (offset < ctx->input->v_offset) {
/* last child was actually larger than the cached size
suggested */
ctx->broken = TRUE;
ctx->broken_reason = "Part larger than its cached size";
return -1;
}
i_stream_skip(ctx->input, offset - ctx->input->v_offset);
Expand Down Expand Up @@ -957,7 +957,7 @@ static int preparsed_parse_next_header(struct message_parser_ctx *ctx,
i_assert(ctx->skip == 0);
if (ctx->input->v_offset != ctx->part->physical_pos +
ctx->part->header_size.physical_size) {
ctx->broken = TRUE;
ctx->broken_reason = "Cached header size mismatch";
return -1;
}
return 1;
Expand Down Expand Up @@ -1029,12 +1029,22 @@ message_parser_init_from_parts(struct message_part *parts,

int message_parser_deinit(struct message_parser_ctx **_ctx,
struct message_part **parts_r)
{
const char *error;

return message_parser_deinit_from_parts(_ctx, parts_r, &error);
}

int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx,
struct message_part **parts_r,
const char **error_r)
{
struct message_parser_ctx *ctx = *_ctx;
int ret = ctx->broken ? -1 : 0;
int ret = ctx->broken_reason != NULL ? -1 : 0;

*_ctx = NULL;
*parts_r = ctx->parts;
*error_r = ctx->broken_reason;

if (ctx->hdr_parser_ctx != NULL)
message_parse_header_deinit(&ctx->hdr_parser_ctx);
Expand Down Expand Up @@ -1069,7 +1079,8 @@ int message_parser_parse_next_block(struct message_parser_ctx *ctx,
if (ret < 0 && ctx->part != NULL) {
/* Successful EOF or unexpected failure */
i_assert(ctx->input->eof || ctx->input->closed ||
ctx->input->stream_errno != 0 || ctx->broken);
ctx->input->stream_errno != 0 ||
ctx->broken_reason != NULL);
while (ctx->part->parent != NULL) {
message_size_add(&ctx->part->parent->body_size,
&ctx->part->body_size);
Expand Down
7 changes: 7 additions & 0 deletions src/lib-mail/message-parser.h
Expand Up @@ -57,6 +57,13 @@ message_parser_init_from_parts(struct message_part *parts,
didn't match the current message */
int message_parser_deinit(struct message_parser_ctx **ctx,
struct message_part **parts_r);
/* Same as message_parser_deinit(), but return an error message describing
why the preparsed parts didn't match the message. This can also safely be
called even when preparsed parts weren't used - it'll always just return
success in that case. */
int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx,
struct message_part **parts_r,
const char **error_r);

/* Read the next block of a message. Returns 1 if block is returned, 0 if
input stream is non-blocking and more data needs to be read, -1 when all is
Expand Down

0 comments on commit 3ef9cfc

Please sign in to comment.