From 81a4e22d82fa47f1ce2049182e4e1bf9b72a2cd0 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 26 Jul 2009 02:37:58 +0200
Subject: [PATCH] Implemented skeleton of the mailbox extension.

---
 configure.in                                  |   1 +
 src/lib-sieve/Makefile.am                     |   4 +-
 src/lib-sieve/plugins/mailbox/Makefile.am     |  23 +++
 .../plugins/mailbox/cmd-mailboxexists.c       | 145 ++++++++++++++++++
 .../plugins/mailbox/ext-mailbox-common.h      |  40 +++++
 src/lib-sieve/plugins/mailbox/ext-mailbox.c   |  62 ++++++++
 .../plugins/mailbox/tag-mailbox-create.c      | 125 +++++++++++++++
 src/lib-sieve/sieve-extensions.c              |   4 +-
 8 files changed, 402 insertions(+), 2 deletions(-)
 create mode 100644 src/lib-sieve/plugins/mailbox/Makefile.am
 create mode 100644 src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c
 create mode 100644 src/lib-sieve/plugins/mailbox/ext-mailbox-common.h
 create mode 100644 src/lib-sieve/plugins/mailbox/ext-mailbox.c
 create mode 100644 src/lib-sieve/plugins/mailbox/tag-mailbox-create.c

diff --git a/configure.in b/configure.in
index 208a1113a..98f8cb729 100644
--- a/configure.in
+++ b/configure.in
@@ -115,6 +115,7 @@ src/lib-sieve/plugins/variables/Makefile
 src/lib-sieve/plugins/enotify/Makefile
 src/lib-sieve/plugins/notify/Makefile
 src/lib-sieve/plugins/environment/Makefile
+src/lib-sieve/plugins/mailbox/Makefile
 src/lib-sieve-tool/Makefile
 src/plugins/Makefile
 src/plugins/lda-sieve/Makefile
diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index ce9d26726..ed89d64c1 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -56,7 +56,9 @@ plugins = \
 	./plugins/variables/libsieve_ext_variables.la \
 	./plugins/enotify/libsieve_ext_enotify.la \
 	./plugins/notify/libsieve_ext_notify.la \
-	./plugins/environment/libsieve_ext_environment.la
+	./plugins/environment/libsieve_ext_environment.la \
+	./plugins/mailbox/libsieve_ext_mailbox.la
+
 
 libsieve_la_DEPENDENCIES = $(plugins)
 libsieve_la_LIBADD = $(plugins)
