diff --git a/.hgignore b/.hgignore index 92b1d2a9bc1188229854dc1d96c5f7ced982aa0a..534f802d959e6ce138f7a60fa79050b339f29ebd 100644 --- a/.hgignore +++ b/.hgignore @@ -37,6 +37,7 @@ Makefile.in *~ *.o *.lo +*.loT *.Po *.Plo *.a diff --git a/src/Makefile.am b/src/Makefile.am index de5f667f3e79e587642927521b2ddeb745ee65ee..e3940c66446bf9e83d65392116a8520794ae7bc0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1 @@ -SUBDIRS = lib-sieve sieve-bin plugins +SUBDIRS = lib-sieve sieve-bin plugins testsuite diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am index 2cf105300ccbfe4fdabc3145dbc10ae4b70b7bfe..2dcf2ccb0abd8819aaaf44c2688074fab43dcec6 100644 --- a/src/lib-sieve/Makefile.am +++ b/src/lib-sieve/Makefile.am @@ -61,6 +61,7 @@ libsieve_la_SOURCES = \ sieve-generator.c \ sieve-interpreter.c \ sieve-code-dumper.c \ + sieve-binary-dumper.c \ sieve-result.c \ sieve-error.c \ sieve-comparators.c \ @@ -87,6 +88,7 @@ noinst_HEADERS = \ sieve-generator.h \ sieve-interpreter.h \ sieve-code-dumper.h \ + sieve-binary-dumper.h \ sieve-result.h \ sieve-error.h \ sieve-error-private.h \ diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 87d29086f76623a55e2256cc6b86fc996ae86768..eaf7cae8b1bbcde5ffabb5ce74a0371b5a87e017 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -24,7 +24,7 @@ #include "sieve-generator.h" #include "sieve-binary.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-result.h" /* Forward declarations */ diff --git a/src/lib-sieve/plugins/body/ext-body.c b/src/lib-sieve/plugins/body/ext-body.c index 0a3218d5033b10a25fda5d6a9fff55d3d79a4480..1aad477c828a450b2237194f4202fa428e4b6ec4 100644 --- a/src/lib-sieve/plugins/body/ext-body.c +++ b/src/lib-sieve/plugins/body/ext-body.c @@ -37,7 +37,7 @@ #include "sieve-generator.h" #include "sieve-binary.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-body-common.h" diff --git a/src/lib-sieve/plugins/body/tst-body.c b/src/lib-sieve/plugins/body/tst-body.c index 03fa540d154fafbf3541db2f32d14c70cae97434..60f180cfe517dad983e93badbbfcd5794c5b0476 100644 --- a/src/lib-sieve/plugins/body/tst-body.c +++ b/src/lib-sieve/plugins/body/tst-body.c @@ -9,7 +9,7 @@ #include "sieve-generator.h" #include "sieve-binary.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-body-common.h" diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c index 10335f2ad6b54a2025b8df18f65b0f6536b265e7..4c203b9247d14320278469a192ddfbce0dd8b0fc 100644 --- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c +++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c @@ -5,7 +5,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-imapflags-common.h" diff --git a/src/lib-sieve/plugins/imapflags/imapflags.sieve b/src/lib-sieve/plugins/imapflags/imapflags.sieve index 44a39ec7c7a05336ee6c793e1a017aa64ffe2fb7..e33b13ebe6603738c6a6a5338e8993a02e7dbf0f 100644 --- a/src/lib-sieve/plugins/imapflags/imapflags.sieve +++ b/src/lib-sieve/plugins/imapflags/imapflags.sieve @@ -25,4 +25,4 @@ if hasflag :count "ge" :comparator "i;ascii-numeric" "2" { fileinto "imap-twoflags"; } -fileinto :flags "\\Seen $MDNRequired \\Draft" "INBOX"; +fileinto :flags "\\Seen MDNRequired \\Draft" "INBOX"; diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c index ff716cc6e5003232a6d6d7576106fc737f5d7eb8..9489d5e61b07c9f0ff8a4542e926e77d50738df0 100644 --- a/src/lib-sieve/plugins/imapflags/tag-flags.c +++ b/src/lib-sieve/plugins/imapflags/tag-flags.c @@ -234,20 +234,25 @@ static void seff_flags_print static bool seff_flags_post_execute (const struct sieve_side_effect *seffect ATTR_UNUSED, const struct sieve_action *action ATTR_UNUSED, - const struct sieve_action_exec_env *aenv ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *se_context, void *tr_context) { struct seff_flags_context *ctx = (struct seff_flags_context *) se_context; struct act_store_transaction *trans = (struct act_store_transaction *) tr_context; + struct mail_keywords *keywords; if ( trans->dest_mail == NULL ) return TRUE; - printf("SETTING FLAGS\n"); + if (mailbox_keywords_create(trans->box, ctx->keywords, &keywords) < 0) { + sieve_result_error(aenv, "invalid keywords"); + return FALSE; + } + /* Update message flags. */ mail_update_flags(trans->dest_mail, MODIFY_ADD, ctx->flags); /* Update message keywords. */ - //mail_update_keywords(trans->dest_mail, MODIFY_REPLACE, keywords); + mail_update_keywords(trans->dest_mail, MODIFY_ADD, keywords); return TRUE; } diff --git a/src/lib-sieve/plugins/imapflags/tst-hasflag.c b/src/lib-sieve/plugins/imapflags/tst-hasflag.c index 152e9ae74920dd7bb470831c4eac0a76e56bc682..97d651c4b4f69c451a1960ddc595ecc0e484c039 100644 --- a/src/lib-sieve/plugins/imapflags/tst-hasflag.c +++ b/src/lib-sieve/plugins/imapflags/tst-hasflag.c @@ -7,7 +7,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-imapflags-common.h" diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index c9eca4896768de8b8fe0ad091592d8e9b7e49f01..3a373e1ffbe69b68ae107a8869601f49bb8e4041 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -10,7 +10,7 @@ #include "sieve-binary.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-include-common.h" diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c index c54c82c009385d5628701d9b3a714ec1e47c4f4b..a3336a4e457101e1c89430ee8f3c1aa9e304103e 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation.c +++ b/src/lib-sieve/plugins/vacation/ext-vacation.c @@ -26,7 +26,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-result.h" #include <stdio.h> diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c index e4180228b0a1233f692d7e96390847ecb55be9b4..0dd06f7b5f894e28491ca61e2100989d4039b09a 100644 --- a/src/lib-sieve/plugins/variables/cmd-set.c +++ b/src/lib-sieve/plugins/variables/cmd-set.c @@ -13,7 +13,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-variables-common.h" diff --git a/src/lib-sieve/plugins/variables/ext-variables-arguments.c b/src/lib-sieve/plugins/variables/ext-variables-arguments.c index 0e59920e989414ad7ef3ca2667e37685cef13186..672fdf7f47fd6d46518b41d906bdf589113c4d6b 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-arguments.c +++ b/src/lib-sieve/plugins/variables/ext-variables-arguments.c @@ -9,7 +9,7 @@ #include "sieve-commands.h" #include "sieve-validator.h" #include "sieve-generator.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-variables-common.h" #include "ext-variables-name.h" diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c index 96abf265c6a1095468d2a1b38f399e3255472631..35530a0c5044f1f737405295fc882c6991e8daec 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-common.c +++ b/src/lib-sieve/plugins/variables/ext-variables-common.c @@ -13,7 +13,7 @@ #include "sieve-commands.h" #include "sieve-validator.h" #include "sieve-generator.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-interpreter.h" #include "ext-variables-common.h" diff --git a/src/lib-sieve/plugins/variables/ext-variables-operands.c b/src/lib-sieve/plugins/variables/ext-variables-operands.c index 31a2e644600a4a61216b5733289c36bb773f7f51..638f8f90ebcd89162c13d026f466443836ce888d 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-operands.c +++ b/src/lib-sieve/plugins/variables/ext-variables-operands.c @@ -13,7 +13,7 @@ #include "sieve-commands.h" #include "sieve-validator.h" #include "sieve-generator.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-interpreter.h" #include "ext-variables-common.h" diff --git a/src/lib-sieve/plugins/variables/tst-string.c b/src/lib-sieve/plugins/variables/tst-string.c index 44f0020afddb07bea535060357439c8e70fb7dbb..e14d9e28289bb5f1f7a3a076b776da01a8677862 100644 --- a/src/lib-sieve/plugins/variables/tst-string.c +++ b/src/lib-sieve/plugins/variables/tst-string.c @@ -8,7 +8,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "ext-variables-common.h" diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 088265038c4177b3b3ae013bd147512f091f1035..afd48bc8a275d6ee0ec7fb76a916b5f75471d475 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -8,7 +8,7 @@ #include "sieve-extensions-private.h" #include "sieve-binary.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-result.h" #include "sieve-actions.h" @@ -277,8 +277,13 @@ static bool act_store_start box = mailbox_open(ns->storage, ctx->folder, NULL, MAILBOX_OPEN_FAST | MAILBOX_OPEN_KEEP_RECENT); + + if (box != NULL && mailbox_sync(box, 0, 0, NULL) < 0) { + mailbox_close(&box); + box = NULL; + } } - + pool = sieve_result_pool(aenv->result); trans = p_new(pool, struct act_store_transaction, 1); trans->context = ctx; diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index 26e72f7b78730d8584aef63a2d49be39651dd313..3b9dc27331095ca974917a747d62cc28f4ae53d2 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -16,7 +16,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-address-parts.h" diff --git a/src/lib-sieve/sieve-binary-dumper.c b/src/lib-sieve/sieve-binary-dumper.c new file mode 100644 index 0000000000000000000000000000000000000000..8b0a0323b0d437f684df192c8164cec816e20a2a --- /dev/null +++ b/src/lib-sieve/sieve-binary-dumper.c @@ -0,0 +1,57 @@ +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-binary.h" + +#include "sieve-dump.h" + +struct sieve_binary_dumper { + pool_t pool; + + /* Dumptime environment */ + struct sieve_dumptime_env dumpenv; +}; + +struct sieve_binary_dumper *sieve_binary_dumper_create + (struct sieve_binary *sbin) +{ + pool_t pool; + struct sieve_binary_dumper *dumper; + + pool = pool_alloconly_create("sieve_binary_dumper", 4096); + dumper = p_new(pool, struct sieve_binary_dumper, 1); + dumper->pool = pool; + dumper->dumpenv.dumper = dumper; + + dumper->dumpenv.sbin = sbin; + sieve_binary_ref(sbin); + + return dumper; +} + +void sieve_binary_dumper_free(struct sieve_binary_dumper **dumper) +{ + sieve_binary_unref(&(*dumper)->dumpenv.sbin); + pool_unref(&((*dumper)->pool)); + + *dumper = NULL; +} + +pool_t sieve_binary_dumper_pool(struct sieve_binary_dumper *dumper) +{ + return dumper->pool; +} + +/* */ + +void sieve_binary_dumper_run + (struct sieve_binary_dumper *dumper, struct ostream *stream) +{ + dumper->dumpenv.stream = stream; + + dumper->dumpenv.cdumper = sieve_code_dumper_create(&(dumper->dumpenv)); + + sieve_code_dumper_run(dumper->dumpenv.cdumper); + + sieve_code_dumper_free(&dumper->dumpenv.cdumper); +} diff --git a/src/lib-sieve/sieve-binary-dumper.h b/src/lib-sieve/sieve-binary-dumper.h new file mode 100644 index 0000000000000000000000000000000000000000..69e7fc79b0cdd5ad40ea00a3b60533097ca842c5 --- /dev/null +++ b/src/lib-sieve/sieve-binary-dumper.h @@ -0,0 +1,22 @@ +#ifndef __SIEVE_BINARY_DUMPER_H +#define __SIEVE_BINARY_DUMPER_H + +#include "sieve-common.h" + +struct sieve_binary_dumper; + +struct sieve_binary_dumper *sieve_binary_dumper_create + (struct sieve_binary *sbin); +void sieve_binary_dumper_free + (struct sieve_binary_dumper **dumper); + +pool_t sieve_binary_dumper_pool + (struct sieve_binary_dumper *dumper); + +/* */ + +void sieve_binary_dumper_run + (struct sieve_binary_dumper *dumper, struct ostream *stream); + + +#endif /* __SIEVE_BINARY_DUMPER_H */ diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index b640e821e2b595dda7a3e0d675728f5fb6cb5d3b..949464ecea58b9e1a68b03b4b6329c0683c58975 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -57,7 +57,7 @@ static inline int sieve_binary_extension_register struct sieve_binary_extension_reg **reg); static inline sieve_size_t sieve_binary_emit_dynamic_data - (struct sieve_binary *binary, void *data, size_t size); + (struct sieve_binary *binary, const void *data, size_t size); /* * Internal structures @@ -1367,7 +1367,7 @@ int sieve_binary_extensions_count(struct sieve_binary *sbin) /* Low-level emission functions */ inline sieve_size_t sieve_binary_emit_data -(struct sieve_binary *binary, void *data, sieve_size_t size) +(struct sieve_binary *binary, const void *data, sieve_size_t size) { sieve_size_t address = buffer_get_used_size(binary->data); @@ -1383,7 +1383,7 @@ inline sieve_size_t sieve_binary_emit_byte } inline void sieve_binary_update_data -(struct sieve_binary *binary, sieve_size_t address, void *data, +(struct sieve_binary *binary, sieve_size_t address, const void *data, sieve_size_t size) { buffer_write(binary->data, address, data, size); @@ -1445,7 +1445,7 @@ sieve_size_t sieve_binary_emit_integer } static inline sieve_size_t sieve_binary_emit_dynamic_data - (struct sieve_binary *binary, void *data, size_t size) + (struct sieve_binary *binary, const void *data, size_t size) { sieve_size_t address = sieve_binary_emit_integer(binary, size); (void) sieve_binary_emit_data(binary, data, size); diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index 003ae11e7605ee0f5ecf29aa04722aa73ea1b015..fadf15fbbab9bf0ace2f8b49d1024e0155b0bc99 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -88,11 +88,11 @@ int sieve_binary_extensions_count(struct sieve_binary *sbin); /* Low-level emission functions */ inline sieve_size_t sieve_binary_emit_data - (struct sieve_binary *binary, void *data, sieve_size_t size); + (struct sieve_binary *binary, const void *data, sieve_size_t size); inline sieve_size_t sieve_binary_emit_byte (struct sieve_binary *binary, unsigned char byte); inline void sieve_binary_update_data - (struct sieve_binary *binary, sieve_size_t address, void *data, + (struct sieve_binary *binary, sieve_size_t address, const void *data, sieve_size_t size); inline sieve_size_t sieve_binary_get_code_size(struct sieve_binary *binary); diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c index 64b406fd1f555ba008ddb4ee3ff8c74ed597049d..b4421619306749e17349ea4b3ddd772e1705c221 100644 --- a/src/lib-sieve/sieve-code-dumper.c +++ b/src/lib-sieve/sieve-code-dumper.c @@ -15,7 +15,7 @@ #include "sieve-result.h" #include "sieve-comparators.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" struct sieve_code_dumper { pool_t pool; @@ -27,11 +27,12 @@ struct sieve_code_dumper { sieve_size_t mark_address; unsigned int indent; - /* Runtime environment environment */ - struct sieve_dumptime_env dumpenv; + /* Dump environment */ + struct sieve_dumptime_env *dumpenv; }; -struct sieve_code_dumper *sieve_code_dumper_create(struct sieve_binary *sbin) +struct sieve_code_dumper *sieve_code_dumper_create + (struct sieve_dumptime_env *denv) { pool_t pool; struct sieve_code_dumper *dumper; @@ -39,23 +40,20 @@ struct sieve_code_dumper *sieve_code_dumper_create(struct sieve_binary *sbin) pool = pool_alloconly_create("sieve_code_dumper", 4096); dumper = p_new(pool, struct sieve_code_dumper, 1); dumper->pool = pool; - dumper->dumpenv.dumper = dumper; - - dumper->dumpenv.sbin = sbin; - sieve_binary_ref(sbin); - + dumper->dumpenv = denv; dumper->pc = 0; return dumper; } -void sieve_code_dumper_free(struct sieve_code_dumper *dumper) +void sieve_code_dumper_free(struct sieve_code_dumper **dumper) { - sieve_binary_unref(&dumper->dumpenv.sbin); - pool_unref(&(dumper->pool)); + pool_unref(&((*dumper)->pool)); + + *dumper = NULL; } -inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper) +pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper) { return dumper->pool; } @@ -65,13 +63,14 @@ inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper) void sieve_code_dumpf (const struct sieve_dumptime_env *denv, const char *fmt, ...) { - unsigned tab = denv->dumper->indent; + struct sieve_code_dumper *cdumper = denv->cdumper; + unsigned tab = cdumper->indent; string_t *outbuf = t_str_new(128); va_list args; va_start(args, fmt); - str_printfa(outbuf, "%08x: ", denv->dumper->mark_address); + str_printfa(outbuf, "%08x: ", cdumper->mark_address); while ( tab > 0 ) { str_append(outbuf, " "); @@ -85,26 +84,26 @@ void sieve_code_dumpf o_stream_send(denv->stream, str_data(outbuf), str_len(outbuf)); } -inline void sieve_code_mark(const struct sieve_dumptime_env *denv) +void sieve_code_mark(const struct sieve_dumptime_env *denv) { - denv->dumper->mark_address = denv->dumper->pc; + denv->cdumper->mark_address = denv->cdumper->pc; } -inline void sieve_code_mark_specific +void sieve_code_mark_specific (const struct sieve_dumptime_env *denv, sieve_size_t location) { - denv->dumper->mark_address = location; + denv->cdumper->mark_address = location; } -inline void sieve_code_descend(const struct sieve_dumptime_env *denv) +void sieve_code_descend(const struct sieve_dumptime_env *denv) { - denv->dumper->indent++; + denv->cdumper->indent++; } -inline void sieve_code_ascend(const struct sieve_dumptime_env *denv) +void sieve_code_ascend(const struct sieve_dumptime_env *denv) { - if ( denv->dumper->indent > 0 ) - denv->dumper->indent--; + if ( denv->cdumper->indent > 0 ) + denv->cdumper->indent--; } /* Operations and operands */ @@ -134,49 +133,58 @@ static bool sieve_code_dumper_print_operation (struct sieve_code_dumper *dumper) { const struct sieve_operation *op; + struct sieve_dumptime_env *denv = dumper->dumpenv; + sieve_size_t address; + const char *opcode_string; /* Mark start address of operation */ dumper->indent = 0; - dumper->mark_address = dumper->pc; + address = dumper->mark_address = dumper->pc; /* Read operation */ dumper->operation = op = - sieve_operation_read(dumper->dumpenv.sbin, &(dumper->pc)); + sieve_operation_read(denv->sbin, &(dumper->pc)); /* Try to dump it */ if ( op != NULL ) { if ( op->dump != NULL ) - return op->dump(op, &(dumper->dumpenv), &(dumper->pc)); + return op->dump(op, denv, &(dumper->pc)); else if ( op->mnemonic != NULL ) - sieve_code_dumpf(&(dumper->dumpenv), "%s", op->mnemonic); + sieve_code_dumpf(denv, "%s", op->mnemonic); else return FALSE; return TRUE; } + opcode_string = sieve_operation_read_string(denv->sbin, &address); + + if ( opcode_string != NULL ) + sieve_code_dumpf(denv, "Unknown upcode: %s", opcode_string); + else + sieve_code_dumpf(denv, "Failed to read opcode."); return FALSE; } -void sieve_code_dumper_run - (struct sieve_code_dumper *dumper, struct ostream *stream) +void sieve_code_dumper_run(struct sieve_code_dumper *dumper) { + struct sieve_binary *sbin = dumper->dumpenv->sbin; + dumper->pc = 0; - dumper->dumpenv.stream = stream; while ( dumper->pc < - sieve_binary_get_code_size(dumper->dumpenv.sbin) ) { + sieve_binary_get_code_size(sbin) ) { if ( !sieve_code_dumper_print_operation(dumper) ) { - sieve_code_dumpf(&(dumper->dumpenv), "Binary is corrupt."); + sieve_code_dumpf(dumper->dumpenv, "Binary is corrupt."); return; } } /* Mark end of the binary */ dumper->indent = 0; - dumper->mark_address = sieve_binary_get_code_size(dumper->dumpenv.sbin); - sieve_code_dumpf(&(dumper->dumpenv), "[End of code]"); + dumper->mark_address = sieve_binary_get_code_size(sbin); + sieve_code_dumpf(dumper->dumpenv, "[End of code]"); /* Add empty line to the file */ - o_stream_send_str(dumper->dumpenv.stream, "\n"); + o_stream_send_str(dumper->dumpenv->stream, "\n"); } diff --git a/src/lib-sieve/sieve-code-dumper.h b/src/lib-sieve/sieve-code-dumper.h index 4a2781f4763caf091050d8fcccb9dec6458c0d4c..4f246ba470d4dffac6daf5f233c3532d8c8a479a 100644 --- a/src/lib-sieve/sieve-code-dumper.h +++ b/src/lib-sieve/sieve-code-dumper.h @@ -5,16 +5,12 @@ struct sieve_code_dumper; -struct sieve_dumptime_env { - struct sieve_code_dumper *dumper; - struct sieve_binary *sbin; - - struct ostream *stream; -}; - -struct sieve_code_dumper *sieve_code_dumper_create(struct sieve_binary *sbin); -void sieve_code_dumper_free(struct sieve_code_dumper *dumper); -inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper); +struct sieve_code_dumper *sieve_code_dumper_create + (struct sieve_dumptime_env *denv); +void sieve_code_dumper_free + (struct sieve_code_dumper **dumper); +pool_t sieve_code_dumper_pool + (struct sieve_code_dumper *dumper); /* */ @@ -22,11 +18,11 @@ void sieve_code_dumpf (const struct sieve_dumptime_env *denv, const char *fmt, ...) ATTR_FORMAT(2, 3); -inline void sieve_code_mark(const struct sieve_dumptime_env *denv); -inline void sieve_code_mark_specific +void sieve_code_mark(const struct sieve_dumptime_env *denv); +void sieve_code_mark_specific (const struct sieve_dumptime_env *denv, sieve_size_t location); -inline void sieve_code_descend(const struct sieve_dumptime_env *denv); -inline void sieve_code_ascend(const struct sieve_dumptime_env *denv); +void sieve_code_descend(const struct sieve_dumptime_env *denv); +void sieve_code_ascend(const struct sieve_dumptime_env *denv); /* Operations and operands */ @@ -35,7 +31,6 @@ bool sieve_code_dumper_print_optional_operands /* Code dump (debugging purposes) */ -void sieve_code_dumper_run - (struct sieve_code_dumper *dumper, struct ostream *stream); +void sieve_code_dumper_run(struct sieve_code_dumper *dumper); #endif /* __SIEVE_CODE_DUMPER_H */ diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index 750211ae33d21552326756a47e79f3a0cf1039f0..c36fbb11df524a73edc42d53db4c080f87e76d0b 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -8,7 +8,7 @@ #include "sieve-binary.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-code.h" @@ -704,6 +704,14 @@ const struct sieve_operation *sieve_operation_read (struct sieve_operation, sbin, address, &oprt_default_reg, sieve_operation_registry_get); } + +const char *sieve_operation_read_string + (struct sieve_binary *sbin, sieve_size_t *address) +{ + return sieve_extension_read_obj_string + (sbin, address, &oprt_default_reg, + sieve_operation_registry_get); +} /* Code dump for core commands */ diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index dbb4902c96498c53463df3c6087c701eee4cebc7..33be0bc5cf7c4f501dcc250697ba6a17df4a2677 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -172,6 +172,8 @@ inline sieve_size_t sieve_operation_emit_code (struct sieve_binary *sbin, const struct sieve_operation *op, int ext_id); const struct sieve_operation *sieve_operation_read (struct sieve_binary *sbin, sieve_size_t *address); +const char *sieve_operation_read_string + (struct sieve_binary *sbin, sieve_size_t *address); bool sieve_operation_string_dump (const struct sieve_operation *op, diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h index 4e851c5b28f122a54af5406e06a5e8e60ee0aed7..79d41b3b7812d18e70aaf78330abf83d2fc6e50d 100644 --- a/src/lib-sieve/sieve-common.h +++ b/src/lib-sieve/sieve-common.h @@ -52,8 +52,11 @@ struct sieve_generator; struct sieve_runtime_env; struct sieve_interpreter; -/* sieve-code-dumper.h */ +/* sieve-binary-dumper.h */ struct sieve_dumptime_env; +struct sieve_binary_dumper; + +/* sieve-code-dumper.h */ struct sieve_code_dumper; /* sieve-extension.h */ diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c index d6a571e5e37231b230caf8e45d3e665c8d24e2e1..5732ae20bc768e342ba499ae1c4eea9e85a036a5 100644 --- a/src/lib-sieve/sieve-comparators.c +++ b/src/lib-sieve/sieve-comparators.c @@ -10,7 +10,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-comparators.h" diff --git a/src/lib-sieve/sieve-dump.h b/src/lib-sieve/sieve-dump.h new file mode 100644 index 0000000000000000000000000000000000000000..1105dc4460e5229017c3815acca0976d8c8c23ee --- /dev/null +++ b/src/lib-sieve/sieve-dump.h @@ -0,0 +1,17 @@ +#ifndef __SIEVE_DUMP_H +#define __SIEVE_DUMP_H + +#include "sieve-common.h" + +#include "sieve-binary-dumper.h" +#include "sieve-code-dumper.h" + +struct sieve_dumptime_env { + struct sieve_binary_dumper *dumper; + struct sieve_code_dumper *cdumper; + struct sieve_binary *sbin; + + struct ostream *stream; +}; + +#endif /* __SIEVE_DUMP_H */ diff --git a/src/lib-sieve/sieve-extensions-private.h b/src/lib-sieve/sieve-extensions-private.h index 0135bc2a8b03be1ef05dee8023b2f89ef82a3a5c..2ebc0e9e95a292859fcd30dca80c038103e8e9f6 100644 --- a/src/lib-sieve/sieve-extensions-private.h +++ b/src/lib-sieve/sieve-extensions-private.h @@ -79,4 +79,33 @@ static inline const void *_sieve_extension_read_obj ((const type *) _sieve_extension_read_obj \ (sbin, address, defreg, get_reg_func)) +static inline const char *sieve_extension_read_obj_string +(struct sieve_binary *sbin, sieve_size_t *address, + const struct sieve_extension_obj_registry *defreg, + const struct sieve_extension_obj_registry *(*get_reg_func) + (struct sieve_binary *sbin, unsigned int index)) +{ + unsigned int obj_code; + + if ( sieve_binary_read_byte(sbin, address, &obj_code) ) { + if ( obj_code < defreg->count ) { + return t_strdup_printf("[CODE: %d]", obj_code); + } else { + unsigned int code = 0; + const struct sieve_extension_obj_registry *reg; + + if ( (reg=get_reg_func(sbin, obj_code - defreg->count)) == NULL || + reg->count == 0 ) + return t_strdup_printf("[EXT: %d; NO CODES!]", obj_code); + + if ( reg->count > 1) + sieve_binary_read_byte(sbin, address, &code); + + return t_strdup_printf("[EXT: %d; CODE: %d]", obj_code, code); + } + } + + return NULL; +} + #endif /* __SIEVE_EXTENSIONS_PRIVATE_H */ diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c index 079b2fe75f1a70f5c857445dbdd64c7d07802c33..2c098c0b2fd0c21a777e95801287a1ae8d4b33dc 100644 --- a/src/lib-sieve/sieve-match-types.c +++ b/src/lib-sieve/sieve-match-types.c @@ -14,7 +14,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" #include "sieve-match-types.h" diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index 7884ffb4970df4daecab0c533870ba9a6ce1d330..f674ff318a8ae72fc45b77f563fecbffc994e582 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -294,7 +294,7 @@ int sieve_result_execute while ( rsef != NULL ) { sef = rsef->seffect; if ( sef->pre_execute != NULL ) - sef->pre_execute + success = success & sef->pre_execute (sef, act, &result->action_env, &rsef->context, context); rsef = rsef->next; } @@ -305,12 +305,12 @@ int sieve_result_execute success = success && rac->success; } - /* Execute pre-execute event of side effects */ + /* Execute post-execute event of side effects */ rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL; while ( rsef != NULL ) { sef = rsef->seffect; if ( sef->post_execute != NULL ) - sef->post_execute + success = success && sef->post_execute (sef, act, &result->action_env, rsef->context, context); rsef = rsef->next; } diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 3062207fd56172b95d695b220abc083ec24ffb39..dc0d252c61d4ac85f9124be139c9b37faa88de74 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */ +/* Copyright (c) 2002-2007 Dovecot Sieve authors, see the included COPYING file */ #include "lib.h" #include "str.h" @@ -16,7 +16,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-binary-dumper.h" #include "sieve.h" #include "sieve-common.h" @@ -174,11 +174,11 @@ struct sieve_binary *sieve_open void sieve_dump(struct sieve_binary *sbin, struct ostream *stream) { - struct sieve_code_dumper *dumpr = sieve_code_dumper_create(sbin); + struct sieve_binary_dumper *dumpr = sieve_binary_dumper_create(sbin); - sieve_code_dumper_run(dumpr, stream); + sieve_binary_dumper_run(dumpr, stream); - sieve_code_dumper_free(dumpr); + sieve_binary_dumper_free(&dumpr); } int sieve_test @@ -214,7 +214,6 @@ int sieve_execute ret = sieve_interpreter_run(interp, msgdata, senv, &sres); sieve_interpreter_free(&interp); - sieve_result_unref(&sres); return ret; } diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c index e2fd446448b7bb4d9934d8570c8a77c9f182c03f..fc5e2e19f0406c43d201a3accab0fbe152f471a3 100644 --- a/src/lib-sieve/tst-header.c +++ b/src/lib-sieve/tst-header.c @@ -8,7 +8,7 @@ #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" -#include "sieve-code-dumper.h" +#include "sieve-dump.h" /* Header test * diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..826cb8141ae0991c4a800687f420e6f65b8a872f --- /dev/null +++ b/src/testsuite/Makefile.am @@ -0,0 +1,53 @@ +noinst_PROGRAMS = testsuite + +AM_CPPFLAGS = \ + -I../lib-sieve \ + -I$(dovecot_incdir) \ + -I$(dovecot_incdir)/src/lib \ + -I$(dovecot_incdir)/src/lib-mail \ + -I$(dovecot_incdir)/src/lib-index \ + -I$(dovecot_incdir)/src/lib-storage \ + -I$(dovecot_incdir)/src/lib-storage/index \ + -I$(dovecot_incdir)/src/lib-storage/index/raw \ + -I$(dovecot_incdir)/src/lib-storage/index/mbox \ + -I$(dovecot_incdir)/src/lib-storage/index/maildir + +testsuite_LDFLAGS = -export-dynamic -Wl,--start-group + +libs = \ + $(top_srcdir)/src/lib-sieve/libsieve.la \ + $(dovecot_incdir)/src/lib-storage/list/libstorage_list.a \ + $(dovecot_incdir)/src/lib-storage/index/raw/libstorage_raw.a \ + $(dovecot_incdir)/src/lib-storage/index/maildir/libstorage_maildir.a \ + $(dovecot_incdir)/src/lib-storage/index/mbox/libstorage_mbox.a \ + $(dovecot_incdir)/src/lib-storage/index/libstorage_index.a \ + $(dovecot_incdir)/src/lib-storage/libstorage.a \ + $(dovecot_incdir)/src/lib-index/libindex.a \ + $(dovecot_incdir)/src/lib-imap/libimap.a \ + $(dovecot_incdir)/src/lib-mail/libmail.a \ + $(dovecot_incdir)/src/lib-charset/libcharset.a \ + $(dovecot_incdir)/src/lib/liblib.a + +ldadd = \ + $(libs) \ + $(LIBICONV) \ + $(RAND_LIBS) \ + $(MODULE_LIBS) + +testsuite_LDADD = $(ldadd) +testsuite_DEPENDENCIES = $(libs) + +cmds = \ + cmd-test-message.c + +testsuite_SOURCES = \ + namespaces.c \ + mail-raw.c \ + $(cmds) \ + ext-testsuite.c \ + testsuite.c + +noinst_HEADERS = \ + testsuite-common.h \ + namespaces.h \ + mail-raw.h diff --git a/src/testsuite/cmd-test-message.c b/src/testsuite/cmd-test-message.c new file mode 100644 index 0000000000000000000000000000000000000000..25f7e79c576d9628dbc446a7145246d5b0c39be4 --- /dev/null +++ b/src/testsuite/cmd-test-message.c @@ -0,0 +1,134 @@ +#include "lib.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "istream.h" +#include "istream-header-filter.h" + +#include "sieve-commands.h" +#include "sieve-commands-private.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-code-dumper.h" +#include "sieve-result.h" + +#include "testsuite-common.h" + +#include <stdio.h> + +/* Forward declarations */ + +static bool cmd_test_message_operation_dump + (const struct sieve_operation *op, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static bool cmd_test_message_operation_execute + (const struct sieve_operation *op, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +static bool cmd_test_message_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); +static bool cmd_test_message_generate + (struct sieve_generator *generator, struct sieve_command_context *ctx); + +/* Redirect command + * + * Syntax + * redirect <address: string> + */ + +const struct sieve_command cmd_test_message = { + "test_message", + SCT_COMMAND, + 1, 0, FALSE, FALSE, + NULL, NULL, + cmd_test_message_validate, + cmd_test_message_generate, + NULL +}; + +/* Redirect operation */ + +const struct sieve_operation test_message_operation = { + "TEST_MESSAGE", + &testsuite_extension, + 0, + cmd_test_message_operation_dump, + cmd_test_message_operation_execute +}; + +/* Validation */ + +static bool cmd_test_message_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check argument */ + if ( !sieve_validate_positional_argument + (validator, cmd, arg, "address", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(validator, cmd, arg, FALSE); +} + +/* + * Generation + */ + +static bool cmd_test_message_generate + (struct sieve_generator *generator, struct sieve_command_context *ctx) +{ + sieve_generator_emit_operation_ext(generator, &test_message_operation, + ext_testsuite_my_id); + + /* Generate arguments */ + if ( !sieve_generate_arguments(generator, ctx, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_test_message_operation_dump +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "TEST MESSAGE:"); + sieve_code_descend(denv); + + return + sieve_opr_string_dump(denv, address); +} + +/* + * Intepretation + */ + +static bool cmd_test_message_operation_execute +(const struct sieve_operation *op ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + string_t *message; + int ret = 0; + + t_push(); + + if ( !sieve_opr_string_read(renv, address, &message) ) { + t_pop(); + return FALSE; + } + + printf(">> TEST MESSAGE \"%s\"\n", str_c(message)); + + t_pop(); + return (ret >= 0); +} + + + diff --git a/src/testsuite/ext-testsuite.c b/src/testsuite/ext-testsuite.c new file mode 100644 index 0000000000000000000000000000000000000000..d4facaf75982cb2233f8c2dce205a46cd2d18564 --- /dev/null +++ b/src/testsuite/ext-testsuite.c @@ -0,0 +1,75 @@ +/* Extension testsuite + * ------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-specific + * (FIXME: provide specification for test authors) + * Implementation: skeleton + * Status: under development + * Purpose: This custom extension is used to add sieve commands that act + * on the test suite. This provides the ability to specify and change the input + * message inside the script and to fail validation, code generation and + * particularly execution based on predicates. + */ + +#include <stdio.h> + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +/* Forward declarations */ + +static bool ext_testsuite_load(int ext_id); +static bool ext_testsuite_validator_load(struct sieve_validator *validator); +static bool ext_testsuite_binary_load(struct sieve_binary *sbin); + +/* Extension definitions */ + +int ext_testsuite_my_id; + +extern const struct sieve_operation test_message_operation; + +const struct sieve_operation *testsuite_operations[] = + { &test_message_operation }; + +extern const struct sieve_command cmd_test_message; + +const struct sieve_extension testsuite_extension = { + "vnd.dovecot.testsuite", + ext_testsuite_load, + ext_testsuite_validator_load, + NULL, + ext_testsuite_binary_load, + NULL, + SIEVE_EXT_DEFINE_OPERATION(test_message_operation), + SIEVE_EXT_DEFINE_NO_OPERANDS +}; + +static bool ext_testsuite_load(int ext_id) +{ + ext_testsuite_my_id = ext_id; + + return TRUE; +} + +/* Load extension into validator */ +static bool ext_testsuite_validator_load(struct sieve_validator *validator) +{ + sieve_validator_register_command(validator, &cmd_test_message); + return TRUE; +} + +static bool ext_testsuite_binary_load(struct sieve_binary *sbin) +{ + return TRUE; +} + + + diff --git a/src/testsuite/mail-raw.c b/src/testsuite/mail-raw.c new file mode 100644 index 0000000000000000000000000000000000000000..269e01e873fa4f712b62435f17c898aa4b16b580 --- /dev/null +++ b/src/testsuite/mail-raw.c @@ -0,0 +1,101 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +/* This file was gratefully stolen from dovecot/src/deliver/deliver.c and altered + * to suit our needs. So, this contains lots and lots of duplicated code. + * The sieve_test program needs to read an email message from stdin and it needs + * to build a struct mail (to be fed to the sieve library). Deliver does something + * similar already, so that source was a basis for this test binary. + */ + +#include "lib.h" +#include "istream.h" +#include "istream-seekable.h" +#include "fd-set-nonblock.h" +#include "str.h" +#include "str-sanitize.h" +#include "strescape.h" +#include "message-address.h" +#include "raw-storage.h" +#include "mail-namespace.h" + +#include "mail-raw.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +/* After buffer grows larger than this, create a temporary file to /tmp + where to read the mail. */ +#define MAIL_MAX_MEMORY_BUFFER (1024*128) + +static struct mail_namespace *raw_ns; + +void mail_raw_init(pool_t namespaces_pool, const char *user) +{ + const char *error; + + raw_ns = mail_namespaces_init_empty(namespaces_pool); + raw_ns->flags |= NAMESPACE_FLAG_INTERNAL; + if (mail_storage_create(raw_ns, "raw", "/tmp", user, + 0, FILE_LOCK_METHOD_FCNTL, &error) < 0) + i_fatal("Couldn't create internal raw storage: %s", error); +} + +struct mail_raw *mail_raw_open(string_t *mail_data) +{ + pool_t pool; + struct raw_mailbox *raw_box; + struct mail_raw *mailr; + + pool = pool_alloconly_create("mail_raw", 1024); + mailr = p_new(pool, struct mail_raw, 1); + mailr->pool = pool; + + mailr->input = i_stream_create_from_data + (str_data(mail_data), str_len(mail_data)); + + mailr->box = mailbox_open(raw_ns->storage, + "Dovecot Raw Mail", mailr->input, MAILBOX_OPEN_NO_INDEX_FILES); + + if (mailr->box == NULL) + i_fatal("Can't open mail stream as raw"); + + if (mailbox_sync(mailr->box, 0, 0, NULL) < 0) { + enum mail_error error; + + i_fatal("Can't sync raw mail: %s", + mail_storage_get_last_error(raw_ns->storage, &error)); + } + raw_box = (struct raw_mailbox *) mailr->box; + raw_box->envelope_sender = DEFAULT_ENVELOPE_SENDER; + + mailr->trans = mailbox_transaction_begin(mailr->box, 0); + mailr->mail = mail_alloc(mailr->trans, 0, NULL); + mail_set_seq(mailr->mail, 1); + + /* */ + i_stream_seek(mailr->input, 0); + + return mailr; +} + +void mail_raw_close(struct mail_raw *mailr) +{ + i_stream_unref(&mailr->input); + + mail_free(&mailr->mail); + mailbox_transaction_rollback(&mailr->trans); + mailbox_close(&mailr->box); + + pool_unref(&mailr->pool); +} + +void mail_raw_deinit(void) +{ + mail_namespaces_deinit(&raw_ns); +} + diff --git a/src/testsuite/mail-raw.h b/src/testsuite/mail-raw.h new file mode 100644 index 0000000000000000000000000000000000000000..789b133e3cc496b9ca9cb13583f23b3eeedc8321 --- /dev/null +++ b/src/testsuite/mail-raw.h @@ -0,0 +1,21 @@ +#ifndef __MAIL_RAW_H +#define __MAIL_RAW_H + +#include "lib.h" +#include "str.h" + +struct mail_raw { + pool_t pool; + struct mail *mail; + + struct istream *input; + struct mailbox *box; + struct mailbox_transaction_context *trans; +}; + +void mail_raw_init(pool_t namespaces_pool, const char *user); +struct mail_raw *mail_raw_open(string_t *mail_data); +void mail_raw_close(struct mail_raw *mailr); +void mail_raw_deinit(void); + +#endif /* __MAIL_RAW_H */ diff --git a/src/testsuite/namespaces.c b/src/testsuite/namespaces.c new file mode 100644 index 0000000000000000000000000000000000000000..cc1378953022d6bde03267b21d6f053043187e8c --- /dev/null +++ b/src/testsuite/namespaces.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "istream.h" +#include "istream-seekable.h" +#include "fd-set-nonblock.h" +#include "str.h" +#include "str-sanitize.h" +#include "strescape.h" +#include "message-address.h" +#include "raw-storage.h" +#include "mbox-storage.h" +#include "maildir-storage.h" +#include "mail-namespace.h" + +#include "namespaces.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +/* Hideous .... */ + +extern struct mail_storage raw_storage; +extern struct mail_storage maildir_storage; +extern struct mail_storage mbox_storage; +void mail_storage_register_all(void) { + mail_storage_class_register(&raw_storage); + mail_storage_class_register(&mbox_storage); + mail_storage_class_register(&maildir_storage); +} + +extern struct mailbox_list maildir_mailbox_list; +extern struct mailbox_list fs_mailbox_list; +void index_mailbox_list_init(void); +void mailbox_list_register_all(void) { +mailbox_list_register(&maildir_mailbox_list); +mailbox_list_register(&fs_mailbox_list); +index_mailbox_list_init(); +} + +static pool_t namespaces_pool; + +pool_t namespaces_init(void) +{ + mail_storage_init(); + mail_storage_register_all(); + mailbox_list_register_all(); + + namespaces_pool = pool_alloconly_create("namespaces", 1024); + + return namespaces_pool; +} + +void namespaces_deinit(void) +{ + mail_storage_deinit(); + pool_unref(&namespaces_pool); +} + diff --git a/src/testsuite/namespaces.h b/src/testsuite/namespaces.h new file mode 100644 index 0000000000000000000000000000000000000000..5f542d3f62d0d796937d97e0818f9003b5417e9b --- /dev/null +++ b/src/testsuite/namespaces.h @@ -0,0 +1,7 @@ +#ifndef __NAMESPACES_H +#define __NAMESPACES_H + +pool_t namespaces_init(void); +void namespaces_deinit(void); + +#endif /* __MAIL_RAW_H */ diff --git a/src/testsuite/tests/testsuite.sieve b/src/testsuite/tests/testsuite.sieve new file mode 100644 index 0000000000000000000000000000000000000000..4d05ffc3a7c0f850eeee61cbde86c25d8e1b736d --- /dev/null +++ b/src/testsuite/tests/testsuite.sieve @@ -0,0 +1,12 @@ +require "vnd.dovecot.testsuite"; + +test_message text: +From: sirius@rename-it.nl +To: nico@vestingbar.nl +Subject: Frop! + +Frop! +. +; + +keep; diff --git a/src/testsuite/testsuite b/src/testsuite/testsuite new file mode 100755 index 0000000000000000000000000000000000000000..1ca190549a46153e848c26e08711ab46d1eb5248 Binary files /dev/null and b/src/testsuite/testsuite differ diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h new file mode 100644 index 0000000000000000000000000000000000000000..5cc7e5a66add76e18cbf46a928afe070ffbd439b --- /dev/null +++ b/src/testsuite/testsuite-common.h @@ -0,0 +1,8 @@ +#ifndef __EXT_TESTSUITE_COMMON_H +#define __EXT_TESTSUITE_COMMON_H + +extern const struct sieve_extension testsuite_extension; + +extern int ext_testsuite_my_id; + +#endif diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c new file mode 100644 index 0000000000000000000000000000000000000000..bb7c6184d483383c11ad2d0a8e84afd8ab1a51f2 --- /dev/null +++ b/src/testsuite/testsuite.c @@ -0,0 +1,257 @@ +/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "ostream.h" +#include "mail-storage.h" + +#include "mail-raw.h" +#include "namespaces.h" +#include "sieve.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" +#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" + +#include "lib.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "ostream.h" +#include "hostpid.h" +#include "mail-storage.h" + +#include "sieve.h" +#include "sieve-extensions.h" + +#include "testsuite-common.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <pwd.h> + +/* Functionality common to all sieve test binaries */ + +/* FIXME: this file is currently very messy */ + +static struct ioloop *ioloop; + +static void sig_die(int signo, void *context ATTR_UNUSED) +{ + /* warn about being killed because of some signal, except SIGINT (^C) + which is too common at least while testing :) */ + if (signo != SIGINT) + i_warning("Killed with signal %d", signo); + // io_loop_stop(ioloop); We are not running an ioloop + exit(1); +} + +static void testsuite_init(void) +{ + lib_init(); + ioloop = io_loop_create(); + + lib_signals_init(); + lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL); + lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL); + lib_signals_ignore(SIGPIPE, TRUE); + lib_signals_ignore(SIGALRM, FALSE); + + if ( !sieve_init("") ) + i_fatal("Failed to initialize sieve implementation\n"); + + sieve_extension_register(&testsuite_extension); +} + +static void testsuite_deinit(void) +{ + sieve_deinit(); + + lib_signals_deinit(); + + io_loop_destroy(&ioloop); + lib_deinit(); +} + +static const char *_get_user(void) +{ + uid_t process_euid = geteuid(); + struct passwd *pw = getpwuid(process_euid); + if (pw != NULL) { + return t_strdup(pw->pw_name); + } + + i_fatal("Couldn't lookup our username (uid=%s)", dec2str(process_euid)); + return NULL; +} + +static struct sieve_binary *_compile_sieve_script(const char *filename) +{ + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + + ehandler = sieve_stderr_ehandler_create(); + sieve_error_handler_accept_infolog(ehandler, TRUE); + + if ( (sbin = sieve_compile(filename, ehandler)) == NULL ) { + sieve_error_handler_unref(&ehandler); + i_fatal("Failed to compile sieve script\n"); + } + + sieve_error_handler_unref(&ehandler); + + return sbin; +} + +static void _dump_sieve_binary_to(struct sieve_binary *sbin, const char *filename) +{ + int dfd = -1; + struct ostream *dumpstream; + + if ( filename == NULL ) return; + + if ( strcmp(filename, "-") == 0 ) + dumpstream = o_stream_create_fd(1, 0, FALSE); + else { + if ( (dfd = open(filename, O_WRONLY | O_CREAT)) < 0 ) { + i_fatal("Failed to open dump-file for writing: %m"); + exit(1); + } + + dumpstream = o_stream_create_fd(dfd, 0, FALSE); + } + + if ( dumpstream != NULL ) { + (void) sieve_dump(sbin, dumpstream); + o_stream_destroy(&dumpstream); + } else { + i_fatal("Failed to create stream for sieve code dump."); + } + + if ( dfd != -1 ) + close(dfd); +} + +static void _fill_in_envelope + (struct mail *mail, const char **recipient, const char **sender) +{ + /* Get recipient address */ + if ( *recipient == NULL ) + (void)mail_get_first_header(mail, "Envelope-To", recipient); + if ( *recipient == NULL ) + (void)mail_get_first_header(mail, "To", recipient); + if ( *recipient == NULL ) + *recipient = "recipient@example.com"; + + /* Get sender address */ + if ( *sender == NULL ) + (void)mail_get_first_header(mail, "Return-path", sender); + if ( *sender == NULL ) + (void)mail_get_first_header(mail, "Sender", sender); + if ( *sender == NULL ) + (void)mail_get_first_header(mail, "From", sender); + if ( *sender == NULL ) + *sender = "sender@example.com"; +} + +static void print_help(void) +{ + printf( +"Usage: testsuite [-d <dump filename>] <scriptfile>\n" + ); +} + +static const char *message_data = +"From: stephan@rename-it.nl\n" +"To: sirius@drunksnipers.com\n" +"Subject: Frop!\n" +"\n" +"Friep!\n"; + +int main(int argc, char **argv) +{ + const char *scriptfile, *dumpfile, *recipient, *sender; + const char *user; + int i; + pool_t namespaces_pool; + struct mail_raw *mailr; + struct sieve_binary *sbin; + struct sieve_message_data msgdata; + struct sieve_script_env scriptenv; + struct sieve_error_handler *ehandler; + string_t *mail_buffer; + + testsuite_init(); + + mail_buffer = t_str_new(1024); + str_append(mail_buffer, message_data); + + /* Parse arguments */ + scriptfile = dumpfile = recipient = sender = NULL; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-d") == 0) { + /* dump file */ + i++; + if (i == argc) + i_fatal("Missing -d argument"); + dumpfile = argv[i]; + } else if ( scriptfile == NULL ) { + scriptfile = argv[i]; + } else { + print_help(); + i_fatal("Unknown argument: %s", argv[i]); + } + } + + if ( scriptfile == NULL ) { + print_help(); + i_fatal("Missing <scriptfile> argument"); + } + + /* Compile sieve script */ + sbin = _compile_sieve_script(scriptfile); + + /* Dump script */ + _dump_sieve_binary_to(sbin, dumpfile); + + user = _get_user(); + + namespaces_pool = namespaces_init(); + mail_raw_init(namespaces_pool, user); + mailr = mail_raw_open(mail_buffer); + + _fill_in_envelope(mailr->mail, &recipient, &sender); + + /* Collect necessary message data */ + memset(&msgdata, 0, sizeof(msgdata)); + msgdata.mail = mailr->mail; + msgdata.return_path = recipient; + msgdata.to_address = sender; + msgdata.auth_user = user; + (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); + + memset(&scriptenv, 0, sizeof(scriptenv)); + scriptenv.inbox = "INBOX"; + scriptenv.username = user; + + ehandler = sieve_stderr_ehandler_create(); + + /* Run the test */ + (void) sieve_test(sbin, &msgdata, &scriptenv, ehandler); + + sieve_close(&sbin); + sieve_error_handler_unref(&ehandler); + + mail_raw_close(mailr); + mail_raw_deinit(); + namespaces_deinit(); + + testsuite_deinit(); + + return 0; +}