From df1bb2870b9e9e6f800ca3a4ff21befbfa6d9ca3 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 6 Dec 2007 02:26:57 +0100
Subject: [PATCH] Implemented implicit keep to execute when not canceled or
 when the preceeding action execution fails.

---
 src/lib-sieve/ext-fileinto.c      |  2 +-
 src/lib-sieve/sieve-interpreter.c |  2 +-
 src/lib-sieve/sieve-result.c      | 51 ++++++++++++++++++++++++++++---
 src/sieve-bin/bin-common.c        |  1 +
 src/sieve-bin/sieve-exec.c        |  6 +++-
 5 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index 5fd761797..365247b3d 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -157,7 +157,7 @@ static bool ext_fileinto_opcode_execute
 		return FALSE;
 
 	t_push();
-
+	
 	if ( !sieve_opr_string_read(renv->sbin, address, &folder) ) {
 		t_pop();
 		return FALSE;
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 18cfe5ba9..7978d8e5f 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -214,7 +214,7 @@ bool sieve_interpreter_handle_optional_operands
 	(const struct sieve_runtime_env *renv, sieve_size_t *address,
 		struct sieve_side_effects_list **list)
 {
-	int opt_code;
+	int opt_code = -1;
 	
 	if ( sieve_operand_optional_present(renv->sbin, address) ) {
 		while ( opt_code != 0 ) {
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 356d97d53..2d7dad57a 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -211,6 +211,33 @@ bool sieve_result_print(struct sieve_result *result)
 	return TRUE;
 }
 
+static bool sieve_result_implicit_keep(struct sieve_result *result)
+{	
+	bool success = TRUE;
+	bool dummy = TRUE;
+	struct act_store_context ctx;
+	void *tr_context;
+	
+	ctx.folder = result->action_env.mailenv->inbox;
+	
+	/* FIXME: Handle persistent side-effects for the (implicit) keep action */
+	
+	success = act_store.start
+		(&act_store, &result->action_env, (void *) &ctx, &tr_context);
+
+	success = success && act_store.execute
+		(&act_store, &result->action_env, tr_context);
+	
+	if ( success ) {	
+		return act_store.commit
+			(&act_store, &result->action_env, tr_context, &dummy); 
+	}
+		
+	act_store.rollback(&act_store, &result->action_env, tr_context, success);
+
+	return FALSE;
+}
+
 bool sieve_result_execute
 	(struct sieve_result *result, const struct sieve_message_data *msgdata,
 		const struct sieve_mail_environment *menv)
@@ -225,7 +252,7 @@ bool sieve_result_execute
 	
 	/* Transaction start */
 	
-	printf("\nTransaction start:\n");
+	printf("\nTransaction start:\n"); /* REMOVEME */
 	
 	rac = result->first_action;
 	while ( success && rac != NULL ) {
@@ -241,7 +268,7 @@ bool sieve_result_execute
 	
 	/* Transaction execute */
 	
-	printf("\nTransaction execute:\n");
+	printf("\nTransaction execute:\n"); /* REMOVEME */
 	
 	last_attempted = rac;
 	rac = result->first_action;
@@ -282,7 +309,7 @@ bool sieve_result_execute
 	}
 	
 	/* Transaction commit/rollback */
-	if ( success )
+	if ( success ) /* REMOVEME */
 		printf("\nTransaction commit:\n");
 	else
 		printf("\nTransaction rollback:\n");
@@ -334,9 +361,25 @@ bool sieve_result_execute
 		rac = rac->next;	
 	}
 	
+	/* REMOVEME */
 	printf("\nTransaction result: %s\n", commit_ok ? "success" : "failed");
+
+	/* Return value indicates whether the caller should attempt an implicit keep 
+	 * of its own. So, if the above transaction fails, but the implicit keep below
+	 * succeeds, the return value is still true. An error is/should be logged 
+	 * though.
+	 */
 	
-	return commit_ok;
+	/* Execute implicit keep if the transaction failed or when the implicit keep
+	 * was not canceled during transaction. 
+	 */
+	if ( !commit_ok || implicit_keep ) {
+		printf("Executing implicit keep\n");
+		return sieve_result_implicit_keep(result);
+	}
+	
+	/* Unconditional success */
+	return TRUE;
 }
 
 /*
diff --git a/src/sieve-bin/bin-common.c b/src/sieve-bin/bin-common.c
index 31415cf49..dbac28110 100644
--- a/src/sieve-bin/bin-common.c
+++ b/src/sieve-bin/bin-common.c
@@ -72,6 +72,7 @@ struct sieve_binary *bin_compile_sieve_script(const char *filename)
 	struct sieve_binary *sbin;
 	
 	ehandler = sieve_stderr_ehandler_create();
+	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
 	if ( (sbin = sieve_compile(filename, ehandler)) == NULL ) {
 		sieve_error_handler_free(&ehandler);
diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-bin/sieve-exec.c
index 172d81907..82a7fcee2 100644
--- a/src/sieve-bin/sieve-exec.c
+++ b/src/sieve-bin/sieve-exec.c
@@ -186,9 +186,13 @@ int main(int argc, char **argv)
 	mailenv.duplicate_check = duplicate_check;
 	
 	ehandler = sieve_stderr_ehandler_create();
+	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
 	/* Run */
-	sieve_execute(sbin, &msgdata, &mailenv, ehandler);
+	if ( sieve_execute(sbin, &msgdata, &mailenv, ehandler) )
+		i_info("Final result: success\n");
+	else
+		i_info("Final result: failed (caller please handle implicit keep!)\n");
 
 	sieve_error_handler_free(&ehandler);
 
-- 
GitLab