diff --git a/src/lib-sieve/plugins/mailbox/Makefile.am b/src/lib-sieve/plugins/mailbox/Makefile.am
new file mode 100644
index 000000000..7e93fa984
--- /dev/null
+++ b/src/lib-sieve/plugins/mailbox/Makefile.am
@@ -0,0 +1,23 @@
+noinst_LTLIBRARIES = libsieve_ext_mailbox.la
+
+AM_CPPFLAGS = \
+	-I../../ \
+	-I$(dovecot_incdir) \
+	-I$(dovecot_incdir)/src/lib \
+	-I$(dovecot_incdir)/src/lib-mail \
+	-I$(dovecot_incdir)/src/lib-storage 
+
+tags = \
+	tag-mailbox-create.c
+
+commands = \
+	cmd-mailboxexists.c
+
+libsieve_ext_mailbox_la_SOURCES = \
+	ext-mailbox-commonc \
+	$(tags) \
+	$(commands) \
+	ext-mailbox.c
+
+noinst_HEADERS = \
+	ext-mailbox-common.h
diff --git a/src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c b/src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c
new file mode 100644
index 000000000..94dc893bc
--- /dev/null
+++ b/src/lib-sieve/plugins/mailbox/cmd-mailboxexists.c
@@ -0,0 +1,145 @@
+/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#include "sieve-common.h"
+#include "sieve-commands.h"
+#include "sieve-code.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-dump.h"
+
+#include "ext-mailbox-common.h"
+
+/* 
+ * Mailboxexists command 
+ *
+ * Syntax:
+ *    mailboxexists <mailbox-names: string-list>
+ */
+
+static bool tst_mailboxexists_validate
+	(struct sieve_validator *validator, struct sieve_command_context *tst);
+static bool tst_mailboxexists_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
+
+const struct sieve_command mailboxexists_test = { 
+	"mailboxexists", 
+	SCT_TEST, 
+	1, 0, FALSE, FALSE,
+	NULL, NULL,
+	tst_mailboxexists_validate, 
+	tst_mailboxexists_generate, 
+	NULL 
+};
+
+/* 
+ * Mailboxexists operation
+ */
+
+static bool tst_mailboxexists_operation_dump
+	(const struct sieve_operation *op, 
+		const struct sieve_dumptime_env *denv, sieve_size_t *address);
+static int tst_mailboxexists_operation_execute
+	(const struct sieve_operation *op, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
+
+const struct sieve_operation mailboxexists_operation = { 
+	"MAILBOXEXISTS",
+	&mailbox_extension, 
+	0, 
+	tst_mailboxexists_operation_dump, 
+	tst_mailboxexists_operation_execute 
+};
+
+/* 
+ * Test validation 
+ */
+
+static bool tst_mailboxexists_validate
+	(struct sieve_validator *validator, struct sieve_command_context *tst) 
+{ 		
+	struct sieve_ast_argument *arg = tst->first_positional;
+	
+	if ( !sieve_validate_positional_argument
+		(validator, tst, arg, "mailbox-names", 1, SAAT_STRING_LIST) ) {
+		return FALSE;
+	}
+	
+	return sieve_validator_argument_activate(validator, tst, arg, FALSE);
+}
+
+/* 
+ * Test generation 
+ */
+
+static bool tst_mailboxexists_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command_context *tst) 
+{
+	sieve_operation_emit_code(cgenv->sbin, &mailboxexists_operation);
+
+ 	/* Generate arguments */
+	return sieve_generate_arguments(cgenv, tst, NULL);
+}
+
+/* 
+ * Code dump 
+ */
+
+static bool tst_mailboxexists_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
+	const struct sieve_dumptime_env *denv, sieve_size_t *address)
+{
+	sieve_code_dumpf(denv, "MAILBOXEXISTS");
+	sieve_code_descend(denv);
+		
+	return
+		sieve_opr_stringlist_dump(denv, address, "mailbox-names");
+}
+
+/* 
+ * Code execution 
+ */
+
+static int tst_mailboxexists_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED, 
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	struct sieve_coded_stringlist *mailbox_names;
+	string_t *uri_item;
+	bool result = TRUE, all_exist = TRUE;
+
+	/*
+	 * Read operands 
+	 */
+	
+	/* Read notify uris */
+	if ( (mailbox_names=sieve_opr_stringlist_read(renv, address)) == NULL ) {
+		sieve_runtime_trace_error(renv, "invalid mailbox-names operand");
+		return SIEVE_EXEC_BIN_CORRUPT;
+	}
+	
+	/*
+	 * Perform operation
+	 */
+
+	sieve_runtime_trace(renv, "MAILBOXEXISTS command");
+
+	uri_item = NULL;
+	while ( (result=sieve_coded_stringlist_next_item(mailbox_names, &uri_item)) 
+		&& uri_item != NULL ) {
+		
+		if ( TRUE ) {
+			all_exist = FALSE;
+			break;
+		}
+	}
+	
+	if ( !result ) {
+		sieve_runtime_trace_error(renv, "invalid mailbox name item");
+		return SIEVE_EXEC_BIN_CORRUPT;
+	}
+	
+	sieve_interpreter_set_test_result(renv->interp, all_exist);
+	return SIEVE_EXEC_OK;
+}
diff --git a/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h b/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h
new file mode 100644
index 000000000..4b593fd65
--- /dev/null
+++ b/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#ifndef __EXT_MAILBOX_COMMON_H
+#define __EXT_MAILBOX_COMMON_H
+
+#include "sieve-common.h"
+
+/*
+ * Tagged arguments
+ */
+
+extern const struct sieve_argument mailbox_create_tag;
+
+/*
+ * Commands
+ */
+
+extern const struct sieve_command mailboxexists_test;
+
+/*
+ * Operands
+ */
+
+extern const struct sieve_operand mailbox_create_operand;
+
+/*
+ * Operations
+ */
+
+extern const struct sieve_operation mailboxexists_operation;
+
+/*
+ * Extension
+ */
+
+extern const struct sieve_extension mailbox_extension;
+
+#endif /* __EXT_MAILBOX_COMMON_H */
+
diff --git a/src/lib-sieve/plugins/mailbox/ext-mailbox.c b/src/lib-sieve/plugins/mailbox/ext-mailbox.c
new file mode 100644
index 000000000..c0fc6e8b4
--- /dev/null
+++ b/src/lib-sieve/plugins/mailbox/ext-mailbox.c
@@ -0,0 +1,62 @@
+/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
+ */
+
+/* Extension mailbox
+ * ------------------
+ *
+ * Authors: Stephan Bosch
+ * Specification: RFC 5490
+ * Implementation: skeleton
+ * Status: under development
+ * 
+ */
+
+#include <stdio.h>
+
+#include "sieve-common.h"
+
+#include "sieve-code.h"
+#include "sieve-extensions.h"
+#include "sieve-actions.h"
+#include "sieve-commands.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-result.h"
+
+#include "ext-mailbox-common.h"
+
+/* 
+ * Extension
+ */
+
+static bool ext_mailbox_validator_load(struct sieve_validator *valdtr);
+
+static int ext_my_id = -1;
+
+const struct sieve_extension mailbox_extension = { 
+	"mailbox", 
+	&ext_my_id,
+	NULL, NULL,
+	ext_mailbox_validator_load, 
+	NULL, NULL, NULL, NULL, NULL,
+	SIEVE_EXT_DEFINE_OPERATION(mailboxexists_operation),
+	SIEVE_EXT_DEFINE_OPERAND(mailbox_create_operand)
+};
+
+static bool ext_mailbox_validator_load(struct sieve_validator *valdtr)
+{
+	/* Register :create tag with fileinto command and we don't care whether this 
+	 * command is registered or even whether it will be registered at all. The 
+	 * validator handles either situation gracefully 
+	 */
+	sieve_validator_register_external_tag
+		(valdtr, &mailbox_create_tag, "fileinto", -1);
+
+	/* Register new test */
+	sieve_validator_register_command(valdtr, &mailboxexists_test);
+
+	return TRUE;
+}
+
+
diff --git a/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c b/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c
new file mode 100644
index 000000000..d6a70424d
--- /dev/null
+++ b/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c
@@ -0,0 +1,125 @@
+/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#include "lib.h"
+
+#include "sieve-common.h"
+#include "sieve-commands.h"
+#include "sieve-code.h"
+#include "sieve-actions.h"
+#include "sieve-result.h"
+#include "sieve-generator.h"
+
+#include "ext-mailbox-common.h"
+
+/* 
+ * Tagged argument 
+ */
+
+static bool tag_mailbox_create_validate
+	(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
+		struct sieve_command_context *cmd);
+static bool tag_mailbox_create_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
+    struct sieve_command_context *context);
+
+const struct sieve_argument mailbox_create_tag = { 
+	"create", 
+	NULL, NULL,
+	tag_mailbox_create_validate, 
+	NULL,
+	tag_mailbox_create_generate
+};
+
+/*
+ * Side effect 
+ */
+
+static void seff_mailbox_create_print
+	(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+		const struct sieve_result_print_env *rpenv, void *se_context, bool *keep);
+static void seff_mailbox_create_post_commit
+	(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+		const struct sieve_action_exec_env *aenv, void *se_context,
+		void *tr_context, bool *keep);
+
+const struct sieve_side_effect mailbox_create_side_effect = {
+	SIEVE_OBJECT("create", &mailbox_create_operand, 0),
+	&act_store,
+	NULL, NULL, NULL,
+	seff_mailbox_create_print,
+	NULL, NULL,
+	seff_mailbox_create_post_commit, 
+	NULL
+};
+
+/*
+ * Operand
+ */
+
+static const struct sieve_extension_objects ext_side_effects =
+	SIEVE_EXT_DEFINE_SIDE_EFFECT(mailbox_create_side_effect);
+
+const struct sieve_operand mailbox_create_operand = {
+	"create operand",
+	&mailbox_extension,
+	0,
+	&sieve_side_effect_operand_class,
+	&ext_side_effects
+};
+
+/* 
+ * Tag validation 
+ */
+
+static bool tag_mailbox_create_validate
+	(struct sieve_validator *validator ATTR_UNUSED, 
+	struct sieve_ast_argument **arg ATTR_UNUSED, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
+{
+	*arg = sieve_ast_argument_next(*arg);
+
+	return TRUE;
+}
+
+/*
+ * Code generation 
+ */
+
+static bool tag_mailbox_create_generate
+(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg,
+    struct sieve_command_context *context ATTR_UNUSED)
+{
+	if ( sieve_ast_argument_type(arg) != SAAT_TAG ) {
+		return FALSE;
+	}
+
+	sieve_opr_side_effect_emit(cgenv->sbin, &mailbox_create_side_effect);
+
+	return TRUE;
+}
+
+/* 
+ * Side effect implementation
+ */
+
+static void seff_mailbox_create_print
+(const struct sieve_side_effect *seffect ATTR_UNUSED, 
+	const struct sieve_action *action ATTR_UNUSED, 
+	const struct sieve_result_print_env *rpenv,
+	void *se_context ATTR_UNUSED, bool *keep ATTR_UNUSED)
+{
+	sieve_result_seffect_printf(rpenv, "create mailbox if it does not exist");
+}
+
+static void seff_mailbox_create_post_commit
+(const struct sieve_side_effect *seffect ATTR_UNUSED, 
+	const struct sieve_action *action ATTR_UNUSED, 
+	const struct sieve_action_exec_env *aenv ATTR_UNUSED,
+	void *se_context ATTR_UNUSED, void *tr_context ATTR_UNUSED, 
+	bool *keep ATTR_UNUSED)
+{	
+}
+
+
+
diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index 368fb6caa..897f7071f 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -80,6 +80,7 @@ extern const struct sieve_extension body_extension;
 extern const struct sieve_extension variables_extension;
 extern const struct sieve_extension enotify_extension;
 extern const struct sieve_extension environment_extension;
+extern const struct sieve_extension mailbox_extension;
 
 /*
  * Extensions under development
@@ -117,7 +118,8 @@ const struct sieve_extension *sieve_core_extensions[] = {
 	&comparator_i_ascii_numeric_extension, 
 	&relational_extension, &regex_extension, &imap4flags_extension,
 	&copy_extension, &include_extension, &body_extension,
-	&variables_extension, &enotify_extension, &environment_extension
+	&variables_extension, &enotify_extension, &environment_extension,
+	&mailbox_extension
 };
 
 const unsigned int sieve_core_extensions_count =
-- 
GitLab