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

lib-sieve: vnd.dovecot.duplicate extension: Only track duplicate when Sieve...

lib-sieve: vnd.dovecot.duplicate extension: Only track duplicate when Sieve script executes successfully.
parent 7dc1be65
No related branches found
No related tags found
No related merge requests found
......@@ -5,6 +5,7 @@
#include "md5.h"
#include "ioloop.h"
#include "str.h"
#include "str-sanitize.h"
#include "array.h"
#include "sieve-common.h"
......@@ -15,6 +16,7 @@
#include "sieve-code.h"
#include "sieve-runtime.h"
#include "sieve-actions.h"
#include "sieve-result.h"
#include "ext-duplicate-common.h"
......@@ -61,6 +63,67 @@ void ext_duplicate_unload
i_free(config);
}
/*
* Duplicate_mark action
*/
struct act_duplicate_mark_data {
const char *handle;
unsigned int period;
unsigned char hash[MD5_RESULTLEN];
};
static void act_duplicate_mark_print
(const struct sieve_action *action,
const struct sieve_result_print_env *rpenv, bool *keep);
static bool act_duplicate_mark_commit
(const struct sieve_action *action,
const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep);
static const struct sieve_action_def act_duplicate_mark = {
"duplicate_mark",
0,
NULL, NULL, NULL,
act_duplicate_mark_print,
NULL, NULL,
act_duplicate_mark_commit,
NULL
};
static void act_duplicate_mark_print
(const struct sieve_action *action,
const struct sieve_result_print_env *rpenv, bool *keep ATTR_UNUSED)
{
struct act_duplicate_mark_data *data =
(struct act_duplicate_mark_data *) action->context;
if (data->handle != NULL) {
sieve_result_action_printf(rpenv, "track duplicate with handle: %s",
str_sanitize(data->handle, 128));
} else {
sieve_result_action_printf(rpenv, "track duplicate");
}
}
static bool act_duplicate_mark_commit
(const struct sieve_action *action,
const struct sieve_action_exec_env *aenv,
void *tr_context ATTR_UNUSED, bool *keep ATTR_UNUSED)
{
const struct sieve_script_env *senv = aenv->scriptenv;
struct act_duplicate_mark_data *data =
(struct act_duplicate_mark_data *) action->context;
/* Message was handled successfully until now, so track duplicate for this
* message.
*/
sieve_action_duplicate_mark
(senv, data->hash, sizeof(data->hash), ioloop_time + data->period);
return TRUE;
}
/*
* Duplicate checking
*/
......@@ -77,7 +140,7 @@ struct ext_duplicate_context {
unsigned int nohandle_checked:1;
};
bool ext_duplicate_check
int ext_duplicate_check
(const struct sieve_runtime_env *renv, string_t *handle,
const char *value, size_t value_len, sieve_number_t period)
{
......@@ -85,13 +148,13 @@ bool ext_duplicate_check
const struct sieve_script_env *senv = renv->scriptenv;
struct ext_duplicate_context *rctx;
bool duplicate = FALSE;
pool_t pool = NULL;
pool_t msg_pool = NULL, result_pool = NULL;
static const char *id = "sieve duplicate";
unsigned char dupl_hash[MD5_RESULTLEN];
struct act_duplicate_mark_data *act;
struct md5_context ctx;
if ( !sieve_action_duplicate_check_available(senv) || value == NULL )
return FALSE;
return 0;
/* Get context; find out whether duplicate was checked earlier */
rctx = (struct ext_duplicate_context *)
......@@ -99,24 +162,30 @@ bool ext_duplicate_check
if ( rctx == NULL ) {
/* Create context */
pool = sieve_message_context_pool(renv->msgctx);
rctx = p_new(pool, struct ext_duplicate_context, 1);
msg_pool = sieve_message_context_pool(renv->msgctx);
rctx = p_new(msg_pool, struct ext_duplicate_context, 1);
sieve_message_context_extension_set(renv->msgctx, this_ext, (void *)rctx);
} else {
if ( handle == NULL ) {
if ( rctx->nohandle_checked ) {
/* Already checked for duplicate */
return rctx->nohandle_duplicate;
return ( rctx->nohandle_duplicate ? 1 : 0 );
}
} else if ( array_is_created(&rctx->handles) ) {
const struct ext_duplicate_handle *record;
array_foreach (&rctx->handles, record) {
if ( strcmp(record->handle, str_c(handle)) == 0 )
return record->duplicate;
return ( record->duplicate ? 1 : 0 );
}
}
}
result_pool = sieve_result_pool(renv->result);
act = p_new(result_pool, struct act_duplicate_mark_data, 1);
if (handle != NULL)
act->handle = p_strdup(result_pool, str_c(handle));
act->period = period;
/* Create hash */
md5_init(&ctx);
md5_update(&ctx, id, strlen(id));
......@@ -127,31 +196,35 @@ bool ext_duplicate_check
md5_update(&ctx, "default", 7);
}
md5_update(&ctx, value, value_len);
md5_final(&ctx, dupl_hash);
md5_final(&ctx, act->hash);
/* Check duplicate */
duplicate = sieve_action_duplicate_check
(senv, dupl_hash, sizeof(dupl_hash));
duplicate = sieve_action_duplicate_check(senv, act->hash, sizeof(act->hash));
/* Create/refresh entry */
sieve_action_duplicate_mark
(senv, dupl_hash, sizeof(dupl_hash), ioloop_time + period);
/* We may only mark the message as duplicate when Sieve script executes
* successfully; therefore defer this operation until successful result
* execution.
*/
if ( sieve_result_add_action
(renv, NULL, &act_duplicate_mark, NULL, (void *) act, 0, FALSE) < 0 )
return -1;
/* Cache result */
if ( handle == NULL ) {
rctx->nohandle_duplicate = duplicate;
rctx->nohandle_checked = TRUE;
} else {
struct ext_duplicate_handle *record;
if ( pool == NULL )
pool = sieve_message_context_pool(renv->msgctx);
if ( msg_pool == NULL )
msg_pool = sieve_message_context_pool(renv->msgctx);
if ( !array_is_created(&rctx->handles) )
p_array_init(&rctx->handles, pool, 64);
p_array_init(&rctx->handles, msg_pool, 64);
record = array_append_space(&rctx->handles);
record->handle = p_strdup(pool, str_c(handle));
record->handle = p_strdup(msg_pool, str_c(handle));
record->duplicate = duplicate;
}
return duplicate;
return ( duplicate ? 1 : 0 );
}
......@@ -38,7 +38,7 @@ extern const struct sieve_operation_def tst_duplicate_operation;
* Duplicate checking
*/
bool ext_duplicate_check
int ext_duplicate_check
(const struct sieve_runtime_env *renv, string_t *handle,
const char *value, size_t value_len, sieve_number_t period);
......
......@@ -343,7 +343,9 @@ static int tst_duplicate_operation_execute
if (val == NULL) {
duplicate = FALSE;
} else {
duplicate = ext_duplicate_check(renv, handle, val, val_len, seconds);
if ((ret=ext_duplicate_check(renv, handle, val, val_len, seconds)) < 0)
return SIEVE_EXEC_FAILURE;
duplicate = ( ret > 0 );
}
/* Trace */
......
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.