dovecot-2.2-pigeonhole: Implemented Sieve extracttext extension.

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Fri Jan 8 19:51:28 UTC 2016


details:   http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/fe174b9f29ad
changeset: 2216:fe174b9f29ad
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Fri Jan 08 20:49:39 2016 +0100
description:
Implemented Sieve extracttext extension.

diffstat:

 Makefile.am                                               |    1 +
 src/lib-sieve/plugins/mime/Makefile.am                    |   12 +-
 src/lib-sieve/plugins/mime/cmd-extracttext.c              |  367 ++++++++++++++
 src/lib-sieve/plugins/mime/ext-extracttext.c              |  126 ++++
 src/lib-sieve/plugins/mime/ext-mime-common.h              |    8 +
 src/lib-sieve/plugins/variables/cmd-set.c                 |  233 +-------
 src/lib-sieve/plugins/variables/ext-variables-modifiers.c |  255 +++++++++-
 src/lib-sieve/plugins/variables/sieve-ext-variables.h     |   41 +-
 src/lib-sieve/sieve-extensions.c                          |    4 +-
 tests/extensions/mime/errors.svtest                       |   31 +
 tests/extensions/mime/errors/extracttext-nofep.sieve      |    4 +
 tests/extensions/mime/errors/extracttext-novar.sieve      |    6 +
 tests/extensions/mime/errors/extracttext.sieve            |   42 +
 tests/extensions/mime/extracttext.svtest                  |  143 +++++
 14 files changed, 1061 insertions(+), 212 deletions(-)

diffs (truncated from 1561 to 300 lines):

diff -r 46a974ebd896 -r fe174b9f29ad Makefile.am
--- a/Makefile.am	Fri Jan 08 20:49:39 2016 +0100
+++ b/Makefile.am	Fri Jan 08 20:49:39 2016 +0100
@@ -173,6 +173,7 @@
 	tests/extensions/mime/execute.svtest \
 	tests/extensions/mime/content-header.svtest \
 	tests/extensions/mime/foreverypart.svtest \
+	tests/extensions/mime/extracttext.svtest \
 	tests/extensions/mime/calendar-example.svtest \
 	tests/extensions/vnd.dovecot/debug/execute.svtest \
 	tests/extensions/vnd.dovecot/environment/basic.svtest \
diff -r 46a974ebd896 -r fe174b9f29ad src/lib-sieve/plugins/mime/Makefile.am
--- a/src/lib-sieve/plugins/mime/Makefile.am	Fri Jan 08 20:49:39 2016 +0100
+++ b/src/lib-sieve/plugins/mime/Makefile.am	Fri Jan 08 20:49:39 2016 +0100
@@ -3,21 +3,27 @@
 AM_CPPFLAGS = \
 	-I$(srcdir)/../.. \
 	-I$(srcdir)/../../util \
+	-I$(srcdir)/../variables  \
 	$(LIBDOVECOT_INCLUDE)
 
 commands = \
 	cmd-foreverypart.c \
-	cmd-break.c
+	cmd-break.c \
+	cmd-extracttext.c
 
 tags = \
 	tag-mime.c
 
-libsieve_ext_mime_la_SOURCES = \
+extensions = \
 	ext-mime.c \
 	ext-foreverypart.c \
+	ext-extracttext.c
+
+libsieve_ext_mime_la_SOURCES = \
 	ext-mime-common.c \
 	$(commands) \
-	$(tags)
+	$(tags) \
+	$(extensions)
 
 noinst_HEADERS = \
 	ext-mime-common.h
