From fbbd3bd1c7b0f13f8c021dd009b5c5b97c545e58 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Wed, 21 Aug 2024 20:34:56 +0200
Subject: [PATCH] lib-sieve: variables extension: Migrate settings to new
 config structure

---
 src/lib-sieve/plugins/variables/Makefile.am   |  2 +
 .../plugins/variables/ext-variables-common.c  | 58 +++++----------
 .../plugins/variables/ext-variables-common.h  |  6 +-
 .../plugins/variables/ext-variables-limits.h  |  3 -
 .../variables/ext-variables-modifiers.c       | 13 ++--
 .../variables/ext-variables-operands.c        |  7 +-
 .../variables/ext-variables-settings.c        | 74 +++++++++++++++++++
 .../variables/ext-variables-settings.h        | 15 ++++
 8 files changed, 122 insertions(+), 56 deletions(-)
 create mode 100644 src/lib-sieve/plugins/variables/ext-variables-settings.c
 create mode 100644 src/lib-sieve/plugins/variables/ext-variables-settings.h

diff --git a/src/lib-sieve/plugins/variables/Makefile.am b/src/lib-sieve/plugins/variables/Makefile.am
index 354bad2a6..d5c9c7b8e 100644
--- a/src/lib-sieve/plugins/variables/Makefile.am
+++ b/src/lib-sieve/plugins/variables/Makefile.am
@@ -11,6 +11,7 @@ tsts = \
 	tst-string.c
 
 libsieve_ext_variables_la_SOURCES = \
+	ext-variables-settings.c \
 	ext-variables-common.c \
 	ext-variables-name.c \
 	ext-variables-namespaces.c \
@@ -26,6 +27,7 @@ public_headers = \
 	sieve-ext-variables.h
 
 headers = \
+	ext-variables-settings.h \
 	ext-variables-common.h \
 	ext-variables-limits.h \
 	ext-variables-name.h \
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index aca892089..a33efc9d3 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -5,9 +5,9 @@
 #include "hash.h"
 #include "str.h"
 #include "array.h"
+#include "settings.h"
 
 #include "sieve-common.h"
-#include "sieve-settings.old.h"
 
 #include "sieve-ast.h"
 #include "sieve-binary.h"
@@ -22,7 +22,6 @@
 #include "sieve-interpreter.h"
 
 #include "ext-variables-common.h"
-#include "ext-variables-limits.h"
 #include "ext-variables-name.h"
 #include "ext-variables-modifiers.h"
 
@@ -36,7 +35,7 @@ sieve_variables_get_max_scope_size(const struct sieve_extension *var_ext)
 	const struct ext_variables_context *extctx =
 		ext_variables_get_context(var_ext);
 
