[dovecot-cvs] dovecot/src/imap imap-messageset.c, NONE, 1.1 imap-messageset.h, NONE, 1.1 Makefile.am, 1.24, 1.25 client.c, 1.34, 1.35 cmd-append.c, 1.32, 1.33 cmd-close.c, 1.11, 1.12 cmd-copy.c, 1.16, 1.17 cmd-create.c, 1.7, 1.8 cmd-delete.c, 1.5, 1.6 cmd-expunge.c, 1.5, 1.6 cmd-fetch.c, 1.19, 1.20 cmd-idle.c, 1.9, 1.10 cmd-list.c, 1.34, 1.35 cmd-logout.c, 1.3, 1.4 cmd-rename.c, 1.5, 1.6 cmd-search.c, 1.18, 1.19 cmd-select.c, 1.23, 1.24 cmd-sort.c, 1.13, 1.14 cmd-status.c, 1.14, 1.15 cmd-store.c, 1.21, 1.22 cmd-subscribe.c, 1.6, 1.7 cmd-thread.c, 1.5, 1.6 cmd-unselect.c, 1.3, 1.4 commands-util.c, 1.29, 1.30 imap-expunge.c, 1.1, 1.2 imap-expunge.h, 1.1, 1.2 imap-fetch-body-section.c, 1.23, 1.24 imap-fetch.c, 1.17, 1.18 imap-fetch.h, 1.5, 1.6 imap-search.c, 1.5, 1.6 imap-search.h, 1.2, 1.3 imap-sort.c, 1.9, 1.10 imap-thread.c, 1.7, 1.8 mail-storage-callbacks.c, 1.7, 1.8 namespace.c, 1.3, 1.4

cras at procontrol.fi cras at procontrol.fi
Tue Apr 27 23:26:27 EEST 2004


Update of /home/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv29236/src/imap

Modified Files:
	Makefile.am client.c cmd-append.c cmd-close.c cmd-copy.c 
	cmd-create.c cmd-delete.c cmd-expunge.c cmd-fetch.c cmd-idle.c 
	cmd-list.c cmd-logout.c cmd-rename.c cmd-search.c cmd-select.c 
	cmd-sort.c cmd-status.c cmd-store.c cmd-subscribe.c 
	cmd-thread.c cmd-unselect.c commands-util.c imap-expunge.c 
	imap-expunge.h imap-fetch-body-section.c imap-fetch.c 
	imap-fetch.h imap-search.c imap-search.h imap-sort.c 
	imap-thread.c mail-storage-callbacks.c namespace.c 
Added Files:
	imap-messageset.c imap-messageset.h 
Log Message:
importing new index code. mbox still broken.



--- NEW FILE: imap-messageset.c ---
/* Copyright (C) 2002-2004 Timo Sirainen */

#include "lib.h"
#include "mail-search.h"
#include "imap-search.h"
#include "imap-messageset.h"

static uint32_t get_next_number(const char **str)
{
	uint32_t num;

	num = 0;
	while (**str != '\0') {
		if (**str < '0' || **str > '9')
			break;

		num = num*10 + (**str - '0');
		(*str)++;
	}

	if (num == (uint32_t)-1) {
		/* FIXME: ugly hack, we're using this number to mean the
		   last existing message. In reality UIDs should never get
		   this high, so we can quite safely just drop this one down. */
		num--;
	}

	return num;
}

struct mail_search_seqset *imap_messageset_parse(const char *messageset)
{
        struct mail_search_seqset *ret, **next;
	uint32_t seq1, seq2;

	ret = NULL;
	next = &ret;

	while (*messageset != '\0') {
		if (*messageset == '*') {
			/* last message */
			seq1 = (uint32_t)-1;
			messageset++;
		} else {
			seq1 = get_next_number(&messageset);
			if (seq1 == 0)
				return NULL;
		}

		if (*messageset != ':')
			seq2 = seq1;
		else {
			/* first:last range */
			messageset++;

			if (*messageset == '*') {
				seq2 = (uint32_t)-1;
				messageset++;
			} else {
				seq2 = get_next_number(&messageset);
				if (seq2 == 0)
					return NULL;
			}
		}

		if (*messageset == ',')
			messageset++;
		else if (*messageset != '\0')
			return NULL;

		if (seq1 > seq2) {
			/* swap, as specified by RFC-3501 */
			uint32_t temp = seq1;
			seq1 = seq2;
			seq2 = temp;
		}

		*next = t_new(struct mail_search_seqset, 1);
		(*next)->seq1 = seq1;
		(*next)->seq2 = seq2;
		next = &(*next)->next;
	}

	return ret;
}

--- NEW FILE: imap-messageset.h ---
#ifndef __IMAP_MESSAGESET_H
#define __IMAP_MESSAGESET_H

struct mail_search_seqset *imap_messageset_parse(const char *messageset);

#endif

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/imap/Makefile.am,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- Makefile.am	20 Aug 2003 23:24:29 -0000	1.24
+++ Makefile.am	27 Apr 2004 20:25:52 -0000	1.25
@@ -65,6 +65,7 @@
 	imap-expunge.c \
 	imap-fetch.c \
 	imap-fetch-body-section.c \
+	imap-messageset.c \
 	imap-search.c \
 	imap-sort.c \
 	imap-thread.c \
@@ -80,6 +81,7 @@
 	common.h \
 	imap-expunge.h \
 	imap-fetch.h \
+	imap-messageset.h \
 	imap-search.h \
 	imap-sort.h \
 	imap-thread.h \

Index: client.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/client.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- client.c	27 Jul 2003 04:48:32 -0000	1.34
+++ client.c	27 Apr 2004 20:25:52 -0000	1.35
@@ -69,9 +69,8 @@
 	client->namespaces = namespaces;
 
 	while (namespaces != NULL) {
-		namespaces->storage->set_callbacks(namespaces->storage,
-						   &mail_storage_callbacks,
-						   client);
+		mail_storage_set_callbacks(namespaces->storage,
+					   &mail_storage_callbacks, client);
 		namespaces = namespaces->next;
 	}
 
@@ -88,7 +87,7 @@
 	o_stream_flush(client->output);
 
 	if (client->mailbox != NULL)
-		client->mailbox->close(client->mailbox);
+		mailbox_close(client->mailbox);
 	namespace_deinit(client->namespaces);
 
 	imap_parser_destroy(client->parser);

Index: cmd-append.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-append.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- cmd-append.c	9 Nov 2003 18:26:25 -0000	1.32
+++ cmd-append.c	27 Apr 2004 20:25:52 -0000	1.33
@@ -48,7 +48,7 @@
 	struct mail_storage *storage;
 	struct mailbox *box;
 	struct mailbox_status status;
-	struct mail_save_context *ctx;
+        struct mailbox_transaction_context *t;
 	struct imap_parser *save_parser;
 	struct imap_arg *args;
 	struct imap_arg_list *flags_list;
@@ -72,16 +72,16 @@
 	if (storage == NULL)
 		return TRUE;
 
-	box = storage->open_mailbox(storage, mailbox,
-				    mailbox_open_flags | MAILBOX_OPEN_FAST);
+	box = mailbox_open(storage, mailbox,
+			   mailbox_open_flags | MAILBOX_OPEN_FAST);
 	if (box == NULL) {
 		client_send_storage_error(client, storage);
 		return TRUE;
 	}
 
