From 6172bd9ce6b576ba5f37d0b29f99b1e806951469 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Sun, 29 Sep 2024 02:42:33 +0200
Subject: [PATCH] plugins: imapsieve: imap-sieve - Use array for composing list
 of scripts to execute

---
 src/plugins/imapsieve/imap-sieve.c | 104 ++++++++++++++---------------
 1 file changed, 50 insertions(+), 54 deletions(-)

diff --git a/src/plugins/imapsieve/imap-sieve.c b/src/plugins/imapsieve/imap-sieve.c
index da669675c..1d5386d2f 100644
--- a/src/plugins/imapsieve/imap-sieve.c
+++ b/src/plugins/imapsieve/imap-sieve.c
@@ -332,6 +332,8 @@ struct imap_sieve_run {
 	bool trace_log_initialized:1;
 };
 
+ARRAY_DEFINE_TYPE(imap_sieve_run_script, struct imap_sieve_run_script);
+
 static void
 imap_sieve_run_init_user_log(struct imap_sieve_run *isrun)
 {
@@ -400,66 +402,75 @@ imap_sieve_run_init_trace_log(struct imap_sieve_run *isrun,
 
 static int
 imap_sieve_run_init_scripts(struct imap_sieve *isieve,
-			    struct imap_sieve_run_script *scripts,
-			    unsigned int max_len,
+			    ARRAY_TYPE(imap_sieve_run_script) *scripts,
 			    struct sieve_storage *storage,
 			    const char *script_name,
 			    const char *const *scripts_before,
 			    const char *const *scripts_after,
-			    struct sieve_script **user_script_r,
-			    unsigned int *count_r)
+			    struct sieve_script **user_script_r)
 {
 	struct sieve_instance *svinst = isieve->svinst;
 	struct sieve_script *user_script;
 	enum sieve_error error_code;
-	unsigned int count = 0;
 	const char *const *sp;
-	int ret;
 
 	/* Admin scripts before user script */
 	if (scripts_before != NULL) {
 		for (sp = scripts_before; *sp != NULL; sp++) {
-			i_assert(count < max_len);
-			ret = sieve_script_create_open(svinst, *sp, NULL,
-						       &scripts[count].script,
-						       &error_code);
-			if (ret == 0)
-				count++;
-			else if (error_code == SIEVE_ERROR_TEMP_FAILURE)
-				return -1;
+			struct sieve_script *script;
+
+			if (sieve_script_create_open(svinst, *sp, NULL, &script,
+						     &error_code) < 0) {
+				if (error_code == SIEVE_ERROR_TEMP_FAILURE)
+					return -1;
+				continue;
+			}
+
+			struct imap_sieve_run_script *rscript;
+
+			rscript = array_append_space(scripts);
+			rscript->script = script;
 		}
 	}
 
 	/* The user script */
 	user_script = NULL;
 	if (storage != NULL) {
-		i_assert(count < max_len);
+		struct sieve_script *script;
+
 		if (sieve_storage_open_script(storage, script_name,
-					      &scripts[count].script,
-					      &error_code) == 0) {
-			user_script = scripts[count].script;
-			count++;
-		} else if (error_code == SIEVE_ERROR_TEMP_FAILURE) {
-			return -1;
+					      &script, &error_code) < 0) {
+			if (error_code == SIEVE_ERROR_TEMP_FAILURE)
+				return -1;
+		} else {
+			struct imap_sieve_run_script *rscript;
+
+			rscript = array_append_space(scripts);
+			rscript->script = script;
+			user_script = script;
 		}
 	}
 
 	/* Admin scripts after user script */
 	if (scripts_after != NULL) {
 		for (sp = scripts_after; *sp != NULL; sp++) {
-			i_assert(count < max_len);
-			ret = sieve_script_create_open(svinst, *sp, NULL,
-						       &scripts[count].script,
-						       &error_code);
-			if (ret == 0)
-				count++;
-			else if (error_code == SIEVE_ERROR_TEMP_FAILURE)
-				return -1;
+			struct sieve_script *script;
+
+			if (sieve_script_create_open(svinst, *sp, NULL, &script,
+						     &error_code) < 0) {
+				if (error_code == SIEVE_ERROR_TEMP_FAILURE)
+					return -1;
+				continue;
+			}
+
+			struct imap_sieve_run_script *rscript;
+
+			rscript = array_append_space(scripts);
+			rscript->script = script;
 		}
 	}
 
 	*user_script_r = user_script;
-	*count_r = count;
 	return 0;
 }
 
@@ -473,27 +484,15 @@ int imap_sieve_run_init(struct imap_sieve *isieve,
 {
 	struct imap_sieve_run *isrun;
 	struct sieve_storage *storage;
-	struct imap_sieve_run_script *scripts;
+	ARRAY_TYPE(imap_sieve_run_script) scripts;
 	struct sieve_script *user_script;
 	pool_t pool;
-	unsigned int max_len, count;
 	int ret;
 
 	*isrun_r = NULL;
 	if (isieve->svinst == NULL)
 		return -1;
 
-	/* Determine how many scripts we may run for this event */
-	max_len = 0;
-	if (scripts_before != NULL)
-		max_len += str_array_length(scripts_before);
-	if (script_name != NULL)
-		max_len++;
-	if (scripts_after != NULL)
-		max_len += str_array_length(scripts_after);
-	if (max_len == 0)
-		return 0;
-
 	/* Get storage for user script */
 	storage = NULL;
 	if (script_name != NULL && *script_name != '\0' &&
@@ -502,23 +501,21 @@ int imap_sieve_run_init(struct imap_sieve *isieve,
 
 	/* Open all scripts */
 	pool = pool_alloconly_create("imap_sieve_run", 256);
-	scripts = p_new(pool, struct imap_sieve_run_script, max_len);
+	p_array_init(&scripts, pool, 16);
 
-	ret = imap_sieve_run_init_scripts(isieve, scripts, max_len,
+	ret = imap_sieve_run_init_scripts(isieve, &scripts,
 					  storage, script_name,
 					  scripts_before, scripts_after,
-					  &user_script, &count);
+					  &user_script);
 	if (ret < 0) {
-		unsigned int i;
+		struct imap_sieve_run_script *rscript;
 
-		for (i = 0; i < max_len; i++) {
-			if (scripts[i].script != NULL)
-				sieve_script_unref(&scripts[i].script);
-		}
+		array_foreach_modifiable(&scripts, rscript)
+			sieve_script_unref(&rscript->script);
 		pool_unref(&pool);
 		return -1;
 	}
-	if (count == 0) {
+	if (array_is_empty(&scripts)) {
 		/* None of the scripts could be opened */
 		pool_unref(&pool);
 		return 0;
@@ -532,8 +529,7 @@ int imap_sieve_run_init(struct imap_sieve *isieve,
 	isrun->src_mailbox = src_mailbox;
 	isrun->cause = p_strdup(pool, cause);
 	isrun->user_script = user_script;
-	isrun->scripts = scripts;
-	isrun->scripts_count = count;
+	isrun->scripts = array_get_modifiable(&scripts, &isrun->scripts_count);
 
 	imap_sieve_run_init_user_log(isrun);
 
-- 
GitLab