From 9d5a7514ef99e93c0330a46b266fdcfa0d412c43 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Mon, 19 Aug 2024 23:50:40 +0200
Subject: [PATCH] lib-sieve: sieve-plugins - Migrate Sieve plugin settings to
 new config structure

---
 src/lib-sieve/sieve-plugins.c  | 49 +++++++++++++++++++++-------------
 src/lib-sieve/sieve-settings.c | 24 ++++++++++++++---
 src/lib-sieve/sieve-settings.h |  4 +++
 3 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/src/lib-sieve/sieve-plugins.c b/src/lib-sieve/sieve-plugins.c
index 178a178e6..ec3e6107d 100644
--- a/src/lib-sieve/sieve-plugins.c
+++ b/src/lib-sieve/sieve-plugins.c
@@ -3,9 +3,10 @@
 
 #include "lib.h"
 #include "str.h"
+#include "settings-parser.h"
 #include "module-dir.h"
+#include "master-service.h"
 
-#include "sieve-settings.old.h"
 #include "sieve-extensions.h"
 
 #include "sieve-common.h"
@@ -58,45 +59,55 @@ int sieve_plugins_load(struct sieve_instance *svinst, const char *path,
 {
 	struct module *module;
 	struct module_dir_load_settings mod_set;
-	const char **module_names;
+	const char *const *module_names;
 	unsigned int i;
 
 	/* Determine what to load */
 
 	if (path == NULL && plugins == NULL) {
-		path = sieve_setting_get(svinst, "sieve_plugin_dir");
-		plugins = sieve_setting_get(svinst, "sieve_plugins");
+		/* From settings */
+		module_names = settings_boollist_get(&svinst->set->plugins);
+		path = svinst->set->plugin_dir;
+	} else {
+		/* From function parameters */
+		const char **module_names_mod;
+
+		if (plugins == NULL || *plugins == '\0')
+			return 0;
+		module_names_mod = t_strsplit_spaces(plugins, ", ");
+
+		if (path == NULL || *path == '\0')
+			path = sieve_default_settings.plugin_dir;
+
+		for (i = 0; module_names_mod[i] != NULL; i++) {
+			/* Allow giving the module names also in non-base form.
+			 */
+			module_names_mod[i] =
+				module_file_get_name(module_names_mod[i]);
+		}
+		module_names = module_names_mod;
 	}
 
-	if (plugins == NULL || *plugins == '\0')
+	if (module_names == NULL || *module_names == NULL)
 		return 0;
 
-	if (path == NULL || *path == '\0')
-		path = MODULEDIR"/sieve";
-
 	i_zero(&mod_set);
 	mod_set.abi_version = PIGEONHOLE_ABI_VERSION;
+	mod_set.binary_name = master_service_get_name(master_service);
+	mod_set.setting_name = "sieve_plugins";
 	mod_set.require_init_funcs = TRUE;
-	mod_set.debug = FALSE;
+	mod_set.debug = svinst->debug;
 
 	/* Load missing plugin modules */
 
-	sieve_modules = module_dir_load_missing(
-		sieve_modules, path, t_strsplit_spaces(plugins, ", "),
-		&mod_set);
+	sieve_modules = module_dir_load_missing(sieve_modules, path,
+						module_names, &mod_set);
 
 	/* Call plugin load functions for this Sieve instance */
 
 	if (svinst->plugins == NULL)
 		sieve_modules_refcount++;
 
-	module_names = t_strsplit_spaces(plugins, ", ");
-
-	for (i = 0; module_names[i] != NULL; i++) {
-		/* Allow giving the module names also in non-base form. */
-		module_names[i] = module_file_get_name(module_names[i]);
-	}
-
  	for (i = 0; module_names[i] != NULL; i++) {
 		struct sieve_plugin *plugin;
 		const char *name = module_names[i];
diff --git a/src/lib-sieve/sieve-settings.c b/src/lib-sieve/sieve-settings.c
index 744cb5f02..8320d35d7 100644
--- a/src/lib-sieve/sieve-settings.c
+++ b/src/lib-sieve/sieve-settings.c
@@ -37,10 +37,13 @@ static const struct setting_define sieve_setting_defines[] = {
 	DEF(BOOL, trace_debug),
 	DEF(BOOL, trace_addresses),
 
+	DEF(BOOLLIST, plugins),
+	DEF(STR, plugin_dir),
+
 	SETTING_DEFINE_LIST_END,
 };
 
-static const struct sieve_settings sieve_default_settings = {
+const struct sieve_settings sieve_default_settings = {
 	.enabled = TRUE,
 
 	.max_script_size = SIEVE_DEFAULT_MAX_SCRIPT_SIZE,
@@ -60,6 +63,9 @@ static const struct sieve_settings sieve_default_settings = {
 	.trace_level = "none:actions:commands:tests:matching",
 	.trace_debug = FALSE,
 	.trace_addresses = FALSE,
+
+	.plugins = ARRAY_INIT,
+	.plugin_dir = MODULEDIR"/sieve",
 };
 
 const struct setting_parser_info sieve_setting_parser_info = {
@@ -86,7 +92,8 @@ sieve_settings_check(void *_set, pool_t pool, const char **error_r)
 	if (!sieve_address_source_parse(
 		pool, set->redirect_envelope_from,
 		&set->parsed.redirect_envelope_from)) {
-		*error_r = t_strdup_printf("Invalid address source '%s'",
+		*error_r = t_strdup_printf("sieve_redirect_envelope_from: "
+					   "Invalid address source '%s'",
 					   set->redirect_envelope_from);
 		return FALSE;
 	}
@@ -96,11 +103,22 @@ sieve_settings_check(void *_set, pool_t pool, const char **error_r)
 				    SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL,
 				    &address, &error) < 0) {
 		*error_r = t_strdup_printf(
-			"Invalid SMTP address '%s': %s",
+			"sieve_user_email: Invalid SMTP address '%s': %s",
 			set->user_email, error);
 		return FALSE;
 	}
 	set->parsed.user_email = address;
+
+#ifdef CONFIG_BINARY
+	if (array_is_created(&set->plugins) &&
+	    array_not_empty(&set->plugins) &&
+	    faccessat(AT_FDCWD, set->plugin_dir, R_OK | X_OK, AT_EACCESS) < 0) {
+		*error_r = t_strdup_printf(
+			"sieve_plugin_dir: access(%s) failed: %m",
+			set->plugin_dir);
+		return FALSE;
+	}
+#endif
 	return TRUE;
 }
 /* </settings checks> */
diff --git a/src/lib-sieve/sieve-settings.h b/src/lib-sieve/sieve-settings.h
index 568963eac..dc63b621a 100644
--- a/src/lib-sieve/sieve-settings.h
+++ b/src/lib-sieve/sieve-settings.h
@@ -32,12 +32,16 @@ struct sieve_settings {
 	bool trace_debug;
 	bool trace_addresses;
 
+	ARRAY_TYPE(const_string) plugins;
+	const char *plugin_dir;
+
 	struct {
 		struct sieve_address_source redirect_envelope_from;
 		const struct smtp_address *user_email;
 	} parsed;
 };
 
+extern const struct sieve_settings sieve_default_settings;
 extern const struct setting_parser_info sieve_setting_parser_info;
 
 #endif
-- 
GitLab