-	return extctx->max_scope_size;
+	return extctx->set->max_scope_size;
 }
 
 size_t sieve_variables_get_max_variable_size(
@@ -45,7 +44,7 @@ size_t sieve_variables_get_max_variable_size(
 	const struct ext_variables_context *extctx =
 		ext_variables_get_context(var_ext);
 
-	return extctx->max_variable_size;
+	return extctx->set->max_variable_size;
 }
 
 /*
@@ -55,42 +54,18 @@ size_t sieve_variables_get_max_variable_size(
 int ext_variables_load(const struct sieve_extension *ext, void **context_r)
 {
 	struct sieve_instance *svinst = ext->svinst;
+	const struct ext_variables_settings *set;
 	struct ext_variables_context *extctx;
-	unsigned long long int uint_setting;
-	size_t size_setting;
+	const char *error;
 
-	extctx = i_new(struct ext_variables_context, 1);
-
-	/* Get limits */
-	extctx->max_scope_size = EXT_VARIABLES_DEFAULT_MAX_SCOPE_SIZE;
-	extctx->max_variable_size = EXT_VARIABLES_DEFAULT_MAX_VARIABLE_SIZE;
-
-	if (sieve_setting_get_uint_value(
-		svinst, "sieve_variables_max_scope_size", &uint_setting)) {
-		if (uint_setting < EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE) {
-			e_warning(svinst->event, "variables: "
-				  "setting sieve_variables_max_scope_size "
-				  "is lower than required by standards "
-				  "(>= %llu items)",
-				  (unsigned long long)
-					EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE);
-		} else {
-			extctx->max_scope_size = (unsigned int)uint_setting;
-		}
+	if (settings_get(svinst->event, &ext_variables_setting_parser_info, 0,
+			 &set, &error) < 0) {
+		e_error(svinst->event, "%s", error);
+		return -1;
 	}
 
-	if (sieve_setting_get_size_value(
-		svinst, "sieve_variables_max_variable_size", &size_setting)) {
-		if (size_setting < EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE) {
-			e_warning(svinst->event, "variables: "
-				  "setting sieve_variables_max_variable_size "
-				  "is lower than required by standards "
-				  "(>= %zu bytes)",
-				  (size_t)EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE);
-		} else {
-			extctx->max_variable_size = size_setting;
-		}
-	}
+	extctx = i_new(struct ext_variables_context, 1);
+	extctx->set = set;
 
 	*context_r = extctx;
 	return 0;
@@ -100,6 +75,9 @@ void ext_variables_unload(const struct sieve_extension *ext)
 {
 	struct ext_variables_context *extctx = ext->context;
 
+	if (extctx == NULL)
+		return;
+	settings_free(extctx->set);
 	i_free(extctx);
 }
 
@@ -627,8 +605,8 @@ bool sieve_variable_assign(struct sieve_variable_storage *storage,
 	str_append_str(varval, value);
 
 	/* Just a precaution, caller should prevent this in the first place */
-	if (str_len(varval) > extctx->max_variable_size)
-		str_truncate_utf8(varval, extctx->max_variable_size);
+	if (str_len(varval) > extctx->set->max_variable_size)
+		str_truncate_utf8(varval, extctx->set->max_variable_size);
 
 	return TRUE;
 }
@@ -647,8 +625,8 @@ bool sieve_variable_assign_cstr(struct sieve_variable_storage *storage,
 	str_append(varval, value);
 
 	/* Just a precaution, caller should prevent this in the first place */
-	if (str_len(varval) > extctx->max_variable_size)
-		str_truncate_utf8(varval, extctx->max_variable_size);
+	if (str_len(varval) > extctx->set->max_variable_size)
+		str_truncate_utf8(varval, extctx->set->max_variable_size);
 
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index 16c6dab9a..5a389a26b 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -5,16 +5,14 @@
 #include "sieve-validator.h"
 
 #include "sieve-ext-variables.h"
+#include "ext-variables-settings.h"
 
 /*
  * Extension
  */
 
 struct ext_variables_context {
-	/* Maximum number of variables (in a scope) */
-	unsigned int max_scope_size;
-	/* Maximum size of variable value */
-	size_t max_variable_size;
+	const struct ext_variables_settings *set;
 };
 
 extern const struct sieve_extension_def variables_extension;
diff --git a/src/lib-sieve/plugins/variables/ext-variables-limits.h b/src/lib-sieve/plugins/variables/ext-variables-limits.h
index 61260c822..c525c176e 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-limits.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-limits.h
@@ -21,9 +21,6 @@
  *  as a syntax error, which SHOULD be discovered at compile-time.
  */
 
-#define EXT_VARIABLES_DEFAULT_MAX_SCOPE_SIZE     255
-#define EXT_VARIABLES_DEFAULT_MAX_VARIABLE_SIZE  (4 * 1024)
-
 #define EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE    128
 #define EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE 4000
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables-modifiers.c b/src/lib-sieve/plugins/variables/ext-variables-modifiers.c
index 37ebe920b..b48c8ce9a 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-modifiers.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-modifiers.c
@@ -545,12 +545,13 @@ int sieve_variables_modifiers_apply(
 	unsigned int i, modf_count;
 
 	/* Hold value within limits */
-	if (str_len(*value) > extctx->max_variable_size) {
+	if (str_len(*value) > extctx->set->max_variable_size) {
 		/* assume variable originates from code, so copy it first */
-		string_t *new_value = t_str_new(extctx->max_variable_size+3);
+		string_t *new_value =
+			t_str_new(extctx->set->max_variable_size+3);
 		str_append_str(new_value, *value);
 		*value = new_value;
-		str_truncate_utf8(*value, extctx->max_variable_size);
+		str_truncate_utf8(*value, extctx->set->max_variable_size);
 	}
 
 	if (!array_is_created(modifiers))
@@ -580,9 +581,9 @@ int sieve_variables_modifiers_apply(
 				str_sanitize(str_c(new_value), 256));
 
 			/* Hold value within limits */
-			if (str_len(*value) > extctx->max_variable_size) {
-				str_truncate_utf8(*value,
-						  extctx->max_variable_size);
+			if (str_len(*value) > extctx->set->max_variable_size) {
+				str_truncate_utf8(
+					*value, extctx->set->max_variable_size);
 			}
 		}
 	}
diff --git a/src/lib-sieve/plugins/variables/ext-variables-operands.c b/src/lib-sieve/plugins/variables/ext-variables-operands.c
index 6e4d28c64..1f2a46b27 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-operands.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-operands.c
@@ -278,9 +278,10 @@ opr_match_value_read(const struct sieve_runtime_env *renv,
 
 			if (*str_r == NULL)
 				*str_r = t_str_new(0);
-			else if (str_len(*str_r) > extctx->max_variable_size) {
-				str_truncate_utf8(*str_r,
-						  extctx->max_variable_size);
+			else if (str_len(*str_r) >
+				 extctx->set->max_variable_size) {
+				str_truncate_utf8(
+					*str_r, extctx->set->max_variable_size);
 			}
 		}
 		return SIEVE_EXEC_OK;
diff --git a/src/lib-sieve/plugins/variables/ext-variables-settings.c b/src/lib-sieve/plugins/variables/ext-variables-settings.c
new file mode 100644
index 000000000..c2615b357
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/ext-variables-settings.c
@@ -0,0 +1,74 @@
+/* Copyright (c) 2024 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "array.h"
+#include "settings.h"
+#include "settings-parser.h"
+
+#include "ext-variables-limits.h"
+#include "ext-variables-settings.h"
+
+static bool
+ext_variables_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+			     const char **error_r);
+
+#undef DEF
+#define DEF(type, name) \
+	SETTING_DEFINE_STRUCT_##type("sieve_variables_"#name, name, \
+				     struct ext_variables_settings)
+
+static const struct setting_define ext_variables_setting_defines[] = {
+	DEF(UINT, max_scope_size),
+	DEF(SIZE, max_variable_size),
+
+	SETTING_DEFINE_LIST_END,
+};
+
+static const struct ext_variables_settings ext_variables_default_settings = {
+	.max_scope_size = 255,
+	.max_variable_size = (4 * 1024),
+};
+
+const struct setting_parser_info ext_variables_setting_parser_info = {
+	.name = "sieve_variables",
+
+	.defines = ext_variables_setting_defines,
+	.defaults = &ext_variables_default_settings,
+
+	.struct_size = sizeof(struct ext_variables_settings),
+
+	.check_func = ext_variables_settings_check,
+
+	.pool_offset1 = 1 + offsetof(struct ext_variables_settings, pool),
+};
+
+/* <settings checks> */
+static bool
+ext_variables_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+			     const char **error_r)
+{
+	struct ext_variables_settings *set = _set;
+
+	if (set->max_scope_size < EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE) {
+		*error_r = t_strdup_printf(
+			  "Setting sieve_variables_max_scope_size "
+			  "is lower than required by standards "
+			  "(>= %llu items)",
+			  (unsigned long long)
+				EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE);
+		return FALSE;
+	}
+	if (set->max_variable_size < EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE) {
+		*error_r = t_strdup_printf(
+			  "Setting sieve_variables_max_variable_size "
+			  "is lower than required by standards "
+			  "(>= %zu bytes)",
+			  (size_t)EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+/* </settings checks> */
+
diff --git a/src/lib-sieve/plugins/variables/ext-variables-settings.h b/src/lib-sieve/plugins/variables/ext-variables-settings.h
new file mode 100644
index 000000000..4ba9eae9f
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/ext-variables-settings.h
@@ -0,0 +1,15 @@
+#ifndef EXT_VARIABLES_SETTINGS_H
+#define EXT_VARIABLES_SETTINGS_H
+
+struct ext_variables_settings {
+	pool_t pool;
+
+	/* Maximum number of variables (in a scope) */
+	unsigned int max_scope_size;
+	/* Maximum size of variable value */
+	size_t max_variable_size;
+};
+
+extern const struct setting_parser_info ext_variables_setting_parser_info;
+
+#endif
-- 
GitLab