Skip to content
Snippets Groups Projects
Commit 2c1540a5 authored by Stephan Bosch's avatar Stephan Bosch
Browse files

lib-sieve: Implemented the vnd.dovecot.environment extension.

This adds the vnd.dovecot.default-mailbox and vnd.dovecot.username environment items.
It creates the 'env' variables namespace through which all environment items can be accessed directly.
This extension is yet to be documented properly.
More environment items are under consideration.
parent 30509319
No related branches found
No related tags found
No related merge requests found
......@@ -162,6 +162,8 @@ test_cases = \
tests/extensions/metadata/execute.svtest \
tests/extensions/metadata/errors.svtest \
tests/extensions/vnd.dovecot/debug/execute.svtest \
tests/extensions/vnd.dovecot/environment/basic.svtest \
tests/extensions/vnd.dovecot/environment/variables.svtest \
tests/deprecated/notify/basic.svtest \
tests/deprecated/notify/mailto.svtest \
tests/deprecated/notify/errors.svtest \
......
......@@ -211,6 +211,7 @@ src/lib-sieve/plugins/duplicate/Makefile
src/lib-sieve/plugins/index/Makefile
src/lib-sieve/plugins/vnd.dovecot/Makefile
src/lib-sieve/plugins/vnd.dovecot/debug/Makefile
src/lib-sieve/plugins/vnd.dovecot/environment/Makefile
src/lib-sieve-tool/Makefile
src/lib-managesieve/Makefile
src/plugins/Makefile
......
......@@ -78,6 +78,7 @@ plugins = \
$(extdir)/index/libsieve_ext_index.la \
$(extdir)/metadata/libsieve_ext_metadata.la \
$(extdir)/vnd.dovecot/debug/libsieve_ext_debug.la \
$(extdir)/vnd.dovecot/environment/libsieve_ext_vnd_environment.la \
$(unfinished_plugins)
libdovecot_sieve_la_DEPENDENCIES = \
......
......@@ -6,14 +6,10 @@
#include "sieve-common.h"
#include "sieve-extensions.h"
#include "sieve-interpreter.h"
#include "ext-environment-common.h"
struct ext_environment_context {
HASH_TABLE(const char *,
const struct sieve_environment_item *) environment_items;
};
/*
* Core environment items
*/
......@@ -30,71 +26,121 @@ static const struct sieve_environment_item *core_env_items[] = {
static unsigned int core_env_items_count = N_ELEMENTS(core_env_items);
/*
* Registration
* Validator context
*/
static void ext_environment_item_register
(struct ext_environment_context *ectx,
const struct sieve_environment_item *item)
struct ext_environment_interpreter_context {
HASH_TABLE(const char *,
const struct sieve_environment_item *) environment_items;
unsigned int active:1;
};
static void ext_environment_interpreter_extension_free
(const struct sieve_extension *ext, struct sieve_interpreter *interp,
void *context);
struct sieve_interpreter_extension environment_interpreter_extension = {
.ext_def = &environment_extension,
.free = ext_environment_interpreter_extension_free,
};
static struct ext_environment_interpreter_context *
ext_environment_interpreter_context_create
(const struct sieve_extension *this_ext, struct sieve_interpreter *interp)
{
hash_table_insert(ectx->environment_items, item->name, item);
pool_t pool = sieve_interpreter_pool(interp);
struct ext_environment_interpreter_context *ctx;
ctx = p_new(pool, struct ext_environment_interpreter_context, 1);
hash_table_create
(&ctx->environment_items, default_pool, 0, str_hash, strcmp);
sieve_interpreter_extension_register
(interp, this_ext, &environment_interpreter_extension, (void *)ctx);
return ctx;
}
void sieve_ext_environment_item_register
(const struct sieve_extension *ext, const struct sieve_environment_item *item)
static void ext_environment_interpreter_extension_free
(const struct sieve_extension *ext ATTR_UNUSED,
struct sieve_interpreter *interp ATTR_UNUSED, void *context)
{
struct ext_environment_context *ectx =
(struct ext_environment_context *) ext->context;
struct ext_environment_interpreter_context *ctx =
(struct ext_environment_interpreter_context *)context;
ext_environment_item_register(ectx, item);
hash_table_destroy(&ctx->environment_items);
}
/*
* Initialization
*/
bool ext_environment_init
(const struct sieve_extension *ext ATTR_UNUSED, void **context)
static struct ext_environment_interpreter_context *
ext_environment_interpreter_context_get
(const struct sieve_extension *this_ext, struct sieve_interpreter *interp)
{
struct ext_environment_context *ectx =
i_new(struct ext_environment_context, 1);
struct ext_environment_interpreter_context *ctx =
(struct ext_environment_interpreter_context *)
sieve_interpreter_extension_get_context(interp, this_ext);
if ( ctx == NULL )
ctx = ext_environment_interpreter_context_create(this_ext, interp);
return ctx;
}
void ext_environment_interpreter_init
(const struct sieve_extension *this_ext, struct sieve_interpreter *interp)
{
struct ext_environment_interpreter_context *ctx;
unsigned int i;
hash_table_create
(&ectx->environment_items, default_pool, 0, str_hash, strcmp);
/* Create our context */
ctx = ext_environment_interpreter_context_get(this_ext, interp);
for ( i = 0; i < core_env_items_count; i++ ) {
ext_environment_item_register(ectx, core_env_items[i]);
const struct sieve_environment_item *item = core_env_items[i];
hash_table_insert(ctx->environment_items, item->name, item);
}
*context = (void *) ectx;
return TRUE;
ctx->active = TRUE;
}
void ext_environment_deinit(const struct sieve_extension *ext)
bool sieve_ext_environment_is_active
(const struct sieve_extension *env_ext, struct sieve_interpreter *interp)
{
struct ext_environment_context *ectx =
(struct ext_environment_context *) ext->context;
struct ext_environment_interpreter_context *ctx =
ext_environment_interpreter_context_get(env_ext, interp);
hash_table_destroy(&ectx->environment_items);
i_free(ectx);
return ( ctx != NULL && ctx->active );
}
/*
* Registration
*/
void sieve_environment_item_register
(const struct sieve_extension *env_ext, struct sieve_interpreter *interp,
const struct sieve_environment_item *item)
{
struct ext_environment_interpreter_context *ctx;
i_assert( sieve_extension_is(env_ext, environment_extension) );
ctx = ext_environment_interpreter_context_get(env_ext, interp);
hash_table_insert(ctx->environment_items, item->name, item);
}
/*
* Retrieval
*/
const char *ext_environment_item_get_value
(const struct sieve_extension *ext, const char *name,
const struct sieve_script_env *senv)
(const struct sieve_extension *env_ext,
const struct sieve_runtime_env *renv, const char *name)
{
struct ext_environment_context *ectx =
(struct ext_environment_context *) ext->context;
struct ext_environment_interpreter_context *ctx =
ext_environment_interpreter_context_get(env_ext, renv->interp);
const struct sieve_environment_item *item =
hash_table_lookup(ectx->environment_items, name);
hash_table_lookup(ctx->environment_items, name);
i_assert( sieve_extension_is(env_ext, environment_extension) );
if ( item == NULL )
return NULL;
......@@ -103,7 +149,7 @@ const char *ext_environment_item_get_value
return item->value;
if ( item->get_value != NULL )
return item->get_value(ext->svinst, senv);
return item->get_value(renv);
return NULL;
}
......@@ -119,10 +165,9 @@ const char *ext_environment_item_get_value
*/
static const char *envit_domain_get_value
(struct sieve_instance *svinst,
const struct sieve_script_env *senv ATTR_UNUSED)
(const struct sieve_runtime_env *renv)
{
return svinst->domainname;
return renv->svinst->domainname;
}
const struct sieve_environment_item domain_env_item = {
......@@ -137,10 +182,9 @@ const struct sieve_environment_item domain_env_item = {
*/
static const char *envit_host_get_value
(struct sieve_instance *svinst,
const struct sieve_script_env *senv ATTR_UNUSED)
(const struct sieve_runtime_env *renv)
{
return svinst->hostname;
return renv->svinst->hostname;
}
const struct sieve_environment_item host_env_item = {
......@@ -160,10 +204,9 @@ const struct sieve_environment_item host_env_item = {
*/
static const char *envit_location_get_value
(struct sieve_instance *svinst,
const struct sieve_script_env *senv ATTR_UNUSED)
(const struct sieve_runtime_env *renv)
{
switch ( svinst->env_location ) {
switch ( renv->svinst->env_location ) {
case SIEVE_ENV_LOCATION_MDA:
return "MDA";
case SIEVE_ENV_LOCATION_MTA:
......@@ -190,10 +233,9 @@ const struct sieve_environment_item location_env_item = {
*/
static const char *envit_phase_get_value
(struct sieve_instance *svinst,
const struct sieve_script_env *senv ATTR_UNUSED)
(const struct sieve_runtime_env *renv)
{
switch ( svinst->delivery_phase ) {
switch ( renv->svinst->delivery_phase ) {
case SIEVE_DELIVERY_PHASE_PRE:
return "pre";
case SIEVE_DELIVERY_PHASE_DURING:
......
......@@ -47,11 +47,10 @@ bool ext_environment_init(const struct sieve_extension *ext, void **context);
void ext_environment_deinit(const struct sieve_extension *ext);
/*
* Environment item retrieval
* Validator context
*/
const char *ext_environment_item_get_value
(const struct sieve_extension *ext, const char *name,
const struct sieve_script_env *senv);
void ext_environment_interpreter_init
(const struct sieve_extension *this_ext, struct sieve_interpreter *interp);
#endif /* __EXT_VARIABLES_COMMON_H */
......@@ -30,12 +30,14 @@
static bool ext_environment_validator_load
(const struct sieve_extension *ext, struct sieve_validator *valdtr);
static bool ext_environment_interpreter_load
(const struct sieve_extension *ext,
const struct sieve_runtime_env *renv, sieve_size_t *address);
const struct sieve_extension_def environment_extension = {
.name = "environment",
.load = ext_environment_init,
.unload = ext_environment_deinit,
.validator_load = ext_environment_validator_load,
.interpreter_load = ext_environment_interpreter_load,
SIEVE_EXT_DEFINE_OPERATION(tst_environment_operation)
};
......@@ -43,7 +45,15 @@ static bool ext_environment_validator_load
(const struct sieve_extension *ext, struct sieve_validator *valdtr)
{
sieve_validator_register_command(valdtr, ext, &tst_environment);
return TRUE;
}
static bool ext_environment_interpreter_load
(const struct sieve_extension *ext,
const struct sieve_runtime_env *renv,
sieve_size_t *address ATTR_UNUSED)
{
ext_environment_interpreter_init(ext, renv->interp);
return TRUE;
}
......@@ -6,16 +6,43 @@
#include "sieve-common.h"
/*
* Environment extension
*/
/* FIXME: this is not suitable for future plugin support */
extern const struct sieve_extension_def environment_extension;
static inline const struct sieve_extension *
sieve_ext_environment_get_extension
(struct sieve_instance *svinst)
{
return sieve_extension_register
(svinst, &environment_extension, FALSE);
}
bool sieve_ext_environment_is_active
(const struct sieve_extension *env_ext,
struct sieve_interpreter *interp);
/*
* Environment item
*/
struct sieve_environment_item {
const char *name;
const char *value;
const char *(*get_value)
(struct sieve_instance *svinst, const struct sieve_script_env *senv);
(const struct sieve_runtime_env *renv);
};
void sieve_ext_environment_item_register
(const struct sieve_extension *ext,
void sieve_environment_item_register
(const struct sieve_extension *env_ext, struct sieve_interpreter *interp,
const struct sieve_environment_item *item);
const char *ext_environment_item_get_value
(const struct sieve_extension *env_ext,
const struct sieve_runtime_env *renv, const char *name);
#endif
......@@ -188,7 +188,7 @@ static int tst_environment_operation_execute
sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "environment test");
env_item = ext_environment_item_get_value
(this_ext, str_c(name), renv->scriptenv);
(this_ext, renv, str_c(name));
if ( env_item != NULL ) {
/* Construct value list */
......
SUBDIRS = debug
SUBDIRS = debug environment
......@@ -139,6 +139,7 @@ extern const struct sieve_extension_def virustest_extension;
extern const struct sieve_extension_def editheader_extension;
extern const struct sieve_extension_def vnd_debug_extension;
extern const struct sieve_extension_def vnd_environment_extension;
const struct sieve_extension_def *sieve_extra_extensions[] = {
&vacation_seconds_extension, &spamtest_extension, &spamtestplus_extension,
......@@ -146,7 +147,7 @@ const struct sieve_extension_def *sieve_extra_extensions[] = {
&mboxmetadata_extension, &servermetadata_extension,
/* vnd.dovecot. */
&vnd_debug_extension
&vnd_debug_extension, &vnd_environment_extension
};
const unsigned int sieve_extra_extensions_count =
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.