changeset 437:20d5136a0c6a HEAD

Fixed several problems with FETCH BODY[..]<limits>, especially related to handling missing CRs.
author Timo Sirainen <tss@iki.fi>
date Wed, 16 Oct 2002 02:46:42 +0300
parents 8a252e6567d7
children 8fd9842b64d9
files src/lib-imap/imap-message-cache.c src/lib-imap/imap-message-cache.h src/lib-mail/message-send.c src/lib-mail/message-send.h src/lib-storage/index/index-fetch-section.c
diffstat 5 files changed, 46 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-imap/imap-message-cache.c	Wed Oct 16 00:35:27 2002 +0300
+++ b/src/lib-imap/imap-message-cache.c	Wed Oct 16 02:46:42 2002 +0300
@@ -424,12 +424,9 @@
 
 static void get_partial_size(IBuffer *inbuf,
 			     uoff_t virtual_skip, uoff_t max_virtual_size,
-			     MessageSize *partial, MessageSize *dest)
+			     MessageSize *partial, MessageSize *dest,
+			     int *cr_skipped)
 {
-	const unsigned char *msg;
-	size_t size;
-	int cr_skipped;
-
 	/* see if we can use the existing partial */
 	if (partial->virtual_size > virtual_skip)
 		memset(partial, 0, sizeof(MessageSize));
@@ -438,32 +435,30 @@
 		virtual_skip -= partial->virtual_size;
 	}
 
-	message_skip_virtual(inbuf, virtual_skip, partial, &cr_skipped);
+	message_skip_virtual(inbuf, virtual_skip, partial, cr_skipped);
+	message_get_body_size(inbuf, dest, max_virtual_size);
 
-	if (!cr_skipped) {
-		/* see if we need to add virtual CR */
-		if (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) {
-			if (msg[0] == '\n')
-				dest->virtual_size++;
-		}
+	if (*cr_skipped) {
+		dest->virtual_size--;
+		partial->virtual_size--;
 	}
-
-	message_get_body_size(inbuf, dest, max_virtual_size);
 }
 
 int imap_msgcache_get_rfc822_partial(ImapMessageCache *cache,
 				     uoff_t virtual_skip,
 				     uoff_t max_virtual_size,
 				     int get_header, MessageSize *size,
-                                     IBuffer **inbuf)
+                                     IBuffer **inbuf, int *cr_skipped)
 {
 	CachedMessage *msg;
-	uoff_t physical_skip;
+	uoff_t physical_skip, full_size;
 	int size_got;
 
 	i_assert(cache->open_msg != NULL);
 
+	memset(size, 0, sizeof(MessageSize));
 	*inbuf = NULL;
+	*cr_skipped = FALSE;
 
 	msg = cache->open_msg;
 	if (msg->hdr_size == NULL) {
@@ -472,8 +467,6 @@
 			return FALSE;
 	}
 
-	physical_skip = get_header ? 0 : msg->hdr_size->physical_size;
-
 	/* see if we can do this easily */
 	size_got = FALSE;
 	if (virtual_skip == 0) {
@@ -483,27 +476,35 @@
 				return FALSE;
 		}
 
-		if (max_virtual_size >= msg->body_size->virtual_size) {
-			*size = *msg->body_size;
+		full_size = msg->body_size->virtual_size;
+		if (get_header)
+			full_size += msg->hdr_size->virtual_size;
+
+		if (max_virtual_size >= full_size) {
+			memcpy(size, msg->body_size, sizeof(MessageSize));
+			if (get_header)
+				message_size_add(size, msg->hdr_size);
 			size_got = TRUE;
 		}
 	}
 
-	if (!size_got) {
-		if (!imap_msgcache_get_inbuf(cache,
-					     msg->hdr_size->physical_size))
+	if (size_got) {
+		physical_skip = get_header ? 0 : msg->hdr_size->physical_size;
+	} else {
+		if (!imap_msgcache_get_inbuf(cache, 0))
 			return FALSE;
 
 		if (msg->partial_size == NULL)
 			msg->partial_size = p_new(msg->pool, MessageSize, 1);
-		get_partial_size(cache->open_inbuf, virtual_skip,
-				 max_virtual_size, msg->partial_size, size);
+		if (!get_header)
+			virtual_skip += msg->hdr_size->virtual_size;
 
-		physical_skip += msg->partial_size->physical_size;
-	}
+		get_partial_size(cache->open_inbuf, virtual_skip,
+				 max_virtual_size, msg->partial_size, size,
+				 cr_skipped);
 
-	if (get_header)
-		message_size_add(size, msg->hdr_size);
+		physical_skip = msg->partial_size->physical_size;
+	}
 
 	/* seek to wanted position */
 	if (!imap_msgcache_get_inbuf(cache, physical_skip))
--- a/src/lib-imap/imap-message-cache.h	Wed Oct 16 00:35:27 2002 +0300
+++ b/src/lib-imap/imap-message-cache.h	Wed Oct 16 02:46:42 2002 +0300
@@ -63,12 +63,14 @@
 			     MessageSize *hdr_size, MessageSize *body_size);
 
 /* Returns TRUE if successful. *inbuf is set to point to the first non-skipped
-   character. size is set to specify the full size of message. */
+   character. size is set to specify the actual message size in
+   virtual_skip..max_virtual_size range. cr_skipped is set to TRUE if first
+   character in inbuf is LF, and we should NOT treat it as CR+LF. */
 int imap_msgcache_get_rfc822_partial(ImapMessageCache *cache,
 				     uoff_t virtual_skip,
 				     uoff_t max_virtual_size,
 				     int get_header, MessageSize *size,
-				     IBuffer **inbuf);
+				     IBuffer **inbuf, int *cr_skipped);
 
 /* Returns TRUE if successful. *inbuf is set to point to beginning of
    message. */
