diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | defconfig | 6 | ||||
-rw-r--r-- | signature-log.c | 143 |
3 files changed, 151 insertions, 2 deletions
@@ -9,6 +9,7 @@ CFLAGS += -I$(DOVECOT)/src/lib/ CFLAGS += -I$(DOVECOT)/src/lib-storage/ CFLAGS += -I$(DOVECOT)/src/lib-mail/ CFLAGS += -I$(DOVECOT)/src/lib-imap/ +CFLAGS += -I$(DOVECOT)/src/lib-dict/ CFLAGS += -I$(DOVECOT)/src/imap/ # debug rules @@ -33,6 +34,9 @@ endif ifeq ("$(BACKEND)", "dspam-exec") objs += signature.o endif +ifeq ("$(BACKEND)", "signature-log") +objs += signature.o +endif # main make rules CFLAGS += -fPIC -shared -Wall @@ -24,8 +24,10 @@ DOVECOT_VERSION=1.0 #DOVECOT_VERSION=1.1 # CURRENTLY BROKEN # backend -# - dspam-exec: direct dspam training by calling dspam executable -BACKEND=dspam-exec +# dspam-exec - direct dspam training by calling dspam executable +# signature-log - signature logging using dovecot's dict API +#BACKEND=dspam-exec +BACKEND=signature-log # install directory for 'make install' diff --git a/signature-log.c b/signature-log.c new file mode 100644 index 0000000..bddca5b --- /dev/null +++ b/signature-log.c @@ -0,0 +1,143 @@ +/* + * signature logging backend for dovecot antispam plugin + * + * Copyright (C) 2007 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * A training implementation must still be written, it needs, to be atomic, + * use transactions to get a list of all values and delete them at the same + * time, or use a temporary table that is copied from the original while the + * original is emptied (again, atomically) + */ + +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <fcntl.h> + +#include "lib.h" +#include "dict.h" +#include "mail-storage-private.h" + +#include "antispam-plugin.h" +#include "signature.h" + +static const char *dict_uri = NULL; +static const char *dict_user = NULL; + +struct antispam_transaction_context { + struct dict *dict; + struct dict_transaction_context *dict_ctx; +}; + +struct antispam_transaction_context *backend_start(struct mailbox *box) +{ + struct antispam_transaction_context *ast; + + ast = i_new(struct antispam_transaction_context, 1); + + ast->dict = dict_init(dict_uri, dict_user); + + /* see comment below */ +// if (ast->dict) +// ast->dict_ctx = dict_transaction_begin(ast->dict); + return ast; +} + +void backend_rollback(struct antispam_transaction_context *ast) +{ + if (ast->dict) { +// dict_transaction_rollback(ast->dict_ctx); + dict_deinit(&ast->dict); + } + + i_free(ast); +} + +int backend_commit(struct mailbox_transaction_context *ctx, + struct antispam_transaction_context *ast) +{ + int ret = 0; + + if (ast->dict) { + ret = 0; +// ret = dict_transaction_commit(ast->dict_ctx); + dict_deinit(&ast->dict); + } + i_free(ast); + + return ret; +} + +int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, bool from_spam) +{ + const char *signature; + int ret; + + if (!ast->dict) { + mail_storage_set_error(t->box->storage, + "Failed to initialise dict connection"); + return -1; + } + + signature = signature_extract(t, mail); + + /* + * We really should have a global transaction as implemented + * by the code that is commented out with C99 comments (//). + * However, this breaks because + * (1) sqlite cannot nest transactions + * (2) the dict proxy keeps only a single connection open + * (3) we here have a transaction per mailbox which makes two + * when moving messages (we might be able to hack around + * this but it's not trivial) + */ + ast->dict_ctx = dict_transaction_begin(ast->dict); + signature = t_strconcat("priv/", signature, NULL); + dict_atomic_inc(ast->dict_ctx, signature, from_spam ? -1 : 1); + ret = dict_transaction_commit(ast->dict_ctx); + if (ret) + mail_storage_set_error(t->box->storage, + "Failed to count signature"); + + return ret; +} + +void backend_init(pool_t pool) +{ + char *tmp; + + tmp = getenv("ANTISPAM_SIGLOG_DICT_URI"); + if (tmp) { + dict_uri = tmp; + debug("antispam: signature logger dict URI set to %s\n", tmp); + } + + tmp = getenv("ANTISPAM_SIGLOG_DICT_USER"); + if (tmp) { + dict_user = tmp; + debug("antispam: signature logger dict user set to %s\n", tmp); + } + + signature_init(); +} + +void backend_exit(void) +{ +} |