From dd412acbf900044a325b2fa54cb588fb63ce99d2 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Wed, 8 Jul 2009 19:37:24 +0200 Subject: [PATCH] Added partial support for the depricated notify extension. --- src/lib-sieve/plugins/enotify/Makefile.am | 1 + src/lib-sieve/plugins/enotify/cmd-notify.c | 34 +- .../plugins/enotify/ext-enotify-common.h | 11 + src/lib-sieve/plugins/enotify/ext-notify.c | 374 ++++++++++++++++++ src/lib-sieve/sieve-ast.c | 6 + src/lib-sieve/sieve-ast.h | 2 + src/lib-sieve/sieve-extensions.c | 4 +- 7 files changed, 409 insertions(+), 23 deletions(-) create mode 100644 src/lib-sieve/plugins/enotify/ext-notify.c diff --git a/src/lib-sieve/plugins/enotify/Makefile.am b/src/lib-sieve/plugins/enotify/Makefile.am index 4d91fd8c4..ad0818c46 100644 --- a/src/lib-sieve/plugins/enotify/Makefile.am +++ b/src/lib-sieve/plugins/enotify/Makefile.am @@ -23,6 +23,7 @@ notify_methods = \ libsieve_ext_enotify_la_SOURCES = \ ext-enotify.c \ + ext-notify.c \ ext-enotify-common.c \ $(commands) \ $(tests) \ diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c index e257c3f1d..0d243b493 100644 --- a/src/lib-sieve/plugins/enotify/cmd-notify.c +++ b/src/lib-sieve/plugins/enotify/cmd-notify.c @@ -103,16 +103,6 @@ static const struct sieve_argument notify_importance_tag = { NULL, NULL }; -/* Codes for optional arguments */ - -enum cmd_notify_optional { - OPT_END, - OPT_FROM, - OPT_OPTIONS, - OPT_MESSAGE, - OPT_IMPORTANCE -}; - /* * Notify operation */ @@ -287,13 +277,13 @@ static bool cmd_notify_registered (struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg) { sieve_validator_register_tag - (valdtr, cmd_reg, ¬ify_importance_tag, OPT_IMPORTANCE); + (valdtr, cmd_reg, ¬ify_importance_tag, CMD_NOTIFY_OPT_IMPORTANCE); sieve_validator_register_tag - (valdtr, cmd_reg, ¬ify_from_tag, OPT_FROM); + (valdtr, cmd_reg, ¬ify_from_tag, CMD_NOTIFY_OPT_FROM); sieve_validator_register_tag - (valdtr, cmd_reg, ¬ify_options_tag, OPT_OPTIONS); + (valdtr, cmd_reg, ¬ify_options_tag, CMD_NOTIFY_OPT_OPTIONS); sieve_validator_register_tag - (valdtr, cmd_reg, ¬ify_message_tag, OPT_MESSAGE); + (valdtr, cmd_reg, ¬ify_message_tag, CMD_NOTIFY_OPT_MESSAGE); return TRUE; } @@ -379,19 +369,19 @@ static bool cmd_notify_operation_dump switch ( opt_code ) { case 0: break; - case OPT_IMPORTANCE: + case CMD_NOTIFY_OPT_IMPORTANCE: if ( !sieve_opr_number_dump(denv, address, "importance") ) return FALSE; break; - case OPT_FROM: + case CMD_NOTIFY_OPT_FROM: if ( !sieve_opr_string_dump(denv, address, "from") ) return FALSE; break; - case OPT_OPTIONS: + case CMD_NOTIFY_OPT_OPTIONS: if ( !sieve_opr_stringlist_dump(denv, address, "options") ) return FALSE; break; - case OPT_MESSAGE: + case CMD_NOTIFY_OPT_MESSAGE: if ( !sieve_opr_string_dump(denv, address, "message") ) return FALSE; break; @@ -446,7 +436,7 @@ static int cmd_notify_operation_execute switch ( opt_code ) { case 0: break; - case OPT_IMPORTANCE: + case CMD_NOTIFY_OPT_IMPORTANCE: if ( !sieve_opr_number_read(renv, address, &importance) ) { sieve_runtime_trace_error(renv, "invalid importance operand"); return SIEVE_EXEC_BIN_CORRUPT; @@ -458,19 +448,19 @@ static int cmd_notify_operation_execute else if ( importance > 3 ) importance = 3; break; - case OPT_FROM: + case CMD_NOTIFY_OPT_FROM: if ( !sieve_opr_string_read(renv, address, &from) ) { sieve_runtime_trace_error(renv, "invalid from operand"); return SIEVE_EXEC_BIN_CORRUPT; } break; - case OPT_MESSAGE: + case CMD_NOTIFY_OPT_MESSAGE: if ( !sieve_opr_string_read(renv, address, &message) ) { sieve_runtime_trace_error(renv, "invalid from operand"); return SIEVE_EXEC_BIN_CORRUPT; } break; - case OPT_OPTIONS: + case CMD_NOTIFY_OPT_OPTIONS: if ( (options=sieve_opr_stringlist_read(renv, address)) == NULL ) { sieve_runtime_trace_error(renv, "invalid options operand"); return SIEVE_EXEC_BIN_CORRUPT; diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.h b/src/lib-sieve/plugins/enotify/ext-enotify-common.h index 52fad08c3..0da2e5eac 100644 --- a/src/lib-sieve/plugins/enotify/ext-enotify-common.h +++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.h @@ -13,6 +13,7 @@ */ extern const struct sieve_extension enotify_extension; +extern const struct sieve_extension notify_extension; extern const struct sieve_extension_capabilities notify_capabilities; /* @@ -21,6 +22,16 @@ extern const struct sieve_extension_capabilities notify_capabilities; extern const struct sieve_command notify_command; +/* Codes for optional arguments */ + +enum cmd_notify_optional { + CMD_NOTIFY_OPT_END, + CMD_NOTIFY_OPT_FROM, + CMD_NOTIFY_OPT_OPTIONS, + CMD_NOTIFY_OPT_MESSAGE, + CMD_NOTIFY_OPT_IMPORTANCE +}; + /* * Tests */ diff --git a/src/lib-sieve/plugins/enotify/ext-notify.c b/src/lib-sieve/plugins/enotify/ext-notify.c new file mode 100644 index 000000000..776fae4dc --- /dev/null +++ b/src/lib-sieve/plugins/enotify/ext-notify.c @@ -0,0 +1,374 @@ +/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file + */ + +/* Extension notify + * ---------------- + * + * Authors: Stephan Bosch + * Specification: draft-ietf-sieve-notify-00.txt + * Implementation: deprecated; provided for backwards compatibility + * denotify command is explicitly not supported. + * Status: deprecated + * + */ + +#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-enotify-common.h" + +/* + * Commands + */ + +static bool cmd_notify_registered + (struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg); +static bool cmd_notify_pre_validate + (struct sieve_validator *valdtr, struct sieve_command_context *cmd); +static bool cmd_notify_validate + (struct sieve_validator *valdtr, struct sieve_command_context *cmd); +static bool cmd_notify_generate + (const struct sieve_codegen_env *cgenv, + struct sieve_command_context *ctx); + +static bool cmd_denotify_pre_validate + (struct sieve_validator *valdtr, struct sieve_command_context *cmd); + +/* Notify command + * + * Syntax: + * notify [":method" string] [":id" string] + * [<":low" / ":normal" / ":high">] [":message" string] + */ + +static const struct sieve_command cmd_notify = { + "notify", + SCT_COMMAND, + 0, 0, FALSE, FALSE, + cmd_notify_registered, + cmd_notify_pre_validate, + cmd_notify_validate, + cmd_notify_generate, + NULL, +}; + +/* Denotify command (NOT IMPLEMENTED) + * + * Syntax: + * denotify [MATCH-TYPE string] [<":low" / ":normal" / ":high">] + */ +static const struct sieve_command cmd_denotify = { + "denotify", + SCT_COMMAND, + 0, 0, FALSE, FALSE, + NULL, + cmd_denotify_pre_validate, + NULL, NULL, NULL +}; + +/* + * Extension + */ + +static bool ext_notify_load(void); +static bool ext_notify_validator_load(struct sieve_validator *valdtr); + +static int ext_notify_my_id = -1; + +const struct sieve_extension notify_extension = { + "notify", + &ext_notify_my_id, + ext_notify_load, + NULL, + ext_notify_validator_load, + NULL, NULL, NULL, NULL, NULL, + SIEVE_EXT_DEFINE_NO_OPERATIONS, + SIEVE_EXT_DEFINE_NO_OPERANDS, +}; + +static bool ext_notify_load(void) +{ + /* Make sure real extension is registered, it is needed by the binary */ + (void)sieve_extension_require(&enotify_extension); + + return TRUE; +} + +/* + * Extension validation + */ + +static bool ext_notify_validator_extension_validate + (struct sieve_validator *valdtr, void *context, struct sieve_ast_argument *require_arg); + +const struct sieve_validator_extension notify_validator_extension = { + ¬ify_extension, + ext_notify_validator_extension_validate, + NULL +}; + +static bool ext_notify_validator_load(struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict with enotify */ + sieve_validator_extension_register + (valdtr, ¬ify_validator_extension, NULL); + + /* Register new commands */ + sieve_validator_register_command(valdtr, &cmd_notify); + sieve_validator_register_command(valdtr, &cmd_denotify); + + return TRUE; +} + +static bool ext_notify_validator_extension_validate +(struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg) +{ + /* Check for conflict with enotify */ + if ( sieve_validator_extension_loaded(valdtr, &enotify_extension) ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) notify extension cannot be used " + "together with the enotify extension"); + return FALSE; + } + + return TRUE; +} + +/* + * Denotify/Notify command tags + */ + +/* Forward declarations */ + +static bool cmd_notify_validate_string_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd); +static bool cmd_notify_validate_importance_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd); + +/* Argument objects */ + +static const struct sieve_argument notify_method_tag = { + "method", + NULL, NULL, + cmd_notify_validate_string_tag, + NULL, NULL +}; + +static const struct sieve_argument notify_id_tag = { + "id", + NULL, NULL, + cmd_notify_validate_string_tag, + NULL, NULL +}; + +static const struct sieve_argument notify_message_tag = { + "message", + NULL, NULL, + cmd_notify_validate_string_tag, + NULL, NULL +}; + +static const struct sieve_argument notify_low_tag = { + "low", + NULL, NULL, + cmd_notify_validate_importance_tag, + NULL, NULL +}; + +static const struct sieve_argument notify_normal_tag = { + "normal", + NULL, NULL, + cmd_notify_validate_importance_tag, + NULL, NULL +}; + +static const struct sieve_argument notify_high_tag = { + "high", + NULL, NULL, + cmd_notify_validate_importance_tag, + NULL, NULL +}; + +/* + * Command validation context + */ + +struct cmd_notify_context_data { + struct sieve_ast_argument *method; + struct sieve_ast_argument *message; +}; + +/* + * Tag validation + */ + +static bool cmd_notify_validate_string_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *) cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :id <string> + * :method <string> + * :message <string> + */ + if ( !sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, SAAT_STRING) ) + return FALSE; + + if ( tag->argument == ¬ify_method_tag ) { + ctx_data->method = *arg; + + /* Removed */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + } else if ( tag->argument == ¬ify_id_tag ) { + + /* Ignored */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + } else if ( tag->argument == ¬ify_message_tag ) { + ctx_data->message = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } + + return TRUE; +} + +static bool cmd_notify_validate_importance_tag +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd ATTR_UNUSED) +{ + struct sieve_ast_argument *tag = *arg; + + if ( tag->argument == ¬ify_low_tag ) + sieve_ast_argument_number_substitute(tag, 1); + else if ( tag->argument == ¬ify_normal_tag ) + sieve_ast_argument_number_substitute(tag, 2); + else + sieve_ast_argument_number_substitute(tag, 3); + + tag->argument = &number_argument; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_notify_registered +(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ¬ify_method_tag, 0); + sieve_validator_register_tag + (valdtr, cmd_reg, ¬ify_id_tag, 0); + sieve_validator_register_tag + (valdtr, cmd_reg, ¬ify_message_tag, CMD_NOTIFY_OPT_MESSAGE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ¬ify_low_tag, CMD_NOTIFY_OPT_IMPORTANCE); + sieve_validator_register_tag + (valdtr, cmd_reg, ¬ify_normal_tag, CMD_NOTIFY_OPT_IMPORTANCE); + sieve_validator_register_tag + (valdtr, cmd_reg, ¬ify_high_tag, CMD_NOTIFY_OPT_IMPORTANCE); + + return TRUE; +} + +/* + * Command validation + */ + +/* Notify */ + +static bool cmd_notify_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command_context *cmd) +{ + struct cmd_notify_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_notify_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static bool cmd_notify_validate +(struct sieve_validator *valdtr, struct sieve_command_context *cmd) +{ + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *) cmd->data; + + if ( ctx_data->method == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the notify command must have a ':method' argument " + "(the deprecated notify extension is not fully implemented)"); + return FALSE; + } + + if ( !sieve_ast_argument_attach(cmd->ast_node, ctx_data->method) ) { + /* Very unlikely */ + sieve_command_validate_error(valdtr, cmd, + "generate notify command; script is too complex"); + return FALSE; + } + + return ext_enotify_compile_check_arguments + (valdtr, ctx_data->method, ctx_data->message, NULL, NULL); +} + +/* Denotify */ + +static bool cmd_denotify_pre_validate +(struct sieve_validator *valdtr, struct sieve_command_context *cmd) +{ + sieve_command_validate_error(valdtr, cmd, + "the denotify command cannot be used " + "(the deprecated notify extension is not fully implemented)"); + return FALSE; +} + +/* + * Code generation + */ + +static bool cmd_notify_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) +{ + sieve_operation_emit_code(cgenv->sbin, ¬ify_operation); + + /* Emit source line */ + sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(ctx)); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, ctx, NULL); +} + diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c index bf3b99154..ce6b87b93 100644 --- a/src/lib-sieve/sieve-ast.c +++ b/src/lib-sieve/sieve-ast.c @@ -679,6 +679,12 @@ struct sieve_ast_argument *sieve_ast_arguments_detach return sieve_ast_arg_list_detach(first, count); } +bool sieve_ast_argument_attach +(struct sieve_ast_node *node, struct sieve_ast_argument *argument) +{ + return sieve_ast_node_add_argument(node, argument); +} + const char *sieve_ast_argument_type_name (enum sieve_ast_argument_type arg_type) { diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h index 77567a241..8682a900d 100644 --- a/src/lib-sieve/sieve-ast.h +++ b/src/lib-sieve/sieve-ast.h @@ -266,6 +266,8 @@ struct sieve_ast_argument *sieve_ast_argument_stringlist_substitute struct sieve_ast_argument *sieve_ast_arguments_detach (struct sieve_ast_argument *first, unsigned int count); +bool sieve_ast_argument_attach + (struct sieve_ast_node *node, struct sieve_ast_argument *argument); const char *sieve_ast_argument_type_name(enum sieve_ast_argument_type arg_type); #define sieve_ast_argument_name(argument) \ diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index cd737e916..bb3cfffc5 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -120,10 +120,12 @@ const unsigned int sieve_core_extensions_count = */ extern const struct sieve_extension imapflags_extension; +extern const struct sieve_extension notify_extension; const struct sieve_extension *sieve_deprecated_extensions[] = { /* Deprecated extensions */ - &imapflags_extension + &imapflags_extension, + ¬ify_extension }; const unsigned int sieve_deprecated_extensions_count = -- GitLab