--- a/src/lib-mail/message-send.c	Wed Oct 16 00:35:27 2002 +0300
+++ b/src/lib-mail/message-send.c	Wed Oct 16 02:46:42 2002 +0300
@@ -10,7 +10,7 @@
 		 uoff_t virtual_skip, uoff_t max_virtual_size)
 {
 	const unsigned char *msg;
-	uoff_t old_limit;
+	uoff_t old_limit, limit;
 	size_t i, size;
 	int cr_skipped, add_cr, ret;
 
@@ -26,8 +26,8 @@
 		i_buffer_skip(inbuf, virtual_skip);
 
 		old_limit = inbuf->v_limit;
-		i_buffer_set_read_limit(inbuf,
-					I_MIN(max_virtual_size, old_limit));
+		limit = inbuf->v_offset + max_virtual_size;
+		i_buffer_set_read_limit(inbuf, I_MIN(limit, old_limit));
 		ret = o_buffer_send_ibuffer(outbuf, inbuf) > 0;
 		i_buffer_set_read_limit(inbuf, old_limit);
 
--- a/src/lib-mail/message-send.h	Wed Oct 16 00:35:27 2002 +0300
+++ b/src/lib-mail/message-send.h	Wed Oct 16 02:46:42 2002 +0300
@@ -5,7 +5,8 @@
 
 /* Send message to client inserting CRs if needed. Only max_virtual_size
    bytes if sent (relative to virtual_skip), if you want it unlimited,
-   use (uoff_t)-1. Returns TRUE if successful. */
+   use (uoff_t)-1. Remember that if inbuf begins with LF, CR is inserted
+   before it unless virtual_skip = 1. Returns TRUE if successful. */
 int message_send(OBuffer *outbuf, IBuffer *inbuf, MessageSize *msg_size,
 		 uoff_t virtual_skip, uoff_t max_virtual_size);
 
--- a/src/lib-storage/index/index-fetch-section.c	Wed Oct 16 00:35:27 2002 +0300
+++ b/src/lib-storage/index/index-fetch-section.c	Wed Oct 16 02:46:42 2002 +0300
@@ -45,10 +45,11 @@
 	MessageSize size;
 	IBuffer *inbuf;
 	const char *str;
+	int cr_skipped;
 
 	if (!imap_msgcache_get_rfc822_partial(ctx->cache, sect->skip,
 					      sect->max_size, fetch_header,
-					      &size, &inbuf)) {
+					      &size, &inbuf, &cr_skipped)) {
 		i_error("Couldn't get BODY[] for UID %u (index %s)",
 			rec->uid, ctx->index->filepath);
 		return FALSE;
@@ -59,7 +60,11 @@
 	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
 		return FALSE;
 
-	return message_send(ctx->outbuf, inbuf, &size, 0, sect->max_size);
+	if (cr_skipped)
+		size.virtual_size++;
+
+	return message_send(ctx->outbuf, inbuf, &size,
+			    cr_skipped ? 1 : 0, sect->max_size);
 }
 
 static char *const *get_fields_array(const char *fields)