1 diff --git a/antispam-plugin.c b/antispam-plugin.c
2 index 7756204..76ced7b 100644
3 --- a/antispam-plugin.c
4 +++ b/antispam-plugin.c
5 @@ -90,7 +90,7 @@ static bool mailbox_patternmatch(struct mailbox *box,
12 boxname = mailbox_get_name(box);
14 @@ -110,7 +110,7 @@ static bool mailbox_patternmatch(struct mailbox *box,
16 rc = memcmp(name, boxname, len) == 0;
23 @@ -257,7 +257,7 @@ static int parse_folder_setting(const struct antispam_config *cfg,
30 for (i = 0; i < NUM_MT; ++i) {
31 tmp = getenv(t_strconcat(setting, match_info[i].suffix, NULL),
32 @@ -286,7 +286,7 @@ static int parse_folder_setting(const struct antispam_config *cfg,
40 debug(&cfg->dbgcfg, "no %s folders\n", display_name);
41 @@ -392,4 +392,8 @@ void PLUGIN_FUNCTION(deinit)(void)
44 /* put dovecot version we built against into plugin for checking */
45 +#if DOVECOT_IS_GE(2,2)
46 +const char *PLUGIN_FUNCTION(version) = DOVECOT_ABI_VERSION;
48 const char *PLUGIN_FUNCTION(version) = PACKAGE_VERSION;
50 diff --git a/antispam-plugin.h b/antispam-plugin.h
51 index 280bb12..62a3eb3 100644
52 --- a/antispam-plugin.h
53 +++ b/antispam-plugin.h
59 #include "imap-search.h"
62 @@ -43,6 +42,7 @@ struct signature_config {
65 struct antispam_debug_config {
67 enum antispam_debug_target target;
70 @@ -98,8 +98,10 @@ struct antispam_config {
74 - const char *spam_arg;
75 - const char *ham_arg;
80 const char *pipe_binary;// = "/usr/sbin/sendmail";
81 const char *tmpdir;// = "/tmp";
83 @@ -204,12 +206,6 @@ o_stream_create_from_fd(int fd, pool_t pool)
84 return o_stream_create_file(fd, pool, 0, TRUE);
87 -static inline struct dict *
88 -string_dict_init(const char *uri, const char *username)
90 - return dict_init(uri, username);
93 static inline int _mail_get_stream(struct mail *mail,
94 struct message_size *hdr_size,
95 struct message_size *body_size,
96 @@ -222,6 +218,11 @@ static inline int _mail_get_stream(struct mail *mail,
99 #define mail_get_stream _mail_get_stream
102 + STMT_START { t_push();
104 + t_pop(); } STMT_END
105 #elif DOVECOT_IS_EQ(1, 1)
106 #define mempool_unref pool_unref
107 #define module_arg void
108 @@ -231,7 +232,7 @@ static inline const char *const *
109 get_mail_headers(struct mail *mail, const char *hdr)
111 const char *const *ret;
112 - if (mail_get_headers(mail, hdr, &ret))
113 + if (mail_get_headers(mail, hdr, &ret) < 0)
117 @@ -250,7 +251,7 @@ static inline const char *const *
118 get_mail_headers(struct mail *mail, const char *hdr)
120 const char *const *ret;
121 - if (mail_get_headers(mail, hdr, &ret))
122 + if (mail_get_headers(mail, hdr, &ret) < 0)
126 @@ -260,7 +261,7 @@ o_stream_create_from_fd(int fd, pool_t pool ATTR_UNUSED)
128 return o_stream_create_fd(fd, 0, TRUE);
130 -#elif DOVECOT_IS_EQ(2, 0)
131 +#elif DOVECOT_IS_EQ(2, 0) || DOVECOT_IS_EQ(2, 1) || DOVECOT_IS_EQ(2, 2)
132 #define mempool_unref pool_unref
133 #define module_arg struct module *
134 #define ME(err) MAIL_ERROR_ ##err,
135 @@ -269,7 +270,7 @@ static inline const char *const *
136 get_mail_headers(struct mail *mail, const char *hdr)
138 const char *const *ret;
139 - if (mail_get_headers(mail, hdr, &ret))
140 + if (mail_get_headers(mail, hdr, &ret) < 0)
144 @@ -279,12 +280,6 @@ o_stream_create_from_fd(int fd, pool_t pool ATTR_UNUSED)
146 return o_stream_create_fd(fd, 0, TRUE);
149 -static inline struct dict *
150 -string_dict_init(const char *uri, const char *username)
152 - return dict_init(uri, DICT_DATA_TYPE_STRING, username, NULL);
155 #error "Building against this dovecot version is not supported"
157 diff --git a/antispam-storage-1.1.c b/antispam-storage-1.1.c
158 index f28a0cf..aab23d9 100644
159 --- a/antispam-storage-1.1.c
160 +++ b/antispam-storage-1.1.c
161 @@ -508,10 +508,10 @@ void antispam_mail_storage_created(struct mail_storage *storage)
163 static const char *_getenv(const char *env, void *data ATTR_UNUSED)
167 env = t_str_ucase(t_strconcat("antispam_", env, NULL));
174 diff --git a/antispam-storage-1.2.c b/antispam-storage-1.2.c
175 index 5e0cb97..269a373 100644
176 --- a/antispam-storage-1.2.c
177 +++ b/antispam-storage-1.2.c
178 @@ -498,10 +498,10 @@ void antispam_mail_storage_created(struct mail_storage *storage)
180 static const char *_getenv(const char *env, void *data ATTR_UNUSED)
184 env = t_str_ucase(t_strconcat("antispam_", env, NULL));
191 diff --git a/antispam-storage-2.0.c b/antispam-storage-2.0.c
192 index 5a089bc..c3d6251 100644
193 --- a/antispam-storage-2.0.c
194 +++ b/antispam-storage-2.0.c
195 @@ -472,7 +472,7 @@ static void antispam_mailbox_allocated(struct mailbox *box)
197 asbox->save_hack = FALSE;
198 asbox->movetype = MMT_APPEND;
199 - asbox->cfg = asuser->cfg;
200 + asbox->cfg = asuser->cfg;
202 v->free = antispam_mailbox_free;
204 @@ -494,11 +494,11 @@ static const char *_getenv(const char *name, void *data)
205 struct mail_user *user = data;
210 env = t_strconcat("antispam_", t_str_lcase(name), NULL);
212 env = mail_user_plugin_getenv(user, env);
218 diff --git a/antispam.7 b/antispam.7
219 index 5e33e4c..497da58 100644
223 -.TH ANTISPAM 7 "15 October 2007" "" ""
224 +.TH ANTISPAM 7 "24 March 2012" "" ""
226 antispam \- The dovecot antispam plugin.
228 @@ -120,6 +120,9 @@ plugin {
229 # antispam_debug_target = syslog
230 # antispam_debug_target = stderr
231 # antispam_verbose_debug = 1
233 + # This can be used to get a prefix, e.g. by specifying %u in it
234 + # antispam_debug_prefix = "antispam: "
236 # backend selection, MUST be configured first,
237 # there's no default so you need to set one of
238 @@ -206,6 +209,11 @@ plugin {
239 # semicolon-separated list of blacklisted results, case insensitive
240 # antispam_dspam_result_blacklist = Virus
242 + # semicolon-separated list of environment variables to set
243 + # (default unset i.e. none)
244 + # antispam_dspam_env =
245 + # antispam_dspam_env = HOME=%h;USER=%u
247 #=====================
250 @@ -228,6 +236,14 @@ plugin {
251 # "mailtrain" are still valid, these are, in the same order as
252 # above: antispam_mail_sendmail, antispam_mail_sendmail_args,
253 # antispam_mail_spam, antispam_mail_notspam and antispam_mail_tmpdir.
255 + # Alternatively, if you need to give multiple options, you can use
256 + # the spam_args/notspam_args parameters (which are used in preference
257 + # of the singular form):
258 + # antispam_pipe_program_spam_args = --spam;--my-other-param1
259 + # antispam_pipe_program_notspam_args = --ham;--my-other-param2
260 + # which will then call
261 + # /path/to/mailtrain --for jberg --spam --my-other-param1
263 # temporary directory
264 antispam_pipe_tmpdir = /tmp
265 @@ -247,7 +263,7 @@ plugin {
266 antispam_crm_binary = /bin/false
267 # antispam_crm_binary = /usr/share/crm114/mailreaver.crm
269 - # semicolon-separated list of extra arguments to dspam
270 + # semicolon-separated list of extra arguments to crm114
271 # (default unset i.e. none)
272 # antispam_crm_args =
273 # antispam_crm_args = --config=/path/to/config
274 @@ -257,11 +273,6 @@ plugin {
276 # antispam_crm_env = HOME=%h;USER=%u
278 - # semicolon-separated list of environment variables to set
279 - # (default unset i.e. none)
280 - # antispam_dspam_env =
281 - # antispam_dspam_env = HOME=%h;USER=%u
283 # NOTE: you need to set the signature for this backend
284 antispam_signature = X-CRM114-CacheID
286 diff --git a/crm114-exec.c b/crm114-exec.c
287 index 5b39ca9..d786e04 100644
290 @@ -113,7 +113,7 @@ static int call_reaver(const struct antispam_config *cfg,
292 debugv(&cfg->dbgcfg, argv);
296 for (i = 0; i < cfg->crm.extra_env_num; i++) {
298 name = t_strdup_noconst(cfg->crm.extra_env[i]);
299 @@ -124,7 +124,7 @@ static int call_reaver(const struct antispam_config *cfg,
301 setenv(name, value, 1);
306 execv(cfg->crm.reaver_binary, argv);
307 /* fall through if reaver can't be found */
308 diff --git a/debug.c b/debug.c
309 index d2683fa..77f0167 100644
317 @@ -14,9 +13,9 @@ static void _debug(const struct antispam_debug_config *cfg,
318 if (cfg->target == ADT_NONE)
324 - fmt = t_strconcat("antispam: ", format, NULL);
325 + fmt = t_strconcat(cfg->prefix, format, NULL);
327 switch (cfg->target) {
329 @@ -30,7 +29,7 @@ static void _debug(const struct antispam_debug_config *cfg,
337 void debug(const struct antispam_debug_config *cfg, const char *fmt, ...)
338 @@ -48,7 +47,7 @@ void debugv(const struct antispam_debug_config *cfg, char **args)
344 buf = t_buffer_get(buflen);
347 @@ -72,7 +71,7 @@ void debugv(const struct antispam_debug_config *cfg, char **args)
350 debug(cfg, "%s", buf);
355 void debugv_not_stderr(const struct antispam_debug_config *cfg, char **args)
356 @@ -111,6 +110,10 @@ int debug_init(struct antispam_debug_config *cfg,
360 + cfg->prefix = getenv("DEBUG_PREFIX", getenv_data);
362 + cfg->prefix = "antispam: ";
364 debug(cfg, "plugin initialising (%s)\n", ANTISPAM_VERSION);
366 tmp = getenv("VERBOSE_DEBUG", getenv_data);
367 diff --git a/dovecot-version.c b/dovecot-version.c
368 index cbcb35b..fe9bc73 100644
369 --- a/dovecot-version.c
370 +++ b/dovecot-version.c
378 int main(int argc, char **argv)
379 @@ -17,21 +18,24 @@ int main(int argc, char **argv)
381 maj = strtol(v, &e, 10);
388 min = strtol(v, &e, 10);
393 /* not end of string yet? */
397 - patch = strtol(v, &e, 10);
401 + patch = strtol(v, &e, 10);
408 printf("/* Auto-generated file, do not edit */\n\n");
409 @@ -40,6 +44,8 @@ int main(int argc, char **argv)
411 printf("#define DOVECOT_VCODE "
412 "0x%.2x%.2x%.2x\n", maj, min, 0);
413 + printf("#define DOVECOT_VCODE_PATCH "
414 + "0x%.2x%.2x%.2x\n", maj, min, patch);
415 printf("#define DOVECOT_IS_EQ(maj, min) "
416 "DOVECOT_VCODE == DOVECOT_VERSION_CODE(maj, min, 0)\n");
417 printf("#define DOVECOT_IS_GT(maj, min) "
418 @@ -50,6 +56,22 @@ int main(int argc, char **argv)
419 "DOVECOT_VCODE < DOVECOT_VERSION_CODE(maj, min, 0)\n");
420 printf("#define DOVECOT_IS_LE(maj, min) "
421 "DOVECOT_VCODE <= DOVECOT_VERSION_CODE(maj, min, 0)\n");
423 + printf("#define DOVECOT_P_IS_EQ(maj, min, patch) "
424 + "DOVECOT_VCODE_PATCH == DOVECOT_VERSION_CODE(maj, min, patch)\n");
425 + printf("#define DOVECOT_P_IS_GT(maj, min, patch) "
426 + "DOVECOT_VCODE_PATCH > DOVECOT_VERSION_CODE(maj, min, patch)\n");
427 + printf("#define DOVECOT_P_IS_GE(maj, min, patch) "
428 + "DOVECOT_VCODE_PATCH >= DOVECOT_VERSION_CODE(maj, min, patch)\n");
429 + printf("#define DOVECOT_P_IS_LT(maj, min, patch) "
430 + "DOVECOT_VCODE_PATCH < DOVECOT_VERSION_CODE(maj, min, patch)\n");
431 + printf("#define DOVECOT_P_IS_LE(maj, min, patch) "
432 + "DOVECOT_VCODE_PATCH <= DOVECOT_VERSION_CODE(maj, min, patch)\n");
434 + /* Use the antispam-storage-2.0.c for dovecot 2.1 and 2.2 as well */
435 + if (maj == 2 && min < 3)
438 printf("#define ANTISPAM_STORAGE "
439 "\"antispam-storage-%d.%d.c\"\n", maj, min);
441 diff --git a/dspam-exec.c b/dspam-exec.c
442 index 2e353ce..856babb 100644
445 @@ -141,7 +141,7 @@ static int call_dspam(const struct antispam_config *cfg,
447 debugv_not_stderr(&cfg->dbgcfg, argv);
451 for (i = 0; i < cfg->dspam.extra_env_num; i++) {
453 name = t_strdup_noconst(cfg->dspam.extra_env[i]);
454 @@ -152,7 +152,7 @@ static int call_dspam(const struct antispam_config *cfg,
456 setenv(name, value, 1);
461 execv(cfg->dspam.binary, argv);
462 debug(&cfg->dbgcfg, "executing %s failed: %d (uid=%d, gid=%d)",
463 diff --git a/pipe.c b/pipe.c
464 index 18c2233..f9abef5 100644
468 static int run_pipe(const struct antispam_config *cfg,
469 int mailfd, enum classification wanted)
479 - dest = cfg->pipe.spam_arg;
480 + dest = cfg->pipe.spam_args;
481 + dest_num = cfg->pipe.spam_args_num;
484 - dest = cfg->pipe.ham_arg;
485 + dest = cfg->pipe.ham_args;
486 + dest_num = cfg->pipe.ham_args_num;
490 @@ -65,18 +68,23 @@ static int run_pipe(const struct antispam_config *cfg,
491 return WEXITSTATUS(status);
494 - int sz = sizeof(char *) * (2 + cfg->pipe.extra_args_num + 1);
496 + int sz = sizeof(char *) * (2 + cfg->pipe.extra_args_num + dest_num + 1);
502 argv[0] = (char *) cfg->pipe.pipe_binary;
504 - for (i = 0; i < cfg->pipe.extra_args_num; i++)
505 + for (i = 0; i < cfg->pipe.extra_args_num; i++) {
506 argv[i + 1] = (char *) cfg->pipe.extra_args[i];
507 + debug(&cfg->dbgcfg, "running mailtrain backend program parameter %d %s", i + 1, argv[i + 1]);
510 - argv[i + 1] = (char *) dest;
511 + for (j = 0; j < dest_num; j++) {
512 + argv[i + 1 + j] = (char *) dest[j];
513 + debug(&cfg->dbgcfg, "running mailtrain backend program parameter %d %s", i + 1 + j, argv[i + 1 + j]);
517 fd = open("/dev/null", O_WRONLY);
518 @@ -128,7 +136,7 @@ static int process_tmpdir(const struct antispam_config *cfg,
519 enum classification wanted;
525 buf = t_malloc(20 + ast->tmplen);
527 @@ -151,7 +159,7 @@ static int process_tmpdir(const struct antispam_config *cfg,
536 @@ -160,7 +168,7 @@ static void clear_tmpdir(struct antispam_transaction_context *ast)
543 buf = t_malloc(20 + ast->tmplen);
545 @@ -172,7 +180,7 @@ static void clear_tmpdir(struct antispam_transaction_context *ast)
553 static void backend_rollback(const struct antispam_config *cfg ATTR_UNUSED,
554 @@ -228,7 +236,7 @@ static int backend_handle_mail(const struct antispam_config *cfg,
558 - if (!cfg->pipe.ham_arg || !cfg->pipe.spam_arg) {
559 + if (!cfg->pipe.ham_args || !cfg->pipe.spam_args) {
560 mail_storage_set_error(t->box->storage,
562 "antispam plugin not configured");
563 @@ -242,7 +250,7 @@ static int backend_handle_mail(const struct antispam_config *cfg,
570 buf = t_malloc(20 + ast->tmplen);
571 i_snprintf(buf, 20 + ast->tmplen - 1, "%s/%d", ast->tmpdir, ast->count);
572 @@ -303,8 +311,8 @@ static int backend_handle_mail(const struct antispam_config *cfg,
573 o_stream_destroy(&outstream);
583 @@ -316,20 +324,50 @@ static void backend_init(struct antispam_config *cfg,
587 - tmp = getenv("PIPE_PROGRAM_SPAM_ARG", getenv_data);
589 - tmp = getenv("MAIL_SPAM", getenv_data);
590 + tmp = getenv("PIPE_PROGRAM_SPAM_ARGS", getenv_data);
592 - cfg->pipe.spam_arg = tmp;
593 - debug(&cfg->dbgcfg, "pipe backend spam argument = %s\n", tmp);
594 + cfg->pipe.spam_args = p_strsplit(cfg->mem_pool, tmp, ";");
595 + cfg->pipe.spam_args_num = str_array_length(
596 + (const char *const *)cfg->pipe.spam_args);
597 + for (i = 0; i < cfg->pipe.spam_args_num; i++)
598 + debug(&cfg->dbgcfg, "pipe backend spam arg[%d] = %s\n",
599 + i, cfg->pipe.spam_args[i]);
601 + tmp = getenv("PIPE_PROGRAM_SPAM_ARG", getenv_data);
603 + tmp = getenv("MAIL_SPAM", getenv_data);
605 + /* bit of a hack */
606 + cfg->pipe.spam_args =
607 + p_strsplit(cfg->mem_pool, tmp, "\x01");
608 + cfg->pipe.spam_args_num = 1;
609 + debug(&cfg->dbgcfg,
610 + "pipe backend spam argument = %s\n", tmp);
615 - tmp = getenv("PIPE_PROGRAM_NOTSPAM_ARG", getenv_data);
617 - tmp = getenv("MAIL_NOTSPAM", getenv_data);
618 + tmp = getenv("PIPE_PROGRAM_NOTSPAM_ARGS", getenv_data);
620 - cfg->pipe.ham_arg = tmp;
621 - debug(&cfg->dbgcfg, "pipe backend not-spam argument = %s\n", tmp);
622 + cfg->pipe.ham_args = p_strsplit(cfg->mem_pool, tmp, ";");
623 + cfg->pipe.ham_args_num = str_array_length(
624 + (const char *const *)cfg->pipe.ham_args);
625 + for (i = 0; i < cfg->pipe.ham_args_num; i++)
626 + debug(&cfg->dbgcfg, "pipe backend ham arg[%d] = %s\n",
627 + i, cfg->pipe.ham_args[i]);
629 + tmp = getenv("PIPE_PROGRAM_NOTSPAM_ARG", getenv_data);
631 + tmp = getenv("MAIL_NOTSPAM", getenv_data);
633 + /* bit of a hack */
634 + cfg->pipe.ham_args =
635 + p_strsplit(cfg->mem_pool, tmp, "\x01");
636 + cfg->pipe.ham_args_num = 1;
637 + debug(&cfg->dbgcfg,
638 + "pipe backend not-spam argument = %s\n", tmp);
643 tmp = getenv("PIPE_PROGRAM", getenv_data);
644 diff --git a/spool2dir.c b/spool2dir.c
645 index cbd1909..d304716 100644
648 @@ -165,7 +165,7 @@ static int backend_handle_mail(const struct antispam_config *cfg,
655 /* atomically create a _new_ file */
656 while (ast->count <= 9999) {
657 @@ -174,9 +174,6 @@ static int backend_handle_mail(const struct antispam_config *cfg,
658 if (fd >= 0 || errno != EEXIST)
660 /* current filename in buf already exists, zap it */
663 - /* buf is invalid now! */
667 @@ -225,8 +222,8 @@ static int backend_handle_mail(const struct antispam_config *cfg,