[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-save.c,1.34,1.35

cras at procontrol.fi cras at procontrol.fi
Thu Feb 20 01:37:25 EET 2003


Update of /home/cvs/dovecot/src/lib-storage/index/mbox
In directory danu:/tmp/cvs-serv2044/lib-storage/index/mbox

Modified Files:
	mbox-save.c 
Log Message:
mbox: strip some headers when saving message. also always set Content-Length
header so message may safely contain lines beginning with "From ".



Index: mbox-save.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-save.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- mbox-save.c	27 Jan 2003 02:05:32 -0000	1.34
+++ mbox-save.c	19 Feb 2003 23:37:23 -0000	1.35
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "hostpid.h"
 #include "ostream.h"
+#include "str.h"
 #include "write-full.h"
 #include "mbox-index.h"
 #include "mbox-lock.h"
@@ -14,25 +15,35 @@
 #include <sys/stat.h>
 #include <netdb.h>
 
+#define HEADER_EXTRA_SPACE 100
+
 struct mail_save_context {
 	struct index_mailbox *ibox;
 	int transaction;
 
 	struct ostream *output;
-	uoff_t sync_offset;
+	uoff_t sync_offset, content_length_offset, eoh_offset;
+
+	const struct mail_full_flags *flags;
 };
 
 static char my_hostdomain[256] = "";
 
+static int syscall_error(struct mail_save_context *ctx, const char *function)
+{
+	mail_storage_set_critical(ctx->ibox->box.storage,
+				  "%s failed for mbox file %s: %m",
+				  function, ctx->ibox->index->mailbox_path);
+	return FALSE;
+}
+
 static int write_error(struct mail_save_context *ctx)
 {
 	if (errno == ENOSPC) {
 		mail_storage_set_error(ctx->ibox->box.storage,
 				       "Not enough disk space");
 	} else {
-		mail_storage_set_critical(ctx->ibox->box.storage,
-			"Error writing to mbox file %s: %m",
-			ctx->ibox->index->mailbox_path);
+                syscall_error(ctx, "write()");
 	}
 
 	return FALSE;
@@ -45,30 +56,18 @@
 	int fd;
 
 	fd = ctx->ibox->index->mbox_fd;
-	if (fstat(fd, &st) < 0) {
-		mail_storage_set_critical(ctx->ibox->box.storage,
-					  "fstat() failed for mbox file %s: %m",
-					  ctx->ibox->index->mailbox_path);
-		return FALSE;
-	}
+	if (fstat(fd, &st) < 0)
+                return syscall_error(ctx, "fstat()");
 
 	*offset = (uoff_t)st.st_size;
 	if (st.st_size == 0)
 		return TRUE;
 
-	if (lseek(fd, st.st_size-1, SEEK_SET) < 0) {
-		mail_storage_set_critical(ctx->ibox->box.storage,
-					  "lseek() failed for mbox file %s: %m",
-					 ctx->ibox->index->mailbox_path);
-		return FALSE;
-	}
+	if (lseek(fd, st.st_size-1, SEEK_SET) < 0)
+                return syscall_error(ctx, "lseek()");
 
-	if (read(fd, &ch, 1) != 1) {
-		mail_storage_set_critical(ctx->ibox->box.storage,
-					  "read() failed for mbox file %s: %m",
-					  ctx->ibox->index->mailbox_path);
-		return FALSE;
-	}
+	if (read(fd, &ch, 1) != 1)
+		return syscall_error(ctx, "read()");
 
 	if (ch != '\n') {
 		if (write_full(fd, "\n", 1) < 0)
@@ -118,58 +117,154 @@
 	return TRUE;
 }
 
-static int write_flags(struct mail_save_context *ctx,
-		       const struct mail_full_flags *full_flags)
+static const char *get_system_flags(enum mail_flags flags)
 {
-	enum mail_flags flags = full_flags->flags;
-	const char *str;
-	unsigned int field;
-	unsigned int i;
+	string_t *str;
 
 	if (flags == 0)
-		return TRUE;
+		return "";
 
-	if (flags & MAIL_SEEN) {
-		if (o_stream_send_str(ctx->output, "Status: R\n") < 0)
-			return write_error(ctx);
-	}
+	str = t_str_new(32);
+	if (flags & MAIL_SEEN)
+		str_append(str, "Status: R\n");
 
 	if (flags & (MAIL_ANSWERED|MAIL_DRAFT|MAIL_FLAGGED|MAIL_DELETED)) {
-		str = t_strconcat("X-Status: ",
-				  (flags & MAIL_ANSWERED) ? "A" : "",
-				  (flags & MAIL_DRAFT) ? "D" : "",
-				  (flags & MAIL_FLAGGED) ? "F" : "",
-				  (flags & MAIL_DELETED) ? "T" : "",
-				  "\n", NULL);
+		str_append(str, "X-Status: ");
 
-		if (o_stream_send_str(ctx->output, str) < 0)
-			return write_error(ctx);
+		if ((flags & MAIL_ANSWERED) != 0)
+			str_append_c(str, 'A');
+		if ((flags & MAIL_DRAFT) != 0)
+			str_append_c(str, 'D');
+		if ((flags & MAIL_FLAGGED) != 0)
+			str_append_c(str, 'F');
+		if ((flags & MAIL_DELETED) != 0)
+			str_append_c(str, 'T');
+		str_append_c(str, '\n');
 	}
 
-	if (flags & MAIL_CUSTOM_FLAGS_MASK) {
-		if (o_stream_send_str(ctx->output, "X-Keywords:") < 0)
-			return write_error(ctx);
+	return str_c(str);
+}
 
-		field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
-		for (i = 0; i < full_flags->custom_flags_count; i++) {
-			const char *custom_flag = full_flags->custom_flags[i];
+static const char *get_custom_flags(const struct mail_full_flags *flags)
+{
+	string_t *str;
+	unsigned int field;
+	unsigned int i;
 
-			if ((flags & field) && custom_flag != NULL) {
-				if (o_stream_send(ctx->output, " ", 1) < 0)
-					return write_error(ctx);
+	if ((flags->flags & MAIL_CUSTOM_FLAGS_MASK) == 0)
+		return "";
 
-				if (o_stream_send_str(ctx->output,
-						      custom_flag) < 0)
-					return write_error(ctx);
-			}
+	str = t_str_new(256);
+	field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
+	for (i = 0; i < flags->custom_flags_count; i++) {
+		const char *custom_flag = flags->custom_flags[i];
 
-                        field <<= 1;
+		if ((flags->flags & field) && custom_flag != NULL) {
+			str_append_c(str, ' ');
+			str_append(str, custom_flag);
 		}
 
-		if (o_stream_send(ctx->output, "\n", 1) < 0)
-			return write_error(ctx);
+		field <<= 1;
 	}
 
+	return str_c(str);
+}
+
+static int save_header_callback(const unsigned char *name, size_t len,
+				write_func_t *write_func, void *context)
+{
+	static const char *content_length = "Content-Length: ";
+	struct mail_save_context *ctx = context;
+	const char *str;
+	char *buf;
+	size_t space;
+
+	switch (len) {
+	case 0:
+		/* write system flags */
+		str = get_system_flags(ctx->flags->flags);
+		if (write_func(ctx->output, str, strlen(str)) < 0)
+			return -1;
+
+		/* write beginning of content-length header */
+		if (write_func(ctx->output, content_length,
+			       strlen(content_length)) < 0) {
+			write_error(ctx);
+			return -1;
+		}
+		ctx->content_length_offset = ctx->output->offset;
+
+		/* calculate how much space custom flags and content-length
+		   value needs, then write that amount of spaces. */
+		space = strlen(get_custom_flags(ctx->flags));
+		space += sizeof("X-Keywords: ");
+		space += HEADER_EXTRA_SPACE + MAX_INT_STRLEN + 1;
+
+		/* @UNSAFE */
+		buf = t_malloc(space);
+		memset(buf, ' ', space-1);
+		buf[space-1] = '\n';
+
+		if (write_func(ctx->output, buf, space) < 0) {
+			write_error(ctx);
+			return -1;
+		}
+		ctx->eoh_offset = ctx->output->offset;
+		break;
+	case 5:
+		if (memcasecmp(name, "X-UID", 5) == 0)
+			return 0;
+		break;
+	case 6:
+		if (memcasecmp(name, "Status", 6) == 0)
+			return 0;
+		break;
+	case 8:
+		if (memcasecmp(name, "X-Status", 8) == 0)
+			return 0;
+		break;
+	case 10:
+		if (memcasecmp(name, "X-Keywords", 10) == 0)
+			return 0;
+		if (memcasecmp(name, "X-IMAPbase", 10) == 0)
+			return 0;
+		break;
+	case 14:
+		if (memcasecmp(name, "Content-Length", 14) == 0)
+			return 0;
+		break;
+	}
+
+	return 1;
+}
+
+static int mbox_fix_header(struct mail_save_context *ctx)
+{
+	uoff_t old_offset;
+	const char *str;
+	int crlf = getenv("MAIL_SAVE_CRLF") != NULL;
+
+	old_offset = ctx->output->offset;
+	if (o_stream_seek(ctx->output, ctx->content_length_offset) < 0)
+                return syscall_error(ctx, "o_stream_seek()");
+
+	/* write value for Content-Length */
+	str = dec2str(old_offset - (ctx->eoh_offset + 1 + crlf));
+	if (o_stream_send_str(ctx->output, str) < 0)
+		return write_error(ctx);
+
+	/* [CR]LF X-Keywords: */
+	str = crlf ? "\r\nX-Keywords:" : "\nX-Keywords:";
+	if (o_stream_send_str(ctx->output, str) < 0)
+		return write_error(ctx);
+
+	/* write custom flags into X-Keywords */
+	str = get_custom_flags(ctx->flags);
+	if (o_stream_send_str(ctx->output, str) < 0)
+		return write_error(ctx);
+
+	if (o_stream_seek(ctx->output, old_offset) < 0)
+		return syscall_error(ctx, "o_stream_seek()");
 	return TRUE;
 }
 
@@ -184,6 +279,7 @@
 
 	/* we don't need the real flag positions, easier to keep using our own.
 	   they need to be checked/added though. */
+	ctx->flags = flags;
 	real_flags = flags->flags;
 	if (!index_mailbox_fix_custom_flags(ctx->ibox, &real_flags,
 					    flags->custom_flags,
@@ -192,10 +288,10 @@
 
 	t_push();
 	if (!write_from_line(ctx, received_date) ||
-	    !write_flags(ctx, flags) ||
 	    !index_storage_save(ctx->ibox->box.storage,
 				ctx->ibox->index->mailbox_path,
-				data, ctx->output) ||
+				data, ctx->output, save_header_callback, ctx) ||
+	    !mbox_fix_header(ctx) ||
 	    !mbox_append_lf(ctx)) {
 		/* failed, truncate file back to original size.
 		   output stream needs to be flushed before truncating
@@ -260,9 +356,7 @@
 	if (rollback && ctx->sync_offset != (uoff_t)-1) {
 		if (ftruncate(ctx->ibox->index->mbox_fd,
 			      ctx->sync_offset) < 0) {
-			mail_storage_set_critical(ctx->ibox->box.storage,
-				"ftruncate(%s) failed: %m",
-				ctx->ibox->index->mailbox_path);
+			syscall_error(ctx, "ftruncate()");
 			failed = TRUE;
 		}
 	}




More information about the dovecot-cvs mailing list