Mercurial > dovecot > core-2.2
view src/plugins/mail-filter/mail-filter-plugin.c @ 18137:3009a1a6f6d5
global: freshen copyright
Robomatically:
git ls-files | xargs perl -p -i -e 's/(\d+)-201[0-4]/$1-2015/g;s/ (201[0-4]) Dovecot/ $1-2015 Dovecot/'
Happy 2015 everyone!
Signed-off-by: Phil Carmody <phil@dovecot.fi>
author | Phil Carmody <phil@dovecot.fi> |
---|---|
date | Mon, 05 Jan 2015 22:20:10 +0200 |
parents | add8c00fb3cc |
children | fefaa6d09a81 |
line wrap: on
line source
/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "str.h" #include "safe-mkstemp.h" #include "mail-user.h" #include "mail-storage-private.h" #include "istream.h" #include "istream-seekable.h" #include "istream-ext-filter.h" #include "ostream-ext-filter.h" #include "mail-filter-plugin.h" /* After buffer grows larger than this, create a temporary file to /tmp where to read the mail. */ #define MAIL_MAX_MEMORY_BUFFER (1024*128) #define MAIL_FILTER_MAIL_CONTEXT(obj) \ MODULE_CONTEXT(obj, mail_filter_mail_module) #define MAIL_FILTER_CONTEXT(obj) \ MODULE_CONTEXT(obj, mail_filter_storage_module) #define MAIL_FILTER_USER_CONTEXT(obj) \ MODULE_CONTEXT(obj, mail_filter_user_module) struct mail_filter_user { union mail_user_module_context module_ctx; const char *socket_path, *args; const char *out_socket_path, *out_args; }; const char *mail_filter_plugin_version = DOVECOT_ABI_VERSION; static MODULE_CONTEXT_DEFINE_INIT(mail_filter_user_module, &mail_user_module_register); static MODULE_CONTEXT_DEFINE_INIT(mail_filter_storage_module, &mail_storage_module_register); static MODULE_CONTEXT_DEFINE_INIT(mail_filter_mail_module, &mail_module_register); static int mail_filter_mail_save_begin(struct mail_save_context *ctx, struct istream *input) { struct mailbox *box = ctx->transaction->box; struct mail_filter_user *muser = MAIL_FILTER_USER_CONTEXT(box->storage->user); union mailbox_module_context *mbox = MAIL_FILTER_CONTEXT(box); struct ostream *output; if (mbox->super.save_begin(ctx, input) < 0) return -1; output = o_stream_create_ext_filter(ctx->data.output, muser->out_socket_path, muser->out_args); ctx->data.output = output; return 0; } static int seekable_fd_callback(const char **path_r, void *context) { struct mail_user *user = context; string_t *path; int fd; path = t_str_new(128); mail_user_set_get_temp_prefix(path, user->set); fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1); if (fd == -1) { i_error("safe_mkstemp(%s) failed: %m", str_c(path)); return -1; } /* we just want the fd, unlink it */ if (unlink(str_c(path)) < 0) { /* shouldn't happen.. */ i_error("unlink(%s) failed: %m", str_c(path)); i_close_fd(&fd); return -1; } *path_r = str_c(path); return fd; } static int mail_filter_istream_opened(struct mail *_mail, struct istream **stream) { struct mail_private *mail = (struct mail_private *)_mail; struct mail_user *user = _mail->box->storage->user; struct mail_filter_user *muser = MAIL_FILTER_USER_CONTEXT(user); union mail_module_context *mmail = MAIL_FILTER_MAIL_CONTEXT(mail); struct istream *input, *inputs[2]; input = *stream; *stream = i_stream_create_ext_filter(input, muser->socket_path, muser->args); i_stream_unref(&input); inputs[0] = *stream; inputs[1] = NULL; *stream = i_stream_create_seekable(inputs, MAIL_MAX_MEMORY_BUFFER, seekable_fd_callback, user); i_stream_unref(&inputs[0]); return mmail->super.istream_opened(_mail, stream); } static void mail_filter_mailbox_allocated(struct mailbox *box) { struct mailbox_vfuncs *v = box->vlast; struct mail_filter_user *muser = MAIL_FILTER_USER_CONTEXT(box->storage->user); union mailbox_module_context *mbox; enum mail_storage_class_flags class_flags = box->storage->class_flags; mbox = p_new(box->pool, union mailbox_module_context, 1); mbox->super = *v; box->vlast = &mbox->super; MODULE_CONTEXT_SET_SELF(box, mail_filter_storage_module, mbox); if ((class_flags & MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0 && (class_flags & MAIL_STORAGE_CLASS_FLAG_BINARY_DATA) != 0 && muser->out_socket_path != NULL) v->save_begin = mail_filter_mail_save_begin; } static void mail_filter_mail_allocated(struct mail *_mail) { struct mail_private *mail = (struct mail_private *)_mail; struct mail_filter_user *muser = MAIL_FILTER_USER_CONTEXT(_mail->box->storage->user); struct mail_vfuncs *v = mail->vlast; union mail_module_context *mmail; mmail = p_new(mail->pool, union mail_module_context, 1); mmail->super = *v; mail->vlast = &mmail->super; if (muser->socket_path != NULL) v->istream_opened = mail_filter_istream_opened; MODULE_CONTEXT_SET_SELF(mail, mail_filter_mail_module, mmail); } static void mail_filter_parse_setting(struct mail_user *user, const char *name, const char **socket_path_r, const char **args_r) { const char *value, *p; value = mail_user_plugin_getenv(user, name); if (value == NULL) return; p = strchr(value, ' '); if (p == NULL) { *socket_path_r = p_strdup(user->pool, value); *args_r = ""; } else { *socket_path_r = p_strdup_until(user->pool, value, p); *args_r = p_strdup(user->pool, p + 1); } if (**socket_path_r != '/') { /* relative to base_dir */ *socket_path_r = p_strdup_printf(user->pool, "%s/%s", user->set->base_dir, *socket_path_r); } if (user->mail_debug) { i_debug("mail_filter: Filtering %s via socket %s", name, *socket_path_r); } } static void mail_filter_mail_user_created(struct mail_user *user) { struct mail_user_vfuncs *v = user->vlast; struct mail_filter_user *muser; muser = p_new(user->pool, struct mail_filter_user, 1); muser->module_ctx.super = *v; user->vlast = &muser->module_ctx.super; mail_filter_parse_setting(user, "mail_filter", &muser->socket_path, &muser->args); mail_filter_parse_setting(user, "mail_filter_out", &muser->out_socket_path, &muser->out_args); if (user->mail_debug && muser->socket_path == NULL && muser->out_socket_path == NULL) { i_debug("mail_filter and mail_filter_out settings missing, " "ignoring mail_filter plugin"); } MODULE_CONTEXT_SET(user, mail_filter_user_module, muser); } static struct mail_storage_hooks mail_filter_mail_storage_hooks = { .mail_user_created = mail_filter_mail_user_created, .mailbox_allocated = mail_filter_mailbox_allocated, .mail_allocated = mail_filter_mail_allocated }; void mail_filter_plugin_init(struct module *module) { mail_storage_hooks_add(module, &mail_filter_mail_storage_hooks); } void mail_filter_plugin_deinit(void) { mail_storage_hooks_remove(&mail_filter_mail_storage_hooks); }