Skip to content

Commit

Permalink
lib-sieve: Added support for evaluating extension availability (ihave…
Browse files Browse the repository at this point in the history
… test) at runtime.
  • Loading branch information
stephanbosch committed Mar 27, 2016
1 parent 222c5af commit 4dce44b
Show file tree
Hide file tree
Showing 18 changed files with 314 additions and 83 deletions.
18 changes: 10 additions & 8 deletions src/lib-sieve/plugins/date/ext-date-common.c
Expand Up @@ -27,9 +27,10 @@ struct ext_date_context {
* Runtime initialization
*/

static void ext_date_runtime_init
(const struct sieve_extension *ext, const struct sieve_runtime_env *renv,
void *context ATTR_UNUSED)
static int ext_date_runtime_init
(const struct sieve_extension *ext,
const struct sieve_runtime_env *renv,
void *context ATTR_UNUSED, bool deferred ATTR_UNUSED)
{
struct ext_date_context *dctx;
pool_t pool;
Expand All @@ -53,12 +54,13 @@ static void ext_date_runtime_init

sieve_message_context_extension_set
(renv->msgctx, ext, (void *) dctx);
return SIEVE_EXEC_OK;
}

static struct sieve_interpreter_extension date_interpreter_extension = {
&date_extension,
ext_date_runtime_init,
NULL,
static struct sieve_interpreter_extension
date_interpreter_extension = {
.ext_def = &date_extension,
.run = ext_date_runtime_init
};

bool ext_date_interpreter_load
Expand Down Expand Up @@ -116,7 +118,7 @@ time_t ext_date_get_current_date
sieve_message_context_extension_get(renv->msgctx, this_ext);

if ( dctx == NULL ) {
ext_date_runtime_init(this_ext, renv, NULL);
ext_date_runtime_init(this_ext, renv, NULL, FALSE);
dctx = (struct ext_date_context *)
sieve_message_context_extension_get(renv->msgctx, this_ext);

Expand Down
5 changes: 3 additions & 2 deletions src/lib-sieve/plugins/ihave/cmd-error.c
Expand Up @@ -48,9 +48,10 @@ static bool cmd_error_operation_dump
static int cmd_error_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address);

const struct sieve_operation_def error_operation = {
const struct sieve_operation_def cmd_error_operation = {
.mnemonic = "ERROR",
.ext_def = &ihave_extension,
.code = EXT_IHAVE_OPERATION_ERROR,
.dump = cmd_error_operation_dump,
.execute = cmd_error_operation_execute
};
Expand Down Expand Up @@ -79,7 +80,7 @@ static bool cmd_error_validate
static bool cmd_error_generate
(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd)
{
(void)sieve_operation_emit(cgenv->sblock, cmd->ext, &error_operation);
(void)sieve_operation_emit(cgenv->sblock, cmd->ext, &cmd_error_operation);

/* Generate arguments */
return sieve_generate_arguments(cgenv, cmd, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/lib-sieve/plugins/ihave/ext-ihave-common.h
Expand Up @@ -28,7 +28,13 @@ extern const struct sieve_command_def error_command;
* Operations
*/

extern const struct sieve_operation_def error_operation;
enum ext_ihave_opcode {
EXT_IHAVE_OPERATION_IHAVE,
EXT_IHAVE_OPERATION_ERROR
};

extern const struct sieve_operation_def tst_ihave_operation;
extern const struct sieve_operation_def cmd_error_operation;

/*
* AST context
Expand Down
12 changes: 11 additions & 1 deletion src/lib-sieve/plugins/ihave/ext-ihave.c
Expand Up @@ -23,6 +23,15 @@
#include "ext-ihave-common.h"
#include "ext-ihave-binary.h"

/*
* Operations
*/

const struct sieve_operation_def *ext_ihave_operations[] = {
&tst_ihave_operation,
&cmd_error_operation
};

/*
* Extension
*/
Expand All @@ -34,11 +43,12 @@ static bool ext_ihave_generator_load

const struct sieve_extension_def ihave_extension = {
"ihave",
.version = 1,
.validator_load = ext_ihave_validator_load,
.generator_load = ext_ihave_generator_load,
.binary_load = ext_ihave_binary_load,
.binary_dump = ext_ihave_binary_dump,
SIEVE_EXT_DEFINE_OPERATION(error_operation)
SIEVE_EXT_DEFINE_OPERATIONS(ext_ihave_operations)
};

static bool ext_ihave_validator_load
Expand Down
128 changes: 126 additions & 2 deletions src/lib-sieve/plugins/ihave/tst-ihave.c
Expand Up @@ -5,10 +5,13 @@
#include "array.h"

#include "sieve-common.h"
#include "sieve-stringlist.h"
#include "sieve-extensions.h"
#include "sieve-code.h"
#include "sieve-commands.h"
#include "sieve-validator.h"
#include "sieve-generator.h"
#include "sieve-interpreter.h"

#include "ext-ihave-common.h"

Expand All @@ -24,6 +27,8 @@ static bool tst_ihave_validate
static bool tst_ihave_validate_const
(struct sieve_validator *valdtr, struct sieve_command *tst,
int *const_current, int const_next);
static bool tst_ihave_generate
(const struct sieve_codegen_env *cgenv, struct sieve_command *tst);

const struct sieve_command_def ihave_test = {
.identifier = "ihave",
Expand All @@ -33,7 +38,25 @@ const struct sieve_command_def ihave_test = {
.block_allowed = FALSE,
.block_required = FALSE,
.validate = tst_ihave_validate,
.validate_const = tst_ihave_validate_const
.validate_const = tst_ihave_validate_const,
.generate = tst_ihave_generate
};

/*
* Ihave operation
*/

static bool tst_ihave_operation_dump
(const struct sieve_dumptime_env *denv, sieve_size_t *address);
static int tst_ihave_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address);

const struct sieve_operation_def tst_ihave_operation = {
.mnemonic = "IHAVE",
.ext_def = &ihave_extension,
.code = EXT_IHAVE_OPERATION_IHAVE,
.dump = tst_ihave_operation_dump,
.execute = tst_ihave_operation_execute
};

/*
Expand Down Expand Up @@ -143,6 +166,10 @@ static bool tst_ihave_validate
return FALSE;
}

if ( !sieve_validator_argument_activate
(valdtr, tst, arg, FALSE) )
return FALSE;

tst->data = (void *) TRUE;
return TRUE;
}
Expand All @@ -152,8 +179,105 @@ static bool tst_ihave_validate_const
int *const_current, int const_next ATTR_UNUSED)
{
if ( (bool)tst->data == TRUE )
*const_current = 1;
*const_current = -1;
else
*const_current = 0;
return TRUE;
}

/*
* Code generation
*/

bool tst_ihave_generate
(const struct sieve_codegen_env *cgenv, struct sieve_command *tst)
{
/* Emit opcode */
sieve_operation_emit(cgenv->sblock,
tst->ext, &tst_ihave_operation);

/* Generate arguments */
return sieve_generate_arguments(cgenv, tst, NULL);
}

/*
* Code dump
*/

static bool tst_ihave_operation_dump
(const struct sieve_dumptime_env *denv, sieve_size_t *address)
{
sieve_code_dumpf(denv, "IHAVE");
sieve_code_descend(denv);

return sieve_opr_stringlist_dump
(denv, address, "capabilities");
}

/*
* Code execution
*/

static int tst_ihave_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
struct sieve_instance *svinst = renv->svinst;
struct sieve_stringlist *capabilities;
string_t *cap_item;
bool matched;
int ret;

/*
* Read operands
*/

/* Read capabilities */
if ( (ret=sieve_opr_stringlist_read
(renv, address, "capabilities", &capabilities)) <= 0 )
return ret;

/*
* Perform test
*/

/* Perform the test */
sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "ihave test");
sieve_runtime_trace_descend(renv);

cap_item = NULL;
matched = TRUE;
while ( matched &&
(ret=sieve_stringlist_next_item(capabilities, &cap_item)) > 0 ) {
const struct sieve_extension *ext;
int sret;

ext = sieve_extension_get_by_name(svinst, str_c(cap_item));
if (ext == NULL) {
sieve_runtime_trace_error(renv,
"ihave: invalid extension name");
return SIEVE_EXEC_BIN_CORRUPT;
}
sret = sieve_interpreter_extension_start(renv->interp, ext);
if ( sret == SIEVE_EXEC_FAILURE ) {
sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
"extension `%s' not available",
sieve_extension_name(ext));
matched = FALSE;
} else if ( sret == SIEVE_EXEC_OK ) {
sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS,
"extension `%s' available",
sieve_extension_name(ext));
} else {
return sret;
}
}
if ( ret < 0 ) {
sieve_runtime_trace_error(renv,
"invalid capabilities item");
return SIEVE_EXEC_BIN_CORRUPT;
}

/* Set test result for subsequent conditional jump */
sieve_interpreter_set_test_result(renv->interp, matched);
return SIEVE_EXEC_OK;
}
16 changes: 9 additions & 7 deletions src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c
Expand Up @@ -242,18 +242,20 @@ static string_t *_get_flags_string
* Runtime initialization
*/

static void ext_imap4flags_runtime_init
(const struct sieve_extension *ext, const struct sieve_runtime_env *renv,
void *context ATTR_UNUSED)
static int ext_imap4flags_runtime_init
(const struct sieve_extension *ext,
const struct sieve_runtime_env *renv,
void *context ATTR_UNUSED, bool deferred ATTR_UNUSED)
{
sieve_result_add_implicit_side_effect
(renv->result, NULL, TRUE, ext, &flags_side_effect, NULL);
return SIEVE_EXEC_OK;
}

const struct sieve_interpreter_extension imap4flags_interpreter_extension = {
&imap4flags_extension,
ext_imap4flags_runtime_init,
NULL,
const struct sieve_interpreter_extension
imap4flags_interpreter_extension = {
.ext_def = &imap4flags_extension,
.run = ext_imap4flags_runtime_init
};

/*
Expand Down
15 changes: 7 additions & 8 deletions src/lib-sieve/plugins/include/ext-include-common.c
Expand Up @@ -327,20 +327,19 @@ void ext_include_register_generator_context
* Runtime initialization
*/

static void ext_include_runtime_init
(const struct sieve_extension *this_ext, const struct sieve_runtime_env *renv,
void *context)
static int ext_include_runtime_init
(const struct sieve_extension *this_ext,
const struct sieve_runtime_env *renv,
void *context, bool deferred ATTR_UNUSED)
{
struct ext_include_interpreter_context *ctx =
(struct ext_include_interpreter_context *) context;
struct ext_include_context *ectx = ext_include_get_context(this_ext);


if ( ctx->parent == NULL ) {
ctx->global = p_new(ctx->pool, struct ext_include_interpreter_global, 1);
p_array_init(&ctx->global->included_scripts, ctx->pool, 10);


ctx->global->var_scope =
ext_include_binary_get_global_scope(this_ext, renv->sbin);
ctx->global->var_storage =
Expand All @@ -351,12 +350,12 @@ static void ext_include_runtime_init

sieve_ext_variables_runtime_set_storage
(ectx->var_ext, renv, this_ext, ctx->global->var_storage);
return SIEVE_EXEC_OK;
}

static struct sieve_interpreter_extension include_interpreter_extension = {
&include_extension,
ext_include_runtime_init,
NULL,
.ext_def = &include_extension,
.run = ext_include_runtime_init
};

/*
Expand Down
8 changes: 4 additions & 4 deletions src/lib-sieve/plugins/variables/ext-variables-common.c
Expand Up @@ -717,10 +717,10 @@ static void ext_variables_interpreter_free
sieve_variable_scope_binary_unref(&ctx->local_scope_bin);
}

static struct sieve_interpreter_extension variables_interpreter_extension = {
&variables_extension,
NULL,
ext_variables_interpreter_free
static struct sieve_interpreter_extension
variables_interpreter_extension = {
.ext_def = &variables_extension,
.free = ext_variables_interpreter_free
};

static struct ext_variables_interpreter_context *
Expand Down

0 comments on commit 4dce44b

Please sign in to comment.