]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added welcome plugin.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 20 Jun 2016 08:39:55 +0000 (11:39 +0300)
committerGitLab <gitlab@git.dovecot.net>
Tue, 21 Jun 2016 14:29:58 +0000 (17:29 +0300)
configure.ac
src/plugins/Makefile.am
src/plugins/welcome/Makefile.am [new file with mode: 0644]
src/plugins/welcome/welcome-plugin.c [new file with mode: 0644]

index 86bfb7ad5cc2c8e8565ff9671301bcf1d8dba472..ef8312cc5d1cf2cc598a2e4d6b84917294b060e7 100644 (file)
@@ -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
index 7e0d00b17d98b42d054e07e874149ccc325be9e7..7dc31d954c6c524ef06539501fb117f3505ea383 100644 (file)
@@ -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 (file)
index 0000000..98968f5
--- /dev/null
@@ -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 (file)
index 0000000..a2ed80e
--- /dev/null
@@ -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;