-	if (!box->get_status(box, STATUS_CUSTOM_FLAGS, &status)) {
+	if (mailbox_get_status(box, STATUS_CUSTOM_FLAGS, &status) < 0) {
 		client_send_storage_error(client, storage);
-		box->close(box);
+		mailbox_close(box);
 		return TRUE;
 	}
 	memset(&old_flags, 0, sizeof(old_flags));
@@ -89,11 +89,7 @@
 	client_save_custom_flags(&old_flags, status.custom_flags,
 				 status.custom_flags_count);
 
-	ctx = box->save_init(box, TRUE);
-	if (ctx == NULL) {
-		client_send_storage_error(client, storage);
-		return TRUE;
-	}
+	t = mailbox_transaction_begin(box, FALSE);
 
 	/* if error occurs, the CRLF is already read. */
 	client->input_skip_line = FALSE;
@@ -159,8 +155,8 @@
 
 		if (internal_date_str == NULL) {
 			/* no time given, default to now. */
-			internal_date = ioloop_time;
-			timezone_offset = ioloop_timezone.tz_minuteswest;
+			internal_date = (time_t)-1;
+			timezone_offset = 0;
 		} else if (!imap_parse_datetime(internal_date_str,
 						&internal_date,
 						&timezone_offset)) {
@@ -184,8 +180,8 @@
 		input = i_stream_create_limit(default_pool, client->input,
 					      client->input->v_offset,
 					      msg_size);
-		if (!box->save_next(ctx, &flags, internal_date,
-				    timezone_offset, input)) {
+		if (mailbox_save(t, &flags, internal_date, timezone_offset,
+				 NULL, input) < 0) {
 			i_stream_unref(input);
 			client_send_storage_error(client, storage);
 			break;
@@ -199,15 +195,19 @@
 	}
         imap_parser_destroy(save_parser);
 
-	if (!box->save_deinit(ctx, failed)) {
-		failed = TRUE;
-		client_send_storage_error(client, storage);
+	if (failed)
+		mailbox_transaction_rollback(t);
+	else {
+		if (mailbox_transaction_commit(t) < 0) {
+			failed = TRUE;
+			client_send_storage_error(client, storage);
+		}
 	}
 
-	box->close(box);
+	mailbox_close(box);
 
 	if (!failed) {
-		client_sync_full_fast(client);
+		client_sync_full(client);
 		client_send_tagline(client, "OK Append completed.");
 	}
 	return TRUE;

Index: cmd-close.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-close.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- cmd-close.c	27 Jul 2003 04:48:32 -0000	1.11
+++ cmd-close.c	27 Apr 2004 20:25:52 -0000	1.12
@@ -7,21 +7,20 @@
 int cmd_close(struct client *client)
 {
 	struct mailbox *mailbox = client->mailbox;
+	struct mail_storage *storage = mailbox_get_storage(mailbox);
 
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
 	client->mailbox = NULL;
 
-	if (!mailbox->is_readonly(mailbox)) {
-		if (!imap_expunge(mailbox, FALSE)) {
-			client_send_untagged_storage_error(client,
-							   mailbox->storage);
-		}
+	if (!mailbox_is_readonly(mailbox)) {
+		if (!imap_expunge(mailbox))
+			client_send_untagged_storage_error(client, storage);
 	}
 
-	if (!mailbox->close(mailbox))
-                client_send_untagged_storage_error(client, mailbox->storage);
+	if (mailbox_close(mailbox) < 0)
+                client_send_untagged_storage_error(client, storage);
 
 	client_send_tagline(client, "OK Close completed.");
 	return TRUE;

Index: cmd-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-copy.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cmd-copy.c	26 Oct 2003 20:13:15 -0000	1.16
+++ cmd-copy.c	27 Apr 2004 20:25:52 -0000	1.17
@@ -4,42 +4,53 @@
 #include "commands.h"
 #include "imap-search.h"
 
-static int fetch_and_copy(struct mail_copy_context *copy_ctx,
-			  struct mailbox *srcbox, struct mailbox *destbox,
-			  const char *messageset, int uidset, int *all_found)
+static int fetch_and_copy(struct mailbox_transaction_context *t,
+			  struct mailbox *srcbox,
+			  struct mail_search_arg *search_args)
 {
-	struct mail_search_arg *search_arg;
 	struct mail_search_context *search_ctx;
+        struct mailbox_transaction_context *src_trans;
 	struct mail *mail;
-	int failed = FALSE;
+	int ret;
 
-	search_arg = imap_search_get_msgset_arg(messageset, uidset);
-	search_ctx = srcbox->search_init(srcbox, NULL, search_arg, NULL,
+	src_trans = mailbox_transaction_begin(srcbox, FALSE);
+	search_ctx = mailbox_search_init(src_trans, NULL, search_args, NULL,
 					 MAIL_FETCH_STREAM_HEADER |
 					 MAIL_FETCH_STREAM_BODY, NULL);
-	if (search_ctx == NULL)
-		return FALSE;
+	if (search_ctx == NULL) {
+		mailbox_transaction_rollback(src_trans);
+		return -1;
+	}
 
-	while ((mail = srcbox->search_next(search_ctx)) != NULL) {
-		if (!destbox->copy(mail, copy_ctx)) {
-			failed = TRUE;
+	ret = 1;
+	while ((mail = mailbox_search_next(search_ctx)) != NULL) {
+		if (mail->expunged) {
+			ret = 0;
+			break;
+		}
+		if (mailbox_copy(t, mail) < 0) {
+			ret = -1;
 			break;
 		}
 	}
 
-	if (!srcbox->search_deinit(search_ctx, all_found))
-		return FALSE;
+	if (mailbox_search_deinit(search_ctx) < 0)
+		ret = -1;
 
-	return !failed;
+	if (mailbox_transaction_commit(src_trans) < 0)
+		ret = -1;
+
+	return ret;
 }
 
 int cmd_copy(struct client *client)
 {
 	struct mail_storage *storage;
 	struct mailbox *destbox;
-        struct mail_copy_context *copy_ctx;
+	struct mailbox_transaction_context *t;
+        struct mail_search_arg *search_arg;
 	const char *messageset, *mailbox;
-	int failed = FALSE, all_found = TRUE;
+	int ret;
 
 	/* <message set> <mailbox> */
 	if (!client_read_string_args(client, 2, &messageset, &mailbox))
@@ -55,42 +66,34 @@
 	if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
 		return TRUE;
 
+	search_arg = imap_search_get_arg(client, messageset, client->cmd_uid);
+	if (search_arg == NULL)
+		return TRUE;
+
 	storage = client_find_storage(client, mailbox);
 	if (storage == NULL)
 		return TRUE;
 
-	destbox = storage->open_mailbox(storage, mailbox,
-					mailbox_open_flags | MAILBOX_OPEN_FAST);
+	destbox = mailbox_open(storage, mailbox,
+			       mailbox_open_flags | MAILBOX_OPEN_FAST);
 	if (destbox == NULL) {
 		client_send_storage_error(client, storage);
 		return TRUE;
 	}
 
-	if (destbox == client->mailbox) {
-		/* copying inside same mailbox, make sure we get the
-		   locking right */
-		if (!destbox->lock(destbox, MAILBOX_LOCK_READ |
-				   MAILBOX_LOCK_SAVE))
-			failed = TRUE;
-	}
+	t = mailbox_transaction_begin(destbox, FALSE);
+	ret = fetch_and_copy(t, client->mailbox, search_arg);
 
-	copy_ctx = failed ? NULL : destbox->copy_init(destbox);
-	if (copy_ctx == NULL)
-		failed = TRUE;
+	if (ret <= 0)
+		mailbox_transaction_rollback(t);
 	else {
-		if (!fetch_and_copy(copy_ctx, client->mailbox, destbox,
-				    messageset, client->cmd_uid, &all_found))
-			failed = TRUE;
-
-		if (!destbox->copy_deinit(copy_ctx, failed || !all_found))
-			failed = TRUE;
+		if (mailbox_transaction_commit(t) < 0)
+			ret = -1;
 	}
 
-	(void)destbox->lock(destbox, MAILBOX_LOCK_UNLOCK);
-
-	if (failed)
+	if (ret < 0)
 		client_send_storage_error(client, storage);
-	else if (!all_found) {
+	else if (ret == 0) {
 		/* some messages were expunged, sync them */
 		client_sync_full(client);
 		client_send_tagline(client,
@@ -103,6 +106,6 @@
 		client_send_tagline(client, "OK Copy completed.");
 	}
 
-	destbox->close(destbox);
+	mailbox_close(destbox);
 	return TRUE;
 }

Index: cmd-create.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-create.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cmd-create.c	15 Sep 2003 17:38:36 -0000	1.7
+++ cmd-create.c	27 Apr 2004 20:25:52 -0000	1.8
@@ -19,7 +19,7 @@
 		return TRUE;
 
 	len = strlen(mailbox);
-	if (mailbox[len-1] != storage->hierarchy_sep)
+	if (mailbox[len-1] != mail_storage_get_hierarchy_sep(storage))
 		directory = FALSE;
 	else {
 		/* name ends with hierarchy separator - client is just
@@ -32,11 +32,9 @@
 	if (!client_verify_mailbox_name(client, mailbox, FALSE, TRUE))
 		return TRUE;
 
-	if (!storage->create_mailbox(storage, mailbox, directory)) {
+	if (mail_storage_mailbox_create(storage, mailbox, directory) < 0)
 		client_send_storage_error(client, storage);
-		return TRUE;
-	}
-
-	client_send_tagline(client, "OK Create completed.");
+	else
+		client_send_tagline(client, "OK Create completed.");
 	return TRUE;
 }

Index: cmd-delete.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-delete.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmd-delete.c	27 Jul 2003 04:48:32 -0000	1.5
+++ cmd-delete.c	27 Apr 2004 20:25:52 -0000	1.6
@@ -20,12 +20,12 @@
 	}
 
 	mailbox = client->mailbox;
-	if (mailbox != NULL && strcmp(mailbox->name, name) == 0) {
+	if (mailbox != NULL && strcmp(mailbox_get_name(mailbox), name) == 0) {
 		/* deleting selected mailbox. close it first */
-		storage = mailbox->storage;
+		storage = mailbox_get_storage(mailbox);
 		client->mailbox = NULL;
 
-		if (!mailbox->close(mailbox))
+		if (mailbox_close(mailbox) < 0)
 			client_send_untagged_storage_error(client, storage);
 	} else {
 		storage = client_find_storage(client, name);
@@ -33,9 +33,9 @@
 			return TRUE;
 	}
 
-	if (storage->delete_mailbox(storage, name))
-		client_send_tagline(client, "OK Delete completed.");
-	else
+	if (mail_storage_mailbox_delete(storage, name) < 0)
 		client_send_storage_error(client, storage);
+	else
+		client_send_tagline(client, "OK Delete completed.");
 	return TRUE;
 }

Index: cmd-expunge.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-expunge.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmd-expunge.c	27 Jul 2003 04:48:32 -0000	1.5
+++ cmd-expunge.c	27 Apr 2004 20:25:52 -0000	1.6
@@ -9,10 +9,13 @@
 	if (!client_verify_open_mailbox(client))
 		return TRUE;
 
-	if (imap_expunge(client->mailbox, TRUE))
+	if (imap_expunge(client->mailbox)) {
+		client_sync_full(client);
 		client_send_tagline(client, "OK Expunge completed.");
-	else
-		client_send_storage_error(client, client->mailbox->storage);
+	} else {
+		client_send_storage_error(client,
+					  mailbox_get_storage(client->mailbox));
+	}
 
 	return TRUE;
 }

Index: cmd-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-fetch.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- cmd-fetch.c	6 Aug 2003 20:15:30 -0000	1.19
+++ cmd-fetch.c	27 Apr 2004 20:25:52 -0000	1.20
@@ -3,6 +3,8 @@
 #include "common.h"
 #include "commands.h"
 #include "imap-fetch.h"
+#include "imap-search.h"
+#include "mail-search.h"
 
 /* Parse next digits in string into integer. Returns FALSE if the integer
    becomes too big and wraps. */
@@ -315,6 +317,7 @@
 	enum mail_fetch_field fetch_data;
 	enum imap_fetch_field imap_data;
 	struct imap_fetch_body_data *bodies, **bodies_p;
+	struct mail_search_arg *search_arg;
 	const char *messageset;
 	int ret;
 
@@ -351,9 +354,12 @@
 	if (client->cmd_uid)
 		imap_data |= IMAP_FETCH_UID;
 
-	ret = imap_fetch(client, fetch_data, imap_data,
-			 bodies, messageset, client->cmd_uid);
-	if (ret >= 0) {
+	search_arg = imap_search_get_arg(client, messageset, client->cmd_uid);
+	if (search_arg == NULL)
+		return TRUE;
+
+	ret = imap_fetch(client, fetch_data, imap_data, bodies, search_arg);
+	if (ret == 0) {
 		if ((client_workarounds &
 		     WORKAROUND_OE6_FETCH_NO_NEWMAIL) == 0) {
 			if (client->cmd_uid)
@@ -362,10 +368,26 @@
 				client_sync_without_expunges(client);
 		}
 
-		client_send_tagline(client, ret > 0 ? "OK Fetch completed." :
-			"NO Some of the requested messages no longer exist.");
+		client_send_tagline(client, "OK Fetch completed.");
 	} else {
-		client_send_storage_error(client, client->mailbox->storage);
+		struct mail_storage *storage;
+		const char *error;
+		int syntax;
+
+                storage = mailbox_get_storage(client->mailbox);
+		error = mail_storage_get_last_error(storage, &syntax);
+		if (!syntax) {
+			/* We never want to reply NO to FETCH requests,
+			   BYE is preferrable (see imap-ml for reasons). */
+			if (error == NULL) {
+				error = "Out of sync: "
+					"Trying to fetch expunged message";
+			}
+			client_disconnect_with_error(client, error);
+		} else {
+			/* user error, we'll reply with BAD */
+			client_send_storage_error(client, storage);
+		}
 	}
 
 	return TRUE;

Index: cmd-idle.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-idle.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmd-idle.c	24 Aug 2003 12:58:13 -0000	1.9
+++ cmd-idle.c	27 Apr 2004 20:25:52 -0000	1.10
@@ -29,11 +29,10 @@
 			    IO_READ, _client_input, client);
 
 	if (client->mailbox != NULL) {
-		client->mailbox->auto_sync(client->mailbox,
-					   mailbox_check_interval != 0 ?
-					   MAILBOX_SYNC_FLAG_NO_EXPUNGES :
-					   MAILBOX_SYNC_NONE,
-					   mailbox_check_interval);
+		mailbox_auto_sync(client->mailbox, mailbox_check_interval != 0 ?
+				  MAILBOX_SYNC_FLAG_NO_EXPUNGES :
+				  MAILBOX_SYNC_AUTO_STOP,
+				  mailbox_check_interval);
 	}
 
 	client_sync_full(client);
@@ -84,18 +83,16 @@
 	timeout_remove(client->idle_to);
 	client->idle_to = NULL;
 
-	if (!client->mailbox->get_status(client->mailbox, STATUS_MESSAGES,
-					 &status)) {
+	if (mailbox_get_status(client->mailbox, STATUS_MESSAGES, &status) < 0) {
 		client_send_untagged_storage_error(client,
-						   client->mailbox->storage);
+			mailbox_get_storage(client->mailbox));
 		idle_finish(client, TRUE);
 	} else {
                 client->idle_expunge = status.messages+1;
 		client_send_line(client,
 			t_strdup_printf("* %u EXISTS", client->idle_expunge));
 
-		client->mailbox->auto_sync(client->mailbox,
-					   MAILBOX_SYNC_NONE, 0);
+		mailbox_auto_sync(client->mailbox, MAILBOX_SYNC_AUTO_STOP, 0);
 	}
 }
 
@@ -116,10 +113,8 @@
 	if (interval == 0)
 		interval = DEFAULT_IDLE_CHECK_INTERVAL;
 
-	if (client->mailbox != NULL) {
-		client->mailbox->auto_sync(client->mailbox,
-					   MAILBOX_SYNC_FULL, interval);
-	}
+	if (client->mailbox != NULL)
+		mailbox_auto_sync(client->mailbox, 0, interval);
 
 	client_send_line(client, "+ idling");
 

Index: cmd-list.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-list.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- cmd-list.c	6 Jan 2004 06:14:48 -0000	1.34
+++ cmd-list.c	27 Apr 2004 20:25:52 -0000	1.35
@@ -56,12 +56,12 @@
 	struct mailbox_list *list;
 	string_t *str;
 
-	ctx = storage->list_mailbox_init(storage, mask, list_flags);
+	ctx = mail_storage_mailbox_list_init(storage, mask, list_flags);
 	if (ctx == NULL)
 		return FALSE;
 
 	str = t_str_new(256);
-	while ((list = storage->list_mailbox_next(ctx)) != NULL) {
+	while ((list = mail_storage_mailbox_list_next(ctx)) != NULL) {
 		str_truncate(str, 0);
 		str_printfa(str, "* %s (%s) \"%s\" ", reply,
 			    mailbox_flags2str(list->flags, list_flags),
@@ -73,7 +73,7 @@
 		client_send_line(client, str_c(str));
 	}
 
-	return storage->list_mailbox_deinit(ctx);
+	return mail_storage_mailbox_list_deinit(ctx);
 }
 
 static int parse_list_flags(struct client *client, struct imap_arg *args,
@@ -152,7 +152,7 @@
 	else
 		storage = client->namespaces->storage;
 
-	sep_chr = storage->hierarchy_sep;
+	sep_chr = mail_storage_get_hierarchy_sep(storage);
 	if (sep_chr == '"' || sep_chr == '\\') {
 		sep[0] = '\\';
 		sep[1] = sep_chr;
@@ -184,8 +184,8 @@
 			}
 		}
 
-		failed = !mailbox_list(client, storage, mask, sep,
-				       lsub ? "LSUB" : "LIST", list_flags);
+		failed = mailbox_list(client, storage, mask, sep,
+				      lsub ? "LSUB" : "LIST", list_flags) < 0;
 	}
 
 	if (failed)

Index: cmd-logout.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-logout.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmd-logout.c	5 Jan 2003 13:09:51 -0000	1.3
+++ cmd-logout.c	27 Apr 2004 20:25:52 -0000	1.4
@@ -11,7 +11,7 @@
 		/* this could be done at client_disconnect() as well,
 		   but eg. mbox rewrite takes a while so the waiting is
 		   better to happen before "OK" message. */
-		client->mailbox->close(client->mailbox);
+		mailbox_close(client->mailbox);
 		client->mailbox = NULL;
 	}
 

Index: cmd-rename.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-rename.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmd-rename.c	27 Jul 2003 05:37:13 -0000	1.5
+++ cmd-rename.c	27 Apr 2004 20:25:52 -0000	1.6
@@ -29,10 +29,10 @@
 		return TRUE;
 	}
 
-	if (old_storage->rename_mailbox(old_storage, oldname, newname))
-		client_send_tagline(client, "OK Rename completed.");
-	else
+	if (mail_storage_mailbox_rename(old_storage, oldname, newname) < 0)
 		client_send_storage_error(client, old_storage);
+	else
+		client_send_tagline(client, "OK Rename completed.");
 
 	return TRUE;
 }

Index: cmd-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-search.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- cmd-search.c	26 Oct 2003 20:13:15 -0000	1.18
+++ cmd-search.c	27 Apr 2004 20:25:52 -0000	1.19
@@ -12,6 +12,7 @@
 		       struct mail_search_arg *sargs)
 {
         struct mail_search_context *ctx;
+        struct mailbox_transaction_context *trans;
 	const struct mail *mail;
 	string_t *str;
 	int ret, uid, first = TRUE;
@@ -19,13 +20,16 @@
 	str = t_str_new(STRBUF_SIZE);
 	uid = client->cmd_uid;
 
-	ctx = client->mailbox->search_init(client->mailbox, charset, sargs,
-					   NULL, 0, NULL);
-	if (ctx == NULL)
+	trans = mailbox_transaction_begin(client->mailbox, FALSE);
+	ctx = mailbox_search_init(trans, charset, sargs,
+				  NULL, 0, NULL);
+	if (ctx == NULL) {
+		mailbox_transaction_rollback(trans);
 		return FALSE;
+	}
 
 	str_append(str, "* SEARCH");
-	while ((mail = client->mailbox->search_next(ctx)) != NULL) {
+	while ((mail = mailbox_search_next(ctx)) != NULL) {
 		if (str_len(str) >= STRBUF_SIZE-MAX_INT_STRLEN) {
 			/* flush */
 			o_stream_send(client->output,
@@ -37,13 +41,16 @@
 		str_printfa(str, " %u", uid ? mail->uid : mail->seq);
 	}
 
-	ret = client->mailbox->search_deinit(ctx, NULL);
+	ret = mailbox_search_deinit(ctx);
 
-	if (!first || ret) {
+	if (mailbox_transaction_commit(trans) < 0)
+		ret = -1;
+
+	if (!first || ret == 0) {
 		str_append(str, "\r\n");
 		o_stream_send(client->output, str_data(str), str_len(str));
 	}
-	return ret;
+	return ret == 0;
 }
 
 int cmd_search(struct client *client)
@@ -86,7 +93,7 @@
 
 	pool = pool_alloconly_create("mail_search_args", 2048);
 
-	sargs = imap_search_args_build(pool, args, &error);
+	sargs = imap_search_args_build(pool, client->mailbox, args, &error);
 	if (sargs == NULL) {
 		/* error in search arguments */
 		client_send_tagline(client, t_strconcat("NO ", error, NULL));
@@ -97,7 +104,8 @@
 			client_sync_without_expunges(client);
 		client_send_tagline(client, "OK Search completed.");
 	} else {
-		client_send_storage_error(client, client->mailbox->storage);
+		client_send_storage_error(client,
+					  mailbox_get_storage(client->mailbox));
 	}
 
 	pool_unref(pool);

Index: cmd-select.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-select.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- cmd-select.c	24 Aug 2003 12:45:32 -0000	1.23
+++ cmd-select.c	27 Apr 2004 20:25:52 -0000	1.24
@@ -18,9 +18,9 @@
 	if (client->mailbox != NULL) {
 		box = client->mailbox;
 		client->mailbox = NULL;
-		if (!box->close(box)) {
+		if (mailbox_close(box) < 0) {
 			client_send_untagged_storage_error(client,
-							   box->storage);
+				mailbox_get_storage(box));
 		}
 	}
 
@@ -31,17 +31,18 @@
 	flags = mailbox_open_flags;
 	if (readonly)
 		flags |= MAILBOX_OPEN_READONLY;
-	box = storage->open_mailbox(storage, mailbox, flags);
+	box = mailbox_open(storage, mailbox, flags);
 	if (box == NULL) {
 		client_send_storage_error(client, storage);
 		return TRUE;
 	}
 
-	if (!box->get_status(box, STATUS_MESSAGES | STATUS_RECENT |
-			     STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
-			     STATUS_UIDNEXT | STATUS_CUSTOM_FLAGS, &status)) {
+	if (mailbox_get_status(box, STATUS_MESSAGES | STATUS_RECENT |
+			       STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
+			       STATUS_UIDNEXT | STATUS_CUSTOM_FLAGS,
+			       &status) < 0) {
 		client_send_storage_error(client, storage);
-		box->close(box);
+		mailbox_close(box);
 		return TRUE;
 	}
 
@@ -80,13 +81,13 @@
 				 "Disk space is full, delete some messages.");
 	}
 
-	client_send_tagline(client, box->is_readonly(box) ?
+	client_send_tagline(client, mailbox_is_readonly(box) ?
 			    "OK [READ-ONLY] Select completed." :
 			    "OK [READ-WRITE] Select completed.");
 
 	if (mailbox_check_interval != 0) {
-		box->auto_sync(box, MAILBOX_SYNC_FLAG_NO_EXPUNGES,
-			       mailbox_check_interval);
+		mailbox_auto_sync(box, MAILBOX_SYNC_FLAG_NO_EXPUNGES,
+				  mailbox_check_interval);
 	}
 
 	return TRUE;

Index: cmd-sort.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-sort.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- cmd-sort.c	21 Sep 2003 16:21:36 -0000	1.13
+++ cmd-sort.c	27 Apr 2004 20:25:52 -0000	1.14
@@ -116,7 +116,7 @@
 
 	pool = pool_alloconly_create("mail_search_args", 2048);
 
-	sargs = imap_search_args_build(pool, args, &error);
+	sargs = imap_search_args_build(pool, client->mailbox, args, &error);
 	if (sargs == NULL) {
 		/* error in search arguments */
 		client_send_tagline(client, t_strconcat("NO ", error, NULL));
@@ -128,7 +128,8 @@
 			client_sync_without_expunges(client);
 		client_send_tagline(client, "OK Sort completed.");
 	} else {
-		client_send_storage_error(client, client->mailbox->storage);
+		client_send_storage_error(client,
+					  mailbox_get_storage(client->mailbox));
 	}
 
 	pool_unref(pool);

Index: cmd-status.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-status.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cmd-status.c	27 Jul 2003 04:48:32 -0000	1.14
+++ cmd-status.c	27 Apr 2004 20:25:52 -0000	1.15
@@ -60,23 +60,21 @@
 	int failed;
 
 	if (client->mailbox != NULL &&
-	    mailbox_name_equals(client->mailbox->name, mailbox)) {
+	    mailbox_name_equals(mailbox_get_name(client->mailbox), mailbox)) {
 		/* this mailbox is selected */
 		box = client->mailbox;
 	} else {
 		/* open the mailbox */
-		box = storage->open_mailbox(storage, mailbox,
-					    mailbox_open_flags |
-					    MAILBOX_OPEN_FAST |
-					    MAILBOX_OPEN_READONLY);
+		box = mailbox_open(storage, mailbox, mailbox_open_flags |
+				   MAILBOX_OPEN_FAST | MAILBOX_OPEN_READONLY);
 		if (box == NULL)
 			return FALSE;
 	}
 
-	failed = !box->get_status(box, items, status);
+	failed = mailbox_get_status(box, items, status) < 0;
 
 	if (box != client->mailbox)
-		box->close(box);
+		mailbox_close(box);
 
 	return !failed;
 }

Index: cmd-store.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-store.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- cmd-store.c	4 Nov 2003 20:40:58 -0000	1.21
+++ cmd-store.c	27 Apr 2004 20:25:52 -0000	1.22
@@ -3,6 +3,7 @@
 #include "common.h"
 #include "commands.h"
 #include "imap-search.h"
+#include "imap-util.h"
 
 static int get_modify_type(struct client *client, const char *item,
 			   enum modify_type *modify_type, int *silent)
@@ -62,9 +63,10 @@
 	struct mailbox *box;
 	struct mail_search_arg *search_arg;
 	struct mail_search_context *search_ctx;
+        struct mailbox_transaction_context *t;
 	struct mail *mail;
 	const char *messageset, *item;
-	int silent, all_found, failed;
+	int silent, modify, failed = FALSE;
 
 	if (!client_read_args(client, 0, 0, &args))
 		return FALSE;
@@ -95,35 +97,35 @@
 			return TRUE;
 	}
 
-	/* and update the flags */
 	box = client->mailbox;
+	search_arg = imap_search_get_arg(client, messageset, client->cmd_uid);
+	if (search_arg == NULL)
+		return TRUE;
 
-	if (box->is_readonly(box)) {
-		/* read-only, don't every try to get write locking */
-		failed = FALSE;
+	t = mailbox_transaction_begin(box, silent);
+	if (!mailbox_is_readonly(box))
+		modify = TRUE;
+	else {
 		/* flag changes will fail, notify client about them */
-		silent = FALSE;
-	} else {
-		failed = !box->lock(box, MAILBOX_LOCK_FLAGS |
-				    MAILBOX_LOCK_READ);
+		modify = FALSE;
 	}
 
-	search_arg = imap_search_get_msgset_arg(messageset, client->cmd_uid);
 	search_ctx = failed ? NULL :
-		box->search_init(box, NULL, search_arg, NULL,
-				 MAIL_FETCH_FLAGS, NULL);
+		mailbox_search_init(t, NULL, search_arg, NULL,
+				    MAIL_FETCH_FLAGS, NULL);
 
 	if (search_ctx == NULL)
 		failed = TRUE;
 	else {
 		failed = FALSE;
-		while ((mail = box->search_next(search_ctx)) != NULL) {
-			if (!mail->update_flags(mail, &flags, modify_type)) {
-				failed = TRUE;
-				break;
-			}
-
-			if (!silent) {
+		while ((mail = mailbox_search_next(search_ctx)) != NULL) {
+			if (modify) {
+				if (mail->update_flags(mail, &flags,
+						       modify_type) < 0) {
+					failed = TRUE;
+					break;
+				}
+			} else {
 				if (!mail_send_flags(client, mail)) {
 					failed = TRUE;
 					break;
@@ -132,20 +134,24 @@
 		}
 	}
 
-	if (!box->search_deinit(search_ctx, &all_found))
+	if (mailbox_search_deinit(search_ctx) < 0)
 		failed = TRUE;
 
-	(void)box->lock(box, MAILBOX_LOCK_UNLOCK);
+	if (failed)
+		mailbox_transaction_rollback(t);
+	else {
+		if (mailbox_transaction_commit(t) < 0)
+			failed = TRUE;
+	}
 
 	if (!failed) {
 		if (client->cmd_uid)
 			client_sync_full_fast(client);
 		else
 			client_sync_without_expunges(client);
-		client_send_tagline(client, all_found ? "OK Store completed." :
-				    "NO Some of the messages no longer exist.");
+		client_send_tagline(client, "OK Store completed.");
 	} else {
-		client_send_storage_error(client, client->mailbox->storage);
+		client_send_storage_error(client, mailbox_get_storage(box));
 	}
 
 	return TRUE;

Index: cmd-subscribe.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-subscribe.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cmd-subscribe.c	27 Jul 2003 04:48:32 -0000	1.6
+++ cmd-subscribe.c	27 Apr 2004 20:25:52 -0000	1.7
@@ -19,14 +19,13 @@
 	if (storage == NULL)
 		return FALSE;
 
-	if (storage->set_subscribed(storage, mailbox, subscribe)) {
+	if (mail_storage_set_subscribed(storage, mailbox, subscribe) == 0)
+		client_send_storage_error(client, storage);
+	else {
 		client_send_tagline(client, subscribe ?
 				    "OK Subscribe completed." :
 				    "OK Unsubscribe completed.");
-	} else {
-		client_send_storage_error(client, storage);
 	}
-
 	return TRUE;
 }
 

Index: cmd-thread.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-thread.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmd-thread.c	27 Jul 2003 04:48:32 -0000	1.5
+++ cmd-thread.c	27 Apr 2004 20:25:52 -0000	1.6
@@ -58,7 +58,7 @@
 
 	pool = pool_alloconly_create("mail_search_args", 2048);
 
-	sargs = imap_search_args_build(pool, args, &error);
+	sargs = imap_search_args_build(pool, client->mailbox, args, &error);
 	if (sargs == NULL) {
 		/* error in search arguments */
 		client_send_tagline(client, t_strconcat("NO ", error, NULL));
@@ -70,7 +70,8 @@
 			client_sync_without_expunges(client);
 		client_send_tagline(client, "OK Search completed.");
 	} else {
-		client_send_storage_error(client, client->mailbox->storage);
+		client_send_storage_error(client,
+					  mailbox_get_storage(client->mailbox));
 	}
 
 	pool_unref(pool);

Index: cmd-unselect.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-unselect.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmd-unselect.c	27 Jul 2003 04:48:32 -0000	1.3
+++ cmd-unselect.c	27 Apr 2004 20:25:52 -0000	1.4
@@ -12,8 +12,10 @@
 
 	client->mailbox = NULL;
 
-	if (!mailbox->close(mailbox))
-		client_send_untagged_storage_error(client, mailbox->storage);
+	if (mailbox_close(mailbox) < 0) {
+		client_send_untagged_storage_error(client,
+						   mailbox_get_storage(mailbox));
+	}
 
 	client_send_tagline(client, "OK Unselect completed.");
 	return TRUE;

Index: commands-util.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands-util.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- commands-util.c	24 Aug 2003 12:45:32 -0000	1.29
+++ commands-util.c	27 Apr 2004 20:25:52 -0000	1.30
@@ -40,7 +40,7 @@
 		return FALSE;
 
 	/* make sure it even looks valid */
-	sep = storage->hierarchy_sep;
+	sep = mail_storage_get_hierarchy_sep(storage);
 	if (*mailbox == '\0' || strspn(mailbox, "\r\n*%?") != 0) {
 		client_send_tagline(client, "NO Invalid mailbox name.");
 		return FALSE;
@@ -60,8 +60,8 @@
 	}
 
 	/* check what our storage thinks of it */
-	if (!storage->get_mailbox_name_status(storage, mailbox,
-					      &mailbox_status)) {
+	if (mail_storage_get_mailbox_name_status(storage, mailbox,
+						 &mailbox_status) < 0) {
 		client_send_storage_error(client, storage);
 		return FALSE;
 	}
@@ -115,9 +115,9 @@
 	if (client->mailbox == NULL)
 		return;
 
-	if (!client->mailbox->sync(client->mailbox, 0)) {
+	if (mailbox_sync(client->mailbox, 0) < 0) {
 		client_send_untagged_storage_error(client,
-						   client->mailbox->storage);
+			mailbox_get_storage(client->mailbox));
 	}
 }
 
@@ -126,9 +126,9 @@
 	if (client->mailbox == NULL)
 		return;
 
-	if (!client->mailbox->sync(client->mailbox, MAILBOX_SYNC_FAST)) {
+	if (mailbox_sync(client->mailbox, MAILBOX_SYNC_FLAG_FAST) < 0) {
 		client_send_untagged_storage_error(client,
-						   client->mailbox->storage);
+			mailbox_get_storage(client->mailbox));
 	}
 }
 
@@ -137,10 +137,10 @@
 	if (client->mailbox == NULL)
 		return;
 
-	if (!client->mailbox->sync(client->mailbox, MAILBOX_SYNC_FAST |
-				   MAILBOX_SYNC_FLAG_NO_EXPUNGES)) {
+	if (mailbox_sync(client->mailbox, MAILBOX_SYNC_FLAG_FAST |
+			 MAILBOX_SYNC_FLAG_NO_EXPUNGES) < 0) {
 		client_send_untagged_storage_error(client,
-						   client->mailbox->storage);
+			mailbox_get_storage(client->mailbox));
 	}
 }
 
@@ -151,14 +151,14 @@
 	int syntax;
 
 	if (client->mailbox != NULL &&
-	    client->mailbox->is_inconsistency_error(client->mailbox)) {
+	    mailbox_is_inconsistent(client->mailbox)) {
 		/* we can't do forced CLOSE, so have to disconnect */
 		client_disconnect_with_error(client,
 			"Mailbox is in inconsistent state, please relogin.");
 		return;
 	}
 
-	error = storage->get_last_error(storage, &syntax);
+	error = mail_storage_get_last_error(storage, &syntax);
 	client_send_tagline(client, t_strconcat(syntax ? "BAD " : "NO ",
 						error, NULL));
 }
@@ -170,14 +170,14 @@
 	int syntax;
 
 	if (client->mailbox != NULL &&
-	    client->mailbox->is_inconsistency_error(client->mailbox)) {
+	    mailbox_is_inconsistent(client->mailbox)) {
 		/* we can't do forced CLOSE, so have to disconnect */
 		client_disconnect_with_error(client,
 			"Mailbox is in inconsistent state, please relogin.");
 		return;
 	}
 
-	error = storage->get_last_error(storage, &syntax);
+	error = mail_storage_get_last_error(storage, &syntax);
 	client_send_line(client,
 			 t_strconcat(syntax ? "* BAD " : "* NO ", error, NULL));
 }
@@ -262,7 +262,7 @@
 				return FALSE;
 			}
 
-			if (i == flags->custom_flags_count) {
+			if (i == flag_pos) {
 				if (!is_valid_custom_flag(client, old_flags,
 							  atom))
 					return FALSE;
@@ -316,13 +316,13 @@
 	client_send_line(client,
 		t_strconcat("* FLAGS ("SYSTEM_FLAGS, str, ")", NULL));
 
-	if (box->is_readonly(box)) {
+	if (mailbox_is_readonly(box)) {
 		client_send_line(client, "* OK [PERMANENTFLAGS ()] "
 				 "Read-only mailbox.");
 	} else {
 		client_send_line(client,
 			t_strconcat("* OK [PERMANENTFLAGS ("SYSTEM_FLAGS, str,
-				    box->allow_new_custom_flags(box) ?
+				    mailbox_allow_new_custom_flags(box) ?
 				    " \\*" : "", ")] Flags permitted.", NULL));
 	}
 }

Index: imap-expunge.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-expunge.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- imap-expunge.c	26 Jul 2003 18:24:00 -0000	1.1
+++ imap-expunge.c	27 Apr 2004 20:25:52 -0000	1.2
@@ -2,28 +2,43 @@
 
 #include "common.h"
 #include "mail-storage.h"
+#include "mail-search.h"
 #include "imap-expunge.h"
 
-int imap_expunge(struct mailbox *box, int notify)
+int imap_expunge(struct mailbox *box)
 {
-	struct mail_expunge_context *ctx;
+	struct mail_search_context *ctx;
+        struct mailbox_transaction_context *t;
 	struct mail *mail;
+        struct mail_search_arg search_arg;
 	int failed = FALSE;
 
-	ctx = box->expunge_init(box, 0, FALSE);
-	if (ctx == NULL)
-		return FALSE;
+	memset(&search_arg, 0, sizeof(search_arg));
+	search_arg.type = SEARCH_DELETED;
 
-	while ((mail = box->expunge_fetch_next(ctx)) != NULL) {
-		if (!mail->expunge(mail, ctx, NULL, notify)) {
-			failed = TRUE;
-			break;
+	t = mailbox_transaction_begin(box, FALSE);
+	ctx = mailbox_search_init(t, NULL, &search_arg, NULL, 0, NULL);
+	if (ctx == NULL)
+		failed = TRUE;
+	else {
+		while ((mail = mailbox_search_next(ctx)) != NULL) {
+			if (mail->expunge(mail) < 0) {
+				failed = TRUE;
+				break;
+			}
 		}
 	}
 
-	if (!box->expunge_deinit(ctx))
+	if (mailbox_search_deinit(ctx) < 0)
 		return FALSE;
 
+	if (failed)
+		mailbox_transaction_rollback(t);
+	else {
+		if (mailbox_transaction_commit(t) < 0)
+			failed = TRUE;
+	}
+
 	return !failed;
 }
 

Index: imap-expunge.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-expunge.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- imap-expunge.h	26 Jul 2003 18:24:00 -0000	1.1
+++ imap-expunge.h	27 Apr 2004 20:25:52 -0000	1.2
@@ -1,6 +1,6 @@
 #ifndef __IMAP_EXPUNGE_H
 #define __IMAP_EXPUNGE_H
 
-int imap_expunge(struct mailbox *box, int notify);
+int imap_expunge(struct mailbox *box);
 
 #endif

Index: imap-fetch-body-section.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch-body-section.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- imap-fetch-body-section.c	25 Apr 2004 22:30:25 -0000	1.23
+++ imap-fetch-body-section.c	27 Apr 2004 20:25:52 -0000	1.24
@@ -463,9 +463,10 @@
 
 		if (part != NULL &&
 		    (part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) &&
-		    (*path >= '0' && *path <= '9' || strncmp(path, "HEADER", 6) == 0)) {
+		    ((*path >= '0' && *path <= '9') ||
+		     strncmp(path, "HEADER", 6) == 0)) {
 			/* if remainder of path is a number or "HEADER",
-				skip the message/rfc822 part */
+			   skip the message/rfc822 part */
 			part = part->children;
 		}
 	}

Index: imap-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- imap-fetch.c	26 Oct 2003 20:13:15 -0000	1.17
+++ imap-fetch.c	27 Apr 2004 20:25:52 -0000	1.18
@@ -10,7 +10,7 @@
 #include "imap-date.h"
 #include "commands.h"
 #include "imap-fetch.h"
-#include "imap-search.h"
+#include "imap-util.h"
 
 #include <unistd.h>
 
@@ -43,12 +43,21 @@
 static int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
 		       const struct mail_full_flags *flags)
 {
+	struct mail_full_flags full_flags;
+
 	if (flags == NULL) {
 		flags = mail->get_flags(mail);
 		if (flags == NULL)
 			return FALSE;
 	}
 
+	if (ctx->update_seen) {
+		/* \Seen change isn't shown by get_flags() yet */
+		full_flags = *flags;
+		full_flags.flags |= MAIL_SEEN;
+		flags = &full_flags;
+	}
+
 	str_printfa(ctx->str, "FLAGS (%s) ", imap_write_flags(flags));
 	return TRUE;
 }
@@ -242,11 +251,9 @@
 			return FALSE;
 
 		if ((flags->flags & MAIL_SEEN) == 0) {
-			if (!mail->update_flags(mail, &ctx->seen_flag,
-						MODIFY_ADD))
+			if (mail->update_flags(mail, &ctx->seen_flag,
+					       MODIFY_ADD) < 0)
 				return FALSE;
-
-			flags = NULL; /* \Seen won't update automatically */
 			seen_updated = TRUE;
 		}
 	}
@@ -328,17 +335,16 @@
 	       enum mail_fetch_field fetch_data,
 	       enum imap_fetch_field imap_data,
 	       struct imap_fetch_body_data *bodies,
-	       const char *messageset, int uidset)
+	       struct mail_search_arg *search_args)
 {
 	struct mailbox *box = client->mailbox;
-	struct mail_search_arg *search_arg;
 	struct imap_fetch_context ctx;
+	struct mailbox_transaction_context *t;
 	struct mail *mail;
 	struct imap_fetch_body_data *body;
 	const char *null = NULL;
 	const char *const *wanted_headers, *const *arr;
 	buffer_t *buffer;
-	int all_found;
 
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.fetch_data = fetch_data;
@@ -348,7 +354,7 @@
 	ctx.select_counter = client->select_counter;
 	ctx.seen_flag.flags = MAIL_SEEN;
 
-	if (!box->is_readonly(box)) {
+	if (!mailbox_is_readonly(box)) {
 		/* If we have any BODY[..] sections, \Seen flag is added for
 		   all messages. */
 		for (body = bodies; body != NULL; body = body->next) {
@@ -383,19 +389,14 @@
 	wanted_headers = !ctx.body_fetch_from_cache ? NULL :
 		buffer_get_data(buffer, NULL);
 
-	if (ctx.update_seen) {
-		if (!box->lock(box, MAILBOX_LOCK_FLAGS | MAILBOX_LOCK_READ))
-			return -1;
-	}
-
-	search_arg = imap_search_get_msgset_arg(messageset, uidset);
-	ctx.search_ctx = box->search_init(box, NULL, search_arg, NULL,
-					  fetch_data, wanted_headers);
+	t = mailbox_transaction_begin(box, TRUE);
+	ctx.search_ctx = mailbox_search_init(t, NULL, search_args, NULL,
+					     fetch_data, wanted_headers);
 	if (ctx.search_ctx == NULL)
 		ctx.failed = TRUE;
 	else {
 		ctx.str = str_new(default_pool, 8192);
-		while ((mail = box->search_next(ctx.search_ctx)) != NULL) {
+		while ((mail = mailbox_search_next(ctx.search_ctx)) != NULL) {
 			if (!fetch_mail(&ctx, mail)) {
 				ctx.failed = TRUE;
 				break;
@@ -403,11 +404,15 @@
 		}
 		str_free(ctx.str);
 
-		if (!box->search_deinit(ctx.search_ctx, &all_found))
+		if (mailbox_search_deinit(ctx.search_ctx) < 0)
 			ctx.failed = TRUE;
 	}
 
-	(void)box->lock(box, MAILBOX_LOCK_UNLOCK);
-
-	return ctx.failed ? -1 : all_found;
+	if (ctx.failed)
+		mailbox_transaction_rollback(t);
+	else {
+		if (mailbox_transaction_commit(t) < 0)
+			ctx.failed = TRUE;
+	}
+	return ctx.failed ? -1 : 0;
 }

Index: imap-fetch.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-fetch.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- imap-fetch.h	26 Oct 2003 20:13:15 -0000	1.5
+++ imap-fetch.h	27 Apr 2004 20:25:52 -0000	1.6
@@ -40,7 +40,7 @@
 	       enum mail_fetch_field fetch_data,
 	       enum imap_fetch_field imap_data,
 	       struct imap_fetch_body_data *bodies,
-	       const char *messageset, int uidset);
+	       struct mail_search_arg *search_args);
 
 int imap_fetch_body_section(struct imap_fetch_context *ctx,
 			    const struct imap_fetch_body_data *body,

Index: imap-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-search.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- imap-search.c	26 Oct 2003 20:13:15 -0000	1.5
+++ imap-search.c	27 Apr 2004 20:25:52 -0000	1.6
@@ -1,15 +1,62 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "mail-storage.h"
 #include "mail-search.h"
 #include "imap-search.h"
 #include "imap-parser.h"
+#include "imap-messageset.h"
 
 struct search_build_data {
 	pool_t pool;
+        struct mailbox *box;
 	const char *error;
 };
 
+static int
+imap_uidset_parse(struct mailbox *box, const char *uidset,
+		  struct mail_search_seqset **seqset_r, const char **error_r)
+{
+	struct mail_search_seqset *seqset, **p;
+	int syntax, last;
+
+	*seqset_r = imap_messageset_parse(uidset);
+	if (*seqset_r == NULL) {
+		*error_r = "Invalid UID messageset";
+		return -1;
+	}
+
+	p = seqset_r;
+	for (seqset = *seqset_r; seqset != NULL; seqset = seqset->next) {
+		if (seqset->seq1 == (uint32_t)-1) {
+			/* last message, stays same */
+			continue;
+		}
+
+		last = seqset->seq2 == (uint32_t)-1;
+		if (mailbox_get_uids(box, seqset->seq1, seqset->seq2,
+				     &seqset->seq1, &seqset->seq2) < 0) {
+			struct mail_storage *storage = mailbox_get_storage(box);
+			*error_r = mail_storage_get_last_error(storage,
+							       &syntax);
+			return -1;
+		}
+
+		if (seqset->seq1 == 0 && last) {
+			/* we need special case for too_high_uid:* case */
+			seqset->seq1 = seqset->seq2 = (uint32_t)-1;
+		}
+
+		if (seqset->seq1 != 0)
+			p = &seqset->next;
+		else
+			*p = seqset->next;
+	}
+
+	*error_r = NULL;
+	return 0;
+}
+
 static struct mail_search_arg *
 search_arg_new(pool_t pool, enum mail_search_arg_type type)
 {
@@ -65,6 +112,7 @@
 			    struct imap_arg **args,
 			    struct mail_search_arg **next_sarg)
 {
+        struct mail_search_seqset *seqset;
 	struct mail_search_arg **subargs;
 	struct imap_arg *arg;
 	char *str;
@@ -277,7 +325,13 @@
 	case 'U':
 		if (strcmp(str, "UID") == 0) {
 			/* <message set> */
-			return ARG_NEW(SEARCH_UID);
+			if (!ARG_NEW(SEARCH_SEQSET))
+				return FALSE;
+
+			return imap_uidset_parse(data->box,
+						 (*next_sarg)->value.str,
+						 &(*next_sarg)->value.seqset,
+						 &data->error) == 0;
 		} else if (strcmp(str, "UNANSWERED") == 0) {
 			if (!ARG_NEW_FLAG(SEARCH_ANSWERED))
 				return FALSE;
@@ -313,10 +367,16 @@
 	default:
 		if (*str == '*' || (*str >= '0' && *str <= '9')) {
 			/* <message-set> */
-			if (!ARG_NEW_FLAG(SEARCH_SET))
+			seqset = imap_messageset_parse(str);
+			if (seqset == NULL) {
+				data->error = "Invalid messageset";
 				return FALSE;
+			}
 
-			(*next_sarg)->value.str = str;
+			if (!ARG_NEW_FLAG(SEARCH_SEQSET))
+				return FALSE;
+
+			(*next_sarg)->value.seqset = seqset;
 			return TRUE;
 		}
 		break;
@@ -327,11 +387,15 @@
 }
 
 struct mail_search_arg *
-imap_search_args_build(pool_t pool, struct imap_arg *args, const char **error)
+imap_search_args_build(pool_t pool, struct mailbox *box, struct imap_arg *args,
+		       const char **error_r)
 {
         struct search_build_data data;
 	struct mail_search_arg *first_sarg, **sargs;
 
+	*error_r = NULL;
+
+	data.box = box;
 	data.pool = pool;
 	data.error = NULL;
 
@@ -339,23 +403,62 @@
 	first_sarg = NULL; sargs = &first_sarg;
 	while (args->type != IMAP_ARG_EOL) {
 		if (!search_arg_build(&data, &args, sargs)) {
-			*error = data.error;
+			*error_r = data.error;
 			return NULL;
 		}
 		sargs = &(*sargs)->next;
 	}
 
-	*error = NULL;
 	return first_sarg;
 }
 
-struct mail_search_arg *
-imap_search_get_msgset_arg(const char *messageset, int uidset)
+int imap_search_get_msgset_arg(const char *messageset,
+			       struct mail_search_arg **arg_r,
+			       const char **error_r)
 {
 	struct mail_search_arg *arg;
 
 	arg = t_new(struct mail_search_arg, 1);
-	arg->type = uidset ? SEARCH_UID : SEARCH_SET;
-	arg->value.str = t_strdup(messageset);
-	return arg;
+	arg->type = SEARCH_SEQSET;
+	arg->value.seqset = imap_messageset_parse(messageset);
+	if (arg->value.seqset == NULL) {
+		*error_r = "Invalid messageset";
+		return -1;
+	}
+	*arg_r = arg;
+	return 0;
+}
+
+int imap_search_get_uidset_arg(struct mailbox *box, const char *uidset,
+			       struct mail_search_arg **arg_r,
+			       const char **error_r)
+{
+	struct mail_search_arg *arg;
+
+	arg = t_new(struct mail_search_arg, 1);
+	arg->type = SEARCH_SEQSET;
+	*arg_r = arg;
+	return imap_uidset_parse(box, uidset, &arg->value.seqset, error_r);
+}
+
+struct mail_search_arg *
+imap_search_get_arg(struct client *client, const char *set, int uid)
+{
+	struct mail_search_arg *search_arg;
+	const char *error;
+	int ret;
+
+	if (!uid) {
+		ret = imap_search_get_msgset_arg(set, &search_arg,
+						 &error);
+	} else {
+		ret = imap_search_get_uidset_arg(client->mailbox, set,
+						 &search_arg, &error);
+	}
+	if (ret < 0) {
+		client_send_tagline(client, t_strconcat("BAD ", error, NULL));
+		return NULL;
+	}
+
+	return search_arg;
 }

Index: imap-search.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-search.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- imap-search.h	26 Oct 2003 20:13:15 -0000	1.2
+++ imap-search.h	27 Apr 2004 20:25:52 -0000	1.3
@@ -1,11 +1,21 @@
 #ifndef __IMAP_SEARCH_H
 #define __IMAP_SEARCH_H
 
+struct imap_arg;
+struct mailbox;
+
 /* Builds search arguments based on IMAP arguments. */
 struct mail_search_arg *
-imap_search_args_build(pool_t pool, struct imap_arg *args, const char **error);
+imap_search_args_build(pool_t pool, struct mailbox *box, struct imap_arg *args,
+		       const char **error_r);
 
+int imap_search_get_msgset_arg(const char *messageset,
+			       struct mail_search_arg **arg_r,
+			       const char **error_r);
+int imap_search_get_uidset_arg(struct mailbox *box, const char *uidset,
+			       struct mail_search_arg **arg_r,
+			       const char **error_r);
 struct mail_search_arg *
-imap_search_get_msgset_arg(const char *messageset, int uidset);
+imap_search_get_arg(struct client *client, const char *set, int uid);
 
 #endif

Index: imap-sort.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-sort.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- imap-sort.c	26 Oct 2003 20:13:15 -0000	1.9
+++ imap-sort.c	27 Apr 2004 20:25:52 -0000	1.10
@@ -29,6 +29,7 @@
 
 struct sort_context {
 	struct mail_search_context *search_ctx;
+	struct mailbox_transaction_context *t;
 
 	enum mail_sort_type sort_program[MAX_SORT_PROGRAM_SIZE];
 	enum mail_sort_type common_mask, cache_mask;
@@ -209,7 +210,7 @@
 
 	/* remove the common part from sort program, we already know input is
 	   sorted that much so we don't have to worry about it. */
-	if (!client->mailbox->search_get_sorting(client->mailbox, norm_prog))
+	if (mailbox_search_get_sorting(client->mailbox, norm_prog) < 0)
 		return FALSE;
 	ctx->common_mask = mail_sort_get_common_mask(ctx->sort_program,
 						     norm_prog, &count);
@@ -223,11 +224,14 @@
 	wanted_fields = init_sort_elements(ctx, wanted_headers);
 
 	/* initialize searching */
-	ctx->search_ctx = client->mailbox->
-		search_init(client->mailbox, charset, args, norm_prog,
-			    wanted_fields, wanted_headers);
-	if (ctx->search_ctx == NULL)
+	ctx->t = mailbox_transaction_begin(client->mailbox, FALSE);
+	ctx->search_ctx =
+		mailbox_search_init(ctx->t, charset, args, norm_prog,
+				    wanted_fields, wanted_headers);
+	if (ctx->search_ctx == NULL) {
+		mailbox_transaction_rollback(ctx->t);
 		return FALSE;
+	}
 
 	ctx->box = client->mailbox;
 	ctx->output = client->output;
@@ -240,11 +244,13 @@
 
         ctx->id_is_uid = client->cmd_uid;
 
-	while ((mail = client->mailbox->search_next(ctx->search_ctx)) != NULL)
+	while ((mail = mailbox_search_next(ctx->search_ctx)) != NULL)
 		mail_sort_input(ctx, mail);
 
 	mail_sort_flush(ctx);
-	ret = client->mailbox->search_deinit(ctx->search_ctx, NULL);
+	ret = mailbox_search_deinit(ctx->search_ctx);
+
+	mailbox_transaction_rollback(ctx->t);
 
 	if (ctx->written || ret) {
 		str_append(ctx->str, "\r\n");
@@ -487,11 +493,15 @@
 static struct mail *get_mail(struct sort_context *ctx, const unsigned char *buf)
 {
 	unsigned int id = *((unsigned int *) buf);
+	uint32_t seq;
 
-	if (ctx->id_is_uid)
-		return ctx->box->fetch_uid(ctx->box, id, 0);
-	else
-		return ctx->box->fetch_seq(ctx->box, id, 0);
+	if (!ctx->id_is_uid)
+		seq = id;
+	else {
+		if (mailbox_get_uids(ctx->box, id, id, &seq, &seq) < 0)
+			return NULL;
+	}
+	return mailbox_fetch(ctx->t, seq, 0);
 
 }
 

Index: imap-thread.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/imap-thread.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- imap-thread.c	3 Dec 2003 00:40:21 -0000	1.7
+++ imap-thread.c	27 Apr 2004 20:25:52 -0000	1.8
@@ -70,6 +70,7 @@
 
 struct thread_context {
 	struct mail_search_context *search_ctx;
+	struct mailbox_transaction_context *t;
 	struct mailbox *box;
 	struct ostream *output;
 
@@ -116,11 +117,14 @@
 	ctx = t_new(struct thread_context, 1);
 
 	/* initialize searching */
-	ctx->search_ctx = client->mailbox->
-		search_init(client->mailbox, charset, args, NULL,
-			    MAIL_FETCH_DATE, wanted_headers);
-	if (ctx->search_ctx == NULL)
+	ctx->t = mailbox_transaction_begin(client->mailbox, FALSE);
+	ctx->search_ctx =
+		mailbox_search_init(ctx->t, charset, args, NULL,
+				    MAIL_FETCH_DATE, wanted_headers);
+	if (ctx->search_ctx == NULL) {
+		mailbox_transaction_rollback(ctx->t);
 		return FALSE;
+	}
 
 	ctx->box = client->mailbox;
 	ctx->output = client->output;
@@ -135,16 +139,17 @@
 				      (hash_cmp_callback_t *)strcmp);
 
 	ctx->id_is_uid = client->cmd_uid;
-	while ((mail = client->mailbox->search_next(ctx->search_ctx)) != NULL)
+	while ((mail = mailbox_search_next(ctx->search_ctx)) != NULL)
 		mail_thread_input(ctx, mail);
 
 	o_stream_send_str(client->output, "* THREAD");
 	mail_thread_finish(ctx);
 	o_stream_send_str(client->output, "\r\n");
 
-	ret = client->mailbox->search_deinit(ctx->search_ctx, NULL);
+	ret = mailbox_search_deinit(ctx->search_ctx);
+	mailbox_transaction_rollback(ctx->t);
         mail_thread_deinit(ctx);
-	return ret;
+	return ret == 0;
 }
 
 static void add_root(struct thread_context *ctx, struct node *node)
@@ -651,6 +656,7 @@
 	struct mail *mail;
 	struct node *node;
 	unsigned int id;
+	uint32_t seq;
 
 	ctx->subject_hash =
 		hash_create(default_pool, ctx->temp_pool, ctx->root_count * 2,
@@ -668,10 +674,14 @@
 			node->u.info->sorted = TRUE;
 		}
 
-		if (ctx->id_is_uid)
-			mail = ctx->box->fetch_uid(ctx->box, id, 0);
-		else
-			mail = ctx->box->fetch_seq(ctx->box, id, 0);
+		if (!ctx->id_is_uid)
+			seq = id;
+		else {
+			if (mailbox_get_uids(ctx->box, id, id, &seq, &seq) < 0)
+				seq = 0;
+		}
+
+		mail = seq == 0 ? NULL : mailbox_fetch(ctx->t, seq, 0);
 
 		if (mail != NULL) {
 			t_push();

Index: mail-storage-callbacks.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/mail-storage-callbacks.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mail-storage-callbacks.c	23 Jul 2003 01:44:16 -0000	1.7
+++ mail-storage-callbacks.c	27 Apr 2004 20:25:52 -0000	1.8
@@ -45,8 +45,7 @@
 	client_send_line(client, str);
 }
 
-static void update_flags(struct mailbox *mailbox,
-			 unsigned int seq, unsigned int uid __attr_unused__,
+static void update_flags(struct mailbox *mailbox, unsigned int seq,
 			 const struct mail_full_flags *flags, void *context)
 {
 	struct client *client = context;

Index: namespace.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/namespace.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- namespace.c	15 Sep 2003 14:02:07 -0000	1.3
+++ namespace.c	27 Apr 2004 20:25:52 -0000	1.4
@@ -47,7 +47,7 @@
 	if (hook_mail_storage_created != NULL)
 		hook_mail_storage_created(&ns->storage);
 
-	ns->hierarchy_sep = ns->storage->hierarchy_sep;
+	ns->hierarchy_sep = mail_storage_get_hierarchy_sep(ns->storage);
 	return ns;
 }
 
@@ -106,7 +106,7 @@
 	ns->type = NAMESPACE_PRIVATE;
 	ns->inbox = TRUE;
 	ns->prefix = p_strdup(pool, "");
-	ns->hierarchy_sep = ns->storage->hierarchy_sep;
+	ns->hierarchy_sep = mail_storage_get_hierarchy_sep(ns->storage);
 	if (hook_mail_storage_created != NULL)
 		hook_mail_storage_created(&ns->storage);
 



More information about the dovecot-cvs mailing list