1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
4
#include "sieve-common.h"
5
#include "sieve-commands.h"
6
#include "sieve-validator.h"
7
#include "sieve-generator.h"
8
#include "sieve-interpreter.h"
9
#include "sieve-code.h"
10
#include "sieve-binary.h"
11
#include "sieve-dump.h"
13
#include "testsuite-common.h"
14
#include "testsuite-smtp.h"
15
#include "testsuite-mailstore.h"
18
* Test_message command
21
* test_message ( :smtp / :mailbox <mailbox: string> ) <index: number>
24
static bool cmd_test_message_registered
25
(struct sieve_validator *valdtr,
26
struct sieve_command_registration *cmd_reg);
27
static bool cmd_test_message_validate
28
(struct sieve_validator *valdtr, struct sieve_command_context *cmd);
29
static bool cmd_test_message_generate
30
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
32
const struct sieve_command cmd_test_message = {
36
cmd_test_message_registered,
38
cmd_test_message_validate,
39
cmd_test_message_generate,
47
/* Test_message_smtp operation */
49
static bool cmd_test_message_smtp_operation_dump
50
(const struct sieve_operation *op,
51
const struct sieve_dumptime_env *denv, sieve_size_t *address);
52
static int cmd_test_message_smtp_operation_execute
53
(const struct sieve_operation *op,
54
const struct sieve_runtime_env *renv, sieve_size_t *address);
56
const struct sieve_operation test_message_smtp_operation = {
59
TESTSUITE_OPERATION_TEST_MESSAGE_SMTP,
60
cmd_test_message_smtp_operation_dump,
61
cmd_test_message_smtp_operation_execute
64
/* Test_message_mailbox operation */
66
static bool cmd_test_message_mailbox_operation_dump
67
(const struct sieve_operation *op,
68
const struct sieve_dumptime_env *denv, sieve_size_t *address);
69
static int cmd_test_message_mailbox_operation_execute
70
(const struct sieve_operation *op,
71
const struct sieve_runtime_env *renv, sieve_size_t *address);
73
const struct sieve_operation test_message_mailbox_operation = {
74
"TEST_MESSAGE_MAILBOX",
76
TESTSUITE_OPERATION_TEST_MESSAGE_MAILBOX,
77
cmd_test_message_mailbox_operation_dump,
78
cmd_test_message_mailbox_operation_execute
82
* Compiler context data
85
enum test_message_source {
91
const struct sieve_operation *test_message_operations[] = {
92
&test_message_smtp_operation,
93
&test_message_mailbox_operation
96
struct cmd_test_message_context_data {
97
enum test_message_source msg_source;
101
#define CMD_TEST_MESSAGE_ERROR_DUP_TAG \
102
"exactly one of the ':smtp' or ':folder' tags must be specified " \
103
"for the test_message command, but more were found"
109
static bool cmd_test_message_validate_smtp_tag
110
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
111
struct sieve_command_context *cmd);
112
static bool cmd_test_message_validate_folder_tag
113
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
114
struct sieve_command_context *cmd);
116
static const struct sieve_argument test_message_smtp_tag = {
119
cmd_test_message_validate_smtp_tag,
123
static const struct sieve_argument test_message_folder_tag = {
126
cmd_test_message_validate_folder_tag,
130
static bool cmd_test_message_registered
131
(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg)
133
/* Register our tags */
134
sieve_validator_register_tag(valdtr, cmd_reg, &test_message_folder_tag, 0);
135
sieve_validator_register_tag(valdtr, cmd_reg, &test_message_smtp_tag, 0);
140
static struct cmd_test_message_context_data *cmd_test_message_validate_tag
141
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
142
struct sieve_command_context *cmd)
144
struct cmd_test_message_context_data *ctx_data =
145
(struct cmd_test_message_context_data *) cmd->data;
147
if ( ctx_data != NULL ) {
148
sieve_argument_validate_error
149
(valdtr, *arg, CMD_TEST_MESSAGE_ERROR_DUP_TAG);
154
(sieve_command_pool(cmd), struct cmd_test_message_context_data, 1);
155
cmd->data = ctx_data;
157
/* Delete this tag */
158
*arg = sieve_ast_arguments_detach(*arg, 1);
163
static bool cmd_test_message_validate_smtp_tag
164
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
165
struct sieve_command_context *cmd)
167
struct cmd_test_message_context_data *ctx_data =
168
cmd_test_message_validate_tag(valdtr, arg, cmd);
170
/* Return value is NULL on error */
171
if ( ctx_data == NULL ) return FALSE;
173
/* Assign chosen message source */
174
ctx_data->msg_source = MSG_SOURCE_SMTP;
179
static bool cmd_test_message_validate_folder_tag
180
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
181
struct sieve_command_context *cmd)
183
struct sieve_ast_argument *tag = *arg;
184
struct cmd_test_message_context_data *ctx_data =
185
cmd_test_message_validate_tag(valdtr, arg, cmd);
187
/* Return value is NULL on error */
188
if ( ctx_data == NULL ) return FALSE;
190
/* Assign chose message source */
191
ctx_data->msg_source = MSG_SOURCE_MAILBOX;
196
if ( !sieve_validate_tag_parameter
197
(valdtr, cmd, tag, *arg, SAAT_STRING) ) {
202
*arg = sieve_ast_argument_next(*arg);
211
static bool cmd_test_message_validate
212
(struct sieve_validator *valdtr, struct sieve_command_context *cmd)
214
struct sieve_ast_argument *arg = cmd->first_positional;
216
if ( cmd->data == NULL ) {
217
sieve_command_validate_error(valdtr, cmd,
218
"the test_message command requires either the :smtp or the :mailbox tag "
223
if ( !sieve_validate_positional_argument
224
(valdtr, cmd, arg, "index", 1, SAAT_NUMBER) ) {
228
return sieve_validator_argument_activate(valdtr, cmd, arg, FALSE);
235
static bool cmd_test_message_generate
236
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *cmd)
238
struct cmd_test_message_context_data *ctx_data =
239
(struct cmd_test_message_context_data *) cmd->data;
241
i_assert( ctx_data->msg_source < MSG_SOURCE_LAST );
244
sieve_operation_emit_code(cgenv->sbin,
245
test_message_operations[ctx_data->msg_source]);
247
/* Emit is_test flag */
248
sieve_binary_emit_byte(cgenv->sbin, ( cmd->ast_node->type == SAT_TEST ));
250
/* Generate arguments */
251
if ( !sieve_generate_arguments(cgenv, cmd, NULL) )
261
static bool cmd_test_message_smtp_operation_dump
262
(const struct sieve_operation *op ATTR_UNUSED,
263
const struct sieve_dumptime_env *denv, sieve_size_t *address)
265
unsigned int is_test;
267
if ( !sieve_binary_read_byte(denv->sbin, address, &is_test) )
270
sieve_code_dumpf(denv, "TEST_MESSAGE_SMTP (%s):",
271
( is_test ? "TEST" : "COMMAND" ));
273
sieve_code_descend(denv);
275
return sieve_opr_number_dump(denv, address, "index");
278
static bool cmd_test_message_mailbox_operation_dump
279
(const struct sieve_operation *op ATTR_UNUSED,
280
const struct sieve_dumptime_env *denv, sieve_size_t *address)
282
unsigned int is_test;
284
if ( !sieve_binary_read_byte(denv->sbin, address, &is_test) )
287
sieve_code_dumpf(denv, "TEST_MESSAGE_MAILBOX (%s):",
288
( is_test ? "TEST" : "COMMAND" ));
290
sieve_code_descend(denv);
293
sieve_opr_string_dump(denv, address, "folder") &&
294
sieve_opr_number_dump(denv, address, "index");
301
static int cmd_test_message_smtp_operation_execute
302
(const struct sieve_operation *op ATTR_UNUSED,
303
const struct sieve_runtime_env *renv, sieve_size_t *address)
305
sieve_number_t msg_index;
306
unsigned int is_test = -1;
315
if ( !sieve_binary_read_byte(renv->sbin, address, &is_test) ) {
316
sieve_runtime_trace_error(renv, "invalid is_test flag");
317
return SIEVE_EXEC_BIN_CORRUPT;
322
if ( !sieve_opr_number_read(renv, address, &msg_index) ) {
323
sieve_runtime_trace_error(renv, "invalid index operand");
324
return SIEVE_EXEC_BIN_CORRUPT;
331
sieve_runtime_trace(renv, "TEST_MESSAGE_SMTP (%s) [%d]",
332
( is_test ? "TEST" : "COMMAND" ), msg_index);
334
result = testsuite_smtp_get(renv, msg_index);
337
sieve_interpreter_set_test_result(renv->interp, result);
338
return SIEVE_EXEC_OK;
342
testsuite_test_failf("no outgoing SMTP message with index %d", msg_index);
344
return SIEVE_EXEC_OK;
347
static int cmd_test_message_mailbox_operation_execute
348
(const struct sieve_operation *op ATTR_UNUSED,
349
const struct sieve_runtime_env *renv, sieve_size_t *address)
352
sieve_number_t msg_index;
353
unsigned int is_test = -1;
361
if ( !sieve_binary_read_byte(renv->sbin, address, &is_test) ) {
362
sieve_runtime_trace_error(renv, "invalid is_test flag");
363
return SIEVE_EXEC_BIN_CORRUPT;
367
if ( !sieve_opr_string_read(renv, address, &folder) ) {
368
sieve_runtime_trace_error(renv, "invalid folder operand");
369
return SIEVE_EXEC_BIN_CORRUPT;
373
if ( !sieve_opr_number_read(renv, address, &msg_index) ) {
374
sieve_runtime_trace_error(renv, "invalid index operand");
375
return SIEVE_EXEC_BIN_CORRUPT;
382
sieve_runtime_trace(renv, "TEST_MESSAGE_MAILBOX (%s) \"%s\" [%d]",
383
( is_test ? "TEST" : "COMMAND" ), str_c(folder), msg_index);
385
result = testsuite_mailstore_mail_index(renv, str_c(folder), msg_index);
388
sieve_interpreter_set_test_result(renv->interp, result);
389
return SIEVE_EXEC_OK;
393
testsuite_test_failf("no message in folder '%s' with index %d",
394
str_c(folder), msg_index);
396
return SIEVE_EXEC_OK;