Mercurial > dovecot > core-2.2
changeset 4698:8ae46b72a460 HEAD
Fixes to handling CRLF linefeeds in mboxes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 16 Oct 2006 01:47:50 +0300 |
parents | ad68cb8119e1 |
children | 9e4cc68b71b2 |
files | src/lib-storage/index/mbox/istream-raw-mbox.c src/lib-storage/index/mbox/istream-raw-mbox.h src/lib-storage/index/mbox/mbox-sync-private.h src/lib-storage/index/mbox/mbox-sync-rewrite.c src/lib-storage/index/mbox/mbox-sync.c |
diffstat | 5 files changed, 45 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/mbox/istream-raw-mbox.c Mon Oct 16 01:14:12 2006 +0300 +++ b/src/lib-storage/index/mbox/istream-raw-mbox.c Mon Oct 16 01:47:50 2006 +0300 @@ -17,6 +17,7 @@ uoff_t input_peak_offset; unsigned int one_mail_only:1; + unsigned int crlf_ending:1; unsigned int corrupted:1; unsigned int eof:1; }; @@ -131,6 +132,7 @@ size_t i, pos, new_pos, from_start_pos, from_after_pos; ssize_t ret = 0; int eoh_char; + bool crlf_ending = FALSE; i_assert(stream->istream.v_offset >= rstream->from_offset); @@ -170,8 +172,10 @@ the \n trailer */ if (pos > 0 && buf[pos-1] == '\n') { pos--; - if (pos > 0 && buf[pos-1] == '\r') + if (pos > 0 && buf[pos-1] == '\r') { + crlf_ending = TRUE; pos--; + } } i_assert(pos >= stream->pos); @@ -187,6 +191,7 @@ rstream->eof = TRUE; } stream->istream.eof = TRUE; + rstream->crlf_ending = crlf_ending; handle_end_of_mail(rstream, pos); return ret < 0 ? _read(stream) : ret; } @@ -240,7 +245,10 @@ if (from_start_pos > 0 && buf[from_start_pos-1] == '\r') { /* CR also belongs to it. */ + crlf_ending = TRUE; from_start_pos--; + } else { + crlf_ending = FALSE; } } fromp = mbox_from; @@ -258,6 +266,7 @@ rstream->next_sender = sender; stream->istream.eof = TRUE; + rstream->crlf_ending = crlf_ending; handle_end_of_mail(rstream, from_start_pos); break; @@ -512,6 +521,14 @@ return rstream->sender == NULL ? "" : rstream->sender; } +bool istream_raw_mbox_has_crlf_ending(struct istream *stream) +{ + struct raw_mbox_istream *rstream = + (struct raw_mbox_istream *)stream->real_stream; + + return rstream->crlf_ending; +} + void istream_raw_mbox_next(struct istream *stream, uoff_t body_size) { struct raw_mbox_istream *rstream =
--- a/src/lib-storage/index/mbox/istream-raw-mbox.h Mon Oct 16 01:14:12 2006 +0300 +++ b/src/lib-storage/index/mbox/istream-raw-mbox.h Mon Oct 16 01:47:50 2006 +0300 @@ -24,6 +24,8 @@ /* Return sender of current message. */ const char *istream_raw_mbox_get_sender(struct istream *stream); +/* Return TRUE if the empty line between this and the next mail contains CR. */ +bool istream_raw_mbox_has_crlf_ending(struct istream *stream); /* Jump to next message. If body_size isn't (uoff_t)-1, we'll use it as potentially valid body size. */
--- a/src/lib-storage/index/mbox/mbox-sync-private.h Mon Oct 16 01:14:12 2006 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync-private.h Mon Oct 16 01:47:50 2006 +0300 @@ -124,6 +124,7 @@ off_t expunged_space, space_diff; unsigned int dest_first_mail:1; + unsigned int first_mail_crlf_expunged:1; /* global flags: */ unsigned int delay_writes:1;
--- a/src/lib-storage/index/mbox/mbox-sync-rewrite.c Mon Oct 16 01:14:12 2006 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync-rewrite.c Mon Oct 16 01:47:50 2006 +0300 @@ -320,6 +320,7 @@ uoff_t expunged_space) { uint32_t old_prev_msg_uid; + unsigned int first_mail_expunge_extra; memset(mail_ctx, 0, sizeof(*mail_ctx)); mail_ctx->sync_ctx = sync_ctx; @@ -334,13 +335,17 @@ so we have to fool it. */ old_prev_msg_uid = sync_ctx->prev_msg_uid; sync_ctx->prev_msg_uid = mails[idx].uid == 0 ? 0 : mails[idx].uid-1; - if (mails[idx].from_offset+1 - expunged_space != 0) { + + first_mail_expunge_extra = 1 + + sync_ctx->first_mail_crlf_expunged ? 1 : 0; + if (mails[idx].from_offset + + first_mail_expunge_extra - expunged_space != 0) { sync_ctx->dest_first_mail = mails[idx].from_offset == 0; } else { /* we need to skip over the initial \n (it's already counted in expunged_space) */ sync_ctx->dest_first_mail = TRUE; - mails[idx].from_offset++; + mails[idx].from_offset += first_mail_expunge_extra; } mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx);
--- a/src/lib-storage/index/mbox/mbox-sync.c Mon Oct 16 01:14:12 2006 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync.c Mon Oct 16 01:47:50 2006 +0300 @@ -664,6 +664,8 @@ static void mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx) { + struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx; + mail_ctx->mail.flags = MBOX_EXPUNGED; mail_ctx->mail.offset = mail_ctx->mail.from_offset; mail_ctx->mail.space = @@ -671,21 +673,26 @@ mail_ctx->mail.body_size; mail_ctx->mail.body_size = 0; - if (mail_ctx->sync_ctx->seq == 1) { + if (sync_ctx->seq == 1) { /* expunging first message, fix space to contain next message's \n header too since it will be removed. */ mail_ctx->mail.space++; + if (istream_raw_mbox_has_crlf_ending(sync_ctx->input)) { + mail_ctx->mail.space++; + sync_ctx->first_mail_crlf_expunged = TRUE; + } /* uid-last offset is invalid now */ - mail_ctx->sync_ctx->base_uid_last_offset = 0; + sync_ctx->base_uid_last_offset = 0; } - mail_ctx->sync_ctx->expunged_space += mail_ctx->mail.space; + sync_ctx->expunged_space += mail_ctx->mail.space; } static int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx) { struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx; + uoff_t orig_from_offset; off_t move_diff; int ret; @@ -693,11 +700,14 @@ /* move the header backwards to fill expunged space */ move_diff = -sync_ctx->expunged_space; + orig_from_offset = mail_ctx->mail.from_offset; if (sync_ctx->dest_first_mail) { /* we're moving this mail to beginning of file. skip the initial \n (it's already counted in expunged_space) */ mail_ctx->mail.from_offset++; + if (sync_ctx->first_mail_crlf_expunged) + mail_ctx->mail.from_offset++; } /* read the From-line before rewriting overwrites it */ @@ -712,6 +722,9 @@ if (ret > 0) { /* rewrite successful, write From-line to new location */ + i_assert(move_diff > 0 || + (off_t)mail_ctx->mail.from_offset >= + -move_diff); mail_ctx->mail.from_offset += move_diff; mail_ctx->mail.offset += move_diff; if (mbox_write_from_line(mail_ctx) < 0) @@ -720,7 +733,7 @@ if (sync_ctx->dest_first_mail) { /* didn't have enough space, move the offset back so seeking into it doesn't fail */ - mail_ctx->mail.from_offset--; + mail_ctx->mail.from_offset = orig_from_offset; } } } else if (mail_ctx->need_rewrite ||