diff options
Diffstat (limited to 'pigeonhole/src/plugins/doveadm-sieve')
13 files changed, 2531 insertions, 0 deletions
diff --git a/pigeonhole/src/plugins/doveadm-sieve/Makefile.am b/pigeonhole/src/plugins/doveadm-sieve/Makefile.am new file mode 100644 index 0000000..9f98dab --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/Makefile.am @@ -0,0 +1,31 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) \ + $(LIBDOVECOT_DOVEADM_INCLUDE) + +doveadm_moduledir = $(dovecot_moduledir)/doveadm +lib10_doveadm_sieve_plugin_la_LDFLAGS = -module -avoid-version + +doveadm_module_LTLIBRARIES = lib10_doveadm_sieve_plugin.la + +lib10_doveadm_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +commands = \ + doveadm-sieve-cmd-list.c \ + doveadm-sieve-cmd-get.c \ + doveadm-sieve-cmd-put.c \ + doveadm-sieve-cmd-delete.c \ + doveadm-sieve-cmd-activate.c \ + doveadm-sieve-cmd-rename.c + +lib10_doveadm_sieve_plugin_la_SOURCES = \ + $(commands) \ + doveadm-sieve-cmd.c \ + doveadm-sieve-sync.c \ + doveadm-sieve-plugin.c + +noinst_HEADERS = \ + doveadm-sieve-cmd.h \ + doveadm-sieve-plugin.h diff --git a/pigeonhole/src/plugins/doveadm-sieve/Makefile.in b/pigeonhole/src/plugins/doveadm-sieve/Makefile.in new file mode 100644 index 0000000..1cba998 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/Makefile.in @@ -0,0 +1,796 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/plugins/doveadm-sieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(doveadm_moduledir)" +LTLIBRARIES = $(doveadm_module_LTLIBRARIES) +lib10_doveadm_sieve_plugin_la_DEPENDENCIES = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la +am__objects_1 = doveadm-sieve-cmd-list.lo doveadm-sieve-cmd-get.lo \ + doveadm-sieve-cmd-put.lo doveadm-sieve-cmd-delete.lo \ + doveadm-sieve-cmd-activate.lo doveadm-sieve-cmd-rename.lo +am_lib10_doveadm_sieve_plugin_la_OBJECTS = $(am__objects_1) \ + doveadm-sieve-cmd.lo doveadm-sieve-sync.lo \ + doveadm-sieve-plugin.lo +lib10_doveadm_sieve_plugin_la_OBJECTS = \ + $(am_lib10_doveadm_sieve_plugin_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +lib10_doveadm_sieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(lib10_doveadm_sieve_plugin_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-get.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-list.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-put.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo \ + ./$(DEPDIR)/doveadm-sieve-cmd.Plo \ + ./$(DEPDIR)/doveadm-sieve-plugin.Plo \ + ./$(DEPDIR)/doveadm-sieve-sync.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(lib10_doveadm_sieve_plugin_la_SOURCES) +DIST_SOURCES = $(lib10_doveadm_sieve_plugin_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) \ + $(LIBDOVECOT_DOVEADM_INCLUDE) + +doveadm_moduledir = $(dovecot_moduledir)/doveadm +lib10_doveadm_sieve_plugin_la_LDFLAGS = -module -avoid-version +doveadm_module_LTLIBRARIES = lib10_doveadm_sieve_plugin.la +lib10_doveadm_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +commands = \ + doveadm-sieve-cmd-list.c \ + doveadm-sieve-cmd-get.c \ + doveadm-sieve-cmd-put.c \ + doveadm-sieve-cmd-delete.c \ + doveadm-sieve-cmd-activate.c \ + doveadm-sieve-cmd-rename.c + +lib10_doveadm_sieve_plugin_la_SOURCES = \ + $(commands) \ + doveadm-sieve-cmd.c \ + doveadm-sieve-sync.c \ + doveadm-sieve-plugin.c + +noinst_HEADERS = \ + doveadm-sieve-cmd.h \ + doveadm-sieve-plugin.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/doveadm-sieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/doveadm-sieve/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-doveadm_moduleLTLIBRARIES: $(doveadm_module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(doveadm_module_LTLIBRARIES)'; test -n "$(doveadm_moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(doveadm_moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(doveadm_moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(doveadm_moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(doveadm_moduledir)"; \ + } + +uninstall-doveadm_moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(doveadm_module_LTLIBRARIES)'; test -n "$(doveadm_moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(doveadm_moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(doveadm_moduledir)/$$f"; \ + done + +clean-doveadm_moduleLTLIBRARIES: + -test -z "$(doveadm_module_LTLIBRARIES)" || rm -f $(doveadm_module_LTLIBRARIES) + @list='$(doveadm_module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +lib10_doveadm_sieve_plugin.la: $(lib10_doveadm_sieve_plugin_la_OBJECTS) $(lib10_doveadm_sieve_plugin_la_DEPENDENCIES) $(EXTRA_lib10_doveadm_sieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib10_doveadm_sieve_plugin_la_LINK) -rpath $(doveadm_moduledir) $(lib10_doveadm_sieve_plugin_la_OBJECTS) $(lib10_doveadm_sieve_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-get.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-list.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-put.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-cmd.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-plugin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doveadm-sieve-sync.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(doveadm_moduledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-doveadm_moduleLTLIBRARIES clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-get.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-list.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-put.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-sync.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-doveadm_moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-activate.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-delete.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-get.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-list.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-put.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd-rename.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-cmd.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-plugin.Plo + -rm -f ./$(DEPDIR)/doveadm-sieve-sync.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-doveadm_moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-doveadm_moduleLTLIBRARIES clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-doveadm_moduleLTLIBRARIES \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-doveadm_moduleLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c new file mode 100644 index 0000000..f392478 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-activate.c @@ -0,0 +1,145 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_activate_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *scriptname; +}; + +static int +cmd_sieve_activate_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_activate_cmd_context *ctx = + (struct doveadm_sieve_activate_cmd_context *)_ctx; + struct sieve_storage *storage = _ctx->storage; + struct sieve_script *script; + enum sieve_error error; + int ret = 0; + + script = sieve_storage_open_script + (storage, ctx->scriptname, NULL); + if ( script == NULL ) { + i_error("Failed to activate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + + if ( sieve_script_is_active(script) <= 0 ) { + /* Script is first being activated; compile it again without the UPLOAD + * flag. + */ + struct sieve_error_handler *ehandler; + enum sieve_compile_flags cpflags = + SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED; + struct sieve_binary *sbin; + enum sieve_error error; + + /* Compile */ + ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, 0); + if ( (sbin=sieve_compile_script + (script, ehandler, cpflags, &error)) == NULL ) { + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } else { + sieve_close(&sbin); + } + sieve_error_handler_unref(&ehandler); + } + + /* Activate only when script is valid (or already active) */ + if ( ret == 0 ) { + /* Refresh activation no matter what; this can also resolve some erroneous + * situations. + */ + ret = sieve_script_activate(script, (time_t)-1); + if ( ret < 0 ) { + i_error("Failed to activate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + } + + sieve_script_unref(&script); + return ret; +} + +static int cmd_sieve_deactivate_run +(struct doveadm_sieve_cmd_context *_ctx) +{ + struct sieve_storage *storage = _ctx->storage; + enum sieve_error error; + + if (sieve_storage_deactivate(storage, (time_t)-1) < 0) { + i_error("Failed to deactivate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + return 0; +} + +static void cmd_sieve_activate_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_activate_cmd_context *ctx = + (struct doveadm_sieve_activate_cmd_context *)_ctx; + + if (str_array_length(args) != 1) + doveadm_mail_help_name("sieve activate"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_activate_alloc(void) +{ + struct doveadm_sieve_activate_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_activate_cmd_context); + ctx->ctx.ctx.v.init = cmd_sieve_activate_init; + ctx->ctx.v.run = cmd_sieve_activate_run; + return &ctx->ctx.ctx; +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_deactivate_alloc(void) +{ + struct doveadm_sieve_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_cmd_context); + ctx->v.run = cmd_sieve_deactivate_run; + return &ctx->ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_activate = { + .name = "sieve activate", + .mail_cmd = cmd_sieve_activate_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<scriptname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_deactivate = { + .name = "sieve deactivate", + .mail_cmd = cmd_sieve_deactivate_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX, +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c new file mode 100644 index 0000000..8517abd --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-delete.c @@ -0,0 +1,116 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_delete_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + ARRAY_TYPE(const_string) scriptnames; + bool ignore_active:1; +}; + +static int +cmd_sieve_delete_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_delete_cmd_context *ctx = + (struct doveadm_sieve_delete_cmd_context *)_ctx; + struct sieve_storage *storage = _ctx->storage; + const ARRAY_TYPE(const_string) *scriptnames = &ctx->scriptnames; + const char *scriptname; + struct sieve_script *script; + enum sieve_error error; + int ret = 0; + + array_foreach_elem(scriptnames, scriptname) { + int sret = 0; + + script = sieve_storage_open_script + (storage, scriptname, NULL); + if (script == NULL) { + sret = -1; + } else { + if (sieve_script_delete(script, ctx->ignore_active) < 0) { + (void)sieve_storage_get_last_error(storage, &error); + sret = -1; + } + sieve_script_unref(&script); + } + + if (sret < 0) { + i_error("Failed to delete Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + } + return ret; +} + +static void cmd_sieve_delete_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_delete_cmd_context *ctx = + (struct doveadm_sieve_delete_cmd_context *)_ctx; + const char *name; + unsigned int i; + + if (args[0] == NULL) + doveadm_mail_help_name("sieve delete"); + doveadm_sieve_cmd_scriptnames_check(args); + + for (i = 0; args[i] != NULL; i++) { + name = p_strdup(ctx->ctx.ctx.pool, args[i]); + array_append(&ctx->scriptnames, &name, 1); + } +} + +static bool +cmd_sieve_delete_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct doveadm_sieve_delete_cmd_context *ctx = + (struct doveadm_sieve_delete_cmd_context *)_ctx; + + switch ( c ) { + case 'a': + ctx->ignore_active = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_delete_alloc(void) +{ + struct doveadm_sieve_delete_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_delete_cmd_context); + ctx->ctx.ctx.getopt_args = "a"; + ctx->ctx.ctx.v.parse_arg = cmd_sieve_delete_parse_arg; + ctx->ctx.ctx.v.init = cmd_sieve_delete_init; + ctx->ctx.v.run = cmd_sieve_delete_run; + p_array_init(&ctx->scriptnames, ctx->ctx.ctx.pool, 16); + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_delete = { + .name = "sieve delete", + .mail_cmd = cmd_sieve_delete_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-a] <scriptname> [...]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('a',"ignore-active",CMD_PARAM_BOOL,0) +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_ARRAY,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c new file mode 100644 index 0000000..e1bf7e3 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-get.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-print.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_get_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *scriptname; +}; + +static int +cmd_sieve_get_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_get_cmd_context *ctx = + (struct doveadm_sieve_get_cmd_context *)_ctx; + struct sieve_script *script; + struct istream *input; + enum sieve_error error; + int ret; + + script = sieve_storage_open_script + (_ctx->storage, ctx->scriptname, &error); + if ( script == NULL || sieve_script_get_stream + (script, &input, &error) < 0 ) { + i_error("Failed to open Sieve script: %s", + sieve_storage_get_last_error(_ctx->storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + if (script != NULL) + sieve_script_unref(&script); + return -1; + } + + ret = doveadm_print_istream(input); + sieve_script_unref(&script); + return ret; +} + +static void cmd_sieve_get_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_get_cmd_context *ctx = + (struct doveadm_sieve_get_cmd_context *)_ctx; + + if ( str_array_length(args) != 1 ) + doveadm_mail_help_name("sieve get"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]); + + doveadm_print_header_simple("sieve script"); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_get_alloc(void) +{ + struct doveadm_sieve_get_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_get_cmd_context); + ctx->ctx.ctx.v.init = cmd_sieve_get_init; + ctx->ctx.v.run = cmd_sieve_get_run; + doveadm_print_init("pager"); + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_get = { + .name = "sieve get", + .mail_cmd = cmd_sieve_get_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<scriptname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c new file mode 100644 index 0000000..0dbf379 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-list.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-print.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +static int +cmd_sieve_list_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct sieve_storage *storage = _ctx->storage; + struct sieve_storage_list_context *lctx; + enum sieve_error error; + const char *scriptname; + bool active; + + if ( (lctx = sieve_storage_list_init(storage)) + == NULL ) { + i_error("Listing Sieve scripts failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + + while ( (scriptname=sieve_storage_list_next(lctx, &active)) + != NULL ) { + doveadm_print(scriptname); + if ( active ) + doveadm_print("ACTIVE"); + else + doveadm_print(""); + } + + if ( sieve_storage_list_deinit(&lctx) < 0 ) { + i_error("Listing Sieve scripts failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + return 0; +} + +static void cmd_sieve_list_init +(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED, + const char *const args[] ATTR_UNUSED) +{ + doveadm_print_header("script", "script", + DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); + doveadm_print_header("active", "active", + DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_list_alloc(void) +{ + struct doveadm_sieve_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_cmd_context); + ctx->ctx.v.init = cmd_sieve_list_init; + ctx->ctx.getopt_args = "s"; + ctx->v.run = cmd_sieve_list_run; + doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); + return &ctx->ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_list = { + .name = "sieve list", + .mail_cmd = cmd_sieve_list_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX, +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAMS_END +}; + diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c new file mode 100644 index 0000000..ef9472d --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-put.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "istream.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_put_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *scriptname; + + bool activate:1; +}; + +static int cmd_sieve_put_run +(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_put_cmd_context *ctx = + (struct doveadm_sieve_put_cmd_context *)_ctx; + struct sieve_storage_save_context *save_ctx; + struct sieve_storage *storage = _ctx->storage; + struct istream *input = _ctx->ctx.cmd_input; + enum sieve_error error; + ssize_t ret; + bool save_failed = FALSE; + + save_ctx = sieve_storage_save_init + (storage, ctx->scriptname, input); + if ( save_ctx == NULL ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + return -1; + } + + while ( (ret = i_stream_read(input)) > 0 || ret == -2 ) { + if ( sieve_storage_save_continue(save_ctx) < 0 ) { + save_failed = TRUE; + ret = -1; + break; + } + } + i_assert(ret == -1); + + if ( input->stream_errno != 0 ) { + i_error("read(script input) failed: %s", i_stream_get_error(input)); + doveadm_sieve_cmd_failed_error + (&ctx->ctx, SIEVE_ERROR_TEMP_FAILURE); + } else if ( save_failed ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, NULL)); + doveadm_sieve_cmd_failed_storage(&ctx->ctx, storage); + } else if ( sieve_storage_save_finish(save_ctx) < 0 ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, NULL)); + doveadm_sieve_cmd_failed_storage(&ctx->ctx, storage); + } else { + ret = 0; + } + + /* Verify that script compiles */ + if ( ret == 0 ) { + struct sieve_error_handler *ehandler; + enum sieve_compile_flags cpflags = + SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED; + struct sieve_script *script; + struct sieve_binary *sbin; + + /* Obtain script object for uploaded script */ + script = sieve_storage_save_get_tempscript(save_ctx); + + /* Check result */ + if ( script == NULL ) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + + } else { + /* Mark this as an activation when we are replacing the active script */ + if ( ctx->activate || sieve_storage_save_will_activate(save_ctx) ) + cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED; + + /* Compile */ + ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, 0); + if ( (sbin=sieve_compile_script + (script, ehandler, cpflags, &error)) == NULL ) { + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } else { + sieve_close(&sbin); + + /* Script is valid; commit it to storage */ + ret = sieve_storage_save_commit(&save_ctx); + if (ret < 0) { + i_error("Saving failed: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + } + sieve_error_handler_unref(&ehandler); + } + } + + if ( save_ctx != NULL ) + sieve_storage_save_cancel(&save_ctx); + + if ( ctx->activate && ret == 0 ) { + struct sieve_script *script = sieve_storage_open_script + (storage, ctx->scriptname, NULL); + if ( script == NULL || + sieve_script_activate(script, (time_t)-1) < 0) { + i_error("Failed to activate Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + if (script != NULL) + sieve_script_unref(&script); + } + + i_assert(input->eof); + return ret < 0 ? -1 : 0; +} + +static void cmd_sieve_put_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_put_cmd_context *ctx = + (struct doveadm_sieve_put_cmd_context *)_ctx; + + if ( str_array_length(args) != 1 ) + doveadm_mail_help_name("sieve put"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->scriptname = p_strdup(ctx->ctx.ctx.pool, args[0]); + + doveadm_mail_get_input(_ctx); +} + +static bool +cmd_sieve_put_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) +{ + struct doveadm_sieve_put_cmd_context *ctx = + (struct doveadm_sieve_put_cmd_context *)_ctx; + + switch ( c ) { + case 'a': + ctx->activate = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_put_alloc(void) +{ + struct doveadm_sieve_put_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_put_cmd_context); + ctx->ctx.ctx.getopt_args = "a"; + ctx->ctx.ctx.v.parse_arg = cmd_sieve_put_parse_arg; + ctx->ctx.ctx.v.init = cmd_sieve_put_init; + ctx->ctx.v.run = cmd_sieve_put_run; + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_put = { + .name = "sieve put", + .mail_cmd = cmd_sieve_put_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"[-a] <scriptname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('a',"activate",CMD_PARAM_BOOL,0) +DOVEADM_CMD_PARAM('\0',"scriptname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('\0',"file",CMD_PARAM_ISTREAM,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c new file mode 100644 index 0000000..3cc53c7 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd-rename.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +struct doveadm_sieve_rename_cmd_context { + struct doveadm_sieve_cmd_context ctx; + + const char *oldname, *newname; +}; + +static int +cmd_sieve_rename_run(struct doveadm_sieve_cmd_context *_ctx) +{ + struct doveadm_sieve_rename_cmd_context *ctx = + (struct doveadm_sieve_rename_cmd_context *)_ctx; + struct sieve_storage *storage = _ctx->storage; + struct sieve_script *script; + enum sieve_error error; + int ret = 0; + + script = sieve_storage_open_script + (storage, ctx->oldname, NULL); + if ( script == NULL ) { + i_error("Failed to rename Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } else if ( sieve_script_rename(script, ctx->newname) < 0 ) { + i_error("Failed to rename Sieve script: %s", + sieve_storage_get_last_error(storage, &error)); + doveadm_sieve_cmd_failed_error(_ctx, error); + ret = -1; + } + + if ( script != NULL ) + sieve_script_unref(&script); + return ret; +} + +static void cmd_sieve_rename_init +(struct doveadm_mail_cmd_context *_ctx, + const char *const args[]) +{ + struct doveadm_sieve_rename_cmd_context *ctx = + (struct doveadm_sieve_rename_cmd_context *)_ctx; + + if ( str_array_length(args) != 2 ) + doveadm_mail_help_name("sieve rename"); + doveadm_sieve_cmd_scriptnames_check(args); + + ctx->oldname = p_strdup(ctx->ctx.ctx.pool, args[0]); + ctx->newname = p_strdup(ctx->ctx.ctx.pool, args[1]); +} + +static struct doveadm_mail_cmd_context * +cmd_sieve_rename_alloc(void) +{ + struct doveadm_sieve_rename_cmd_context *ctx; + + ctx = doveadm_sieve_cmd_alloc(struct doveadm_sieve_rename_cmd_context); + ctx->ctx.ctx.v.init = cmd_sieve_rename_init; + ctx->ctx.v.run = cmd_sieve_rename_run; + return &ctx->ctx.ctx; +} + +struct doveadm_cmd_ver2 doveadm_sieve_cmd_rename = { + .name = "sieve rename", + .mail_cmd = cmd_sieve_rename_alloc, + .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX"<oldname> <newname>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_MAIL_COMMON +DOVEADM_CMD_PARAM('\0',"oldname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAM('\0',"newname",CMD_PARAM_STR,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}; diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.c new file mode 100644 index 0000000..eb9318c --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "mail-storage.h" +#include "doveadm-mail.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-cmd.h" + +void doveadm_sieve_cmd_failed_error +(struct doveadm_sieve_cmd_context *ctx, enum sieve_error error) +{ + struct doveadm_mail_cmd_context *mctx = &ctx->ctx; + int exit_code = 0; + + switch ( error ) { + case SIEVE_ERROR_NONE: + i_unreached(); + return; + case SIEVE_ERROR_TEMP_FAILURE: + exit_code = EX_TEMPFAIL; + break; + case SIEVE_ERROR_NOT_POSSIBLE: + case SIEVE_ERROR_EXISTS: + case SIEVE_ERROR_NOT_VALID: + case SIEVE_ERROR_ACTIVE: + exit_code = DOVEADM_EX_NOTPOSSIBLE; + break; + case SIEVE_ERROR_BAD_PARAMS: + exit_code = EX_USAGE; + break; + case SIEVE_ERROR_NO_PERMISSION: + exit_code = EX_NOPERM; + break; + case SIEVE_ERROR_NO_QUOTA: + exit_code = EX_CANTCREAT; + break; + case SIEVE_ERROR_NOT_FOUND: + exit_code = DOVEADM_EX_NOTFOUND; + break; + default: + i_unreached(); + } + /* tempfail overrides all other exit codes, otherwise use whatever + error happened first */ + if ( mctx->exit_code == 0 || exit_code == EX_TEMPFAIL ) + mctx->exit_code = exit_code; +} + +void doveadm_sieve_cmd_failed_storage +(struct doveadm_sieve_cmd_context *ctx, struct sieve_storage *storage) +{ + enum sieve_error error; + + (void)sieve_storage_get_last_error(storage, &error); + doveadm_sieve_cmd_failed_error(ctx, error); +} + +static const char *doveadm_sieve_cmd_get_setting +(void *context, const char *identifier) +{ + struct doveadm_sieve_cmd_context *ctx = + (struct doveadm_sieve_cmd_context *) context; + + return mail_user_plugin_getenv(ctx->ctx.cur_mail_user, identifier); +} + +static const struct sieve_callbacks sieve_callbacks = { + NULL, + doveadm_sieve_cmd_get_setting +}; + +static bool doveadm_sieve_cmd_parse_arg +(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED, + int c ATTR_UNUSED) +{ + return FALSE; +} + +void doveadm_sieve_cmd_scriptnames_check(const char *const args[]) +{ + unsigned int i; + + for (i = 0; args[i] != NULL; i++) { + if (!uni_utf8_str_is_valid(args[i])) { + i_fatal_status(EX_DATAERR, + "Sieve script name not valid UTF-8: %s", args[i]); + } + if ( !sieve_script_name_is_valid(args[i]) ) { + i_fatal_status(EX_DATAERR, + "Sieve script name not valid: %s", args[i]); + } + } +} + +static int +doveadm_sieve_cmd_run +(struct doveadm_mail_cmd_context *_ctx, + struct mail_user *user) +{ + struct doveadm_sieve_cmd_context *ctx = + (struct doveadm_sieve_cmd_context *)_ctx; + struct sieve_environment svenv; + enum sieve_error error; + int ret; + + memset((void*)&svenv, 0, sizeof(svenv)); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.base_dir = user->set->base_dir; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + + ctx->svinst = sieve_init + (&svenv, &sieve_callbacks, (void *)ctx, user->mail_debug); + + ctx->storage = sieve_storage_create_main + (ctx->svinst, user, SIEVE_STORAGE_FLAG_READWRITE, &error); + if ( ctx->storage == NULL ) { + switch ( error ) { + case SIEVE_ERROR_NOT_POSSIBLE: + error = SIEVE_ERROR_NOT_FOUND; + i_error("Failed to open Sieve storage: " + "Sieve is disabled for this user"); + break; + case SIEVE_ERROR_NOT_FOUND: + i_error("Failed to open Sieve storage: " + "User cannot manage personal Sieve scripts."); + break; + default: + i_error("Failed to open Sieve storage."); + } + doveadm_sieve_cmd_failed_error(ctx, error); + ret = -1; + + } else { + i_assert( ctx->v.run != NULL ); + ret = ctx->v.run(ctx); + sieve_storage_unref(&ctx->storage); + } + + sieve_deinit(&ctx->svinst); + return ret; +} + +struct doveadm_sieve_cmd_context * +doveadm_sieve_cmd_alloc_size(size_t size) +{ + struct doveadm_sieve_cmd_context *ctx; + + ctx = (struct doveadm_sieve_cmd_context *) + doveadm_mail_cmd_alloc_size(size); + ctx->ctx.getopt_args = "s"; + ctx->ctx.v.parse_arg = doveadm_sieve_cmd_parse_arg; + ctx->ctx.v.run = doveadm_sieve_cmd_run; + return ctx; +} + +static struct doveadm_cmd_ver2 *doveadm_sieve_commands[] = { + &doveadm_sieve_cmd_list, + &doveadm_sieve_cmd_get, + &doveadm_sieve_cmd_put, + &doveadm_sieve_cmd_delete, + &doveadm_sieve_cmd_activate, + &doveadm_sieve_cmd_deactivate, + &doveadm_sieve_cmd_rename +}; + +void doveadm_sieve_cmds_init(void) +{ + unsigned int i; + + for (i = 0; i < N_ELEMENTS(doveadm_sieve_commands); i++) + doveadm_cmd_register_ver2(doveadm_sieve_commands[i]); +} diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.h b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.h new file mode 100644 index 0000000..1296701 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-cmd.h @@ -0,0 +1,43 @@ +#ifndef DOVEADM_SIEVE_CMD_H +#define DOVEADM_SIEVE_CMD_H + +struct doveadm_sieve_cmd_context; + +struct doveadm_sieve_cmd_vfuncs { + /* This is the main function which performs all the work for the + command. This is called once per each user. */ + int (*run)(struct doveadm_sieve_cmd_context *ctx); +}; + +struct doveadm_sieve_cmd_context { + struct doveadm_mail_cmd_context ctx; + + struct sieve_instance *svinst; + struct sieve_storage *storage; + + struct doveadm_sieve_cmd_vfuncs v; +}; + +void doveadm_sieve_cmd_failed_error +(struct doveadm_sieve_cmd_context *ctx, enum sieve_error error); +void doveadm_sieve_cmd_failed_storage +(struct doveadm_sieve_cmd_context *ctx, struct sieve_storage *storage); + +#define doveadm_sieve_cmd_alloc(type) \ + (type *)doveadm_sieve_cmd_alloc_size(sizeof(type)) +struct doveadm_sieve_cmd_context * +doveadm_sieve_cmd_alloc_size(size_t size); + +void doveadm_sieve_cmd_scriptnames_check(const char *const args[]); + +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_list; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_get; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_put; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_delete; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_activate; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_deactivate; +extern struct doveadm_cmd_ver2 doveadm_sieve_cmd_rename; + +void doveadm_sieve_cmds_init(void); + +#endif diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c new file mode 100644 index 0000000..0478b55 --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.c @@ -0,0 +1,24 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "doveadm-mail.h" + +#include "sieve.h" + +#include "doveadm-sieve-cmd.h" +#include "doveadm-sieve-plugin.h" + +const char *doveadm_sieve_plugin_version = DOVECOT_ABI_VERSION; + +void doveadm_sieve_plugin_init(struct module *module) +{ + doveadm_sieve_sync_init(module); + doveadm_sieve_cmds_init(); +} + +void doveadm_sieve_plugin_deinit(void) +{ + /* the hooks array is freed already */ + /*mail_storage_hooks_remove(&doveadm_sieve_mail_storage_hooks);*/ +} diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.h b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.h new file mode 100644 index 0000000..6e9446d --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-plugin.h @@ -0,0 +1,17 @@ +#ifndef DOVEADM_SIEVE_PLUGIN_H +#define DOVEADM_SIEVE_PLUGIN_H + +/* + * Plugin interface + */ + +void doveadm_sieve_plugin_init(struct module *module); +void doveadm_sieve_plugin_deinit(void); + +/* + * Replication + */ + +void doveadm_sieve_sync_init(struct module *module); + +#endif diff --git a/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-sync.c b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-sync.c new file mode 100644 index 0000000..c85a3fc --- /dev/null +++ b/pigeonhole/src/plugins/doveadm-sieve/doveadm-sieve-sync.c @@ -0,0 +1,746 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "ioloop.h" +#include "time-util.h" +#include "istream.h" +#include "istream-concat.h" +#include "mail-storage-private.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "doveadm-sieve-plugin.h" + +#define SIEVE_MAIL_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, sieve_storage_module) +#define SIEVE_USER_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, sieve_user_module) + +struct sieve_mail_user { + union mail_user_module_context module_ctx; + + struct sieve_instance *svinst; + struct sieve_storage *sieve_storage; +}; + +struct sieve_mailbox_attribute_iter { + struct mailbox_attribute_iter iter; + struct mailbox_attribute_iter *super; + + struct sieve_storage_list_context *sieve_list; + string_t *name; + + bool failed; + bool have_active; +}; + +static MODULE_CONTEXT_DEFINE_INIT(sieve_storage_module, + &mail_storage_module_register); +static MODULE_CONTEXT_DEFINE_INIT(sieve_user_module, + &mail_user_module_register); + +static const char * +mail_sieve_get_setting(void *context, const char *identifier) +{ + struct mail_user *mail_user = context; + + return mail_user_plugin_getenv(mail_user, identifier); +} + +static const struct sieve_callbacks mail_sieve_callbacks = { + NULL, + mail_sieve_get_setting +}; + +static void mail_sieve_user_deinit(struct mail_user *user) +{ + struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); + + if ( suser->svinst != NULL ) { + if (suser->sieve_storage != NULL) + sieve_storage_unref(&suser->sieve_storage); + sieve_deinit(&suser->svinst); + } + + suser->module_ctx.super.deinit(user); +} + +static int +mail_sieve_user_init +(struct mail_user *user, struct sieve_storage **svstorage_r) +{ + struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); + enum sieve_storage_flags storage_flags = + SIEVE_STORAGE_FLAG_READWRITE | + SIEVE_STORAGE_FLAG_SYNCHRONIZING; + struct sieve_environment svenv; + + if ( suser->svinst != NULL ) { + *svstorage_r = suser->sieve_storage; + return suser->sieve_storage != NULL ? 1 : 0; + } + + /* Delayed initialization of sieve storage until it's actually needed */ + i_zero(&svenv); + svenv.username = user->username; + (void)mail_user_get_home(user, &svenv.home_dir); + svenv.base_dir = user->set->base_dir; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + + suser->svinst = sieve_init(&svenv, &mail_sieve_callbacks, + user, user->mail_debug); + suser->sieve_storage = sieve_storage_create_main + (suser->svinst, user, storage_flags, NULL); + + *svstorage_r = suser->sieve_storage; + return suser->sieve_storage != NULL ? 1 : 0; +} + +static int sieve_attribute_unset_script(struct mail_storage *storage, + struct sieve_storage *svstorage, + const char *scriptname) +{ + struct sieve_script *script; + const char *errstr; + enum sieve_error error; + int ret = 0; + + script = sieve_storage_open_script(svstorage, scriptname, NULL); + if (script == NULL) { + ret = -1; + } else { + ret = sieve_script_delete(script, TRUE); + sieve_script_unref(&script); + } + + if (ret < 0) { + errstr = sieve_storage_get_last_error(svstorage, &error); + if (error == SIEVE_ERROR_NOT_FOUND) { + /* already deleted, ignore */ + return 0; + } + mail_storage_set_critical(storage, + "Failed to delete Sieve script '%s': %s", scriptname, + errstr); + return -1; + } + return 0; +} + +static int +sieve_attribute_set_active(struct mail_storage *storage, + struct sieve_storage *svstorage, + const struct mail_attribute_value *value) +{ + const char *scriptname; + struct sieve_script *script; + time_t last_change = + (value->last_change == 0 ? ioloop_time : value->last_change); + int ret; + + if (mailbox_attribute_value_to_string(storage, value, &scriptname) < 0) + return -1; + + if (scriptname == NULL) { + /* don't affect non-link active script */ + if ((ret=sieve_storage_is_singular(svstorage)) != 0) { + if (ret < 0) { + mail_storage_set_internal_error(storage); + return -1; + } + return 0; + } + + /* deactivate current script */ + if (sieve_storage_deactivate(svstorage, last_change) < 0) { + mail_storage_set_critical(storage, + "Failed to deactivate Sieve: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return -1; + } + return 0; + } + i_assert(scriptname[0] == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK); + scriptname++; + + /* activate specified script */ + script = sieve_storage_open_script(svstorage, scriptname, NULL); + ret = script == NULL ? -1 : + sieve_script_activate(script, last_change); + if (ret < 0) { + mail_storage_set_critical(storage, + "Failed to activate Sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + } + if (script != NULL) + sieve_script_unref(&script); + sieve_storage_set_modified(svstorage, last_change); + return ret; +} + +static int +sieve_attribute_unset_active_script(struct mail_storage *storage, + struct sieve_storage *svstorage, time_t last_change) +{ + int ret; + + if ((ret=sieve_storage_is_singular(svstorage)) != 0) { + if (ret < 0) + mail_storage_set_internal_error(storage); + return ret; + } + + if (sieve_storage_deactivate(svstorage, last_change) < 0) { + mail_storage_set_critical(storage, + "Failed to deactivate sieve: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return -1; + } + return 0; +} + +static int +sieve_attribute_set_active_script(struct mail_storage *storage, + struct sieve_storage *svstorage, + const struct mail_attribute_value *value) +{ + struct istream *input; + time_t last_change = + (value->last_change == 0 ? ioloop_time : value->last_change); + + if (value->value != NULL) { + input = i_stream_create_from_data(value->value, strlen(value->value)); + } else if (value->value_stream != NULL) { + input = value->value_stream; + i_stream_ref(input); + } else { + return sieve_attribute_unset_active_script + (storage, svstorage, last_change); + } + /* skip over the 'S' type */ + i_stream_skip(input, 1); + + if (sieve_storage_save_as_active + (svstorage, input, last_change) < 0) { + mail_storage_set_critical(storage, + "Failed to save active sieve script: %s", + sieve_storage_get_last_error(svstorage, NULL)); + i_stream_unref(&input); + return -1; + } + + sieve_storage_set_modified(svstorage, last_change); + i_stream_unref(&input); + return 0; +} + +static int +sieve_attribute_set_default(struct mail_storage *storage, + struct sieve_storage *svstorage, + const struct mail_attribute_value *value) +{ + const unsigned char *data; + size_t size; + ssize_t ret; + char type; + + if (value->value != NULL) { + type = value->value[0]; + } else if (value->value_stream != NULL) { + ret = i_stream_read_more(value->value_stream, &data, &size); + if (ret == -1) { + mail_storage_set_critical(storage, "read(%s) failed: %m", + i_stream_get_name(value->value_stream)); + return -1; + } + i_assert(ret > 0); + type = data[0]; + } else { + type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT; + } + if (type == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK) + return sieve_attribute_set_active(storage, svstorage, value); + if (type == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT) + return sieve_attribute_set_active_script(storage, svstorage, value); + mail_storage_set_error(storage, MAIL_ERROR_PARAMS, + "Invalid value for default sieve attribute"); + return -1; +} + +static int +sieve_attribute_set_sieve(struct mail_storage *storage, + const char *key, + const struct mail_attribute_value *value) +{ + struct sieve_storage *svstorage; + struct sieve_storage_save_context *save_ctx; + struct istream *input; + const char *scriptname; + int ret; + + if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) { + if (ret == 0) { + mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, + "Sieve not enabled for user"); + } + return -1; + } + + if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0) + return sieve_attribute_set_default(storage, svstorage, value); + if (!str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) { + mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, + "Nonexistent sieve attribute"); + return -1; + } + scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); + + if (value->value != NULL) { + input = i_stream_create_from_data(value->value, + strlen(value->value)); + save_ctx = sieve_storage_save_init(svstorage, scriptname, input); + } else if (value->value_stream != NULL) { + input = value->value_stream; + i_stream_ref(input); + save_ctx = sieve_storage_save_init(svstorage, scriptname, input); + } else { + return sieve_attribute_unset_script(storage, svstorage, scriptname); + } + + if (save_ctx == NULL) { + /* save initialization failed */ + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + i_stream_unref(&input); + return -1; + } + + if (value->last_change != 0) + sieve_storage_save_set_mtime(save_ctx, value->last_change); + + ret = 0; + while (input->stream_errno == 0 && + !i_stream_read_eof(input)) { + if (sieve_storage_save_continue(save_ctx) < 0) { + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + ret = -1; + break; + } + } + if (input->stream_errno != 0) { + errno = input->stream_errno; + mail_storage_set_critical(storage, + "Saving sieve script: read(%s) failed: %m", + i_stream_get_name(input)); + ret = -1; + } + i_assert(input->eof || ret < 0); + if (ret == 0 && sieve_storage_save_finish(save_ctx) < 0) { + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + ret = -1; + } + if (ret < 0) + sieve_storage_save_cancel(&save_ctx); + else if (sieve_storage_save_commit(&save_ctx) < 0) { + mail_storage_set_critical(storage, + "Failed to save sieve script '%s': %s", scriptname, + sieve_storage_get_last_error(svstorage, NULL)); + ret = -1; + } + i_stream_unref(&input); + return ret; +} + +static int +sieve_attribute_set(struct mailbox_transaction_context *t, + enum mail_attribute_type type, const char *key, + const struct mail_attribute_value *value) +{ + struct mail_user *user = t->box->storage->user; + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(t->box); + + if (t->box->storage->user->dsyncing && + type == MAIL_ATTRIBUTE_TYPE_PRIVATE && + str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE)) { + time_t ts = + (value->last_change != 0 ? value->last_change : ioloop_time); + + if (sieve_attribute_set_sieve(t->box->storage, key, value) < 0) + return -1; + + if (user->mail_debug) { + const char *change; + if (value->last_change != 0) { + change = t_strflocaltime + ("(last change: %Y-%m-%d %H:%M:%S)", value->last_change); + } else { + change = t_strflocaltime + ("(time: %Y-%m-%d %H:%M:%S)", ioloop_time); + } + i_debug("doveadm-sieve: Assigned value for key `%s' %s", + key, change); + } + + /* FIXME: set value len to sieve script size / active name + length */ + if (value->value != NULL || value->value_stream != NULL) + mail_index_attribute_set(t->itrans, TRUE, key, ts, 0); + else + mail_index_attribute_unset(t->itrans, TRUE, key, ts); + return 0; + } + return sbox->super.attribute_set(t, type, key, value); +} + +static int +sieve_attribute_retrieve_script(struct mail_storage *storage, + struct sieve_storage *svstorage, struct sieve_script *script, + bool add_type_prefix, + struct mail_attribute_value *value_r, const char **errorstr_r) +{ + static char type = MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_SCRIPT; + struct istream *input, *inputs[3]; + const struct stat *st; + enum sieve_error error; + + if (script == NULL) + *errorstr_r = sieve_storage_get_last_error(svstorage, &error); + else if (sieve_script_get_stream(script, &input, &error) < 0) + sieve_script_unref(&script); + + if (script == NULL) { + if (error == SIEVE_ERROR_NOT_FOUND) { + /* already deleted, but return the last_change */ + (void)sieve_storage_get_last_change(svstorage, + &value_r->last_change); + return 0; + } + *errorstr_r = sieve_storage_get_last_error(svstorage, &error); + return -1; + } + if (i_stream_stat(input, FALSE, &st) < 0) { + mail_storage_set_critical(storage, + "stat(%s) failed: %m", i_stream_get_name(input)); + } else { + value_r->last_change = st->st_mtime; + } + if (!add_type_prefix) { + i_stream_ref(input); + value_r->value_stream = input; + } else { + inputs[0] = i_stream_create_from_data(&type, 1); + inputs[1] = input; + inputs[2] = NULL; + value_r->value_stream = i_stream_create_concat(inputs); + i_stream_unref(&inputs[0]); + } + sieve_script_unref(&script); + return 1; +} + +static int +sieve_attribute_get_active_script(struct mail_storage *storage, + struct sieve_storage *svstorage, + struct mail_attribute_value *value_r) +{ + struct sieve_script *script; + const char *errstr; + int ret; + + if ((ret=sieve_storage_is_singular(svstorage)) <= 0) { + if (ret == 0 && sieve_storage_active_script_get_last_change + (svstorage, &value_r->last_change) < 0) { + ret = -1; + } + if (ret < 0) + mail_storage_set_internal_error(storage); + return ret; + } + + if ((script=sieve_storage_active_script_open + (svstorage, NULL)) == NULL) + return 0; + + if ((ret=sieve_attribute_retrieve_script + (storage, svstorage, script, TRUE, value_r, &errstr)) < 0) { + mail_storage_set_critical(storage, + "Failed to access active sieve script: %s", errstr); + } + return ret; +} + +static int +sieve_attribute_get_default(struct mail_storage *storage, + struct sieve_storage *svstorage, + struct mail_attribute_value *value_r) +{ + const char *scriptname; + int ret; + + ret = sieve_storage_active_script_get_name(svstorage, &scriptname); + if (ret == 0) + return sieve_attribute_get_active_script(storage, svstorage, value_r); + + if (ret > 0) { + value_r->value = t_strdup_printf("%c%s", + MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK, scriptname); + if (sieve_storage_active_script_get_last_change + (svstorage, &value_r->last_change) < 0) + ret = -1; + } + if (ret < 0) + mail_storage_set_internal_error(storage); + return ret; +} + +static int +sieve_attribute_get_sieve(struct mail_storage *storage, const char *key, + struct mail_attribute_value *value_r) +{ + struct sieve_storage *svstorage; + struct sieve_script *script; + const char *scriptname, *errstr; + int ret; + + if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) + return ret; + + if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0) + return sieve_attribute_get_default(storage, svstorage, value_r); + if (!str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) + return 0; + if ((value_r->flags & MAIL_ATTRIBUTE_VALUE_FLAG_INT_STREAMS) == 0) { + mail_storage_set_error(storage, MAIL_ERROR_PARAMS, + "Sieve attributes are available only as streams"); + return -1; + } + scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); + script = sieve_storage_open_script(svstorage, scriptname, NULL); + if ((ret=sieve_attribute_retrieve_script + (storage, svstorage, script, FALSE, value_r, &errstr)) < 0) { + mail_storage_set_critical(storage, + "Failed to access sieve script '%s': %s", + scriptname, errstr); + } + return ret; +} + +static int +sieve_attribute_get(struct mailbox *box, + enum mail_attribute_type type, const char *key, + struct mail_attribute_value *value_r) +{ + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(box); + struct mail_user *user = box->storage->user; + int ret; + + if (box->storage->user->dsyncing && + type == MAIL_ATTRIBUTE_TYPE_PRIVATE && + str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE)) { + + ret = sieve_attribute_get_sieve(box->storage, key, value_r); + if (ret >= 0 && user->mail_debug) { + struct tm *tm = localtime(&value_r->last_change); + char str[256]; + const char *timestamp = ""; + + if (strftime(str, sizeof(str), + " (last change: %Y-%m-%d %H:%M:%S)", tm) > 0) + timestamp = str; + + if (ret > 0) { + i_debug("doveadm-sieve: Retrieved value for key `%s'%s", + key, timestamp); + } else { + i_debug("doveadm-sieve: Value missing for key `%s'%s", + key, timestamp); + } + } + return ret; + } + return sbox->super.attribute_get(box, type, key, value_r); +} + +static int +sieve_attribute_iter_script_init(struct sieve_mailbox_attribute_iter *siter) +{ + struct mail_user *user = siter->iter.box->storage->user; + struct sieve_storage *svstorage; + int ret; + + if (user->mail_debug) + i_debug("doveadm-sieve: Iterating Sieve mailbox attributes"); + + if ((ret = mail_sieve_user_init(user, &svstorage)) <= 0) + return ret; + + siter->sieve_list = sieve_storage_list_init(svstorage); + if (siter->sieve_list == NULL) { + mail_storage_set_critical(siter->iter.box->storage, + "Failed to iterate sieve scripts: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return -1; + } + siter->name = str_new(default_pool, 128); + str_append(siter->name, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); + return 0; +} + +static struct mailbox_attribute_iter * +sieve_attribute_iter_init(struct mailbox *box, enum mail_attribute_type type, + const char *prefix) +{ + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(box); + struct sieve_mailbox_attribute_iter *siter; + + siter = i_new(struct sieve_mailbox_attribute_iter, 1); + siter->iter.box = box; + siter->super = sbox->super.attribute_iter_init(box, type, prefix); + + if (box->storage->user->dsyncing && + type == MAIL_ATTRIBUTE_TYPE_PRIVATE) { + if (sieve_attribute_iter_script_init(siter) < 0) + siter->failed = TRUE; + } + return &siter->iter; +} + +static const char * +sieve_attribute_iter_next_script(struct sieve_mailbox_attribute_iter *siter) +{ + struct mail_user *user = siter->iter.box->storage->user; + struct sieve_mail_user *suser = SIEVE_USER_CONTEXT(user); + struct sieve_storage *svstorage = suser->sieve_storage; + const char *scriptname; + bool active; + int ret; + + if (siter->sieve_list == NULL) + return NULL; + + /* Iterate through all scripts in sieve_dir */ + while ((scriptname = sieve_storage_list_next(siter->sieve_list, &active)) + != NULL) { + if (active) + siter->have_active = TRUE; + str_truncate(siter->name, strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)); + str_append(siter->name, scriptname); + return str_c(siter->name); + } + if (sieve_storage_list_deinit(&siter->sieve_list) < 0) { + mail_storage_set_critical(siter->iter.box->storage, + "Failed to iterate sieve scripts: %s", + sieve_storage_get_last_error(svstorage, NULL)); + siter->failed = TRUE; + return NULL; + } + + /* Check whether active script is a proper symlink or a regular file */ + if ((ret=sieve_storage_is_singular(svstorage)) < 0) { + mail_storage_set_critical(siter->iter.box->storage, + "Failed to iterate sieve scripts: %s", + sieve_storage_get_last_error(svstorage, NULL)); + return NULL; + } + + /* Regular file */ + if (ret > 0) + return MAILBOX_ATTRIBUTE_SIEVE_DEFAULT; + + /* Symlink or none active */ + return siter->have_active ? MAILBOX_ATTRIBUTE_SIEVE_DEFAULT : NULL; +} + +static const char * +sieve_attribute_iter_next(struct mailbox_attribute_iter *iter) +{ + struct sieve_mailbox_attribute_iter *siter = + (struct sieve_mailbox_attribute_iter *)iter; + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(iter->box); + struct mail_user *user = iter->box->storage->user; + const char *key; + + if (siter->sieve_list != NULL) { + if ((key = sieve_attribute_iter_next_script(siter)) != NULL) { + if (user->mail_debug) { + i_debug("doveadm-sieve: Iterating Sieve mailbox attribute: %s", key); + } + return key; + } + } + return sbox->super.attribute_iter_next(siter->super); +} + +static int +sieve_attribute_iter_deinit(struct mailbox_attribute_iter *iter) +{ + struct sieve_mailbox_attribute_iter *siter = + (struct sieve_mailbox_attribute_iter *)iter; + union mailbox_module_context *sbox = SIEVE_MAIL_CONTEXT(iter->box); + int ret = siter->failed ? -1 : 0; + + if (siter->super != NULL) { + if (sbox->super.attribute_iter_deinit(siter->super) < 0) + ret = -1; + } + if (siter->sieve_list != NULL) + (void)sieve_storage_list_deinit(&siter->sieve_list); + if (siter->name != NULL) + str_free(&siter->name); + i_free(siter); + return ret; +} + +static void +sieve_mail_user_created(struct mail_user *user) +{ + struct sieve_mail_user *suser; + struct mail_user_vfuncs *v = user->vlast; + + suser = p_new(user->pool, struct sieve_mail_user, 1); + suser->module_ctx.super = *v; + user->vlast = &suser->module_ctx.super; + v->deinit = mail_sieve_user_deinit; + MODULE_CONTEXT_SET(user, sieve_user_module, suser); +} + +static void +sieve_mailbox_allocated(struct mailbox *box) +{ + struct mailbox_vfuncs *v = box->vlast; + union mailbox_module_context *sbox; + + /* attribute syncing is done via INBOX */ + if (!box->inbox_user) + return; + + sbox = p_new(box->pool, union mailbox_module_context, 1); + sbox->super = *v; + box->vlast = &sbox->super; + v->attribute_set = sieve_attribute_set; + v->attribute_get = sieve_attribute_get; + v->attribute_iter_init = sieve_attribute_iter_init; + v->attribute_iter_next = sieve_attribute_iter_next; + v->attribute_iter_deinit = sieve_attribute_iter_deinit; + MODULE_CONTEXT_SET_SELF(box, sieve_storage_module, sbox); +} + +static struct mail_storage_hooks doveadm_sieve_mail_storage_hooks = { + .mail_user_created = sieve_mail_user_created, + .mailbox_allocated = sieve_mailbox_allocated +}; + +void doveadm_sieve_sync_init(struct module *module) +{ + mail_storage_hooks_add_forced + (module, &doveadm_sieve_mail_storage_hooks); +} |