diff --git a/src/lib-sieve/sieve-message.c b/src/lib-sieve/sieve-message.c index bc623222f3c7a893f63e0fa84410c55a9c6f7872..810c9c74f00df6e48fbbed551fcae01321cf2296 100644 --- a/src/lib-sieve/sieve-message.c +++ b/src/lib-sieve/sieve-message.c @@ -20,16 +20,13 @@ struct sieve_message_context { struct sieve_message_context *sieve_message_context_create(void) { - pool_t pool; struct sieve_message_context *msgctx; - pool = pool_alloconly_create("sieve_message_context", 1024); - msgctx = p_new(pool, struct sieve_message_context, 1); - msgctx->pool = pool; + msgctx = i_new(struct sieve_message_context, 1); msgctx->refcount = 1; - - p_array_init(&msgctx->ext_contexts, pool, 4); - + + sieve_message_context_flush(msgctx); + return msgctx; } @@ -46,10 +43,25 @@ void sieve_message_context_unref(struct sieve_message_context **msgctx) return; pool_unref(&((*msgctx)->pool)); - + + i_free(*msgctx); *msgctx = NULL; } +void sieve_message_context_flush(struct sieve_message_context *msgctx) +{ + pool_t pool; + + if ( msgctx->pool != NULL ) { + pool_unref(&msgctx->pool); + } + + pool = pool_alloconly_create("sieve_message_context", 1024); + msgctx->pool = pool; + + p_array_init(&msgctx->ext_contexts, pool, sieve_extensions_get_count()); +} + void sieve_message_context_extension_set (struct sieve_message_context *msgctx, const struct sieve_extension *ext, void *context) diff --git a/src/lib-sieve/sieve-message.h b/src/lib-sieve/sieve-message.h index 4e6e848bf56c1476de21ab4a0ab702fd27c6d934..dff96e8d058738eafc0ac36a9449deb65eccd97c 100644 --- a/src/lib-sieve/sieve-message.h +++ b/src/lib-sieve/sieve-message.h @@ -9,6 +9,8 @@ struct sieve_message_context *sieve_message_context_create(void); void sieve_message_context_ref(struct sieve_message_context *msgctx); void sieve_message_context_unref(struct sieve_message_context **msgctx); +void sieve_message_context_flush(struct sieve_message_context *msgctx); + void sieve_message_context_extension_set (struct sieve_message_context *msgctx, const struct sieve_extension *ext, void *context); diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c index a6abbcb8d10315b584cc4c510dcc347055c9ef09..63c8f96353374523c94fce0694348f34d724a60f 100644 --- a/src/testsuite/cmd-test-set.c +++ b/src/testsuite/cmd-test-set.c @@ -149,7 +149,7 @@ static int cmd_test_set_operation_execute return SIEVE_EXEC_FAILURE; } - object->set_member(member_id, value); + object->set_member(renv, member_id, value); return SIEVE_EXEC_OK; } diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c index 297ebf6e5c5df7fb4b608cf2506a8dbc22be295e..bd1331944aa8bf87c329833823eaf1a131ea555f 100644 --- a/src/testsuite/testsuite-common.c +++ b/src/testsuite/testsuite-common.c @@ -11,10 +11,12 @@ #include "sieve.h" #include "sieve-error-private.h" #include "sieve-code.h" +#include "sieve-message.h" #include "sieve-commands.h" #include "sieve-extensions.h" #include "sieve-validator.h" #include "sieve-generator.h" +#include "sieve-interpreter.h" #include "sieve-dump.h" #include "testsuite-objects.h" @@ -114,11 +116,14 @@ void testsuite_message_init(pool_t namespaces_pool, const char *user) envelope_auth = str_new(message_pool, 256); } -void testsuite_message_set(string_t *message) +void testsuite_message_set +(const struct sieve_runtime_env *renv, string_t *message) { mail_raw_close(_raw_message); _testsuite_message_set(message); + + sieve_message_context_flush(renv->msgctx); } void testsuite_message_deinit(void) diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h index 5385b26c894c484e2ff42cb1c4dc05ac4a207fdd..8bf37ab4752126bb325401ddc066ef86491e3aba 100644 --- a/src/testsuite/testsuite-common.h +++ b/src/testsuite/testsuite-common.h @@ -12,7 +12,8 @@ extern struct sieve_message_data testsuite_msgdata; void testsuite_message_init(pool_t namespaces_pool, const char *user); void testsuite_message_deinit(void); -void testsuite_message_set(string_t *message); +void testsuite_message_set + (const struct sieve_runtime_env *renv, string_t *message); void testsuite_envelope_set_sender(const char *value); void testsuite_envelope_set_recipient(const char *value); diff --git a/src/testsuite/testsuite-objects.c b/src/testsuite/testsuite-objects.c index 88142303a63e63c432f3e053887d34fd4b90d863..4e002603fec2cf02e782d8de765e4371d6668bbb 100644 --- a/src/testsuite/testsuite-objects.c +++ b/src/testsuite/testsuite-objects.c @@ -249,11 +249,13 @@ static bool arg_testsuite_object_generate * Testsuite core object implementation */ -static bool tsto_message_set_member(int id, string_t *value); +static bool tsto_message_set_member + (const struct sieve_runtime_env *renv, int id, string_t *value); static int tsto_envelope_get_member_id(const char *identifier); static const char *tsto_envelope_get_member_name(int id); -static bool tsto_envelope_set_member(int id, string_t *value); +static bool tsto_envelope_set_member + (const struct sieve_runtime_env *renv, int id, string_t *value); const struct testsuite_object message_testsuite_object = { SIEVE_OBJECT("message", &testsuite_object_operand, TESTSUITE_OBJECT_MESSAGE), @@ -276,11 +278,12 @@ enum testsuite_object_envelope_field { TESTSUITE_OBJECT_ENVELOPE_AUTH_USER }; -static bool tsto_message_set_member(int id, string_t *value) +static bool tsto_message_set_member +(const struct sieve_runtime_env *renv, int id, string_t *value) { if ( id != -1 ) return FALSE; - testsuite_message_set(value); + testsuite_message_set(renv, value); return TRUE; } @@ -311,7 +314,8 @@ static const char *tsto_envelope_get_member_name(int id) return NULL; } -static bool tsto_envelope_set_member(int id, string_t *value) +static bool tsto_envelope_set_member +(const struct sieve_runtime_env *renv ATTR_UNUSED, int id, string_t *value) { switch ( id ) { case TESTSUITE_OBJECT_ENVELOPE_FROM: diff --git a/src/testsuite/testsuite-objects.h b/src/testsuite/testsuite-objects.h index 999a0c7fc6619e9e7f725f66d860923ebfdf2aa2..0512ea370c2037d5089f1c0554108dac4b6a84fb 100644 --- a/src/testsuite/testsuite-objects.h +++ b/src/testsuite/testsuite-objects.h @@ -21,8 +21,9 @@ struct testsuite_object { int (*get_member_id)(const char *identifier); const char *(*get_member_name)(int id); - bool (*set_member)(int id, string_t *value); - string_t *(*get_member)(int id); + + bool (*set_member)(const struct sieve_runtime_env *renv, int id, string_t *value); + string_t *(*get_member)(const struct sieve_runtime_env *renv, int id); }; /* Testsuite object registration */ diff --git a/tests/extensions/body/basic.svtest b/tests/extensions/body/basic.svtest index f9dab31da92928130a3fca12f1d82c6a42ed87d0..da86d488ec7b6324de1f82ca8efbc1b1ab0518f2 100644 --- a/tests/extensions/body/basic.svtest +++ b/tests/extensions/body/basic.svtest @@ -63,3 +63,33 @@ test "Defaults" { test_fail "default comparator is not i;ascii-casemap as is required"; } } + +/* No body + * + * RFC 5173: + * 'If a message consists of a header only, not followed by an empty line, + * then that set is empty and all "body" tests return false, including + * those that test for an empty string. (This is similar to how the + * "header" test always fails when the named header fields aren't present.)' + */ + +test_set "message" text: +From: stephan@rename-it.nl +To: tss@iki.fi +Subject: No body is here! +. +; + +test "No body" { + if body :raw :contains "" { + test_fail "matched against non-existant body (:contains \"\")"; + } + + if body :raw :is "" { + test_fail "matched against non-existant body (:is \"\")"; + } + + if body :raw :matches "*" { + test_fail "matched against non-existant body (:matches \"*\")"; + } +}