[dovecot-cvs] dovecot/src/imap imap-fetch-body-section.c,1.21,1.22

cras at procontrol.fi cras at procontrol.fi
Sat Nov 8 23:12:47 EET 2003


Update of /home/cvs/dovecot/src/imap
In directory danu:/tmp/cvs-serv29087

Modified Files:
	imap-fetch-body-section.c 
Log Message:
cleanups and fix for partial header fetching



Index: imap-fetch-body-section.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch-body-section.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- imap-fetch-body-section.c	8 Nov 2003 20:47:07 -0000	1.21
+++ imap-fetch-body-section.c	8 Nov 2003 21:12:45 -0000	1.22
@@ -85,45 +85,72 @@
 	return size <= body->max_size ? size : body->max_size;
 }
 
-/* fetch BODY[] or BODY[TEXT] */
-static int fetch_body(struct imap_fetch_context *ctx,
+static int fetch_data(struct imap_fetch_context *ctx,
 		      const struct imap_fetch_body_data *body,
-		      struct mail *mail, int fetch_header)
+		      struct mail *mail, struct istream *input,
+		      uoff_t physical_start, const struct message_size *size)
 {
-	struct message_size hdr_size, body_size;
-	struct istream *stream;
 	const char *str;
-	int skip_cr, last_cr;
 	uoff_t send_size;
 	off_t ret;
+	int skip_cr, last_cr;
 
-	stream = mail->get_stream(mail, &hdr_size, &body_size);
-	if (stream == NULL)
-		return FALSE;
-
-	if (fetch_header)
-		message_size_add(&body_size, &hdr_size);
+	send_size = get_send_size(body, size->virtual_size);
 
-	send_size = get_send_size(body, body_size.virtual_size);
 	str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", ctx->prefix, send_size);
 	if (o_stream_send_str(ctx->output, str) < 0)
 		return FALSE;
 
 	skip_cr = seek_partial(ctx->select_counter, mail->uid,
-			       &partial, stream,
-			       fetch_header ? 0 : hdr_size.physical_size,
-			       body->skip);
+			       &partial, input, physical_start, body->skip);
 
-	ret = message_send(ctx->output, stream, &body_size,
-			   skip_cr, send_size, &last_cr,
-			   !mail->has_no_nuls);
+	ret = message_send(ctx->output, input, size, skip_cr, send_size,
+			   &last_cr, !mail->has_no_nuls);
 	if (ret > 0) {
 		partial.cr_skipped = last_cr != 0;
 		partial.pos.physical_size =
-			stream->v_offset - partial.physical_start;
+			input->v_offset - partial.physical_start;
 		partial.pos.virtual_size += ret;
 	}
-	return ret >= 0;
+
+	if (ret != (off_t)send_size) {
+		/* Input stream gave less data then we expected. Two choices
+		   here: either we fill the missing data with spaces or we
+		   disconnect the client.
+
+		   We shouldn't really ever get here. One reason is if mail
+		   was deleted from NFS server while we were reading it.
+		   Another is some temporary disk error.
+
+		   If we filled the missing data the client could cache it,
+		   and if it was just a temporary error the message would be
+		   permanently left corrupted in client's local cache. So, we
+		   disconnect the client and hope that next try works. */
+		o_stream_close(ctx->output);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/* fetch BODY[] or BODY[TEXT] */
+static int fetch_body(struct imap_fetch_context *ctx,
+		      const struct imap_fetch_body_data *body,
+		      struct mail *mail, int fetch_header)
+{
+	struct message_size hdr_size, body_size;
+	struct istream *stream;
+
+	stream = mail->get_stream(mail, &hdr_size, &body_size);
+	if (stream == NULL)
+		return FALSE;
+
+	if (fetch_header)
+		message_size_add(&body_size, &hdr_size);
+
+	return fetch_data(ctx, body, mail, stream,
+			  fetch_header ? 0 : hdr_size.physical_size,
+			  &body_size);
 }
 
 static int header_match(const char *const *fields,
@@ -304,25 +331,14 @@
 	const char *str;
 	const void *data;
 	size_t data_size;
-	uoff_t start_offset, send_size;
-	int failed, skip_cr;
+	uoff_t start_offset;
+	int failed;
 
 	/* HEADER, MIME, HEADER.FIELDS (list), HEADER.FIELDS.NOT (list) */
 
 	if (strcmp(header_section, "HEADER") == 0) {
 		/* all headers */
-		send_size = get_send_size(body, size->virtual_size);
-		str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n",
-				      ctx->prefix, send_size);
-		if (o_stream_send_str(ctx->output, str) < 0)
-			return FALSE;
-
-		skip_cr = seek_partial(ctx->select_counter, mail->uid,
-				       &partial, input, 0, body->skip);
-
-		return message_send(ctx->output, input, size,
-				    skip_cr, send_size, NULL,
-				    !mail->has_no_nuls) >= 0;
+		return fetch_data(ctx, body, mail, input, 0, size);
 	}
 
 	/* partial headers - copy the wanted fields into memory, inserting
@@ -457,36 +473,6 @@
 	return TRUE;
 }
 
-/* fetch BODY[1.2] or BODY[1.2.TEXT] */
-static int fetch_part_body(struct imap_fetch_context *ctx,
-			   struct istream *stream,
-			   const struct imap_fetch_body_data *body,
-			   struct mail *mail, const struct message_part *part)
-{
-	const char *str;
-	int skip_cr, last_cr;
-	uoff_t send_size;
-	off_t ret;
-
-	send_size = get_send_size(body, part->body_size.virtual_size);
-	str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", ctx->prefix, send_size);
-	if (o_stream_send_str(ctx->output, str) < 0)
-		return FALSE;
-
-	skip_cr = seek_partial(ctx->select_counter, mail->uid,
-			       &partial, stream, part->physical_pos +
-			       part->header_size.physical_size, body->skip);
-	ret = message_send(ctx->output, stream, &part->body_size,
-			   skip_cr, send_size, &last_cr, !mail->has_no_nuls);
-	if (ret > 0) {
-		partial.cr_skipped = last_cr != 0;
-		partial.pos.physical_size =
-			stream->v_offset - partial.physical_start;
-		partial.pos.virtual_size += ret;
-	}
-	return ret >= 0;
-}
-
 static int fetch_part(struct imap_fetch_context *ctx, struct mail *mail,
 		      const struct imap_fetch_body_data *body)
 {
@@ -507,8 +493,12 @@
 	if (stream == NULL)
 		return FALSE;
 
-	if (*section == '\0' || strcmp(section, "TEXT") == 0)
-		return fetch_part_body(ctx, stream, body, mail, part);
+	if (*section == '\0' || strcmp(section, "TEXT") == 0) {
+		return fetch_data(ctx, body, mail, stream,
+				  part->physical_pos +
+				  part->header_size.physical_size,
+				  &part->body_size);
+	}
 
 	if (strncmp(section, "HEADER", 6) == 0 ||
 	    strcmp(section, "MIME") == 0) {



More information about the dovecot-cvs mailing list