[dovecot-cvs] dovecot/src/lib-storage/index/mbox istream-raw-mbox.c, 1.44, 1.45 istream-raw-mbox.h, 1.11, 1.12 mbox-sync-private.h, 1.57, 1.58 mbox-sync-rewrite.c, 1.66, 1.67 mbox-sync.c, 1.186, 1.187

tss at dovecot.org tss at dovecot.org
Sun Oct 15 23:47:55 UTC 2006


Update of /var/lib/cvs/dovecot/src/lib-storage/index/mbox
In directory talvi:/tmp/cvs-serv1852

Modified Files:
	istream-raw-mbox.c istream-raw-mbox.h mbox-sync-private.h 
	mbox-sync-rewrite.c mbox-sync.c 
Log Message:
Fixes to handling CRLF linefeeds in mboxes.



Index: istream-raw-mbox.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/istream-raw-mbox.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- istream-raw-mbox.c	10 Aug 2006 19:06:29 -0000	1.44
+++ istream-raw-mbox.c	15 Oct 2006 22:47:50 -0000	1.45
@@ -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 =

Index: istream-raw-mbox.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/istream-raw-mbox.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- istream-raw-mbox.h	7 Aug 2006 12:42:38 -0000	1.11
+++ istream-raw-mbox.h	15 Oct 2006 22:47:50 -0000	1.12
@@ -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. */

Index: mbox-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-private.h,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- mbox-sync-private.h	28 Jun 2006 13:10:53 -0000	1.57
+++ mbox-sync-private.h	15 Oct 2006 22:47:50 -0000	1.58
@@ -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;

Index: mbox-sync-rewrite.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-rewrite.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -u -d -r1.66 -r1.67
--- mbox-sync-rewrite.c	13 Oct 2006 17:42:05 -0000	1.66
+++ mbox-sync-rewrite.c	15 Oct 2006 22:47:50 -0000	1.67
@@ -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);

Index: mbox-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync.c,v
retrieving revision 1.186
retrieving revision 1.187
diff -u -d -r1.186 -r1.187
--- mbox-sync.c	13 Oct 2006 19:54:05 -0000	1.186
+++ mbox-sync.c	15 Oct 2006 22:47:50 -0000	1.187
@@ -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 ||



More information about the dovecot-cvs mailing list