diff -r 46a974ebd896 -r fe174b9f29ad src/lib-sieve/plugins/mime/cmd-extracttext.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sieve/plugins/mime/cmd-extracttext.c	Fri Jan 08 20:49:39 2016 +0100
@@ -0,0 +1,367 @@
+/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "str.h"
+#include "array.h"
+
+#include "sieve-common.h"
+#include "sieve-extensions.h"
+#include "sieve-code.h"
+#include "sieve-ast.h"
+#include "sieve-commands.h"
+#include "sieve-binary.h"
+#include "sieve-message.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-dump.h"
+
+#include "sieve-ext-variables.h"
+
+#include "ext-mime-common.h"
+
+/*
+ * Extracttext command
+ *
+ * Syntax:
+ *    extracttext [MODIFIER] [":first" number] <varname: string>
+ */
+
+static bool cmd_extracttext_registered
+	(struct sieve_validator *valdtr, const struct sieve_extension *ext,
+		struct sieve_command_registration *cmd_reg);
+static bool cmd_extracttext_validate
+	(struct sieve_validator *valdtr, struct sieve_command *cmd);
+static bool cmd_extracttext_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command *ctx);
+
+const struct sieve_command_def cmd_extracttext = {
+	.identifier = "extracttext",
+	.type = SCT_COMMAND,
+	.positional_args = 1,
+	.subtests = 0,
+	.block_allowed = FALSE,
+	.block_required = FALSE,
+	.registered = cmd_extracttext_registered,
+	.validate = cmd_extracttext_validate,
+	.generate = cmd_extracttext_generate
+};
+
+/*
+ * Extracttext command tags
+ */
+
+enum cmd_extracttext_optional {
+	CMD_EXTRACTTEXT_OPT_END,
+	CMD_EXTRACTTEXT_OPT_FIRST
+};
+
+static bool cmd_extracttext_validate_first_tag
+	(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
+		struct sieve_command *cmd);
+
+static const struct sieve_argument_def extracttext_from_tag = {
+	.identifier = "first",
+	.validate = cmd_extracttext_validate_first_tag
+};
+
+/*
+ * Extracttext operation
+ */
+
+static bool cmd_extracttext_operation_dump
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
+static int cmd_extracttext_operation_execute
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
+
+const struct sieve_operation_def extracttext_operation = {
+	.mnemonic = "EXTRACTTEXT",
+	.ext_def = &extracttext_extension,
+	.dump = cmd_extracttext_operation_dump,
+	.execute = cmd_extracttext_operation_execute
+};
+
+/*
+ * Compiler context
+ */
+
+struct cmd_extracttext_context {
+	ARRAY_TYPE(sieve_variables_modifier) modifiers;
+};
+
+/*
+ * Tag validation
+ */
+
+static bool cmd_extracttext_validate_first_tag
+(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
+	struct sieve_command *cmd)
+{
+	struct sieve_ast_argument *tag = *arg;
+
+	/* Detach the tag itself */
+	*arg = sieve_ast_arguments_detach(*arg,1);
+
+	/* Check syntax:
+	 *   :first <number>
+	 */
+	if ( !sieve_validate_tag_parameter
+		(valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) )
+		return FALSE;
+
+	/* Skip parameter */
+	*arg = sieve_ast_argument_next(*arg);
+
+	return TRUE;
+}
+
+/* Command registration */
+
+static bool cmd_extracttext_registered
+(struct sieve_validator *valdtr, const struct sieve_extension *ext,
+	struct sieve_command_registration *cmd_reg)
+{
+	struct ext_extracttext_context *ectx =
+		(struct ext_extracttext_context *)ext->context;
+
+	sieve_validator_register_tag(valdtr, cmd_reg, ext,
+		&extracttext_from_tag, CMD_EXTRACTTEXT_OPT_FIRST);
+	sieve_variables_modifiers_link_tag
+		(valdtr, ectx->var_ext, cmd_reg);
+	return TRUE;
+}
+
+/*
+ * Command validation
+ */
+
+static bool cmd_extracttext_validate(struct sieve_validator *valdtr,
+	struct sieve_command *cmd)
+{
+	const struct sieve_extension *this_ext = cmd->ext;
+	struct ext_extracttext_context *ectx =
+		(struct ext_extracttext_context *)this_ext->context;
+	struct sieve_ast_node *node = cmd->ast_node;
+	struct sieve_ast_argument *arg = cmd->first_positional;
+	pool_t pool = sieve_command_pool(cmd);
+	struct cmd_extracttext_context *sctx;
+
+	/* Create command context */
+	sctx = p_new(pool, struct cmd_extracttext_context, 1);
+	p_array_init(&sctx->modifiers, pool, 4);
+	cmd->data = (void *) sctx;
+
+	/* Validate modifiers */
+	if ( !sieve_variables_modifiers_validate
+		(valdtr, cmd, &sctx->modifiers) )
+		return FALSE;
+
+	/* Validate varname argument */
+	if ( !sieve_validate_positional_argument
+		(valdtr, cmd, arg, "varname", 1, SAAT_STRING) ) {
+		return FALSE;
+	}
+	if ( !sieve_variable_argument_activate
+		(ectx->var_ext, valdtr, cmd, arg, TRUE) )
+		return FALSE;
+
+	/* Check foreverypart context */
+	i_assert(node != NULL);
+	while ( node != NULL ) {
+		if ( node->command != NULL &&
+			sieve_command_is(node->command, cmd_foreverypart) )
+			break;
+		node = sieve_ast_node_parent(node);
+	}
+
+	if ( node == NULL ) {
+		sieve_command_validate_error(valdtr, cmd,
+			"the extracttext command is not placed inside "
+			"a foreverypart loop");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/*
+ * Code generation
+ */
+
+static bool cmd_extracttext_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd)
+{
+	const struct sieve_extension *this_ext = cmd->ext;
+	struct sieve_binary_block *sblock = cgenv->sblock;
+	struct cmd_extracttext_context *sctx =
+		(struct cmd_extracttext_context *) cmd->data;
+
+	sieve_operation_emit(sblock, this_ext, &extracttext_operation);
+
+	/* Generate arguments */
+	if ( !sieve_generate_arguments(cgenv, cmd, NULL) )
+		return FALSE;
+
+	/* Generate modifiers */
+	if ( !sieve_variables_modifiers_generate
+		(cgenv, &sctx->modifiers) )
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+ * Code dump
+ */
+
+static bool cmd_extracttext_operation_dump
+(const struct sieve_dumptime_env *denv, sieve_size_t *address)
+{
+	int opt_code = 0;
+
+	sieve_code_dumpf(denv, "EXTRACTTEXT");
+	sieve_code_descend(denv);
+
+	/* Dump optional operands */
+
+	for (;;) {
+		int opt;
+		bool opok = TRUE;
+
+		if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 )
+			return FALSE;
+		if ( opt == 0 ) break;
+
+		switch ( opt_code ) {
+		case CMD_EXTRACTTEXT_OPT_FIRST:
+			opok = sieve_opr_number_dump(denv, address, "first");
+			break;
+		default:
+			return FALSE;
+		}
+		if ( !opok ) return FALSE;
+	}
+
+	/* Print both variable name and string value */
+	if ( !sieve_opr_string_dump(denv, address, "varname") )
+		return FALSE;
+
+	return sieve_variables_modifiers_code_dump(denv, address);
+}
+


More information about the dovecot-cvs mailing list