From: Timo Sirainen Date: Mon, 20 Jun 2016 08:39:55 +0000 (+0300) Subject: Added welcome plugin. X-Git-Tag: 2.3.0.rc1~3445 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ba16a89e4e5afde0a1878a883741df3593dccf02;p=thirdparty%2Fdovecot%2Fcore.git Added welcome plugin. --- diff --git a/configure.ac b/configure.ac index 86bfb7ad5c..ef8312cc5d 100644 --- a/configure.ac +++ b/configure.ac @@ -917,6 +917,7 @@ src/plugins/stats/Makefile src/plugins/imap-stats/Makefile src/plugins/trash/Makefile src/plugins/virtual/Makefile +src/plugins/welcome/Makefile src/plugins/zlib/Makefile src/plugins/imap-zlib/Makefile stamp.h diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 7e0d00b17d..7dc31d954c 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -39,6 +39,7 @@ SUBDIRS = \ imap-stats \ trash \ virtual \ + welcome \ $(ZLIB) \ $(FTS_LUCENE) \ $(FTS_SOLR) \ diff --git a/src/plugins/welcome/Makefile.am b/src/plugins/welcome/Makefile.am new file mode 100644 index 0000000000..98968f5dc0 --- /dev/null +++ b/src/plugins/welcome/Makefile.am @@ -0,0 +1,14 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-index \ + -I$(top_srcdir)/src/lib-storage + +NOPLUGIN_LDFLAGS = +lib99_welcome_plugin_la_LDFLAGS = -module -avoid-version + +module_LTLIBRARIES = \ + lib99_welcome_plugin.la + +lib99_welcome_plugin_la_SOURCES = \ + welcome-plugin.c diff --git a/src/plugins/welcome/welcome-plugin.c b/src/plugins/welcome/welcome-plugin.c new file mode 100644 index 0000000000..a2ed80ed63 --- /dev/null +++ b/src/plugins/welcome/welcome-plugin.c @@ -0,0 +1,146 @@ +/* Copyright (c) 2015-2016 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "net.h" +#include "str.h" +#include "eacces-error.h" +#include "write-full.h" +#include "module-context.h" +#include "mail-storage-private.h" + +#define WELCOME_SOCKET_TIMEOUT_SECS 30 + +#define WELCOME_CONTEXT(obj) \ + MODULE_CONTEXT(obj, welcome_storage_module) + +struct welcome_mailbox { + union mailbox_module_context module_ctx; + bool created; +}; + +static MODULE_CONTEXT_DEFINE_INIT(welcome_storage_module, + &mail_storage_module_register); + +static void script_execute(struct mail_user *user, const char *cmd, bool wait) +{ + const char *socket_path, *const *args; + string_t *str; + char buf[1024]; + int fd, ret; + + if (user->mail_debug) + i_debug("welcome: Executing %s (wait=%d)", cmd, wait); + + args = t_strsplit_spaces(cmd, " "); + socket_path = args[0]; + args++; + + if (*socket_path != '/') { + socket_path = t_strconcat(user->set->base_dir, "/", + socket_path, NULL); + } + if ((fd = net_connect_unix_with_retries(socket_path, 1000)) < 0) { + if (errno == EACCES) { + i_error("welcome: %s", + eacces_error_get("net_connect_unix", + socket_path)); + } else { + i_error("welcome: net_connect_unix(%s) failed: %m", + socket_path); + } + return; + } + + str = t_str_new(1024); + str_append(str, "VERSION\tscript\t3\t0\n"); + if (!wait) + str_append(str, "noreply\n"); + else + str_append(str, "-\n"); + for (; *args != NULL; args++) { + str_append(str, *args); + str_append_c(str, '\n'); + } + str_append_c(str, '\n'); + + alarm(WELCOME_SOCKET_TIMEOUT_SECS); + net_set_nonblock(fd, FALSE); + if (write_full(fd, str_data(str), str_len(str)) < 0) + i_error("write(%s) failed: %m", socket_path); + else if (wait) { + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + i_error("welcome: read(%s) failed: %m", socket_path); + else if (ret < 2) + i_error("welcome: %s failed: Only %d bytes read", socket_path, ret); + else if (buf[0] != '+') + i_error("welcome: %s failed: Script returned error", socket_path); + } + if (close(fd) < 0) + i_error("close(%s) failed: %m", socket_path); +} + +static int +welcome_create_box(struct mailbox *box, + const struct mailbox_update *update, bool directory) +{ + struct welcome_mailbox *wbox = WELCOME_CONTEXT(box); + + if (wbox->module_ctx.super.create_box(box, update, directory) < 0) + return -1; + /* the mailbox isn't fully created here yet, so just mark it as created + and wait until open() time to actually run it */ + wbox->created = TRUE; + return 0; +} + +static int welcome_open_box(struct mailbox *box) +{ + struct welcome_mailbox *wbox = WELCOME_CONTEXT(box); + const char *cmd; + + cmd = !wbox->created ? NULL : + mail_user_plugin_getenv(box->storage->user, "welcome_script"); + if (cmd != NULL) { + bool wait = mail_user_plugin_getenv_bool(box->storage->user, + "welcome_wait"); + script_execute(box->storage->user, cmd, wait); + } + return wbox->module_ctx.super.open(box); +} + +static void welcome_mailbox_allocated(struct mailbox *box) +{ + struct mailbox_vfuncs *v = box->vlast; + struct welcome_mailbox *wbox; + + if (!box->inbox_user) + return; + + wbox = p_new(box->pool, struct welcome_mailbox, 1); + wbox->module_ctx.super = *v; + box->vlast = &wbox->module_ctx.super; + + v->create_box = welcome_create_box; + v->open = welcome_open_box; + MODULE_CONTEXT_SET(box, welcome_storage_module, wbox); +} + +static struct mail_storage_hooks welcome_mail_storage_hooks = { + .mailbox_allocated = welcome_mailbox_allocated +}; + +void welcome_plugin_init(struct module *module); +void welcome_plugin_deinit(void); + +void welcome_plugin_init(struct module *module) +{ + mail_storage_hooks_add(module, &welcome_mail_storage_hooks); +} + +void welcome_plugin_deinit(void) +{ + mail_storage_hooks_remove(&welcome_mail_storage_hooks); +} + +const char *welcome_plugin_version = DOVECOT_ABI_VERSION;