From 14e91a15ae136681f48284b70e0f16d47711bcff Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sat, 19 Jun 2010 13:07:10 +0200
Subject: [PATCH] Cleaned up mail storage-related code (modified patch by Timo
 Sirainen).

---
 .../plugins/mailbox/tag-mailbox-create.c      |  60 ++++-----
 .../plugins/mailbox/tst-mailboxexists.c       |   4 +-
 src/lib-sieve/sieve-actions.c                 | 115 ++++++++----------
 src/lib-sieve/sieve-actions.h                 |   8 +-
 src/lib-sieve/sieve-types.h                   |   2 +-
 src/plugins/lda-sieve/lda-sieve-plugin.c      |   2 +-
 src/sieve-tools/sieve-filter.c                |   2 +-
 src/sieve-tools/sieve-test.c                  |   2 +-
 src/testsuite/testsuite-mailstore.c           |   6 +-
 src/testsuite/testsuite-mailstore.h           |   4 +-
 src/testsuite/testsuite-script.c              |   5 +-
 src/testsuite/testsuite.c                     |   2 +-
 12 files changed, 89 insertions(+), 123 deletions(-)

diff --git a/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c b/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c
index f78142f4f..a1e91d180 100644
--- a/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c
+++ b/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c
@@ -122,54 +122,42 @@ static bool seff_mailbox_create_pre_execute
 	struct act_store_transaction *trans = 
 		(struct act_store_transaction *) tr_context;
 	struct mail_storage **storage = &(aenv->exec_status->last_storage);
-	enum mailbox_flags flags =
-		MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_SAVEONLY |
-		MAILBOX_FLAG_POST_SESSION;
-	struct mailbox *box = NULL;
+	enum mail_error error;
 	
 	/* Check whether creation is necessary */
-	if ( trans->box != NULL || trans->redundant || trans->disabled ) 
+	if ( trans->box == NULL || trans->redundant || trans->disabled )
 		return TRUE;
 
-	/* Check availability of namespace and folder name */
-	if ( trans->namespace == NULL || trans->folder == NULL )
-		return FALSE;
-
 	/* Check whether creation has a chance of working */
-	if ( trans->error_code != MAIL_ERROR_NONE 
-		&& trans->error_code != MAIL_ERROR_NOTFOUND )
+	if ( trans->error_code != MAIL_ERROR_NONE && 
+		trans->error_code != MAIL_ERROR_NOTFOUND )
 		return FALSE;
 
-	*storage = trans->namespace->storage; 
+	*storage = mailbox_get_storage(trans->box);
 
-    box = mailbox_alloc(trans->namespace->list, trans->folder, flags);
 	/* Create mailbox */
-	if ( mailbox_create(box, NULL, FALSE) < 0 ) {
-		mailbox_free(&box);
-		box = NULL;
-
-	} else {
-		/* Subscribe to it if necessary */
-		if ( aenv->scriptenv->mailbox_autosubscribe ) {
-			(void)mailbox_list_set_subscribed
-				(trans->namespace->list, trans->folder, TRUE);
+	if ( mailbox_create(trans->box, NULL, FALSE) < 0 ) {
+		(void)mail_storage_get_last_error(*storage, &error);
+		if ( error != MAIL_ERROR_EXISTS ) {
+			sieve_act_store_get_storage_error(aenv, trans);
+			return FALSE;
 		}
+	}
+	/* Subscribe to it if necessary */
+	if ( aenv->scriptenv->mailbox_autosubscribe ) {
+		(void)mailbox_list_set_subscribed
+			(mailbox_get_namespace(trans->box)->list,
+			 mailbox_get_name(trans->box), TRUE);
+	}
 
-		/* Try opening again */
-		if ( mailbox_sync(box, 0) < 0 ) {
-			/* Failed definitively */
-			mailbox_free(&box);
-			box = NULL;
-		}
-	} 
-
-	/* Fetch error */
-	if ( box == NULL )
-		sieve_act_store_get_storage_error(aenv, trans);	
+	/* Try opening again */
+	if ( mailbox_sync(trans->box, 0) < 0 ) {
+		/* Failed definitively */
+		sieve_act_store_get_storage_error(aenv, trans);
+		return FALSE;
+	}
 
-	trans->box = box;
-	
-	return ( box != NULL );
+	return TRUE;
 }
 
 
diff --git a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
index 208f806ee..9c57204c1 100644
--- a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
+++ b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c
@@ -124,7 +124,7 @@ static int tst_mailboxexists_operation_execute
 
 	sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "mailboxexists test");
 
-	if ( renv->scriptenv->namespaces != NULL ) {
+	if ( renv->scriptenv->user != NULL ) {
 		mailbox_item = NULL;
 		while ( (result=sieve_coded_stringlist_next_item
 			(mailbox_names, &mailbox_item)) 
@@ -134,7 +134,7 @@ static int tst_mailboxexists_operation_execute
 			struct mailbox *box;
 
 			/* Find the namespace */	
-			ns = mail_namespace_find(renv->scriptenv->namespaces, &mailbox);
+			ns = mail_namespace_find(renv->scriptenv->user->namespaces, &mailbox);
 			if ( ns == NULL) {
 				all_exist = FALSE;
 				break;
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index dee8cbfe6..ffadf2752 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -265,11 +265,11 @@ void sieve_act_store_get_storage_error
 {
 	pool_t pool = sieve_result_pool(aenv->result);
 	
-	trans->error = p_strdup(pool, 
-		mail_storage_get_last_error(trans->namespace->storage, &trans->error_code));
+	trans->error = p_strdup(pool,
+		mail_storage_get_last_error(mailbox_get_storage(trans->box), 
+		&trans->error_code));
 }
 
-
 /* Equality */
 
 static bool act_store_equals
@@ -330,18 +330,22 @@ static void act_store_print
 
 /* Action implementation */
 
-static struct mailbox *act_store_mailbox_open
+static bool act_store_mailbox_open
 (const struct sieve_action_exec_env *aenv, const char **mailbox,
-	struct mail_namespace **ns_r, const char **folder_r)
+ struct mailbox **box_r)
 {
 	struct mail_storage **storage = &(aenv->exec_status->last_storage);
 	enum mailbox_flags flags =
 		MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_SAVEONLY |
 		MAILBOX_FLAG_POST_SESSION;
 	string_t *mailbox_mutf7;
+	struct mail_namespace *ns;
 	struct mailbox *box;
+	const char *folder;
 	enum mail_error error;
 
+	*box_r = NULL;
+
 	/* Deliveries to INBOX must always succeed, regardless of ACLs */
 	if (strcasecmp(*mailbox, "INBOX") == 0) {
 		flags |= MAILBOX_FLAG_IGNORE_ACLS;
@@ -353,37 +357,32 @@ static struct mailbox *act_store_mailbox_open
 	if ( imap_utf8_to_utf7(*mailbox, mailbox_mutf7) < 0 ) {
 		/* FIXME: check utf-8 validity at compiletime/runtime */
 		sieve_result_error(aenv, "mailbox name not utf-8: %s", *mailbox);
-		return NULL;
+		return FALSE;
 	}
 
-	*folder_r = str_c(mailbox_mutf7);
-	*ns_r = mail_namespace_find(aenv->scriptenv->namespaces, folder_r);
-	if ( *ns_r == NULL) {
-		*storage = NULL;
-		return NULL;
+	folder = str_c(mailbox_mutf7);
+	ns = mail_namespace_find(aenv->scriptenv->user->namespaces, &folder);
+	if ( ns == NULL) {
+		sieve_result_error
+			(aenv, "failed to find namespace for mailbox '%s'", *mailbox);
+		return FALSE;
 	}
 	
-	if ( **folder_r == '\0' ) {
+	if ( *folder == '\0' ) {
 		/* delivering to a namespace prefix means we actually want to
 		 * deliver to the INBOX instead
 		 */
-		*folder_r = *mailbox = "INBOX";
+		folder = *mailbox = "INBOX";
 		flags |= MAILBOX_FLAG_IGNORE_ACLS;
 
-		*ns_r = mail_namespace_find(aenv->scriptenv->namespaces, folder_r);
-		if ( *ns_r == NULL) {
-			*storage = NULL;
-			return NULL;
-		}
-
-		*storage = (*ns_r)->storage;
+		ns = mail_namespace_find_inbox(aenv->scriptenv->user->namespaces);
 	}
 
 	/* First attempt at opening the box */
-	box = mailbox_alloc((*ns_r)->list, *folder_r, flags);
+	*box_r = box = mailbox_alloc(ns->list, folder, flags);
 	if ( mailbox_open(box) == 0 ) {
 		/* Success */
-		return box;
+		return TRUE;
 	}
 
 	/* Failed */
@@ -394,33 +393,28 @@ static struct mailbox *act_store_mailbox_open
 	/* Only continue when the mailbox is missing and when we are allowed to
 	 * create it.
 	 */
-	if ( !aenv->scriptenv->mailbox_autocreate || error != MAIL_ERROR_NOTFOUND ) {
-		mailbox_free(&box);
-		return NULL;
-	}
+	if ( error != MAIL_ERROR_NOTFOUND || !aenv->scriptenv->mailbox_autocreate )
+		return FALSE;
 
 	/* Try creating it. */
 	if ( mailbox_create(box, NULL, FALSE) < 0 ) {
 		(void)mail_storage_get_last_error(*storage, &error);
-		if (error != MAIL_ERROR_EXISTS) {
-			mailbox_free(&box);
-			return NULL;
-		}
+		if (error != MAIL_ERROR_EXISTS)
+			return FALSE;
 	}
 
 	/* Subscribe to it if required */
 	if ( aenv->scriptenv->mailbox_autosubscribe ) {
-		(void)mailbox_list_set_subscribed((*ns_r)->list, *folder_r, TRUE);
+		(void)mailbox_list_set_subscribed(ns->list, folder, TRUE);
 	}
 
 	/* Try opening again */
 	if ( mailbox_sync(box, 0) < 0 ) {
 		/* Failed definitively */
-		mailbox_free(&box);
-		return NULL;
+		return FALSE;
 	}
 
-	return box;
+	return TRUE;
 }
 
 static bool act_store_start
@@ -431,11 +425,9 @@ static bool act_store_start
 	const struct sieve_script_env *senv = aenv->scriptenv;
 	const struct sieve_message_data *msgdata = aenv->msgdata;
 	struct act_store_transaction *trans;
-	struct mail_namespace *ns = NULL;
 	struct mailbox *box = NULL;
-	const char *folder;
 	pool_t pool = sieve_result_pool(aenv->result);
-	bool disabled = FALSE, redundant = FALSE;
+	bool disabled = FALSE, redundant = FALSE, open_failed = FALSE;
 
 	/* If context is NULL, the store action is the result of (implicit) keep */	
 	if ( ctx == NULL ) {
@@ -445,19 +437,19 @@ static bool act_store_start
 
 	/* Open the requested mailbox */
 
-	/* NOTE: The caller of the sieve library is allowed to leave namespaces set 
+	/* NOTE: The caller of the sieve library is allowed to leave user set 
 	 * to NULL. This implementation will then skip actually storing the message.
 	 */
-	if ( senv->namespaces != NULL ) {
-		box = act_store_mailbox_open(aenv, &ctx->mailbox, &ns, &folder);
+	if ( senv->user != NULL ) {
+		if ( !act_store_mailbox_open(aenv, &ctx->mailbox, &box) ) {
+			open_failed = TRUE;
 
 		/* Check whether we are trying to store the message in the folder it
 		 * originates from. In that case we skip actually storing it.
 		 */
-		if ( box != NULL && mailbox_backends_equal(box, msgdata->mail->box) ) {
+		} else if ( mailbox_backends_equal(box, msgdata->mail->box) ) {
 			mailbox_free(&box);
 			box = NULL;
-			ns = NULL;
 			redundant = TRUE;
 		}
 	} else {
@@ -468,22 +460,19 @@ static bool act_store_start
 	trans = p_new(pool, struct act_store_transaction, 1);
 
 	trans->context = ctx;
-	trans->namespace = ns;
-	trans->folder = folder;
 	trans->box = box;
 	trans->flags = 0;
 
 	trans->disabled = disabled;
 	trans->redundant = redundant;
+	trans->error_code = MAIL_ERROR_NONE;
 
-	if ( ns != NULL && box == NULL )
+	if ( open_failed )
 		sieve_act_store_get_storage_error(aenv, trans);
-	
+
 	*tr_context = (void *)trans;
 
-	return ( (box != NULL)
-		|| (trans->error_code == MAIL_ERROR_NOTFOUND)
-		|| disabled || redundant );
+	return TRUE;
 }
 
 static struct mail_keywords *act_store_keywords_create
@@ -545,10 +534,8 @@ static bool act_store_execute
 		return TRUE;
 	}
 
-	/* Exit early if namespace or mailbox are not available */
-	if ( trans->namespace == NULL )
-		return FALSE;
-	else if ( trans->box == NULL ) 
+	/* Exit early if mailbox is not available */
+	if ( trans->box == NULL ) 
 		return FALSE;
 
 	/* Mark attempt to store in default mailbox */
@@ -582,7 +569,7 @@ static bool act_store_execute
 	if ( mailbox_copy(&save_ctx, aenv->msgdata->mail) < 0 ) {
 		sieve_act_store_get_storage_error(aenv, trans);
  		result = FALSE;
- 	}
+	}
  	
 	/* Deallocate keywords */
  	if ( keywords != NULL ) {
@@ -608,11 +595,6 @@ static void act_store_log_status
 	} else if ( trans->redundant ) {
 		sieve_result_log(aenv, "left message in mailbox '%s'", mailbox_name);
 
-	/* Namespace not set? */
-	} else if ( trans->namespace == NULL ) {
-		sieve_result_error
-			(aenv, "failed to find namespace for mailbox '%s'", mailbox_name);
-
 	/* Store failed? */
 	} else if ( !status ) {
 		const char *errstr;
@@ -621,7 +603,8 @@ static void act_store_log_status
 		if ( trans->error != NULL )
 			errstr = trans->error;
 		else
-			errstr = mail_storage_get_last_error(trans->namespace->storage, &error);
+			errstr = mail_storage_get_last_error
+				(mailbox_get_storage(trans->box), &error);
 	
 		sieve_result_error(aenv, "failed to store into mailbox '%s': %s", 
 			mailbox_name, errstr);
@@ -652,24 +635,22 @@ static bool act_store_commit
 	if ( trans->disabled ) {
 		act_store_log_status(trans, aenv, FALSE, status);
 		*keep = FALSE;
+		if ( trans->box != NULL )
+			mailbox_free(&trans->box);
 		return TRUE;
 	} else if ( trans->redundant ) {
 		act_store_log_status(trans, aenv, FALSE, status);
 		aenv->exec_status->keep_original = TRUE;
 		aenv->exec_status->message_saved = TRUE;
+		if ( trans->box != NULL )
+			mailbox_free(&trans->box);
 		return TRUE;	
 	}
 
-	/* Exit early if namespace is not available */
-	if ( trans->namespace == NULL )
-		return FALSE;
-	else if ( trans->box == NULL ) 
-		return FALSE;
-
 	/* Mark attempt to use storage. Can only get here when all previous actions
 	 * succeeded. 
 	 */
-	aenv->exec_status->last_storage = trans->namespace->storage;
+	aenv->exec_status->last_storage = mailbox_get_storage(trans->box);
 
 	/* Free mail object for stored message */
 	if ( trans->dest_mail != NULL ) 
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index f84a7aaae..c858580e6 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -214,17 +214,13 @@ struct act_store_context {
 
 struct act_store_transaction {
 	struct act_store_context *context;
-	struct mail_namespace *namespace;
 	struct mailbox *box;
 	struct mailbox_transaction_context *mail_trans;
 	struct mail *dest_mail;
-
-	const char *folder;
-	const char *folder_mutf7;
-
+	
 	const char *error;
 	enum mail_error error_code;
-	
+
 	enum mail_flags flags;
 	ARRAY_TYPE(const_string) keywords;
 
diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h
index 5dc3de9c5..1d026c879 100644
--- a/src/lib-sieve/sieve-types.h
+++ b/src/lib-sieve/sieve-types.h
@@ -72,7 +72,7 @@ struct sieve_script_env {
 	const char *action_log_format;
 
 	/* Mail-related */
-	struct mail_namespace *namespaces;
+	struct mail_user *user;
 	const char *default_mailbox;
 	bool mailbox_autocreate;
 	bool mailbox_autosubscribe;
diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c
index 35b3497fb..35774e77f 100644
--- a/src/plugins/lda-sieve/lda-sieve-plugin.c
+++ b/src/plugins/lda-sieve/lda-sieve-plugin.c
@@ -596,7 +596,7 @@ static int lda_sieve_run
 	scriptenv.default_mailbox = mdctx->dest_mailbox_name;
 	scriptenv.mailbox_autocreate = mdctx->set->lda_mailbox_autocreate;
 	scriptenv.mailbox_autosubscribe = mdctx->set->lda_mailbox_autosubscribe;
-	scriptenv.namespaces = mdctx->dest_user->namespaces;
+	scriptenv.user = mdctx->dest_user;
 	scriptenv.username = mdctx->dest_user->username;
 	scriptenv.hostname = mdctx->set->hostname;
 	scriptenv.postmaster_address = mdctx->set->postmaster_address;
diff --git a/src/sieve-tools/sieve-filter.c b/src/sieve-tools/sieve-filter.c
index e0e79e900..868f2adc6 100644
--- a/src/sieve-tools/sieve-filter.c
+++ b/src/sieve-tools/sieve-filter.c
@@ -413,7 +413,7 @@ int main(int argc, char **argv)
 	memset(&scriptenv, 0, sizeof(scriptenv));
 	scriptenv.mailbox_autocreate = TRUE;
 	scriptenv.default_mailbox = dst_mailbox;
-	scriptenv.namespaces = dst_ns;
+	scriptenv.user = mail_user;
 	scriptenv.username = user;
 	scriptenv.hostname = "host.example.com";
 	scriptenv.postmaster_address = "postmaster@example.com";
diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index c459b69ac..149b5848e 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -328,7 +328,7 @@ int main(int argc, char **argv)
 		/* Compose script environment */
 		memset(&scriptenv, 0, sizeof(scriptenv));
 		scriptenv.default_mailbox = "INBOX";
-		scriptenv.namespaces = ns;
+		scriptenv.user = mail_user;
 		scriptenv.username = user;
 		scriptenv.hostname = "host.example.com";
 		scriptenv.postmaster_address = "postmaster@example.com";
diff --git a/src/testsuite/testsuite-mailstore.c b/src/testsuite/testsuite-mailstore.c
index 1b6f9b6e6..ca5b95512 100644
--- a/src/testsuite/testsuite-mailstore.c
+++ b/src/testsuite/testsuite-mailstore.c
@@ -109,9 +109,9 @@ void testsuite_mailstore_reset(void)
  * Mailbox Access
  */
 
-struct mail_namespace *testsuite_mailstore_get_namespace(void)
+struct mail_user *testsuite_mailstore_get_user(void)
 {
-	return testsuite_mailstore_user->namespaces;
+	return testsuite_mailstore_user;
 }
 
 bool testsuite_mailstore_mailbox_create
@@ -168,6 +168,7 @@ static struct mail *testsuite_mailstore_open(const char *folder)
 	box = mailbox_alloc(ns->list, folder, flags);
 	if ( mailbox_open(box) < 0 ) {
 		sieve_sys_error("testsuite: failed to open mailbox '%s'", folder);
+		mailbox_free(&box);
 		return NULL;	
 	}
 	
@@ -175,6 +176,7 @@ static struct mail *testsuite_mailstore_open(const char *folder)
 
 	if ( mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0 ) {
 		sieve_sys_error("testsuite: failed to sync mailbox '%s'", folder);
+		mailbox_free(&box);
 		return NULL;
 	}
 
diff --git a/src/testsuite/testsuite-mailstore.h b/src/testsuite/testsuite-mailstore.h
index c45a27500..132cdd387 100644
--- a/src/testsuite/testsuite-mailstore.h
+++ b/src/testsuite/testsuite-mailstore.h
@@ -19,10 +19,10 @@ void testsuite_mailstore_deinit(void);
 void testsuite_mailstore_reset(void);
 
 /* 
- * Namespace
+ * User
  */
 
-struct mail_namespace *testsuite_mailstore_get_namespace(void);
+struct mail_user *testsuite_mailstore_get_user(void);
 
 /*
  * Mailbox Access
diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c
index f939ce4be..ddd1f7168 100644
--- a/src/testsuite/testsuite-script.c
+++ b/src/testsuite/testsuite-script.c
@@ -103,7 +103,7 @@ bool testsuite_script_run(const struct sieve_runtime_env *renv)
 	scriptenv.smtp_close = NULL;
 	scriptenv.duplicate_mark = NULL;
 	scriptenv.duplicate_check = NULL;
-	scriptenv.namespaces = renv->scriptenv->namespaces;
+	scriptenv.user = renv->scriptenv->user;
 	scriptenv.trace_stream = renv->scriptenv->trace_stream;
 	scriptenv.trace_level = renv->scriptenv->trace_level;
 	
@@ -157,7 +157,6 @@ bool testsuite_script_multiscript
 	/* Compose script execution environment */
 	memset(&scriptenv, 0, sizeof(scriptenv));
 	scriptenv.default_mailbox = "INBOX";
-	scriptenv.namespaces = NULL;
 	scriptenv.username = "user";
 	scriptenv.hostname = "host.example.com";
 	scriptenv.postmaster_address = "postmaster@example.com";
@@ -165,7 +164,7 @@ bool testsuite_script_multiscript
 	scriptenv.smtp_close = NULL;
 	scriptenv.duplicate_mark = NULL;
 	scriptenv.duplicate_check = NULL;
-	scriptenv.namespaces = renv->scriptenv->namespaces;
+	scriptenv.user = renv->scriptenv->user;
 	scriptenv.trace_stream = renv->scriptenv->trace_stream;	
 
 	/* Start execution */
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index 4964965a9..fd01722de 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -241,7 +241,7 @@ int main(int argc, char **argv)
 		testsuite_message_init(master_service, user, mail_user_dovecot);
 
 		memset(&scriptenv, 0, sizeof(scriptenv));
-		scriptenv.namespaces = testsuite_mailstore_get_namespace();
+		scriptenv.user = testsuite_mailstore_get_user();
 		scriptenv.default_mailbox = "INBOX";
 		scriptenv.hostname = "testsuite.example.com";
 		scriptenv.postmaster_address = "postmaster@example.com";
-- 
GitLab