diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
commit | 0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch) | |
tree | 3f3789daa2f6db22da6e55e92bee0062a7d613fe /pigeonhole/src/lib-sieve/plugins | |
parent | Initial commit. (diff) | |
download | dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip |
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/src/lib-sieve/plugins')
204 files changed, 52770 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/plugins/Makefile.am b/pigeonhole/src/lib-sieve/plugins/Makefile.am new file mode 100644 index 0000000..2a1c054 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/Makefile.am @@ -0,0 +1,32 @@ +if BUILD_UNFINISHED +UNFINISHED = +endif + +SUBDIRS = \ + vacation \ + subaddress \ + comparator-i-ascii-numeric \ + relational \ + regex \ + imap4flags \ + copy \ + include \ + body \ + variables \ + enotify \ + notify \ + environment \ + mailbox \ + date \ + spamvirustest \ + ihave \ + editheader \ + duplicate \ + index \ + metadata \ + mime \ + special-use \ + vnd.dovecot \ + $(UNFINISHED) + + diff --git a/pigeonhole/src/lib-sieve/plugins/Makefile.in b/pigeonhole/src/lib-sieve/plugins/Makefile.in new file mode 100644 index 0000000..8443114 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/Makefile.in @@ -0,0 +1,719 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins +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 $(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_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 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +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 +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +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@ +@BUILD_UNFINISHED_TRUE@UNFINISHED = +SUBDIRS = \ + vacation \ + subaddress \ + comparator-i-ascii-numeric \ + relational \ + regex \ + imap4flags \ + copy \ + include \ + body \ + variables \ + enotify \ + notify \ + environment \ + mailbox \ + date \ + spamvirustest \ + ihave \ + editheader \ + duplicate \ + index \ + metadata \ + mime \ + special-use \ + vnd.dovecot \ + $(UNFINISHED) + +all: all-recursive + +.SUFFIXES: +$(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/lib-sieve/plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(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-recursive + +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-recursive + +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 + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean 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-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 \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.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/lib-sieve/plugins/body/Makefile.am b/pigeonhole/src/lib-sieve/plugins/body/Makefile.am new file mode 100644 index 0000000..251b8d6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_body.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tsts = \ + tst-body.c + +libsieve_ext_body_la_SOURCES = \ + ext-body-common.c \ + $(tsts) \ + ext-body.c + +noinst_HEADERS = \ + ext-body-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/body/Makefile.in b/pigeonhole/src/lib-sieve/plugins/body/Makefile.in new file mode 100644 index 0000000..5d58bbd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/body +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_body_la_LIBADD = +am__objects_1 = tst-body.lo +am_libsieve_ext_body_la_OBJECTS = ext-body-common.lo $(am__objects_1) \ + ext-body.lo +libsieve_ext_body_la_OBJECTS = $(am_libsieve_ext_body_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 = +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)/ext-body-common.Plo \ + ./$(DEPDIR)/ext-body.Plo ./$(DEPDIR)/tst-body.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 = $(libsieve_ext_body_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_body_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@ +noinst_LTLIBRARIES = libsieve_ext_body.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tsts = \ + tst-body.c + +libsieve_ext_body_la_SOURCES = \ + ext-body-common.c \ + $(tsts) \ + ext-body.c + +noinst_HEADERS = \ + ext-body-common.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/lib-sieve/plugins/body/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/body/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_body.la: $(libsieve_ext_body_la_OBJECTS) $(libsieve_ext_body_la_DEPENDENCIES) $(EXTRA_libsieve_ext_body_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_body_la_OBJECTS) $(libsieve_ext_body_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-body-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-body.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-body.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-body-common.Plo + -rm -f ./$(DEPDIR)/ext-body.Plo + -rm -f ./$(DEPDIR)/tst-body.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-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)/ext-body-common.Plo + -rm -f ./$(DEPDIR)/ext-body.Plo + -rm -f ./$(DEPDIR)/tst-body.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/body/ext-body-common.c b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.c new file mode 100644 index 0000000..c19940e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "buffer.h" +#include "array.h" +#include "str.h" +#include "istream.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-interpreter.h" + +#include "ext-body-common.h" + + +/* + * Body part stringlist + */ + +static int ext_body_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void ext_body_stringlist_reset + (struct sieve_stringlist *_strlist); + +struct ext_body_stringlist { + struct sieve_stringlist strlist; + + struct sieve_message_part_data *body_parts; + struct sieve_message_part_data *body_parts_iter; +}; + +int ext_body_get_part_list +(const struct sieve_runtime_env *renv, enum tst_body_transform transform, + const char * const *content_types, struct sieve_stringlist **strlist_r) +{ + static const char * const _no_content_types[] = { "", NULL }; + struct ext_body_stringlist *strlist; + struct sieve_message_part_data *body_parts = NULL; + int ret; + + *strlist_r = NULL; + + if ( content_types == NULL ) content_types = _no_content_types; + + switch ( transform ) { + case TST_BODY_TRANSFORM_RAW: + if ( (ret=sieve_message_body_get_raw(renv, &body_parts)) <= 0 ) + return ret; + break; + case TST_BODY_TRANSFORM_CONTENT: + if ( (ret=sieve_message_body_get_content + (renv, content_types, &body_parts)) <= 0 ) + return ret; + break; + case TST_BODY_TRANSFORM_TEXT: + if ( (ret=sieve_message_body_get_text(renv, &body_parts)) <= 0 ) + return ret; + break; + default: + i_unreached(); + } + + strlist = t_new(struct ext_body_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.next_item = ext_body_stringlist_next_item; + strlist->strlist.reset = ext_body_stringlist_reset; + strlist->body_parts = body_parts; + strlist->body_parts_iter = body_parts; + + *strlist_r = &strlist->strlist; + return SIEVE_EXEC_OK; +} + +static int ext_body_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct ext_body_stringlist *strlist = + (struct ext_body_stringlist *)_strlist; + + *str_r = NULL; + + if ( strlist->body_parts_iter->content == NULL ) return 0; + + *str_r = t_str_new_const + (strlist->body_parts_iter->content, strlist->body_parts_iter->size); + strlist->body_parts_iter++; + return 1; +} + +static void ext_body_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct ext_body_stringlist *strlist = + (struct ext_body_stringlist *)_strlist; + + strlist->body_parts_iter = strlist->body_parts; +} diff --git a/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.h b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.h new file mode 100644 index 0000000..290ca13 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/ext-body-common.h @@ -0,0 +1,40 @@ +#ifndef EXT_BODY_COMMON_H +#define EXT_BODY_COMMON_H + +/* + * Types + */ + +enum tst_body_transform { + TST_BODY_TRANSFORM_RAW, + TST_BODY_TRANSFORM_CONTENT, + TST_BODY_TRANSFORM_TEXT +}; + +/* + * Extension + */ + +extern const struct sieve_extension_def body_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def body_test; + +/* + * Operations + */ + +extern const struct sieve_operation_def body_operation; + +/* + * Message body part extraction + */ + +int ext_body_get_part_list + (const struct sieve_runtime_env *renv, enum tst_body_transform transform, + const char * const *content_types, struct sieve_stringlist **strlist_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/body/ext-body.c b/pigeonhole/src/lib-sieve/plugins/body/ext-body.c new file mode 100644 index 0000000..27218bd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/ext-body.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension body + * ------------------ + * + * Authors: Stephan Bosch + * Original CMUSieve implementation by Timo Sirainen + * Specification: RFC 5173 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-body-common.h" + +/* + * Extension + */ + +static bool ext_body_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def body_extension = { + .name = "body", + .validator_load = ext_body_validator_load, + SIEVE_EXT_DEFINE_OPERATION(body_operation) +}; + +static bool ext_body_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &body_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/body/tst-body.c b/pigeonhole/src/lib-sieve/plugins/body/tst-body.c new file mode 100644 index 0000000..f08dd54 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/body/tst-body.c @@ -0,0 +1,385 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-body-common.h" + +/* + * Body test + * + * Syntax + * body [COMPARATOR] [MATCH-TYPE] [BODY-TRANSFORM] + * <key-list: string-list> + */ + +static bool tst_body_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_body_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_body_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def body_test = { + .identifier = "body", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_body_registered, + .validate = tst_body_validate, + .generate = tst_body_generate +}; + +/* + * Body operation + */ + +static bool ext_body_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int ext_body_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def body_operation = { + .mnemonic = "body", + .ext_def = &body_extension, + .dump = ext_body_operation_dump, + .execute = ext_body_operation_execute +}; + +/* + * Optional operands + */ + +enum tst_body_optional { + OPT_BODY_TRANSFORM = SIEVE_MATCH_OPT_LAST +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool tag_body_transform_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_body_transform_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def body_raw_tag = { + .identifier = "raw", + .validate = tag_body_transform_validate, + .generate = tag_body_transform_generate +}; + +static const struct sieve_argument_def body_content_tag = { + .identifier = "content", + .validate = tag_body_transform_validate, + .generate = tag_body_transform_generate +}; + +static const struct sieve_argument_def body_text_tag = { + .identifier = "text", + .validate = tag_body_transform_validate, + .generate = tag_body_transform_generate +}; + +/* Argument implementation */ + +static bool tag_body_transform_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + enum tst_body_transform transform; + struct sieve_ast_argument *tag = *arg; + + /* BODY-TRANSFORM: + * :raw + * / :content <content-types: string-list> + * / :text + */ + if ( (bool) cmd->data ) { + sieve_argument_validate_error(valdtr, *arg, + "the :raw, :content and :text arguments for the body test are mutually " + "exclusive, but more than one was specified"); + return FALSE; + } + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + /* :content tag has a string-list argument */ + if ( sieve_argument_is(tag, body_raw_tag) ) + transform = TST_BODY_TRANSFORM_RAW; + + else if ( sieve_argument_is(tag, body_text_tag) ) + transform = TST_BODY_TRANSFORM_TEXT; + + else if ( sieve_argument_is(tag, body_content_tag) ) { + /* Check syntax: + * :content <content-types: string-list> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) { + return FALSE; + } + + /* Assign tag parameters */ + tag->parameters = *arg; + *arg = sieve_ast_arguments_detach(*arg,1); + + transform = TST_BODY_TRANSFORM_CONTENT; + } else + return FALSE; + + /* Signal the presence of this tag */ + cmd->data = (void *) TRUE; + + /* Assign context data */ + tag->argument->data = (void *) transform; + + return TRUE; +} + +/* + * Command Registration + */ + +static bool tst_body_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &body_raw_tag, OPT_BODY_TRANSFORM); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &body_content_tag, OPT_BODY_TRANSFORM); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &body_text_tag, OPT_BODY_TRANSFORM); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_body_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_body_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &body_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +static bool tag_body_transform_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + enum tst_body_transform transform = + POINTER_CAST_TO(arg->argument->data, enum tst_body_transform); + + sieve_binary_emit_byte(cgenv->sblock, transform); + sieve_generate_argument_parameters(cgenv, cmd, arg); + + return TRUE; +} + +/* + * Code dump + */ + +static bool ext_body_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int transform; + int opt_code = 0; + + sieve_code_dumpf(denv, "BODY"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_BODY_TRANSFORM: + if ( !sieve_binary_read_byte(denv->sblock, address, &transform) ) + return FALSE; + + switch ( transform ) { + case TST_BODY_TRANSFORM_RAW: + sieve_code_dumpf(denv, "BODY-TRANSFORM: RAW"); + break; + case TST_BODY_TRANSFORM_TEXT: + sieve_code_dumpf(denv, "BODY-TRANSFORM: TEXT"); + break; + case TST_BODY_TRANSFORM_CONTENT: + sieve_code_dumpf(denv, "BODY-TRANSFORM: CONTENT"); + + sieve_code_descend(denv); + if ( !sieve_opr_stringlist_dump(denv, address, "content types") ) + return FALSE; + sieve_code_ascend(denv); + break; + default: + return FALSE; + } + break; + default: + return FALSE; + } + }; + + return sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Interpretation + */ + +static int ext_body_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + int opt_code = 0; + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + unsigned int transform = TST_BODY_TRANSFORM_TEXT; + struct sieve_stringlist *ctype_list, *value_list, *key_list; + bool mvalues_active; + const char * const *content_types = NULL; + int match, ret; + + /* + * Read operands + */ + + /* Optional operands */ + + ctype_list = NULL; + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_BODY_TRANSFORM: + if ( !sieve_binary_read_byte(renv->sblock, address, &transform) || + transform > TST_BODY_TRANSFORM_TEXT ) { + sieve_runtime_trace_error(renv, "invalid body transform type"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( transform == TST_BODY_TRANSFORM_CONTENT && + (ret=sieve_opr_stringlist_read + (renv, address, "content-type-list", &ctype_list)) <= 0 ) + return ret; + + break; + + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read key-list */ + + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + if ( ctype_list != NULL && sieve_stringlist_read_all + (ctype_list, pool_datastack_create(), &content_types) < 0 ) { + sieve_runtime_trace_error(renv, "failed to read content-type-list operand"); + return ctype_list->exec_status; + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "body test"); + + /* Extract requested parts */ + if ( (ret=ext_body_get_part_list(renv, + (enum tst_body_transform) transform, content_types,&value_list)) <= 0 ) + return ret; + + /* Disable match values processing as required by RFC */ + mvalues_active = sieve_match_values_set_enabled(renv, FALSE); + + /* Perform match */ + match = sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret); + + /* Restore match values processing */ + (void)sieve_match_values_set_enabled(renv, mvalues_active); + + if ( match < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am new file mode 100644 index 0000000..8e385c5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libsieve_ext_comparator-i-ascii-numeric.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_comparator_i_ascii_numeric_la_SOURCES = \ + ext-cmp-i-ascii-numeric.c diff --git a/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.in b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.in new file mode 100644 index 0000000..35ef51f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile.in @@ -0,0 +1,674 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/comparator-i-ascii-numeric +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 $(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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_comparator_i_ascii_numeric_la_LIBADD = +am_libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS = \ + ext-cmp-i-ascii-numeric.lo +libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS = \ + $(am_libsieve_ext_comparator_i_ascii_numeric_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 = +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)/ext-cmp-i-ascii-numeric.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 = $(libsieve_ext_comparator_i_ascii_numeric_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_comparator_i_ascii_numeric_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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@ +noinst_LTLIBRARIES = libsieve_ext_comparator-i-ascii-numeric.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_comparator_i_ascii_numeric_la_SOURCES = \ + ext-cmp-i-ascii-numeric.c + +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/lib-sieve/plugins/comparator-i-ascii-numeric/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/comparator-i-ascii-numeric/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_comparator-i-ascii-numeric.la: $(libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS) $(libsieve_ext_comparator_i_ascii_numeric_la_DEPENDENCIES) $(EXTRA_libsieve_ext_comparator_i_ascii_numeric_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_comparator_i_ascii_numeric_la_OBJECTS) $(libsieve_ext_comparator_i_ascii_numeric_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-cmp-i-ascii-numeric.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) +installdirs: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-cmp-i-ascii-numeric.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-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)/ext-cmp-i-ascii-numeric.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c new file mode 100644 index 0000000..20ec38b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c @@ -0,0 +1,160 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension comparator-i;ascii-numeric + * ------------------------------------ + * + * Author: Stephan Bosch + * Specification: RFC 2244 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-comparators.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include <ctype.h> + +/* + * Forward declarations + */ + +static const struct sieve_operand_def my_comparator_operand; + +const struct sieve_comparator_def i_ascii_numeric_comparator; + +/* + * Extension + */ + +static bool ext_cmp_i_ascii_numeric_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def comparator_i_ascii_numeric_extension = { + .name = "comparator-i;ascii-numeric", + .validator_load = ext_cmp_i_ascii_numeric_validator_load, + SIEVE_EXT_DEFINE_OPERAND(my_comparator_operand) +}; + +static bool ext_cmp_i_ascii_numeric_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_comparator_register(validator, ext, &i_ascii_numeric_comparator); + return TRUE; +} + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_comparators = + SIEVE_EXT_DEFINE_COMPARATOR(i_ascii_numeric_comparator); + +static const struct sieve_operand_def my_comparator_operand = { + .name = "comparator-i;ascii-numeric", + .ext_def = &comparator_i_ascii_numeric_extension, + .class = &sieve_comparator_operand_class, + .interface = &ext_comparators +}; + +/* + * Comparator + */ + +/* Forward declarations */ + +static int cmp_i_ascii_numeric_compare + (const struct sieve_comparator *cmp, + const char *val1, size_t val1_size, const char *val2, size_t val2_size); + +/* Comparator object */ + +const struct sieve_comparator_def i_ascii_numeric_comparator = { + SIEVE_OBJECT("i;ascii-numeric", + &my_comparator_operand, 0), + .flags = + SIEVE_COMPARATOR_FLAG_ORDERING | + SIEVE_COMPARATOR_FLAG_EQUALITY, + .compare = cmp_i_ascii_numeric_compare +}; + +/* Comparator implementation */ + +static int cmp_i_ascii_numeric_compare + (const struct sieve_comparator *cmp ATTR_UNUSED, + const char *val, size_t val_size, const char *key, size_t key_size) +{ + const char *vend = val + val_size; + const char *kend = key + key_size; + const char *vp = val; + const char *kp = key; + int digits, i; + + /* RFC 4790: All input is valid; strings that do not start with a digit + * represent positive infinity. + */ + if ( !i_isdigit(*vp) ) { + if ( i_isdigit(*kp) ) { + /* Value is greater */ + return 1; + } + } else { + if ( !i_isdigit(*kp) ) { + /* Value is less */ + return -1; + } + } + + /* Ignore leading zeros */ + + while ( *vp == '0' && vp < vend ) + vp++; + + while ( *kp == '0' && kp < kend ) + kp++; + + /* Check whether both numbers are equally long in terms of digits */ + + digits = 0; + while ( vp < vend && kp < kend && i_isdigit(*vp) && i_isdigit(*kp) ) { + vp++; + kp++; + digits++; + } + + if ( vp == vend || !i_isdigit(*vp) ) { + if ( kp != kend && i_isdigit(*kp) ) { + /* Value is less */ + return -1; + } + } else { + /* Value is greater */ + return 1; + } + + /* Equally long: compare digits */ + + vp -= digits; + kp -= digits; + i = 0; + while ( i < digits ) { + if ( *vp > *kp ) + return 1; + else if ( *vp < *kp ) + return -1; + + kp++; + vp++; + i++; + } + + return 0; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/copy/Makefile.am b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.am new file mode 100644 index 0000000..483032a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.am @@ -0,0 +1,18 @@ +noinst_LTLIBRARIES = libsieve_ext_copy.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_copy_la_SOURCES = \ + ext-copy.c + +public_headers = \ + sieve-ext-copy.h + +headers = + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) + diff --git a/pigeonhole/src/lib-sieve/plugins/copy/Makefile.in b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.in new file mode 100644 index 0000000..9824089 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/Makefile.in @@ -0,0 +1,735 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/copy +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) \ + $(pkginc_lib_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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_copy_la_LIBADD = +am_libsieve_ext_copy_la_OBJECTS = ext-copy.lo +libsieve_ext_copy_la_OBJECTS = $(am_libsieve_ext_copy_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 = +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)/ext-copy.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 = $(libsieve_ext_copy_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_copy_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_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@ +noinst_LTLIBRARIES = libsieve_ext_copy.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_copy_la_SOURCES = \ + ext-copy.c + +public_headers = \ + sieve-ext-copy.h + +headers = +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +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/lib-sieve/plugins/copy/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/copy/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_copy.la: $(libsieve_ext_copy_la_OBJECTS) $(libsieve_ext_copy_la_DEPENDENCIES) $(EXTRA_libsieve_ext_copy_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_copy_la_OBJECTS) $(libsieve_ext_copy_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-copy.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 +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +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)$(pkginc_libdir)"; 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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-copy.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-pkginc_libHEADERS + +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)/ext-copy.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-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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-pkginc_libHEADERS 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-pkginc_libHEADERS + +.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/lib-sieve/plugins/copy/ext-copy.c b/pigeonhole/src/lib-sieve/plugins/copy/ext-copy.c new file mode 100644 index 0000000..e7db9dd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/ext-copy.c @@ -0,0 +1,183 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension copy + * -------------- + * + * Authors: Stephan Bosch + * Specification: RFC 3894 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "sieve-ext-copy.h" + +/* + * Forward declarations + */ + +static const struct sieve_argument_def copy_tag; +static const struct sieve_operand_def copy_side_effect_operand; + +/* + * Extension + */ + +static bool +ext_copy_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); + +const struct sieve_extension_def copy_extension = { + .name = "copy", + .validator_load = ext_copy_validator_load, + SIEVE_EXT_DEFINE_OPERAND(copy_side_effect_operand), +}; + +static bool +ext_copy_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register copy tag with redirect and fileinto commands and we don't + care whether these commands are registered or even whether they will + be registered at all. The validator handles either situation + gracefully. + */ + sieve_validator_register_external_tag(valdtr, "redirect", ext, + ©_tag, SIEVE_OPT_SIDE_EFFECT); + sieve_validator_register_external_tag(valdtr, "fileinto", ext, + ©_tag, SIEVE_OPT_SIDE_EFFECT); + return TRUE; +} + +/* + * Side effect + */ + +static void +seff_copy_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +seff_copy_post_execute(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *tr_context ATTR_UNUSED, + void *se_tr_context ATTR_UNUSED, bool *keep); + +const struct sieve_side_effect_def copy_side_effect = { + SIEVE_OBJECT("copy", ©_side_effect_operand, 0), + .to_action = &act_store, + .print = seff_copy_print, + .post_execute = seff_copy_post_execute, +}; + +/* + * Tagged argument + */ + +static bool +tag_copy_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); +static bool +tag_copy_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, struct sieve_command *cmd); + +static const struct sieve_argument_def copy_tag = { + .identifier = "copy", + .validate = tag_copy_validate, + .generate = tag_copy_generate, +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(copy_side_effect); + +static const struct sieve_operand_def copy_side_effect_operand = { + .name = "copy operand", + .ext_def = ©_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects, +}; + +/* + * Tag registration + */ + +void sieve_ext_copy_register_tag(struct sieve_validator *valdtr, + const struct sieve_extension *copy_ext, + const char *command) +{ + if (sieve_validator_extension_loaded(valdtr, copy_ext)) { + sieve_validator_register_external_tag( + valdtr, command, copy_ext, ©_tag, + SIEVE_OPT_SIDE_EFFECT); + } +} + +/* + * Tag validation + */ + +static bool +tag_copy_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED) +{ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_copy_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, sieve_argument_ext(arg), + ©_side_effect); + return TRUE; +} + +/* + * Side effect implementation + */ + +static void +seff_copy_print(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, bool *keep) +{ + sieve_result_seffect_printf(rpenv, "preserve implicit keep"); + *keep = TRUE; +} + +static int +seff_copy_post_execute(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action_exec_env *aenv ATTR_UNUSED, + void *tr_context ATTR_UNUSED, + void *se_tr_context ATTR_UNUSED, bool *keep) +{ + *keep = TRUE; + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/copy/sieve-ext-copy.h b/pigeonhole/src/lib-sieve/plugins/copy/sieve-ext-copy.h new file mode 100644 index 0000000..faf19dc --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/copy/sieve-ext-copy.h @@ -0,0 +1,21 @@ +#ifndef SIEVE_EXT_COPY_H +#define SIEVE_EXT_COPY_H + +/* sieve_ext_copy_get_extension(): + * Get the extension struct for the copy extension. + */ +static inline const struct sieve_extension *sieve_ext_copy_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_get_by_name(svinst, "copy"); +} + +/* sieve_ext_copy_register_tag(): + * Register the :copy tagged argument for a command other than fileinto and + * redirect. + */ +void sieve_ext_copy_register_tag + (struct sieve_validator *valdtr, const struct sieve_extension *copy_ext, + const char *command); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/date/Makefile.am b/pigeonhole/src/lib-sieve/plugins/date/Makefile.am new file mode 100644 index 0000000..bf257ac --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_date.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-date.c + +libsieve_ext_date_la_SOURCES = \ + $(tests) \ + ext-date-common.c \ + ext-date.c + +noinst_HEADERS = \ + ext-date-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/date/Makefile.in b/pigeonhole/src/lib-sieve/plugins/date/Makefile.in new file mode 100644 index 0000000..0bc3ec0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/date +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_date_la_LIBADD = +am__objects_1 = tst-date.lo +am_libsieve_ext_date_la_OBJECTS = $(am__objects_1) ext-date-common.lo \ + ext-date.lo +libsieve_ext_date_la_OBJECTS = $(am_libsieve_ext_date_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 = +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)/ext-date-common.Plo \ + ./$(DEPDIR)/ext-date.Plo ./$(DEPDIR)/tst-date.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 = $(libsieve_ext_date_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_date_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@ +noinst_LTLIBRARIES = libsieve_ext_date.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-date.c + +libsieve_ext_date_la_SOURCES = \ + $(tests) \ + ext-date-common.c \ + ext-date.c + +noinst_HEADERS = \ + ext-date-common.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/lib-sieve/plugins/date/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/date/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_date.la: $(libsieve_ext_date_la_OBJECTS) $(libsieve_ext_date_la_DEPENDENCIES) $(EXTRA_libsieve_ext_date_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_date_la_OBJECTS) $(libsieve_ext_date_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-date-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-date.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-date.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-date-common.Plo + -rm -f ./$(DEPDIR)/ext-date.Plo + -rm -f ./$(DEPDIR)/tst-date.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-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)/ext-date-common.Plo + -rm -f ./$(DEPDIR)/ext-date.Plo + -rm -f ./$(DEPDIR)/tst-date.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/date/ext-date-common.c b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.c new file mode 100644 index 0000000..7493b87 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.c @@ -0,0 +1,593 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "utc-offset.h" +#include "str.h" +#include "iso8601-date.h" +#include "message-date.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-message.h" + +#include "ext-date-common.h" + +#include <time.h> +#include <ctype.h> + +struct ext_date_context { + time_t current_date; + int zone_offset; +}; + +/* + * Runtime initialization + */ + +static int ext_date_runtime_init +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred ATTR_UNUSED) +{ + struct ext_date_context *dctx; + pool_t pool; + struct timeval msg_time; + time_t current_date; + struct tm *tm; + int zone_offset; + + /* Get current time at instance main script is started */ + sieve_message_context_time(renv->msgctx, &msg_time); + current_date = msg_time.tv_sec; + + tm = localtime(¤t_date); + zone_offset = utc_offset(tm, current_date); + + /* Create context */ + pool = sieve_message_context_pool(renv->msgctx); + dctx = p_new(pool, struct ext_date_context, 1); + dctx->current_date = current_date; + dctx->zone_offset = zone_offset; + + sieve_message_context_extension_set + (renv->msgctx, ext, (void *) dctx); + return SIEVE_EXEC_OK; +} + +static struct sieve_interpreter_extension +date_interpreter_extension = { + .ext_def = &date_extension, + .run = ext_date_runtime_init +}; + +bool ext_date_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + /* Register runtime hook to obtain stript start timestamp */ + if ( renv->msgctx == NULL || + sieve_message_context_extension_get(renv->msgctx, ext) == NULL ) { + sieve_interpreter_extension_register + (renv->interp, ext, &date_interpreter_extension, NULL); + } + + return TRUE; +} + +/* + * Zone string + */ + +bool ext_date_parse_timezone +(const char *zone, int *zone_offset_r) +{ + const unsigned char *str = (const unsigned char *) zone; + size_t len = strlen(zone); + + if (len == 5 && (*str == '+' || *str == '-')) { + int offset; + + if (!i_isdigit(str[1]) || !i_isdigit(str[2]) || + !i_isdigit(str[3]) || !i_isdigit(str[4])) + return FALSE; + + offset = ((str[1]-'0') * 10 + (str[2]-'0')) * 60 + + (str[3]-'0') * 10 + (str[4]-'0'); + + if ( zone_offset_r != NULL ) + *zone_offset_r = *str == '+' ? offset : -offset; + + return TRUE; + } + + return FALSE; +} + +/* + * Current date + */ + +time_t ext_date_get_current_date +(const struct sieve_runtime_env *renv, int *zone_offset_r) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_date_context *dctx = (struct ext_date_context *) + sieve_message_context_extension_get(renv->msgctx, this_ext); + + if ( dctx == NULL ) { + ext_date_runtime_init(this_ext, renv, NULL, FALSE); + dctx = (struct ext_date_context *) + sieve_message_context_extension_get(renv->msgctx, this_ext); + + i_assert(dctx != NULL); + } + + /* Read script start timestamp from message context */ + + if ( zone_offset_r != NULL ) + *zone_offset_r = dctx->zone_offset; + + return dctx->current_date; +} + +/* + * Date parts + */ + +/* "year" => the year, "0000" .. "9999". + */ + +static const char *ext_date_year_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part year_date_part = { + "year", + ext_date_year_part_get +}; + +/* "month" => the month, "01" .. "12". + */ + +static const char *ext_date_month_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part month_date_part = { + "month", + ext_date_month_part_get +}; + +/* "day" => the day, "01" .. "31". + */ + +static const char *ext_date_day_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part day_date_part = { + "day", + ext_date_day_part_get +}; + +/* "date" => the date in "yyyy-mm-dd" format. + */ + +static const char *ext_date_date_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part date_date_part = { + "date", + ext_date_date_part_get +}; + +/* "julian" => the Modified Julian Day, that is, the date + * expressed as an integer number of days since + * 00:00 UTC on November 17, 1858 (using the Gregorian + * calendar). This corresponds to the regular + * Julian Day minus 2400000.5. Sample routines to + * convert to and from modified Julian dates are + * given in Appendix A. + */ + +static const char *ext_date_julian_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part julian_date_part = { + "julian", + ext_date_julian_part_get +}; + +/* "hour" => the hour, "00" .. "23". + */ +static const char *ext_date_hour_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part hour_date_part = { + "hour", + ext_date_hour_part_get +}; + +/* "minute" => the minute, "00" .. "59". + */ +static const char *ext_date_minute_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part minute_date_part = { + "minute", + ext_date_minute_part_get +}; + +/* "second" => the second, "00" .. "60". + */ +static const char *ext_date_second_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part second_date_part = { + "second", + ext_date_second_part_get +}; + +/* "time" => the time in "hh:mm:ss" format. + */ +static const char *ext_date_time_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part time_date_part = { + "time", + ext_date_time_part_get +}; + +/* "iso8601" => the date and time in restricted ISO 8601 format. + */ +static const char *ext_date_iso8601_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part iso8601_date_part = { + "iso8601", + ext_date_iso8601_part_get +}; + +/* "std11" => the date and time in a format appropriate + * for use in a Date: header field [RFC2822]. + */ +static const char *ext_date_std11_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part std11_date_part = { + "std11", + ext_date_std11_part_get +}; + +/* "zone" => the time zone in use. If the user specified a + * time zone with ":zone", "zone" will + * contain that value. If :originalzone is specified + * this value will be the original zone specified + * in the date-time value. If neither argument is + * specified the value will be the server's default + * time zone in offset format "+hhmm" or "-hhmm". An + * offset of 0 (Zulu) always has a positive sign. + */ +static const char *ext_date_zone_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part zone_date_part = { + "zone", + ext_date_zone_part_get +}; + +/* "weekday" => the day of the week expressed as an integer between + * "0" and "6". "0" is Sunday, "1" is Monday, etc. + */ +static const char *ext_date_weekday_part_get(struct tm *tm, int zone_offset); + +static const struct ext_date_part weekday_date_part = { + "weekday", + ext_date_weekday_part_get +}; + +/* + * Date part extraction + */ + +static const struct ext_date_part *date_parts[] = { + &year_date_part, &month_date_part, &day_date_part, &date_date_part, + &julian_date_part, &hour_date_part, &minute_date_part, &second_date_part, + &time_date_part, &iso8601_date_part, &std11_date_part, &zone_date_part, + &weekday_date_part +}; + +unsigned int date_parts_count = N_ELEMENTS(date_parts); + +const struct ext_date_part *ext_date_part_find(const char *part) +{ + unsigned int i; + + for ( i = 0; i < date_parts_count; i++ ) { + if ( strcasecmp(date_parts[i]->identifier, part) == 0 ) { + return date_parts[i]; + } + } + + return NULL; +} + +const char *ext_date_part_extract +(const struct ext_date_part *dpart, struct tm *tm, int zone_offset) +{ + if ( dpart == NULL || dpart->get_string == NULL ) + return NULL; + + return dpart->get_string(tm, zone_offset); +} + +/* + * Date part implementations + */ + +static const char *month_names[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const char *weekday_names[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const char *ext_date_year_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%04d", tm->tm_year + 1900); +} + +static const char *ext_date_month_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_mon + 1); +} + +static const char *ext_date_day_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_mday); +} + +static const char *ext_date_date_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%04d-%02d-%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); +} + +static const char *ext_date_julian_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + int year = tm->tm_year+1900; + int month = tm->tm_mon+1; + int day = tm->tm_mday; + int c, ya, jd; + + /* Modified from RFC 5260 Appendix A (refer to Errata) */ + + if ( month > 2 ) + month -= 3; + else { + month += 9; + year--; + } + + c = year / 100; + ya = year - c * 100; + + jd = c * 146097 / 4 + ya * 1461 / 4 + (month * 153 + 2) / 5 + day + 1721119; + + return t_strdup_printf("%d", jd - 2400001); +} + +static const char *ext_date_hour_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_hour); +} + +static const char *ext_date_minute_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_min); +} + +static const char *ext_date_second_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d", tm->tm_sec); +} + +static const char *ext_date_time_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +static const char *ext_date_iso8601_part_get +(struct tm *tm, int zone_offset) +{ + /* From RFC: `The restricted ISO 8601 format is specified by the date-time + * ABNF production given in [RFC3339], Section 5.6, with the added + * restrictions that the letters "T" and "Z" MUST be in upper case, and + * a time zone offset of zero MUST be represented by "Z" and not "+00:00". + */ + if ( zone_offset == 0 ) + zone_offset = INT_MAX; + + return iso8601_date_create_tm(tm, zone_offset); +} + + +static const char *ext_date_std11_part_get +(struct tm *tm, int zone_offset) +{ + return t_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %s", + weekday_names[tm->tm_wday], + tm->tm_mday, + month_names[tm->tm_mon], + tm->tm_year+1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + ext_date_zone_part_get(tm, zone_offset)); +} + +static const char *ext_date_zone_part_get +(struct tm *tm ATTR_UNUSED, int zone_offset) +{ + bool negative; + int offset = zone_offset; + + if (zone_offset >= 0) + negative = FALSE; + else { + negative = TRUE; + offset = -offset; + } + + return t_strdup_printf + ("%c%02d%02d", negative ? '-' : '+', offset / 60, offset % 60); +} + +static const char *ext_date_weekday_part_get +(struct tm *tm, int zone_offset ATTR_UNUSED) +{ + return t_strdup_printf("%d", tm->tm_wday); +} + +/* + * Date stringlist + */ + +/* Forward declarations */ + +static int ext_date_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void ext_date_stringlist_reset + (struct sieve_stringlist *_strlist); + +/* Stringlist object */ + +struct ext_date_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *field_values; + int time_zone; + const struct ext_date_part *date_part; + + time_t local_time; + int local_zone; + + bool read:1; +}; + +struct sieve_stringlist *ext_date_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *field_values, + int time_zone, const struct ext_date_part *dpart) +{ + struct ext_date_stringlist *strlist; + + strlist = t_new(struct ext_date_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = ext_date_stringlist_next_item; + strlist->strlist.reset = ext_date_stringlist_reset; + strlist->field_values = field_values; + strlist->time_zone = time_zone; + strlist->date_part = dpart; + + strlist->local_time = ext_date_get_current_date(renv, &strlist->local_zone); + + return &strlist->strlist; +} + +/* Stringlist implementation */ + +static int ext_date_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct ext_date_stringlist *strlist = + (struct ext_date_stringlist *) _strlist; + bool got_date = FALSE; + time_t date_value; + const char *part_value = NULL; + int original_zone; + + /* Check whether the item was already read */ + if ( strlist->read ) return 0; + + if ( strlist->field_values != NULL ) { + string_t *hdr_item; + const char *header_value, *date_string; + int ret; + + /* Use header field value */ + + /* Read first */ + if ( (ret=sieve_stringlist_next_item(strlist->field_values, &hdr_item)) + <= 0 ) + return ret; + + /* Extract the date string value */ + + header_value = str_c(hdr_item); + date_string = strrchr(header_value, ';'); + + if ( date_string == NULL ) { + /* Direct header value */ + date_string = header_value; + } else { + /* Delimited by ';', e.g. a Received: header */ + date_string++; + } + + /* Parse the date value */ + if ( message_date_parse((const unsigned char *) date_string, + strlen(date_string), &date_value, &original_zone) ) { + got_date = TRUE; + } + } else { + /* Use time stamp recorded at the time the script first started */ + date_value = strlist->local_time; + original_zone = strlist->local_zone; + got_date = TRUE; + } + + if ( got_date ) { + int wanted_zone; + struct tm *date_tm; + + /* Apply wanted timezone */ + + switch ( strlist->time_zone ) { + case EXT_DATE_TIMEZONE_LOCAL: + wanted_zone = strlist->local_zone; + break; + case EXT_DATE_TIMEZONE_ORIGINAL: + wanted_zone = original_zone; + break; + default: + wanted_zone = strlist->time_zone; + } + + date_value += wanted_zone * 60; + + /* Convert timestamp to struct tm */ + + if ( (date_tm=gmtime(&date_value)) != NULL ) { + /* Extract the date part */ + part_value = ext_date_part_extract + (strlist->date_part, date_tm, wanted_zone); + } + } + + strlist->read = TRUE; + + if ( part_value == NULL ) + return 0; + + *str_r = t_str_new_const(part_value, strlen(part_value)); + return 1; +} + +static void ext_date_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct ext_date_stringlist *strlist = + (struct ext_date_stringlist *) _strlist; + + if ( strlist->field_values != NULL ) + sieve_stringlist_reset(strlist->field_values); + strlist->read = FALSE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.h b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.h new file mode 100644 index 0000000..116af3e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/ext-date-common.h @@ -0,0 +1,80 @@ +#ifndef EXT_DATE_COMMON_H +#define EXT_DATE_COMMON_H + +#include "sieve-common.h" + +#include <time.h> + +/* + * Extension + */ + +extern const struct sieve_extension_def date_extension; + +bool ext_date_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED); + +/* + * Tests + */ + +extern const struct sieve_command_def date_test; +extern const struct sieve_command_def currentdate_test; + +/* + * Operations + */ + +enum ext_date_opcode { + EXT_DATE_OPERATION_DATE, + EXT_DATE_OPERATION_CURRENTDATE +}; + +extern const struct sieve_operation_def date_operation; +extern const struct sieve_operation_def currentdate_operation; + +/* + * Zone string + */ + +bool ext_date_parse_timezone(const char *zone, int *zone_offset_r); + +/* + * Current date + */ + +time_t ext_date_get_current_date + (const struct sieve_runtime_env *renv, int *zone_offset_r); + +/* + * Date part + */ + +struct ext_date_part { + const char *identifier; + + const char *(*get_string)(struct tm *tm, int zone_offset); +}; + +const struct ext_date_part *ext_date_part_find(const char *part); + +const char *ext_date_part_extract + (const struct ext_date_part *dpart, struct tm *tm, int zone_offset); + +/* + * Date stringlist + */ + +enum ext_date_timezone_special { + EXT_DATE_TIMEZONE_LOCAL = 100, + EXT_DATE_TIMEZONE_ORIGINAL = 101 +}; + +struct sieve_stringlist *ext_date_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *field_values, + int time_zone, const struct ext_date_part *dpart); + + + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/date/ext-date.c b/pigeonhole/src/lib-sieve/plugins/date/ext-date.c new file mode 100644 index 0000000..3880d82 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/ext-date.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension date + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5260 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-date-common.h" + +/* + * Extension + */ + +static bool ext_date_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_operation_def *ext_date_operations[] = { + &date_operation, + ¤tdate_operation +}; + +const struct sieve_extension_def date_extension = { + .name = "date", + .validator_load = ext_date_validator_load, + .interpreter_load = ext_date_interpreter_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_date_operations) +}; + +static bool ext_date_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &date_test); + sieve_validator_register_command(valdtr, ext, ¤tdate_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/date/tst-date.c b/pigeonhole/src/lib-sieve/plugins/date/tst-date.c new file mode 100644 index 0000000..60ee92c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/date/tst-date.c @@ -0,0 +1,496 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" +#include "sieve-message.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-date-common.h" + +#include <time.h> + +/* + * Tests + */ + +static bool tst_date_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_date_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +/* Date test + * + * Syntax: + * date [<":zone" <time-zone: string>> / ":originalzone"] + * [COMPARATOR] [MATCH-TYPE] <header-name: string> + * <date-part: string> <key-list: string-list> + */ + +static bool tst_date_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +const struct sieve_command_def date_test = { + .identifier = "date", + .type = SCT_TEST, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_date_registered, + .validate = tst_date_validate, + .generate = tst_date_generate +}; + +/* Currentdate test + * + * Syntax: + * currentdate [":zone" <time-zone: string>] + * [COMPARATOR] [MATCH-TYPE] + * <date-part: string> <key-list: string-list> + */ + +static bool tst_currentdate_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +const struct sieve_command_def currentdate_test = { + .identifier = "currentdate", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_currentdate_registered, + .validate = tst_date_validate, + .generate = tst_date_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool tag_zone_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_zone_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def date_zone_tag = { + .identifier = "zone", + .validate = tag_zone_validate, + .generate = tag_zone_generate +}; + +static const struct sieve_argument_def date_originalzone_tag = { + .identifier = "originalzone", + .validate = tag_zone_validate, + .generate = tag_zone_generate +}; + +/* + * Date operation + */ + +static bool tst_date_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_date_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def date_operation = { + .mnemonic = "DATE", + .ext_def = &date_extension, + .code = EXT_DATE_OPERATION_DATE, + .dump = tst_date_operation_dump, + .execute = tst_date_operation_execute +}; + +const struct sieve_operation_def currentdate_operation = { + .mnemonic = "CURRENTDATE", + .ext_def = &date_extension, + .code = EXT_DATE_OPERATION_CURRENTDATE, + .dump = tst_date_operation_dump, + .execute = tst_date_operation_execute +}; + +/* + * Optional operands + */ + +enum tst_date_optional { + OPT_DATE_ZONE = SIEVE_AM_OPT_LAST, + OPT_DATE_LAST +}; + +/* + * Tag implementation + */ + +static bool tag_zone_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + if ( (bool) cmd->data ) { + if ( sieve_command_is(cmd, date_test) ) { + sieve_argument_validate_error(valdtr, *arg, + "multiple :zone or :originalzone arguments specified for " + "the currentdate test"); + } else { + sieve_argument_validate_error(valdtr, *arg, + "multiple :zone arguments specified for the currentdate test"); + } + return FALSE; + } + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + /* :content tag has a string-list argument */ + if ( sieve_argument_is(tag, date_zone_tag) ) { + + /* Check syntax: + * :zone <time-zone: string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, FALSE) ) { + return FALSE; + } + + /* Check it */ + if ( sieve_argument_is_string_literal(*arg) ) { + const char *zone = sieve_ast_argument_strc(*arg); + + if ( !ext_date_parse_timezone(zone, NULL) ) { + sieve_argument_validate_warning(valdtr, *arg, + "specified :zone argument '%s' is not a valid timezone", + str_sanitize(zone, 40)); + } + } + + /* Assign tag parameters */ + tag->parameters = *arg; + *arg = sieve_ast_arguments_detach(*arg,1); + } + + cmd->data = (void *) TRUE; + + return TRUE; +} + +/* + * Test registration + */ + +static bool tst_date_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &date_zone_tag, OPT_DATE_ZONE); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &date_originalzone_tag, OPT_DATE_ZONE); + + return TRUE; +} + +static bool tst_currentdate_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &date_zone_tag, OPT_DATE_ZONE); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_date_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + unsigned int arg_offset = 0 ; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + /* Check header name */ + + if ( sieve_command_is(tst, date_test) ) { + arg_offset = 1; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "header name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + if ( !sieve_command_verify_headers_argument(valdtr, arg) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + } + + /* Check date part */ + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "date part", arg_offset + 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + const char * part = sieve_ast_argument_strc(arg); + + if ( ext_date_part_find(part) == NULL ) { + sieve_argument_validate_warning + (valdtr, arg, "specified date part `%s' is not known", + str_sanitize(part, 80)); + } + } + + arg = sieve_ast_argument_next(arg); + + /* Check key list */ + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", arg_offset + 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_date_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + if ( sieve_command_is(tst, date_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, &date_operation); + else if ( sieve_command_is(tst, currentdate_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, ¤tdate_operation); + else + i_unreached(); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +static bool tag_zone_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + if ( arg->parameters == NULL ) { + sieve_opr_omitted_emit(cgenv->sblock); + return TRUE; + } + + return sieve_generate_argument_parameters(cgenv, cmd, arg); +} + +/* + * Code dump + */ + +static bool tst_date_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + const struct sieve_operation *op = denv->oprtn; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + for (;;) { + int opt; + + if ( (opt=sieve_message_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_DATE_ZONE: + if ( !sieve_opr_string_dump_ex(denv, address, "zone", "ORIGINAL") ) + return FALSE; + break; + default: + return FALSE; + } + } + + if ( sieve_operation_is(op, date_operation) && + !sieve_opr_string_dump(denv, address, "header name") ) + return FALSE; + + return + sieve_opr_string_dump(denv, address, "date part") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + + +/* + * Code execution + */ + +static int tst_date_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + int opt_code = 0; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + ARRAY_TYPE(sieve_message_override) svmos; + string_t *date_part = NULL, *zone = NULL; + struct sieve_stringlist *hdr_list = NULL, *hdr_value_list; + struct sieve_stringlist *value_list, *key_list; + bool zone_specified = FALSE, zone_literal = TRUE; + const struct ext_date_part *dpart; + int time_zone; + int match, ret; + + /* Read optional operands */ + for (;;) { + int opt; + + /* Optional operands */ + i_zero(&svmos); + if ( (opt=sieve_message_opr_optional_read + (renv, address, &opt_code, &ret, NULL, &mcht, &cmp, &svmos)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_DATE_ZONE: + if ( (ret=sieve_opr_string_read_ex + (renv, address, "zone", TRUE, &zone, &zone_literal)) <= 0 ) + return ret; + + zone_specified = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + if ( sieve_operation_is(op, date_operation) ) { + /* Read header name as stringlist */ + if ( (ret=sieve_opr_stringlist_read + (renv, address, "header-name", &hdr_list)) <= 0 ) + return ret; + } + + /* Read date part */ + if ( (ret=sieve_opr_string_read(renv, address, "date-part", &date_part)) + <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* Determine what time zone to use in the result */ + if ( !zone_specified ) { + time_zone = EXT_DATE_TIMEZONE_LOCAL; + } else if ( zone == NULL ) { + time_zone = EXT_DATE_TIMEZONE_ORIGINAL; + } else if ( !ext_date_parse_timezone(str_c(zone), &time_zone) ) { + if ( !zone_literal ) + sieve_runtime_warning(renv, NULL, + "specified :zone argument `%s' is not a valid timezone " + "(using local zone)", str_sanitize(str_c(zone), 40)); + time_zone = EXT_DATE_TIMEZONE_LOCAL; + } + + if ( (dpart=ext_date_part_find(str_c(date_part))) == NULL ) { + sieve_runtime_warning(renv, NULL, + "specified date part argument `%s' is not known", + str_sanitize(str_c(date_part), 40)); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + /* + * Perform test + */ + + if ( sieve_operation_is(op, date_operation) ) { + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "date test"); + + /* Get header */ + sieve_runtime_trace_descend(renv); + if ( (ret=sieve_message_get_header_fields + (renv, hdr_list, &svmos, FALSE, &hdr_value_list)) <= 0 ) + return ret; + sieve_runtime_trace_ascend(renv); + + /* Create value stringlist */ + value_list = ext_date_stringlist_create + (renv, hdr_value_list, time_zone, dpart); + + } else if ( sieve_operation_is(op, currentdate_operation) ) { + /* Use time stamp recorded at the time the script first started */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "currentdatedate test"); + + /* Create value stringlist */ + value_list = ext_date_stringlist_create(renv, NULL, time_zone, dpart); + } else { + i_unreached(); + } + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.am b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.am new file mode 100644 index 0000000..7469b98 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.am @@ -0,0 +1,20 @@ +noinst_LTLIBRARIES = libsieve_ext_duplicate.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-duplicate.c + +extensions = \ + ext-duplicate.c + +libsieve_ext_duplicate_la_SOURCES = \ + $(tests) \ + $(extensions) \ + ext-duplicate-common.c + +noinst_HEADERS = \ + ext-duplicate-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.in b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.in new file mode 100644 index 0000000..d29f834 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/Makefile.in @@ -0,0 +1,697 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/duplicate +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_duplicate_la_LIBADD = +am__objects_1 = tst-duplicate.lo +am__objects_2 = ext-duplicate.lo +am_libsieve_ext_duplicate_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) ext-duplicate-common.lo +libsieve_ext_duplicate_la_OBJECTS = \ + $(am_libsieve_ext_duplicate_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 = +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)/ext-duplicate-common.Plo \ + ./$(DEPDIR)/ext-duplicate.Plo ./$(DEPDIR)/tst-duplicate.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 = $(libsieve_ext_duplicate_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_duplicate_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@ +noinst_LTLIBRARIES = libsieve_ext_duplicate.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-duplicate.c + +extensions = \ + ext-duplicate.c + +libsieve_ext_duplicate_la_SOURCES = \ + $(tests) \ + $(extensions) \ + ext-duplicate-common.c + +noinst_HEADERS = \ + ext-duplicate-common.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/lib-sieve/plugins/duplicate/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/duplicate/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_duplicate.la: $(libsieve_ext_duplicate_la_OBJECTS) $(libsieve_ext_duplicate_la_DEPENDENCIES) $(EXTRA_libsieve_ext_duplicate_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_duplicate_la_OBJECTS) $(libsieve_ext_duplicate_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-duplicate-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-duplicate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-duplicate.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-duplicate-common.Plo + -rm -f ./$(DEPDIR)/ext-duplicate.Plo + -rm -f ./$(DEPDIR)/tst-duplicate.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-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)/ext-duplicate-common.Plo + -rm -f ./$(DEPDIR)/ext-duplicate.Plo + -rm -f ./$(DEPDIR)/tst-duplicate.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/duplicate/ext-duplicate-common.c b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.c new file mode 100644 index 0000000..5af7e04 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.c @@ -0,0 +1,298 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "md5.h" +#include "ioloop.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-message.h" +#include "sieve-code.h" +#include "sieve-runtime.h" +#include "sieve-interpreter.h" +#include "sieve-actions.h" +#include "sieve-result.h" + +#include "ext-duplicate-common.h" + +/* + * Extension configuration + */ + +#define EXT_DUPLICATE_DEFAULT_PERIOD (12*60*60) +#define EXT_DUPLICATE_DEFAULT_MAX_PERIOD (2*24*60*60) + +bool ext_duplicate_load(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_duplicate_config *config; + sieve_number_t default_period, max_period; + + if (*context != NULL) + ext_duplicate_unload(ext); + + if (!sieve_setting_get_duration_value( + svinst, "sieve_duplicate_default_period", &default_period)) + default_period = EXT_DUPLICATE_DEFAULT_PERIOD; + if (!sieve_setting_get_duration_value( + svinst, "sieve_duplicate_max_period", &max_period)) { + max_period = EXT_DUPLICATE_DEFAULT_MAX_PERIOD; + } + + config = i_new(struct ext_duplicate_config, 1); + config->default_period = default_period; + config->max_period = max_period; + + *context = (void *) config; + return TRUE; +} + +void ext_duplicate_unload(const struct sieve_extension *ext) +{ + struct ext_duplicate_config *config = + (struct ext_duplicate_config *)ext->context; + + i_free(config); +} + +/* + * Duplicate_mark action + */ + +struct act_duplicate_mark_data { + const char *handle; + unsigned int period; + unsigned char hash[MD5_RESULTLEN]; + bool last:1; +}; + +static void +act_duplicate_mark_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static void +act_duplicate_mark_finish(const struct sieve_action_exec_env *aenv, + void *tr_context, int status); + +static const struct sieve_action_def act_duplicate_mark = { + .name = "duplicate_mark", + .print = act_duplicate_mark_print, + .finish = act_duplicate_mark_finish +}; + +static void +act_duplicate_mark_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct act_duplicate_mark_data *data = + (struct act_duplicate_mark_data *)action->context; + const char *last = (data->last ? " last" : ""); + + if (data->handle != NULL) { + sieve_result_action_printf( + rpenv, "track%s duplicate with handle: %s", + last, str_sanitize(data->handle, 128)); + } else { + sieve_result_action_printf(rpenv, "track%s duplicate", last); + } +} + +static void +act_duplicate_mark_finish(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED, int status) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_duplicate_mark_data *data = + (struct act_duplicate_mark_data *)aenv->action->context; + + if (status != SIEVE_EXEC_OK) { + e_debug(aenv->event, "Not marking duplicate (status=%s)", + sieve_execution_exitcode_to_str(status)); + return; + } + + e_debug(aenv->event, "Marking duplicate"); + + /* Message was handled successfully, so track duplicate for this + * message. + */ + eenv->exec_status->significant_action_executed = TRUE; + sieve_action_duplicate_mark(aenv, data->hash, sizeof(data->hash), + ioloop_time + data->period); +} + +/* + * Duplicate checking + */ + +struct ext_duplicate_handle { + const char *handle; + bool last:1; + bool duplicate:1; +}; + +struct ext_duplicate_hash { + unsigned char hash[MD5_RESULTLEN]; + ARRAY(struct ext_duplicate_handle) handles; +}; + +struct ext_duplicate_context { + ARRAY(struct ext_duplicate_hash) hashes; +}; + +static void +ext_duplicate_hash(string_t *handle, const char *value, size_t value_len, + bool last, unsigned char hash_r[]) +{ + static const char *id = "sieve duplicate"; + struct md5_context md5ctx; + + md5_init(&md5ctx); + md5_update(&md5ctx, id, strlen(id)); + if (last) + md5_update(&md5ctx, "0", 1); + else + md5_update(&md5ctx, "+", 1); + if (handle != NULL) { + md5_update(&md5ctx, "h-", 2); + md5_update(&md5ctx, str_c(handle), str_len(handle)); + } else { + md5_update(&md5ctx, "default", 7); + } + md5_update(&md5ctx, value, value_len); + md5_final(&md5ctx, hash_r); +} + +int ext_duplicate_check(const struct sieve_runtime_env *renv, string_t *handle, + const char *value, size_t value_len, + sieve_number_t period, bool last, bool *duplicate_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_duplicate_context *rctx; + bool duplicate = FALSE; + pool_t msg_pool = NULL, result_pool = NULL; + unsigned char hash[MD5_RESULTLEN]; + struct ext_duplicate_hash *hash_record = NULL; + struct ext_duplicate_handle *handle_record = NULL; + struct act_duplicate_mark_data *act; + int ret; + + *duplicate_r = FALSE; + + if (!sieve_execute_duplicate_check_available(eenv)) { + sieve_runtime_warning( + renv, NULL, "duplicate test: " + "duplicate checking not available in this context"); + return SIEVE_EXEC_OK; + } + + if (value == NULL) + return SIEVE_EXEC_OK; + + /* Create hash */ + ext_duplicate_hash(handle, value, value_len, last, hash); + + /* Get context; find out whether duplicate was checked earlier */ + rctx = (struct ext_duplicate_context *) + sieve_message_context_extension_get(renv->msgctx, this_ext); + + if (rctx == NULL) { + /* Create context */ + msg_pool = sieve_message_context_pool(renv->msgctx); + rctx = p_new(msg_pool, struct ext_duplicate_context, 1); + sieve_message_context_extension_set(renv->msgctx, this_ext, + (void *)rctx); + } else if (array_is_created(&rctx->hashes)) { + struct ext_duplicate_hash *record; + + array_foreach_modifiable(&rctx->hashes, record) { + if (memcmp(record->hash, hash, MD5_RESULTLEN) == 0) { + hash_record = record; + break; + } + } + } + if (hash_record != NULL) { + const struct ext_duplicate_handle *rhandle; + array_foreach(&hash_record->handles, rhandle) { + const char *handle_str = + (handle == NULL ? NULL : str_c(handle)); + if (null_strcmp(rhandle->handle, handle_str) == 0 && + rhandle->last == last) + return (rhandle->duplicate ? + SIEVE_DUPLICATE_CHECK_RESULT_EXISTS : + SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND); + } + } + + result_pool = sieve_result_pool(renv->result); + act = p_new(result_pool, struct act_duplicate_mark_data, 1); + if (handle != NULL) + act->handle = p_strdup(result_pool, str_c(handle)); + act->period = period; + memcpy(act->hash, hash, MD5_RESULTLEN); + act->last = last; + + /* Check duplicate */ + ret = sieve_execute_duplicate_check(eenv, hash, sizeof(hash), + &duplicate); + if (ret >= SIEVE_EXEC_OK && !duplicate && last) { + unsigned char no_last_hash[MD5_RESULTLEN]; + + /* Check for entry without :last */ + ext_duplicate_hash(handle, value, value_len, + FALSE, no_last_hash); + ret = sieve_execute_duplicate_check( + eenv, no_last_hash, sizeof(no_last_hash), + &duplicate); + } + if (ret < SIEVE_EXEC_OK) { + sieve_runtime_critical( + renv, NULL, "failed to check for duplicate", + "failed to check for duplicate%s", + (ret == SIEVE_EXEC_TEMP_FAILURE ? + " (temporary failure)" : "")); + return ret; + } + + /* We may only mark the message as duplicate when Sieve script executes + * successfully; therefore defer this operation until successful result + * execution. + */ + if (!duplicate || last) { + if (sieve_result_add_action(renv, NULL, NULL, + &act_duplicate_mark, + NULL, (void *) act, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + } + + /* Cache result */ + if (msg_pool == NULL) + msg_pool = sieve_message_context_pool(renv->msgctx); + if (hash_record == NULL) { + if (!array_is_created(&rctx->hashes)) + p_array_init(&rctx->hashes, msg_pool, 64); + hash_record = array_append_space(&rctx->hashes); + memcpy(hash_record->hash, hash, MD5_RESULTLEN); + p_array_init(&hash_record->handles, msg_pool, 64); + } + + handle_record = array_append_space(&hash_record->handles); + if (handle != NULL) + handle_record->handle = p_strdup(msg_pool, str_c(handle)); + handle_record->last = last; + handle_record->duplicate = duplicate; + + *duplicate_r = duplicate; + + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.h b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.h new file mode 100644 index 0000000..c802b08 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate-common.h @@ -0,0 +1,41 @@ +#ifndef EXT_DUPLICATE_COMMON_H +#define EXT_DUPLICATE_COMMON_H + +#include "sieve-common.h" + +/* + * Extension + */ + +struct ext_duplicate_config { + unsigned int default_period; + unsigned int max_period; +}; + +bool ext_duplicate_load(const struct sieve_extension *ext, void **context); +void ext_duplicate_unload(const struct sieve_extension *ext); + +extern const struct sieve_extension_def duplicate_extension; +extern const struct sieve_extension_def vnd_duplicate_extension; + +/* + * Tests + */ + +extern const struct sieve_command_def tst_duplicate; + +/* + * Operations + */ + +extern const struct sieve_operation_def tst_duplicate_operation; + +/* + * Duplicate checking + */ + +int ext_duplicate_check(const struct sieve_runtime_env *renv, string_t *handle, + const char *value, size_t value_len, + sieve_number_t period, bool last, bool *duplicate_r); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate.c b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate.c new file mode 100644 index 0000000..54de5e5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/ext-duplicate.c @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension duplicate + * ------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-duplicate + * Implementation: full + * Status: experimental + * + */ + +/* Extension vnd.dovecot.duplicate + * ------------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-duplicate + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: experimental + * + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" + +#include "ext-duplicate-common.h" + +/* + * Extensions + */ + +static bool ext_duplicate_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def duplicate_extension = { + .name = "duplicate", + .load = ext_duplicate_load, + .unload = ext_duplicate_unload, + .validator_load = ext_duplicate_validator_load, + SIEVE_EXT_DEFINE_OPERATION(tst_duplicate_operation) +}; + +const struct sieve_extension_def vnd_duplicate_extension = { + .name = "vnd.dovecot.duplicate", + .load = ext_duplicate_load, + .unload = ext_duplicate_unload, + .validator_load = ext_duplicate_validator_load, + SIEVE_EXT_DEFINE_OPERATION(tst_duplicate_operation) +}; + +/* + * Validation + */ + +static bool ext_duplicate_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); + +const struct sieve_validator_extension +duplicate_validator_extension = { + .ext = &vnd_duplicate_extension, + .check_conflict = ext_duplicate_validator_check_conflict +}; + +static bool ext_duplicate_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict between + vnd.dovecot.duplicate and duplicate extensions */ + if ( sieve_extension_is(ext, vnd_duplicate_extension) ) { + sieve_validator_extension_register + (valdtr, ext, &duplicate_validator_extension, NULL); + } + + /* Register duplicate test */ + sieve_validator_register_command(valdtr, ext, &tst_duplicate); + + return TRUE; +} + +static bool ext_duplicate_validator_check_conflict +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + /* Check for conflict with duplicate extension */ + if ( sieve_extension_name_is(ext_other, "duplicate") ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) vnd.dovecot.duplicate extension " + "cannot be used together with the duplicate extension"); + return FALSE; + } + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/duplicate/tst-duplicate.c b/pigeonhole/src/lib-sieve/plugins/duplicate/tst-duplicate.c new file mode 100644 index 0000000..d211e04 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/duplicate/tst-duplicate.c @@ -0,0 +1,449 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-duplicate-common.h" + +/* Duplicate test + * + * Syntax: + * Usage: "duplicate" [":handle" <handle: string>] + * [":header" <header-name: string> / + * ":uniqueid" <value: string>] + * [":seconds" <timeout: number>] [":last"] + */ + +static bool +tst_duplicate_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +tst_duplicate_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def tst_duplicate = { + .identifier = "duplicate", + .type = SCT_TEST, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_duplicate_registered, + .generate = tst_duplicate_generate +}; + +/* + * Duplicate test tags + */ + +static bool +tst_duplicate_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +tst_duplicate_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def duplicate_seconds_tag = { + .identifier = "seconds", + .validate = tst_duplicate_validate_number_tag +}; + +static const struct sieve_argument_def duplicate_header_tag = { + .identifier = "header", + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_uniqueid_tag = { + .identifier = "uniqueid", + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_value_tag = { + .identifier = "value", /* vnd.dovecot.duplicate (deprecated) */ + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_handle_tag = { + .identifier = "handle", + .validate = tst_duplicate_validate_string_tag +}; + +static const struct sieve_argument_def duplicate_last_tag = { + .identifier = "last" +}; + +/* Codes for optional arguments */ + +enum tst_duplicate_optional { + OPT_END, + OPT_SECONDS, + OPT_HEADER, + OPT_UNIQUEID, + OPT_LAST, + OPT_HANDLE +}; + +/* + * Duplicate operation + */ + +static bool +tst_duplicate_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_duplicate_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def tst_duplicate_operation = { + .mnemonic = "DUPLICATE", + .ext_def = &duplicate_extension, + .dump = tst_duplicate_operation_dump, + .execute = tst_duplicate_operation_execute +}; + +/* + * Tag validation + */ + +static bool +tst_duplicate_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *ext = sieve_argument_ext(*arg); + const struct ext_duplicate_config *config = + (const struct ext_duplicate_config *)ext->context; + struct sieve_ast_argument *tag = *arg; + sieve_number_t seconds; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :seconds number + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_NUMBER, FALSE)) + return FALSE; + + seconds = sieve_ast_argument_number(*arg); + /* Enforce :days <= max_period */ + if (config->max_period > 0 && seconds > config->max_period) { + seconds = config->max_period; + + sieve_argument_validate_warning( + valdtr, *arg, + "specified :seconds value '%llu' is over the maximum", + (unsigned long long)seconds); + } + + sieve_ast_argument_number_set(*arg, seconds); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +static bool +tst_duplicate_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *ext = cmd->ext; + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :header <header-name: string> + * :value <value: string> + * :handle <handle: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (!sieve_argument_is(tag, duplicate_handle_tag) && (bool)cmd->data) { + sieve_argument_validate_error( + valdtr, *arg, + "conflicting :header and %s arguments specified " + "for the duplicate test", + (sieve_extension_is(ext, duplicate_extension) ? + ":uniqueid" : ":value")); + return FALSE; + } + + /* :header <header-name: string> */ + if (sieve_argument_is(tag, duplicate_header_tag)) { + if (!sieve_command_verify_headers_argument(valdtr, *arg)) + return FALSE; + cmd->data = (void *)TRUE; + /* :handle <handle: string> */ + } else if (sieve_argument_is(tag, duplicate_handle_tag)) { + /* nothing to be done */ + } else if (sieve_argument_is(tag, duplicate_uniqueid_tag)) { + i_assert(sieve_extension_is(ext, duplicate_extension)); + cmd->data = (void *)TRUE; + /* :value <value: string> (vnd.dovecot.duplicate) */ + } else if (sieve_argument_is(tag, duplicate_value_tag)) { + i_assert(sieve_extension_is(ext, vnd_duplicate_extension)); + cmd->data = (void *)TRUE; + } else { + i_unreached(); + } + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +/* + * Command registration + */ + +static bool +tst_duplicate_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_seconds_tag, OPT_SECONDS); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_last_tag, OPT_LAST); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_header_tag, OPT_HEADER); + if (sieve_extension_is(ext, duplicate_extension)) { + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_uniqueid_tag, + OPT_UNIQUEID); + } else { + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_value_tag, + OPT_UNIQUEID); + } + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &duplicate_handle_tag, OPT_HANDLE); + return TRUE; +} + +/* + * Code generation + */ + +static bool +tst_duplicate_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_duplicate_operation); + + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +tst_duplicate_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + const struct sieve_extension *ext = denv->oprtn->ext; + int opt_code = 0; + + sieve_code_dumpf(denv, "DUPLICATE"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + opok = sieve_opr_number_dump(denv, address, "seconds"); + break; + case OPT_LAST: + sieve_code_dumpf(denv, "last"); + break; + case OPT_HEADER: + opok = sieve_opr_string_dump(denv, address, "header"); + break; + case OPT_UNIQUEID: + if (sieve_extension_is(ext, duplicate_extension)) { + opok = sieve_opr_string_dump(denv, address, + "uniqueid"); + } else { + opok = sieve_opr_string_dump(denv, address, + "value"); + } + break; + case OPT_HANDLE: + opok = sieve_opr_string_dump(denv, address, "handle"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + return TRUE; +} + +/* + * Code execution + */ + +static int +tst_duplicate_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *ext = renv->oprtn->ext; + const struct ext_duplicate_config *config = + (const struct ext_duplicate_config *)ext->context; + struct mail *mail = eenv->msgdata->mail; + int opt_code = 0; + string_t *handle = NULL, *header = NULL, *uniqueid = NULL; + const char *val = NULL; + size_t val_len = 0; + sieve_number_t seconds = config->default_period; + bool last = FALSE, duplicate = FALSE; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + ret = sieve_opr_number_read(renv, address, "seconds", + &seconds); + break; + case OPT_LAST: + last = TRUE; + ret = SIEVE_EXEC_OK; + break; + case OPT_HEADER: + ret = sieve_opr_string_read(renv, address, "header", + &header); + break; + case OPT_UNIQUEID: + if (sieve_extension_is(ext, duplicate_extension)) { + ret = sieve_opr_string_read(renv, address, + "uniqueid", + &uniqueid); + } else { + ret = sieve_opr_string_read(renv, address, + "value", &uniqueid); + } + break; + case OPT_HANDLE: + ret = sieve_opr_string_read(renv, address, + "handle", &handle); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* + * Perform operation + */ + + /* Trace */ + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "duplicate test"); + sieve_runtime_trace_descend(renv); + + /* Get value */ + if (uniqueid != NULL) { + val = str_c(uniqueid); + val_len = str_len(uniqueid); + } else { + if (header == NULL) { + ret = mail_get_message_id(mail, &val); + if (ret < 0) { + return sieve_runtime_mail_error( + renv, mail, "duplicate test: " + "failed to read header field `message-id'"); + } + } else { + ret = mail_get_first_header_utf8(mail, str_c(header), + &val); + if (ret < 0) { + return sieve_runtime_mail_error( + renv, mail, "duplicate test: " + "failed to read header field `%s'", + str_c(header)); + } + } + + if (ret > 0) + val_len = strlen(val); + } + + /* Check duplicate */ + if (val == NULL) { + duplicate = FALSE; + } else { + ret = ext_duplicate_check(renv, handle, val, val_len, + seconds, last, &duplicate); + if (ret < SIEVE_EXEC_OK) + return ret; + } + + /* Trace */ + if (duplicate) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "message is a duplicate"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "message is not a duplicate"); + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, duplicate); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.am b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.am new file mode 100644 index 0000000..6824ec0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libsieve_ext_editheader.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-addheader.c \ + cmd-deleteheader.c + +libsieve_ext_editheader_la_SOURCES = \ + $(commands) \ + ext-editheader.c \ + ext-editheader-common.c + +noinst_HEADERS = \ + ext-editheader-limits.h \ + ext-editheader-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.in b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.in new file mode 100644 index 0000000..75d9571 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/Makefile.in @@ -0,0 +1,701 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/editheader +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_editheader_la_LIBADD = +am__objects_1 = cmd-addheader.lo cmd-deleteheader.lo +am_libsieve_ext_editheader_la_OBJECTS = $(am__objects_1) \ + ext-editheader.lo ext-editheader-common.lo +libsieve_ext_editheader_la_OBJECTS = \ + $(am_libsieve_ext_editheader_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 = +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)/cmd-addheader.Plo \ + ./$(DEPDIR)/cmd-deleteheader.Plo \ + ./$(DEPDIR)/ext-editheader-common.Plo \ + ./$(DEPDIR)/ext-editheader.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 = $(libsieve_ext_editheader_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_editheader_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@ +noinst_LTLIBRARIES = libsieve_ext_editheader.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-addheader.c \ + cmd-deleteheader.c + +libsieve_ext_editheader_la_SOURCES = \ + $(commands) \ + ext-editheader.c \ + ext-editheader-common.c + +noinst_HEADERS = \ + ext-editheader-limits.h \ + ext-editheader-common.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/lib-sieve/plugins/editheader/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/editheader/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_editheader.la: $(libsieve_ext_editheader_la_OBJECTS) $(libsieve_ext_editheader_la_DEPENDENCIES) $(EXTRA_libsieve_ext_editheader_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_editheader_la_OBJECTS) $(libsieve_ext_editheader_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-addheader.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-deleteheader.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-editheader-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-editheader.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-addheader.Plo + -rm -f ./$(DEPDIR)/cmd-deleteheader.Plo + -rm -f ./$(DEPDIR)/ext-editheader-common.Plo + -rm -f ./$(DEPDIR)/ext-editheader.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-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)/cmd-addheader.Plo + -rm -f ./$(DEPDIR)/cmd-deleteheader.Plo + -rm -f ./$(DEPDIR)/ext-editheader-common.Plo + -rm -f ./$(DEPDIR)/ext-editheader.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/editheader/cmd-addheader.c b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-addheader.c new file mode 100644 index 0000000..f39cbb7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-addheader.c @@ -0,0 +1,337 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" + +#include "rfc2822.h" +#include "edit-mail.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-editheader-common.h" + +/* + * Addheader command + * + * Syntax + * "addheader" [":last"] <field-name: string> <value: string> + */ + +static bool cmd_addheader_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_addheader_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool cmd_addheader_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def addheader_command = { + .identifier = "addheader", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_addheader_registered, + .validate = cmd_addheader_validate, + .generate = cmd_addheader_generate +}; + +/* + * Addheader command tags + */ + +/* Argument objects */ + +static const struct sieve_argument_def addheader_last_tag = { + .identifier = "last" +}; + +/* Codes for optional arguments */ + +enum cmd_addheader_optional { + OPT_END, + OPT_LAST +}; + +/* + * Addheader operation + */ + +static bool cmd_addheader_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_addheader_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def addheader_operation = { + .mnemonic = "ADDHEADER", + .ext_def = &editheader_extension, + .code = EXT_EDITHEADER_OPERATION_ADDHEADER, + .dump = cmd_addheader_operation_dump, + .execute = cmd_addheader_operation_execute +}; + +/* + * Utility + */ + +static bool _str_contains_nul(const string_t *str) +{ + const unsigned char *p, *pend; + + p = str_data(str); + pend = p + str_len(str); + while (p < pend) { + if (*p == '\0') + return TRUE; + p++; + } + return FALSE; +} + +/* + * Validation + */ + +static bool cmd_addheader_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* Check field-name syntax */ + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "field-name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + string_t *fname = sieve_ast_argument_str(arg); + + if ( !rfc2822_header_field_name_verify(str_c(fname), str_len(fname)) ) { + sieve_argument_validate_error + (valdtr, arg, "addheader command: specified field name `%s' is invalid", + str_sanitize(str_c(fname), 80)); + return FALSE; + } + + if ( !ext_editheader_header_allow_add + (cmd->ext, str_c(fname)) ) { + sieve_argument_validate_warning + (valdtr, arg, "addheader command: " + "adding specified header field `%s' is forbidden; " + "modification will be denied", + str_sanitize(str_c(fname), 80)); + } + } + + /* Check value syntax */ + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + string_t *fvalue = sieve_ast_argument_str(arg); + + if ( _str_contains_nul(fvalue) ) { + sieve_argument_validate_error(valdtr, arg, + "addheader command: specified value `%s' is invalid " + "(contains NUL character)", str_sanitize(str_c(fvalue), 80)); + return FALSE; + } + + if ( !rfc2822_header_field_body_verify + (str_c(fvalue), str_len(fvalue), TRUE, TRUE) ) { + sieve_argument_validate_warning(valdtr, arg, + "addheader command: specified value `%s' is invalid", + str_sanitize(str_c(fvalue), 80)); + } + + if ( ext_editheader_header_too_large(cmd->ext, str_len(fvalue)) ) { + sieve_argument_validate_error(valdtr, arg, "addheader command: " + "specified header value `%s' is too large (%zu bytes)", + str_sanitize(str_c(fvalue), 80), str_len(fvalue)); + return SIEVE_EXEC_FAILURE; + } + } + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_addheader_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &addheader_last_tag, OPT_LAST); + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_addheader_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &addheader_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_addheader_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "addheader"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + if ( opt_code == OPT_LAST ) { + sieve_code_dumpf(denv, "last"); + } else { + return FALSE; + } + } + + return + sieve_opr_string_dump(denv, address, "field-name") && + sieve_opr_string_dump(denv, address, "value"); +} + +/* + * Interpretation + */ + +static int cmd_addheader_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + string_t *field_name; + string_t *value; + struct edit_mail *edmail; + bool last = FALSE; + int opt_code = 0; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_LAST: + last = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read message */ + + if ( (ret=sieve_opr_string_read + (renv, address, "field-name", &field_name)) <= 0 ) + return ret; + + if ( (ret=sieve_opr_string_read + (renv, address, "value", &value)) <= 0 ) + return ret; + + /* + * Verify arguments + */ + + if ( !rfc2822_header_field_name_verify + (str_c(field_name), str_len(field_name)) ) { + sieve_runtime_error(renv, NULL, "addheader action: " + "specified field name `%s' is invalid", + str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_FAILURE; + } + + if ( !ext_editheader_header_allow_add + (this_ext, str_c(field_name)) ) { + sieve_runtime_warning(renv, NULL, "addheader action: " + "adding specified header field `%s' is forbidden; " + "modification denied", str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_OK; + } + + if ( _str_contains_nul(value) ) { + sieve_runtime_error(renv, NULL, "addheader action: " + "specified value `%s' is invalid (contains NUL character)", + str_sanitize(str_c(value), 80)); + return SIEVE_EXEC_FAILURE; + } + + if ( ext_editheader_header_too_large(this_ext, str_len(value)) ) { + sieve_runtime_error(renv, NULL, "addheader action: " + "specified header value `%s' is too large (%zu bytes)", + str_sanitize(str_c(value), 80), str_len(value)); + return SIEVE_EXEC_FAILURE; + } + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "addheader \"%s: %s\"", + str_sanitize(str_c(field_name), 80), str_sanitize(str_c(value), 80)); + + edmail = sieve_message_edit(renv->msgctx); + edit_mail_header_add(edmail, + rfc2822_header_field_name_sanitize(str_c(field_name)), + str_c(value), last); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/cmd-deleteheader.c b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-deleteheader.c new file mode 100644 index 0000000..a6964b7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/cmd-deleteheader.c @@ -0,0 +1,551 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" + +#include "rfc2822.h" +#include "edit-mail.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-editheader-common.h" + +/* + * Deleteheader command + * + * Syntax: + * deleteheader [":index" <fieldno: number> [":last"]] + * [COMPARATOR] [MATCH-TYPE] + * <field-name: string> [<value-patterns: string-list>] + */ + +static bool cmd_deleteheader_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_deleteheader_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_deleteheader_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def deleteheader_command = { + .identifier = "deleteheader", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_deleteheader_registered, + .validate = cmd_deleteheader_validate, + .generate = cmd_deleteheader_generate +}; + +/* + * Deleteheader command tags + */ + +/* Forward declarations */ + +static bool cmd_deleteheader_validate_index_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool cmd_deleteheader_validate_last_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def deleteheader_index_tag = { + .identifier = "index", + .validate = cmd_deleteheader_validate_index_tag +}; + +static const struct sieve_argument_def deleteheader_last_tag = { + .identifier = "last", + .validate = cmd_deleteheader_validate_last_tag +}; + +/* Codes for optional arguments */ + +enum cmd_deleteheader_optional { + OPT_INDEX = SIEVE_MATCH_OPT_LAST, + OPT_LAST +}; + +/* + * Deleteheader operation + */ + +static bool cmd_deleteheader_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_deleteheader_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def deleteheader_operation = { + .mnemonic = "DELETEHEADER", + .ext_def = &editheader_extension, + .code = EXT_EDITHEADER_OPERATION_DELETEHEADER, + .dump = cmd_deleteheader_operation_dump, + .execute = cmd_deleteheader_operation_execute +}; + +/* + * Command registration + */ + +static bool cmd_deleteheader_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &deleteheader_index_tag, OPT_INDEX); + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &deleteheader_last_tag, OPT_LAST); + + return TRUE; +} + +/* + * Command validation context + */ + +struct cmd_deleteheader_context_data { + struct sieve_ast_argument *arg_index; + struct sieve_ast_argument *arg_last; +}; + +/* + * Tag validation + */ + +static struct cmd_deleteheader_context_data * +cmd_deleteheader_get_context +(struct sieve_command *cmd) +{ + struct cmd_deleteheader_context_data *ctx_data = + (struct cmd_deleteheader_context_data *)cmd->data; + + if ( ctx_data != NULL ) return ctx_data; + + ctx_data = p_new + (sieve_command_pool(cmd), struct cmd_deleteheader_context_data, 1); + cmd->data = (void *)ctx_data; + + return ctx_data; +} + +static bool cmd_deleteheader_validate_index_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_deleteheader_context_data *ctx_data; + sieve_number_t index; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :index number + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) { + return FALSE; + } + + index = sieve_ast_argument_number(*arg); + if ( index > INT_MAX ) { + sieve_argument_validate_warning(valdtr, *arg, + "the :%s tag for the %s %s has a parameter value '%llu' " + "exceeding the maximum (%d)", + sieve_argument_identifier(tag), sieve_command_identifier(cmd), + sieve_command_type_name(cmd), (unsigned long long) index, + INT_MAX); + return FALSE; + } + + ctx_data = cmd_deleteheader_get_context(cmd); + ctx_data->arg_index = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool cmd_deleteheader_validate_last_tag +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_deleteheader_context_data *ctx_data; + + ctx_data = cmd_deleteheader_get_context(cmd); + ctx_data->arg_last = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Validation + */ + +static bool cmd_deleteheader_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_deleteheader_context_data *ctx_data = + (struct cmd_deleteheader_context_data *)cmd->data; + struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + + if ( ctx_data != NULL ) { + if ( ctx_data->arg_last != NULL && ctx_data->arg_index == NULL ) { + sieve_argument_validate_error(valdtr, ctx_data->arg_last, + "the :last tag for the %s %s cannot be specified " + "without the :index tag", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + } + } + + /* Field name argument */ + + if ( arg == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the %s %s expects at least one positional argument, but none was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "field name", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + if ( sieve_argument_is_string_literal(arg) ) { + string_t *fname = sieve_ast_argument_str(arg); + + if ( !rfc2822_header_field_name_verify(str_c(fname), str_len(fname)) ) { + sieve_argument_validate_error(valdtr, arg, "deleteheader command:" + "specified field name `%s' is invalid", + str_sanitize(str_c(fname), 80)); + return FALSE; + } + + if ( !ext_editheader_header_allow_delete + (cmd->ext, str_c(fname)) ) { + sieve_argument_validate_warning + (valdtr, arg, "deleteheader command: " + "deleting specified header field `%s' is forbidden; " + "modification will be denied", + str_sanitize(str_c(fname), 80)); + } + } + + /* Value patterns argument */ + + arg = sieve_ast_argument_next(arg); + if ( arg == NULL ) { + /* There is none; let's not generate code for useless match arguments */ + sieve_match_type_arguments_remove(valdtr, cmd); + + return TRUE; + } + + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value patterns", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* Validate the value patterns to a specified match type */ + return sieve_match_type_validate + (valdtr, cmd, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool cmd_deleteheader_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &deleteheader_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + /* Emit a placeholder when the value-patterns argument is missing */ + if ( sieve_ast_argument_next(cmd->first_positional) == NULL ) + sieve_opr_omitted_emit(cgenv->sblock); + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_deleteheader_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "DELETEHEADER"); + sieve_code_descend(denv); + + /* Optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_INDEX: + if ( !sieve_opr_number_dump(denv, address, "index") ) + return FALSE; + break; + case OPT_LAST: + sieve_code_dumpf(denv, "last"); + break; + default: + return FALSE; + } + }; + + if ( !sieve_opr_string_dump(denv, address, "field name") ) + return FALSE; + + return sieve_opr_stringlist_dump_ex(denv, address, "value patterns", ""); +} + +/* + * Code execution + */ + +static int cmd_deleteheader_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + int opt_code = 0; + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + string_t *field_name; + struct sieve_stringlist *vpattern_list = NULL; + struct edit_mail *edmail; + sieve_number_t index_offset = 0; + bool index_last = FALSE; + bool trace = FALSE; + int ret; + + /* + * Read operands + */ + + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_INDEX: + if ( (ret=sieve_opr_number_read(renv, address, "index", &index_offset)) + <= 0 ) + return ret; + + if ( index_offset > INT_MAX ) { + sieve_runtime_trace_error(renv, "index is > %d", INT_MAX); + return SIEVE_EXEC_BIN_CORRUPT; + } + + break; + case OPT_LAST: + index_last = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read field-name */ + if ( (ret=sieve_opr_string_read(renv, address, "field-name", &field_name)) + <= 0 ) + return ret; + + /* Read value-patterns */ + if ( (ret=sieve_opr_stringlist_read_ex + (renv, address, "value-patterns", TRUE, &vpattern_list)) <= 0 ) + return ret; + + /* + * Verify arguments + */ + + if ( !rfc2822_header_field_name_verify + (str_c(field_name), str_len(field_name)) ) { + sieve_runtime_error(renv, NULL, "deleteheader action: " + "specified field name `%s' is invalid", + str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_FAILURE; + } + + if ( !ext_editheader_header_allow_delete + (this_ext, str_c(field_name)) ) { + sieve_runtime_warning(renv, NULL, "deleteheader action: " + "deleting specified header field `%s' is forbidden; " + "modification denied", + str_sanitize(str_c(field_name), 80)); + return SIEVE_EXEC_OK; + } + + /* + * Execute command + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "deleteheader command"); + + /* Start editing the mail */ + edmail = sieve_message_edit(renv->msgctx); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS); + + /* Either do string matching or just kill all/indexed notify action(s) */ + if ( vpattern_list != NULL ) { + struct edit_mail_header_iter *edhiter; + struct sieve_match_context *mctx; + + if ( trace ) { + sieve_runtime_trace_descend(renv); + if ( index_offset != 0 ) { + sieve_runtime_trace(renv, 0, + "deleting matching occurrences of header `%s' at index %llu%s", + str_c(field_name), (unsigned long long)index_offset, + ( index_last ? " from last": "")); + } else { + sieve_runtime_trace(renv, 0, + "deleting matching occurrences of header `%s'", str_c(field_name)); + } + } + + /* Iterate through all headers and delete those that match */ + if ( (ret=edit_mail_headers_iterate_init + (edmail, str_c(field_name), index_last, &edhiter)) > 0 ) + { + int mret = 0; + sieve_number_t pos = 0; + + /* Initialize match */ + mctx = sieve_match_begin(renv, &mcht, &cmp); + + /* Match */ + for (;;) { + pos++; + + /* Check index if any */ + if ( index_offset == 0 || pos == index_offset ) { + const char *value; + int match; + + /* Match value against all value patterns */ + edit_mail_headers_iterate_get(edhiter, &value); + if ( (match=sieve_match_value + (mctx, value, strlen(value), vpattern_list)) < 0 ) + break; + + if ( match > 0 ) { + /* Remove it and iterate to next */ + sieve_runtime_trace(renv, 0, "deleting header with value `%s'", + value); + + if ( !edit_mail_headers_iterate_remove(edhiter) ) break; + continue; + } + } + + if ( !edit_mail_headers_iterate_next(edhiter) ) + break; + } + + /* Finish match */ + mret = sieve_match_end(&mctx, &ret); + + edit_mail_headers_iterate_deinit(&edhiter); + + if ( mret < 0 ) + return ret; + } + + if ( ret == 0 ) { + sieve_runtime_trace(renv, 0, "header `%s' not found", str_c(field_name)); + } else if ( ret < 0 ) { + sieve_runtime_warning(renv, NULL, "deleteheader action: " + "failed to delete occurrences of header `%s' (this should not happen!)", + str_c(field_name)); + } + + } else { + int index = ( index_last ? -((int)index_offset) : ((int)index_offset) ); + + if ( trace ) { + sieve_runtime_trace_descend(renv); + if ( index_offset != 0 ) { + sieve_runtime_trace(renv, 0, "deleting header `%s' at index %llu%s", + str_c(field_name), (unsigned long long)index_offset, + ( index_last ? " from last": "")); + } else { + sieve_runtime_trace(renv, 0, "deleting header `%s'", str_c(field_name)); + } + } + + /* Delete all occurrences of header */ + ret = edit_mail_header_delete(edmail, str_c(field_name), index); + + if ( ret < 0 ) { + sieve_runtime_warning(renv, NULL, "deleteheader action: " + "failed to delete occurrences of header `%s' (this should not happen!)", + str_c(field_name)); + } else if ( trace ) { + sieve_runtime_trace(renv, 0, "deleted %d occurrences of header `%s'", + ret, str_c(field_name)); + } + + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.c b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.c new file mode 100644 index 0000000..89fb180 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mempool.h" +#include "array.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" + +#include "ext-editheader-limits.h" +#include "ext-editheader-common.h" + +/* + * Extension configuration + */ + +struct ext_editheader_header { + const char *name; + + bool forbid_add:1; + bool forbid_delete:1; +}; + +struct ext_editheader_config { + pool_t pool; + + ARRAY(struct ext_editheader_header) headers; + + size_t max_header_size; +}; + +static struct ext_editheader_header * +ext_editheader_config_header_find(struct ext_editheader_config *ext_config, + const char *hname) +{ + struct ext_editheader_header *headers; + unsigned int count, i; + + headers = array_get_modifiable(&ext_config->headers, &count); + for (i = 0; i < count; i++) { + if (strcasecmp(hname, headers[i].name) == 0) + return &headers[i]; + } + return NULL; +} + +static void +ext_editheader_config_headers(struct sieve_instance *svinst, + struct ext_editheader_config *ext_config, + const char *setting, bool forbid_add, + bool forbid_delete) +{ + const char *setval; + + setval = sieve_setting_get(svinst, setting); + if (setval != NULL) { + const char **headers = t_strsplit_spaces(setval, " \t"); + + while (*headers != NULL) { + struct ext_editheader_header *header; + + if (!rfc2822_header_field_name_verify( + *headers, strlen(*headers))) { + e_warning(svinst->event, "editheader: " + "setting %s contains invalid header field name " + "`%s' (ignored)", + setting, *headers); + headers++; + continue; + } + + header = ext_editheader_config_header_find( + ext_config, *headers); + if (header == NULL) { + header = array_append_space( + &ext_config->headers); + header->name = p_strdup(ext_config->pool, + *headers); + } + + if (forbid_add) + header->forbid_add = TRUE; + if (forbid_delete) + header->forbid_delete = TRUE; + + headers++; + } + } +} + +bool ext_editheader_load(const struct sieve_extension *ext, void **context) +{ + struct ext_editheader_config *ext_config; + struct sieve_instance *svinst = ext->svinst; + size_t max_header_size; + pool_t pool; + + if (*context != NULL) { + ext_editheader_unload(ext); + *context = NULL; + } + + T_BEGIN { + pool = pool_alloconly_create("editheader_config", 1024); + ext_config = p_new(pool, struct ext_editheader_config, 1); + ext_config->pool = pool; + ext_config->max_header_size = + EXT_EDITHEADER_DEFAULT_MAX_HEADER_SIZE; + + p_array_init(&ext_config->headers, pool, 16); + + ext_editheader_config_headers( + svinst, ext_config, + "sieve_editheader_protected", TRUE, TRUE); + ext_editheader_config_headers( + svinst, ext_config, + "sieve_editheader_forbid_add", TRUE, FALSE); + ext_editheader_config_headers( + svinst, ext_config, + "sieve_editheader_forbid_delete", FALSE, TRUE); + + if (sieve_setting_get_size_value( + svinst, "sieve_editheader_max_header_size", + &max_header_size)) { + if (max_header_size < EXT_EDITHEADER_MINIMUM_MAX_HEADER_SIZE) { + e_warning(svinst->event, "editheader: " + "value of sieve_editheader_max_header_size setting " + "(=%zu) is less than the minimum (=%zu) " + "(ignored)", max_header_size, + (size_t)EXT_EDITHEADER_MINIMUM_MAX_HEADER_SIZE); + } else { + ext_config->max_header_size = max_header_size; + } + } + } T_END; + + *context = (void *)ext_config; + return TRUE; +} + +void ext_editheader_unload(const struct sieve_extension *ext) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + + if (ext_config != NULL) + pool_unref(&ext_config->pool); +} + +/* + * Protected headers + */ + +bool ext_editheader_header_allow_add(const struct sieve_extension *ext, + const char *hname) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + const struct ext_editheader_header *header; + + if (strcasecmp(hname, "subject") == 0) + return TRUE; + if (strcasecmp(hname, "x-sieve-redirected-from") == 0) + return FALSE; + + header = ext_editheader_config_header_find(ext_config, hname); + if (header == NULL) + return TRUE; + + return !header->forbid_add; +} + +bool ext_editheader_header_allow_delete(const struct sieve_extension *ext, + const char *hname) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + const struct ext_editheader_header *header; + + if (strcasecmp(hname, "received") == 0 || + strcasecmp(hname, "auto-submitted") == 0) + return FALSE; + if (strcasecmp(hname, "x-sieve-redirected-from") == 0) + return FALSE; + if (strcasecmp(hname, "subject") == 0) + return TRUE; + + header = ext_editheader_config_header_find(ext_config, hname); + if (header == NULL) + return TRUE; + + return !header->forbid_delete; +} + +/* + * Limits + */ + +bool ext_editheader_header_too_large(const struct sieve_extension *ext, + size_t size) +{ + struct ext_editheader_config *ext_config = + (struct ext_editheader_config *)ext->context; + + return size > ext_config->max_header_size; +} diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.h b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.h new file mode 100644 index 0000000..8a6cc36 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-common.h @@ -0,0 +1,48 @@ +#ifndef EXT_EDITHEADER_COMMON_H +#define EXT_EDITHEADER_COMMON_H + +/* + * Commands + */ + +extern const struct sieve_command_def addheader_command; +extern const struct sieve_command_def deleteheader_command; + +/* + * Operations + */ + +enum ext_imap4flags_opcode { + EXT_EDITHEADER_OPERATION_ADDHEADER, + EXT_EDITHEADER_OPERATION_DELETEHEADER, +}; + +extern const struct sieve_operation_def addheader_operation; +extern const struct sieve_operation_def deleteheader_operation; + +/* + * Extension + */ + +extern const struct sieve_extension_def editheader_extension; + +bool ext_editheader_load(const struct sieve_extension *ext, void **context); +void ext_editheader_unload(const struct sieve_extension *ext); + +/* + * Protected headers + */ + +bool ext_editheader_header_allow_add(const struct sieve_extension *ext, + const char *hname); +bool ext_editheader_header_allow_delete(const struct sieve_extension *ext, + const char *hname); + +/* + * Limits + */ + +bool ext_editheader_header_too_large(const struct sieve_extension *ext, + size_t size); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-limits.h b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-limits.h new file mode 100644 index 0000000..a8e834b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader-limits.h @@ -0,0 +1,7 @@ +#ifndef EXT_EDITHEADER_LIMITS_H +#define EXT_EDITHEADER_LIMITS_H + +#define EXT_EDITHEADER_MINIMUM_MAX_HEADER_SIZE 1024 +#define EXT_EDITHEADER_DEFAULT_MAX_HEADER_SIZE 2048 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader.c b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader.c new file mode 100644 index 0000000..dc8eb12 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/editheader/ext-editheader.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension debug + * --------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5293 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-editheader-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *editheader_operations[] = { + &addheader_operation, + &deleteheader_operation +}; + +/* + * Extension + */ + +static bool ext_editheader_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def editheader_extension = { + .name = "editheader", + .load = ext_editheader_load, + .unload = ext_editheader_unload, + .validator_load = ext_editheader_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(editheader_operations) +}; + +static bool ext_editheader_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + /* Register new commands */ + sieve_validator_register_command(validator, ext, &addheader_command); + sieve_validator_register_command(validator, ext, &deleteheader_command); + + return TRUE; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.am b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.am new file mode 100644 index 0000000..4b65630 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.am @@ -0,0 +1,44 @@ +SUBDIRS = mailto + +noinst_LTLIBRARIES = libsieve_ext_enotify.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c + +tests = \ + tst-valid-notify-method.c \ + tst-notify-method-capability.c + +var_modifiers = \ + vmodf-encodeurl.c + +notify_methods = \ + ./mailto/libsieve_ext_enotify_mailto.la + +libsieve_ext_enotify_la_DEPENDENCIES = \ + $(notify_methods) +libsieve_ext_enotify_la_LIBADD = \ + $(notify_methods) + +libsieve_ext_enotify_la_SOURCES = \ + ext-enotify.c \ + ext-enotify-common.c \ + $(commands) \ + $(tests) \ + $(var_modifiers) + +public_headers = \ + sieve-ext-enotify.h + +headers = \ + ext-enotify-limits.h \ + ext-enotify-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.in b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.in new file mode 100644 index 0000000..fea2423 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/Makefile.in @@ -0,0 +1,904 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/enotify +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) \ + $(pkginc_lib_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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__objects_1 = cmd-notify.lo +am__objects_2 = tst-valid-notify-method.lo \ + tst-notify-method-capability.lo +am__objects_3 = vmodf-encodeurl.lo +am_libsieve_ext_enotify_la_OBJECTS = ext-enotify.lo \ + ext-enotify-common.lo $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) +libsieve_ext_enotify_la_OBJECTS = \ + $(am_libsieve_ext_enotify_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 = +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)/cmd-notify.Plo \ + ./$(DEPDIR)/ext-enotify-common.Plo ./$(DEPDIR)/ext-enotify.Plo \ + ./$(DEPDIR)/tst-notify-method-capability.Plo \ + ./$(DEPDIR)/tst-valid-notify-method.Plo \ + ./$(DEPDIR)/vmodf-encodeurl.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 = $(libsieve_ext_enotify_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_enotify_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +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 +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +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@ +SUBDIRS = mailto +noinst_LTLIBRARIES = libsieve_ext_enotify.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c + +tests = \ + tst-valid-notify-method.c \ + tst-notify-method-capability.c + +var_modifiers = \ + vmodf-encodeurl.c + +notify_methods = \ + ./mailto/libsieve_ext_enotify_mailto.la + +libsieve_ext_enotify_la_DEPENDENCIES = \ + $(notify_methods) + +libsieve_ext_enotify_la_LIBADD = \ + $(notify_methods) + +libsieve_ext_enotify_la_SOURCES = \ + ext-enotify.c \ + ext-enotify-common.c \ + $(commands) \ + $(tests) \ + $(var_modifiers) + +public_headers = \ + sieve-ext-enotify.h + +headers = \ + ext-enotify-limits.h \ + ext-enotify-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +all: all-recursive + +.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/lib-sieve/plugins/enotify/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/enotify/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_enotify.la: $(libsieve_ext_enotify_la_OBJECTS) $(libsieve_ext_enotify_la_DEPENDENCIES) $(EXTRA_libsieve_ext_enotify_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_enotify_la_OBJECTS) $(libsieve_ext_enotify_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-notify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-enotify-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-enotify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-notify-method-capability.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-valid-notify-method.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmodf-encodeurl.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 +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(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-recursive + +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-recursive + +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 + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-enotify-common.Plo + -rm -f ./$(DEPDIR)/ext-enotify.Plo + -rm -f ./$(DEPDIR)/tst-notify-method-capability.Plo + -rm -f ./$(DEPDIR)/tst-valid-notify-method.Plo + -rm -f ./$(DEPDIR)/vmodf-encodeurl.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-enotify-common.Plo + -rm -f ./$(DEPDIR)/ext-enotify.Plo + -rm -f ./$(DEPDIR)/tst-notify-method-capability.Plo + -rm -f ./$(DEPDIR)/tst-valid-notify-method.Plo + -rm -f ./$(DEPDIR)/vmodf-encodeurl.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES 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-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-pkginc_libHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am 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-pkginc_libHEADERS + +.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/lib-sieve/plugins/enotify/cmd-notify.c b/pigeonhole/src/lib-sieve/plugins/enotify/cmd-notify.c new file mode 100644 index 0000000..4fe121a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/cmd-notify.c @@ -0,0 +1,621 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "ext-enotify-common.h" + +/* + * Forward declarations + */ + +static const struct sieve_argument_def notify_importance_tag; +static const struct sieve_argument_def notify_from_tag; +static const struct sieve_argument_def notify_options_tag; +static const struct sieve_argument_def notify_message_tag; + +/* + * Notify command + * + * Syntax: + * notify [":from" string] + * [":importance" <"1" / "2" / "3">] + * [":options" string-list] + * [":message" string] + * <method: string> + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_notify_pre_validate(struct sieve_validator *validator, + struct sieve_command *cmd); +static bool +cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def notify_command = { + .identifier = "notify", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_notify_registered, + .pre_validate = cmd_notify_pre_validate, + .validate = cmd_notify_validate, + .generate = cmd_notify_generate, +}; + +/* + * Notify command tags + */ + +/* Forward declarations */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_notify_validate_importance_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def notify_from_tag = { + .identifier = "from", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_options_tag = { + .identifier = "options", + .validate = cmd_notify_validate_stringlist_tag +}; + +static const struct sieve_argument_def notify_message_tag = { + .identifier = "message", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_importance_tag = { + .identifier = "importance", + .validate = cmd_notify_validate_importance_tag +}; + +/* + * Notify operation + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def notify_operation = { + .mnemonic = "NOTIFY", + .ext_def = &enotify_extension, + .code = EXT_ENOTIFY_OPERATION_NOTIFY, + .dump = cmd_notify_operation_dump, + .execute = cmd_notify_operation_execute +}; + +/* + * Notify action + */ + +/* Forward declarations */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_notify = { + .name = "notify", + .check_duplicate =act_notify_check_duplicate, + .print = act_notify_print, + .commit = act_notify_commit, +}; + +/* + * Command validation context + */ + +struct cmd_notify_context_data { + struct sieve_ast_argument *from; + struct sieve_ast_argument *message; + struct sieve_ast_argument *options; +}; + +/* + * Tag validation + */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :from <string> + * :message <string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (sieve_argument_is(tag, notify_from_tag)) { + ctx_data->from = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, notify_message_tag)) { + ctx_data->message = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } + return TRUE; +} + +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :options string-list + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + /* Assign context */ + ctx_data->options = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool +cmd_notify_validate_importance_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + const struct sieve_ast_argument *tag = *arg; + const char *impstr; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :importance <"1" / "2" / "3"> + */ + if (sieve_ast_argument_type(*arg) != SAAT_STRING) { + /* Not a string */ + sieve_argument_validate_error( + valdtr, *arg, + "the :importance tag for the notify command requires a string parameter, " + "but %s was found", sieve_ast_argument_name(*arg)); + return FALSE; + } + + impstr = sieve_ast_argument_strc(*arg); + if (impstr[0] < '1' || impstr[0] > '3' || impstr[1] != '\0') { + /* Invalid importance */ + sieve_argument_validate_error( + valdtr, *arg, + "invalid :importance value for notify command: %s", + impstr); + return FALSE; + } + + sieve_ast_argument_number_substitute(*arg, impstr[0] - '0'); + (*arg)->argument = sieve_argument_create((*arg)->ast, &number_argument, + tag->argument->ext, + tag->argument->id_code); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_importance_tag, + CMD_NOTIFY_OPT_IMPORTANCE); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_from_tag, CMD_NOTIFY_OPT_FROM); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_options_tag, + CMD_NOTIFY_OPT_OPTIONS); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_message_tag, + CMD_NOTIFY_OPT_MESSAGE); + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_notify_pre_validate(struct sieve_validator *validator ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_notify_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_notify_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static bool +cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "method", 1, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + return ext_enotify_compile_check_arguments( + valdtr, cmd, arg, ctx_data->message, ctx_data->from, + ctx_data->options); +} + +/* + * Code generation + */ + +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, ¬ify_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "NOTIFY"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case CMD_NOTIFY_OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, + "importance"); + break; + case CMD_NOTIFY_OPT_FROM: + opok = sieve_opr_string_dump(denv, address, "from"); + break; + case CMD_NOTIFY_OPT_OPTIONS: + opok = sieve_opr_stringlist_dump(denv, address, + "options"); + break; + case CMD_NOTIFY_OPT_MESSAGE: + opok = sieve_opr_string_dump(denv, address, "message"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + /* Dump method operand */ + return sieve_opr_string_dump(denv, address, "method"); +} + +/* + * Code execution + */ + +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_side_effects_list *slist = NULL; + struct sieve_enotify_action *act; + void *method_context; + pool_t pool; + int opt_code = 0; + sieve_number_t importance = 2; + struct sieve_stringlist *options = NULL; + const struct sieve_enotify_method *method; + string_t *method_uri, *message = NULL, *from = NULL; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) break; + + switch (opt_code) { + case CMD_NOTIFY_OPT_IMPORTANCE: + ret = sieve_opr_number_read(renv, address, "importance", + &importance); + break; + case CMD_NOTIFY_OPT_FROM: + ret = sieve_opr_string_read(renv, address, "from", + &from); + break; + case CMD_NOTIFY_OPT_MESSAGE: + ret = sieve_opr_string_read(renv, address, "message", + &message); + break; + case CMD_NOTIFY_OPT_OPTIONS: + ret = sieve_opr_stringlist_read(renv, address, + "options", &options); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* Method operand */ + + if ((ret = sieve_opr_string_read(renv, address, "method", + &method_uri)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Enforce 0 < importance < 4 (just to be sure) */ + + if (importance < 1) + importance = 1; + else if (importance > 3) + importance = 3; + + /* Trace */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "notify action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "notify with uri `%s'", + str_sanitize(str_c(method_uri), 80)); + } + + /* Check operands */ + + if ((ret = ext_enotify_runtime_check_operands(renv, method_uri, message, + from, options, &method, + &method_context)) > 0) + { + /* Add notify action to the result */ + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct sieve_enotify_action, 1); + act->method = method; + act->method_context = method_context; + act->importance = importance; + if (message != NULL) + act->message = p_strdup(pool, str_c(message)); + if (from != NULL) + act->from = p_strdup(pool, str_c(from)); + + if (sieve_result_add_action(renv, this_ext, "notify", + &act_notify, slist, + (void *)act, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; + } + return ret; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_enotify_action *nact, *nact_other; + const struct sieve_enotify_method_def *nmth_def; + struct sieve_enotify_env nenv; + int result; + + if (act->context == NULL || act_other->context == NULL) + return 0; + + nact = (const struct sieve_enotify_action *)act->context; + nact_other = (const struct sieve_enotify_action *)act_other->context; + + if (nact->method == NULL || nact->method->def == NULL) + return 0; + + nmth_def = nact->method->def; + if (nmth_def->action_check_duplicates == NULL) + return 0; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = nact->method; + nenv.ehandler = renv->ehandler; + nenv.location = act->location; + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify: "); + + result = nmth_def->action_check_duplicates(&nenv, nact, nact_other); + + event_unref(&nenv.event); + + return result; +} + +/* Result printing */ + +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct sieve_enotify_action *act = + (const struct sieve_enotify_action *)action->context; + const struct sieve_enotify_method *method; + + method = act->method; + + if (method->def != NULL) { + sieve_result_action_printf( + rpenv, "send notification with method '%s:':", + method->def->identifier); + + if (method->def->action_print != NULL) { + struct sieve_enotify_print_env penv; + + i_zero(&penv); + penv.result_penv = rpenv; + + method->def->action_print(&penv, act); + } + } +} + +/* Result execution */ + +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_enotify_action *act = + (const struct sieve_enotify_action *)aenv->action->context; + const struct sieve_enotify_method *method = act->method; + struct sieve_enotify_exec_env nenv; + int ret = 0; + + if (method->def != NULL && method->def->action_execute != NULL) { + /* Compose log structure */ + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.flags = eenv->flags; + nenv.method = method; + nenv.scriptenv = eenv->scriptenv; + nenv.msgdata = eenv->msgdata; + nenv.msgctx = aenv->msgctx; + + nenv.ehandler = aenv->ehandler; + nenv.event = aenv->event; + + ret = method->def->action_execute(&nenv, act); + if (ret >= 0) + eenv->exec_status->significant_action_executed = TRUE; + } + + return (ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_TEMP_FAILURE); +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.c b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.c new file mode 100644 index 0000000..e0539f0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.c @@ -0,0 +1,718 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-enotify-limits.h" +#include "ext-enotify-common.h" + +#include <ctype.h> + +/* FIXME: (from draft RFC) + + Header/envelope tests [Sieve] together with Sieve variables can be used to + extract the list of users to receive notifications from the incoming email + message or its envelope. This is potentially quite dangerous, as this can be + used for Deny Of Service attacks on recipients controlled by the message + sender. For this reason implementations SHOULD NOT allow use of variables + containing values extracted from the email message in the method parameter to + the notify action. Note that violation of this SHOULD NOT may result in* the + creation of an open relay, i.e. any sender would be able to create specially + crafted email messages that would result in notifications delivered to + recipients under the control of the sender. In worst case this might result + in financial loss by user controlling the Sieve script and/or by recipients + of notifications (e.g. if a notification is an SMS message). + + --> This is currently not possible to check. + */ + +/* + * Notify capability + */ + +static const char * +ext_notify_get_methods_string(const struct sieve_extension *ntfy_ext); + +const struct sieve_extension_capabilities notify_capabilities = { + "notify", + ext_notify_get_methods_string +}; + +/* + * Core notification methods + */ + +extern const struct sieve_enotify_method_def mailto_notify; + +/* + * Notify method registry + */ + +static const struct sieve_enotify_method * +ext_enotify_method_register(struct sieve_instance *svinst, + struct ext_enotify_context *ectx, + const struct sieve_enotify_method_def *nmth_def) +{ + struct sieve_enotify_method *nmth; + int nmth_id = (int)array_count(&ectx->notify_methods); + + nmth = array_append_space(&ectx->notify_methods); + nmth->def = nmth_def; + nmth->id = nmth_id; + nmth->svinst = svinst; + + if (nmth_def->load != NULL) + nmth_def->load(nmth, &nmth->context); + + return nmth; +} + +void ext_enotify_methods_init(struct sieve_instance *svinst, + struct ext_enotify_context *ectx) +{ + p_array_init(&ectx->notify_methods, default_pool, 4); + + ext_enotify_method_register(svinst, ectx, &mailto_notify); +} + +void ext_enotify_methods_deinit(struct ext_enotify_context *ectx) +{ + const struct sieve_enotify_method *methods; + unsigned int meth_count, i; + + methods = array_get(&ectx->notify_methods, &meth_count); + for (i = 0; i < meth_count; i++) { + if (methods[i].def != NULL && methods[i].def->unload != NULL) + methods[i].def->unload(&methods[i]); + } + + array_free(&ectx->notify_methods); +} + +const struct sieve_enotify_method * +sieve_enotify_method_register(struct sieve_instance *svinst, + const struct sieve_enotify_method_def *nmth_def) +{ + const struct sieve_extension *ntfy_ext = + sieve_extension_get_by_name(svinst, "enotify"); + + if (ntfy_ext != NULL) { + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + + return ext_enotify_method_register(svinst, ectx, nmth_def); + } + return NULL; +} + +void sieve_enotify_method_unregister(const struct sieve_enotify_method *nmth) +{ + struct sieve_instance *svinst = nmth->svinst; + const struct sieve_extension *ntfy_ext = + sieve_extension_get_by_name(svinst, "enotify"); + + if (ntfy_ext != NULL) { + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + int nmth_id = nmth->id; + + if (nmth_id >= 0 && + nmth_id < (int)array_count(&ectx->notify_methods)) { + struct sieve_enotify_method *nmth_mod = + array_idx_modifiable(&ectx->notify_methods, + nmth_id); + + nmth_mod->def = NULL; + } + } +} + +const struct sieve_enotify_method * +ext_enotify_method_find(const struct sieve_extension *ntfy_ext, + const char *identifier) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *)ntfy_ext->context; + unsigned int meth_count, i; + const struct sieve_enotify_method *methods; + + methods = array_get(&ectx->notify_methods, &meth_count); + for (i = 0; i < meth_count; i++) { + if (methods[i].def == NULL) + continue; + + if (strcasecmp(methods[i].def->identifier, identifier) == 0) + return &methods[i]; + } + return NULL; +} + +static const char * +ext_notify_get_methods_string(const struct sieve_extension *ntfy_ext) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + unsigned int meth_count, i; + const struct sieve_enotify_method *methods; + string_t *result = t_str_new(128); + + methods = array_get(&ectx->notify_methods, &meth_count); + if (meth_count > 0) { + for (i = 0; i < meth_count; i++) { + if (str_len(result) > 0) + str_append_c(result, ' '); + if (methods[i].def != NULL) + str_append(result, methods[i].def->identifier); + } + return str_c(result); + } + return NULL; +} + +/* + * Compile-time argument validation + */ + +static const char *ext_enotify_uri_scheme_parse(const char **uri_p) +{ + string_t *scheme = t_str_new(EXT_ENOTIFY_MAX_SCHEME_LEN); + const char *p = *uri_p; + unsigned int len = 0; + + /* RFC 3968: + + scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + + FIXME: we do not allow '%' in schemes. Is this correct? + */ + + if (!i_isalpha(*p)) + return NULL; + + str_append_c(scheme, *p); + p++; + + while (*p != '\0' && len < EXT_ENOTIFY_MAX_SCHEME_LEN) { + if (!i_isalnum(*p) && *p != '+' && *p != '-' && *p != '.') + break; + + str_append_c(scheme, *p); + p++; + len++; + } + + if (*p != ':') + return NULL; + p++; + + *uri_p = p; + return str_c(scheme); +} + +static bool +ext_enotify_option_parse(struct sieve_enotify_env *nenv, + const char *option, bool name_only, + const char **opt_name_r, const char **opt_value_r) +{ + const char *p = option; + + /* "<optionname>=<value>". + + l-d = ALPHA / DIGIT + l-d-p = l-d / "." / "-" / "_" + optionname = l-d *l-d-p + value = *(%x01-09 / %x0B-0C / %x0E-FF) + */ + + /* + * Parse option name + */ + + /* optionname = l-d *l-d-p + */ + + /* Explicitly report empty option as such */ + if (*p == '\0') { + sieve_enotify_error(nenv, "empty option specified"); + return FALSE; + } + + /* l-d = ALPHA / DIGIT */ + if (i_isalnum(*p)) { + p++; + + /* l-d-p = l-d / "." / "-" / "_" */ + while (i_isalnum(*p) || *p == '.' || *p == '-' || *p == '_') + p++; + } + + /* Parsing must end at '=' and we must parse at least one character */ + if (*p != '=' || p == option) { + sieve_enotify_error( + nenv, "invalid option name specified in option '%s'", + str_sanitize(option, 80)); + return FALSE; + } + + /* Assign option name */ + if (opt_name_r != NULL) + *opt_name_r = t_strdup_until(option, p); + + /* Skip '=' */ + p++; + + /* Exit now if only the option name is of interest */ + if (name_only) + return TRUE; + + /* + * Parse option value + */ + + /* value = *(%x01-09 / %x0B-0C / %x0E-FF) */ + while (*p != '\0' && *p != 0x0A && *p != 0x0D) + p++; + + /* Parse must end at end of string */ + if (*p != '\0') { + sieve_enotify_error( + nenv, "notify command: " + "invalid option value specified in option '%s'", + str_sanitize(option, 80)); + return FALSE; + } + + /* Assign option value */ + if (opt_value_r != NULL) + *opt_value_r = p; + + return TRUE; +} + +struct _ext_enotify_option_check_context { + struct sieve_instance *svinst; + struct sieve_validator *valdtr; + const struct sieve_enotify_method *method; +}; + +static int +_ext_enotify_option_check(void *context, struct sieve_ast_argument *arg) +{ + struct _ext_enotify_option_check_context *optn_context = + (struct _ext_enotify_option_check_context *) context; + struct sieve_validator *valdtr = optn_context->valdtr; + const struct sieve_enotify_method *method = optn_context->method; + struct sieve_enotify_env nenv; + const char *option = sieve_ast_argument_strc(arg); + const char *opt_name = NULL, *opt_value = NULL; + bool check = TRUE; + int result = 1; + + /* Compose log structure */ + i_zero(&nenv); + nenv.svinst = optn_context->svinst; + nenv.method = method; + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Parse option */ + if (!sieve_argument_is_string_literal(arg)) { + /* Variable string: partial option parse + + If the string item is not a string literal, it cannot be + validated fully at compile time. We can however check whether + the '=' is in the string specification and whether the part + before the '=' is a valid option name. In that case, the + method option check function is called with the value + parameter equal to NULL, meaning that it should only check + the validity of the option itself and not the assigned value. + */ + if (!ext_enotify_option_parse(NULL, option, TRUE, + &opt_name, &opt_value)) + check = FALSE; + } else { + /* Literal string: full option parse */ + if (!ext_enotify_option_parse(&nenv, option, FALSE, + &opt_name, &opt_value)) + result = -1; + } + + /* Call method's option check function */ + if (result > 0 && check && method->def != NULL && + method->def->compile_check_option != NULL) { + result = (method->def->compile_check_option(&nenv, opt_name, + opt_value) ? + 1 : -1 ); + } + + event_unref(&nenv.event); + return result; +} + +bool ext_enotify_compile_check_arguments(struct sieve_validator *valdtr, + struct sieve_command *cmd, + struct sieve_ast_argument *uri_arg, + struct sieve_ast_argument *msg_arg, + struct sieve_ast_argument *from_arg, + struct sieve_ast_argument *options_arg) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_instance *svinst = this_ext->svinst; + const char *uri = sieve_ast_argument_strc(uri_arg); + const char *scheme; + const struct sieve_enotify_method *method; + struct sieve_enotify_env nenv; + bool result = TRUE; + + /* If the uri string is not a constant literal, we cannot determine + which method is used, so we bail out successfully and defer checking + to runtime. + */ + if (!sieve_argument_is_string_literal(uri_arg)) + return TRUE; + + /* Parse scheme part of URI */ + if ((scheme = ext_enotify_uri_scheme_parse(&uri)) == NULL) { + sieve_argument_validate_error( + valdtr, uri_arg, "notify command: " + "invalid scheme part for method URI '%s'", + str_sanitize(sieve_ast_argument_strc(uri_arg), 80)); + return FALSE; + } + + /* Find used method with the parsed scheme identifier */ + if ((method = ext_enotify_method_find(this_ext, scheme)) == NULL) { + sieve_argument_validate_error( + valdtr, uri_arg, "notify command: " + "invalid method '%s'", scheme); + return FALSE; + } + + if (method->def == NULL) + return TRUE; + + /* Compose log structure */ + i_zero(&nenv); + nenv.svinst = svinst; + nenv.method = method; + + /* Check URI itself */ + if (result && method->def->compile_check_uri != NULL) { + /* Set log location to location of URI argument */ + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), uri_arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Execute method check function */ + result = method->def->compile_check_uri( + &nenv, sieve_ast_argument_strc(uri_arg), uri); + } + + /* Check :message argument */ + if (result && msg_arg != NULL && + sieve_argument_is_string_literal(msg_arg) && + method->def->compile_check_message != NULL ) { + /* Set log location to location of :message argument */ + event_unref(&nenv.event); + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), msg_arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Execute method check function */ + result = method->def->compile_check_message( + &nenv, sieve_ast_argument_str(msg_arg)); + } + + /* Check :from argument */ + if (result && from_arg != NULL && + sieve_argument_is_string_literal(from_arg) && + method->def->compile_check_from != NULL ) { + /* Set log location to location of :from argument */ + event_unref(&nenv.event); + nenv.ehandler = sieve_validator_error_handler(valdtr); + nenv.location = sieve_error_script_location( + sieve_validator_script(valdtr), from_arg->source_line); + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify command: "); + + /* Execute method check function */ + result = method->def->compile_check_from( + &nenv, sieve_ast_argument_str(from_arg)); + } + + event_unref(&nenv.event); + + /* Check :options argument */ + if (result && options_arg != NULL) { + struct sieve_ast_argument *option = options_arg; + struct _ext_enotify_option_check_context optn_context = { + svinst, valdtr, method }; + + /* Parse and check options */ + result = (sieve_ast_stringlist_map( + &option, (void *) &optn_context, + _ext_enotify_option_check) > 0); + + /* Discard argument if options are not accepted by method */ + if (result && method->def->compile_check_option == NULL) { + sieve_argument_validate_warning( + valdtr, options_arg, "notify command: " + "method '%s' accepts no options", scheme); + (void)sieve_ast_arguments_detach(options_arg, 1); + } + } + return result; +} + +/* + * Runtime operand checking + */ + +bool ext_enotify_runtime_method_validate(const struct sieve_runtime_env *renv, + string_t *method_uri) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + const struct sieve_enotify_method *method; + const char *uri = str_c(method_uri); + const char *scheme; + bool result = TRUE; + + /* Get the method */ + + if ((scheme = ext_enotify_uri_scheme_parse(&uri)) == NULL) + return FALSE; + if ((method = ext_enotify_method_find(this_ext, scheme)) == NULL) + return FALSE; + + /* Validate the provided URI */ + + if (method->def != NULL && method->def->runtime_check_uri != NULL) { + struct sieve_enotify_env nenv; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = method; + nenv.ehandler = renv->ehandler; + nenv.location = sieve_runtime_get_full_command_location(renv), + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, + "valid_notify_method test: "); + + /* Use the method check function to validate the URI */ + result = method->def->runtime_check_uri( + &nenv, str_c(method_uri), uri); + + event_unref(&nenv.event); + } + + return result; +} + +static const struct +sieve_enotify_method *ext_enotify_get_method( + const struct sieve_runtime_env *renv, string_t *method_uri, + const char **uri_body_r) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + const struct sieve_enotify_method *method; + const char *uri = str_c(method_uri); + const char *scheme; + + /* Parse part before ':' of the uri (the scheme) and use it to identify + notify method. + */ + if ((scheme = ext_enotify_uri_scheme_parse(&uri)) == NULL) { + sieve_runtime_error( + renv, NULL, "invalid scheme part for method URI '%s'", + str_sanitize(str_c(method_uri), 80)); + return NULL; + } + + /* Find the notify method */ + if ((method = ext_enotify_method_find(this_ext, scheme)) == NULL) { + sieve_runtime_error(renv, NULL, "invalid notify method '%s'", + scheme); + return NULL; + } + + /* Return the parse pointer and the found method */ + *uri_body_r = uri; + return method; +} + +const char * +ext_enotify_runtime_get_method_capability(const struct sieve_runtime_env *renv, + string_t *method_uri, + const char *capability) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_enotify_method *method; + const char *uri_body; + const char *result = NULL; + + /* Get method */ + method = ext_enotify_get_method(renv, method_uri, &uri_body); + if ( method == NULL ) return NULL; + + /* Get requested capability */ + if (method->def != NULL && + method->def->runtime_get_method_capability != NULL) { + struct sieve_enotify_env nenv; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = method; + nenv.ehandler = renv->ehandler; + nenv.location = sieve_runtime_get_full_command_location(renv), + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, + "notify_method_capability test: "); + + /* Execute method function to acquire capability value */ + result = method->def->runtime_get_method_capability( + &nenv, str_c(method_uri), uri_body, capability); + + event_unref(&nenv.event); + } + + return result; +} + +int ext_enotify_runtime_check_operands( + const struct sieve_runtime_env *renv, string_t *method_uri, + string_t *message, string_t *from, struct sieve_stringlist *options, + const struct sieve_enotify_method **method_r, void **method_context) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_enotify_method *method; + const char *uri_body; + + /* Get method */ + method = ext_enotify_get_method(renv, method_uri, &uri_body); + if (method == NULL) + return SIEVE_EXEC_FAILURE; + + /* Check provided operands */ + if (method->def != NULL && + method->def->runtime_check_operands != NULL) { + struct sieve_enotify_env nenv; + int result = SIEVE_EXEC_OK; + + i_zero(&nenv); + nenv.svinst = eenv->svinst; + nenv.method = method; + nenv.ehandler = renv->ehandler; + nenv.location = sieve_runtime_get_full_command_location(renv), + nenv.event = event_create(nenv.svinst->event); + event_set_append_log_prefix(nenv.event, "notify_action: "); + + /* Execute check function */ + if (method->def->runtime_check_operands( + &nenv, str_c(method_uri), uri_body, message, from, + sieve_result_pool(renv->result), method_context)) { + + /* Check any provided options */ + if (options != NULL) { + string_t *option = NULL; + int ret; + + /* Iterate through all provided options */ + while ((ret = sieve_stringlist_next_item( + options, &option)) > 0) { + const char *opt_name = NULL; + const char *opt_value = NULL; + + /* Parse option into <optionname> and + <value> */ + if (ext_enotify_option_parse( + &nenv, str_c(option), FALSE, + &opt_name, &opt_value)) { + + /* Set option */ + if (method->def->runtime_set_option != NULL) { + (void)method->def->runtime_set_option( + &nenv, *method_context, + opt_name, opt_value); + } + } + } + + /* Check for binary corruptions encountered + during string list iteration */ + if (ret >= 0) { + *method_r = method; + } else { + /* Binary corrupt */ + sieve_runtime_trace_error( + renv, "invalid item in options string list"); + result = SIEVE_EXEC_BIN_CORRUPT; + } + + } else { + /* No options */ + *method_r = method; + } + + } else { + /* Operand check failed */ + result = SIEVE_EXEC_FAILURE; + } + + event_unref(&nenv.event); + return result; + } + + /* No check function defined: a most unlikely situation */ + *method_context = NULL; + *method_r = method; + return SIEVE_EXEC_OK; +} + +/* + * Notify method printing + */ + +void sieve_enotify_method_printf(const struct sieve_enotify_print_env *penv, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_result_vprintf(penv->result_penv, fmt, args); + va_end(args); +} + +/* + * Action execution + */ + +struct event_passthrough * +sieve_enotify_create_finish_event(const struct sieve_enotify_exec_env *nenv) +{ + struct event_passthrough *e = + event_create_passthrough(nenv->event)-> + set_name("sieve_action_finished"); + + return e; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.h b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.h new file mode 100644 index 0000000..ec43202 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-common.h @@ -0,0 +1,122 @@ +#ifndef EXT_ENOTIFY_COMMON_H +#define EXT_ENOTIFY_COMMON_H + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "sieve-ext-variables.h" + +#include "sieve-ext-enotify.h" + +/* + * Extension + */ + +extern const struct sieve_extension_def enotify_extension; +extern const struct sieve_extension_capabilities notify_capabilities; + +struct ext_enotify_context { + const struct sieve_extension *var_ext; + ARRAY(struct sieve_enotify_method) notify_methods; +}; + + +/* + * Commands + */ + +extern const struct sieve_command_def notify_command; + +/* Codes for optional arguments */ + +enum cmd_notify_optional { + CMD_NOTIFY_OPT_END, + CMD_NOTIFY_OPT_FROM, + CMD_NOTIFY_OPT_OPTIONS, + CMD_NOTIFY_OPT_MESSAGE, + CMD_NOTIFY_OPT_IMPORTANCE +}; + +/* + * Tests + */ + +extern const struct sieve_command_def valid_notify_method_test; +extern const struct sieve_command_def notify_method_capability_test; + +/* + * Operations + */ + +extern const struct sieve_operation_def notify_operation; +extern const struct sieve_operation_def valid_notify_method_operation; +extern const struct sieve_operation_def notify_method_capability_operation; + +enum ext_variables_opcode { + EXT_ENOTIFY_OPERATION_NOTIFY, + EXT_ENOTIFY_OPERATION_VALID_NOTIFY_METHOD, + EXT_ENOTIFY_OPERATION_NOTIFY_METHOD_CAPABILITY +}; + +/* + * Operands + */ + +extern const struct sieve_operand_def encodeurl_operand; + +/* + * Modifiers + */ + +extern const struct sieve_variables_modifier_def encodeurl_modifier; + +/* + * Notify methods + */ + +void ext_enotify_methods_init(struct sieve_instance *svinst, + struct ext_enotify_context *ectx); +void ext_enotify_methods_deinit(struct ext_enotify_context *ectx); + +const struct sieve_enotify_method * +ext_enotify_method_find(const struct sieve_extension *ntfy_ext, + const char *identifier); + +/* + * Validation + */ + +bool ext_enotify_compile_check_arguments( + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *uri_arg, struct sieve_ast_argument *msg_arg, + struct sieve_ast_argument *from_arg, + struct sieve_ast_argument *options_arg); + +/* + * Runtime + */ + +bool ext_enotify_runtime_method_validate(const struct sieve_runtime_env *renv, + string_t *method_uri); + +const char * +ext_enotify_runtime_get_method_capability(const struct sieve_runtime_env *renv, + string_t *method_uri, + const char *capability); + +int ext_enotify_runtime_check_operands( + const struct sieve_runtime_env *renv, string_t *method_uri, + string_t *message, string_t *from, struct sieve_stringlist *options, + const struct sieve_enotify_method **method_r, void **method_context); + +/* + * Method printing + */ + +struct sieve_enotify_print_env { + const struct sieve_result_print_env *result_penv; +}; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-limits.h b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-limits.h new file mode 100644 index 0000000..aac48df --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify-limits.h @@ -0,0 +1,6 @@ +#ifndef EXT_ENOTIFY_LIMITS_H +#define EXT_ENOTIFY_LIMITS_H + +#define EXT_ENOTIFY_MAX_SCHEME_LEN 32 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify.c b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify.c new file mode 100644 index 0000000..df479b3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/ext-enotify.c @@ -0,0 +1,103 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension enotify + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5435 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "sieve-ext-variables.h" + +#include "ext-enotify-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_enotify_operations[] = { + ¬ify_operation, + &valid_notify_method_operation, + ¬ify_method_capability_operation +}; + +/* + * Extension + */ + +static bool ext_enotify_load(const struct sieve_extension *ext, void **context); +static void ext_enotify_unload(const struct sieve_extension *ext); +static bool ext_enotify_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def enotify_extension = { + .name = "enotify", + .load = ext_enotify_load, + .unload = ext_enotify_unload, + .validator_load = ext_enotify_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_enotify_operations), + SIEVE_EXT_DEFINE_OPERAND(encodeurl_operand) +}; + +static bool ext_enotify_load(const struct sieve_extension *ext, void **context) +{ + struct ext_enotify_context *ectx; + + if ( *context != NULL ) { + ext_enotify_unload(ext); + } + + ectx = i_new(struct ext_enotify_context, 1); + ectx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + *context = (void *) ectx; + + ext_enotify_methods_init(ext->svinst, ectx); + + sieve_extension_capabilities_register(ext, ¬ify_capabilities); + + return TRUE; +} + +static void ext_enotify_unload(const struct sieve_extension *ext) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ext->context; + + ext_enotify_methods_deinit(ectx); + + i_free(ectx); +} + +static bool ext_enotify_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ext->context; + + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, ¬ify_command); + sieve_validator_register_command(valdtr, ext, &valid_notify_method_test); + sieve_validator_register_command(valdtr, ext, ¬ify_method_capability_test); + + /* Register new set modifier for variables extension */ + sieve_variables_modifier_register + (ectx->var_ext, valdtr, ext, &encodeurl_modifier); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.am b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.am new file mode 100644 index 0000000..83f129c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_enotify_mailto.la + +AM_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_enotify_mailto_la_SOURCES = \ + uri-mailto.c \ + ntfy-mailto.c + +noinst_HEADERS = \ + uri-mailto.h + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.in b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.in new file mode 100644 index 0000000..49aa41a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/Makefile.in @@ -0,0 +1,687 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/enotify/mailto +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_enotify_mailto_la_LIBADD = +am_libsieve_ext_enotify_mailto_la_OBJECTS = uri-mailto.lo \ + ntfy-mailto.lo +libsieve_ext_enotify_mailto_la_OBJECTS = \ + $(am_libsieve_ext_enotify_mailto_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 = +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)/ntfy-mailto.Plo \ + ./$(DEPDIR)/uri-mailto.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 = $(libsieve_ext_enotify_mailto_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_enotify_mailto_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@ +noinst_LTLIBRARIES = libsieve_ext_enotify_mailto.la +AM_CPPFLAGS = \ + -I$(srcdir)/.. \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_enotify_mailto_la_SOURCES = \ + uri-mailto.c \ + ntfy-mailto.c + +noinst_HEADERS = \ + uri-mailto.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/lib-sieve/plugins/enotify/mailto/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/enotify/mailto/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_enotify_mailto.la: $(libsieve_ext_enotify_mailto_la_OBJECTS) $(libsieve_ext_enotify_mailto_la_DEPENDENCIES) $(EXTRA_libsieve_ext_enotify_mailto_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_enotify_mailto_la_OBJECTS) $(libsieve_ext_enotify_mailto_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfy-mailto.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri-mailto.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ntfy-mailto.Plo + -rm -f ./$(DEPDIR)/uri-mailto.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-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)/ntfy-mailto.Plo + -rm -f ./$(DEPDIR)/uri-mailto.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c new file mode 100644 index 0000000..4e104d1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c @@ -0,0 +1,794 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Notify method mailto + * -------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5436 + * Implementation: full + * Status: testing + * + */ + +/* FIXME: URI syntax conforms to something somewhere in between RFC 2368 and + * draft-duerst-mailto-bis-05.txt. Should fully migrate to new specification + * when it matures. This requires modifications to the address parser (no + * whitespace allowed within the address itself) and UTF-8 support will be + * required in the URL. + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "message-date.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-address.h" +#include "sieve-address-source.h" +#include "sieve-message.h" +#include "sieve-smtp.h" +#include "sieve-settings.h" + +#include "sieve-ext-enotify.h" + +#include "rfc2822.h" + +#include "uri-mailto.h" + +/* + * Configuration + */ + +#define NTFY_MAILTO_MAX_RECIPIENTS 8 +#define NTFY_MAILTO_MAX_HEADERS 16 +#define NTFY_MAILTO_MAX_SUBJECT 256 + +/* + * Mailto notification configuration + */ + +struct ntfy_mailto_config { + pool_t pool; + struct sieve_address_source envelope_from; +}; + +/* + * Mailto notification method + */ + +static bool ntfy_mailto_load + (const struct sieve_enotify_method *nmth, void **context); +static void ntfy_mailto_unload + (const struct sieve_enotify_method *nmth); + +static bool ntfy_mailto_compile_check_uri + (const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body); +static bool ntfy_mailto_compile_check_from + (const struct sieve_enotify_env *nenv, string_t *from); + +static const char *ntfy_mailto_runtime_get_notify_capability + (const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body, + const char *capability); +static bool ntfy_mailto_runtime_check_uri + (const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body); +static bool ntfy_mailto_runtime_check_operands + (const struct sieve_enotify_env *nenv, const char *uri,const char *uri_body, + string_t *message, string_t *from, pool_t context_pool, + void **method_context); + +static int ntfy_mailto_action_check_duplicates + (const struct sieve_enotify_env *nenv, + const struct sieve_enotify_action *nact, + const struct sieve_enotify_action *nact_other); + +static void ntfy_mailto_action_print + (const struct sieve_enotify_print_env *penv, + const struct sieve_enotify_action *nact); + +static int ntfy_mailto_action_execute + (const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact); + +const struct sieve_enotify_method_def mailto_notify = { + "mailto", + ntfy_mailto_load, + ntfy_mailto_unload, + ntfy_mailto_compile_check_uri, + NULL, + ntfy_mailto_compile_check_from, + NULL, + ntfy_mailto_runtime_check_uri, + ntfy_mailto_runtime_get_notify_capability, + ntfy_mailto_runtime_check_operands, + NULL, + ntfy_mailto_action_check_duplicates, + ntfy_mailto_action_print, + ntfy_mailto_action_execute +}; + +/* + * Reserved and unique headers + */ + +static const char *_reserved_headers[] = { + "auto-submitted", + "received", + "message-id", + "data", + "bcc", + "in-reply-to", + "references", + "resent-date", + "resent-from", + "resent-sender", + "resent-to", + "resent-cc", + "resent-bcc", + "resent-msg-id", + "from", + "sender", + NULL +}; + +static const char *_unique_headers[] = { + "reply-to", + NULL +}; + +/* + * Method context data + */ + +struct ntfy_mailto_context { + struct uri_mailto *uri; + const struct smtp_address *from_address; +}; + +/* + * Method registration + */ + +static bool ntfy_mailto_load +(const struct sieve_enotify_method *nmth, void **context) +{ + struct sieve_instance *svinst = nmth->svinst; + struct ntfy_mailto_config *config; + pool_t pool; + + if ( *context != NULL ) { + ntfy_mailto_unload(nmth); + } + + pool = pool_alloconly_create("ntfy_mailto_config", 256); + config = p_new(pool, struct ntfy_mailto_config, 1); + config->pool = pool; + + (void)sieve_address_source_parse_from_setting (svinst, + config->pool, "sieve_notify_mailto_envelope_from", + &config->envelope_from); + + *context = (void *) config; + + return TRUE; +} + +static void ntfy_mailto_unload +(const struct sieve_enotify_method *nmth) +{ + struct ntfy_mailto_config *config = + (struct ntfy_mailto_config *) nmth->context; + + pool_unref(&config->pool); +} + +/* + * URI parsing + */ + +struct ntfy_mailto_uri_env { + const struct sieve_enotify_env *nenv; + + struct event *event; + + struct uri_mailto_log uri_log; +}; + +static void ATTR_FORMAT(5, 0) +ntfy_mailto_uri_logv(void *context, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, va_list args) +{ + struct ntfy_mailto_uri_env *nmuenv = context; + const struct sieve_enotify_env *nenv = nmuenv->nenv; + + sieve_event_logv(nenv->svinst, nenv->ehandler, nmuenv->event, + log_type, csrc_filename, csrc_linenum, + nenv->location, 0, fmt, args); +} + +static void +ntfy_mailto_uri_env_init(struct ntfy_mailto_uri_env *nmuenv, + const struct sieve_enotify_env *nenv) +{ + i_zero(nmuenv); + nmuenv->nenv = nenv; + nmuenv->event = event_create(nenv->event); + event_set_append_log_prefix(nmuenv->event, "mailto URI: "); + + nmuenv->uri_log.context = nmuenv; + nmuenv->uri_log.logv = ntfy_mailto_uri_logv; +} + +static void +ntfy_mailto_uri_env_deinit(struct ntfy_mailto_uri_env *nmuenv) +{ + event_unref(&nmuenv->event); +} + +/* + * Validation + */ + + +static bool ntfy_mailto_compile_check_uri +(const struct sieve_enotify_env *nenv, const char *uri ATTR_UNUSED, + const char *uri_body) +{ + struct ntfy_mailto_uri_env nmuenv; + bool result; + + ntfy_mailto_uri_env_init(&nmuenv, nenv); + result = uri_mailto_validate( + uri_body, _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, NTFY_MAILTO_MAX_HEADERS, + &nmuenv.uri_log); + ntfy_mailto_uri_env_deinit(&nmuenv); + + return result; +} + +static bool ntfy_mailto_compile_check_from +(const struct sieve_enotify_env *nenv, string_t *from) +{ + const char *error; + bool result = FALSE; + + T_BEGIN { + result = sieve_address_validate_str(from, &error); + if ( !result ) { + sieve_enotify_error(nenv, + "specified :from address '%s' is invalid for " + "the mailto method: %s", + str_sanitize(str_c(from), 128), error); + } + } T_END; + + return result; +} + +/* + * Runtime + */ + +struct ntfy_mailto_runtime_env { + const struct sieve_enotify_env *nenv; + + struct event *event; +}; + +static const char *ntfy_mailto_runtime_get_notify_capability +(const struct sieve_enotify_env *nenv ATTR_UNUSED, const char *uri ATTR_UNUSED, + const char *uri_body, const char *capability) +{ + if ( !uri_mailto_validate(uri_body, _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, NTFY_MAILTO_MAX_HEADERS, NULL) ) { + return NULL; + } + + if ( strcasecmp(capability, "online") == 0 ) + return "maybe"; + + return NULL; +} + +static bool ntfy_mailto_runtime_check_uri +(const struct sieve_enotify_env *nenv ATTR_UNUSED, const char *uri ATTR_UNUSED, + const char *uri_body) +{ + return uri_mailto_validate + (uri_body, _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, NTFY_MAILTO_MAX_HEADERS, NULL); +} + +static bool ntfy_mailto_runtime_check_operands +(const struct sieve_enotify_env *nenv, const char *uri ATTR_UNUSED, + const char *uri_body, string_t *message ATTR_UNUSED, string_t *from, + pool_t context_pool, void **method_context) +{ + struct ntfy_mailto_context *mtctx; + struct uri_mailto *parsed_uri; + const struct smtp_address *address; + struct ntfy_mailto_uri_env nmuenv; + const char *error; + + /* Need to create context before validation to have arrays present */ + mtctx = p_new(context_pool, struct ntfy_mailto_context, 1); + + /* Validate :from */ + if ( from != NULL ) { + T_BEGIN { + address = sieve_address_parse_str(from, &error); + if ( address == NULL ) { + sieve_enotify_error(nenv, + "specified :from address '%s' is invalid for " + "the mailto method: %s", + str_sanitize(str_c(from), 128), error); + } else + mtctx->from_address = + smtp_address_clone(context_pool, address); + } T_END; + + if ( address == NULL ) return FALSE; + } + + ntfy_mailto_uri_env_init(&nmuenv, nenv); + parsed_uri = uri_mailto_parse(uri_body, context_pool, + _reserved_headers, _unique_headers, + NTFY_MAILTO_MAX_RECIPIENTS, + NTFY_MAILTO_MAX_HEADERS, + &nmuenv.uri_log); + ntfy_mailto_uri_env_deinit(&nmuenv); + + if (parsed_uri == NULL) + return FALSE; + + mtctx->uri = parsed_uri; + *method_context = (void *) mtctx; + return TRUE; +} + +/* + * Action duplicates + */ + +static int ntfy_mailto_action_check_duplicates +(const struct sieve_enotify_env *nenv ATTR_UNUSED, + const struct sieve_enotify_action *nact, + const struct sieve_enotify_action *nact_other) +{ + struct ntfy_mailto_context *mtctx = + (struct ntfy_mailto_context *) nact->method_context; + struct ntfy_mailto_context *mtctx_other = + (struct ntfy_mailto_context *) nact_other->method_context; + const struct uri_mailto_recipient *new_rcpts, *old_rcpts; + unsigned int new_count, old_count, i, j; + unsigned int del_start = 0, del_len = 0; + + new_rcpts = array_get(&mtctx->uri->recipients, &new_count); + old_rcpts = array_get(&mtctx_other->uri->recipients, &old_count); + + for ( i = 0; i < new_count; i++ ) { + for ( j = 0; j < old_count; j++ ) { + if ( smtp_address_equals + (new_rcpts[i].address, old_rcpts[j].address) ) + break; + } + + if ( j == old_count ) { + /* Not duplicate */ + if ( del_len > 0 ) { + /* Perform pending deletion */ + array_delete(&mtctx->uri->recipients, del_start, del_len); + + /* Make sure the loop integrity is maintained */ + i -= del_len; + new_rcpts = array_get(&mtctx->uri->recipients, &new_count); + } + del_len = 0; + } else { + /* Mark deletion */ + if ( del_len == 0 ) + del_start = i; + del_len++; + } + } + + /* Perform pending deletion */ + if ( del_len > 0 ) { + array_delete(&mtctx->uri->recipients, del_start, del_len); + } + + return ( array_count(&mtctx->uri->recipients) > 0 ? 0 : 1 ); +} + +/* + * Action printing + */ + +static void ntfy_mailto_action_print +(const struct sieve_enotify_print_env *penv, + const struct sieve_enotify_action *nact) +{ + unsigned int count, i; + const struct uri_mailto_recipient *recipients; + const struct uri_mailto_header_field *headers; + struct ntfy_mailto_context *mtctx = + (struct ntfy_mailto_context *) nact->method_context; + + /* Print main method parameters */ + + sieve_enotify_method_printf + (penv, " => importance : %llu\n", + (unsigned long long)nact->importance); + + if ( nact->message != NULL ) + sieve_enotify_method_printf + (penv, " => subject : %s\n", nact->message); + else if ( mtctx->uri->subject != NULL ) + sieve_enotify_method_printf + (penv, " => subject : %s\n", mtctx->uri->subject); + + if ( nact->from != NULL ) + sieve_enotify_method_printf + (penv, " => from : %s\n", nact->from); + + /* Print mailto: recipients */ + + sieve_enotify_method_printf(penv, " => recipients :\n" ); + + recipients = array_get(&mtctx->uri->recipients, &count); + if ( count == 0 ) { + sieve_enotify_method_printf(penv, " NONE, action has no effect\n"); + } else { + for ( i = 0; i < count; i++ ) { + if ( recipients[i].carbon_copy ) + sieve_enotify_method_printf + (penv, " + Cc: %s\n", recipients[i].full); + else + sieve_enotify_method_printf + (penv, " + To: %s\n", recipients[i].full); + } + } + + /* Print accepted headers for notification message */ + + headers = array_get(&mtctx->uri->headers, &count); + if ( count > 0 ) { + sieve_enotify_method_printf(penv, " => headers :\n" ); + for ( i = 0; i < count; i++ ) { + sieve_enotify_method_printf(penv, " + %s: %s\n", + headers[i].name, headers[i].body); + } + } + + /* Print body for notification message */ + + if ( mtctx->uri->body != NULL ) + sieve_enotify_method_printf + (penv, " => body : \n--\n%s\n--\n", mtctx->uri->body); + + /* Finish output with an empty line */ + + sieve_enotify_method_printf(penv, "\n"); +} + +/* + * Action execution + */ + +static bool _contains_8bit(const char *msg) +{ + const unsigned char *s = (const unsigned char *)msg; + + for (; *s != '\0'; s++) { + if ((*s & 0x80) != 0) + return TRUE; + } + + return FALSE; +} + +static int ntfy_mailto_send +(const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact, + const struct smtp_address *owner_email) +{ + struct sieve_instance *svinst = nenv->svinst; + const struct sieve_message_data *msgdata = nenv->msgdata; + const struct sieve_script_env *senv = nenv->scriptenv; + struct ntfy_mailto_context *mtctx = + (struct ntfy_mailto_context *) nact->method_context; + struct ntfy_mailto_config *mth_config = + (struct ntfy_mailto_config *)nenv->method->context; + struct sieve_address_source env_from = + mth_config->envelope_from; + const char *from = NULL; + const struct smtp_address *from_smtp = NULL; + const char *subject = mtctx->uri->subject; + const char *body = mtctx->uri->body; + string_t *to, *cc, *all; + const struct uri_mailto_recipient *recipients; + const struct uri_mailto_header_field *headers; + struct sieve_smtp_context *sctx; + struct ostream *output; + string_t *msg; + unsigned int count, i, hcount, h; + const char *outmsgid, *error; + int ret; + + /* Get recipients */ + recipients = array_get(&mtctx->uri->recipients, &count); + if ( count == 0 ) { + sieve_enotify_warning(nenv, + "notify mailto uri specifies no recipients; action has no effect"); + return 0; + } + + /* Just to be sure */ + if ( !sieve_smtp_available(senv) ) { + sieve_enotify_global_warning(nenv, + "notify mailto method has no means to send mail"); + return 0; + } + + /* Determine which sender to use + + From RFC 5436, Section 2.3: + + The ":from" tag overrides the default sender of the notification + message. "Sender", here, refers to the value used in the [RFC5322] + "From" header. Implementations MAY also use this value in the + [RFC5321] "MAIL FROM" command (the "envelope sender"), or they may + prefer to establish a mailbox that receives bounces from notification + messages. + */ + if ( (nenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 ) { + from_smtp = sieve_message_get_sender(nenv->msgctx); + if ( from_smtp == NULL ) { + /* "<>" */ + i_zero(&env_from); + env_from.type = SIEVE_ADDRESS_SOURCE_EXPLICIT; + } + } + from = nact->from; + if ( (ret=sieve_address_source_get_address(&env_from, svinst, + senv, nenv->msgctx, nenv->flags, &from_smtp)) < 0 ) { + from_smtp = NULL; + } else if ( ret == 0 ) { + if ( mtctx->from_address != NULL ) + from_smtp = mtctx->from_address; + else if ( svinst->user_email != NULL ) + from_smtp = svinst->user_email; + else { + from_smtp = sieve_get_postmaster_smtp(senv); + if (from == NULL) + from = sieve_get_postmaster_address(senv); + } + } + + /* Determine message from address */ + if ( from == NULL ) { + if ( from_smtp == NULL ) + from = sieve_get_postmaster_address(senv); + else { + from = t_strdup_printf("<%s>", + smtp_address_encode(from_smtp)); + } + } + + /* Determine subject */ + if ( nact->message != NULL ) { + /* FIXME: handle UTF-8 */ + subject = str_sanitize(nact->message, NTFY_MAILTO_MAX_SUBJECT); + } else if ( subject == NULL ) { + const char *const *hsubject; + + /* Fetch subject from original message */ + if ( mail_get_headers_utf8 + (msgdata->mail, "subject", &hsubject) > 0 ) + subject = str_sanitize(t_strdup_printf("Notification: %s", hsubject[0]), + NTFY_MAILTO_MAX_SUBJECT); + else + subject = "Notification: (no subject)"; + } + + /* Compose To and Cc headers */ + to = NULL; + cc = NULL; + all = t_str_new(256); + for ( i = 0; i < count; i++ ) { + if ( recipients[i].carbon_copy ) { + if ( cc == NULL ) { + cc = t_str_new(256); + str_append(cc, recipients[i].full); + } else { + str_append(cc, ", "); + str_append(cc, recipients[i].full); + } + } else { + if ( to == NULL ) { + to = t_str_new(256); + str_append(to, recipients[i].full); + } else { + str_append(to, ", "); + str_append(to, recipients[i].full); + } + } + if ( i < 3) { + if ( i > 0 ) + str_append(all, ", "); + str_append(all, + smtp_address_encode_path(recipients[i].address)); + } else if (i == 3) { + str_printfa(all, ", ... (%u total)", count); + } + } + + msg = t_str_new(512); + outmsgid = sieve_message_get_new_id(svinst); + + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Message-ID", outmsgid); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + rfc2822_header_utf8_printf(msg, "Subject", "%s", subject); + + rfc2822_header_write_address(msg, "From", from); + + if ( to != NULL ) + rfc2822_header_write_address(msg, "To", str_c(to)); + if ( cc != NULL ) + rfc2822_header_write_address(msg, "Cc", str_c(cc)); + + rfc2822_header_printf(msg, "Auto-Submitted", + "auto-notified; owner-email=\"%s\"", + smtp_address_encode(owner_email)); + rfc2822_header_write(msg, "Precedence", "bulk"); + + /* Set importance */ + switch ( nact->importance ) { + case 1: + rfc2822_header_write(msg, "X-Priority", "1 (Highest)"); + rfc2822_header_write(msg, "Importance", "High"); + break; + case 3: + rfc2822_header_write(msg, "X-Priority", "5 (Lowest)"); + rfc2822_header_write(msg, "Importance", "Low"); + break; + case 2: + default: + rfc2822_header_write(msg, "X-Priority", "3 (Normal)"); + rfc2822_header_write(msg, "Importance", "Normal"); + break; + } + + /* Add custom headers */ + + headers = array_get(&mtctx->uri->headers, &hcount); + for ( h = 0; h < hcount; h++ ) { + const char *name = rfc2822_header_field_name_sanitize(headers[h].name); + + rfc2822_header_write(msg, name, headers[h].body); + } + + /* Generate message body */ + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + if ( body != NULL ) { + if (_contains_8bit(body)) { + rfc2822_header_write + (msg, "Content-Type", "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + } else { + rfc2822_header_write + (msg, "Content-Type", "text/plain; charset=us-ascii"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + } + str_printfa(msg, "\r\n%s\r\n", body); + + } else { + rfc2822_header_write + (msg, "Content-Type", "text/plain; charset=US-ASCII"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + + str_append(msg, "\r\nNotification of new message.\r\n"); + } + + sctx = sieve_smtp_start(senv, from_smtp); + + /* Send message to all recipients */ + for ( i = 0; i < count; i++ ) + sieve_smtp_add_rcpt(sctx, recipients[i].address); + + output = sieve_smtp_send(sctx); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { + if (ret < 0) { + sieve_enotify_global_error(nenv, + "failed to send mail notification to %s: %s (temporary failure)", + str_c(all), str_sanitize(error, 512)); + } else { + sieve_enotify_global_log_error(nenv, + "failed to send mail notification to %s: %s (permanent failure)", + str_c(all), str_sanitize(error, 512)); + } + } else { + struct event_passthrough *e = + sieve_enotify_create_finish_event(nenv)-> + add_str("notify_target", str_c(all)); + + sieve_enotify_event_log(nenv, e->event(), + "sent mail notification to %s", + str_c(all)); + } + + return 0; +} + +static int ntfy_mailto_action_execute +(const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact) +{ + struct sieve_instance *svinst = nenv->svinst; + const struct sieve_script_env *senv = nenv->scriptenv; + struct mail *mail = nenv->msgdata->mail; + const struct smtp_address *owner_email; + const char *const *hdsp; + int ret; + + owner_email = svinst->user_email; + if ( owner_email == NULL && + (nenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 ) + owner_email = sieve_message_get_final_recipient(nenv->msgctx); + if ( owner_email == NULL ) { + owner_email = sieve_get_postmaster_smtp(senv); + } + i_assert( owner_email != NULL ); + + /* Is the message an automatic reply ? */ + if ( (ret=mail_get_headers(mail, "auto-submitted", &hdsp)) < 0 ) { + sieve_enotify_critical(nenv, + "mailto notification: " + "failed to read `auto-submitted' header field", + "mailto notification: " + "failed to read `auto-submitted' header field: %s", + mailbox_get_last_internal_error(mail->box, NULL)); + return -1; + } + + /* Theoretically multiple headers could exist, so lets make sure */ + if ( ret > 0 ) { + while ( *hdsp != NULL ) { + if ( strcasecmp(*hdsp, "no") != 0 ) { + const struct smtp_address *sender = NULL; + const char *from; + + if ( (nenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 ) + sender = sieve_message_get_sender(nenv->msgctx); + from = (sender == NULL ? "" : t_strdup_printf + (" from <%s>", smtp_address_encode(sender))); + + sieve_enotify_global_info(nenv, + "not sending notification " + "for auto-submitted message%s", from); + return 0; + } + hdsp++; + } + } + + T_BEGIN { + ret = ntfy_mailto_send(nenv, nact, owner_email); + } T_END; + + return ret; +} + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.c b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.c new file mode 100644 index 0000000..c5a0953 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.c @@ -0,0 +1,683 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* FIXME: URI syntax conforms to something somewhere in between RFC 2368 and + draft-duerst-mailto-bis-05.txt. Should fully migrate to new + specification when it matures. This requires modifications to the + address parser (no whitespace allowed within the address itself) and + UTF-8 support will be required in the URL. + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "str-sanitize.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-address.h" +#include "sieve-message.h" + +#include "uri-mailto.h" + +/* Parser object */ + +struct uri_mailto_parser { + pool_t pool; + const struct uri_mailto_log *log; + + struct uri_mailto *uri; + + const char **reserved_headers; + const char **unique_headers; + + int max_recipients; + int max_headers; +}; + +/* Error handling */ + +#define uri_mailto_error(PARSER, ...) \ + uri_mailto_log((PARSER), LOG_TYPE_ERROR, \ + __FILE__, __LINE__, __VA_ARGS__) +#define uri_mailto_warning(PARSER, ...) \ + uri_mailto_log((PARSER), LOG_TYPE_WARNING, \ + __FILE__, __LINE__, __VA_ARGS__) + +static inline void ATTR_FORMAT(5, 6) +uri_mailto_log(struct uri_mailto_parser *parser, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, ...) +{ + va_list args; + + if (parser->log == NULL || parser->log->logv == NULL) + return; + + va_start(args, fmt); + parser->log->logv(parser->log->context, log_type, + csrc_filename, csrc_linenum, fmt, args); + va_end(args); +} + + +/* + * Error handling + */ + +/* + * Reserved and unique headers + */ + +static inline bool +uri_mailto_header_is_reserved(struct uri_mailto_parser *parser, + const char *field_name) +{ + const char **hdr = parser->reserved_headers; + + if (hdr == NULL) + return FALSE; + + /* Check whether it is reserved */ + while (*hdr != NULL) { + if (strcasecmp(field_name, *hdr) == 0) + return TRUE; + hdr++; + } + return FALSE; +} + +static inline bool +uri_mailto_header_is_unique(struct uri_mailto_parser *parser, + const char *field_name) +{ + const char **hdr = parser->unique_headers; + + if (hdr == NULL) + return FALSE; + + /* Check whether it is supposed to be unique */ + while (*hdr != NULL) { + if (strcasecmp(field_name, *hdr) == 0) + return TRUE; + hdr++; + } + return FALSE; +} + +/* + * Low-level URI parsing. + * + * FIXME: much of this implementation will be common to other URI schemes. This + * should be merged into a common implementation. + */ + +static const char _qchar_lookup[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, // 70 + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F0 +}; + +static inline bool _is_qchar(char c) +{ + return ((_qchar_lookup[(unsigned char)c] & 0x01) != 0); +} + +static inline int _decode_hex_digit(unsigned char digit) +{ + switch (digit) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return (int) digit - '0'; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return (int) digit - 'a' + 0x0a; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return (int) digit - 'A' + 0x0A; + } + return -1; +} + +static bool _parse_hex_value(const char **in, char *out) +{ + int value, digit; + + if ((digit = _decode_hex_digit((unsigned char)**in)) < 0) + return FALSE; + + value = digit << 4; + (*in)++; + + if ((digit = _decode_hex_digit((unsigned char)**in)) < 0) + return FALSE; + + value |= digit; + (*in)++; + + if (value == 0) + return FALSE; + + *out = (char)value; + return TRUE; +} + +/* + * URI recipient parsing + */ + +static bool +uri_mailto_add_valid_recipient(struct uri_mailto_parser *parser, + string_t *recipient, bool cc) +{ + struct uri_mailto *uri = parser->uri; + struct uri_mailto_recipient *new_recipient; + struct uri_mailto_recipient *rcpts; + unsigned int count, i; + const char *error; + const struct smtp_address *address; + + /* Verify recipient */ + if ((address = sieve_address_parse_str(recipient, &error)) == NULL) { + uri_mailto_error(parser, "invalid recipient '%s': %s", + str_sanitize(str_c(recipient), 80), error); + return FALSE; + } + + /* Add recipient to the uri */ + if (uri != NULL) { + /* Get current recipients */ + rcpts = array_get_modifiable(&uri->recipients, &count); + + /* Enforce limits */ + if (parser->max_recipients > 0 && + (int)count >= parser->max_recipients) { + if ((int)count == parser->max_recipients) { + uri_mailto_warning( + parser, + "more than the maximum %u recipients specified; " + "rest is discarded", + parser->max_recipients); + } + return TRUE; + } + + /* Check for duplicate first */ + for (i = 0; i < count; i++) { + if (smtp_address_equals(rcpts[i].address, address)) { + /* Upgrade existing Cc: recipient to a To: + recipient if possible */ + rcpts[i].carbon_copy = + (rcpts[i].carbon_copy && cc); + + uri_mailto_warning( + parser, + "ignored duplicate recipient '%s'", + str_sanitize(str_c(recipient), 80)); + return TRUE; + } + } + + /* Add */ + new_recipient = array_append_space(&uri->recipients); + new_recipient->carbon_copy = cc; + new_recipient->full = p_strdup(parser->pool, str_c(recipient)); + new_recipient->address = + smtp_address_clone(parser->pool, address); + } + + return TRUE; +} + +static bool +uri_mailto_parse_recipients(struct uri_mailto_parser *parser, + const char **uri_p) +{ + string_t *to = t_str_new(128); + const char *p = *uri_p; + + if (*p == '\0' || *p == '?') + return TRUE; + + while (*p != '\0' && *p != '?') { + if (*p == '%') { + /* % encoded character */ + char ch; + + p++; + + /* Parse 2-digit hex value */ + if (!_parse_hex_value(&p, &ch)) { + uri_mailto_error(parser, "invalid %% encoding"); + return FALSE; + } + + /* Check for delimiter */ + if (ch == ',') { + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient( + parser, to, FALSE)) + return FALSE; + + /* Reset for next recipient */ + str_truncate(to, 0); + } else { + /* Content character */ + str_append_c(to, ch); + } + } else { + if (*p == ':' || *p == ';' || *p == ',' || + !_is_qchar(*p)) { + uri_mailto_error( + parser, + "invalid character '%c' in 'to' part", *p); + return FALSE; + } + + /* Content character */ + str_append_c(to, *p); + p++; + } + } + + i_assert(*p == '\0' || *p == '?'); + + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient(parser, to, FALSE)) + return FALSE; + + *uri_p = p; + return TRUE; +} + +static bool +uri_mailto_parse_header_recipients(struct uri_mailto_parser *parser, + string_t *rcpt_header, bool cc) +{ + string_t *to = t_str_new(128); + const char *p = (const char *)str_data(rcpt_header); + const char *pend = p + str_len(rcpt_header); + + while (p < pend) { + if (*p == ',') { + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient(parser, to, cc)) + return FALSE; + + /* Reset for next recipient */ + str_truncate(to, 0); + } else { + /* Content character */ + str_append_c(to, *p); + } + p++; + } + + /* Verify and add recipient */ + if (!uri_mailto_add_valid_recipient(parser, to, cc)) + return FALSE; + + return TRUE; +} + +/* URI header parsing */ + +static bool +uri_mailto_header_is_duplicate(struct uri_mailto_parser *parser, + const char *field_name) +{ + struct uri_mailto *uri = parser->uri; + + if (uri == NULL) + return FALSE; + + if (uri_mailto_header_is_unique(parser, field_name)) { + const struct uri_mailto_header_field *hdrs; + unsigned int count, i; + + hdrs = array_get(&uri->headers, &count); + for (i = 0; i < count; i++) { + if (strcasecmp(hdrs[i].name, field_name) == 0) + return TRUE; + } + } + return FALSE; +} + +static bool +uri_mailto_parse_headers(struct uri_mailto_parser *parser, const char **uri_p) +{ + struct uri_mailto *uri = parser->uri; + unsigned int header_count = 0; + string_t *field = t_str_new(128); + const char *p = *uri_p; + + while (*p != '\0') { + enum { + _HNAME_IGNORED, + _HNAME_GENERIC, + _HNAME_TO, + _HNAME_CC, + _HNAME_SUBJECT, + _HNAME_BODY, + } hname_type = _HNAME_GENERIC; + struct uri_mailto_header_field *hdrf = NULL; + const char *field_name; + + /* Parse field name */ + while (*p != '\0' && *p != '=') { + char ch = *p; + p++; + + if (ch == '%') { + /* Encoded, parse 2-digit hex value */ + if (!_parse_hex_value(&p, &ch)) { + uri_mailto_error(parser, + "invalid %% encoding"); + return FALSE; + } + } else if (ch != '=' && !_is_qchar(ch)) { + uri_mailto_error( + parser, + "invalid character '%c' in header field name part", + ch); + return FALSE; + } + + str_append_c(field, ch); + } + if (*p != '\0') + p++; + + /* Verify field name */ + if (!rfc2822_header_field_name_verify(str_c(field), + str_len(field))) { + uri_mailto_error(parser, "invalid header field name"); + return FALSE; + } + + if (parser->max_headers > -1 && + (int)header_count >= parser->max_headers) { + /* Refuse to accept more headers than allowed by policy + */ + if ((int)header_count == parser->max_headers) { + uri_mailto_warning( + parser, + "more than the maximum %u headers specified; " + "rest is discarded", + parser->max_headers); + } + + hname_type = _HNAME_IGNORED; + } else { + /* Add new header field to array and assign its name */ + + field_name = str_c(field); + if (strcasecmp(field_name, "to") == 0) + hname_type = _HNAME_TO; + else if (strcasecmp(field_name, "cc") == 0) + hname_type = _HNAME_CC; + else if (strcasecmp(field_name, "subject") == 0) + hname_type = _HNAME_SUBJECT; + else if (strcasecmp(field_name, "body") == 0) + hname_type = _HNAME_BODY; + else if (!uri_mailto_header_is_reserved(parser, field_name)) { + if (uri != NULL) { + if (!uri_mailto_header_is_duplicate(parser, field_name)) { + hdrf = array_append_space(&uri->headers); + hdrf->name = p_strdup(parser->pool, field_name); + } else { + uri_mailto_warning( + parser, + "ignored duplicate for unique header field '%s'", + str_sanitize(field_name, 32)); + hname_type = _HNAME_IGNORED; + } + } else { + hname_type = _HNAME_IGNORED; + } + } else { + uri_mailto_warning( + parser, + "ignored reserved header field '%s'", + str_sanitize(field_name, 32)); + hname_type = _HNAME_IGNORED; + } + } + + header_count++; + + /* Reset for field body */ + str_truncate(field, 0); + + /* Parse field body */ + while (*p != '\0' && *p != '&') { + char ch = *p; + p++; + + if (ch == '%') { + /* Encoded, parse 2-digit hex value */ + if (!_parse_hex_value(&p, &ch)) { + uri_mailto_error(parser, + "invalid %% encoding"); + return FALSE; + } + } else if (ch != '=' && !_is_qchar(ch)) { + uri_mailto_error( + parser, + "invalid character '%c' in header field value part", + ch); + return FALSE; + } + str_append_c(field, ch); + } + if (*p != '\0') + p++; + + /* Verify field body */ + if (hname_type == _HNAME_BODY) { + // FIXME: verify body ... + } else { + if (!rfc2822_header_field_body_verify( + str_c(field), str_len(field), FALSE, FALSE)) { + uri_mailto_error(parser, + "invalid header field body"); + return FALSE; + } + } + + /* Assign field body */ + + switch (hname_type) { + case _HNAME_IGNORED: + break; + case _HNAME_TO: + /* Gracefully allow duplicate To fields */ + if (!uri_mailto_parse_header_recipients( + parser, field, FALSE)) + return FALSE; + break; + case _HNAME_CC: + /* Gracefully allow duplicate Cc fields */ + if (!uri_mailto_parse_header_recipients( + parser, field, TRUE)) + return FALSE; + break; + case _HNAME_SUBJECT: + /* Ignore duplicate subject field */ + if (uri != NULL) { + if (uri->subject == NULL) { + uri->subject = + p_strdup(parser->pool, str_c(field)); + } else { + uri_mailto_warning( + parser, + "ignored duplicate subject field"); + } + } + break; + case _HNAME_BODY: + /* Ignore duplicate body field */ + if (uri != NULL) { + if (uri->body == NULL) { + uri->body = p_strdup( + parser->pool, str_c(field)); + } else { + uri_mailto_warning( + parser, "ignored duplicate body field"); + } + } + break; + case _HNAME_GENERIC: + if (uri != NULL && hdrf != NULL) + hdrf->body = p_strdup(parser->pool, str_c(field)); + break; + } + + /* Reset for next name */ + str_truncate(field, 0); + } + + /* Skip '&' */ + if (*p != '\0') + p++; + + *uri_p = p; + return TRUE; +} + +static bool +uri_mailto_parse_uri(struct uri_mailto_parser *parser, const char *uri_body) +{ + const char *p = uri_body; + + /* + * mailtoURI = "mailto:" [ to ] [ hfields ] + * to = [ addr-spec *("%2C" addr-spec ) ] + * hfields = "?" hfield *( "&" hfield ) + * hfield = hfname "=" hfvalue + * hfname = *qchar + * hfvalue = *qchar + * addr-spec = local-part "@" domain + * local-part = dot-atom / quoted-string + * qchar = unreserved / pct-encoded / some-delims + * some-delims = "!" / "$" / "'" / "(" / ")" / "*" + * / "+" / "," / ";" / ":" / "@" + * + * to ~= *tqchar + * tqchar ~= <qchar> without ";" and ":" + * + * Scheme 'mailto:' already parsed, starting parse after colon + */ + + /* First extract to-part by searching for '?' and decoding % items + */ + + if (!uri_mailto_parse_recipients(parser, &p)) + return FALSE; + + if (*p == '\0') + return TRUE; + i_assert(*p == '?'); + p++; + + /* Extract hfield items */ + + while (*p != '\0') { + /* Extract hfield item by searching for '&' and decoding '%' + items */ + if (!uri_mailto_parse_headers(parser, &p)) + return FALSE; + } + return TRUE; +} + +/* + * Validation + */ + +bool uri_mailto_validate(const char *uri_body, + const char **reserved_headers, + const char **unique_headers, int max_recipients, + int max_headers, const struct uri_mailto_log *log) +{ + struct uri_mailto_parser parser; + + i_zero(&parser); + parser.log = log; + parser.max_recipients = max_recipients; + parser.max_headers = max_headers; + parser.reserved_headers = reserved_headers; + parser.unique_headers = unique_headers; + + /* If no errors are reported, we don't need to record any data */ + if (log != NULL) { + parser.pool = pool_datastack_create(); + + parser.uri = p_new(parser.pool, struct uri_mailto, 1); + p_array_init(&parser.uri->recipients, parser.pool, max_recipients); + p_array_init(&parser.uri->headers, parser.pool, max_headers); + } + + if (!uri_mailto_parse_uri(&parser, uri_body)) + return FALSE; + + if (log != NULL) { + if (array_count(&parser.uri->recipients) == 0) { + uri_mailto_warning( + &parser, + "notification URI specifies no recipients"); + } + } + return TRUE; +} + +/* + * Parsing + */ + +struct uri_mailto * +uri_mailto_parse(const char *uri_body, pool_t pool, + const char **reserved_headers, const char **unique_headers, + int max_recipients, int max_headers, + const struct uri_mailto_log *log) +{ + struct uri_mailto_parser parser; + + parser.pool = pool; + parser.log = log; + parser.max_recipients = max_recipients; + parser.max_headers = max_headers; + parser.reserved_headers = reserved_headers; + parser.unique_headers = unique_headers; + + parser.uri = p_new(pool, struct uri_mailto, 1); + p_array_init(&parser.uri->recipients, pool, max_recipients); + p_array_init(&parser.uri->headers, pool, max_headers); + + if (!uri_mailto_parse_uri(&parser, uri_body)) + return NULL; + + if (log != NULL) { + if (array_count(&parser.uri->recipients) == 0) { + uri_mailto_warning( + &parser, + "notification URI specifies no recipients"); + } + } + return parser.uri; +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.h b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.h new file mode 100644 index 0000000..8e9e057 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/mailto/uri-mailto.h @@ -0,0 +1,49 @@ +#ifndef URI_MAILTO_H +#define URI_MAILTO_H + +/* + * Types + */ + +struct uri_mailto_header_field { + const char *name; + const char *body; +}; + +struct uri_mailto_recipient { + const char *full; + const struct smtp_address *address; + bool carbon_copy; +}; + +ARRAY_DEFINE_TYPE(recipients, struct uri_mailto_recipient); +ARRAY_DEFINE_TYPE(headers, struct uri_mailto_header_field); + +struct uri_mailto_log { + void *context; + + void (*logv)(void *context, enum log_type log_type, + const char *csrc_filename, unsigned int csrc_linenum, + const char *fmt, va_list args) ATTR_FORMAT(5, 0); +}; + +struct uri_mailto { + ARRAY_TYPE(recipients) recipients; + ARRAY_TYPE(headers) headers; + const char *subject; + const char *body; +}; + +bool uri_mailto_validate + (const char *uri_body, const char **reserved_headers, + const char **unique_headers, int max_recipients, int max_headers, + const struct uri_mailto_log *log); + +struct uri_mailto *uri_mailto_parse +(const char *uri_body, pool_t pool, const char **reserved_headers, + const char **unique_headers, int max_recipients, int max_headers, + const struct uri_mailto_log *log); + +#endif + + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h b/pigeonhole/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h new file mode 100644 index 0000000..fd8b574 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h @@ -0,0 +1,197 @@ +#ifndef SIEVE_EXT_ENOTIFY_H +#define SIEVE_EXT_ENOTIFY_H + +#include "lib.h" +#include "compat.h" +#include <stdarg.h> + +#include "sieve-common.h" +#include "sieve-error.h" + +/* + * Forward declarations + */ + +struct sieve_enotify_method; +struct sieve_enotify_env; +struct sieve_enotify_action; +struct sieve_enotify_print_env; +struct sieve_enotify_exec_env; + +/* + * Notify method definition + */ + +struct sieve_enotify_method_def { + const char *identifier; + + /* Registration */ + bool (*load) + (const struct sieve_enotify_method *nmth, void **context); + void (*unload) + (const struct sieve_enotify_method *nmth); + + /* Validation */ + bool (*compile_check_uri) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body); + bool (*compile_check_message) + (const struct sieve_enotify_env *nenv, string_t *message); + bool (*compile_check_from) + (const struct sieve_enotify_env *nenv, string_t *from); + bool (*compile_check_option) + (const struct sieve_enotify_env *nenv, const char *option, + const char *value); + + /* Runtime */ + bool (*runtime_check_uri) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body); + const char *(*runtime_get_method_capability) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body, const char *capability); + bool (*runtime_check_operands) + (const struct sieve_enotify_env *nenv, const char *uri, + const char *uri_body, string_t *message, string_t *from, + pool_t context_pool, void **method_context); + bool (*runtime_set_option) + (const struct sieve_enotify_env *nenv, void *method_context, + const char *option, const char *value); + + /* Action duplicates */ + int (*action_check_duplicates) + (const struct sieve_enotify_env *nenv, + const struct sieve_enotify_action *nact, + const struct sieve_enotify_action *nact_other); + + /* Action print */ + void (*action_print) + (const struct sieve_enotify_print_env *penv, + const struct sieve_enotify_action *nact); + + /* Action execution + (returns 0 if all is ok and -1 for temporary error) + */ + int (*action_execute) + (const struct sieve_enotify_exec_env *nenv, + const struct sieve_enotify_action *nact); +}; + +/* + * Notify method instance + */ + +struct sieve_enotify_method { + const struct sieve_enotify_method_def *def; + int id; + + struct sieve_instance *svinst; + void *context; +}; + +const struct sieve_enotify_method *sieve_enotify_method_register + (struct sieve_instance *svinst, + const struct sieve_enotify_method_def *nmth_def); +void sieve_enotify_method_unregister + (const struct sieve_enotify_method *nmth); + +/* + * Notify method environment + */ + +struct sieve_enotify_env { + struct sieve_instance *svinst; + + const struct sieve_enotify_method *method; + + struct sieve_error_handler *ehandler; + const char *location; + struct event *event; +}; + +/* + * Notify method printing + */ + +void sieve_enotify_method_printf + (const struct sieve_enotify_print_env *penv, const char *fmt, ...) + ATTR_FORMAT(2, 3); + +/* + * Notify execution environment + */ + +struct sieve_enotify_exec_env { + struct sieve_instance *svinst; + enum sieve_execute_flags flags; + + const struct sieve_enotify_method *method; + + const struct sieve_script_env *scriptenv; + const struct sieve_message_data *msgdata; + struct sieve_message_context *msgctx; + + struct sieve_error_handler *ehandler; + const char *location; + struct event *event; +}; + +struct event_passthrough * +sieve_enotify_create_finish_event(const struct sieve_enotify_exec_env *nenv); + +/* + * Notify action + */ + +struct sieve_enotify_action { + const struct sieve_enotify_method *method; + void *method_context; + + sieve_number_t importance; + const char *message; + const char *from; +}; + +/* + * Error handling + */ + +#define sieve_enotify_error(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_ERROR, (ENV)->location, 0, __VA_ARGS__ ) +#define sieve_enotify_warning(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_WARNING, \ + (ENV)->location, 0, __VA_ARGS__ ) +#define sieve_enotify_info(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_INFO, \ + (ENV)->location, 0, __VA_ARGS__ ) +#define sieve_enotify_critical(ENV, ...) \ + sieve_critical((ENV)->svinst, (ENV)->ehandler, NULL, __VA_ARGS__ ) + +#define sieve_enotify_global_error(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_ERROR, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) +#define sieve_enotify_global_warning(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_WARNING, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) +#define sieve_enotify_global_info(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_INFO, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) + +#define sieve_enotify_event_log(ENV, EVENT, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (EVENT), \ + LOG_TYPE_INFO, (ENV)->location, \ + SIEVE_ERROR_FLAG_GLOBAL, __VA_ARGS__ ) + +#define sieve_enotify_global_log_error(ENV, ...) \ + sieve_event_log((ENV)->svinst, (ENV)->ehandler, (ENV)->event, \ + LOG_TYPE_ERROR, (ENV)->location, \ + (SIEVE_ERROR_FLAG_GLOBAL | \ + SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO), __VA_ARGS__ ) +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c b/pigeonhole/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c new file mode 100644 index 0000000..8a6c071 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c @@ -0,0 +1,233 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-enotify-common.h" + +/* + * String test + * + * Syntax: + * notify_method_capability [COMPARATOR] [MATCH-TYPE] + * <notification-uri: string> + * <notification-capability: string> + * <key-list: string-list> + */ + +static bool tst_notifymc_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_notifymc_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_notifymc_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def notify_method_capability_test = { + .identifier = "notify_method_capability", + .type = SCT_TEST, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_notifymc_registered, + .validate = tst_notifymc_validate, + .generate = tst_notifymc_generate +}; + +/* + * String operation + */ + +static bool tst_notifymc_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_notifymc_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def notify_method_capability_operation = { + .mnemonic = "NOTIFY_METHOD_CAPABILITY", + .ext_def = &enotify_extension, + .code = EXT_ENOTIFY_OPERATION_NOTIFY_METHOD_CAPABILITY, + .dump = tst_notifymc_operation_dump, + .execute = tst_notifymc_operation_execute +}; + +/* + * Optional arguments + */ + +enum tst_notifymc_optional { + OPT_END, + OPT_COMPARATOR, + OPT_MATCH_TYPE +}; + +/* + * Test registration + */ + +static bool tst_notifymc_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Test validation + */ + +static bool tst_notifymc_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "notification-uri", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "notification-capability", 2, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key-list", 3, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool tst_notifymc_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit + (cgenv->sblock, cmd->ext, ¬ify_method_capability_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool tst_notifymc_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "NOTIFY_METHOD_CAPABILITY"); + sieve_code_descend(denv); + + /* Handle any optional arguments */ + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_string_dump(denv, address, "notify uri") && + sieve_opr_string_dump(denv, address, "notify capability") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_notifymc_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + string_t *notify_uri, *notify_capability; + struct sieve_stringlist *value_list, *key_list; + const char *cap_value; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; + + /* Read notify uri */ + if ( (ret=sieve_opr_string_read(renv, address, "notify-uri", ¬ify_uri)) + <= 0 ) + return ret; + + /* Read notify capability */ + if ( (ret=sieve_opr_string_read + (renv, address, "notify-capability", ¬ify_capability)) <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "notify_method_capability test"); + + cap_value = ext_enotify_runtime_get_method_capability + (renv, notify_uri, str_c(notify_capability)); + + if ( cap_value != NULL ) { + value_list = sieve_single_stringlist_create_cstr(renv, cap_value, TRUE); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) + < 0 ) + return ret; + } else { + match = 0; + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c b/pigeonhole/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c new file mode 100644 index 0000000..becc41c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-enotify-common.h" + +/* + * Valid_notify_method test + * + * Syntax: + * valid_notify_method <notification-uris: string-list> + */ + +static bool tst_vnotifym_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_vnotifym_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def valid_notify_method_test = { + .identifier = "valid_notify_method", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_vnotifym_validate, + .generate = tst_vnotifym_generate +}; + +/* + * Valid_notify_method operation + */ + +static bool tst_vnotifym_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_vnotifym_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def valid_notify_method_operation = { + .mnemonic = "VALID_NOTIFY_METHOD", + .ext_def = &enotify_extension, + .code = EXT_ENOTIFY_OPERATION_VALID_NOTIFY_METHOD, + .dump = tst_vnotifym_operation_dump, + .execute = tst_vnotifym_operation_execute +}; + +/* + * Test validation + */ + +static bool tst_vnotifym_validate + (struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "notification-uris", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Test generation + */ + +static bool tst_vnotifym_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &valid_notify_method_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool tst_vnotifym_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "VALID_NOTIFY_METHOD"); + sieve_code_descend(denv); + + return + sieve_opr_stringlist_dump(denv, address, "notify-uris"); +} + +/* + * Code execution + */ + +static int tst_vnotifym_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_stringlist *notify_uris; + string_t *uri_item; + bool all_valid = TRUE; + int ret; + + /* + * Read operands + */ + + /* Read notify uris */ + if ( (ret=sieve_opr_stringlist_read + (renv, address, "notify-uris", ¬ify_uris)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "valid_notify_method test"); + + uri_item = NULL; + while ( (ret=sieve_stringlist_next_item(notify_uris, &uri_item)) > 0 ) { + if ( !ext_enotify_runtime_method_validate(renv, uri_item) ) { + all_valid = FALSE; + break; + } + } + + if ( ret < 0 ) { + sieve_runtime_trace_error(renv, "invalid method uri item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + sieve_interpreter_set_test_result(renv->interp, all_valid); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c b/pigeonhole/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c new file mode 100644 index 0000000..801f882 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-code.h" + +#include "sieve-ext-variables.h" + +#include "ext-enotify-common.h" + +/* + * Encodeurl modifier + */ + +static bool +mod_encodeurl_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); + +const struct sieve_variables_modifier_def encodeurl_modifier = { + SIEVE_OBJECT("encodeurl", &encodeurl_operand, 0), + 15, + mod_encodeurl_modify +}; + +/* + * Modifier operand + */ + +static const struct sieve_extension_objects ext_enotify_modifiers = + SIEVE_VARIABLES_DEFINE_MODIFIER(encodeurl_modifier); + +const struct sieve_operand_def encodeurl_operand = { + .name = "modifier", + .ext_def = &enotify_extension, + .class = &sieve_variables_modifier_operand_class, + .interface = &ext_enotify_modifiers +}; + +/* + * Modifier implementation + */ + +static const char _uri_reserved_lookup[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, // 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // 30 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 50 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, // 70 + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // F0 +}; + +static bool +mod_encodeurl_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result) +{ + size_t max_var_size = + sieve_variables_get_max_variable_size(modf->var_ext); + const unsigned char *p, *poff, *pend; + size_t new_size; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + /* allocate new string */ + new_size = str_len(in) + 32; + if (new_size > max_var_size) + new_size = max_var_size; + *result = t_str_new(new_size + 1); + + /* escape string */ + p = str_data(in); + pend = p + str_len(in); + poff = p; + while (p < pend) { + unsigned int i, n = uni_utf8_char_bytes(*p); + + if (n > 1 || (_uri_reserved_lookup[*p] & 0x01) != 0) { + str_append_data(*result, poff, p - poff); + poff = p; + + if (str_len(*result) + 3 * n > max_var_size) + break; + + str_printfa(*result, "%%%02X", *p); + for (i = 1; i < n && p < pend; i++) { + p++; + poff++; + str_printfa(*result, "%%%02X", *p); + } + + poff++; + } else if ((str_len(*result) + (p - poff) + 1) > max_var_size) { + break; + } + p++; + } + + str_append_data(*result, poff, p - poff); + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/environment/Makefile.am b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.am new file mode 100644 index 0000000..916362e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.am @@ -0,0 +1,24 @@ +noinst_LTLIBRARIES = libsieve_ext_environment.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-environment.c + +libsieve_ext_environment_la_SOURCES = \ + $(tests) \ + ext-environment-common.c \ + ext-environment.c + +public_headers = \ + sieve-ext-environment.h + +headers = \ + ext-environment-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) + diff --git a/pigeonhole/src/lib-sieve/plugins/environment/Makefile.in b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.in new file mode 100644 index 0000000..68424f4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/Makefile.in @@ -0,0 +1,753 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/environment +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) \ + $(pkginc_lib_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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_environment_la_LIBADD = +am__objects_1 = tst-environment.lo +am_libsieve_ext_environment_la_OBJECTS = $(am__objects_1) \ + ext-environment-common.lo ext-environment.lo +libsieve_ext_environment_la_OBJECTS = \ + $(am_libsieve_ext_environment_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 = +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)/ext-environment-common.Plo \ + ./$(DEPDIR)/ext-environment.Plo \ + ./$(DEPDIR)/tst-environment.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 = $(libsieve_ext_environment_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_environment_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_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@ +noinst_LTLIBRARIES = libsieve_ext_environment.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-environment.c + +libsieve_ext_environment_la_SOURCES = \ + $(tests) \ + ext-environment-common.c \ + ext-environment.c + +public_headers = \ + sieve-ext-environment.h + +headers = \ + ext-environment-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +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/lib-sieve/plugins/environment/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/environment/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_environment.la: $(libsieve_ext_environment_la_OBJECTS) $(libsieve_ext_environment_la_DEPENDENCIES) $(EXTRA_libsieve_ext_environment_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_environment_la_OBJECTS) $(libsieve_ext_environment_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-environment-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-environment.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-environment.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 +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +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)$(pkginc_libdir)"; 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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-environment-common.Plo + -rm -f ./$(DEPDIR)/ext-environment.Plo + -rm -f ./$(DEPDIR)/tst-environment.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-pkginc_libHEADERS + +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)/ext-environment-common.Plo + -rm -f ./$(DEPDIR)/ext-environment.Plo + -rm -f ./$(DEPDIR)/tst-environment.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-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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-pkginc_libHEADERS 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-pkginc_libHEADERS + +.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/lib-sieve/plugins/environment/ext-environment-common.c b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.c new file mode 100644 index 0000000..28d4251 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.c @@ -0,0 +1,339 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-interpreter.h" + +#include "ext-environment-common.h" + +struct ext_environment_interpreter_context; + +/* + * Core environment items + */ + +static const struct sieve_environment_item *core_env_items[] = { + &domain_env_item, + &host_env_item, + &location_env_item, + &phase_env_item, + &name_env_item, + &version_env_item +}; + +static unsigned int core_env_items_count = N_ELEMENTS(core_env_items); + +static void +sieve_environment_item_insert(struct ext_environment_interpreter_context *ctx, + const struct sieve_environment_item *item); + +/* + * Validator context + */ + +struct ext_environment_interpreter_context { + HASH_TABLE(const char *, + const struct sieve_environment_item *) name_items; + ARRAY(const struct sieve_environment_item *) prefix_items; + + bool active:1; +}; + +static void +ext_environment_interpreter_extension_free(const struct sieve_extension *ext, + struct sieve_interpreter *interp, + void *context); + +struct sieve_interpreter_extension environment_interpreter_extension = { + .ext_def = &environment_extension, + .free = ext_environment_interpreter_extension_free, +}; + +static struct ext_environment_interpreter_context * +ext_environment_interpreter_context_create( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + pool_t pool = sieve_interpreter_pool(interp); + struct ext_environment_interpreter_context *ctx; + + ctx = p_new(pool, struct ext_environment_interpreter_context, 1); + + hash_table_create(&ctx->name_items, default_pool, 0, str_hash, strcmp); + i_array_init(&ctx->prefix_items, 16); + + sieve_interpreter_extension_register(interp, this_ext, + &environment_interpreter_extension, + (void *)ctx); + return ctx; +} + +static void +ext_environment_interpreter_extension_free( + const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, void *context) +{ + struct ext_environment_interpreter_context *ctx = + (struct ext_environment_interpreter_context *)context; + + hash_table_destroy(&ctx->name_items); + array_free(&ctx->prefix_items); +} + +static struct ext_environment_interpreter_context * +ext_environment_interpreter_context_get(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx = + (struct ext_environment_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); + + if (ctx == NULL) { + ctx = ext_environment_interpreter_context_create( + this_ext, interp); + } + return ctx; +} + +void ext_environment_interpreter_init(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx; + unsigned int i; + + /* Create our context */ + ctx = ext_environment_interpreter_context_get(this_ext, interp); + + for (i = 0; i < core_env_items_count; i++) + sieve_environment_item_insert(ctx, core_env_items[i]); + + ctx->active = TRUE; +} + +bool sieve_ext_environment_is_active(const struct sieve_extension *env_ext, + struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx = + ext_environment_interpreter_context_get(env_ext, interp); + + return (ctx != NULL && ctx->active); +} + +/* + * Registration + */ + +static void +sieve_environment_item_insert(struct ext_environment_interpreter_context *ctx, + const struct sieve_environment_item *item) +{ + if (!item->prefix) + hash_table_insert(ctx->name_items, item->name, item); + else + array_append(&ctx->prefix_items, &item, 1); +} + +void sieve_environment_item_register(const struct sieve_extension *env_ext, + struct sieve_interpreter *interp, + const struct sieve_environment_item *item) +{ + struct ext_environment_interpreter_context *ctx; + + i_assert(sieve_extension_is(env_ext, environment_extension)); + ctx = ext_environment_interpreter_context_get(env_ext, interp); + + sieve_environment_item_insert(ctx, item); +} + +/* + * Retrieval + */ + +static const struct sieve_environment_item * +ext_environment_item_lookup(struct ext_environment_interpreter_context *ctx, + const char **_name) +{ + const struct sieve_environment_item *item; + const char *name = *_name; + + item = hash_table_lookup(ctx->name_items, name); + if (item != NULL) + return item; + + array_foreach_elem(&ctx->prefix_items, item) { + size_t prefix_len; + + i_assert(item->prefix); + prefix_len = strlen(item->name); + + if (str_begins(name, item->name)) { + if (name[prefix_len] == '.') { + *_name = &name[prefix_len+1]; + return item; + } else if (name[prefix_len] == '\0') { + *_name = &name[prefix_len+1]; + return item; + } + } + } + return NULL; +} + +const char * +ext_environment_item_get_value(const struct sieve_extension *env_ext, + const struct sieve_runtime_env *renv, + const char *name) +{ + struct ext_environment_interpreter_context *ctx; + const struct sieve_environment_item *item; + + i_assert(sieve_extension_is(env_ext, environment_extension)); + ctx = ext_environment_interpreter_context_get(env_ext, renv->interp); + + item = ext_environment_item_lookup(ctx, &name); + if (item == NULL) + return NULL; + + if (item->value != NULL) + return item->value; + if (item->get_value != NULL) + return item->get_value(renv, name); + return NULL; +} + +/* + * Default environment items + */ + +/* "domain": + + The primary DNS domain associated with the Sieve execution context, usually + but not always a proper suffix of the host name. + */ + +static const char * +envit_domain_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->domainname; +} + +const struct sieve_environment_item domain_env_item = { + .name = "domain", + .get_value = envit_domain_get_value, +}; + +/* "host": + + The fully-qualified domain name of the host where the Sieve script is + executing. + */ + +static const char * +envit_host_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->hostname; +} + +const struct sieve_environment_item host_env_item = { + .name = "host", + .get_value = envit_host_get_value, +}; + +/* "location": + + Sieve evaluation can be performed at various different points as messages + are processed. This item provides additional information about the type of + service that is evaluating the script. Possible values are: + "MTA" - the Sieve script is being evaluated by a Message Transfer Agent + "MDA" - evaluation is being performed by a Mail Delivery Agent + "MUA" - evaluation is being performed by a Mail User Agent (right...) + "MS" - evaluation is being performed by a Message Store + */ + +static const char * +envit_location_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + switch (eenv->svinst->env_location ) { + case SIEVE_ENV_LOCATION_MDA: + return "MDA"; + case SIEVE_ENV_LOCATION_MTA: + return "MTA"; + case SIEVE_ENV_LOCATION_MS: + return "MS"; + default: + break; + } + return NULL; +} + +const struct sieve_environment_item location_env_item = { + .name = "location", + .get_value = envit_location_get_value +}; + +/* "phase": + + The point relative to final delivery where the Sieve script is being + evaluated. Possible values are "pre", "during", and "post", referring + respectively to processing before, during, and after final delivery has + taken place. + */ + +static const char * +envit_phase_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + switch (eenv->svinst->delivery_phase) { + case SIEVE_DELIVERY_PHASE_PRE: + return "pre"; + case SIEVE_DELIVERY_PHASE_DURING: + return "during"; + case SIEVE_DELIVERY_PHASE_POST: + return "post"; + default: + break; + } + return NULL; +} + +const struct sieve_environment_item phase_env_item = { + .name = "phase", + .get_value = envit_phase_get_value +}; + +/* "name": + + The product name associated with the Sieve interpreter. + */ + +const struct sieve_environment_item name_env_item = { + .name = "name", + .value = PIGEONHOLE_NAME" Sieve" +}; + +/* "version": + + The product version associated with the Sieve interpreter. The meaning of the + product version string is product-specific and should always be considered + in the context of the product name given by the "name" item. + */ + +const struct sieve_environment_item version_env_item = { + .name = "version", + .value = PIGEONHOLE_VERSION, +}; diff --git a/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.h b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.h new file mode 100644 index 0000000..288b82e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment-common.h @@ -0,0 +1,53 @@ +#ifndef EXT_ENVIRONMENT_COMMON_H +#define EXT_ENVIRONMENT_COMMON_H + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-ext-environment.h" + +/* + * Extension + */ + +extern const struct sieve_extension_def environment_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def tst_environment; + +/* + * Operations + */ + +extern const struct sieve_operation_def tst_environment_operation; + +/* + * Environment items + */ + +extern const struct sieve_environment_item domain_env_item; +extern const struct sieve_environment_item host_env_item; +extern const struct sieve_environment_item location_env_item; +extern const struct sieve_environment_item phase_env_item; +extern const struct sieve_environment_item name_env_item; +extern const struct sieve_environment_item version_env_item; + +/* + * Initialization + */ + +bool ext_environment_init(const struct sieve_extension *ext, void **context); +void ext_environment_deinit(const struct sieve_extension *ext); + +/* + * Validator context + */ + +void ext_environment_interpreter_init(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/environment/ext-environment.c b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment.c new file mode 100644 index 0000000..c2130a2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/ext-environment.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension variables + * ------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5183 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" + +#include "sieve-validator.h" + +#include "ext-environment-common.h" + +/* + * Extension + */ + +static bool ext_environment_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_environment_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_extension_def environment_extension = { + .name = "environment", + .validator_load = ext_environment_validator_load, + .interpreter_load = ext_environment_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(tst_environment_operation) +}; + +static bool ext_environment_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &tst_environment); + return TRUE; +} + +static bool ext_environment_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_environment_interpreter_init(ext, renv->interp); + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/environment/sieve-ext-environment.h b/pigeonhole/src/lib-sieve/plugins/environment/sieve-ext-environment.h new file mode 100644 index 0000000..8ae0d18 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/sieve-ext-environment.h @@ -0,0 +1,54 @@ +#ifndef SIEVE_EXT_ENVIRONMENT_H +#define SIEVE_EXT_ENVIRONMENT_H + +#include "sieve-common.h" + +/* + * Environment extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def environment_extension; + +static inline const struct sieve_extension * +sieve_ext_environment_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_register + (svinst, &environment_extension, FALSE); +} + +static inline const struct sieve_extension * +sieve_ext_environment_require_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_require + (svinst, &environment_extension, TRUE); +} + +bool sieve_ext_environment_is_active + (const struct sieve_extension *env_ext, + struct sieve_interpreter *interp); + +/* + * Environment item + */ + +struct sieve_environment_item { + const char *name; + bool prefix; + + const char *value; + const char *(*get_value) + (const struct sieve_runtime_env *renv, const char *name); +}; + +void sieve_environment_item_register + (const struct sieve_extension *env_ext, struct sieve_interpreter *interp, + const struct sieve_environment_item *item); +const char *ext_environment_item_get_value + (const struct sieve_extension *env_ext, + const struct sieve_runtime_env *renv, const char *name); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c b/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c new file mode 100644 index 0000000..9eaa099 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/environment/tst-environment.c @@ -0,0 +1,215 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-environment-common.h" + +/* + * Environment test + * + * Syntax: + * environment [COMPARATOR] [MATCH-TYPE] + * <name: string> <key-list: string-list> + */ + +static bool tst_environment_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_environment_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_environment_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_environment = { + .identifier = "environment", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_environment_registered, + .validate = tst_environment_validate, + .generate = tst_environment_generate +}; + +/* + * Environment operation + */ + +static bool tst_environment_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_environment_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_environment_operation = { + .mnemonic = "ENVIRONMENT", + .ext_def = &environment_extension, + .dump = tst_environment_operation_dump, + .execute = tst_environment_operation_execute +}; + +/* + * Test registration + */ + +static bool tst_environment_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Test validation + */ + +static bool tst_environment_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "name", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool tst_environment_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_environment_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool tst_environment_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "ENVIRONMENT"); + sieve_code_descend(denv); + + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_string_dump(denv, address, "name") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_environment_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + string_t *name; + struct sieve_stringlist *value_list, *key_list; + const char *env_item; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; + + /* Read source */ + if ( (ret=sieve_opr_string_read(renv, address, "name", &name)) <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "environment test"); + + env_item = ext_environment_item_get_value + (this_ext, renv, str_c(name)); + + if ( env_item != NULL ) { + /* Construct value list */ + value_list = sieve_single_stringlist_create_cstr(renv, env_item, FALSE); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) + < 0 ) + return ret; + } else { + match = 0; + + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "environment item `%s' not found", + str_sanitize(str_c(name), 128)); + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.am b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.am new file mode 100644 index 0000000..1eb0472 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.am @@ -0,0 +1,22 @@ +noinst_LTLIBRARIES = libsieve_ext_ihave.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-ihave.c + +commands = \ + cmd-error.c + +libsieve_ext_ihave_la_SOURCES = \ + $(tests) \ + $(commands) \ + ext-ihave-binary.c \ + ext-ihave-common.c \ + ext-ihave.c + +noinst_HEADERS = \ + ext-ihave-binary.h \ + ext-ihave-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.in b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.in new file mode 100644 index 0000000..c5b8952 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/Makefile.in @@ -0,0 +1,707 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/ihave +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_ihave_la_LIBADD = +am__objects_1 = tst-ihave.lo +am__objects_2 = cmd-error.lo +am_libsieve_ext_ihave_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + ext-ihave-binary.lo ext-ihave-common.lo ext-ihave.lo +libsieve_ext_ihave_la_OBJECTS = $(am_libsieve_ext_ihave_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 = +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)/cmd-error.Plo \ + ./$(DEPDIR)/ext-ihave-binary.Plo \ + ./$(DEPDIR)/ext-ihave-common.Plo ./$(DEPDIR)/ext-ihave.Plo \ + ./$(DEPDIR)/tst-ihave.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 = $(libsieve_ext_ihave_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_ihave_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@ +noinst_LTLIBRARIES = libsieve_ext_ihave.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-ihave.c + +commands = \ + cmd-error.c + +libsieve_ext_ihave_la_SOURCES = \ + $(tests) \ + $(commands) \ + ext-ihave-binary.c \ + ext-ihave-common.c \ + ext-ihave.c + +noinst_HEADERS = \ + ext-ihave-binary.h \ + ext-ihave-common.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/lib-sieve/plugins/ihave/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/ihave/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_ihave.la: $(libsieve_ext_ihave_la_OBJECTS) $(libsieve_ext_ihave_la_DEPENDENCIES) $(EXTRA_libsieve_ext_ihave_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_ihave_la_OBJECTS) $(libsieve_ext_ihave_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-error.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-ihave-binary.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-ihave-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-ihave.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-ihave.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-error.Plo + -rm -f ./$(DEPDIR)/ext-ihave-binary.Plo + -rm -f ./$(DEPDIR)/ext-ihave-common.Plo + -rm -f ./$(DEPDIR)/ext-ihave.Plo + -rm -f ./$(DEPDIR)/tst-ihave.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-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)/cmd-error.Plo + -rm -f ./$(DEPDIR)/ext-ihave-binary.Plo + -rm -f ./$(DEPDIR)/ext-ihave-common.Plo + -rm -f ./$(DEPDIR)/ext-ihave.Plo + -rm -f ./$(DEPDIR)/tst-ihave.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/ihave/cmd-error.c b/pigeonhole/src/lib-sieve/plugins/ihave/cmd-error.c new file mode 100644 index 0000000..6e971bd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/cmd-error.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-ihave-common.h" + +/* + * Error command + * + * Syntax + * error <message: string> + */ + +static bool cmd_error_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool cmd_error_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def error_command = { + .identifier = "error", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_error_validate, + .generate = cmd_error_generate +}; + +/* + * Body operation + */ + +static bool cmd_error_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_error_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def cmd_error_operation = { + .mnemonic = "ERROR", + .ext_def = &ihave_extension, + .code = EXT_IHAVE_OPERATION_ERROR, + .dump = cmd_error_operation_dump, + .execute = cmd_error_operation_execute +}; + +/* + * Validation + */ + +static bool cmd_error_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "message", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_error_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &cmd_error_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_error_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "ERROR"); + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "message"); +} + +/* + * Interpretation + */ + +static int cmd_error_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + string_t *message; + int ret; + + /* + * Read operands + */ + + /* Read message */ + + if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "error \"%s\"", + str_sanitize(str_c(message), 80)); + + sieve_runtime_error(renv, NULL, "%s", str_c(message)); + + return SIEVE_EXEC_FAILURE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.c b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.c new file mode 100644 index 0000000..01b375e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.c @@ -0,0 +1,249 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-ihave-common.h" +#include "ext-ihave-binary.h" + +/* + * Forward declarations + */ + +static bool ext_ihave_binary_pre_save + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_error *error_r); +static bool ext_ihave_binary_open + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context); +static bool ext_ihave_binary_up_to_date + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_compile_flags cpflags); + +/* + * Binary include extension + */ + +const struct sieve_binary_extension ihave_binary_ext = { + .extension = &ihave_extension, + .binary_pre_save = ext_ihave_binary_pre_save, + .binary_open = ext_ihave_binary_open, + .binary_up_to_date = ext_ihave_binary_up_to_date +}; + +/* + * Binary context management + */ + +struct ext_ihave_binary_context { + struct sieve_binary *binary; + struct sieve_binary_block *block; + + ARRAY(const char *) missing_extensions; +}; + +static struct ext_ihave_binary_context *ext_ihave_binary_create_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + pool_t pool = sieve_binary_pool(sbin); + + struct ext_ihave_binary_context *ctx = + p_new(pool, struct ext_ihave_binary_context, 1); + + ctx->binary = sbin; + p_array_init(&ctx->missing_extensions, pool, 64); + + sieve_binary_extension_set(sbin, this_ext, &ihave_binary_ext, ctx); + return ctx; +} + +struct ext_ihave_binary_context *ext_ihave_binary_get_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + struct ext_ihave_binary_context *ctx = (struct ext_ihave_binary_context *) + sieve_binary_extension_get_context(sbin, this_ext); + + if ( ctx == NULL ) + ctx = ext_ihave_binary_create_context(this_ext, sbin); + + return ctx; +} + +struct ext_ihave_binary_context *ext_ihave_binary_init +(const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast) +{ + struct ext_ihave_ast_context *ast_ctx = + ext_ihave_get_ast_context(this_ext, ast); + struct ext_ihave_binary_context *binctx; + const char *const *exts; + unsigned int i, count; + + binctx = ext_ihave_binary_get_context(this_ext, sbin); + + exts = array_get(&ast_ctx->missing_extensions, &count); + + if ( count > 0 ) { + pool_t pool = sieve_binary_pool(sbin); + + if ( binctx->block == NULL ) + binctx->block = sieve_binary_extension_create_block(sbin, this_ext); + + for ( i = 0; i < count; i++ ) { + const char *ext_name = p_strdup(pool, exts[i]); + + array_append(&binctx->missing_extensions, &ext_name, 1); + } + } + + return binctx; +} + +/* + * Binary extension + */ + +static bool ext_ihave_binary_pre_save +(const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_error *error_r ATTR_UNUSED) +{ + struct ext_ihave_binary_context *binctx = + (struct ext_ihave_binary_context *) context; + const char *const *exts; + unsigned int count, i; + + exts = array_get(&binctx->missing_extensions, &count); + + if ( binctx->block != NULL ) + sieve_binary_block_clear(binctx->block); + + if ( count > 0 ) { + if ( binctx->block == NULL ) + binctx->block = sieve_binary_extension_create_block(sbin, ext); + + sieve_binary_emit_unsigned(binctx->block, count); + + for ( i = 0; i < count; i++ ) { + sieve_binary_emit_cstring(binctx->block, exts[i]); + } + } + + return TRUE; +} + +static bool ext_ihave_binary_open +(const struct sieve_extension *ext, struct sieve_binary *sbin, void *context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_ihave_binary_context *binctx = + (struct ext_ihave_binary_context *) context; + struct sieve_binary_block *sblock; + unsigned int i, count, block_id; + sieve_size_t offset; + + sblock = sieve_binary_extension_get_block(sbin, ext); + + if ( sblock != NULL ) { + binctx->block = sblock; + block_id = sieve_binary_block_get_id(sblock); + + offset = 0; + + /* Read number of missing extensions to read subsequently */ + if ( !sieve_binary_read_unsigned(sblock, &offset, &count) ) { + e_error(svinst->event, "ihave: " + "failed to read missing extension count " + "from block %d of binary %s", + block_id, sieve_binary_path(sbin)); + return FALSE; + } + + /* Read dependencies */ + for ( i = 0; i < count; i++ ) { + string_t *ext_name; + const char *name; + + if ( !sieve_binary_read_string(sblock, &offset, &ext_name) ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, "ihave: " + "failed to read missing extension name " + "from block %d of binary %s", + block_id, sieve_binary_path(sbin)); + return FALSE; + } + + name = str_c(ext_name); + array_append(&binctx->missing_extensions, &name, 1); + } + } + + return TRUE; +} + +static bool ext_ihave_binary_up_to_date +(const struct sieve_extension *ext, struct sieve_binary *sbin ATTR_UNUSED, + void *context, enum sieve_compile_flags cpflags) +{ + struct ext_ihave_binary_context *binctx = + (struct ext_ihave_binary_context *) context; + const struct sieve_extension *mext; + const char *const *mexts; + unsigned int count, i; + + mexts = array_get(&binctx->missing_extensions, &count); + for ( i = 0; i < count; i++ ) { + if ( (mext=sieve_extension_get_by_name(ext->svinst, mexts[i])) != NULL && + ((cpflags & SIEVE_COMPILE_FLAG_NOGLOBAL) == 0 || !mext->global) ) + return FALSE; + } + + return TRUE; +} + +/* + * Main extension interface + */ + +bool ext_ihave_binary_load +(const struct sieve_extension *ext, struct sieve_binary *sbin) +{ + (void)ext_ihave_binary_get_context(ext, sbin); + + return TRUE; +} + +bool ext_ihave_binary_dump +(const struct sieve_extension *ext, struct sieve_dumptime_env *denv) +{ + struct sieve_binary *sbin = denv->sbin; + struct ext_ihave_binary_context *binctx = + ext_ihave_binary_get_context(ext, sbin); + const char *const *exts; + unsigned int count, i; + + exts = array_get(&binctx->missing_extensions, &count); + + if ( count > 0 ) { + sieve_binary_dump_sectionf(denv, + "Extensions missing at compile (block: %d)", + sieve_binary_block_get_id(binctx->block)); + + for ( i = 0; i < count; i++ ) { + sieve_binary_dumpf(denv, " - %s\n", exts[i]); + } + } + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.h b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.h new file mode 100644 index 0000000..418f078 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-binary.h @@ -0,0 +1,33 @@ +#ifndef EXT_IHAVE_BINARY_H +#define EXT_IHAVE_BINARY_H + +/* + * Binary context management + */ + +struct ext_ihave_binary_context; + +struct ext_ihave_binary_context *ext_ihave_binary_get_context + (const struct sieve_extension *this_ext, struct sieve_binary *sbin); +struct ext_ihave_binary_context *ext_ihave_binary_init + (const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast); + +/* + * Registering missing extension + */ + +void ext_ihave_binary_add_missing_extension + (struct ext_ihave_binary_context *binctx, const char *ext_name); + +/* + * Main extension interface + */ + +bool ext_ihave_binary_load + (const struct sieve_extension *ext, struct sieve_binary *sbin); +bool ext_ihave_binary_dump + (const struct sieve_extension *ext, struct sieve_dumptime_env *denv); + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.c b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.c new file mode 100644 index 0000000..1d31238 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" + +#include "ext-ihave-common.h" + +/* + * AST context management + */ + +struct ext_ihave_ast_context *ext_ihave_get_ast_context +(const struct sieve_extension *this_ext, struct sieve_ast *ast) +{ + struct ext_ihave_ast_context *actx = (struct ext_ihave_ast_context *) + sieve_ast_extension_get_context(ast, this_ext); + pool_t pool; + + if ( actx != NULL ) + return actx; + + pool = sieve_ast_pool(ast); + actx = p_new(pool, struct ext_ihave_ast_context, 1); + p_array_init(&actx->missing_extensions, pool, 64); + + sieve_ast_extension_set_context(ast, this_ext, (void *) actx); + + return actx; +} + +void ext_ihave_ast_add_missing_extension +(const struct sieve_extension *this_ext, struct sieve_ast *ast, + const char *ext_name) +{ + struct ext_ihave_ast_context *actx = + ext_ihave_get_ast_context(this_ext, ast); + const char *const *exts; + unsigned int i, count; + + exts = array_get(&actx->missing_extensions, &count); + for ( i = 0; i < count; i++ ) { + if ( strcmp(exts[i], ext_name) == 0 ) + return; + } + + array_append(&actx->missing_extensions, &ext_name, 1); +} + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.h b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.h new file mode 100644 index 0000000..371d03d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave-common.h @@ -0,0 +1,52 @@ +#ifndef EXT_IHAVE_COMMON_H +#define EXT_IHAVE_COMMON_H + +#include "sieve-common.h" + +/* + * Extensions + */ + +extern const struct sieve_extension_def ihave_extension; + +/* + * Tests + */ + +extern const struct sieve_command_def ihave_test; + +/* + * Commands + */ + +extern const struct sieve_command_def error_command; + +/* + * Operations + */ + +enum ext_ihave_opcode { + EXT_IHAVE_OPERATION_IHAVE, + EXT_IHAVE_OPERATION_ERROR +}; + +extern const struct sieve_operation_def tst_ihave_operation; +extern const struct sieve_operation_def cmd_error_operation; + +/* + * AST context + */ + +struct ext_ihave_ast_context { + ARRAY(const char *) missing_extensions; +}; + +struct ext_ihave_ast_context *ext_ihave_get_ast_context + (const struct sieve_extension *this_ext, struct sieve_ast *ast); + +void ext_ihave_ast_add_missing_extension + (const struct sieve_extension *this_ext, struct sieve_ast *ast, + const char *ext_name); + + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave.c b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave.c new file mode 100644 index 0000000..40b70eb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/ext-ihave.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension ihave + * --------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5463 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +#include "ext-ihave-common.h" +#include "ext-ihave-binary.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_ihave_operations[] = { + &tst_ihave_operation, + &cmd_error_operation +}; + +/* + * Extension + */ + +static bool ext_ihave_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); +static bool ext_ihave_generator_load + (const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv); + +const struct sieve_extension_def ihave_extension = { + "ihave", + .version = 1, + .validator_load = ext_ihave_validator_load, + .generator_load = ext_ihave_generator_load, + .binary_load = ext_ihave_binary_load, + .binary_dump = ext_ihave_binary_dump, + SIEVE_EXT_DEFINE_OPERATIONS(ext_ihave_operations) +}; + +static bool ext_ihave_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_validator_register_command(validator, ext, &ihave_test); + sieve_validator_register_command(validator, ext, &error_command); + + return TRUE; +} + +static bool ext_ihave_generator_load +(const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv) +{ + (void)ext_ihave_binary_init(ext, cgenv->sbin, cgenv->ast); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/ihave/tst-ihave.c b/pigeonhole/src/lib-sieve/plugins/ihave/tst-ihave.c new file mode 100644 index 0000000..c6c8e8f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/ihave/tst-ihave.c @@ -0,0 +1,294 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-ihave-common.h" + +/* + * Ihave test + * + * Syntax: + * ihave <capabilities: string-list> + */ + +static bool +tst_ihave_validate(struct sieve_validator *valdtr, struct sieve_command *tst); +static bool +tst_ihave_validate_const(struct sieve_validator *valdtr, + struct sieve_command *tst, int *const_current, + int const_next); +static bool +tst_ihave_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst); + +const struct sieve_command_def ihave_test = { + .identifier = "ihave", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_ihave_validate, + .validate_const = tst_ihave_validate_const, + .generate = tst_ihave_generate +}; + +/* + * Ihave operation + */ + +static bool +tst_ihave_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_ihave_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def tst_ihave_operation = { + .mnemonic = "IHAVE", + .ext_def = &ihave_extension, + .code = EXT_IHAVE_OPERATION_IHAVE, + .dump = tst_ihave_operation_dump, + .execute = tst_ihave_operation_execute +}; + +/* + * Code validation + */ + +static bool +tst_ihave_validate(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct _capability { + const struct sieve_extension *ext; + struct sieve_ast_argument *arg; + }; + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *stritem; + enum sieve_compile_flags cpflags = + sieve_validator_compile_flags(valdtr); + bool no_global = ((cpflags & SIEVE_COMPILE_FLAG_NOGLOBAL) != 0); + ARRAY(struct _capability) capabilities; + struct _capability capability; + const struct _capability *caps; + unsigned int i, count; + bool all_known = TRUE; + + t_array_init(&capabilities, 64); + + tst->data = (void *)FALSE; + + /* Check stringlist argument */ + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "capabilities", 1, + SAAT_STRING_LIST)) + return FALSE; + + switch (sieve_ast_argument_type(arg)) { + case SAAT_STRING: + /* Single string */ + capability.arg = arg; + capability.ext = sieve_extension_get_by_name( + tst->ext->svinst, sieve_ast_argument_strc(arg)); + + if (capability.ext == NULL || + (no_global && capability.ext->global)) { + all_known = FALSE; + + ext_ihave_ast_add_missing_extension( + tst->ext, tst->ast_node->ast, + sieve_ast_argument_strc(arg)); + } else { + array_append(&capabilities, &capability, 1); + } + + break; + + case SAAT_STRING_LIST: + /* String list */ + stritem = sieve_ast_strlist_first(arg); + + while (stritem != NULL) { + capability.arg = stritem; + capability.ext = sieve_extension_get_by_name( + tst->ext->svinst, + sieve_ast_argument_strc(stritem)); + + if (capability.ext == NULL || + (no_global && capability.ext->global)) { + all_known = FALSE; + + ext_ihave_ast_add_missing_extension( + tst->ext, tst->ast_node->ast, + sieve_ast_argument_strc(stritem)); + } else { + array_append(&capabilities, &capability, 1); + } + stritem = sieve_ast_strlist_next(stritem); + } + + break; + default: + i_unreached(); + } + + if (!all_known) + return TRUE; + + /* RFC 5463, Section 4, page 4: + + The "ihave" extension is designed to be used with other extensions + that add tests, actions, comparators, or arguments. Implementations + MUST NOT allow it to be used with extensions that change the + underlying Sieve grammar, or extensions like encoded-character + [RFC5228], or variables [RFC5229] that change how the content of + Sieve scripts are interpreted. The test MUST fail and the extension + MUST NOT be enabled if such usage is attempted. + + FIXME: current implementation of this restriction is hardcoded and + therefore highly inflexible + */ + caps = array_get(&capabilities, &count); + for (i = 0; i < count; i++) { + if (sieve_extension_name_is(caps[i].ext, "variables") || + sieve_extension_name_is(caps[i].ext, "encoded-character")) + return TRUE; + } + + /* Load all extensions */ + caps = array_get(&capabilities, &count); + for (i = 0; i < count; i++) { + if (!sieve_validator_extension_load(valdtr, tst, caps[i].arg, + caps[i].ext, FALSE)) + return FALSE; + } + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + tst->data = (void *)TRUE; + return TRUE; +} + +static bool +tst_ihave_validate_const(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *tst, int *const_current, + int const_next ATTR_UNUSED) +{ + if ((bool)tst->data == TRUE) + *const_current = -1; + else + *const_current = 0; + return TRUE; +} + +/* + * Code generation + */ + +bool tst_ihave_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + /* Emit opcode */ + sieve_operation_emit(cgenv->sblock, tst->ext, &tst_ihave_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool +tst_ihave_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "IHAVE"); + sieve_code_descend(denv); + + return sieve_opr_stringlist_dump(denv, address, "capabilities"); +} + +/* + * Code execution + */ + +static int +tst_ihave_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct sieve_stringlist *capabilities; + string_t *cap_item; + bool matched; + int ret; + + /* + * Read operands + */ + + /* Read capabilities */ + if ((ret = sieve_opr_stringlist_read(renv, address, "capabilities", + &capabilities)) <= 0) + return ret; + + /* + * Perform test + */ + + /* Perform the test */ + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "ihave test"); + sieve_runtime_trace_descend(renv); + + cap_item = NULL; + matched = TRUE; + while (matched && + (ret = sieve_stringlist_next_item(capabilities, + &cap_item)) > 0) { + const struct sieve_extension *ext; + int sret; + + ext = sieve_extension_get_by_name(svinst, str_c(cap_item)); + if (ext == NULL) { + sieve_runtime_trace_error( + renv, "ihave: invalid extension name"); + return SIEVE_EXEC_BIN_CORRUPT; + } + sret = sieve_interpreter_extension_start(renv->interp, ext); + if (sret == SIEVE_EXEC_FAILURE) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "extension `%s' not available", + sieve_extension_name(ext)); + matched = FALSE; + } else if (sret == SIEVE_EXEC_OK) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "extension `%s' available", + sieve_extension_name(ext)); + } else { + return sret; + } + } + if (ret < 0) { + sieve_runtime_trace_error(renv, "invalid capabilities item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, matched); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.am b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.am new file mode 100644 index 0000000..e5390d4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.am @@ -0,0 +1,33 @@ +noinst_LTLIBRARIES = libsieve_ext_imap4flags.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-flag.c + +tests = \ + tst-hasflag.c + +tags = \ + tag-flags.c + +libsieve_ext_imap4flags_la_SOURCES = \ + ext-imap4flags-common.c \ + $(commands) \ + $(tests) \ + $(tags) \ + ext-imap4flags.c \ + ext-imapflags.c + +public_headers = \ + sieve-ext-imap4flags.h + +headers = \ + ext-imap4flags-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.in b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.in new file mode 100644 index 0000000..77f2dc3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/Makefile.in @@ -0,0 +1,776 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/imap4flags +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) \ + $(pkginc_lib_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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_imap4flags_la_LIBADD = +am__objects_1 = cmd-flag.lo +am__objects_2 = tst-hasflag.lo +am__objects_3 = tag-flags.lo +am_libsieve_ext_imap4flags_la_OBJECTS = ext-imap4flags-common.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + ext-imap4flags.lo ext-imapflags.lo +libsieve_ext_imap4flags_la_OBJECTS = \ + $(am_libsieve_ext_imap4flags_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 = +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)/cmd-flag.Plo \ + ./$(DEPDIR)/ext-imap4flags-common.Plo \ + ./$(DEPDIR)/ext-imap4flags.Plo ./$(DEPDIR)/ext-imapflags.Plo \ + ./$(DEPDIR)/tag-flags.Plo ./$(DEPDIR)/tst-hasflag.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 = $(libsieve_ext_imap4flags_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_imap4flags_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_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@ +noinst_LTLIBRARIES = libsieve_ext_imap4flags.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-flag.c + +tests = \ + tst-hasflag.c + +tags = \ + tag-flags.c + +libsieve_ext_imap4flags_la_SOURCES = \ + ext-imap4flags-common.c \ + $(commands) \ + $(tests) \ + $(tags) \ + ext-imap4flags.c \ + ext-imapflags.c + +public_headers = \ + sieve-ext-imap4flags.h + +headers = \ + ext-imap4flags-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +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/lib-sieve/plugins/imap4flags/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/imap4flags/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_imap4flags.la: $(libsieve_ext_imap4flags_la_OBJECTS) $(libsieve_ext_imap4flags_la_DEPENDENCIES) $(EXTRA_libsieve_ext_imap4flags_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_imap4flags_la_OBJECTS) $(libsieve_ext_imap4flags_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-flag.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imap4flags-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imap4flags.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-imapflags.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-flags.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-hasflag.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 +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +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)$(pkginc_libdir)"; 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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-flag.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags-common.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags.Plo + -rm -f ./$(DEPDIR)/ext-imapflags.Plo + -rm -f ./$(DEPDIR)/tag-flags.Plo + -rm -f ./$(DEPDIR)/tst-hasflag.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-pkginc_libHEADERS + +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)/cmd-flag.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags-common.Plo + -rm -f ./$(DEPDIR)/ext-imap4flags.Plo + -rm -f ./$(DEPDIR)/ext-imapflags.Plo + -rm -f ./$(DEPDIR)/tag-flags.Plo + -rm -f ./$(DEPDIR)/tst-hasflag.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-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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-pkginc_libHEADERS 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-pkginc_libHEADERS + +.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/lib-sieve/plugins/imap4flags/cmd-flag.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/cmd-flag.c new file mode 100644 index 0000000..2645669 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -0,0 +1,251 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-stringlist.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-imap4flags-common.h" + +/* + * Commands + */ + +/* Forward declarations */ + +static bool cmd_flag_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +/* Setflag command + * + * Syntax: + * setflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command_def cmd_setflag = { + .identifier = "setflag", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = ext_imap4flags_command_validate, + .generate = cmd_flag_generate +}; + +/* Addflag command + * + * Syntax: + * addflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command_def cmd_addflag = { + .identifier = "addflag", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = ext_imap4flags_command_validate, + .generate = cmd_flag_generate +}; + + +/* Removeflag command + * + * Syntax: + * removeflag [<variablename: string>] <list-of-flags: string-list> + */ + +const struct sieve_command_def cmd_removeflag = { + .identifier = "removeflag", + .type = SCT_COMMAND, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = ext_imap4flags_command_validate, + .generate = cmd_flag_generate +}; + +/* + * Operations + */ + +/* Forward declarations */ + +bool cmd_flag_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_flag_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Setflag operation */ + +const struct sieve_operation_def setflag_operation = { + .mnemonic = "SETFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_SETFLAG, + .dump = cmd_flag_operation_dump, + .execute = cmd_flag_operation_execute +}; + +/* Addflag operation */ + +const struct sieve_operation_def addflag_operation = { + .mnemonic = "ADDFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_ADDFLAG, + .dump = cmd_flag_operation_dump, + .execute = cmd_flag_operation_execute +}; + +/* Removeflag operation */ + +const struct sieve_operation_def removeflag_operation = { + .mnemonic = "REMOVEFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_REMOVEFLAG, + .dump = cmd_flag_operation_dump, + .execute = cmd_flag_operation_execute +}; + +/* + * Code generation + */ + +static bool cmd_flag_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg1, *arg2; + + /* Emit operation */ + if ( sieve_command_is(cmd, cmd_setflag) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &setflag_operation); + else if ( sieve_command_is(cmd, cmd_addflag) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &addflag_operation); + else if ( sieve_command_is(cmd, cmd_removeflag) ) + sieve_operation_emit(cgenv->sblock, cmd->ext, &removeflag_operation); + + arg1 = cmd->first_positional; + arg2 = sieve_ast_argument_next(arg1); + + if ( arg2 == NULL ) { + /* No variable */ + sieve_opr_omitted_emit(cgenv->sblock); + if ( !sieve_generate_argument(cgenv, arg1, cmd) ) + return FALSE; + } else { + /* Full command */ + if ( !sieve_generate_argument(cgenv, arg1, cmd) ) + return FALSE; + if ( !sieve_generate_argument(cgenv, arg2, cmd) ) + return FALSE; + } + return TRUE; +} + +/* + * Code dump + */ + +bool cmd_flag_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct sieve_operand oprnd; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); + sieve_code_descend(denv); + + sieve_code_mark(denv); + if ( !sieve_operand_read(denv->sblock, address, NULL, &oprnd) ) { + sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); + return FALSE; + } + + if ( !sieve_operand_is_omitted(&oprnd) ) { + return + sieve_opr_string_dump_data(denv, &oprnd, address, "variable name") && + sieve_opr_stringlist_dump(denv, address, "list of flags"); + } + + return + sieve_opr_stringlist_dump(denv, address, "list of flags"); +} + +/* + * Code execution + */ + +static int cmd_flag_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + struct sieve_operand oprnd; + struct sieve_stringlist *flag_list; + struct sieve_variable_storage *storage; + unsigned int var_index; + ext_imapflag_flag_operation_t flag_op; + int ret; + + /* + * Read operands + */ + + /* Read bare operand (two types possible) */ + if ( (ret=sieve_operand_runtime_read + (renv, address, NULL, &oprnd)) <= 0 ) + return ret; + + /* Variable operand (optional) */ + if ( !sieve_operand_is_omitted(&oprnd) ) { + /* Read the variable operand */ + if ( (ret=sieve_variable_operand_read_data + (renv, &oprnd, address, "variable", &storage, &var_index)) <= 0 ) + return ret; + + /* Read flag list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "flag-list", &flag_list)) + <= 0 ) + return ret; + + /* Flag-list operand */ + } else { + storage = NULL; + var_index = 0; + + /* Read flag list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, + "flag-list", &flag_list)) <= 0 ) + return ret; + } + + /* + * Perform operation + */ + + /* Determine what to do */ + + if ( sieve_operation_is(op, setflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "setflag command"); + flag_op = sieve_ext_imap4flags_set_flags; + } else if ( sieve_operation_is(op, addflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "addflag command"); + flag_op = sieve_ext_imap4flags_add_flags; + } else if ( sieve_operation_is(op, removeflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "removeflag command"); + flag_op = sieve_ext_imap4flags_remove_flags; + } else { + i_unreached(); + } + + sieve_runtime_trace_descend(renv); + + /* Perform requested operation */ + return flag_op(renv, op->ext, storage, var_index, flag_list); +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c new file mode 100644 index 0000000..3c364b8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c @@ -0,0 +1,733 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "imap-arg.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-stringlist.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-imap4flags-common.h" + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def tag_flags; +extern const struct sieve_argument_def tag_flags_implicit; + +/* + * Common command functions + */ + +bool ext_imap4flags_command_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_ast_argument *arg2; + const struct sieve_extension *var_ext; + + /* Check arguments */ + + if ( arg == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the %s %s expects at least one argument, but none was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + if ( sieve_ast_argument_type(arg) != SAAT_STRING && + sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) + { + sieve_argument_validate_error(valdtr, arg, + "the %s %s expects either a string (variable name) or " + "a string-list (list of flags) as first argument, but %s was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + sieve_ast_argument_name(arg)); + return FALSE; + } + + arg2 = sieve_ast_argument_next(arg); + if ( arg2 != NULL ) { + /* First, check syntax sanity */ + + if ( sieve_ast_argument_type(arg) != SAAT_STRING ) + { + if ( sieve_command_is(cmd, tst_hasflag) ) { + if ( sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) { + sieve_argument_validate_error(valdtr, arg, + "if a second argument is specified for the hasflag, the first " + "must be a string-list (variable-list), but %s was found", + sieve_ast_argument_name(arg)); + return FALSE; + } + } else { + sieve_argument_validate_error(valdtr, arg, + "if a second argument is specified for the %s %s, the first " + "must be a string (variable name), but %s was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + sieve_ast_argument_name(arg)); + return FALSE; + } + } + + /* Then, check whether the second argument is permitted */ + + var_ext = sieve_ext_variables_get_extension(cmd->ext->svinst); + + if ( var_ext == NULL || !sieve_ext_variables_is_active(var_ext, valdtr) ) + { + sieve_argument_validate_error(valdtr,arg, + "the %s %s only allows for the specification of a " + "variable name when the variables extension is active", + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + if ( !sieve_variable_argument_activate(var_ext, var_ext, + valdtr, cmd, arg, !sieve_command_is(cmd, tst_hasflag) ) ) + return FALSE; + + if ( sieve_ast_argument_type(arg2) != SAAT_STRING && + sieve_ast_argument_type(arg2) != SAAT_STRING_LIST ) + { + sieve_argument_validate_error(valdtr, arg2, + "the %s %s expects a string list (list of flags) as " + "second argument when two arguments are specified, " + "but %s was found", + sieve_command_identifier(cmd), sieve_command_type_name(cmd), + sieve_ast_argument_name(arg2)); + return FALSE; + } + } else + arg2 = arg; + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg2, FALSE) ) + return FALSE; + + if ( !sieve_command_is(cmd, tst_hasflag) && + sieve_argument_is_string_literal(arg2) ) { + struct ext_imap4flags_iter fiter; + const char *flag; + + /* Warn the user about validity of verifiable flags */ + ext_imap4flags_iter_init(&fiter, sieve_ast_argument_str(arg)); + + while ( (flag=ext_imap4flags_iter_get_flag(&fiter)) != NULL ) { + if ( !sieve_ext_imap4flags_flag_is_valid(flag) ) { + sieve_argument_validate_warning(valdtr, arg, + "IMAP flag '%s' specified for the %s command is invalid " + "and will be ignored (only first invalid is reported)", + str_sanitize(flag, 64), sieve_command_identifier(cmd)); + break; + } + } + } + + return TRUE; +} + +/* + * Flags tag registration + */ + +void ext_imap4flags_attach_flags_tag +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const char *command) +{ + /* Register :flags tag with the command and we don't care whether it is + * registered or even whether it will be registered at all. The validator + * handles either situation gracefully + */ + + /* Tag specified by user */ + sieve_validator_register_external_tag + (valdtr, command, ext, &tag_flags, SIEVE_OPT_SIDE_EFFECT); +} + +void sieve_ext_imap4flags_register_side_effect +(struct sieve_validator *valdtr, const struct sieve_extension *flg_ext, + const char *command) +{ + /* Implicit tag if none is specified */ + sieve_validator_register_persistent_tag + (valdtr, command, flg_ext, &tag_flags_implicit); +} + + +/* + * Result context + */ + +struct ext_imap4flags_result_context { + string_t *internal_flags; +}; + +static void _get_initial_flags +(struct sieve_result *result, string_t *flags) +{ + const struct sieve_message_data *msgdata = + sieve_result_get_message_data(result); + enum mail_flags mail_flags; + const char *const *mail_keywords; + + mail_flags = mail_get_flags(msgdata->mail); + mail_keywords = mail_get_keywords(msgdata->mail); + + if ( (mail_flags & MAIL_FLAGGED) > 0 ) + str_printfa(flags, " \\flagged"); + + if ( (mail_flags & MAIL_ANSWERED) > 0 ) + str_printfa(flags, " \\answered"); + + if ( (mail_flags & MAIL_DELETED) > 0 ) + str_printfa(flags, " \\deleted"); + + if ( (mail_flags & MAIL_SEEN) > 0 ) + str_printfa(flags, " \\seen"); + + if ( (mail_flags & MAIL_DRAFT) > 0 ) + str_printfa(flags, " \\draft"); + + while ( *mail_keywords != NULL ) { + str_printfa(flags, " %s", *mail_keywords); + mail_keywords++; + } +} + +static inline struct ext_imap4flags_result_context *_get_result_context +(const struct sieve_extension *this_ext, struct sieve_result *result) +{ + struct ext_imap4flags_result_context *rctx = + (struct ext_imap4flags_result_context *) + sieve_result_extension_get_context(result, this_ext); + + if ( rctx == NULL ) { + pool_t pool = sieve_result_pool(result); + + rctx =p_new(pool, struct ext_imap4flags_result_context, 1); + rctx->internal_flags = str_new(pool, 32); + _get_initial_flags(result, rctx->internal_flags); + + sieve_result_extension_set_context + (result, this_ext, rctx); + } + + return rctx; +} + +static string_t *_get_flags_string +(const struct sieve_extension *this_ext, struct sieve_result *result) +{ + struct ext_imap4flags_result_context *ctx = + _get_result_context(this_ext, result); + + return ctx->internal_flags; +} + +/* + * Runtime initialization + */ + +static int ext_imap4flags_runtime_init +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred ATTR_UNUSED) +{ + sieve_result_add_implicit_side_effect + (renv->result, NULL, TRUE, ext, &flags_side_effect, NULL); + return SIEVE_EXEC_OK; +} + +const struct sieve_interpreter_extension +imap4flags_interpreter_extension = { + .ext_def = &imap4flags_extension, + .run = ext_imap4flags_runtime_init +}; + +/* + * Flag handling + */ + +/* FIXME: This currently accepts a potentially unlimited number of + * flags, making the internal or variable flag list indefinitely long + */ + +bool sieve_ext_imap4flags_flag_is_valid(const char *flag) +{ + if ( *flag == '\0' ) + return FALSE; + + if ( *flag == '\\' ) { + /* System flag */ + const char *atom = t_str_ucase(flag); + + if ( + (strcmp(atom, "\\ANSWERED") != 0) && + (strcmp(atom, "\\FLAGGED") != 0) && + (strcmp(atom, "\\DELETED") != 0) && + (strcmp(atom, "\\SEEN") != 0) && + (strcmp(atom, "\\DRAFT") != 0) ) + { + return FALSE; + } + } else { + const char *p; + + /* Custom keyword: + * + * Syntax (IMAP4rev1, RFC 3501, Section 9. Formal Syntax) : + * flag-keyword = atom + * atom = 1*ATOM-CHAR + */ + p = flag; + while ( *p != '\0' ) { + if ( !IS_ATOM_CHAR(*p) ) + return FALSE; + p++; + } + } + + return TRUE; +} + +/* Flag iterator */ + +static void ext_imap4flags_iter_clear +(struct ext_imap4flags_iter *iter) +{ + i_zero(iter); +} + +void ext_imap4flags_iter_init +(struct ext_imap4flags_iter *iter, string_t *flags_list) +{ + ext_imap4flags_iter_clear(iter); + iter->flags_list = flags_list; +} + +static string_t *ext_imap4flags_iter_get_flag_str +(struct ext_imap4flags_iter *iter) +{ + unsigned int len; + const unsigned char *fp; + const unsigned char *fbegin; + const unsigned char *fstart; + const unsigned char *fend; + + /* Return if not initialized */ + if ( iter->flags_list == NULL ) return NULL; + + /* Return if no more flags are available */ + len = str_len(iter->flags_list); + if ( iter->offset >= len ) return NULL; + + /* Mark string boundries */ + fbegin = str_data(iter->flags_list); + fend = fbegin + len; + + /* Start of this flag */ + fstart = fbegin + iter->offset; + + /* Scan for next flag */ + fp = fstart; + for (;;) { + /* Have we reached the end or a flag boundary? */ + if ( fp >= fend || *fp == ' ' ) { + /* Did we scan more than nothing ? */ + if ( fp > fstart ) { + /* Return flag */ + string_t *flag = t_str_new(fp-fstart+1); + str_append_data(flag, fstart, fp-fstart); + + iter->last = fstart - fbegin; + iter->offset = fp - fbegin; + + return flag; + } + + fstart = fp + 1; + } + + if ( fp >= fend ) break; + + fp++; + } + + iter->last = fstart - fbegin; + iter->offset = fp - fbegin; + return NULL; +} + +const char *ext_imap4flags_iter_get_flag +(struct ext_imap4flags_iter *iter) +{ + string_t *flag = ext_imap4flags_iter_get_flag_str(iter); + + if ( flag == NULL ) return NULL; + + return str_c(flag); +} + +static void ext_imap4flags_iter_delete_last +(struct ext_imap4flags_iter *iter) +{ + iter->offset++; + if ( iter->offset > str_len(iter->flags_list) ) + iter->offset = str_len(iter->flags_list); + if ( iter->offset == str_len(iter->flags_list) && iter->last > 0 ) + iter->last--; + + str_delete(iter->flags_list, iter->last, iter->offset - iter->last); + + iter->offset = iter->last; +} + +/* Flag operations */ + +static string_t *ext_imap4flags_get_flag_variable +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index) + ATTR_NULL(2); + +static bool flags_list_flag_exists +(string_t *flags_list, const char *flag) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags_list); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + if ( strcasecmp(flg, flag) == 0 ) + return TRUE; + } + + return FALSE; +} + +static void flags_list_flag_delete +(string_t *flags_list, const char *flag) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags_list); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + if ( strcasecmp(flg, flag) == 0 ) { + ext_imap4flags_iter_delete_last(&flit); + } + } +} + +static void flags_list_add_flags +(string_t *flags_list, string_t *flags) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + if ( sieve_ext_imap4flags_flag_is_valid(flg) && + !flags_list_flag_exists(flags_list, flg) ) { + if ( str_len(flags_list) != 0 ) + str_append_c(flags_list, ' '); + str_append(flags_list, flg); + } + } +} + +static void flags_list_remove_flags +(string_t *flags_list, string_t *flags) +{ + const char *flg; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags); + + while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) { + flags_list_flag_delete(flags_list, flg); + } +} + +static void flags_list_set_flags +(string_t *flags_list, string_t *flags) +{ + str_truncate(flags_list, 0); + flags_list_add_flags(flags_list, flags); +} + +static void flags_list_clear_flags +(string_t *flags_list) +{ + str_truncate(flags_list, 0); +} + +static string_t *ext_imap4flags_get_flag_variable +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index) +{ + string_t *flags; + + if ( storage != NULL ) { + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + const char *var_name, *var_id; + + (void)sieve_variable_get_identifier(storage, var_index, &var_name); + var_id = sieve_variable_get_varid(storage, var_index); + + sieve_runtime_trace(renv, 0, "update variable `%s' [%s]", + var_name, var_id); + } + + if ( !sieve_variable_get_modifiable(storage, var_index, &flags) ) + return NULL; + } else { + i_assert( sieve_extension_is(flg_ext, imap4flags_extension) ); + flags = _get_flags_string(flg_ext, renv->result); + } + + return flags; +} + +int sieve_ext_imap4flags_set_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) +{ + string_t *cur_flags = ext_imap4flags_get_flag_variable + (renv, flg_ext, storage, var_index); + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + flags_list_clear_flags(cur_flags); + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "set flags `%s'", str_c(flags_item)); + + flags_list_add_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_ext_imap4flags_add_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) +{ + string_t *cur_flags = ext_imap4flags_get_flag_variable + (renv, flg_ext, storage, var_index); + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "add flags `%s'", str_c(flags_item)); + + flags_list_add_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_ext_imap4flags_remove_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) +{ + string_t *cur_flags = ext_imap4flags_get_flag_variable + (renv, flg_ext, storage, var_index); + + if ( cur_flags != NULL ) { + string_t *flags_item; + int ret; + + while ( (ret=sieve_stringlist_next_item(flags, &flags_item)) > 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "remove flags `%s'", str_c(flags_item)); + + flags_list_remove_flags(cur_flags, flags_item); + } + + if ( ret < 0 ) return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } + + return SIEVE_EXEC_BIN_CORRUPT; +} + +/* Flag stringlist */ + +static int ext_imap4flags_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void ext_imap4flags_stringlist_reset + (struct sieve_stringlist *_strlist); + +struct ext_imap4flags_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *flags_list; + string_t *flags_string; + struct ext_imap4flags_iter flit; + + bool normalize:1; +}; + +static struct sieve_stringlist *ext_imap4flags_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *flags_list, + bool normalize) +{ + struct ext_imap4flags_stringlist *strlist; + + strlist = t_new(struct ext_imap4flags_stringlist, 1); + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.runenv = renv; + strlist->strlist.next_item = ext_imap4flags_stringlist_next_item; + strlist->strlist.reset = ext_imap4flags_stringlist_reset; + strlist->normalize = normalize; + + strlist->flags_list = flags_list; + + return &strlist->strlist; +} + +static struct sieve_stringlist *ext_imap4flags_stringlist_create_single +(const struct sieve_runtime_env *renv, string_t *flags_string, bool normalize) +{ + struct ext_imap4flags_stringlist *strlist; + + strlist = t_new(struct ext_imap4flags_stringlist, 1); + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.runenv = renv; + strlist->strlist.next_item = ext_imap4flags_stringlist_next_item; + strlist->strlist.reset = ext_imap4flags_stringlist_reset; + strlist->normalize = normalize; + + if ( normalize ) { + strlist->flags_string = t_str_new(256); + flags_list_set_flags(strlist->flags_string, flags_string); + } else { + strlist->flags_string = flags_string; + } + + ext_imap4flags_iter_init(&strlist->flit, strlist->flags_string); + + return &strlist->strlist; +} + +static int ext_imap4flags_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct ext_imap4flags_stringlist *strlist = + (struct ext_imap4flags_stringlist *)_strlist; + + while ( (*str_r=ext_imap4flags_iter_get_flag_str(&strlist->flit)) == NULL ) { + int ret; + + if ( strlist->flags_list == NULL ) + return 0; + + if ( (ret=sieve_stringlist_next_item + (strlist->flags_list, &strlist->flags_string)) <= 0 ) + return ret; + + if ( strlist->flags_string == NULL ) + return -1; + + if ( strlist->normalize ) { + string_t *flags_string = t_str_new(256); + + flags_list_set_flags(flags_string, strlist->flags_string); + strlist->flags_string = flags_string; + } + + ext_imap4flags_iter_init(&strlist->flit, strlist->flags_string); + } + + return 1; +} + +static void ext_imap4flags_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct ext_imap4flags_stringlist *strlist = + (struct ext_imap4flags_stringlist *)_strlist; + + if ( strlist->flags_list != NULL ) { + sieve_stringlist_reset(strlist->flags_list); + ext_imap4flags_iter_clear(&strlist->flit); + } else { + ext_imap4flags_iter_init(&strlist->flit, strlist->flags_string); + } +} + +/* Flag access */ + +struct sieve_stringlist *sieve_ext_imap4flags_get_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_stringlist *flags_list) +{ + if ( flags_list == NULL ) { + i_assert( sieve_extension_is(flg_ext, imap4flags_extension) ); + return ext_imap4flags_stringlist_create_single + (renv, _get_flags_string(flg_ext, renv->result), FALSE); + } + + return ext_imap4flags_stringlist_create(renv, flags_list, TRUE); +} + +void ext_imap4flags_get_implicit_flags_init +(struct ext_imap4flags_iter *iter, const struct sieve_extension *this_ext, + struct sieve_result *result) +{ + string_t *cur_flags = _get_flags_string(this_ext, result); + + ext_imap4flags_iter_init(iter, cur_flags); +} + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h new file mode 100644 index 0000000..4bedb85 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h @@ -0,0 +1,97 @@ +#ifndef EXT_IMAP4FLAGS_COMMON_H +#define EXT_IMAP4FLAGS_COMMON_H + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-ext-variables.h" + +#include "sieve-ext-imap4flags.h" + +/* + * Side effect + */ + +extern const struct sieve_side_effect_def flags_side_effect; + +/* + * Operands + */ + +extern const struct sieve_operand_def flags_side_effect_operand; + +/* + * Operations + */ + +enum ext_imap4flags_opcode { + EXT_IMAP4FLAGS_OPERATION_SETFLAG, + EXT_IMAP4FLAGS_OPERATION_ADDFLAG, + EXT_IMAP4FLAGS_OPERATION_REMOVEFLAG, + EXT_IMAP4FLAGS_OPERATION_HASFLAG +}; + +extern const struct sieve_operation_def setflag_operation; +extern const struct sieve_operation_def addflag_operation; +extern const struct sieve_operation_def removeflag_operation; +extern const struct sieve_operation_def hasflag_operation; + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_setflag; +extern const struct sieve_command_def cmd_addflag; +extern const struct sieve_command_def cmd_removeflag; + +extern const struct sieve_command_def tst_hasflag; + +/* + * Common command functions + */ + +bool ext_imap4flags_command_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +/* + * Flags tagged argument + */ + +void ext_imap4flags_attach_flags_tag + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + const char *command); + +/* + * Flag management + */ + +struct ext_imap4flags_iter { + string_t *flags_list; + unsigned int offset; + unsigned int last; +}; + +void ext_imap4flags_iter_init + (struct ext_imap4flags_iter *iter, string_t *flags_list); + +const char *ext_imap4flags_iter_get_flag + (struct ext_imap4flags_iter *iter); + +/* Flag operations */ + +typedef int (*ext_imapflag_flag_operation_t) + (const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, struct sieve_stringlist *flags) + ATTR_NULL(2); + +/* Flags access */ + +void ext_imap4flags_get_implicit_flags_init + (struct ext_imap4flags_iter *iter, const struct sieve_extension *this_ext, + struct sieve_result *result); + + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c new file mode 100644 index 0000000..23230c1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension imap4flags + * -------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5232 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "mempool.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-imap4flags-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *imap4flags_operations[] = { + &setflag_operation, + &addflag_operation, + &removeflag_operation, + &hasflag_operation +}; + +/* + * Extension + */ + +static bool ext_imap4flags_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_imap4flags_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def imap4flags_extension = { + .name = "imap4flags", + .version = 1, + .validator_load = ext_imap4flags_validator_load, + .interpreter_load = ext_imap4flags_interpreter_load, + SIEVE_EXT_DEFINE_OPERATIONS(imap4flags_operations), + SIEVE_EXT_DEFINE_OPERAND(flags_side_effect_operand) +}; + +static bool ext_imap4flags_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register commands */ + sieve_validator_register_command(valdtr, ext, &cmd_setflag); + sieve_validator_register_command(valdtr, ext, &cmd_addflag); + sieve_validator_register_command(valdtr, ext, &cmd_removeflag); + sieve_validator_register_command(valdtr, ext, &tst_hasflag); + + /* Attach :flags tag to keep and fileinto commands */ + ext_imap4flags_attach_flags_tag(valdtr, ext, "keep"); + ext_imap4flags_attach_flags_tag(valdtr, ext, "fileinto"); + + /* Attach flags side-effect to keep and fileinto actions */ + sieve_ext_imap4flags_register_side_effect(valdtr, ext, "keep"); + sieve_ext_imap4flags_register_side_effect(valdtr, ext, "fileinto"); + + return TRUE; +} + +void sieve_ext_imap4flags_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv) +{ + sieve_interpreter_extension_register + (renv->interp, ext, &imap4flags_interpreter_extension, NULL); +} + +static bool ext_imap4flags_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_ext_imap4flags_interpreter_load(ext, renv); + return TRUE; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imapflags.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imapflags.c new file mode 100644 index 0000000..ba99035 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/ext-imapflags.c @@ -0,0 +1,213 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension imapflags + * -------------------- + * + * Authors: Stephan Bosch + * Specification: draft-melnikov-sieve-imapflags-03.txt + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: testing + * + */ + +#include "lib.h" +#include "mempool.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-imap4flags-common.h" + +/* + * Commands + */ + +static bool cmd_mark_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); + +/* Mark command + * + * Syntax: + * mark + */ + +static const struct sieve_command_def cmd_mark = { + .identifier = "mark", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_mark_validate +}; + +/* Unmark command + * + * Syntax: + * unmark + */ +static const struct sieve_command_def cmd_unmark = { + .identifier = "unmark", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_mark_validate +}; + +/* + * Extension + */ + +static bool ext_imapflags_load + (const struct sieve_extension *ext, void **context); +static bool ext_imapflags_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_imapflags_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def imapflags_extension = { + .name = "imapflags", + .load = ext_imapflags_load, + .validator_load = ext_imapflags_validator_load, + .interpreter_load = ext_imapflags_interpreter_load +}; + +static bool ext_imapflags_load +(const struct sieve_extension *ext, void **context) +{ + if ( *context == NULL ) { + /* Make sure real extension is registered, it is needed by the binary */ + *context = (void *) + sieve_extension_require(ext->svinst, &imap4flags_extension, FALSE); + } + + return TRUE; +} + +/* + * Validator + */ + +static bool ext_imapflags_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *other_ext, + bool required); +static bool ext_imapflags_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +const struct sieve_validator_extension +imapflags_validator_extension = { + .ext = &imapflags_extension, + .check_conflict = ext_imapflags_validator_check_conflict, + .validate = ext_imapflags_validator_validate +}; + +static bool ext_imapflags_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_extension_register + (valdtr, ext, &imapflags_validator_extension, NULL); + + return TRUE; +} + +static bool ext_imapflags_validator_check_conflict +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + const struct sieve_extension *master_ext = + (const struct sieve_extension *) ext->context; + + if ( ext_other == master_ext ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) imapflags extension cannot be used " + "together with the imap4flags extension"); + return FALSE; + } + + return TRUE; +} + +static bool ext_imapflags_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg ATTR_UNUSED, + bool required ATTR_UNUSED) +{ + const struct sieve_extension *master_ext = + (const struct sieve_extension *) ext->context; + + /* No conflicts */ + + /* Register commands */ + sieve_validator_register_command(valdtr, master_ext, &cmd_setflag); + sieve_validator_register_command(valdtr, master_ext, &cmd_addflag); + sieve_validator_register_command(valdtr, master_ext, &cmd_removeflag); + + sieve_validator_register_command(valdtr, master_ext, &cmd_mark); + sieve_validator_register_command(valdtr, master_ext, &cmd_unmark); + + /* Attach flags side-effect to keep and fileinto actions */ + sieve_ext_imap4flags_register_side_effect(valdtr, master_ext, "keep"); + sieve_ext_imap4flags_register_side_effect(valdtr, master_ext, "fileinto"); + + return TRUE; +} + +/* + * Interpreter + */ + +static bool ext_imapflags_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + const struct sieve_extension *master_ext = + (const struct sieve_extension *) ext->context; + + sieve_ext_imap4flags_interpreter_load(master_ext, renv); + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_mark_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + if ( sieve_command_is(cmd, cmd_mark) ) + cmd->def = &cmd_addflag; + else + cmd->def = &cmd_removeflag; + + cmd->first_positional = sieve_ast_argument_cstring_create + (cmd->ast_node, "\\flagged", cmd->ast_node->source_line); + + if ( !sieve_validator_argument_activate + (valdtr, cmd, cmd->first_positional, FALSE) ) + return FALSE; + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h b/pigeonhole/src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h new file mode 100644 index 0000000..b38a3c8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/sieve-ext-imap4flags.h @@ -0,0 +1,74 @@ +#ifndef SIEVE_EXT_IMAP4FLAGS_H +#define SIEVE_EXT_IMAP4FLAGS_H + +struct sieve_variable_storage; + +/* + * Imap4flags extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def imap4flags_extension; +extern const struct sieve_interpreter_extension + imap4flags_interpreter_extension; + +static inline const struct sieve_extension * +sieve_ext_imap4flags_require_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_require + (svinst, &imap4flags_extension, TRUE); +} + +void sieve_ext_imap4flags_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv); + +/* + * Action side-effect + */ + +void sieve_ext_imap4flags_register_side_effect +(struct sieve_validator *valdtr, const struct sieve_extension *flg_ext, + const char *command); + +/* + * Flag syntax + */ + +bool sieve_ext_imap4flags_flag_is_valid(const char *flag); + +/* + * Flag manipulation + */ + +int sieve_ext_imap4flags_set_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) ATTR_NULL(3); +int sieve_ext_imap4flags_add_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) ATTR_NULL(3); +int sieve_ext_imap4flags_remove_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_variable_storage *storage, + unsigned int var_index, + struct sieve_stringlist *flags) ATTR_NULL(3); + +/* + * Flag retrieval + */ + +struct sieve_stringlist *sieve_ext_imap4flags_get_flags +(const struct sieve_runtime_env *renv, + const struct sieve_extension *flg_ext, + struct sieve_stringlist *flags_list); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/tag-flags.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/tag-flags.c new file mode 100644 index 0000000..331063d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/tag-flags.c @@ -0,0 +1,402 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "array.h" +#include "mail-storage.h" + +#include "sieve-code.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-actions.h" +#include "sieve-dump.h" + +#include "ext-imap4flags-common.h" + +#include <ctype.h> + +/* + * Flags tagged argument + */ + +static bool +tag_flags_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); +static bool +tag_flags_validate_persistent(struct sieve_validator *valdtr, + struct sieve_command *cmd, + const struct sieve_extension *ext); +static bool +tag_flags_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, struct sieve_command *cmd); + +const struct sieve_argument_def tag_flags = { + .identifier = "flags", + .validate = tag_flags_validate, + .generate = tag_flags_generate, +}; + +const struct sieve_argument_def tag_flags_implicit = { + .identifier = "flags-implicit", + .validate_persistent = tag_flags_validate_persistent, + .generate = tag_flags_generate, +}; + +/* + * Side effect + */ + +static bool +seff_flags_dump_context(const struct sieve_side_effect *seffect, + const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +seff_flags_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **context); + +static int +seff_flags_merge(const struct sieve_runtime_env *renv, + const struct sieve_action *action, + const struct sieve_side_effect *old_seffect, + const struct sieve_side_effect *new_seffect, + void **old_context); + +static void +seff_flags_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); + +static int +seff_flags_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context); + +const struct sieve_side_effect_def flags_side_effect = { + SIEVE_OBJECT("flags", &flags_side_effect_operand, 0), + .to_action = &act_store, + .dump_context = seff_flags_dump_context, + .read_context = seff_flags_read_context, + .merge = seff_flags_merge, + .print = seff_flags_print, + .pre_execute = seff_flags_pre_execute, +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(flags_side_effect); + +const struct sieve_operand_def flags_side_effect_operand = { + .name = "flags operand", + .ext_def = &imap4flags_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects, +}; + +/* + * Tag validation + */ + +static bool +tag_flags_validate_persistent(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd, + const struct sieve_extension *ext) +{ + if (sieve_command_find_argument(cmd, &tag_flags) == NULL) + sieve_command_add_dynamic_tag(cmd, ext, &tag_flags_implicit, + -1); + return TRUE; +} + +static bool +tag_flags_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * :flags <list-of-flags: string-list> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + tag->parameters = *arg; + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_flags_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *param; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, arg->argument->ext, + &flags_side_effect); + + if (sieve_argument_is(arg, tag_flags)) { + /* Explicit :flags tag */ + param = arg->parameters; + + /* Call the generation function for the argument */ + if (param->argument != NULL && param->argument->def != NULL && + param->argument->def->generate != NULL && + !param->argument->def->generate(cgenv, param, cmd)) + return FALSE; + } else if (sieve_argument_is(arg, tag_flags_implicit)) { + /* Implicit flags */ + sieve_opr_omitted_emit(cgenv->sblock); + } else { + /* Something else?! */ + i_unreached(); + } + return TRUE; +} + +/* + * Side effect implementation + */ + +/* Context data */ + +struct seff_flags_context { + ARRAY(const char *) keywords; + enum mail_flags flags; +}; + +/* Context coding */ + +static bool +seff_flags_dump_context(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + return sieve_opr_stringlist_dump_ex(denv, address, "flags", "INTERNAL"); +} + +static struct seff_flags_context * +seff_flags_get_implicit_context(const struct sieve_extension *this_ext, + struct sieve_result *result) +{ + pool_t pool = sieve_result_pool(result); + struct seff_flags_context *ctx; + const char *flag; + struct ext_imap4flags_iter flit; + + ctx = p_new(pool, struct seff_flags_context, 1); + p_array_init(&ctx->keywords, pool, 2); + + T_BEGIN { + /* Unpack */ + ext_imap4flags_get_implicit_flags_init(&flit, this_ext, result); + while ((flag = ext_imap4flags_iter_get_flag(&flit)) != NULL) { + if (flag != NULL && *flag != '\\') { + /* keyword */ + const char *keyword = p_strdup(pool, flag); + array_append(&ctx->keywords, &keyword, 1); + } else { + /* system flag */ + if (flag == NULL || + strcasecmp(flag, "\\flagged") == 0) + ctx->flags |= MAIL_FLAGGED; + else if (strcasecmp(flag, "\\answered") == 0) + ctx->flags |= MAIL_ANSWERED; + else if (strcasecmp(flag, "\\deleted") == 0) + ctx->flags |= MAIL_DELETED; + else if (strcasecmp(flag, "\\seen") == 0) + ctx->flags |= MAIL_SEEN; + else if (strcasecmp(flag, "\\draft") == 0) + ctx->flags |= MAIL_DRAFT; + } + } + } T_END; + + return ctx; +} + +static int +seff_flags_do_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **se_context) +{ + pool_t pool = sieve_result_pool(renv->result); + struct seff_flags_context *ctx; + string_t *flags_item; + struct sieve_stringlist *flag_list = NULL; + int ret; + + ret = sieve_opr_stringlist_read_ex(renv, address, "flags", TRUE, + &flag_list); + if (ret <= 0) + return ret; + + if (flag_list == NULL) { + /* Flag list is omitted, use current value of internal + * variable to construct side effect context. + */ + *se_context = seff_flags_get_implicit_context( + SIEVE_OBJECT_EXTENSION(seffect), renv->result); + return SIEVE_EXEC_OK; + } + + ctx = p_new(pool, struct seff_flags_context, 1); + p_array_init(&ctx->keywords, pool, 2); + + /* Unpack */ + flags_item = NULL; + while ((ret = sieve_stringlist_next_item(flag_list, &flags_item)) > 0) { + const char *flag; + struct ext_imap4flags_iter flit; + + ext_imap4flags_iter_init(&flit, flags_item); + + while ((flag = ext_imap4flags_iter_get_flag(&flit)) != NULL) { + if (flag != NULL && *flag != '\\') { + /* keyword */ + const char *keyword = p_strdup(pool, flag); + + /* FIXME: should check for duplicates (cannot + trust variables) */ + array_append(&ctx->keywords, &keyword, 1); + } else { + /* system flag */ + if (flag == NULL || + strcasecmp(flag, "\\flagged") == 0) + ctx->flags |= MAIL_FLAGGED; + else if (strcasecmp(flag, "\\answered") == 0) + ctx->flags |= MAIL_ANSWERED; + else if (strcasecmp(flag, "\\deleted") == 0) + ctx->flags |= MAIL_DELETED; + else if (strcasecmp(flag, "\\seen") == 0) + ctx->flags |= MAIL_SEEN; + else if (strcasecmp(flag, "\\draft") == 0) + ctx->flags |= MAIL_DRAFT; + } + } + } + + if (ret < 0) + return flag_list->exec_status; + + *se_context = (void *)ctx; + return SIEVE_EXEC_OK; +} + +static int +seff_flags_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **se_context) +{ + int ret; + + T_BEGIN { + ret = seff_flags_do_read_context(seffect, renv, address, + se_context); + } T_END; + + return ret; +} + +/* Result verification */ + +static int +seff_flags_merge(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_side_effect *old_seffect ATTR_UNUSED, + const struct sieve_side_effect *new_seffect, + void **old_context) +{ + if (new_seffect != NULL) + *old_context = new_seffect->context; + return 1; +} + +/* Result printing */ + +static void +seff_flags_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct sieve_result *result = rpenv->result; + struct seff_flags_context *ctx = + (struct seff_flags_context *)seffect->context; + unsigned int i; + + if (ctx == NULL) { + ctx = seff_flags_get_implicit_context( + SIEVE_OBJECT_EXTENSION(seffect), result); + } + + if (ctx->flags != 0 || array_count(&ctx->keywords) > 0) { + T_BEGIN { + string_t *flags = t_str_new(128); + + if ((ctx->flags & MAIL_FLAGGED) > 0) + str_printfa(flags, " \\flagged"); + if ((ctx->flags & MAIL_ANSWERED) > 0) + str_printfa(flags, " \\answered"); + if ((ctx->flags & MAIL_DELETED) > 0) + str_printfa(flags, " \\deleted"); + if ((ctx->flags & MAIL_SEEN) > 0) + str_printfa(flags, " \\seen"); + if ((ctx->flags & MAIL_DRAFT) > 0) + str_printfa(flags, " \\draft"); + + for (i = 0; i < array_count(&ctx->keywords); i++) { + const char *const *keyword = + array_idx(&ctx->keywords, i); + str_printfa(flags, " %s", + str_sanitize(*keyword, 64)); + } + + sieve_result_seffect_printf(rpenv, "add IMAP flags:%s", + str_c(flags)); + } T_END; + } +} + +/* Result execution */ + +static int +seff_flags_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context ATTR_UNUSED) +{ + struct seff_flags_context *ctx = seffect->context; + const char *const *keywords; + + if (ctx == NULL) { + ctx = seff_flags_get_implicit_context( + SIEVE_OBJECT_EXTENSION(seffect), aenv->result); + } + + (void)array_append_space(&ctx->keywords); + keywords = array_idx(&ctx->keywords, 0); + + sieve_act_store_add_flags(aenv, tr_context, keywords, ctx->flags); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/imap4flags/tst-hasflag.c b/pigeonhole/src/lib-sieve/plugins/imap4flags/tst-hasflag.c new file mode 100644 index 0000000..23f2acc --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/imap4flags/tst-hasflag.c @@ -0,0 +1,248 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-imap4flags-common.h" + +/* + * Hasflag test + * + * Syntax: + * hasflag [MATCH-TYPE] [COMPARATOR] [<variable-list: string-list>] + * <list-of-flags: string-list> + */ + +static bool tst_hasflag_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_hasflag_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_hasflag_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def tst_hasflag = { + .identifier = "hasflag", + .type = SCT_TEST, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_hasflag_registered, + .validate = tst_hasflag_validate, + .generate = tst_hasflag_generate +}; + +/* + * Hasflag operation + */ + +static bool tst_hasflag_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_hasflag_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def hasflag_operation = { + .mnemonic = "HASFLAG", + .ext_def = &imap4flags_extension, + .code = EXT_IMAP4FLAGS_OPERATION_HASFLAG, + .dump = tst_hasflag_operation_dump, + .execute = tst_hasflag_operation_execute +}; + +/* + * Optional arguments + */ + +enum tst_hasflag_optional { + OPT_VARIABLES = SIEVE_MATCH_OPT_LAST, +}; + +/* + * Tag registration + */ + +static bool tst_hasflag_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_hasflag_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *vars = tst->first_positional; + struct sieve_ast_argument *keys = sieve_ast_argument_next(vars); + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + if ( !ext_imap4flags_command_validate(valdtr, tst) ) + return FALSE; + + if ( keys == NULL ) { + keys = vars; + vars = NULL; + } else { + vars->argument->id_code = OPT_VARIABLES; + } + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, keys, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_hasflag_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &hasflag_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool tst_hasflag_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "HASFLAG"); + sieve_code_descend(denv); + + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_VARIABLES: + opok = sieve_opr_stringlist_dump(denv, address, "variables"); + break; + default: + return FALSE; + } + + if ( !opok ) return FALSE; + } + + return + sieve_opr_stringlist_dump(denv, address, "list of flags"); +} + +/* + * Interpretation + */ + +static int tst_hasflag_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + int opt_code = 0; + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_stringlist *flag_list, *variables_list, *value_list, *key_list; + int match, ret; + + /* + * Read operands + */ + + /* Optional operands */ + + variables_list = NULL; + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_VARIABLES: + ret = sieve_opr_stringlist_read + (renv, address, "variables-list", &variables_list); + break; + default: + sieve_runtime_trace_error(renv, "invalid optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if ( ret <= 0 ) return ret; + } + + /* Fixed operands */ + + if ( (ret=sieve_opr_stringlist_read(renv, address, "flag-list", &flag_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "hasflag test"); + + value_list = sieve_ext_imap4flags_get_flags + (renv, op->ext, variables_list); + + if ( sieve_match_type_is(&mcht, is_match_type) || + sieve_match_type_is(&mcht, contains_match_type) ) { + key_list = sieve_ext_imap4flags_get_flags + (renv, op->ext, flag_list); + } else { + key_list = flag_list; + } + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/Makefile.am b/pigeonhole/src/lib-sieve/plugins/include/Makefile.am new file mode 100644 index 0000000..5ce1599 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/Makefile.am @@ -0,0 +1,24 @@ +noinst_LTLIBRARIES = libsieve_ext_include.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-include.c \ + cmd-return.c \ + cmd-global.c + +libsieve_ext_include_la_SOURCES = \ + $(cmds) \ + ext-include-common.c \ + ext-include-binary.c \ + ext-include-variables.c \ + ext-include.c + +noinst_HEADERS = \ + ext-include-common.h \ + ext-include-limits.h \ + ext-include-binary.h \ + ext-include-variables.h diff --git a/pigeonhole/src/lib-sieve/plugins/include/Makefile.in b/pigeonhole/src/lib-sieve/plugins/include/Makefile.in new file mode 100644 index 0000000..06f003f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/Makefile.in @@ -0,0 +1,718 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/include +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_include_la_LIBADD = +am__objects_1 = cmd-include.lo cmd-return.lo cmd-global.lo +am_libsieve_ext_include_la_OBJECTS = $(am__objects_1) \ + ext-include-common.lo ext-include-binary.lo \ + ext-include-variables.lo ext-include.lo +libsieve_ext_include_la_OBJECTS = \ + $(am_libsieve_ext_include_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 = +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)/cmd-global.Plo \ + ./$(DEPDIR)/cmd-include.Plo ./$(DEPDIR)/cmd-return.Plo \ + ./$(DEPDIR)/ext-include-binary.Plo \ + ./$(DEPDIR)/ext-include-common.Plo \ + ./$(DEPDIR)/ext-include-variables.Plo \ + ./$(DEPDIR)/ext-include.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 = $(libsieve_ext_include_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_include_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@ +noinst_LTLIBRARIES = libsieve_ext_include.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-include.c \ + cmd-return.c \ + cmd-global.c + +libsieve_ext_include_la_SOURCES = \ + $(cmds) \ + ext-include-common.c \ + ext-include-binary.c \ + ext-include-variables.c \ + ext-include.c + +noinst_HEADERS = \ + ext-include-common.h \ + ext-include-limits.h \ + ext-include-binary.h \ + ext-include-variables.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/lib-sieve/plugins/include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/include/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_include.la: $(libsieve_ext_include_la_OBJECTS) $(libsieve_ext_include_la_DEPENDENCIES) $(EXTRA_libsieve_ext_include_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_include_la_OBJECTS) $(libsieve_ext_include_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-include.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-return.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include-binary.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include-variables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-include.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-global.Plo + -rm -f ./$(DEPDIR)/cmd-include.Plo + -rm -f ./$(DEPDIR)/cmd-return.Plo + -rm -f ./$(DEPDIR)/ext-include-binary.Plo + -rm -f ./$(DEPDIR)/ext-include-common.Plo + -rm -f ./$(DEPDIR)/ext-include-variables.Plo + -rm -f ./$(DEPDIR)/ext-include.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-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)/cmd-global.Plo + -rm -f ./$(DEPDIR)/cmd-include.Plo + -rm -f ./$(DEPDIR)/cmd-return.Plo + -rm -f ./$(DEPDIR)/ext-include-binary.Plo + -rm -f ./$(DEPDIR)/ext-include-common.Plo + -rm -f ./$(DEPDIR)/ext-include-variables.Plo + -rm -f ./$(DEPDIR)/ext-include.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/include/cmd-global.c b/pigeonhole/src/lib-sieve/plugins/include/cmd-global.c new file mode 100644 index 0000000..0ef37eb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/cmd-global.c @@ -0,0 +1,329 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Commands + */ + +static bool cmd_global_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_global_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_global = { + .identifier = "global", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_global_validate, + .generate = cmd_global_generate, +}; + +/* DEPRICATED: + */ + +/* Import command + * + * Syntax + * import + */ +const struct sieve_command_def cmd_import = { + .identifier = "import", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_global_validate, + .generate = cmd_global_generate, +}; + +/* Export command + * + * Syntax + * export + */ +const struct sieve_command_def cmd_export = { + .identifier = "export", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_global_validate, + .generate = cmd_global_generate, +}; + +/* + * Operations + */ + +static bool opc_global_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int opc_global_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +/* Global operation */ + +const struct sieve_operation_def global_operation = { + .mnemonic = "GLOBAL", + .ext_def = &include_extension, + .code = EXT_INCLUDE_OPERATION_GLOBAL, + .dump = opc_global_dump, + .execute = opc_global_execute +}; + +/* + * Validation + */ + +static inline struct sieve_argument *_create_variable_argument +(struct sieve_command *cmd, struct sieve_variable *var) +{ + struct sieve_argument *argument = sieve_argument_create + (cmd->ast_node->ast, NULL, cmd->ext, 0); + + argument->data = (void *) var; + + return argument; +} + +static bool cmd_global_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast_argument *arg = cmd->first_positional; + struct sieve_command *prev = sieve_command_prev(cmd); + + /* DEPRECATED: Check valid command placement */ + if ( !sieve_command_is(cmd, cmd_global) ) { + if ( !sieve_command_is_toplevel(cmd) || + ( !sieve_command_is_first(cmd) && prev != NULL && + !sieve_command_is(prev, cmd_require) && + !sieve_command_is(prev, cmd_import) && + !sieve_command_is(prev, cmd_export) ) ) { + sieve_command_validate_error(valdtr, cmd, + "the DEPRECATED %s command can only be placed at top level " + "at the beginning of the file after any require or " + "import/export commands", + sieve_command_identifier(cmd)); + return FALSE; + } + } + + /* Check for use of variables extension */ + if ( !ext_include_validator_have_variables(this_ext, valdtr) ) { + sieve_command_validate_error(valdtr, cmd, + "%s command requires that variables extension is active", + sieve_command_identifier(cmd)); + return FALSE; + } + + /* Register global variable */ + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + const char *identifier = sieve_ast_argument_strc(arg); + struct sieve_variable *var; + + if ( (var=ext_include_variable_import_global + (valdtr, cmd, identifier)) == NULL ) + return FALSE; + + arg->argument = _create_variable_argument(cmd, var); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg); + + while ( stritem != NULL ) { + const char *identifier = sieve_ast_argument_strc(stritem); + struct sieve_variable *var; + + if ( (var=ext_include_variable_import_global + (valdtr, cmd, identifier)) == NULL ) + return FALSE; + + stritem->argument = _create_variable_argument(cmd, var); + + stritem = sieve_ast_strlist_next(stritem); + } + } else { + /* Something else */ + sieve_argument_validate_error(valdtr, arg, + "the %s command accepts a single string or string list argument, " + "but %s was found", sieve_command_identifier(cmd), + sieve_ast_argument_name(arg)); + return FALSE; + } + + /* Join global commands with predecessors if possible */ + if ( sieve_commands_equal(prev, cmd) ) { + /* Join this command's string list with the previous one */ + prev->first_positional = sieve_ast_stringlist_join + (prev->first_positional, cmd->first_positional); + + if ( prev->first_positional == NULL ) { + /* Not going to happen unless MAXINT stringlist items are specified */ + sieve_command_validate_error(valdtr, cmd, + "compiler reached AST limit (script too complex)"); + return FALSE; + } + + /* Detach this command node */ + sieve_ast_node_detach(cmd->ast_node); + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_global_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + sieve_operation_emit(cgenv->sblock, cmd->ext, &global_operation); + + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + struct sieve_variable *var = (struct sieve_variable *) arg->argument->data; + + (void)sieve_binary_emit_unsigned(cgenv->sblock, 1); + (void)sieve_binary_emit_unsigned(cgenv->sblock, var->index); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg); + + (void)sieve_binary_emit_unsigned + (cgenv->sblock, sieve_ast_strlist_count(arg)); + + while ( stritem != NULL ) { + struct sieve_variable *var = + (struct sieve_variable *) stritem->argument->data; + + (void)sieve_binary_emit_unsigned(cgenv->sblock, var->index); + + stritem = sieve_ast_strlist_next(stritem); + } + } else { + i_unreached(); + } + + return TRUE; +} + +/* + * Code dump + */ + +static bool opc_global_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = denv->oprtn->ext; + unsigned int count, i, var_count; + struct sieve_variable_scope_binary *global_vars; + struct sieve_variable_scope *global_scope; + struct sieve_variable * const *vars; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &count) ) + return FALSE; + + sieve_code_dumpf(denv, "GLOBAL (count: %u):", count); + + global_vars = ext_include_binary_get_global_scope(this_ext, denv->sbin); + global_scope = sieve_variable_scope_binary_get(global_vars); + vars = sieve_variable_scope_get_variables(global_scope, &var_count); + + sieve_code_descend(denv); + + for ( i = 0; i < count; i++ ) { + unsigned int index; + + sieve_code_mark(denv); + if ( !sieve_binary_read_unsigned(denv->sblock, address, &index) || + index >= var_count ) + return FALSE; + + sieve_code_dumpf(denv, "%d: VAR[%d]: '%s'", i, index, vars[index]->identifier); + } + + return TRUE; +} + +/* + * Execution + */ + +static int opc_global_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_variable_scope_binary *global_vars; + struct sieve_variable_scope *global_scope; + struct sieve_variable_storage *storage; + struct sieve_variable * const *vars; + unsigned int var_count, count, i; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &count) ) { + sieve_runtime_trace_error(renv, + "global: count operand invalid"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + global_vars = ext_include_binary_get_global_scope(this_ext, renv->sbin); + global_scope = sieve_variable_scope_binary_get(global_vars); + vars = sieve_variable_scope_get_variables(global_scope, &var_count); + storage = ext_include_interpreter_get_global_variables + (this_ext, renv->interp); + + for ( i = 0; i < count; i++ ) { + unsigned int index; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + sieve_runtime_trace_error(renv, + "global: variable index operand invalid"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( index >= var_count ) { + sieve_runtime_trace_error(renv, + "global: variable index %u is invalid in global storage (> %u)", + index, var_count); + return SIEVE_EXEC_BIN_CORRUPT; + } + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "global: exporting variable '%s' [gvid: %u, vid: %u]", + vars[index]->identifier, i, index); + + /* Make sure variable is initialized (export) */ + (void)sieve_variable_get_modifiable(storage, index, NULL); + } + + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/cmd-include.c b/pigeonhole/src/lib-sieve/plugins/include/cmd-include.c new file mode 100644 index 0000000..92aefb4 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/cmd-include.c @@ -0,0 +1,406 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-storage.h" +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" + +/* + * Include command + * + * Syntax: + * include [LOCATION] [":once"] [":optional"] <value: string> + * + * [LOCATION]: + * ":personal" / ":global" + */ + +static bool cmd_include_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_include_pre_validate + (struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd); +static bool cmd_include_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_include_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def cmd_include = { + .identifier = "include", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_include_registered, + .pre_validate = cmd_include_pre_validate, + .validate = cmd_include_validate, + .generate = cmd_include_generate +}; + +/* + * Include operation + */ + +static bool opc_include_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int opc_include_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def include_operation = { + .mnemonic = "include", + .ext_def = &include_extension, + .code = EXT_INCLUDE_OPERATION_INCLUDE, + .dump = opc_include_dump, + .execute = opc_include_execute +}; + +/* + * Context structures + */ + +struct cmd_include_context_data { + enum ext_include_script_location location; + + struct sieve_script *script; + enum ext_include_flags flags; + + bool location_assigned:1; +}; + +/* + * Tagged arguments + */ + +static bool cmd_include_validate_location_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def include_personal_tag = { + .identifier = "personal", + .validate = cmd_include_validate_location_tag +}; + +static const struct sieve_argument_def include_global_tag = { + .identifier = "global", + .validate = cmd_include_validate_location_tag +}; + +static bool cmd_include_validate_boolean_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def include_once_tag = { + .identifier = "once", + .validate = cmd_include_validate_boolean_tag +}; + +static const struct sieve_argument_def include_optional_tag = { + .identifier = "optional", + .validate = cmd_include_validate_boolean_tag +}; + +/* + * Tag validation + */ + +static bool cmd_include_validate_location_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + + if ( ctx_data->location_assigned) { + sieve_argument_validate_error(valdtr, *arg, + "include: cannot use location tags ':personal' and ':global' " + "multiple times"); + return FALSE; + } + + if ( sieve_argument_is(*arg, include_personal_tag) ) + ctx_data->location = EXT_INCLUDE_LOCATION_PERSONAL; + else if ( sieve_argument_is(*arg, include_global_tag) ) + ctx_data->location = EXT_INCLUDE_LOCATION_GLOBAL; + else + return FALSE; + + ctx_data->location_assigned = TRUE; + + /* Delete this tag (for now) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + +static bool cmd_include_validate_boolean_tag +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + + if ( sieve_argument_is(*arg, include_once_tag) ) + ctx_data->flags |= EXT_INCLUDE_FLAG_ONCE; + else + ctx_data->flags |= EXT_INCLUDE_FLAG_OPTIONAL; + + /* Delete this tag (for now) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_include_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_personal_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_global_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_once_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, &include_optional_tag, 0); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_include_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), struct cmd_include_context_data, 1); + ctx_data->location = EXT_INCLUDE_LOCATION_PERSONAL; + cmd->data = ctx_data; + + return TRUE; +} + +static bool cmd_include_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + struct sieve_storage *storage; + struct sieve_script *script; + const char *script_name; + enum sieve_error error = SIEVE_ERROR_NONE; + int ret; + + /* Check argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) ) + return FALSE; + + /* + * Variables are not allowed. + */ + if ( !sieve_argument_is_string_literal(arg) ) { + sieve_argument_validate_error(valdtr, arg, + "the include command requires a constant string for its value argument"); + return FALSE; + } + + /* Find the script */ + + script_name = sieve_ast_argument_strc(arg); + + if ( !sieve_script_name_is_valid(script_name) ) { + sieve_argument_validate_error(valdtr, arg, + "include: invalid script name '%s'", + str_sanitize(script_name, 80)); + return FALSE; + } + + storage = ext_include_get_script_storage + (this_ext, ctx_data->location, script_name, &error); + if ( storage == NULL ) { + // FIXME: handle ':optional' in this case + if (error == SIEVE_ERROR_NOT_FOUND) { + sieve_argument_validate_error(valdtr, arg, + "include: %s location for included script `%s' is unavailable " + "(contact system administrator for more information)", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + } else { + sieve_argument_validate_error(valdtr, arg, + "include: failed to access %s location for included script `%s' " + "(contact system administrator for more information)", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + } + return FALSE; + } + + /* Create script object */ + script = sieve_storage_get_script + (storage, script_name, &error); + if ( script == NULL ) + return FALSE; + + ret = sieve_script_open(script, &error); + if ( ret < 0 ) { + if ( error != SIEVE_ERROR_NOT_FOUND ) { + sieve_argument_validate_error(valdtr, arg, + "failed to access included %s script '%s': %s", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80), + sieve_script_get_last_error_lcase(script)); + sieve_script_unref(&script); + return FALSE; + + /* Not found */ + } else { + enum sieve_compile_flags cpflags = + sieve_validator_compile_flags(valdtr); + + if ( (ctx_data->flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0 ) { + /* :optional */ + + } else if ( (cpflags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 ) { + /* Script is being uploaded */ + sieve_argument_validate_warning(valdtr, arg, + "included %s script '%s' does not exist (ignored during upload)", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + ctx_data->flags |= EXT_INCLUDE_FLAG_MISSING_AT_UPLOAD; + + } else { + /* Should have existed */ + sieve_argument_validate_error(valdtr, arg, + "included %s script '%s' does not exist", + ext_include_script_location_name(ctx_data->location), + str_sanitize(script_name, 80)); + sieve_script_unref(&script); + return FALSE; + } + } + } + + ext_include_ast_link_included_script(cmd->ext, cmd->ast_node->ast, script); + ctx_data->script = script; + + (void)sieve_ast_arguments_detach(arg, 1); + return TRUE; +} + +/* + * Code Generation + */ + +static bool cmd_include_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + const struct ext_include_script_info *included; + int ret; + + /* Compile (if necessary) and include the script into the binary. + * This yields the id of the binary block containing the compiled byte code. + */ + if ( (ret=ext_include_generate_include + (cgenv, cmd, ctx_data->location, ctx_data->flags, ctx_data->script, + &included)) < 0 ) + return FALSE; + + if ( ret > 0 ) { + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation); + (void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); + (void)sieve_binary_emit_byte(cgenv->sblock, ctx_data->flags); + } + + return TRUE; +} + +/* + * Code dump + */ + +static bool opc_include_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct ext_include_script_info *included; + struct ext_include_binary_context *binctx; + unsigned int include_id, flags; + + sieve_code_dumpf(denv, "INCLUDE:"); + + sieve_code_mark(denv); + if ( !sieve_binary_read_unsigned(denv->sblock, address, &include_id) ) + return FALSE; + + if ( !sieve_binary_read_byte(denv->sblock, address, &flags) ) + return FALSE; + + binctx = ext_include_binary_get_context(denv->oprtn->ext, denv->sbin); + included = ext_include_binary_script_get_included(binctx, include_id); + if ( included == NULL ) + return FALSE; + + sieve_code_descend(denv); + sieve_code_dumpf(denv, "script: `%s' from %s %s%s[ID: %d, BLOCK: %d]", + sieve_script_name(included->script), sieve_script_location(included->script), + ((flags & EXT_INCLUDE_FLAG_ONCE) != 0 ? "(once) " : ""), + ((flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0 ? "(optional) " : ""), + include_id, sieve_binary_block_get_id(included->block)); + + return TRUE; +} + +/* + * Execution + */ + +static int opc_include_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + unsigned int include_id, flags; + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &include_id) ) { + sieve_runtime_trace_error(renv, "invalid include-id operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &flags) ) { + sieve_runtime_trace_error(renv, "invalid flags operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return ext_include_execute_include + (renv, include_id, (enum ext_include_flags)flags); +} + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/cmd-return.c b/pigeonhole/src/lib-sieve/plugins/include/cmd-return.c new file mode 100644 index 0000000..65a156d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/cmd-return.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-include-common.h" + +/* + * Return command + * + * Syntax + * return + */ + +static bool cmd_return_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_return = { + .identifier = "return", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .generate = cmd_return_generate +}; + +/* + * Return operation + */ + +static int opc_return_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def return_operation = { + .mnemonic = "RETURN", + .ext_def = &include_extension, + .code = EXT_INCLUDE_OPERATION_RETURN, + .execute = opc_return_execute +}; + +/* + * Code generation + */ + +static bool cmd_return_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &return_operation); + + return TRUE; +} + +/* + * Execution + */ + +static int opc_return_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + ext_include_execute_return(renv); + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.c new file mode 100644 index 0000000..3711c30 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.c @@ -0,0 +1,492 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-storage.h" +#include "sieve-binary.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-limits.h" +#include "ext-include-variables.h" +#include "ext-include-binary.h" + +/* + * Forward declarations + */ + +static bool ext_include_binary_pre_save + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_error *error_r); +static bool ext_include_binary_open + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context); +static bool ext_include_binary_up_to_date + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context, enum sieve_compile_flags cpflags); +static void ext_include_binary_free + (const struct sieve_extension *ext, struct sieve_binary *sbin, + void *context); + +/* + * Binary include extension + */ + +const struct sieve_binary_extension include_binary_ext = { + .extension = &include_extension, + .binary_pre_save = ext_include_binary_pre_save, + .binary_open = ext_include_binary_open, + .binary_free = ext_include_binary_free, + .binary_up_to_date = ext_include_binary_up_to_date +}; + +/* + * Binary context management + */ + +struct ext_include_binary_context { + struct sieve_binary *binary; + struct sieve_binary_block *dependency_block; + + HASH_TABLE(struct sieve_script *, + struct ext_include_script_info *) included_scripts; + ARRAY(struct ext_include_script_info *) include_index; + + struct sieve_variable_scope_binary *global_vars; + + bool outdated:1; +}; + +static struct ext_include_binary_context *ext_include_binary_create_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + pool_t pool = sieve_binary_pool(sbin); + + struct ext_include_binary_context *ctx = + p_new(pool, struct ext_include_binary_context, 1); + + ctx->binary = sbin; + hash_table_create(&ctx->included_scripts, pool, 0, + sieve_script_hash, sieve_script_cmp); + p_array_init(&ctx->include_index, pool, 128); + + sieve_binary_extension_set(sbin, this_ext, &include_binary_ext, ctx); + + return ctx; +} + +struct ext_include_binary_context *ext_include_binary_get_context +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + struct ext_include_binary_context *ctx = (struct ext_include_binary_context *) + sieve_binary_extension_get_context(sbin, this_ext); + + if ( ctx == NULL ) + ctx = ext_include_binary_create_context(this_ext, sbin); + + return ctx; +} + +struct ext_include_binary_context *ext_include_binary_init +(const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast) +{ + struct ext_include_ast_context *ast_ctx = + ext_include_get_ast_context(this_ext, ast); + struct ext_include_binary_context *ctx; + + /* Get/create our context from the binary we are working on */ + ctx = ext_include_binary_get_context(this_ext, sbin); + + /* Create dependency block */ + if ( ctx->dependency_block == 0 ) + ctx->dependency_block = + sieve_binary_extension_create_block(sbin, this_ext); + + if ( ctx->global_vars == NULL ) { + ctx->global_vars = + sieve_variable_scope_binary_create(ast_ctx->global_vars); + sieve_variable_scope_binary_ref(ctx->global_vars); + } + + return ctx; +} + +/* + * Script inclusion + */ + +struct ext_include_script_info *ext_include_binary_script_include +(struct ext_include_binary_context *binctx, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, struct sieve_binary_block *inc_block) +{ + pool_t pool = sieve_binary_pool(binctx->binary); + struct ext_include_script_info *incscript; + + incscript = p_new(pool, struct ext_include_script_info, 1); + incscript->id = array_count(&binctx->include_index)+1; + incscript->location = location; + incscript->flags = flags; + incscript->script = script; + incscript->block = inc_block; + + /* Unreferenced on binary_free */ + sieve_script_ref(script); + + hash_table_insert(binctx->included_scripts, script, incscript); + array_append(&binctx->include_index, &incscript, 1); + + return incscript; +} + +struct ext_include_script_info *ext_include_binary_script_get_include_info +(struct ext_include_binary_context *binctx, struct sieve_script *script) +{ + struct ext_include_script_info *incscript = + hash_table_lookup(binctx->included_scripts, script); + + return incscript; +} + +const struct ext_include_script_info *ext_include_binary_script_get_included +(struct ext_include_binary_context *binctx, unsigned int include_id) +{ + if ( include_id > 0 && + (include_id - 1) < array_count(&binctx->include_index) ) { + struct ext_include_script_info *const *sinfo = + array_idx(&binctx->include_index, include_id - 1); + + return *sinfo; + } + + return NULL; +} + +const struct ext_include_script_info *ext_include_binary_script_get +(struct ext_include_binary_context *binctx, struct sieve_script *script) +{ + return hash_table_lookup(binctx->included_scripts, script); +} + +unsigned int ext_include_binary_script_get_count +(struct ext_include_binary_context *binctx) +{ + return array_count(&binctx->include_index); +} + +/* + * Variables + */ + +struct sieve_variable_scope_binary *ext_include_binary_get_global_scope +(const struct sieve_extension *this_ext, struct sieve_binary *sbin) +{ + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(this_ext, sbin); + + return binctx->global_vars; +} + +/* + * Binary extension + */ + +static bool ext_include_binary_pre_save +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context, + enum sieve_error *error_r) +{ + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + struct ext_include_script_info *const *scripts; + struct sieve_binary_block *sblock = binctx->dependency_block; + unsigned int script_count, i; + bool result = TRUE; + + sieve_binary_block_clear(sblock); + + scripts = array_get(&binctx->include_index, &script_count); + + sieve_binary_emit_unsigned(sblock, script_count); + + for ( i = 0; i < script_count; i++ ) { + struct ext_include_script_info *incscript = scripts[i]; + + if ( incscript->block != NULL ) { + sieve_binary_emit_unsigned + (sblock, sieve_binary_block_get_id(incscript->block)); + } else { + sieve_binary_emit_unsigned(sblock, 0); + } + sieve_binary_emit_byte(sblock, incscript->location); + sieve_binary_emit_cstring(sblock, sieve_script_name(incscript->script)); + sieve_binary_emit_byte(sblock, incscript->flags); + sieve_script_binary_write_metadata(incscript->script, sblock); + } + + result = ext_include_variables_save(sblock, binctx->global_vars, error_r); + + return result; +} + +static bool ext_include_binary_open +(const struct sieve_extension *ext, struct sieve_binary *sbin, void *context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_include_context *ext_ctx = + (struct ext_include_context *)ext->context; + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + struct sieve_binary_block *sblock; + unsigned int depcount, i, block_id; + sieve_size_t offset; + + sblock = sieve_binary_extension_get_block(sbin, ext); + block_id = sieve_binary_block_get_id(sblock); + + offset = 0; + + if ( !sieve_binary_read_unsigned(sblock, &offset, &depcount) ) { + e_error(svinst->event, + "include: failed to read include count " + "for dependency block %d of binary %s", block_id, + sieve_binary_path(sbin)); + return FALSE; + } + + /* Check include limit */ + if ( depcount > ext_ctx->max_includes ) { + e_error(svinst->event, + "include: binary %s includes too many scripts (%u > %u)", + sieve_binary_path(sbin), depcount, ext_ctx->max_includes); + return FALSE; + } + + /* Read dependencies */ + for ( i = 0; i < depcount; i++ ) { + unsigned int inc_block_id; + struct sieve_binary_block *inc_block = NULL; + unsigned int location, flags; + string_t *script_name; + struct sieve_storage *storage; + struct sieve_script *script; + enum sieve_error error; + int ret; + + if ( + !sieve_binary_read_unsigned(sblock, &offset, &inc_block_id) || + !sieve_binary_read_byte(sblock, &offset, &location) || + !sieve_binary_read_string(sblock, &offset, &script_name) || + !sieve_binary_read_byte(sblock, &offset, &flags) ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, + "include: failed to read included script " + "from dependency block %d of binary %s", + block_id, sieve_binary_path(sbin)); + return FALSE; + } + + if ( inc_block_id != 0 && + (inc_block=sieve_binary_block_get(sbin, inc_block_id)) == NULL ) { + e_error(svinst->event, + "include: failed to find block %d for included script " + "from dependency block %d of binary %s", + inc_block_id, block_id, + sieve_binary_path(sbin)); + return FALSE; + } + + if ( location >= EXT_INCLUDE_LOCATION_INVALID ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, + "include: dependency block %d of binary %s " + "uses invalid script location (id %d)", + block_id, sieve_binary_path(sbin), location); + return FALSE; + } + + /* Can we find the script dependency ? */ + storage = ext_include_get_script_storage + (ext, location, str_c(script_name), &error); + if ( storage == NULL ) { + /* No, recompile */ + // FIXME: handle ':optional' in this case + return FALSE; + } + + /* Can we open the script dependency ? */ + script = sieve_storage_get_script + (storage, str_c(script_name), &error); + if ( script == NULL ) { + /* No, recompile */ + return FALSE; + } + if ( sieve_script_open(script, &error) < 0 ) { + if ( error != SIEVE_ERROR_NOT_FOUND ) { + /* No, recompile */ + return FALSE; + } + + if ( (flags & EXT_INCLUDE_FLAG_OPTIONAL) == 0 ) { + /* Not supposed to be missing, recompile */ + if ( svinst->debug ) { + e_debug(svinst->event, "include: " + "script '%s' included in binary %s is missing, " + "so recompile", + str_c(script_name), + sieve_binary_path(sbin)); + } + return FALSE; + } + + } else if (inc_block == NULL) { + /* Script exists, but it is missing from the binary, recompile no matter + * what. + */ + if ( svinst->debug ) { + e_debug(svinst->event, "include: " + "script '%s' is missing in binary %s, but is now available, " + "so recompile", str_c(script_name), sieve_binary_path(sbin)); + } + sieve_script_unref(&script); + return FALSE; + } + + /* Can we read script metadata ? */ + if ( (ret=sieve_script_binary_read_metadata + (script, sblock, &offset)) < 0 ) { + /* Binary is corrupt, recompile */ + e_error(svinst->event, "include: " + "dependency block %d of binary %s " + "contains invalid script metadata for script %s", + block_id, sieve_binary_path(sbin), + sieve_script_location(script)); + sieve_script_unref(&script); + return FALSE; + } + + if ( ret == 0 ) + binctx->outdated = TRUE; + + (void)ext_include_binary_script_include + (binctx, location, flags, script, inc_block); + + sieve_script_unref(&script); + } + + if ( !ext_include_variables_load + (ext, sblock, &offset, &binctx->global_vars) ) + return FALSE; + + return TRUE; +} + +static bool ext_include_binary_up_to_date +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context, + enum sieve_compile_flags cpflags ATTR_UNUSED) +{ + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + + return !binctx->outdated; +} + +static void ext_include_binary_free +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context) +{ + struct ext_include_binary_context *binctx = + (struct ext_include_binary_context *) context; + struct hash_iterate_context *hctx; + struct sieve_script *script; + struct ext_include_script_info *incscript; + + /* Release references to all included script objects */ + hctx = hash_table_iterate_init(binctx->included_scripts); + while ( hash_table_iterate + (hctx, binctx->included_scripts, &script, &incscript) ) + sieve_script_unref(&incscript->script); + hash_table_iterate_deinit(&hctx); + + hash_table_destroy(&binctx->included_scripts); + + if ( binctx->global_vars != NULL ) + sieve_variable_scope_binary_unref(&binctx->global_vars); +} + +/* + * Dumping the binary + */ + +bool ext_include_binary_dump +(const struct sieve_extension *ext, struct sieve_dumptime_env *denv) +{ + struct sieve_binary *sbin = denv->sbin; + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(ext, sbin); + struct hash_iterate_context *hctx; + struct sieve_script *script; + struct ext_include_script_info *incscript; + + if ( !ext_include_variables_dump(denv, binctx->global_vars) ) + return FALSE; + + hctx = hash_table_iterate_init(binctx->included_scripts); + while ( hash_table_iterate + (hctx, binctx->included_scripts, &script, &incscript) ) { + + if ( incscript->block == NULL ) { + sieve_binary_dump_sectionf(denv, "Included %s script '%s' (MISSING)", + ext_include_script_location_name(incscript->location), + sieve_script_name(incscript->script)); + + } else { + unsigned int block_id = sieve_binary_block_get_id(incscript->block); + + sieve_binary_dump_sectionf(denv, "Included %s script '%s' (block: %d)", + ext_include_script_location_name(incscript->location), + sieve_script_name(incscript->script), block_id); + + denv->sblock = incscript->block; + denv->cdumper = sieve_code_dumper_create(denv); + + if ( denv->cdumper == NULL ) + return FALSE; + + sieve_code_dumper_run(denv->cdumper); + sieve_code_dumper_free(&(denv->cdumper)); + } + } + hash_table_iterate_deinit(&hctx); + + return TRUE; +} + +bool ext_include_code_dump +(const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED) +{ + struct sieve_binary *sbin = denv->sbin; + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(ext, sbin); + struct ext_include_context *ectx = ext_include_get_context(ext); + + sieve_ext_variables_dump_set_scope + (ectx->var_ext, denv, ext, + sieve_variable_scope_binary_get(binctx->global_vars)); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.h new file mode 100644 index 0000000..066df2f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-binary.h @@ -0,0 +1,64 @@ +#ifndef EXT_INCLUDE_BINARY_H +#define EXT_INCLUDE_BINARY_H + +#include "sieve-common.h" + +/* + * Binary context management + */ + +struct ext_include_binary_context; + +struct ext_include_binary_context *ext_include_binary_init + (const struct sieve_extension *this_ext, struct sieve_binary *sbin, + struct sieve_ast *ast); +struct ext_include_binary_context *ext_include_binary_get_context + (const struct sieve_extension *this_ext, struct sieve_binary *sbin); + +/* + * Variables + */ + +struct sieve_variable_scope_binary *ext_include_binary_get_global_scope + (const struct sieve_extension *this_ext, struct sieve_binary *sbin); + +/* + * Including scripts + */ + +struct ext_include_script_info { + unsigned int id; + + struct sieve_script *script; + enum ext_include_flags flags; + enum ext_include_script_location location; + + struct sieve_binary_block *block; +}; + +struct ext_include_script_info *ext_include_binary_script_include + (struct ext_include_binary_context *binctx, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, struct sieve_binary_block *inc_block); +struct ext_include_script_info *ext_include_binary_script_get_include_info + (struct ext_include_binary_context *binctx, struct sieve_script *script); + +const struct ext_include_script_info *ext_include_binary_script_get_included + (struct ext_include_binary_context *binctx, unsigned int include_id); +const struct ext_include_script_info *ext_include_binary_script_get + (struct ext_include_binary_context *binctx, struct sieve_script *script); +unsigned int ext_include_binary_script_get_count + (struct ext_include_binary_context *binctx); + +/* + * Dumping the binary + */ + +bool ext_include_binary_dump + (const struct sieve_extension *ext, struct sieve_dumptime_env *denv); +bool ext_include_code_dump + (const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED); + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c new file mode 100644 index 0000000..7af3f00 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.c @@ -0,0 +1,892 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str-sanitize.h" +#include "home-expand.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-storage.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-include-common.h" +#include "ext-include-limits.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + + +/* + * Forward declarations + */ + +/* Generator context */ + +struct ext_include_generator_context { + unsigned int nesting_depth; + struct sieve_script *script; + struct ext_include_generator_context *parent; +}; + +static inline struct ext_include_generator_context * +ext_include_get_generator_context(const struct sieve_extension *ext_this, + struct sieve_generator *gentr); + +/* Interpreter context */ + +struct ext_include_interpreter_global { + ARRAY(struct sieve_script *) included_scripts; + + struct sieve_variable_scope_binary *var_scope; + struct sieve_variable_storage *var_storage; +}; + +struct ext_include_interpreter_context { + struct ext_include_interpreter_context *parent; + struct ext_include_interpreter_global *global; + + struct sieve_interpreter *interp; + pool_t pool; + + unsigned int nesting_depth; + + struct sieve_script *script; + const struct ext_include_script_info *script_info; + + const struct ext_include_script_info *include; + bool returned; +}; + +/* + * Extension configuration + */ + +/* Extension hooks */ + +bool ext_include_load(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_include_context *ctx; + const char *location; + unsigned long long int uint_setting; + + if (*context != NULL) + ext_include_unload(ext); + + ctx = i_new(struct ext_include_context, 1); + + /* Get location for :global scripts */ + location = sieve_setting_get(svinst, "sieve_global"); + if (location == NULL) + location = sieve_setting_get(svinst, "sieve_global_dir"); + + if (location == NULL) { + e_debug(svinst->event, "include: " + "sieve_global is not set; " + "it is currently not possible to include `:global' scripts."); + } + + ctx->global_location = i_strdup(location); + + /* Get limits */ + ctx->max_nesting_depth = EXT_INCLUDE_DEFAULT_MAX_NESTING_DEPTH; + ctx->max_includes = EXT_INCLUDE_DEFAULT_MAX_INCLUDES; + + if (sieve_setting_get_uint_value( + svinst, "sieve_include_max_nesting_depth", &uint_setting)) + ctx->max_nesting_depth = (unsigned int)uint_setting; + if (sieve_setting_get_uint_value( + svinst, "sieve_include_max_includes", &uint_setting)) + ctx->max_includes = (unsigned int)uint_setting; + + /* Extension dependencies */ + ctx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + + *context = (void *)ctx; + return TRUE; +} + +void ext_include_unload(const struct sieve_extension *ext) +{ + struct ext_include_context *ctx = + (struct ext_include_context *)ext->context; + + if (ctx->global_storage != NULL) + sieve_storage_unref(&ctx->global_storage); + if (ctx->personal_storage != NULL) + sieve_storage_unref(&ctx->personal_storage); + + i_free(ctx->global_location); + i_free(ctx); +} + +/* + * Script access + */ + +struct sieve_storage * +ext_include_get_script_storage(const struct sieve_extension *ext, + enum ext_include_script_location location, + const char *script_name, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_include_context *ctx = + (struct ext_include_context *)ext->context; + + switch (location) { + case EXT_INCLUDE_LOCATION_PERSONAL: + if (ctx->personal_storage == NULL) { + ctx->personal_storage = + sieve_storage_create_main(svinst, NULL, 0, + error_r); + } + return ctx->personal_storage; + case EXT_INCLUDE_LOCATION_GLOBAL: + if (ctx->global_location == NULL) { + e_info(svinst->event, "include: " + "sieve_global is unconfigured; " + "include of `:global' script `%s' is therefore not possible", + str_sanitize(script_name, 80)); + if (error_r != NULL) + *error_r = SIEVE_ERROR_NOT_FOUND; + return NULL; + } + if (ctx->global_storage == NULL) { + ctx->global_storage = sieve_storage_create( + svinst, ctx->global_location, 0, error_r); + } + return ctx->global_storage; + default: + break; + } + + i_unreached(); + return NULL; +} + +/* + * AST context management + */ + +static void +ext_include_ast_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_ast *ast ATTR_UNUSED, void *context) +{ + struct ext_include_ast_context *actx = + (struct ext_include_ast_context *)context; + struct sieve_script **scripts; + unsigned int count, i; + + /* Unreference included scripts */ + scripts = array_get_modifiable(&actx->included_scripts, &count); + for (i = 0; i < count; i++) { + sieve_script_unref(&scripts[i]); + } + + /* Unreference variable scopes */ + if (actx->global_vars != NULL) + sieve_variable_scope_unref(&actx->global_vars); +} + +static const struct sieve_ast_extension include_ast_extension = { + &include_extension, + ext_include_ast_free +}; + +struct ext_include_ast_context * +ext_include_create_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast, struct sieve_ast *parent) +{ + struct ext_include_ast_context *actx; + + pool_t pool = sieve_ast_pool(ast); + actx = p_new(pool, struct ext_include_ast_context, 1); + p_array_init(&actx->included_scripts, pool, 32); + + if (parent != NULL) { + struct ext_include_ast_context *parent_ctx = + (struct ext_include_ast_context *) + sieve_ast_extension_get_context(parent, this_ext); + + actx->global_vars = parent_ctx->global_vars; + i_assert(actx->global_vars != NULL); + + sieve_variable_scope_ref(actx->global_vars); + } else { + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + + actx->global_vars = sieve_variable_scope_create( + this_ext->svinst, ectx->var_ext, this_ext); + } + + sieve_ast_extension_register(ast, this_ext, &include_ast_extension, + (void *)actx); + return actx; +} + +struct ext_include_ast_context * +ext_include_get_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast) +{ + struct ext_include_ast_context *actx = + (struct ext_include_ast_context *) + sieve_ast_extension_get_context(ast, this_ext); + + if (actx != NULL) + return actx; + return ext_include_create_ast_context(this_ext, ast, NULL); +} + +void ext_include_ast_link_included_script( + const struct sieve_extension *this_ext, struct sieve_ast *ast, + struct sieve_script *script) +{ + struct ext_include_ast_context *actx = + ext_include_get_ast_context(this_ext, ast); + + array_append(&actx->included_scripts, &script, 1); +} + +bool ext_include_validator_have_variables( + const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + return sieve_ext_variables_is_active(ectx->var_ext, valdtr); +} + +/* + * Generator context management + */ + +static struct ext_include_generator_context * +ext_include_create_generator_context( + struct sieve_generator *gentr, + struct ext_include_generator_context *parent, + struct sieve_script *script) +{ + struct ext_include_generator_context *ctx; + + pool_t pool = sieve_generator_pool(gentr); + ctx = p_new(pool, struct ext_include_generator_context, 1); + ctx->parent = parent; + ctx->script = script; + if (parent == NULL) + ctx->nesting_depth = 0; + else + ctx->nesting_depth = parent->nesting_depth + 1; + + return ctx; +} + +static inline struct ext_include_generator_context * +ext_include_get_generator_context(const struct sieve_extension *this_ext, + struct sieve_generator *gentr) +{ + return (struct ext_include_generator_context *) + sieve_generator_extension_get_context(gentr, this_ext); +} + +static inline void +ext_include_initialize_generator_context( + const struct sieve_extension *this_ext, struct sieve_generator *gentr, + struct ext_include_generator_context *parent, + struct sieve_script *script) +{ + sieve_generator_extension_set_context( + gentr, this_ext, + ext_include_create_generator_context(gentr, parent, script)); +} + +void ext_include_register_generator_context( + const struct sieve_extension *this_ext, + const struct sieve_codegen_env *cgenv) +{ + struct ext_include_generator_context *ctx = + ext_include_get_generator_context(this_ext, cgenv->gentr); + + /* Initialize generator context if necessary */ + if (ctx == NULL) { + ctx = ext_include_create_generator_context( + cgenv->gentr, NULL, cgenv->script); + + sieve_generator_extension_set_context( + cgenv->gentr, this_ext, (void *)ctx); + } + + /* Initialize ast context if necessary */ + (void)ext_include_get_ast_context(this_ext, cgenv->ast); + (void)ext_include_binary_init(this_ext, cgenv->sbin, cgenv->ast); +} + +/* + * Runtime initialization + */ + +static int +ext_include_runtime_init(const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred ATTR_UNUSED) +{ + struct ext_include_interpreter_context *ctx = + (struct ext_include_interpreter_context *)context; + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + if (ctx->parent == NULL) { + ctx->global = p_new(ctx->pool, + struct ext_include_interpreter_global, 1); + p_array_init(&ctx->global->included_scripts, ctx->pool, 10); + + ctx->global->var_scope = + ext_include_binary_get_global_scope( + this_ext, renv->sbin); + ctx->global->var_storage = + sieve_variable_storage_create(ectx->var_ext, ctx->pool, + ctx->global->var_scope); + } else { + ctx->global = ctx->parent->global; + } + + sieve_ext_variables_runtime_set_storage(ectx->var_ext, renv, this_ext, + ctx->global->var_storage); + return SIEVE_EXEC_OK; +} + +static struct sieve_interpreter_extension include_interpreter_extension = { + .ext_def = &include_extension, + .run = ext_include_runtime_init +}; + +/* + * Interpreter context management + */ + +static struct ext_include_interpreter_context * +ext_include_interpreter_context_create( + struct sieve_interpreter *interp, + struct ext_include_interpreter_context *parent, + struct sieve_script *script, + const struct ext_include_script_info *sinfo) +{ + struct ext_include_interpreter_context *ctx; + + pool_t pool = sieve_interpreter_pool(interp); + ctx = p_new(pool, struct ext_include_interpreter_context, 1); + ctx->pool = pool; + ctx->parent = parent; + ctx->interp = interp; + ctx->script = script; + ctx->script_info = sinfo; + + if (parent == NULL) + ctx->nesting_depth = 0; + else + ctx->nesting_depth = parent->nesting_depth + 1; + return ctx; +} + +static inline struct ext_include_interpreter_context * +ext_include_get_interpreter_context(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + return (struct ext_include_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); +} + +static inline struct ext_include_interpreter_context * +ext_include_interpreter_context_init_child( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp, + struct ext_include_interpreter_context *parent, + struct sieve_script *script, + const struct ext_include_script_info *sinfo) +{ + struct ext_include_interpreter_context *ctx = + ext_include_interpreter_context_create(interp, parent, + script, sinfo); + + sieve_interpreter_extension_register(interp, this_ext, + &include_interpreter_extension, + ctx); + return ctx; +} + +void ext_include_interpreter_context_init( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_include_interpreter_context *ctx = + ext_include_get_interpreter_context(this_ext, interp); + + /* Is this is the top-level interpreter ? */ + if (ctx == NULL) { + struct sieve_script *script; + + /* Initialize top context */ + script = sieve_interpreter_script(interp); + ctx = ext_include_interpreter_context_create(interp, NULL, + script, NULL); + + sieve_interpreter_extension_register( + interp, this_ext, &include_interpreter_extension, + (void *)ctx); + } +} + +struct sieve_variable_storage * +ext_include_interpreter_get_global_variables( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_include_interpreter_context *ctx = + ext_include_get_interpreter_context(this_ext, interp); + + return ctx->global->var_storage; +} + +/* + * Including a script during code generation + */ + +int ext_include_generate_include( + const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, + const struct ext_include_script_info **included_r) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct ext_include_context *ext_ctx = + (struct ext_include_context *)this_ext->context; + int result = 1; + struct sieve_ast *ast; + struct sieve_binary *sbin = cgenv->sbin; + struct sieve_generator *gentr = cgenv->gentr; + struct ext_include_binary_context *binctx; + struct sieve_generator *subgentr; + struct ext_include_generator_context *ctx = + ext_include_get_generator_context(this_ext, gentr); + struct ext_include_generator_context *pctx; + struct sieve_error_handler *ehandler = + sieve_generator_error_handler(gentr); + struct ext_include_script_info *included; + + *included_r = NULL; + + /* Just to be sure: do not include more scripts when errors have occured + already. + */ + if (sieve_get_errors(ehandler) > 0) + return -1; + + /* Limit nesting level */ + if (ctx->nesting_depth >= ext_ctx->max_nesting_depth) { + sieve_command_generate_error( + gentr, cmd, + "cannot nest includes deeper than %d levels", + ext_ctx->max_nesting_depth); + return -1; + } + + /* Check for circular include */ + if ((flags & EXT_INCLUDE_FLAG_ONCE) == 0) { + pctx = ctx; + while (pctx != NULL) { + if (sieve_script_equals(pctx->script, script)) { + /* Just drop circular include when uploading + inactive script; not an error + */ + if ((cgenv->flags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 && + (cgenv->flags & SIEVE_COMPILE_FLAG_ACTIVATED) == 0) { + sieve_command_generate_warning( + gentr, cmd, + "circular include (ignored during upload)"); + return 0; + } + + sieve_command_generate_error(gentr, cmd, + "circular include"); + return -1; + } + + pctx = pctx->parent; + } + } + + /* Get binary context */ + binctx = ext_include_binary_init(this_ext, sbin, cgenv->ast); + + /* Is the script already compiled into the current binary? */ + included = ext_include_binary_script_get_include_info(binctx, script); + if (included != NULL) { + /* Yes, only update flags */ + if ((flags & EXT_INCLUDE_FLAG_OPTIONAL) == 0) + included->flags &= ENUM_NEGATE(EXT_INCLUDE_FLAG_OPTIONAL); + if ((flags & EXT_INCLUDE_FLAG_ONCE) == 0) + included->flags &= ENUM_NEGATE(EXT_INCLUDE_FLAG_ONCE); + } else { + const char *script_name = sieve_script_name(script); + enum sieve_compile_flags cpflags = cgenv->flags; + + /* No, include new script */ + + /* Check whether include limit is exceeded */ + if (ext_include_binary_script_get_count(binctx) >= + ext_ctx->max_includes) { + sieve_command_generate_error( + gentr, cmd, "failed to include script '%s': " + "no more than %u includes allowed", + str_sanitize(script_name, 80), + ext_ctx->max_includes); + return -1; + } + + /* Allocate a new block in the binary and mark the script as + included. */ + if (!sieve_script_is_open(script)) { + /* Just making an empty entry to mark a missing script + */ + i_assert((flags & EXT_INCLUDE_FLAG_MISSING_AT_UPLOAD) != 0 || + (flags & EXT_INCLUDE_FLAG_OPTIONAL) != 0); + included = ext_include_binary_script_include( + binctx, location, flags, script, NULL); + result = 0; + + } else { + struct sieve_binary_block *inc_block = + sieve_binary_block_create(sbin); + + /* Real include */ + included = ext_include_binary_script_include( + binctx, location, flags, script, inc_block); + + /* Parse */ + if ((ast = sieve_parse(script, ehandler, + NULL)) == NULL) { + sieve_command_generate_error( + gentr, cmd, + "failed to parse included script '%s'", + str_sanitize(script_name, 80)); + return -1; + } + + /* Included scripts inherit global variable scope */ + (void)ext_include_create_ast_context( + this_ext, ast, cmd->ast_node->ast); + + if (location == EXT_INCLUDE_LOCATION_GLOBAL) { + cpflags &= + ENUM_NEGATE(SIEVE_EXECUTE_FLAG_NOGLOBAL); + } else { + cpflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + } + + /* Validate */ + if (!sieve_validate(ast, ehandler, cpflags, NULL)) { + sieve_command_generate_error( + gentr, cmd, + "failed to validate included script '%s'", + str_sanitize(script_name, 80)); + sieve_ast_unref(&ast); + return -1; + } + + /* Generate + + FIXME: It might not be a good idea to recurse code + generation for included scripts. + */ + subgentr = sieve_generator_create(ast, ehandler, cpflags); + ext_include_initialize_generator_context( + cmd->ext, subgentr, ctx, script); + + if (sieve_generator_run(subgentr, &inc_block) == NULL) { + sieve_command_generate_error( + gentr, cmd, + "failed to generate code for included script '%s'", + str_sanitize(script_name, 80)); + result = -1; + } + + sieve_generator_free(&subgentr); + + /* Cleanup */ + sieve_ast_unref(&ast); + } + } + + if (result > 0) + *included_r = included; + return result; +} + +/* + * Executing an included script during interpretation + */ + +static bool +ext_include_runtime_check_circular( + struct ext_include_interpreter_context *ctx, + const struct ext_include_script_info *include) +{ + struct ext_include_interpreter_context *pctx; + + pctx = ctx; + while (pctx != NULL) { + + if (sieve_script_equals(include->script, pctx->script)) + return TRUE; + + pctx = pctx->parent; + } + + return FALSE; +} + +static bool +ext_include_runtime_include_mark(struct ext_include_interpreter_context *ctx, + const struct ext_include_script_info *include, + bool once) +{ + struct sieve_script *const *includes; + unsigned int count, i; + + includes = array_get(&ctx->global->included_scripts, &count); + for (i = 0; i < count; i++) { + if (sieve_script_equals(include->script, includes[i])) + return (!once); + } + + array_append(&ctx->global->included_scripts, &include->script, 1); + return TRUE; +} + +int ext_include_execute_include(const struct sieve_runtime_env *renv, + unsigned int include_id, + enum ext_include_flags flags) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + int result = SIEVE_EXEC_OK; + struct ext_include_interpreter_context *ctx; + const struct ext_include_script_info *included; + struct ext_include_binary_context *binctx = + ext_include_binary_get_context(this_ext, renv->sbin); + bool once = ((flags & EXT_INCLUDE_FLAG_ONCE) != 0); + unsigned int block_id; + + /* Check for invalid include id (== corrupt binary) */ + included = ext_include_binary_script_get_included(binctx, include_id); + if (included == NULL) { + sieve_runtime_trace_error( + renv, "include: include id %d is invalid", include_id); + return SIEVE_EXEC_BIN_CORRUPT; + } + + ctx = ext_include_get_interpreter_context(this_ext, renv->interp); + block_id = sieve_binary_block_get_id(included->block); + + /* If :once modifier is specified, check for duplicate include */ + if (ext_include_runtime_include_mark(ctx, included, once)) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_NONE, + "include: start script '%s' [inc id: %d, block: %d]", + sieve_script_name(included->script), + include_id, block_id); + } else { + /* skip */ + sieve_runtime_trace( + renv, SIEVE_TRLVL_NONE, + "include: skipped include for script '%s' " + "[inc id: %d, block: %d]; already run once", + sieve_script_name(included->script), + include_id, block_id); + return result; + } + + /* Check circular include during interpretation as well. + * Let's not trust binaries. + */ + if (ext_include_runtime_check_circular(ctx, included)) { + sieve_runtime_trace_error(renv, + "include: circular include of script '%s' " + "[inc id: %d, block: %d]", + sieve_script_name(included->script), + include_id, block_id); + + /* Situation has no valid way to emerge at runtime */ + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ctx->parent == NULL) { + struct ext_include_interpreter_context *curctx = NULL; + struct sieve_error_handler *ehandler = renv->ehandler; + struct sieve_interpreter *subinterp; + bool interrupted = FALSE; + + /* We are the top-level interpreter instance */ + if (result == SIEVE_EXEC_OK) { + struct sieve_execute_env eenv_new = *eenv; + + if (included->location != EXT_INCLUDE_LOCATION_GLOBAL) + eenv_new.flags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + else { + eenv_new.flags &= + ENUM_NEGATE(SIEVE_EXECUTE_FLAG_NOGLOBAL); + } + + /* Create interpreter for top-level included script + (first sub-interpreter) + */ + subinterp = sieve_interpreter_create_for_block( + included->block, included->script, renv->interp, + &eenv_new, ehandler); + if (subinterp != NULL) { + curctx = ext_include_interpreter_context_init_child( + this_ext, subinterp, ctx, included->script, + included); + + /* Activate and start the top-level included script */ + result = sieve_interpreter_start( + subinterp, renv->result, &interrupted); + } else { + result = SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Included scripts can have includes of their own. This is not + implemented recursively. Rather, the sub-interpreter + interrupts and defers the include to the top-level + interpreter, which is here. */ + if (result == SIEVE_EXEC_OK && interrupted && + !curctx->returned) { + while (result == SIEVE_EXEC_OK) { + if (((interrupted && curctx->returned) || + (!interrupted)) && + curctx->parent != NULL) { + const struct ext_include_script_info *ended_script = + curctx->script_info; + + /* Sub-interpreter ended or executed + return */ + + /* Ascend interpreter stack */ + curctx = curctx->parent; + sieve_interpreter_free(&subinterp); + + sieve_runtime_trace(renv, SIEVE_TRLVL_NONE, + "include: script '%s' ended " + "[inc id: %d, block: %d]", + sieve_script_name(ended_script->script), + ended_script->id, + sieve_binary_block_get_id(ended_script->block)); + + /* This is the top-most sub-interpreter, + bail out */ + if (curctx->parent == NULL) + break; + + subinterp = curctx->interp; + + /* Continue parent */ + curctx->include = NULL; + curctx->returned = FALSE; + + result = sieve_interpreter_continue( + subinterp, &interrupted); + } else { + if (curctx->include != NULL) { + /* Sub-include requested */ + + if (result == SIEVE_EXEC_OK) { + struct sieve_execute_env eenv_new = *eenv; + + if (curctx->include->location != EXT_INCLUDE_LOCATION_GLOBAL) + eenv_new.flags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + else { + eenv_new.flags &= + ENUM_NEGATE(SIEVE_EXECUTE_FLAG_NOGLOBAL); + } + + /* Create sub-interpreter */ + subinterp = sieve_interpreter_create_for_block( + curctx->include->block, curctx->include->script, + curctx->interp, &eenv_new, ehandler); + if (subinterp != NULL) { + curctx = ext_include_interpreter_context_init_child( + this_ext, subinterp, curctx, + curctx->include->script, curctx->include); + + /* Start the sub-include's interpreter */ + curctx->include = NULL; + curctx->returned = FALSE; + result = sieve_interpreter_start( + subinterp, renv->result, &interrupted); + } else { + result = SIEVE_EXEC_BIN_CORRUPT; + } + } + } else { + /* Sub-interpreter was interrupted outside + this extension, probably stop command was + executed. Generate an interrupt ourselves, + ending all script execution. */ + sieve_interpreter_interrupt(renv->interp); + break; + } + } + } + } + + /* Free any sub-interpreters that might still be active */ + while (curctx != NULL && curctx->parent != NULL) { + struct ext_include_interpreter_context *nextctx = + curctx->parent; + struct sieve_interpreter *killed_interp = curctx->interp; + const struct ext_include_script_info *ended_script = + curctx->script_info; + + /* This kills curctx too */ + sieve_interpreter_free(&killed_interp); + + sieve_runtime_trace( + renv, SIEVE_TRLVL_NONE, + "include: script '%s' ended [id: %d, block: %d]", + sieve_script_name(ended_script->script), + ended_script->id, + sieve_binary_block_get_id(ended_script->block)); + + /* Luckily we recorded the parent earlier */ + curctx = nextctx; + } + + } else { + /* We are an included script already, defer inclusion to main + interpreter */ + ctx->include = included; + sieve_interpreter_interrupt(renv->interp); + } + + return result; +} + +void ext_include_execute_return(const struct sieve_runtime_env *renv) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_include_interpreter_context *ctx = + ext_include_get_interpreter_context(this_ext, renv->interp); + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "return: exiting included script"); + ctx->returned = TRUE; + sieve_interpreter_interrupt(renv->interp); +} diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.h new file mode 100644 index 0000000..44bfe9a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-common.h @@ -0,0 +1,170 @@ +#ifndef EXT_INCLUDE_COMMON_H +#define EXT_INCLUDE_COMMON_H + +#include "lib.h" +#include "hash.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" + +/* + * Forward declarations + */ + +struct ext_include_script_info; +struct ext_include_binary_context; + +/* + * Types + */ + +enum ext_include_flags { // stored in one byte + EXT_INCLUDE_FLAG_ONCE = 0x01, + EXT_INCLUDE_FLAG_OPTIONAL = 0x02, + EXT_INCLUDE_FLAG_MISSING_AT_UPLOAD = 0x04 +}; + +enum ext_include_script_location { + EXT_INCLUDE_LOCATION_PERSONAL, + EXT_INCLUDE_LOCATION_GLOBAL, + EXT_INCLUDE_LOCATION_INVALID +}; + +static inline const char * +ext_include_script_location_name(enum ext_include_script_location location) +{ + switch (location) { + case EXT_INCLUDE_LOCATION_PERSONAL: + return "personal"; + case EXT_INCLUDE_LOCATION_GLOBAL: + return "global"; + default: + break; + } + + return "[INVALID LOCATION]"; +} + + +/* + * Extension + */ + +extern const struct sieve_extension_def include_extension; +extern const struct sieve_binary_extension include_binary_ext; + +bool ext_include_load(const struct sieve_extension *ext, void **context); +void ext_include_unload(const struct sieve_extension *ext); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_include; +extern const struct sieve_command_def cmd_return; +extern const struct sieve_command_def cmd_global; + +/* DEPRICATED */ +extern const struct sieve_command_def cmd_import; +extern const struct sieve_command_def cmd_export; + +/* + * Operations + */ + +enum ext_include_opcode { + EXT_INCLUDE_OPERATION_INCLUDE, + EXT_INCLUDE_OPERATION_RETURN, + EXT_INCLUDE_OPERATION_GLOBAL +}; + +extern const struct sieve_operation_def include_operation; +extern const struct sieve_operation_def return_operation; +extern const struct sieve_operation_def global_operation; + +/* + * Script access + */ + +struct sieve_storage * +ext_include_get_script_storage(const struct sieve_extension *ext, + enum ext_include_script_location location, + const char *script_name, + enum sieve_error *error_r); +/* + * Context + */ + +/* Extension context */ + +struct ext_include_context { + /* Extension dependencies */ + const struct sieve_extension *var_ext; + + /* Configuration */ + char *global_location; + + struct sieve_storage *global_storage; + struct sieve_storage *personal_storage; + + unsigned int max_nesting_depth; + unsigned int max_includes; +}; + +static inline struct ext_include_context * +ext_include_get_context(const struct sieve_extension *ext) +{ + return (struct ext_include_context *) ext->context; +} + +/* AST Context */ + +struct ext_include_ast_context { + struct sieve_variable_scope *global_vars; + + ARRAY(struct sieve_script *) included_scripts; +}; + +struct ext_include_ast_context * +ext_include_create_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast, struct sieve_ast *parent); +struct ext_include_ast_context * +ext_include_get_ast_context(const struct sieve_extension *this_ext, + struct sieve_ast *ast); + +void ext_include_ast_link_included_script( + const struct sieve_extension *this_ext, struct sieve_ast *ast, + struct sieve_script *script); + +bool ext_include_validator_have_variables( + const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +/* Generator context */ + +void ext_include_register_generator_context( + const struct sieve_extension *this_ext, + const struct sieve_codegen_env *cgenv); + +int ext_include_generate_include( + const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, + enum ext_include_script_location location, enum ext_include_flags flags, + struct sieve_script *script, + const struct ext_include_script_info **included_r); + +/* Interpreter context */ + +void ext_include_interpreter_context_init( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp); + +int ext_include_execute_include(const struct sieve_runtime_env *renv, + unsigned int block_id, + enum ext_include_flags flags); +void ext_include_execute_return(const struct sieve_runtime_env *renv); + +struct sieve_variable_storage * +ext_include_interpreter_get_global_variables( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-limits.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-limits.h new file mode 100644 index 0000000..37246c0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-limits.h @@ -0,0 +1,9 @@ +#ifndef EXT_INCLUDE_LIMITS_H +#define EXT_INCLUDE_LIMITS_H + +#include "sieve-common.h" + +#define EXT_INCLUDE_DEFAULT_MAX_NESTING_DEPTH 10 +#define EXT_INCLUDE_DEFAULT_MAX_INCLUDES 255 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c new file mode 100644 index 0000000..28cd803 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c @@ -0,0 +1,254 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Variable import-export + */ + +struct sieve_variable *ext_include_variable_import_global +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *variable) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast *ast = cmd->ast_node->ast; + struct ext_include_ast_context *ctx = + ext_include_get_ast_context(this_ext, ast); + struct ext_include_context *ectx = ext_include_get_context(this_ext); + struct sieve_variable_scope *local_scope; + struct sieve_variable_scope *global_scope = ctx->global_vars; + struct sieve_variable *global_var = NULL, *local_var; + + /* Sanity safeguard */ + i_assert ( ctx->global_vars != NULL ); + + if ( !sieve_variable_identifier_is_valid(variable) ) { + sieve_command_validate_error(valdtr, cmd, + "invalid variable identifier '%s'", str_sanitize(variable,80)); + return NULL; + } + + /* Get/Declare the variable in the global scope */ + global_var = sieve_variable_scope_declare(global_scope, variable); + + /* Check whether scope is over its size limit */ + if ( global_var == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "declaration of new global variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(ectx->var_ext)); + return NULL; + } + + /* Import the global variable into the local script scope */ + local_scope = sieve_ext_variables_get_local_scope(ectx->var_ext, valdtr); + + local_var = sieve_variable_scope_get_variable(local_scope, variable); + if ( local_var != NULL && local_var->ext != this_ext ) { + /* FIXME: indicate location of conflicting set statement */ + sieve_command_validate_error(valdtr, cmd, + "declaration of new global variable '%s' conflicts with earlier local " + "use", variable); + return NULL; + } + + return sieve_variable_scope_import(local_scope, global_var); +} + +/* + * Binary symbol table + */ + +bool ext_include_variables_save +(struct sieve_binary_block *sblock, + struct sieve_variable_scope_binary *global_vars, + enum sieve_error *error_r ATTR_UNUSED) +{ + struct sieve_variable_scope *global_scope = + sieve_variable_scope_binary_get(global_vars); + unsigned int count = sieve_variable_scope_size(global_scope); + sieve_size_t jump; + + sieve_binary_emit_unsigned(sblock, count); + + jump = sieve_binary_emit_offset(sblock, 0); + + if ( count > 0 ) { + unsigned int size, i; + struct sieve_variable *const *vars = + sieve_variable_scope_get_variables(global_scope, &size); + + for ( i = 0; i < size; i++ ) { + sieve_binary_emit_cstring(sblock, vars[i]->identifier); + } + } + + sieve_binary_resolve_offset(sblock, jump); + + return TRUE; +} + +bool ext_include_variables_load +(const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope_binary **global_vars_r) +{ + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + + /* Sanity assert */ + i_assert( *global_vars_r == NULL ); + + *global_vars_r = sieve_variable_scope_binary_read + (this_ext->svinst, ectx->var_ext, this_ext, sblock, offset); + + return ( *global_vars_r != NULL ); +} + +bool ext_include_variables_dump +(struct sieve_dumptime_env *denv, + struct sieve_variable_scope_binary *global_vars) +{ + struct sieve_variable_scope *global_scope = + sieve_variable_scope_binary_get(global_vars); + unsigned int size; + struct sieve_variable *const *vars; + + i_assert(global_scope != NULL); + + vars = sieve_variable_scope_get_variables(global_scope, &size); + + if ( size > 0 ) { + unsigned int i; + + sieve_binary_dump_sectionf(denv, "Global variables"); + + for ( i = 0; i < size; i++ ) { + sieve_binary_dumpf(denv, "%3d: '%s' \n", i, vars[i]->identifier); + } + } + + return TRUE; +} + +/* + * Global variables namespace + */ + +bool vnspc_global_variables_validate + (struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +bool vnspc_global_variables_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data); + +static const struct sieve_variables_namespace_def +global_variables_namespace = { + SIEVE_OBJECT("global", NULL, 0), + .validate = vnspc_global_variables_validate, + .generate = vnspc_global_variables_generate +}; + +bool vnspc_global_variables_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment ATTR_UNUSED) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct sieve_ast *ast = arg->ast; + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + struct ext_include_ast_context *ctx = + ext_include_get_ast_context(this_ext, ast); + struct sieve_variable *var = NULL; + const struct sieve_variable_name *name_element; + const char *variable; + + /* Sanity safeguard */ + i_assert ( ctx->global_vars != NULL ); + + /* Check variable name */ + + if ( array_count(var_name) != 2 ) { + sieve_argument_validate_error(valdtr, arg, + "invalid variable name within global namespace: " + "encountered sub-namespace"); + return FALSE; + } + + name_element = array_idx(var_name, 1); + if ( name_element->num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "invalid variable name within global namespace: " + "encountered numeric variable name"); + return FALSE; + } + + variable = str_c(name_element->identifier); + + /* Get/Declare the variable in the global scope */ + + var = sieve_variable_scope_declare(ctx->global_vars, variable); + + if ( var == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "(implicit) declaration of new global variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(ectx->var_ext)); + return FALSE; + } + + *var_data = (void *) var; + + return TRUE; +} + +bool vnspc_global_variables_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct ext_include_context *ectx = ext_include_get_context(this_ext); + struct sieve_variable *var = (struct sieve_variable *) var_data; + + sieve_variables_opr_variable_emit(cgenv->sblock, ectx->var_ext, var); + + return TRUE; +} + +void ext_include_variables_global_namespace_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + sieve_variables_namespace_register + (ectx->var_ext, valdtr, this_ext, &global_variables_namespace); +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.h b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.h new file mode 100644 index 0000000..d5927b2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.h @@ -0,0 +1,41 @@ +#ifndef EXT_INCLUDE_VARIABLES_H +#define EXT_INCLUDE_VARIABLES_H + +#include "sieve-common.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" + +/* + * Variable import-export + */ + +struct sieve_variable *ext_include_variable_import_global + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *variable); + +/* + * Binary symbol table + */ + +bool ext_include_variables_save + (struct sieve_binary_block *sblock, + struct sieve_variable_scope_binary *global_vars, + enum sieve_error *error_r); +bool ext_include_variables_load + (const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope_binary **global_vars_r); +bool ext_include_variables_dump + (struct sieve_dumptime_env *denv, + struct sieve_variable_scope_binary *global_vars); + +/* + * Validation + */ + +void ext_include_variables_global_namespace_init + (const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include.c new file mode 100644 index 0000000..0a38687 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include.c @@ -0,0 +1,121 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension include + * ----------------- + * + * Authors: Stephan Bosch + * Specification: RFC 6609 + * Implementation: full + * Status: testing + * + */ + +/* FIXME: Current include implementation does not allow for parts of the script + * to be located in external binaries; all included scripts are recompiled and + * the resulting byte code is imported into the main binary in separate blocks. + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Operations + */ + +static const struct sieve_operation_def *ext_include_operations[] = { + &include_operation, + &return_operation, + &global_operation +}; + +/* + * Extension + */ + +/* Forward declaration */ + +static bool ext_include_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); +static bool ext_include_generator_load + (const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv); +static bool ext_include_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); +static bool ext_include_binary_load + (const struct sieve_extension *ext, struct sieve_binary *binary); + +/* Extension objects */ + +const struct sieve_extension_def include_extension = { + .name = "include", + .version = 1, + + .load = ext_include_load, + .unload = ext_include_unload, + .validator_load = ext_include_validator_load, + .generator_load = ext_include_generator_load, + .interpreter_load = ext_include_interpreter_load, + .binary_load = ext_include_binary_load, + .binary_dump = ext_include_binary_dump, + .code_dump = ext_include_code_dump, + + SIEVE_EXT_DEFINE_OPERATIONS(ext_include_operations) +}; + +static bool ext_include_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_include); + sieve_validator_register_command(valdtr, ext, &cmd_return); + sieve_validator_register_command(valdtr, ext, &cmd_global); + + /* DEPRICATED */ + sieve_validator_register_command(valdtr, ext, &cmd_import); + sieve_validator_register_command(valdtr, ext, &cmd_export); + + /* Initialize global variables namespace */ + ext_include_variables_global_namespace_init(ext, valdtr); + + return TRUE; +} + +static bool ext_include_generator_load +(const struct sieve_extension *ext, const struct sieve_codegen_env *cgenv) +{ + ext_include_register_generator_context(ext, cgenv); + + return TRUE; +} + +static bool ext_include_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_include_interpreter_context_init(ext, renv->interp); + + return TRUE; +} + +static bool ext_include_binary_load +(const struct sieve_extension *ext, struct sieve_binary *sbin) +{ + (void)ext_include_binary_get_context(ext, sbin); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/index/Makefile.am b/pigeonhole/src/lib-sieve/plugins/index/Makefile.am new file mode 100644 index 0000000..434ca1c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve_ext_index.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_index_la_SOURCES = \ + ext-index-common.c \ + ext-index.c \ + tag-index.c + +noinst_HEADERS = \ + ext-index-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/index/Makefile.in b/pigeonhole/src/lib-sieve/plugins/index/Makefile.in new file mode 100644 index 0000000..852316c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/Makefile.in @@ -0,0 +1,688 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/index +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_index_la_LIBADD = +am_libsieve_ext_index_la_OBJECTS = ext-index-common.lo ext-index.lo \ + tag-index.lo +libsieve_ext_index_la_OBJECTS = $(am_libsieve_ext_index_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 = +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)/ext-index-common.Plo \ + ./$(DEPDIR)/ext-index.Plo ./$(DEPDIR)/tag-index.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 = $(libsieve_ext_index_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_index_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@ +noinst_LTLIBRARIES = libsieve_ext_index.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_index_la_SOURCES = \ + ext-index-common.c \ + ext-index.c \ + tag-index.c + +noinst_HEADERS = \ + ext-index-common.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/lib-sieve/plugins/index/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/index/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_index.la: $(libsieve_ext_index_la_OBJECTS) $(libsieve_ext_index_la_DEPENDENCIES) $(EXTRA_libsieve_ext_index_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_index_la_OBJECTS) $(libsieve_ext_index_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-index-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-index.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-index.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-index-common.Plo + -rm -f ./$(DEPDIR)/ext-index.Plo + -rm -f ./$(DEPDIR)/tag-index.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-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)/ext-index-common.Plo + -rm -f ./$(DEPDIR)/ext-index.Plo + -rm -f ./$(DEPDIR)/tag-index.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/index/ext-index-common.c b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.c new file mode 100644 index 0000000..26fb706 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.c @@ -0,0 +1,15 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "utc-offset.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-message.h" + +#include "ext-index-common.h" + diff --git a/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.h b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.h new file mode 100644 index 0000000..7ce3244 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/ext-index-common.h @@ -0,0 +1,29 @@ +#ifndef EXT_INDEX_COMMON_H +#define EXT_INDEX_COMMON_H + +#include "sieve-common.h" + +#include <time.h> + +#define SIEVE_EXT_INDEX_HDR_OVERRIDE_SEQUENCE 100 + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def index_tag; +extern const struct sieve_argument_def last_tag; + +/* + * Operands + */ + +extern const struct sieve_operand_def index_operand; + +/* + * Extension + */ + +extern const struct sieve_extension_def index_extension; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/index/ext-index.c b/pigeonhole/src/lib-sieve/plugins/index/ext-index.c new file mode 100644 index 0000000..33e7771 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/ext-index.c @@ -0,0 +1,69 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension index + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5260 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-index-common.h" + +/* + * Extension + */ + +static bool ext_index_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def index_extension = { + .name = "index", + .validator_load = ext_index_validator_load, + SIEVE_EXT_DEFINE_OPERAND(index_operand) +}; + +static bool ext_index_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register :index and :last tags with header, address and date test commands + * and we don't care whether these command are registered or even whether + * these will be registered at all. The validator handles either situation + * gracefully. + */ + sieve_validator_register_external_tag + (valdtr, "header", ext, &index_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "header", ext, &last_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "address", ext, &index_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "address", ext, &last_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "date", ext, &index_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "date", ext, &last_tag, 0); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/index/tag-index.c b/pigeonhole/src/lib-sieve/plugins/index/tag-index.c new file mode 100644 index 0000000..d8938a5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/index/tag-index.c @@ -0,0 +1,278 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +#include "ext-index-common.h" + +/* + * Tagged argument + */ + +static bool +tag_index_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); +static bool +tag_index_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def index_tag = { + .identifier = "index", + .validate = tag_index_validate, + .generate = tag_index_generate +}; + +static bool +tag_last_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, struct sieve_command *cmd); + +const struct sieve_argument_def last_tag = { + .identifier = "last", + .validate = tag_last_validate, +}; + +/* + * Header override + */ + +static bool +svmo_index_dump_context(const struct sieve_message_override *svmo, + const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +svmo_index_read_context(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **ho_context); +static int +svmo_index_header_override(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode, struct sieve_stringlist **headers); + +const struct sieve_message_override_def index_header_override = { + SIEVE_OBJECT("index", &index_operand, 0), + .sequence = SIEVE_EXT_INDEX_HDR_OVERRIDE_SEQUENCE, + .dump_context = svmo_index_dump_context, + .read_context = svmo_index_read_context, + .header_override = svmo_index_header_override +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_header_overrides = + SIEVE_EXT_DEFINE_MESSAGE_OVERRIDE(index_header_override); + +const struct sieve_operand_def index_operand = { + .name = "index operand", + .ext_def = &index_extension, + .class = &sieve_message_override_operand_class, + .interface = &ext_header_overrides +}; + +/* + * Tag data + */ + +struct tag_index_data { + sieve_number_t fieldno; + bool last:1; +}; + +/* + * Tag validation + */ + +static bool +tag_index_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct tag_index_data *data; + + /* Skip the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * ":index" <fieldno: number> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_NUMBER, FALSE)) + return FALSE; + + if (tag->argument->data == NULL) { + data = p_new(sieve_command_pool(cmd), struct tag_index_data, 1); + tag->argument->data = (void *)data; + } else { + data = (struct tag_index_data *)tag->argument->data; + } + + data->fieldno = sieve_ast_argument_number(*arg); + if (data->fieldno == 0) { + sieve_argument_validate_error(valdtr, *arg, + "the :index tag for the %s %s cannot be zero", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + return TRUE; +} + +static bool +tag_last_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *index_arg; + struct tag_index_data *data; + + index_arg = sieve_command_find_argument(cmd, &index_tag); + if (index_arg == NULL) { + sieve_argument_validate_error( + valdtr, *arg, + "the :last tag for the %s %s cannot be specified " + "without the :index tag", + sieve_command_identifier(cmd), + sieve_command_type_name(cmd)); + return FALSE; + } + + /* Set :last flag */ + if (index_arg->argument->data == NULL) { + data = p_new(sieve_command_pool(cmd), struct tag_index_data, 1); + index_arg->argument->data = (void*)data; + } else { + data = (struct tag_index_data *)index_arg->argument->data; + } + data->last = TRUE; + + /* Detach */ + *arg = sieve_ast_arguments_detach(*arg, 1); + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_index_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct tag_index_data *data = + (struct tag_index_data *)arg->argument->data; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_message_override_emit(cgenv->sblock, arg->argument->ext, + &index_header_override); + + (void)sieve_binary_emit_integer (cgenv->sblock, data->fieldno); + (void)sieve_binary_emit_byte(cgenv->sblock, (data->last ? 1 : 0)); + return TRUE; +} + +/* + * Header override implementation + */ + +/* Context data */ + +struct svmo_index_context { + unsigned int fieldno; + bool last:1; +}; + +/* Context coding */ + +static bool +svmo_index_dump_context(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_number_t fieldno = 0; + unsigned int last; + + if (!sieve_binary_read_integer(denv->sblock, address, &fieldno) || + fieldno == 0) + return FALSE; + + sieve_code_dumpf(denv, "fieldno: %llu", (unsigned long long) fieldno); + + if (!sieve_binary_read_byte(denv->sblock, address, &last)) + return FALSE; + + if (last > 0) + sieve_code_dumpf(denv, "last"); + return TRUE; +} + +static int +svmo_index_read_context(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **ho_context) +{ + pool_t pool = sieve_result_pool(renv->result); + struct svmo_index_context *ctx; + sieve_number_t fieldno; + unsigned int last = 0; + + if (!sieve_binary_read_integer(renv->sblock, address, &fieldno)) { + sieve_runtime_trace_error(renv, "fieldno: invalid number"); + return SIEVE_EXEC_BIN_CORRUPT; + } + if (fieldno == 0) { + sieve_runtime_trace_error(renv, "fieldno: index is zero"); + return SIEVE_EXEC_BIN_CORRUPT; + } + if (!sieve_binary_read_byte(renv->sblock, address, &last)) { + sieve_runtime_trace_error(renv, "last: invalid byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + ctx = p_new(pool, struct svmo_index_context, 1); + ctx->fieldno = fieldno; + ctx->last = (last == 0 ? FALSE : TRUE); + + *ho_context = (void *) ctx; + return SIEVE_EXEC_OK; +} + +/* Override */ + +static int +svmo_index_header_override(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode ATTR_UNUSED, + struct sieve_stringlist **headers) +{ + struct svmo_index_context *ctx = + (struct svmo_index_context *)svmo->context; + + sieve_runtime_trace( + renv, SIEVE_TRLVL_MATCHING, + "header index override: only returning index %d%s", + ctx->fieldno, (ctx->last ? " (from last)" : "")); + + *headers = sieve_index_stringlist_create( + renv, *headers, (int)ctx->fieldno * (ctx->last ? -1 : 1)); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.am b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.am new file mode 100644 index 0000000..b627735 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.am @@ -0,0 +1,26 @@ +noinst_LTLIBRARIES = libsieve_ext_mailbox.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-mailbox-create.c + +tests = \ + tst-mailboxexists.c + +libsieve_ext_mailbox_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-mailbox.c + +public_headers = \ + sieve-ext-mailbox.h + +headers = \ + ext-mailbox-common.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.in b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.in new file mode 100644 index 0000000..6d5ed09 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/Makefile.in @@ -0,0 +1,757 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/mailbox +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) \ + $(pkginc_lib_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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_mailbox_la_LIBADD = +am__objects_1 = tag-mailbox-create.lo +am__objects_2 = tst-mailboxexists.lo +am_libsieve_ext_mailbox_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + ext-mailbox.lo +libsieve_ext_mailbox_la_OBJECTS = \ + $(am_libsieve_ext_mailbox_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 = +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)/ext-mailbox.Plo \ + ./$(DEPDIR)/tag-mailbox-create.Plo \ + ./$(DEPDIR)/tst-mailboxexists.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 = $(libsieve_ext_mailbox_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_mailbox_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_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@ +noinst_LTLIBRARIES = libsieve_ext_mailbox.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-mailbox-create.c + +tests = \ + tst-mailboxexists.c + +libsieve_ext_mailbox_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-mailbox.c + +public_headers = \ + sieve-ext-mailbox.h + +headers = \ + ext-mailbox-common.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +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/lib-sieve/plugins/mailbox/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/mailbox/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_mailbox.la: $(libsieve_ext_mailbox_la_OBJECTS) $(libsieve_ext_mailbox_la_DEPENDENCIES) $(EXTRA_libsieve_ext_mailbox_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_mailbox_la_OBJECTS) $(libsieve_ext_mailbox_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-mailbox.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-mailbox-create.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-mailboxexists.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 +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +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)$(pkginc_libdir)"; 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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-mailbox.Plo + -rm -f ./$(DEPDIR)/tag-mailbox-create.Plo + -rm -f ./$(DEPDIR)/tst-mailboxexists.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-pkginc_libHEADERS + +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)/ext-mailbox.Plo + -rm -f ./$(DEPDIR)/tag-mailbox-create.Plo + -rm -f ./$(DEPDIR)/tst-mailboxexists.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-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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-pkginc_libHEADERS 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-pkginc_libHEADERS + +.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/lib-sieve/plugins/mailbox/ext-mailbox-common.h b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h new file mode 100644 index 0000000..96cff39 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox-common.h @@ -0,0 +1,39 @@ +#ifndef EXT_MAILBOX_COMMON_H +#define EXT_MAILBOX_COMMON_H + +#include "sieve-common.h" + +#include "sieve-ext-mailbox.h" + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def mailbox_create_tag; + +/* + * Commands + */ + +extern const struct sieve_command_def mailboxexists_test; + +/* + * Operands + */ + +extern const struct sieve_operand_def mailbox_create_operand; + +/* + * Operations + */ + +extern const struct sieve_operation_def mailboxexists_operation; + +/* + * Extension + */ + +extern const struct sieve_extension_def mailbox_extension; + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox.c b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox.c new file mode 100644 index 0000000..a2dcd88 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/ext-mailbox.c @@ -0,0 +1,72 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension mailbox + * ------------------ + * + * Authors: Stephan Bosch + * Specification: RFC 5490 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-mailbox-common.h" + +/* + * Tag registration + */ + +void sieve_ext_mailbox_register_create_tag +(struct sieve_validator *valdtr, const struct sieve_extension *mailbox_ext, + const char *command) +{ + if ( sieve_validator_extension_loaded(valdtr, mailbox_ext) ) { + sieve_validator_register_external_tag(valdtr, command, + mailbox_ext, &mailbox_create_tag, SIEVE_OPT_SIDE_EFFECT); + } +} + + +/* + * Extension + */ + +static bool ext_mailbox_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def mailbox_extension = { + .name = "mailbox", + .validator_load = ext_mailbox_validator_load, + SIEVE_EXT_DEFINE_OPERATION(mailboxexists_operation), + SIEVE_EXT_DEFINE_OPERAND(mailbox_create_operand) +}; + +static bool ext_mailbox_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register :create tag with fileinto command and we don't care whether this + * command is registered or even whether it will be registered at all. The + * validator handles either situation gracefully + */ + sieve_validator_register_external_tag + (valdtr, "fileinto", ext, &mailbox_create_tag, SIEVE_OPT_SIDE_EFFECT); + + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &mailboxexists_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h b/pigeonhole/src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h new file mode 100644 index 0000000..f7fa4cf --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h @@ -0,0 +1,21 @@ +#ifndef SIEVE_EXT_MAILBOX_H +#define SIEVE_EXT_MAILBOX_H + +/* sieve_ext_mailbox_get_extension(): + * Get the extension struct for the mailbox extension. + */ +static inline const struct sieve_extension *sieve_ext_mailbox_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_get_by_name(svinst, "mailbox"); +} + +/* sieve_ext_mailbox_register_create_tag(): + * Register the :create tagged argument for a command other than fileinto and + * redirect. + */ +void sieve_ext_mailbox_register_create_tag + (struct sieve_validator *valdtr, const struct sieve_extension *mailbox_ext, + const char *command); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c b/pigeonhole/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c new file mode 100644 index 0000000..f3c64cf --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c @@ -0,0 +1,186 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-result.h" +#include "sieve-generator.h" + +#include "ext-mailbox-common.h" + +/* + * Tagged argument + */ + +static bool +tag_mailbox_create_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +tag_mailbox_create_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def mailbox_create_tag = { + .identifier = "create", + .validate = tag_mailbox_create_validate, + .generate = tag_mailbox_create_generate +}; + +/* + * Side effect + */ + +static void +seff_mailbox_create_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep); +static int +seff_mailbox_create_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, + void **se_tr_context ATTR_UNUSED); + +const struct sieve_side_effect_def mailbox_create_side_effect = { + SIEVE_OBJECT("create", &mailbox_create_operand, 0), + .precedence = 100, + .to_action = &act_store, + .print = seff_mailbox_create_print, + .pre_execute = seff_mailbox_create_pre_execute +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(mailbox_create_side_effect); + +const struct sieve_operand_def mailbox_create_operand = { + .name = "create operand", + .ext_def = &mailbox_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects +}; + +/* + * Tag validation + */ + +static bool +tag_mailbox_create_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_mailbox_create_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, arg->argument->ext, + &mailbox_create_side_effect); + return TRUE; +} + +/* + * Side effect implementation + */ + +static void +seff_mailbox_create_print(const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + sieve_result_seffect_printf( + rpenv, "create mailbox if it does not exist"); +} + +static int +seff_mailbox_create_pre_execute( + const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_action_exec_env *aenv, void *tr_context, + void **se_tr_context ATTR_UNUSED) +{ + struct act_store_transaction *trans = tr_context; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct mailbox *box = trans->box; + + /* Check whether creation is necessary */ + if (box == NULL || trans->disabled) + return SIEVE_EXEC_OK; + + eenv->exec_status->last_storage = mailbox_get_storage(box); + + /* Open the mailbox (may already be open) */ + if (trans->error_code == MAIL_ERROR_NONE) { + if (mailbox_open(box) < 0) + sieve_act_store_get_storage_error(aenv, trans); + } + + /* Check whether creation has a chance of working */ + switch (trans->error_code) { + case MAIL_ERROR_NONE: + return SIEVE_EXEC_OK; + case MAIL_ERROR_NOTFOUND: + break; + case MAIL_ERROR_TEMP: + return SIEVE_EXEC_TEMP_FAILURE; + default: + return SIEVE_EXEC_FAILURE; + } + + trans->error = NULL; + trans->error_code = MAIL_ERROR_NONE; + + /* Create mailbox */ + if (mailbox_create(box, NULL, FALSE) < 0) { + sieve_act_store_get_storage_error(aenv, trans); + if (trans->error_code == MAIL_ERROR_EXISTS) { + trans->error = NULL; + trans->error_code = MAIL_ERROR_NONE; + } else { + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + } + + /* Subscribe to it if necessary */ + if (eenv->scriptenv->mailbox_autosubscribe) { + (void)mailbox_list_set_subscribed( + mailbox_get_namespace(box)->list, + mailbox_get_name(box), TRUE); + } + + /* Try opening again */ + if (mailbox_open(box) < 0) { + /* Failed definitively */ + sieve_act_store_get_storage_error(aenv, trans); + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + return SIEVE_EXEC_OK; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c new file mode 100644 index 0000000..e0fd33d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c @@ -0,0 +1,284 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-actions.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-mailbox-common.h" + +/* + * Mailboxexists command + * + * Syntax: + * mailboxexists <mailbox-names: string-list> + */ + +static bool +tst_mailboxexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_mailboxexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def mailboxexists_test = { + .identifier = "mailboxexists", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_mailboxexists_validate, + .generate = tst_mailboxexists_generate, +}; + +/* + * Mailboxexists operation + */ + +static bool +tst_mailboxexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_mailboxexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def mailboxexists_operation = { + .mnemonic = "MAILBOXEXISTS", + .ext_def = &mailbox_extension, + .dump = tst_mailboxexists_operation_dump, + .execute = tst_mailboxexists_operation_execute, +}; + +/* + * Test validation + */ + +struct _validate_context { + struct sieve_validator *valdtr; + struct sieve_command *tst; +}; + +static int +tst_mailboxexists_mailbox_validate(void *context, + struct sieve_ast_argument *arg) +{ + struct _validate_context *valctx = + (struct _validate_context *)context; + + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg), *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valctx->valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(valctx->tst), + str_sanitize(mailbox, 256), error); + } + } + + return 1; +} + +static bool +tst_mailboxexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *aarg; + struct _validate_context valctx; + + if (!sieve_validate_positional_argument( + valdtr, tst, arg, "mailbox-names", 1, SAAT_STRING_LIST)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + aarg = arg; + i_zero(&valctx); + valctx.valdtr = valdtr; + valctx.tst = tst; + + return (sieve_ast_stringlist_map( + &aarg, (void*)&valctx, + tst_mailboxexists_mailbox_validate) >= 0); +} + +/* + * Test generation + */ + +static bool +tst_mailboxexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + sieve_operation_emit(cgenv->sblock, tst->ext, &mailboxexists_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool +tst_mailboxexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + sieve_code_dumpf(denv, "MAILBOXEXISTS"); + sieve_code_descend(denv); + + return sieve_opr_stringlist_dump(denv, address, "mailbox-names"); +} + +/* + * Code execution + */ + +static int +tst_mailboxexists_test_mailbox(const struct sieve_runtime_env *renv, + const char *mailbox, bool trace, + bool *all_exist_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mailbox *box; + const char *error; + + /* Check validity of mailbox name */ + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_runtime_warning( + renv, NULL, "mailboxexists test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(mailbox, 256), error); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + /* Open the box */ + box = mailbox_alloc_for_user(eenv->scriptenv->user, + mailbox, + MAILBOX_FLAG_POST_SESSION); + + if (mailbox_open(box) < 0) { + if (trace) { + sieve_runtime_trace( + renv, 0, + "mailbox `%s' cannot be opened", + str_sanitize(mailbox, 80)); + } + mailbox_free(&box); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + /* Also fail when it is readonly */ + if (mailbox_is_readonly(box)) { + if (trace) { + sieve_runtime_trace( + renv, 0, + "mailbox `%s' is read-only", + str_sanitize(mailbox, 80)); + } + mailbox_free(&box); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + /* FIXME: check acl for 'p' or 'i' ACL permissions as + required by RFC */ + + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' exists", + str_sanitize(mailbox, 80)); + } + + /* Close mailbox */ + mailbox_free(&box); + return SIEVE_EXEC_OK; +} + +static int +tst_mailboxexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_stringlist *mailbox_names; + string_t *mailbox_item; + bool trace = FALSE; + bool all_exist = TRUE; + int ret; + + /* + * Read operands + */ + + /* Read notify uris */ + ret = sieve_opr_stringlist_read(renv, address, "mailbox-names", + &mailbox_names); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + sieve_runtime_trace(renv, 0, "mailboxexists test"); + sieve_runtime_trace_descend(renv); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + } + + if (eenv->scriptenv->user == NULL) { + sieve_runtime_trace(renv, 0, "no mail user; yield true"); + sieve_interpreter_set_test_result(renv->interp, TRUE); + return SIEVE_EXEC_OK; + } + + mailbox_item = NULL; + while (all_exist && + (ret = sieve_stringlist_next_item(mailbox_names, + &mailbox_item)) > 0) { + const char *mailbox = str_c(mailbox_item); + + ret = tst_mailboxexists_test_mailbox(renv, mailbox, + trace, &all_exist); + if (ret <= 0) + return ret; + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid mailbox name item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (trace) { + if (all_exist) { + sieve_runtime_trace(renv, 0, + "all mailboxes are available"); + } else { + sieve_runtime_trace(renv, 0, + "some mailboxes are unavailable"); + } + } + + sieve_interpreter_set_test_result(renv->interp, all_exist); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.am b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.am new file mode 100644 index 0000000..6d69ba8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.am @@ -0,0 +1,24 @@ +noinst_LTLIBRARIES = libsieve_ext_metadata.la + +libsieve_ext_metadata_la_LDFLAGS = -module -avoid-version + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) + +tests = \ + tst-metadata.c \ + tst-metadataexists.c + +extensions = \ + ext-metadata.c + +libsieve_ext_metadata_la_SOURCES = \ + $(tests) \ + $(extensions) + +noinst_HEADERS = \ + ext-metadata-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.in b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.in new file mode 100644 index 0000000..0b95819 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/Makefile.in @@ -0,0 +1,705 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/metadata +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_metadata_la_LIBADD = +am__objects_1 = tst-metadata.lo tst-metadataexists.lo +am__objects_2 = ext-metadata.lo +am_libsieve_ext_metadata_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) +libsieve_ext_metadata_la_OBJECTS = \ + $(am_libsieve_ext_metadata_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 = +libsieve_ext_metadata_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libsieve_ext_metadata_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)/ext-metadata.Plo \ + ./$(DEPDIR)/tst-metadata.Plo \ + ./$(DEPDIR)/tst-metadataexists.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 = $(libsieve_ext_metadata_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_metadata_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@ +noinst_LTLIBRARIES = libsieve_ext_metadata.la +libsieve_ext_metadata_la_LDFLAGS = -module -avoid-version +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_STORAGE_INCLUDE) + +tests = \ + tst-metadata.c \ + tst-metadataexists.c + +extensions = \ + ext-metadata.c + +libsieve_ext_metadata_la_SOURCES = \ + $(tests) \ + $(extensions) + +noinst_HEADERS = \ + ext-metadata-common.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/lib-sieve/plugins/metadata/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/metadata/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_metadata.la: $(libsieve_ext_metadata_la_OBJECTS) $(libsieve_ext_metadata_la_DEPENDENCIES) $(EXTRA_libsieve_ext_metadata_la_DEPENDENCIES) + $(AM_V_CCLD)$(libsieve_ext_metadata_la_LINK) $(libsieve_ext_metadata_la_OBJECTS) $(libsieve_ext_metadata_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-metadata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-metadata.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-metadataexists.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadataexists.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-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)/ext-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadata.Plo + -rm -f ./$(DEPDIR)/tst-metadataexists.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/metadata/ext-metadata-common.h b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata-common.h new file mode 100644 index 0000000..a4b25a0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata-common.h @@ -0,0 +1,40 @@ +#ifndef EXT_METADATA_COMMON_H +#define EXT_METADATA_COMMON_H + +#include "lib.h" +#include "mail-storage.h" +#include "imap-metadata.h" + +#include "sieve-common.h" + +/* + * Extension + */ + +extern const struct sieve_extension_def mboxmetadata_extension; +extern const struct sieve_extension_def servermetadata_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def metadata_test; +extern const struct sieve_command_def servermetadata_test; +extern const struct sieve_command_def metadataexists_test; +extern const struct sieve_command_def servermetadataexists_test; + +/* + * Operations + */ + +enum ext_metadata_opcode { + EXT_METADATA_OPERATION_METADATA, + EXT_METADATA_OPERATION_METADATAEXISTS +}; + +extern const struct sieve_operation_def metadata_operation; +extern const struct sieve_operation_def servermetadata_operation; +extern const struct sieve_operation_def metadataexists_operation; +extern const struct sieve_operation_def servermetadataexists_operation; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata.c b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata.c new file mode 100644 index 0000000..882116b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/ext-metadata.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-interpreter.h" + +#include "ext-metadata-common.h" + +/* + * Extension mboxmetadata + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5490; Section 3 + * Implementation: skeleton + * Status: development + * + */ + +const struct sieve_operation_def *mboxmetadata_operations[] = { + &metadata_operation, + &metadataexists_operation, +}; + +static bool ext_mboxmetadata_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def mboxmetadata_extension = { + .name = "mboxmetadata", + .validator_load = ext_mboxmetadata_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(mboxmetadata_operations) +}; + +static bool ext_mboxmetadata_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &metadata_test); + sieve_validator_register_command(valdtr, ext, &metadataexists_test); + + return TRUE; +} + +/* + * Extension servermetadata + * ----------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5490; Section 4 + * Implementation: skeleton + * Status: development + * + */ + +const struct sieve_operation_def *servermetadata_operations[] = { + &servermetadata_operation, + &servermetadataexists_operation, +}; + +static bool ext_servermetadata_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def servermetadata_extension = { + .name = "servermetadata", + .validator_load = ext_servermetadata_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(servermetadata_operations) +}; + +static bool ext_servermetadata_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_validator_register_command(valdtr, ext, &servermetadata_test); + sieve_validator_register_command(valdtr, ext, &servermetadataexists_test); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadata.c b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadata.c new file mode 100644 index 0000000..2e14535 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadata.c @@ -0,0 +1,433 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "istream.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-metadata-common.h" + +#define TST_METADATA_MAX_MATCH_SIZE SIEVE_MAX_STRING_LEN + +/* + * Test definitions + */ + +/* Forward declarations */ + +static bool +tst_metadata_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +tst_metadata_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_metadata_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +/* Metadata test + * + * Syntax: + * metadata [MATCH-TYPE] [COMPARATOR] + * <mailbox: string> + * <annotation-name: string> <key-list: string-list> + */ + +const struct sieve_command_def metadata_test = { + .identifier = "metadata", + .type = SCT_TEST, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_metadata_registered, + .validate = tst_metadata_validate, + .generate = tst_metadata_generate, +}; + +/* Servermetadata test + * + * Syntax: + * servermetadata [MATCH-TYPE] [COMPARATOR] + * <annotation-name: string> <key-list: string-list> + */ + +const struct sieve_command_def servermetadata_test = { + .identifier = "servermetadata", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_metadata_registered, + .validate = tst_metadata_validate, + .generate = tst_metadata_generate, +}; + +/* + * Opcode definitions + */ + +static bool +tst_metadata_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_metadata_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +/* Metadata operation */ + +const struct sieve_operation_def metadata_operation = { + .mnemonic = "METADATA", + .ext_def = &mboxmetadata_extension, + .code = EXT_METADATA_OPERATION_METADATA, + .dump = tst_metadata_operation_dump, + .execute = tst_metadata_operation_execute, +}; + +/* Servermetadata operation */ + +const struct sieve_operation_def servermetadata_operation = { + .mnemonic = "SERVERMETADATA", + .ext_def = &servermetadata_extension, + .code = EXT_METADATA_OPERATION_METADATA, + .dump = tst_metadata_operation_dump, + .execute = tst_metadata_operation_execute, +}; + +/* + * Test registration + */ + +static bool +tst_metadata_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, + SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, + SIEVE_MATCH_OPT_MATCH_TYPE); + return TRUE; +} + +/* + * Test validation + */ + +static bool +tst_metadata_validate(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + unsigned int arg_index = 1; + const char *error; + + /* mailbox */ + if (sieve_command_is(tst, metadata_test)) { + if (!sieve_validate_positional_argument( + valdtr, tst, arg, "mailbox", arg_index++, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check name validity when mailbox argument is not a variable + */ + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg); + const char *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(tst), + str_sanitize(mailbox, 256), error); + } + } + arg = sieve_ast_argument_next(arg); + } + + /* annotation-name */ + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "annotation-name", arg_index++, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + if (sieve_argument_is_string_literal(arg)) { + string_t *aname = sieve_ast_argument_str(arg); + + if (!imap_metadata_verify_entry_name(str_c(aname), &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "specified annotation name `%s' is invalid: %s", + sieve_command_identifier(tst), + str_sanitize(str_c(aname), 256), + sieve_error_from_external(error)); + } + } + + arg = sieve_ast_argument_next(arg); + + /* key-list */ + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "key-list", arg_index++, + SAAT_STRING_LIST)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate(valdtr, tst, arg, + &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool +tst_metadata_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + if (sieve_command_is(tst, metadata_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &metadata_operation); + } else if (sieve_command_is(tst, servermetadata_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &servermetadata_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, tst, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +tst_metadata_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(denv->oprtn, metadata_operation); + + if (metadata) + sieve_code_dumpf(denv, "METADATA"); + else + sieve_code_dumpf(denv, "SERVERMETADATA"); + + sieve_code_descend(denv); + + /* Handle any optional arguments */ + if (sieve_match_opr_optional_dump(denv, address, NULL) != 0) + return FALSE; + if (metadata && !sieve_opr_string_dump(denv, address, "mailbox")) + return FALSE; + + return (sieve_opr_string_dump(denv, address, "annotation-name") && + sieve_opr_stringlist_dump(denv, address, "key list")); +} + +/* + * Code execution + */ + +static int +tst_metadata_get_annotation(const struct sieve_runtime_env *renv, + const char *mailbox, const char *aname, + const char **annotation_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box; + struct imap_metadata_transaction *imtrans; + struct mail_attribute_value avalue; + int status, ret; + + *annotation_r = NULL; + + if (user == NULL) + return SIEVE_EXEC_OK; + + if (mailbox != NULL) { + struct mail_namespace *ns; + ns = mail_namespace_find(user->namespaces, mailbox); + box = mailbox_alloc(ns->list, mailbox, 0); + imtrans = imap_metadata_transaction_begin(box); + } else { + box = NULL; + imtrans = imap_metadata_transaction_begin_server(user); + } + + status = SIEVE_EXEC_OK; + ret = imap_metadata_get(imtrans, aname, &avalue); + if (ret < 0) { + enum mail_error error_code; + const char *error; + + error = imap_metadata_transaction_get_last_error( + imtrans, &error_code); + + sieve_runtime_error( + renv, NULL, "%s test: " + "failed to retrieve annotation `%s': %s%s", + (mailbox != NULL ? "metadata" : "servermetadata"), + str_sanitize(aname, 256), + sieve_error_from_external(error), + (error_code == MAIL_ERROR_TEMP ? + " (temporary failure)" : "")); + + status = (error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + + } else if (avalue.value != NULL) { + *annotation_r = avalue.value; + } + (void)imap_metadata_transaction_commit(&imtrans, NULL, NULL); + if (box != NULL) + mailbox_free(&box); + return status; +} + +static int +tst_metadata_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(renv->oprtn, metadata_operation); + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + string_t *mailbox, *aname; + struct sieve_stringlist *value_list, *key_list; + const char *annotation = NULL, *error; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if (sieve_match_opr_optional_read(renv, address, NULL, + &ret, &cmp, &mcht) < 0) + return ret; + + /* Read mailbox */ + if (metadata) { + ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox); + if (ret <= 0) + return ret; + } + + /* Read annotation-name */ + ret = sieve_opr_string_read(renv, address, "annotation-name", &aname); + if (ret <= 0) + return ret; + + /* Read key-list */ + ret = sieve_opr_stringlist_read(renv, address, "key-list", &key_list); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (metadata) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "metadata test"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "servermetadata test"); + } + sieve_runtime_trace_descend(renv); + + if (!imap_metadata_verify_entry_name(str_c(aname), &error)) { + sieve_runtime_warning( + renv, NULL, "%s test: " + "specified annotation name `%s' is invalid: %s", + (metadata ? "metadata" : "servermetadata"), + str_sanitize(str_c(aname), 256), + sieve_error_from_external(error)); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (metadata) { + if (!sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_warning( + renv, NULL, "metadata test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(str_c(mailbox), 256), error); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "retrieving annotation `%s' from mailbox `%s'", + str_sanitize(str_c(aname), 256), + str_sanitize(str_c(mailbox), 80)); + } else { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "retrieving server annotation `%s'", + str_sanitize(str_c(aname), 256)); + } + + /* Get annotation */ + ret = tst_metadata_get_annotation(renv, + (metadata ? str_c(mailbox) : NULL), + str_c(aname), &annotation); + if (ret == SIEVE_EXEC_OK) { + /* Perform match */ + if (annotation != NULL) { + /* Create value stringlist */ + value_list = sieve_single_stringlist_create_cstr( + renv, annotation, FALSE); + + /* Perform match */ + match = sieve_match(renv, &mcht, &cmp, + value_list, key_list, &ret); + if (ret < 0) + return ret; + } else { + match = 0; + } + } + + /* Set test result for subsequent conditional jump */ + if (ret == SIEVE_EXEC_OK) + sieve_interpreter_set_test_result(renv->interp, match > 0); + return ret; +} diff --git a/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadataexists.c b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadataexists.c new file mode 100644 index 0000000..e11d692 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/metadata/tst-metadataexists.c @@ -0,0 +1,431 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-metadata-common.h" + +/* + * Command definitions + */ + +/* Forward declarations */ + +static bool +tst_metadataexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_metadataexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +/* Metadataexists command + * + * Syntax: + * metadataexists <mailbox: string> <annotation-names: string-list> + */ + +static bool +tst_metadataexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_metadataexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def metadataexists_test = { + .identifier = "metadataexists", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_metadataexists_validate, + .generate = tst_metadataexists_generate, +}; + +/* Servermetadataexists command + * + * Syntax: + * servermetadataexists <annotation-names: string-list> + */ + +const struct sieve_command_def servermetadataexists_test = { + .identifier = "servermetadataexists", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_metadataexists_validate, + .generate = tst_metadataexists_generate, +}; + +/* + * Opcode definitions + */ + +static bool +tst_metadataexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_metadataexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +/* Metadata operation */ + +const struct sieve_operation_def metadataexists_operation = { + .mnemonic = "METADATAEXISTS", + .ext_def = &mboxmetadata_extension, + .code = EXT_METADATA_OPERATION_METADATAEXISTS, + .dump = tst_metadataexists_operation_dump, + .execute = tst_metadataexists_operation_execute, +}; + +/* Mailboxexists operation */ + +const struct sieve_operation_def servermetadataexists_operation = { + .mnemonic = "SERVERMETADATAEXISTS", + .ext_def = &servermetadata_extension, + .code = EXT_METADATA_OPERATION_METADATAEXISTS, + .dump = tst_metadataexists_operation_dump, + .execute = tst_metadataexists_operation_execute, +}; + +/* + * Test validation + */ + +struct _validate_context { + struct sieve_validator *valdtr; + struct sieve_command *tst; +}; + +static int +tst_metadataexists_annotation_validate(void *context, + struct sieve_ast_argument *arg) +{ + struct _validate_context *valctx = + (struct _validate_context *)context; + + if (sieve_argument_is_string_literal(arg)) { + const char *aname = sieve_ast_strlist_strc(arg); + const char *error; + + if (!imap_metadata_verify_entry_name(aname, &error)) { + sieve_argument_validate_warning( + valctx->valdtr, arg, "%s test: " + "specified annotation name `%s' is invalid: %s", + sieve_command_identifier(valctx->tst), + str_sanitize(aname, 256), + sieve_error_from_external(error)); + } + } + return 1; /* Can't check at compile time */ +} + +static bool +tst_metadataexists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *aarg; + struct _validate_context valctx; + unsigned int arg_index = 1; + + if (sieve_command_is(tst, metadataexists_test)) { + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "mailbox", arg_index++, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check name validity when mailbox argument is not a variable */ + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg); + const char *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(tst), + str_sanitize(mailbox, 256), error); + } + } + arg = sieve_ast_argument_next(arg); + } + + if (!sieve_validate_positional_argument(valdtr, tst, arg, + "annotation-names", arg_index++, + SAAT_STRING_LIST)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + aarg = arg; + i_zero(&valctx); + valctx.valdtr = valdtr; + valctx.tst = tst; + + return (sieve_ast_stringlist_map( + &aarg, (void*)&valctx, + tst_metadataexists_annotation_validate) >= 0); +} + +/* + * Test generation + */ + +static bool +tst_metadataexists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + if (sieve_command_is(tst, metadataexists_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &metadataexists_operation); + } else if (sieve_command_is(tst, servermetadataexists_test)) { + sieve_operation_emit(cgenv->sblock, tst->ext, + &servermetadataexists_operation); + } else { + i_unreached(); + } + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool +tst_metadataexists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(denv->oprtn, + metadataexists_operation); + + if (metadata) + sieve_code_dumpf(denv, "METADATAEXISTS"); + else + sieve_code_dumpf(denv, "SERVERMETADATAEXISTS"); + + sieve_code_descend(denv); + + if (metadata && !sieve_opr_string_dump(denv, address, "mailbox")) + return FALSE; + + return sieve_opr_stringlist_dump(denv, address, "annotation-names"); +} + +/* + * Code execution + */ + +static int +tst_metadataexists_check_annotation(const struct sieve_runtime_env *renv, + struct imap_metadata_transaction *imtrans, + const char *mailbox, const char *aname, + bool *all_exist_r) +{ + struct mail_attribute_value avalue; + const char *error; + int ret; + + if (!imap_metadata_verify_entry_name(aname, &error)) { + sieve_runtime_warning( + renv, NULL, "%s test: " + "specified annotation name `%s' is invalid: %s", + (mailbox != NULL ? + "metadataexists" : "servermetadataexists"), + str_sanitize(aname, 256), + sieve_error_from_external(error)); + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + + ret = imap_metadata_get(imtrans, aname, &avalue); + if (ret < 0) { + enum mail_error error_code; + const char *error; + + error = imap_metadata_transaction_get_last_error( + imtrans, &error_code); + sieve_runtime_error( + renv, NULL, "%s test: " + "failed to retrieve annotation `%s': %s%s", + (mailbox != NULL ? + "metadataexists" : "servermetadataexists"), + str_sanitize(aname, 256), + sieve_error_from_external(error), + (error_code == MAIL_ERROR_TEMP ? + " (temporary failure)" : "")); + + *all_exist_r = FALSE; + return (error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + if (avalue.value == NULL && avalue.value_stream == NULL) { + sieve_runtime_trace(renv, 0, + "annotation `%s': not found", aname); + *all_exist_r = FALSE; + } + + sieve_runtime_trace(renv, 0, "annotation `%s': found", aname); + return SIEVE_EXEC_OK; +} + +static int +tst_metadataexists_check_annotations(const struct sieve_runtime_env *renv, + const char *mailbox, + struct sieve_stringlist *anames, + bool *all_exist_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box = NULL; + struct imap_metadata_transaction *imtrans; + string_t *aname; + bool all_exist = TRUE; + int ret, sret, status; + + *all_exist_r = FALSE; + + if (user == NULL) + return SIEVE_EXEC_OK; + + if (mailbox != NULL) { + struct mail_namespace *ns; + ns = mail_namespace_find(user->namespaces, mailbox); + box = mailbox_alloc(ns->list, mailbox, 0); + imtrans = imap_metadata_transaction_begin(box); + } else { + imtrans = imap_metadata_transaction_begin_server(user); + } + + if (mailbox != NULL) { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "checking annotations of mailbox `%s':", + str_sanitize(mailbox, 80)); + } else { + sieve_runtime_trace( + renv, SIEVE_TRLVL_TESTS, + "checking server annotations"); + } + + aname = NULL; + status = SIEVE_EXEC_OK; + while (all_exist && + (sret = sieve_stringlist_next_item(anames, &aname)) > 0) { + ret = tst_metadataexists_check_annotation( + renv, imtrans, mailbox, str_c(aname), &all_exist); + if (ret <= 0) { + status = ret; + break; + } + } + + if (sret < 0) { + sieve_runtime_trace_error( + renv, "invalid annotation name stringlist item"); + status = SIEVE_EXEC_BIN_CORRUPT; + } + + (void)imap_metadata_transaction_commit(&imtrans, NULL, NULL); + if (box != NULL) + mailbox_free(&box); + + *all_exist_r = all_exist; + return status; +} + +static int +tst_metadataexists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + bool metadata = sieve_operation_is(renv->oprtn, + metadataexists_operation); + struct sieve_stringlist *anames; + string_t *mailbox; + bool trace = FALSE, all_exist = TRUE; + const char *error; + int ret; + + /* + * Read operands + */ + + /* Read mailbox */ + if (metadata) { + ret = sieve_opr_string_read(renv, address, "mailbox", &mailbox); + if (ret <= 0) + return ret; + } + + /* Read annotation names */ + ret = sieve_opr_stringlist_read(renv, address, "annotation-names", + &anames); + if (ret <= 0) + return ret; + + /* + * Perform operation + */ + + if (metadata && + !sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_warning( + renv, NULL, "metadataexists test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(str_c(mailbox), 256), error); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + if (metadata) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "metadataexists test"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "servermetadataexists test"); + } + + sieve_runtime_trace_descend(renv); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + } + + ret = tst_metadataexists_check_annotations( + renv, (metadata ? str_c(mailbox) : NULL), anames, &all_exist); + if (ret <= 0) + return ret; + + if (trace) { + if (all_exist) { + sieve_runtime_trace(renv, 0, + "all annotations exist"); + } else { + sieve_runtime_trace(renv, 0, + "some annotations do not exist"); + } + } + + sieve_interpreter_set_test_result(renv->interp, all_exist); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/Makefile.am b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.am new file mode 100644 index 0000000..8ded659 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.am @@ -0,0 +1,30 @@ +noinst_LTLIBRARIES = libsieve_ext_mime.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-foreverypart.c \ + cmd-break.c \ + cmd-extracttext.c + +tags = \ + tag-mime.c + +extensions = \ + ext-mime.c \ + ext-foreverypart.c \ + ext-extracttext.c + +libsieve_ext_mime_la_SOURCES = \ + ext-mime-common.c \ + $(commands) \ + $(tags) \ + $(extensions) + +noinst_HEADERS = \ + ext-mime-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/Makefile.in b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.in new file mode 100644 index 0000000..cfe25ff --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/Makefile.in @@ -0,0 +1,727 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/mime +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_mime_la_LIBADD = +am__objects_1 = cmd-foreverypart.lo cmd-break.lo cmd-extracttext.lo +am__objects_2 = tag-mime.lo +am__objects_3 = ext-mime.lo ext-foreverypart.lo ext-extracttext.lo +am_libsieve_ext_mime_la_OBJECTS = ext-mime-common.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) +libsieve_ext_mime_la_OBJECTS = $(am_libsieve_ext_mime_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 = +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)/cmd-break.Plo \ + ./$(DEPDIR)/cmd-extracttext.Plo \ + ./$(DEPDIR)/cmd-foreverypart.Plo \ + ./$(DEPDIR)/ext-extracttext.Plo \ + ./$(DEPDIR)/ext-foreverypart.Plo \ + ./$(DEPDIR)/ext-mime-common.Plo ./$(DEPDIR)/ext-mime.Plo \ + ./$(DEPDIR)/tag-mime.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 = $(libsieve_ext_mime_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_mime_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@ +noinst_LTLIBRARIES = libsieve_ext_mime.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + -I$(srcdir)/../variables \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-foreverypart.c \ + cmd-break.c \ + cmd-extracttext.c + +tags = \ + tag-mime.c + +extensions = \ + ext-mime.c \ + ext-foreverypart.c \ + ext-extracttext.c + +libsieve_ext_mime_la_SOURCES = \ + ext-mime-common.c \ + $(commands) \ + $(tags) \ + $(extensions) + +noinst_HEADERS = \ + ext-mime-common.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/lib-sieve/plugins/mime/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/mime/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_mime.la: $(libsieve_ext_mime_la_OBJECTS) $(libsieve_ext_mime_la_DEPENDENCIES) $(EXTRA_libsieve_ext_mime_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_mime_la_OBJECTS) $(libsieve_ext_mime_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-break.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-extracttext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-foreverypart.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-extracttext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-foreverypart.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-mime-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-mime.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-mime.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-break.Plo + -rm -f ./$(DEPDIR)/cmd-extracttext.Plo + -rm -f ./$(DEPDIR)/cmd-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-extracttext.Plo + -rm -f ./$(DEPDIR)/ext-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-mime-common.Plo + -rm -f ./$(DEPDIR)/ext-mime.Plo + -rm -f ./$(DEPDIR)/tag-mime.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-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)/cmd-break.Plo + -rm -f ./$(DEPDIR)/cmd-extracttext.Plo + -rm -f ./$(DEPDIR)/cmd-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-extracttext.Plo + -rm -f ./$(DEPDIR)/ext-foreverypart.Plo + -rm -f ./$(DEPDIR)/ext-mime-common.Plo + -rm -f ./$(DEPDIR)/ext-mime.Plo + -rm -f ./$(DEPDIR)/tag-mime.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/mime/cmd-break.c b/pigeonhole/src/lib-sieve/plugins/mime/cmd-break.c new file mode 100644 index 0000000..e6ade4c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/cmd-break.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "ext-mime-common.h" + +#include <ctype.h> + +/* break + * + * Syntax: + * break [":name" <name: string>] + * + */ + +static bool cmd_break_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_break_pre_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_break_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_break_generate + (const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_break = { + .identifier = "break", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_break_registered, + .pre_validate = cmd_break_pre_validate, + .validate = cmd_break_validate, + .generate = cmd_break_generate, +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool cmd_break_validate_name_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def break_name_tag = { + .identifier = "name", + .validate = cmd_break_validate_name_tag +}; + +/* + * Break operation + */ + +static bool cmd_break_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_break_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def break_operation = { + .mnemonic = "BREAK", + .ext_def = &foreverypart_extension, + .code = EXT_FOREVERYPART_OPERATION_BREAK, + .dump = cmd_break_operation_dump, + .execute = cmd_break_operation_execute +}; + +/* + * Validation data + */ + +struct cmd_break_data { + struct sieve_ast_argument *name; + struct sieve_command *loop_cmd; +}; + +/* + * Tag validation + */ + +static bool cmd_break_validate_name_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_break_data *data = + (struct cmd_break_data *)cmd->data; + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :name <string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, TRUE) ) + return FALSE; + data->name = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_break_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &break_name_tag, 0); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_break_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct cmd_break_data *data; + pool_t pool = sieve_command_pool(cmd); + + data = p_new(pool, struct cmd_break_data, 1); + cmd->data = data; + return TRUE; +} + +static bool cmd_break_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct cmd_break_data *data = + (struct cmd_break_data *)cmd->data; + struct sieve_ast_node *node = cmd->ast_node; + const char *name = ( data->name == NULL ? + NULL : sieve_ast_argument_strc(data->name) ); + + i_assert(node != NULL); + while ( node != NULL && node->command != NULL ) { + if ( sieve_command_is(node->command, cmd_foreverypart) ) { + struct ext_foreverypart_loop *loop = + (struct ext_foreverypart_loop *)node->command->data; + if ( name == NULL || + (name != NULL && loop->name != NULL && + strcmp(name, loop->name) == 0) ) { + data->loop_cmd = node->command; + break; + } + } + node = sieve_ast_node_parent(node); + } + + if ( data->loop_cmd == NULL ) { + if ( name == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the break command is not placed inside " + "a foreverypart loop"); + } else { + sieve_command_validate_error(valdtr, cmd, + "the break command is not placed inside " + "a foreverypart loop named `%s'", + name); + } + return FALSE; + } + + sieve_command_exit_block_unconditionally(cmd); + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_break_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct cmd_break_data *data = + (struct cmd_break_data *)cmd->data; + struct ext_foreverypart_loop *loop; + + i_assert( data->loop_cmd != NULL ); + loop = (struct ext_foreverypart_loop *)data->loop_cmd->data; + + sieve_operation_emit(cgenv->sblock, cmd->ext, &break_operation); + sieve_jumplist_add(loop->exit_jumps, + sieve_binary_emit_offset(cgenv->sblock, 0)); + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_break_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int pc = *address; + sieve_offset_t offset; + + sieve_code_dumpf(denv, "BREAK"); + sieve_code_descend(denv); + + if ( !sieve_binary_read_offset(denv->sblock, address, &offset) ) + return FALSE; + + sieve_code_dumpf(denv, "END: %d [%08x]", offset, pc + offset); + return TRUE; +} + +/* + * Code execution + */ + +static int cmd_break_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_interpreter_loop *loop; + unsigned int pc = *address; + sieve_offset_t offset; + sieve_size_t loop_end; + + /* + * Read operands + */ + + if ( !sieve_binary_read_offset(renv->sblock, address, &offset) ) + { + sieve_runtime_trace_error(renv, "invalid loop end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + loop_end = pc + offset; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "break command"); + sieve_runtime_trace_descend(renv); + + loop = sieve_interpreter_loop_get + (renv->interp, loop_end, &foreverypart_extension); + if ( loop == NULL ) { + sieve_runtime_trace_error(renv, "no matching loop found"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + sieve_interpreter_loop_break(renv->interp, loop); + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/cmd-extracttext.c b/pigeonhole/src/lib-sieve/plugins/mime/cmd-extracttext.c new file mode 100644 index 0000000..d9b31a2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/cmd-extracttext.c @@ -0,0 +1,370 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-message.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-mime-common.h" + +/* + * Extracttext command + * + * Syntax: + * extracttext [MODIFIER] [":first" number] <varname: string> + */ + +static bool cmd_extracttext_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_extracttext_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_extracttext_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def cmd_extracttext = { + .identifier = "extracttext", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_extracttext_registered, + .validate = cmd_extracttext_validate, + .generate = cmd_extracttext_generate +}; + +/* + * Extracttext command tags + */ + +enum cmd_extracttext_optional { + CMD_EXTRACTTEXT_OPT_END, + CMD_EXTRACTTEXT_OPT_FIRST +}; + +static bool cmd_extracttext_validate_first_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def extracttext_from_tag = { + .identifier = "first", + .validate = cmd_extracttext_validate_first_tag +}; + +/* + * Extracttext operation + */ + +static bool cmd_extracttext_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_extracttext_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def extracttext_operation = { + .mnemonic = "EXTRACTTEXT", + .ext_def = &extracttext_extension, + .dump = cmd_extracttext_operation_dump, + .execute = cmd_extracttext_operation_execute +}; + +/* + * Compiler context + */ + +struct cmd_extracttext_context { + ARRAY_TYPE(sieve_variables_modifier) modifiers; +}; + +/* + * Tag validation + */ + +static bool cmd_extracttext_validate_first_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :first <number> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_NUMBER, FALSE) ) + return FALSE; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* Command registration */ + +static bool cmd_extracttext_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)ext->context; + + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &extracttext_from_tag, CMD_EXTRACTTEXT_OPT_FIRST); + sieve_variables_modifiers_link_tag + (valdtr, ectx->var_ext, cmd_reg); + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_extracttext_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)this_ext->context; + struct sieve_ast_node *node = cmd->ast_node; + struct sieve_ast_argument *arg = cmd->first_positional; + pool_t pool = sieve_command_pool(cmd); + struct cmd_extracttext_context *sctx; + + /* Create command context */ + sctx = p_new(pool, struct cmd_extracttext_context, 1); + p_array_init(&sctx->modifiers, pool, 4); + cmd->data = (void *) sctx; + + /* Validate modifiers */ + if ( !sieve_variables_modifiers_validate + (valdtr, cmd, &sctx->modifiers) ) + return FALSE; + + /* Validate varname argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "varname", 1, SAAT_STRING) ) { + return FALSE; + } + if ( !sieve_variable_argument_activate + (ectx->var_ext, ectx->var_ext, valdtr, cmd, arg, TRUE) ) + return FALSE; + + /* Check foreverypart context */ + i_assert(node != NULL); + while ( node != NULL ) { + if ( node->command != NULL && + sieve_command_is(node->command, cmd_foreverypart) ) + break; + node = sieve_ast_node_parent(node); + } + + if ( node == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "the extracttext command is not placed inside " + "a foreverypart loop"); + return FALSE; + } + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_extracttext_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_binary_block *sblock = cgenv->sblock; + struct cmd_extracttext_context *sctx = + (struct cmd_extracttext_context *) cmd->data; + + sieve_operation_emit(sblock, this_ext, &extracttext_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + /* Generate modifiers */ + if ( !sieve_variables_modifiers_generate + (cgenv, &sctx->modifiers) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_extracttext_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "EXTRACTTEXT"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + if ( opt == 0 ) break; + + switch ( opt_code ) { + case CMD_EXTRACTTEXT_OPT_FIRST: + opok = sieve_opr_number_dump(denv, address, "first"); + break; + default: + return FALSE; + } + if ( !opok ) return FALSE; + } + + /* Print both variable name and string value */ + if ( !sieve_opr_string_dump(denv, address, "varname") ) + return FALSE; + + return sieve_variables_modifiers_code_dump(denv, address); +} + +/* + * Code execution + */ + +static int cmd_extracttext_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)this_ext->context; + struct sieve_variable_storage *storage; + ARRAY_TYPE(sieve_variables_modifier) modifiers; + struct ext_foreverypart_runtime_loop *sfploop; + struct sieve_message_part *mpart; + struct sieve_message_part_data mpart_data; + int opt_code = 0; + sieve_number_t first = 0; + string_t *value; + unsigned int var_index; + bool have_first = FALSE; + int ret = SIEVE_EXEC_OK; + + /* + * Read the normal operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read + (renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + if ( opt == 0 ) break; + + switch ( opt_code ) { + case CMD_EXTRACTTEXT_OPT_FIRST: + ret = sieve_opr_number_read + (renv, address, "first", &first); + have_first = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + if ( ret <= 0 ) return ret; + } + + /* Varname operand */ + + if ( (ret=sieve_variable_operand_read + (renv, address, "varname", &storage, &var_index)) <= 0 ) + return ret; + + /* Modifiers */ + + if ( (ret=sieve_variables_modifiers_code_read + (renv, ectx->var_ext, address, &modifiers)) <= 0 ) + return ret; + + /* + * Determine and assign the value + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "extracttext command"); + sieve_runtime_trace_descend(renv); + + sfploop = ext_foreverypart_runtime_loop_get_current(renv); + if ( sfploop == NULL ) { + sieve_runtime_trace_error(renv, + "outside foreverypart context"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Get current message part */ + mpart = sieve_message_part_iter_current(&sfploop->part_iter); + i_assert( mpart != NULL ); + + /* Get message part content */ + sieve_message_part_get_data(mpart, &mpart_data, TRUE); + + /* Apply ":first" limit, if any */ + if ( !have_first || (size_t)first > mpart_data.size ) { + value = t_str_new_const(mpart_data.content, mpart_data.size); + } else { + value = t_str_new((size_t)first); + str_append_data(value, mpart_data.content, (size_t)first); + } + + /* Apply modifiers */ + if ( (ret=sieve_variables_modifiers_apply + (renv, ectx->var_ext, &modifiers, &value)) <= 0 ) + return ret; + + /* Actually assign the value if all is well */ + i_assert ( value != NULL ); + if ( !sieve_variable_assign(storage, var_index, value) ) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Trace */ + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + const char *var_name, *var_id; + + (void)sieve_variable_get_identifier(storage, var_index, &var_name); + var_id = sieve_variable_get_varid(storage, var_index); + + sieve_runtime_trace_here(renv, 0, "assign `%s' [%s] = \"%s\"", + var_name, var_id, str_c(value)); + } + + return SIEVE_EXEC_OK; +} + + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/cmd-foreverypart.c b/pigeonhole/src/lib-sieve/plugins/mime/cmd-foreverypart.c new file mode 100644 index 0000000..435cb5c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/cmd-foreverypart.c @@ -0,0 +1,377 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-binary.h" +#include "sieve-dump.h" +#include "sieve-message.h" + +#include "ext-mime-common.h" + +#include <ctype.h> + +/* Foreverypart + * + * Syntax: + * foreverypart [":name" <name: string>] <block> + * + */ + +static bool cmd_foreverypart_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_foreverypart_pre_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_foreverypart_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_foreverypart_generate + (const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_foreverypart = { + .identifier = "foreverypart", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = TRUE, + .block_required = TRUE, + .registered = cmd_foreverypart_registered, + .pre_validate = cmd_foreverypart_pre_validate, + .validate = cmd_foreverypart_validate, + .generate = cmd_foreverypart_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool cmd_foreverypart_validate_name_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def foreverypart_name_tag = { + .identifier = "name", + .validate = cmd_foreverypart_validate_name_tag, +}; + +/* + * foreverypart operation + */ + +static bool cmd_foreverypart_begin_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_foreverypart_begin_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def foreverypart_begin_operation = { + .mnemonic = "FOREVERYPART_BEGIN", + .ext_def = &foreverypart_extension, + .code = EXT_FOREVERYPART_OPERATION_FOREVERYPART_BEGIN, + .dump = cmd_foreverypart_begin_operation_dump, + .execute = cmd_foreverypart_begin_operation_execute +}; + +static bool cmd_foreverypart_end_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_foreverypart_end_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def foreverypart_end_operation = { + .mnemonic = "FOREVERYPART_END", + .ext_def = &foreverypart_extension, + .code = EXT_FOREVERYPART_OPERATION_FOREVERYPART_END, + .dump = cmd_foreverypart_end_operation_dump, + .execute = cmd_foreverypart_end_operation_execute +}; + +/* + * Tag validation + */ + +static bool cmd_foreverypart_validate_name_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct ext_foreverypart_loop *loop = + (struct ext_foreverypart_loop *)cmd->data; + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :name <string> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING, TRUE) ) + return FALSE; + loop->name = sieve_ast_argument_strc(*arg); + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg, 1); + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_foreverypart_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &foreverypart_name_tag, 0); + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_foreverypart_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *cmd) +{ + struct ext_foreverypart_loop *loop; + pool_t pool = sieve_command_pool(cmd); + + loop = p_new(pool, struct ext_foreverypart_loop, 1); + cmd->data = loop; + + return TRUE; +} + +static bool cmd_foreverypart_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_node *node = cmd->ast_node; + unsigned int nesting = 0; + + /* Determine nesting depth of foreverypart commands at this point. */ + i_assert(node != NULL); + node = sieve_ast_node_parent(node); + while ( node != NULL && node->command != NULL ) { + if ( sieve_command_is(node->command, cmd_foreverypart) ) + nesting++; + node = sieve_ast_node_parent(node); + } + + /* Enforce nesting limit + NOTE: this only recognizes the foreverypart command as a loop; if + new loop commands are introduced in the future, these must be + recognized somehow. */ + if ( nesting + 1 > SIEVE_MAX_LOOP_DEPTH ) { + sieve_command_validate_error(valdtr, cmd, + "the nested foreverypart loop exceeds " + "the nesting limit (<= %u levels)", + SIEVE_MAX_LOOP_DEPTH); + return FALSE; + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_foreverypart_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + struct ext_foreverypart_loop *loop = + (struct ext_foreverypart_loop *)cmd->data; + sieve_size_t block_begin, loop_jump; + + /* Emit FOREVERYPART_BEGIN operation */ + sieve_operation_emit(cgenv->sblock, + cmd->ext, &foreverypart_begin_operation); + + /* Emit exit address */ + loop->exit_jumps = sieve_jumplist_create + (sieve_command_pool(cmd), cgenv->sblock); + sieve_jumplist_add(loop->exit_jumps, + sieve_binary_emit_offset(cgenv->sblock, 0)); + block_begin = sieve_binary_block_get_size(cgenv->sblock); + + /* Generate loop block */ + if ( !sieve_generate_block(cgenv, cmd->ast_node) ) + return FALSE; + + /* Emit FOREVERYPART_END operation */ + sieve_operation_emit(cgenv->sblock, + cmd->ext, &foreverypart_end_operation); + loop_jump = sieve_binary_block_get_size(cgenv->sblock); + i_assert(loop_jump > block_begin); + (void)sieve_binary_emit_offset + (cgenv->sblock, (loop_jump - block_begin)); + + /* Resolve exit address */ + sieve_jumplist_resolve(loop->exit_jumps); + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_foreverypart_begin_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int pc = *address; + sieve_offset_t offset; + + sieve_code_dumpf(denv, "FOREVERYPART_BEGIN"); + sieve_code_descend(denv); + + if ( !sieve_binary_read_offset(denv->sblock, address, &offset) ) + return FALSE; + + sieve_code_dumpf(denv, "END: %d [%08x]", offset, pc + offset); + return TRUE; +} + +static bool cmd_foreverypart_end_operation_dump +(const struct sieve_dumptime_env *denv, + sieve_size_t *address ATTR_UNUSED) +{ + unsigned int pc = *address; + sieve_offset_t offset; + + sieve_code_dumpf(denv, "FOREVERYPART_END"); + sieve_code_descend(denv); + + if ( !sieve_binary_read_offset(denv->sblock, address, &offset) ) + return FALSE; + + sieve_code_dumpf(denv, "BEGIN: -%d [%08x]", offset, pc - offset); + return TRUE; +} + +/* + * Code execution + */ + +static int cmd_foreverypart_begin_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_interpreter_loop *loop; + struct ext_foreverypart_runtime_loop *fploop, *sfploop; + unsigned int pc = *address; + sieve_offset_t offset; + sieve_size_t loop_end; + pool_t pool; + int ret; + + /* + * Read operands + */ + + if ( !sieve_binary_read_offset(renv->sblock, address, &offset) ) + { + sieve_runtime_trace_error(renv, "invalid loop end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + loop_end = pc + offset; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "foreverypart loop begin"); + sieve_runtime_trace_descend(renv); + + sfploop = ext_foreverypart_runtime_loop_get_current(renv); + + if ( (ret=sieve_interpreter_loop_start(renv->interp, + loop_end, &foreverypart_extension, &loop)) <= 0 ) + return ret; + + pool = sieve_interpreter_loop_get_pool(loop); + fploop = p_new(pool, struct ext_foreverypart_runtime_loop, 1); + + if ( sfploop == NULL ) { + if ( (ret=sieve_message_part_iter_init + (&fploop->part_iter, renv)) <= 0 ) + return ret; + } else { + sieve_message_part_iter_children(&sfploop->part_iter, + &fploop->part_iter); + } + fploop->part = sieve_message_part_iter_current(&fploop->part_iter); + if (fploop->part != NULL) { + sieve_interpreter_loop_set_context(loop, (void*)fploop); + } else { + /* No children parts to iterate */ + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "no children at this level"); + sieve_interpreter_loop_break(renv->interp, loop); + } + return SIEVE_EXEC_OK; +} + +static int cmd_foreverypart_end_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_interpreter_loop *loop; + struct ext_foreverypart_runtime_loop *fploop; + unsigned int pc = *address; + sieve_offset_t offset; + sieve_size_t loop_begin; + + /* + * Read operands + */ + + if ( !sieve_binary_read_offset(renv->sblock, address, &offset) ) + { + sieve_runtime_trace_error(renv, "invalid loop begin offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + loop_begin = pc - offset; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, + SIEVE_TRLVL_COMMANDS, "foreverypart loop end"); + sieve_runtime_trace_descend(renv); + + loop = sieve_interpreter_loop_get + (renv->interp, *address, &foreverypart_extension); + if ( loop == NULL ) { + sieve_runtime_trace_error(renv, "no matching loop found"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + fploop = (struct ext_foreverypart_runtime_loop *) + sieve_interpreter_loop_get_context(loop); + i_assert(fploop->part != NULL); + fploop->part = sieve_message_part_iter_next(&fploop->part_iter); + if ( fploop->part == NULL ) { + sieve_runtime_trace(renv, + SIEVE_TRLVL_COMMANDS, "no more message parts"); + return sieve_interpreter_loop_break(renv->interp, loop); + } + + sieve_runtime_trace(renv, + SIEVE_TRLVL_COMMANDS, "switched to next message part"); + return sieve_interpreter_loop_next(renv->interp, loop, loop_begin); +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-extracttext.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-extracttext.c new file mode 100644 index 0000000..4eab76b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-extracttext.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension extracttext + * --------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5703, Section 7 + * Implementation: full + * Status: experimental + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "sieve-ext-variables.h" + +#include "ext-mime-common.h" + +/* + * Extension + */ + +static bool ext_extracttext_load + (const struct sieve_extension *ext, void **context); +static void ext_extracttext_unload + (const struct sieve_extension *ext); +static bool ext_extracttext_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def extracttext_extension = { + .name = "extracttext", + .load = ext_extracttext_load, + .unload = ext_extracttext_unload, + .validator_load = ext_extracttext_validator_load, + SIEVE_EXT_DEFINE_OPERATION(extracttext_operation) +}; + +static bool ext_extracttext_load +(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_extracttext_context *ectx; + + if ( *context != NULL ) + ext_extracttext_unload(ext); + + ectx = i_new(struct ext_extracttext_context, 1); + ectx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + ectx->fep_ext = sieve_extension_register + (svinst, &foreverypart_extension, FALSE); + *context = (void *)ectx; + return TRUE; +} + +static void ext_extracttext_unload +(const struct sieve_extension *ext) +{ + struct ext_extracttext_context *ctx = + (struct ext_extracttext_context *) ext->context; + + i_free(ctx); +} + +/* + * Extension validation + */ + +static bool ext_extracttext_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +const struct sieve_validator_extension +extracttext_validator_extension = { + .ext = &extracttext_extension, + .validate = ext_extracttext_validator_validate +}; + +static bool ext_extracttext_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict with eextracttext */ + sieve_validator_extension_register + (valdtr, ext, &extracttext_validator_extension, NULL); + + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_extracttext); + + return TRUE; +} + +static bool ext_extracttext_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + bool required ATTR_UNUSED) +{ + struct ext_extracttext_context *ectx = + (struct ext_extracttext_context *)ext->context; + + if ( ectx->var_ext == NULL || + !sieve_ext_variables_is_active + (ectx->var_ext, valdtr) ) { + sieve_argument_validate_error(valdtr, require_arg, + "extracttext extension cannot be used " + "without variables extension"); + return FALSE; + } + if ( ectx->fep_ext == NULL || + !sieve_validator_extension_loaded + (valdtr, ectx->fep_ext) ) { + sieve_argument_validate_error(valdtr, require_arg, + "extracttext extension cannot be used " + "without foreverypart extension"); + return FALSE; + } + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-foreverypart.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-foreverypart.c new file mode 100644 index 0000000..6bca199 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-foreverypart.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension foreverypart + * ---------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5703, Section 3 + * Implementation: full + * Status: experimental + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-mime-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_foreverypart_operations[] = { + &foreverypart_begin_operation, + &foreverypart_end_operation, + &break_operation +}; + +/* + * Extension + */ + +static bool ext_foreverypart_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def foreverypart_extension = { + .name = "foreverypart", + .validator_load = ext_foreverypart_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_foreverypart_operations) +}; + +/* + * Extension validation + */ + +static bool ext_foreverypart_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_foreverypart); + sieve_validator_register_command(valdtr, ext, &cmd_break); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.c new file mode 100644 index 0000000..5b38bcb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.c @@ -0,0 +1,27 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-interpreter.h" + +#include "ext-mime-common.h" + +struct ext_foreverypart_runtime_loop * +ext_foreverypart_runtime_loop_get_current +(const struct sieve_runtime_env *renv) +{ + struct sieve_interpreter_loop *loop; + struct ext_foreverypart_runtime_loop *fploop; + + loop = sieve_interpreter_loop_get_global + (renv->interp, NULL, &foreverypart_extension); + if ( loop == NULL ) { + fploop = NULL; + } else { + fploop = (struct ext_foreverypart_runtime_loop *) + sieve_interpreter_loop_get_context(loop); + i_assert(fploop->part != NULL); + } + + return fploop; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.h b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.h new file mode 100644 index 0000000..8b0054d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime-common.h @@ -0,0 +1,85 @@ +#ifndef EXT_FOREVERYPART_COMMON_H +#define EXT_FOREVERYPART_COMMON_H + +#include "sieve-message.h" + +/* + * Extension + */ + +struct ext_extracttext_context { + const struct sieve_extension *var_ext; + const struct sieve_extension *fep_ext; +}; + +extern const struct sieve_extension_def foreverypart_extension; +extern const struct sieve_extension_def mime_extension; +extern const struct sieve_extension_def extracttext_extension; + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def mime_tag; +extern const struct sieve_argument_def mime_anychild_tag; +extern const struct sieve_argument_def mime_type_tag; +extern const struct sieve_argument_def mime_subtype_tag; +extern const struct sieve_argument_def mime_contenttype_tag; +extern const struct sieve_argument_def mime_param_tag; + +/* + * Commands + */ + +struct ext_foreverypart_loop { + const char *name; + struct sieve_jumplist *exit_jumps; +}; + +extern const struct sieve_command_def cmd_foreverypart; +extern const struct sieve_command_def cmd_break; +extern const struct sieve_command_def cmd_extracttext; + +/* + * Operations + */ + +extern const struct sieve_operation_def foreverypart_begin_operation; +extern const struct sieve_operation_def foreverypart_end_operation; +extern const struct sieve_operation_def break_operation; +extern const struct sieve_operation_def extracttext_operation; + +enum ext_foreverypart_opcode { + EXT_FOREVERYPART_OPERATION_FOREVERYPART_BEGIN, + EXT_FOREVERYPART_OPERATION_FOREVERYPART_END, + EXT_FOREVERYPART_OPERATION_BREAK, +}; + +/* + * Operands + */ + +enum ext_mime_option { + EXT_MIME_OPTION_NONE = 0, + EXT_MIME_OPTION_TYPE, + EXT_MIME_OPTION_SUBTYPE, + EXT_MIME_OPTION_CONTENTTYPE, + EXT_MIME_OPTION_PARAM +}; + +extern const struct sieve_operand_def mime_operand; + +/* + * Foreverypart loop + */ + +struct ext_foreverypart_runtime_loop { + struct sieve_message_part_iter part_iter; + struct sieve_message_part *part; +}; + +struct ext_foreverypart_runtime_loop * +ext_foreverypart_runtime_loop_get_current +(const struct sieve_runtime_env *renv); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/mime/ext-mime.c b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime.c new file mode 100644 index 0000000..da9963f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/ext-mime.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension mime + * -------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5703, Section 4 + * Implementation: full + * Status: experimental + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-message.h" +#include "sieve-result.h" + +#include "ext-mime-common.h" + +/* + * Extension + */ + +static bool ext_mime_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def mime_extension = { + .name = "mime", + .validator_load = ext_mime_validator_load, + SIEVE_EXT_DEFINE_OPERAND(mime_operand) +}; + +/* + * Extension validation + */ + +static bool ext_mime_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register :mime tag and friends with header, address and exists test + * commands and we don't care whether these command are registered or + * even whether these will be registered at all. The validator handles + * either situation gracefully. + */ + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_anychild_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_type_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_subtype_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_contenttype_tag, 0); + sieve_validator_register_external_tag + (valdtr, "header", ext, &mime_param_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "address", ext, &mime_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "address", ext, &mime_anychild_tag, 0); + + sieve_validator_register_external_tag + (valdtr, "exists", ext, &mime_tag, SIEVE_OPT_MESSAGE_OVERRIDE); + sieve_validator_register_external_tag + (valdtr, "exists", ext, &mime_anychild_tag, 0); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/mime/tag-mime.c b/pigeonhole/src/lib-sieve/plugins/mime/tag-mime.c new file mode 100644 index 0000000..379365e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/mime/tag-mime.c @@ -0,0 +1,757 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "rfc822-parser.h" +#include "rfc2231-parser.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" + +#include "ext-mime-common.h" + +/* + * Tagged argument + */ + +static bool tag_mime_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool tag_mime_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def mime_tag = { + .identifier = "mime", + .validate = tag_mime_validate, + .generate = tag_mime_generate +}; + +static bool tag_mime_option_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +const struct sieve_argument_def mime_anychild_tag = { + .identifier = "anychild", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_type_tag = { + .identifier = "type", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_subtype_tag = { + .identifier = "subtype", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_contenttype_tag = { + .identifier = "contenttype", + .validate = tag_mime_option_validate +}; + +const struct sieve_argument_def mime_param_tag = { + .identifier = "param", + .validate = tag_mime_option_validate +}; + +/* + * Header override + */ + +static bool svmo_mime_dump_context + (const struct sieve_message_override *svmo, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int svmo_mime_read_context + (const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **ho_context); +static int svmo_mime_header_override + (const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, + bool mime_decode, struct sieve_stringlist **headers); + +const struct sieve_message_override_def mime_header_override = { + SIEVE_OBJECT("mime", &mime_operand, 0), + .sequence = 0, /* Completely replace header source */ + .dump_context = svmo_mime_dump_context, + .read_context = svmo_mime_read_context, + .header_override = svmo_mime_header_override +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_header_overrides = + SIEVE_EXT_DEFINE_MESSAGE_OVERRIDE(mime_header_override); + +const struct sieve_operand_def mime_operand = { + .name = "mime operand", + .ext_def = &mime_extension, + .class = &sieve_message_override_operand_class, + .interface = &ext_header_overrides +}; + +/* + * Tag data + */ + +struct tag_mime_data { + enum ext_mime_option mimeopt; + struct sieve_ast_argument *param_arg; + bool anychild:1; +}; + +/* + * Tag validation + */ + +static struct tag_mime_data * +tag_mime_get_data(struct sieve_command *cmd, + struct sieve_ast_argument *tag) +{ + struct tag_mime_data *data; + + if (tag->argument->data == NULL) { + data = p_new(sieve_command_pool(cmd), struct tag_mime_data, 1); + tag->argument->data = (void *)data; + } else { + data = (struct tag_mime_data *)tag->argument->data; + } + + return data; +} + +static bool tag_mime_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Skip the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + (void)tag_mime_get_data(cmd, tag); + return TRUE; +} + +static bool tag_mime_option_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct sieve_ast_argument *mime_arg; + struct tag_mime_data *data; + + i_assert(tag != NULL); + + /* Detach tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Find required ":mime" tag */ + mime_arg = sieve_command_find_argument(cmd, &mime_tag); + if ( mime_arg == NULL ) { + sieve_argument_validate_error(valdtr, tag, + "the :%s tag for the %s %s cannot be specified " + "without the :mime tag", sieve_ast_argument_tag(tag), + sieve_command_identifier(cmd), sieve_command_type_name(cmd)); + return FALSE; + } + + /* Annotate ":mime" tag with the data provided by this option tag */ + data = tag_mime_get_data(cmd, mime_arg); + if ( sieve_argument_is(tag, mime_anychild_tag) ) + data->anychild = TRUE; + else { + if ( data->mimeopt != EXT_MIME_OPTION_NONE ) { + sieve_argument_validate_error(valdtr, *arg, + "the :type, :subtype, :contenttype, and :param " + "arguments for the %s test are mutually exclusive, " + "but more than one was specified", + sieve_command_identifier(cmd)); + return FALSE; + } + if ( sieve_argument_is(tag, mime_type_tag) ) + data->mimeopt = EXT_MIME_OPTION_TYPE; + else if ( sieve_argument_is(tag, mime_subtype_tag) ) + data->mimeopt = EXT_MIME_OPTION_SUBTYPE; + else if ( sieve_argument_is(tag, mime_contenttype_tag) ) + data->mimeopt = EXT_MIME_OPTION_CONTENTTYPE; + else if ( sieve_argument_is(tag, mime_param_tag) ) { + /* Check syntax: + * ":param" <param-list: string-list> + */ + if ( !sieve_validate_tag_parameter + (valdtr, cmd, tag, *arg, NULL, 0, SAAT_STRING_LIST, FALSE) ) { + return FALSE; + } + + data->mimeopt = EXT_MIME_OPTION_PARAM; + data->param_arg = *arg; + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + } else + i_unreached(); + } + return TRUE; +} + +/* + * Code generation + */ + +static bool tag_mime_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct tag_mime_data *data = + (struct tag_mime_data *)arg->argument->data; + + if ( sieve_ast_argument_type(arg) != SAAT_TAG ) + return FALSE; + + sieve_opr_message_override_emit + (cgenv->sblock, arg->argument->ext, &mime_header_override); + + (void)sieve_binary_emit_byte + (cgenv->sblock, ( data->anychild ? 1 : 0 )); + (void)sieve_binary_emit_byte + (cgenv->sblock, data->mimeopt); + if ( data->mimeopt == EXT_MIME_OPTION_PARAM && + !sieve_generate_argument(cgenv, data->param_arg, cmd) ) + return FALSE; + return TRUE; +} + +/* + * Content-type stringlist + */ + +enum content_type_part { + CONTENT_TYPE_PART_NONE = 0, + CONTENT_TYPE_PART_TYPE, + CONTENT_TYPE_PART_SUBTYPE, + CONTENT_TYPE_PART_CONTENTTYPE, +}; + +/* Object */ + +static int content_header_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void content_header_stringlist_reset + (struct sieve_stringlist *_strlist); +static int content_header_stringlist_get_length + (struct sieve_stringlist *_strlist); +static void content_header_stringlist_set_trace + (struct sieve_stringlist *strlist, bool trace); + +struct content_header_stringlist { + struct sieve_stringlist strlist; + + struct sieve_header_list *source; + + enum ext_mime_option option; + const char *const *params; + + const char *const *param_values; +}; + +static struct sieve_stringlist *content_header_stringlist_create +(const struct sieve_runtime_env *renv, + struct sieve_header_list *source, + enum ext_mime_option option, const char *const *params) +{ + struct content_header_stringlist *strlist; + + strlist = t_new(struct content_header_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = content_header_stringlist_next_item; + strlist->strlist.reset = content_header_stringlist_reset; + strlist->strlist.set_trace = content_header_stringlist_set_trace; + strlist->source = source; + strlist->option = option; + strlist->params = params; + + if ( option != EXT_MIME_OPTION_PARAM ) { + /* One header can have multiple parameters, so we cannot rely + on the source length for the :param option. */ + strlist->strlist.get_length = content_header_stringlist_get_length; + } + + return &strlist->strlist; +} + +/* Implementation */ + +static inline int _decode_hex_digit(const unsigned char digit) +{ + switch ( digit ) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return digit - '0'; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return digit - 'a' + 0x0a; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return digit - 'A' + 0x0A; + } + return -1; +} + +static string_t * +content_type_param_decode(const char *value) +{ + const unsigned char *p, *plast; + + string_t *str = t_str_new(64); + plast = p = (const unsigned char *)value; + while ( *p != '\0' ) { + unsigned char ch; + int digit; + + if ( *p == '%' ) { + if ( p - plast > 0 ) + str_append_data(str, plast, (p - plast)); + p++; + if ( *p == '\0' || (digit=_decode_hex_digit(*p)) < 0 ) + return NULL; + ch = (unsigned char)digit; + p++; + if ( *p == '\0' || (digit=_decode_hex_digit(*p)) < 0 ) + return NULL; + ch = (ch << 4) + (unsigned char)digit; + str_append_data(str, &ch, 1); + plast = p + 1; + } + p++; + } + if ( p - plast > 0 ) + str_append_data(str, plast, (p - plast)); + return str; +} + +static string_t * +content_type_param_next(struct content_header_stringlist *strlist) +{ + const struct sieve_runtime_env *renv = strlist->strlist.runenv; + const char *const *values = strlist->param_values; + bool trace = strlist->strlist.trace; + + i_assert( strlist->params != NULL ); + + /* Iterate over all parsed parameter values */ + for ( ; *values != NULL; values += 2 ) { + const char *const *params = strlist->params; + const char *name = values[0], *value = values[1]; + size_t nlen = strlen(name); + + /* Iterate over all interesting parameter names */ + for ( ; *params != NULL; params++ ) { + size_t plen = strlen(*params); + + if ( plen != nlen && + (nlen != plen + 1 || name[nlen-1] != '*') ) + continue; + + if ( plen == nlen ) { + if ( strcasecmp(name, *params) == 0 ) { + /* Return raw value */ + if ( trace ) { + sieve_runtime_trace(renv, 0, + "found mime parameter `%s' in mime header", + *params); + } + + strlist->param_values = values + 2; + return t_str_new_const(value, strlen(value)); + } + } else { + if ( trace ) { + sieve_runtime_trace(renv, 0, + "found encoded parameter `%s' in mime header", + *params); + } + + if ( strncasecmp(name, *params, plen) == 0 ) { + string_t *result = NULL; + + strlist->param_values = values + 2; + + /* Decode value first */ + // FIXME: transcode charset + value = strchr(value, '\''); + if (value != NULL) + value = strchr(value+1, '\''); + if (value != NULL) + result = content_type_param_decode(value + 1); + if (result == NULL) + strlist->param_values = NULL; + return result; + } + } + } + } + + strlist->param_values = NULL; + return NULL; +} + +// FIXME: not too happy with the use of string_t like this. +// Sieve should have a special runtime string type (TODO) +static string_t * +content_header_parse(struct content_header_stringlist *strlist, + const char *hdr_name, string_t *str) +{ + const struct sieve_runtime_env *renv = strlist->strlist.runenv; + bool trace = strlist->strlist.trace; + struct rfc822_parser_context parser; + const char *type, *p; + bool is_ctype = FALSE; + string_t *content; + + if ( strlist->option == EXT_MIME_OPTION_NONE ) + return str; + + if ( strcasecmp(hdr_name, "content-type") == 0 ) + is_ctype = TRUE; + else if ( strcasecmp(hdr_name, "content-disposition") != 0 ) { + if ( trace ) { + sieve_runtime_trace(renv, 0, + "non-mime header yields empty string"); + } + return t_str_new(0); + } + + /* Initialize parsing */ + rfc822_parser_init(&parser, str_data(str), str_len(str), NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse content type/disposition */ + content = t_str_new(64); + if ( is_ctype ){ + if (rfc822_parse_content_type(&parser, content) < 0) { + str_truncate(content, 0); + return content; + } + } else { + if (rfc822_parse_mime_token(&parser, content) < 0) { + str_truncate(content, 0); + return content; + } + } + + /* Content-type value must end here, otherwise it is invalid after all */ + (void)rfc822_skip_lwsp(&parser); + if ( parser.data != parser.end && *parser.data != ';' ) { + str_truncate(content, 0); + return content; + } + + if ( strlist->option == EXT_MIME_OPTION_PARAM ) { + string_t *param_val; + + /* MIME parameter */ + i_assert( strlist->params != NULL ); + + // FIXME: not very nice when multiple parameters in the same header + // are queried in successive tests. + str_truncate(content, 0); + rfc2231_parse(&parser, &strlist->param_values); + + param_val = content_type_param_next(strlist); + if ( param_val != NULL ) + content = param_val; + } else { + /* Get :type/:subtype:/:contenttype value */ + type = str_c(content); + p = strchr(type, '/'); + switch ( strlist->option ) { + case EXT_MIME_OPTION_TYPE: + if ( trace ) { + sieve_runtime_trace(renv, 0, + "extracted MIME type"); + } + if ( p != NULL ) { + i_assert( is_ctype ); + str_truncate(content, (p - type)); + } + break; + case EXT_MIME_OPTION_SUBTYPE: + if ( p == NULL ) { + i_assert( !is_ctype ); + if ( trace ) { + sieve_runtime_trace(renv, 0, + "no MIME sub-type for content-disposition"); + } + str_truncate(content, 0); + break; + } + + i_assert( is_ctype ); + if ( trace ) { + sieve_runtime_trace(renv, 0, + "extracted MIME sub-type"); + } + str_delete(content, 0, (p - type) + 1); + break; + case EXT_MIME_OPTION_CONTENTTYPE: + sieve_runtime_trace(renv, 0, + "extracted full MIME contenttype"); + break; + default: + break; + } + } + + /* Success */ + return content; +} + +static int content_header_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + const char *hdr_name; + int ret; + + if ( strlist->param_values != NULL ) { + string_t *param_val; + + i_assert( strlist->option == EXT_MIME_OPTION_PARAM ); + param_val = content_type_param_next(strlist); + if ( param_val != NULL ) { + *str_r = param_val; + return 1; + } + } + + if ( (ret=sieve_header_list_next_item + (strlist->source, &hdr_name, str_r)) <= 0 ) { + if (ret < 0) { + _strlist->exec_status = + strlist->source->strlist.exec_status; + } + return ret; + } + + *str_r = content_header_parse(strlist, hdr_name, *str_r); + return 1; +} + +static void content_header_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + sieve_header_list_reset(strlist->source); +} + +static int content_header_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + return sieve_header_list_get_length(strlist->source); +} + +static void content_header_stringlist_set_trace +(struct sieve_stringlist *_strlist, bool trace) +{ + struct content_header_stringlist *strlist = + (struct content_header_stringlist *)_strlist; + sieve_header_list_set_trace(strlist->source, trace); +} + +/* + * Header override implementation + */ + +/* Context data */ + +struct svmo_mime_context { + enum ext_mime_option mimeopt; + const char *const *params; + bool anychild:1; +}; + +/* Context coding */ + +static bool svmo_mime_dump_context +(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int anychild, mimeopt; + + if ( !sieve_binary_read_byte(denv->sblock, address, &anychild) ) + return FALSE; + if ( anychild > 0 ) + sieve_code_dumpf(denv, "anychild"); + + if ( !sieve_binary_read_byte(denv->sblock, address, &mimeopt) ) + return FALSE; + + switch ( mimeopt ) { + case EXT_MIME_OPTION_NONE: + break; + case EXT_MIME_OPTION_TYPE: + sieve_code_dumpf(denv, "option: type"); + break; + case EXT_MIME_OPTION_SUBTYPE: + sieve_code_dumpf(denv, "option: subtype"); + break; + case EXT_MIME_OPTION_CONTENTTYPE: + sieve_code_dumpf(denv, "option: contenttype"); + break; + case EXT_MIME_OPTION_PARAM: + sieve_code_dumpf(denv, "option: param"); + sieve_code_descend(denv); + if ( !sieve_opr_stringlist_dump(denv, address, "param-list") ) + return FALSE; + sieve_code_ascend(denv); + break; + default: + return FALSE; + } + return TRUE; +} + +static int svmo_mime_read_context +(const struct sieve_message_override *svmo ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **ho_context) +{ + pool_t pool = sieve_result_pool(renv->result); // FIXME: investigate + struct svmo_mime_context *ctx; + unsigned int anychild = 0, mimeopt = EXT_MIME_OPTION_NONE; + struct sieve_stringlist *param_list = NULL; + int ret; + + if ( !sieve_binary_read_byte + (renv->sblock, address, &anychild) ) { + sieve_runtime_trace_error(renv, + "anychild: invalid byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_byte + (renv->sblock, address, &mimeopt) || + mimeopt > EXT_MIME_OPTION_PARAM ) { + sieve_runtime_trace_error(renv, + "option: invalid mime option code"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( mimeopt == EXT_MIME_OPTION_PARAM && + (ret=sieve_opr_stringlist_read + (renv, address, "param-list", ¶m_list)) <= 0 ) + return ret; + + ctx = p_new(pool, struct svmo_mime_context, 1); + ctx->anychild = (anychild == 0 ? FALSE : TRUE); + ctx->mimeopt = (enum ext_mime_option)mimeopt; + + if ( param_list != NULL && sieve_stringlist_read_all + (param_list, pool, &ctx->params) < 0 ) { + sieve_runtime_trace_error(renv, + "failed to read param-list operand"); + return param_list->exec_status; + } + + *ho_context = (void *) ctx; + return SIEVE_EXEC_OK; +} + +/* Override */ + +static int svmo_mime_header_override +(const struct sieve_message_override *svmo, + const struct sieve_runtime_env *renv, bool mime_decode, + struct sieve_stringlist **headers_r) +{ + struct svmo_mime_context *ctx = + (struct svmo_mime_context *)svmo->context; + struct ext_foreverypart_runtime_loop *sfploop; + struct sieve_header_list *headers; + struct sieve_stringlist *values; + int ret; + + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "header mime override:"); + sieve_runtime_trace_descend(renv); + + if ( ctx->anychild ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "headers from current mime part and children"); + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "headers from current mime part"); + } + + sfploop = ext_foreverypart_runtime_loop_get_current(renv); + if ( sfploop != NULL ) { + headers = sieve_mime_header_list_create + (renv, *headers_r, &sfploop->part_iter, + mime_decode, ctx->anychild); + } else if ( ctx->anychild ) { + struct sieve_message_part_iter part_iter; + + if ( (ret=sieve_message_part_iter_init + (&part_iter, renv)) <= 0 ) + return ret; + + headers = sieve_mime_header_list_create + (renv, *headers_r, &part_iter, mime_decode, TRUE); + } else { + headers = sieve_message_header_list_create + (renv, *headers_r, mime_decode); + } + values = &headers->strlist; + + switch ( ctx->mimeopt ) { + case EXT_MIME_OPTION_NONE: + break; + case EXT_MIME_OPTION_TYPE: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime type from header value"); + break; + case EXT_MIME_OPTION_SUBTYPE: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime subtype from header value"); + break; + case EXT_MIME_OPTION_CONTENTTYPE: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime contenttype from header value"); + break; + case EXT_MIME_OPTION_PARAM: + sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, + "extract mime parameters from header value"); + break; + default: + i_unreached(); + } + + if ( ctx->mimeopt != EXT_MIME_OPTION_NONE ) { + values = content_header_stringlist_create + (renv, headers, ctx->mimeopt, ctx->params); + } + *headers_r = values; + + sieve_runtime_trace_ascend(renv); + return SIEVE_EXEC_OK; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/notify/Makefile.am b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.am new file mode 100644 index 0000000..aaa76b3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.am @@ -0,0 +1,20 @@ +noinst_LTLIBRARIES = libsieve_ext_notify.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c \ + cmd-denotify.c + +libsieve_ext_notify_la_SOURCES = \ + ext-notify.c \ + ext-notify-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-notify-common.h \ + ext-notify-limits.h + diff --git a/pigeonhole/src/lib-sieve/plugins/notify/Makefile.in b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.in new file mode 100644 index 0000000..910007d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/Makefile.in @@ -0,0 +1,699 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/notify +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_notify_la_LIBADD = +am__objects_1 = cmd-notify.lo cmd-denotify.lo +am_libsieve_ext_notify_la_OBJECTS = ext-notify.lo ext-notify-common.lo \ + $(am__objects_1) +libsieve_ext_notify_la_OBJECTS = $(am_libsieve_ext_notify_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 = +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)/cmd-denotify.Plo \ + ./$(DEPDIR)/cmd-notify.Plo ./$(DEPDIR)/ext-notify-common.Plo \ + ./$(DEPDIR)/ext-notify.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 = $(libsieve_ext_notify_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_notify_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@ +noinst_LTLIBRARIES = libsieve_ext_notify.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-notify.c \ + cmd-denotify.c + +libsieve_ext_notify_la_SOURCES = \ + ext-notify.c \ + ext-notify-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-notify-common.h \ + ext-notify-limits.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/lib-sieve/plugins/notify/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/notify/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_notify.la: $(libsieve_ext_notify_la_OBJECTS) $(libsieve_ext_notify_la_DEPENDENCIES) $(EXTRA_libsieve_ext_notify_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_notify_la_OBJECTS) $(libsieve_ext_notify_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-denotify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-notify.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-notify-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-notify.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-denotify.Plo + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-notify-common.Plo + -rm -f ./$(DEPDIR)/ext-notify.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-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)/cmd-denotify.Plo + -rm -f ./$(DEPDIR)/cmd-notify.Plo + -rm -f ./$(DEPDIR)/ext-notify-common.Plo + -rm -f ./$(DEPDIR)/ext-notify.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/notify/cmd-denotify.c b/pigeonhole/src/lib-sieve/plugins/notify/cmd-denotify.c new file mode 100644 index 0000000..8769808 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/cmd-denotify.c @@ -0,0 +1,389 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-match-types.h" +#include "sieve-comparators.h" +#include "sieve-match.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "ext-notify-common.h" + +/* + * Denotify command + * + * Syntax: + * denotify [MATCH-TYPE string] [<":low" / ":normal" / ":high">] + */ + +static bool cmd_denotify_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_denotify_pre_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_denotify_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_denotify_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); + +const struct sieve_command_def cmd_denotify = { + .identifier = "denotify", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_denotify_registered, + .pre_validate = cmd_denotify_pre_validate, + .validate = cmd_denotify_validate, + .generate = cmd_denotify_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool tag_match_type_is_instance_of + (struct sieve_validator *validator, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data); +static bool tag_match_type_validate + (struct sieve_validator *validator, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument object */ + +const struct sieve_argument_def denotify_match_tag = { + .identifier = "MATCH-TYPE-STRING", + .is_instance_of = tag_match_type_is_instance_of, + .validate = tag_match_type_validate +}; + +/* Codes for optional operands */ + +enum cmd_denotify_optional { + OPT_END, + OPT_IMPORTANCE, + OPT_MATCH_TYPE, + OPT_MATCH_KEY +}; + +/* + * Denotify operation + */ + +static bool cmd_denotify_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_denotify_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def denotify_operation = { + .mnemonic = "DENOTIFY", + .ext_def = ¬ify_extension, + .code = EXT_NOTIFY_OPERATION_DENOTIFY, + .dump = cmd_denotify_operation_dump, + .execute = cmd_denotify_operation_execute +}; + +/* + * Command validation context + */ + +struct cmd_denotify_context_data { + struct sieve_ast_argument *match_key_arg; +}; + +/* + * Tag validation + */ + +static bool tag_match_type_is_instance_of +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data) +{ + return match_type_tag.is_instance_of(valdtr, cmd, ext, identifier, data); +} + +static bool tag_match_type_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_denotify_context_data *cmd_data = + (struct cmd_denotify_context_data *) cmd->data; + struct sieve_ast_argument *tag = *arg; + + i_assert(tag != NULL); + + if ( !match_type_tag.validate(valdtr, arg, cmd) ) + return FALSE; + + if ( *arg == NULL ) { + sieve_argument_validate_error(valdtr, tag, + "the MATCH-TYPE argument (:%s) for the denotify command requires " + "an additional key-string parameter, but no more arguments were found", + sieve_ast_argument_tag(tag)); + return FALSE; + } + + if ( sieve_ast_argument_type(*arg) != SAAT_STRING ) + { + sieve_argument_validate_error(valdtr, *arg, + "the MATCH-TYPE argument (:%s) for the denotify command requires " + "an additional key-string parameter, but %s was found", + sieve_ast_argument_tag(tag), sieve_ast_argument_name(*arg)); + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, cmd, *arg, FALSE) ) + return FALSE; + + tag->argument->def = &match_type_tag; + tag->argument->ext = NULL; + + (*arg)->argument->id_code = OPT_MATCH_KEY; + cmd_data->match_key_arg = *arg; + + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool cmd_denotify_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &denotify_match_tag, OPT_MATCH_TYPE); + + ext_notify_register_importance_tags(valdtr, cmd_reg, ext, OPT_IMPORTANCE); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_denotify_pre_validate +(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_denotify_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_denotify_context_data, 1); + cmd->data = (void *) ctx_data; + + return TRUE; +} + +static bool cmd_denotify_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct cmd_denotify_context_data *ctx_data = + (struct cmd_denotify_context_data *) cmd->data; + struct sieve_ast_argument *key_arg = ctx_data->match_key_arg; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + + if ( key_arg != NULL ) { + if ( !sieve_match_type_validate + (valdtr, cmd, key_arg, &mcht_default, &cmp_default) ) + return FALSE; + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool cmd_denotify_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &denotify_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_denotify_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + const struct sieve_operation *op = denv->oprtn; + int opt_code = 0; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_descend(denv); + + for (;;) { + int opt; + bool opok = TRUE; + + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_MATCH_KEY: + opok = sieve_opr_string_dump(denv, address, "key-string"); + break; + case OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + case OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, "importance"); + break; + default: + return FALSE; + } + + if ( !opok ) return FALSE; + } + + return TRUE; +} + +/* + * Code execution + */ + +static int cmd_denotify_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + int opt_code = 0; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_stringlist *match_key = NULL; + sieve_number_t importance = 0; + struct sieve_match_context *mctx; + struct sieve_result_iterate_context *rictx; + const struct sieve_action *action; + int ret; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_MATCH_TYPE: + ret = sieve_opr_match_type_read(renv, address, &mcht); + break; + case OPT_MATCH_KEY: + ret = sieve_opr_stringlist_read(renv, address, "match key", &match_key); + break; + case OPT_IMPORTANCE: + ret = sieve_opr_number_read(renv, address, "importance", &importance); + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( ret <= 0 ) return ret; + } + + /* + * Perform operation + */ + + /* Enforce 0 < importance < 4 (just to be sure) */ + + if ( importance < 1 ) + importance = 1; + else if ( importance > 3 ) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "denotify action"); + + /* Either do string matching or just kill all notify actions */ + if ( match_key != NULL ) { + /* Initialize match */ + mctx = sieve_match_begin(renv, &mcht, &cmp); + + /* Iterate through all notify actions and delete those that match */ + rictx = sieve_result_iterate_init(renv->result); + + while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { + if ( sieve_action_is(action, act_notify_old) ) { + struct ext_notify_action *nact = + (struct ext_notify_action *) action->context; + + if ( importance == 0 || nact->importance == importance ) { + int match; + + if ( (match=sieve_match_value + (mctx, nact->id, strlen(nact->id), match_key)) < 0 ) + break; + + if ( match > 0 ) + sieve_result_iterate_delete(rictx); + } + } + } + + /* Finish match */ + if ( sieve_match_end(&mctx, &ret) < 0 ) + return ret; + + } else { + /* Delete all notify actions */ + rictx = sieve_result_iterate_init(renv->result); + + while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { + + if ( sieve_action_is(action, act_notify_old) ) { + struct ext_notify_action *nact = + (struct ext_notify_action *) action->context; + + if ( importance == 0 || nact->importance == importance ) + sieve_result_iterate_delete(rictx); + } + } + } + + return SIEVE_EXEC_OK; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/notify/cmd-notify.c b/pigeonhole/src/lib-sieve/plugins/notify/cmd-notify.c new file mode 100644 index 0000000..a683c31 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/cmd-notify.c @@ -0,0 +1,900 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ioloop.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "message-date.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-address.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +#include "ext-notify-common.h" +#include "ext-notify-limits.h" + +#include <ctype.h> + +/* Notify command (DEPRECATED) + * + * Syntax: + * notify [":method" string] [":id" string] [":options" string-list] + * [<":low" / ":normal" / ":high">] ["message:" string] + * + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_notify_pre_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_notify_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_notify_old = { + .identifier = "notify", + .type = SCT_COMMAND, + .positional_args = 0, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_notify_registered, + .pre_validate = cmd_notify_pre_validate, + .validate = cmd_notify_validate, + .generate = cmd_notify_generate +}; + +/* + * Tagged arguments + */ + +/* Forward declarations */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def notify_method_tag = { + .identifier = "method", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_options_tag = { + .identifier = "options", + .validate = cmd_notify_validate_stringlist_tag +}; + +static const struct sieve_argument_def notify_id_tag = { + .identifier = "id", + .validate = cmd_notify_validate_string_tag +}; + +static const struct sieve_argument_def notify_message_tag = { + .identifier = "message", + .validate = cmd_notify_validate_string_tag +}; + +/* + * Notify operation + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def notify_old_operation = { + .mnemonic = "NOTIFY", + .ext_def = ¬ify_extension, + .code = EXT_NOTIFY_OPERATION_NOTIFY, + .dump = cmd_notify_operation_dump, + .execute = cmd_notify_operation_execute +}; + +/* Codes for optional operands */ + +enum cmd_notify_optional { + OPT_END, + OPT_MESSAGE, + OPT_IMPORTANCE, + OPT_OPTIONS, + OPT_ID +}; + +/* + * Notify action + */ + +/* Forward declarations */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, + void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_notify_old = { + .name = "notify", + .check_duplicate = act_notify_check_duplicate, + .print = act_notify_print, + .commit = act_notify_commit +}; + +/* + * Command validation context + */ + +struct cmd_notify_context_data { + struct sieve_ast_argument *id; + struct sieve_ast_argument *method; + struct sieve_ast_argument *options; + struct sieve_ast_argument *message; +}; + +/* + * Tag validation + */ + +static bool +cmd_notify_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Check syntax: + * :id <string> + * :method <string> + * :message <string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (sieve_argument_is(tag, notify_method_tag)) { + ctx_data->method = *arg; + + /* Removed */ + *arg = sieve_ast_arguments_detach(*arg, 1); + } else if (sieve_argument_is(tag, notify_id_tag)) { + ctx_data->id = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, notify_message_tag)) { + ctx_data->message = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } + return TRUE; +} + +static bool +cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :options string-list + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + /* Assign context */ + ctx_data->options = *arg; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_notify_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_method_tag, 0); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_id_tag, OPT_ID); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_message_tag, OPT_MESSAGE); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + ¬ify_options_tag, OPT_OPTIONS); + + ext_notify_register_importance_tags(valdtr, cmd_reg, ext, + OPT_IMPORTANCE); + + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_notify_pre_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_notify_context_data *ctx_data; + + /* Create context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_notify_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static int +cmd_notify_address_validate(void *context, struct sieve_ast_argument *arg) +{ + struct sieve_validator *valdtr = (struct sieve_validator *)context; + + if (sieve_argument_is_string_literal(arg)) { + string_t *address = sieve_ast_argument_str(arg); + const char *error; + int result; + + T_BEGIN { + result = (sieve_address_validate_str(address, &error) ? + 1 : -1); + + if (result <= 0) { + sieve_argument_validate_error( + valdtr, arg, + "specified :options address '%s' is invalid for " + "the mailto notify method: %s", + str_sanitize(str_c(address), 128), + error); + } + } T_END; + + return result; + } + + return 1; +} + +static bool +cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct cmd_notify_context_data *ctx_data = + (struct cmd_notify_context_data *)cmd->data; + + /* Check :method argument */ + if (ctx_data->method != NULL) { + const char *method = sieve_ast_argument_strc(ctx_data->method); + + if (strcasecmp(method, "mailto") != 0) { + sieve_command_validate_error( + valdtr, cmd, + "the notify command of the deprecated notify extension " + "only supports the 'mailto' notification method"); + return FALSE; + } + } + + /* Check :options argument */ + if (ctx_data->options != NULL) { + struct sieve_ast_argument *option = ctx_data->options; + + /* Parse and check options */ + if (sieve_ast_stringlist_map( + &option, (void *)valdtr, + cmd_notify_address_validate) <= 0) { + return FALSE; + } + } else { + sieve_command_validate_warning( + valdtr, cmd, + "no :options (and hence recipients) specified for the notify command"); + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_notify_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, ¬ify_old_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_notify_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "NOTIFY"); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, + "importance"); + break; + case OPT_ID: + opok = sieve_opr_string_dump(denv, address, + "id"); + break; + case OPT_OPTIONS: + opok = sieve_opr_stringlist_dump(denv, address, + "options"); + break; + case OPT_MESSAGE: + opok = sieve_opr_string_dump(denv, address, + "message"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + return TRUE; +} + +/* + * Code execution + */ + + +static int +cmd_notify_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_notify_action *act; + pool_t pool; + int opt_code = 0; + sieve_number_t importance = 1; + struct sieve_stringlist *options = NULL; + string_t *message = NULL, *id = NULL; + int ret = 0; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_IMPORTANCE: + ret = sieve_opr_number_read(renv, address, "importance", + &importance); + break; + case OPT_ID: + ret = sieve_opr_string_read(renv, address, "id", &id); + break; + case OPT_MESSAGE: + ret = sieve_opr_string_read(renv, address, "from", + &message); + break; + case OPT_OPTIONS: + ret = sieve_opr_stringlist_read(renv, address, + "options", &options); + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) return ret; + } + + /* + * Perform operation + */ + + /* Enforce 0 < importance < 4 (just to be sure) */ + + if (importance < 1) + importance = 1; + else if (importance > 3) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "notify action"); + + /* Compose action */ + if (options != NULL) { + string_t *raw_address; + string_t *out_message; + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct ext_notify_action, 1); + if (id != NULL) + act->id = p_strdup(pool, str_c(id)); + act->importance = importance; + + /* Process message */ + + out_message = t_str_new(1024); + if ((ret = ext_notify_construct_message( + renv, (message == NULL ? NULL : str_c(message)), + out_message)) <= 0) + return ret; + act->message = p_strdup(pool, str_c(out_message)); + + /* Normalize and verify all :options addresses */ + + sieve_stringlist_reset(options); + + p_array_init(&act->recipients, pool, 4); + + raw_address = NULL; + while ((ret = sieve_stringlist_next_item( + options, &raw_address)) > 0) { + const char *error = NULL; + const struct smtp_address *address; + + /* Add if valid address */ + address = sieve_address_parse_str(raw_address, &error); + if (address != NULL) { + const struct ext_notify_recipient *rcpts; + unsigned int rcpt_count, i; + + /* Prevent duplicates */ + rcpts = array_get(&act->recipients, &rcpt_count); + + for (i = 0; i < rcpt_count; i++) { + if (smtp_address_equals(rcpts[i].address, + address)) + break; + } + + /* Add only if unique */ + if (i != rcpt_count) { + sieve_runtime_warning( + renv, NULL, + "duplicate recipient '%s' specified in the :options argument of " + "the deprecated notify command", + str_sanitize(str_c(raw_address), 128)); + + } else if (array_count(&act->recipients) >= + EXT_NOTIFY_MAX_RECIPIENTS) { + sieve_runtime_warning(renv, NULL, + "more than the maximum %u recipients are specified " + "for the deprecated notify command; " + "the rest is discarded", + EXT_NOTIFY_MAX_RECIPIENTS); + break; + + } else { + struct ext_notify_recipient recipient; + + recipient.full = + p_strdup(pool, str_c(raw_address)); + recipient.address = + smtp_address_clone(pool, address); + + array_append(&act->recipients, &recipient, 1); + } + } else { + sieve_runtime_error( + renv, NULL, + "specified :options address '%s' is invalid for " + "the deprecated notify command: %s", + str_sanitize(str_c(raw_address), 128), error); + return SIEVE_EXEC_FAILURE; + } + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid options stringlist"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (sieve_result_add_action(renv, this_ext, "notify", + &act_notify_old, NULL, (void *)act, + 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + } + + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_notify_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act ATTR_UNUSED, + const struct sieve_action *act_other ATTR_UNUSED) +{ + struct ext_notify_action *new_nact, *old_nact; + const struct ext_notify_recipient *new_rcpts; + const struct ext_notify_recipient *old_rcpts; + unsigned int new_count, old_count, i, j; + unsigned int del_start = 0, del_len = 0; + + if (act->context == NULL || act_other->context == NULL) + return 0; + + new_nact = (struct ext_notify_action *)act->context; + old_nact = (struct ext_notify_action *)act_other->context; + + new_rcpts = array_get(&new_nact->recipients, &new_count); + old_rcpts = array_get(&old_nact->recipients, &old_count); + + for (i = 0; i < new_count; i++) { + for (j = 0; j < old_count; j++) { + if (smtp_address_equals(new_rcpts[i].address, + old_rcpts[j].address)) + break; + } + + if (j == old_count) { + /* Not duplicate */ + if (del_len > 0) { + /* Perform pending deletion */ + array_delete(&new_nact->recipients, + del_start, del_len); + + /* Make sure the loop integrity is maintained */ + i -= del_len; + new_rcpts = array_get(&new_nact->recipients, + &new_count); + } + + del_len = 0; + } else { + /* Mark deletion */ + if (del_len == 0) + del_start = i; + del_len++; + } + } + + /* Perform pending deletion */ + if (del_len > 0) + array_delete(&new_nact->recipients, del_start, del_len); + + return (array_count(&new_nact->recipients) > 0 ? 0 : 1); +} + +/* Result printing */ + +static void +act_notify_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct ext_notify_action *act = + (const struct ext_notify_action *)action->context; + const struct ext_notify_recipient *recipients; + unsigned int count, i; + + sieve_result_action_printf( + rpenv, "send (deprecated) notification with method 'mailto':"); + + /* Print main method parameters */ + + sieve_result_printf(rpenv, " => importance : %llu\n", + (unsigned long long)act->importance); + + if (act->message != NULL) { + sieve_result_printf( + rpenv, " => message : %s\n", act->message); + } + if (act->id != NULL) { + sieve_result_printf( + rpenv, " => id : %s \n", act->id); + } + + /* Print mailto: recipients */ + + sieve_result_printf(rpenv, " => recipients :\n"); + + recipients = array_get(&act->recipients, &count); + if (count == 0) { + sieve_result_printf( + rpenv, " NONE, action has no effect\n"); + } else { + for (i = 0; i < count; i++) { + sieve_result_printf( + rpenv, " + To: %s\n", recipients[i].full); + } + } + + /* Finish output with an empty line */ + + sieve_result_printf(rpenv, "\n"); +} + +/* Result execution */ + +static bool contains_8bit(const char *msg) +{ + const unsigned char *s = (const unsigned char *)msg; + + for (; *s != '\0'; s++) { + if ((*s & 0x80) != 0) + return TRUE; + } + return FALSE; +} + +static bool +act_notify_send(const struct sieve_action_exec_env *aenv, + const struct ext_notify_action *act) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_script_env *senv = eenv->scriptenv; + const struct ext_notify_recipient *recipients; + struct sieve_smtp_context *sctx; + unsigned int count, i; + struct ostream *output; + string_t *msg, *to, *all; + const char *outmsgid, *error; + int ret; + + /* Get recipients */ + recipients = array_get(&act->recipients, &count); + if (count == 0) { + sieve_result_warning( + aenv, "notify action specifies no recipients; " + "action has no effect"); + return TRUE; + } + + /* Just to be sure */ + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning( + aenv, "notify action has no means to send mail"); + return TRUE; + } + + /* Compose common headers */ + msg = t_str_new(512); + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + + /* Set importance */ + switch (act->importance) { + case 1: + rfc2822_header_write(msg, "X-Priority", "1 (Highest)"); + rfc2822_header_write(msg, "Importance", "High"); + break; + case 3: + rfc2822_header_write(msg, "X-Priority", "5 (Lowest)"); + rfc2822_header_write(msg, "Importance", "Low"); + break; + case 2: + default: + rfc2822_header_write(msg, "X-Priority", "3 (Normal)"); + rfc2822_header_write(msg, "Importance", "Normal"); + break; + } + + rfc2822_header_write(msg, "From", sieve_get_postmaster_address(senv)); + + rfc2822_header_write(msg, "Subject", "[SIEVE] New mail notification"); + + rfc2822_header_write(msg, "Auto-Submitted", "auto-generated (notify)"); + rfc2822_header_write(msg, "Precedence", "bulk"); + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + if (contains_8bit(act->message)) { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + } else { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=us-ascii"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + } + + outmsgid = sieve_message_get_new_id(eenv->svinst); + rfc2822_header_write(msg, "Message-ID", outmsgid); + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 && + sieve_message_get_sender(aenv->msgctx) != NULL) { + sctx = sieve_smtp_start(senv, sieve_get_postmaster_smtp(senv)); + } else { + sctx = sieve_smtp_start(senv, NULL); + } + + /* Add all recipients (and compose To header field) */ + to = t_str_new(128); + all = t_str_new(256); + for (i = 0; i < count; i++) { + sieve_smtp_add_rcpt(sctx, recipients[i].address); + if (i > 0) + str_append(to, ", "); + str_append(to, recipients[i].full); + if (i < 3) { + if (i > 0) + str_append(all, ", "); + str_append(all, smtp_address_encode_path( + recipients[i].address)); + } else if (i == 3) { + str_printfa(all, ", ... (%u total)", count); + } + } + + rfc2822_header_write_address(msg, "To", str_c(to)); + + /* Generate message body */ + str_printfa(msg, "\r\n%s\r\n", act->message); + + output = sieve_smtp_send(sctx); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to send mail notification to %s: " + "%s (temporary failure)", str_c(all), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error( + aenv, "failed to send mail notification to %s: " + "%s (permanent failure)", str_c(all), + str_sanitize(error, 512)); + } + } else { + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("notify_target", str_c(all)); + + sieve_result_event_log(aenv, e->event(), + "sent mail notification to %s", + str_c(all)); + } + + return TRUE; +} + +static int +act_notify_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct mail *mail = eenv->msgdata->mail; + const struct ext_notify_action *act = + (const struct ext_notify_action *)aenv->action->context; + const char *const *hdsp; + bool result; + int ret; + + /* Is the message an automatic reply ? */ + if ((ret = mail_get_headers(mail, "auto-submitted", &hdsp)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read `auto-submitted' header field"); + } + + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + while (*hdsp != NULL) { + if (strcasecmp(*hdsp, "no") != 0) { + const struct smtp_address *sender = NULL; + const char *from; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) + sender = sieve_message_get_sender(aenv->msgctx); + from = (sender == NULL ? "" : + t_strdup_printf(" from <%s>", + smtp_address_encode(sender))); + + sieve_result_global_log( + aenv, + "not sending notification for auto-submitted message%s", + from); + return SIEVE_EXEC_OK; + } + hdsp++; + } + } + + T_BEGIN { + result = act_notify_send(aenv, act); + } T_END; + + if (!result) + return SIEVE_EXEC_FAILURE; + eenv->exec_status->significant_action_executed = TRUE; + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.c b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.c new file mode 100644 index 0000000..589b21b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.c @@ -0,0 +1,361 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "istream.h" +#include "rfc822-parser.h" +#include "message-parser.h" +#include "message-decoder.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-code.h" +#include "sieve-message.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" + +#include "ext-notify-common.h" + +#include <ctype.h> + +/* + * Importance argument + */ + +static bool +tag_importance_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +static const struct sieve_argument_def importance_low_tag = { + .identifier = "low", + .validate = tag_importance_validate, +}; + +static const struct sieve_argument_def importance_normal_tag = { + .identifier = "normal", + .validate = tag_importance_validate, +}; + +static const struct sieve_argument_def importance_high_tag = { + .identifier = "high", + .validate = tag_importance_validate, +}; + +static bool +tag_importance_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct sieve_ast_argument *tag = *arg; + + if (sieve_argument_is(tag, importance_low_tag)) + sieve_ast_argument_number_substitute(tag, 3); + else if (sieve_argument_is(tag, importance_normal_tag)) + sieve_ast_argument_number_substitute(tag, 2); + else + sieve_ast_argument_number_substitute(tag, 1); + + tag->argument = sieve_argument_create(tag->ast, &number_argument, + tag->argument->ext, + tag->argument->id_code); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +void ext_notify_register_importance_tags( + struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *ext, unsigned int id_code) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &importance_low_tag, id_code); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &importance_normal_tag, id_code); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &importance_high_tag, id_code); +} + +/* + * Body extraction + */ + +/* FIXME: overlaps somewhat with body extension */ + +struct ext_notify_message_context { + pool_t pool; + buffer_t *body_text; +}; + +static struct ext_notify_message_context * +ext_notify_get_message_context(const struct sieve_extension *this_ext, + struct sieve_message_context *msgctx) +{ + struct ext_notify_message_context *ctx; + + /* Get message context (contains cached message body information) */ + ctx = (struct ext_notify_message_context *) + sieve_message_context_extension_get(msgctx, this_ext); + + /* Create it if it does not exist already */ + if (ctx == NULL) { + pool_t pool = sieve_message_context_pool(msgctx); + ctx = p_new(pool, struct ext_notify_message_context, 1); + ctx->pool = pool; + ctx->body_text = NULL; + + /* Register context */ + sieve_message_context_extension_set(msgctx, this_ext, + (void *)ctx); + } + + return ctx; +} + +static bool _is_text_content(const struct message_header_line *hdr) +{ + struct rfc822_parser_context parser; + string_t *content_type; + const char *data; + + /* Initialize parsing */ + rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse content type */ + content_type = t_str_new(64); + if (rfc822_parse_content_type(&parser, content_type) < 0) + return FALSE; + + /* Content-type value must end here, otherwise it is invalid after all + */ + (void)rfc822_skip_lwsp(&parser); + if (parser.data != parser.end && *parser.data != ';') + return FALSE; + + /* Success */ + data = str_c(content_type); + if (str_begins(data, "text/")) + return TRUE; + return FALSE; +} + +static int +cmd_notify_extract_body_text(const struct sieve_runtime_env *renv, + const char **body_text_r, size_t *body_size_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct ext_notify_message_context *mctx; + struct mail *mail = eenv->msgdata->mail; + struct message_parser_ctx *parser; + struct message_decoder_context *decoder; + struct message_part *parts; + struct message_block block, decoded; + struct istream *input; + bool is_text, save_body; + int ret = 1; + + *body_text_r = NULL; + *body_size_r = 0; + + /* Return cached result if available */ + mctx = ext_notify_get_message_context(this_ext, renv->msgctx); + if (mctx->body_text != NULL) { + *body_text_r = (const char *) + buffer_get_data(mctx->body_text, body_size_r); + return SIEVE_EXEC_OK; + } + + /* Create buffer */ + mctx->body_text = buffer_create_dynamic(mctx->pool, 1024*64); + + /* Get the message stream */ + if (mail_get_stream(mail, NULL, NULL, &input) < 0) { + return sieve_runtime_mail_error(renv, mail, "notify action: " + "failed to read input message"); + } + + /* Initialize body decoder */ + decoder = message_decoder_init(NULL, 0); + + struct message_parser_settings mparser_set = { + .hdr_flags = 0, + .flags = 0, + }; + parser = message_parser_init(mctx->pool, input, &mparser_set); + is_text = TRUE; + save_body = FALSE; + while ((ret = message_parser_parse_next_block(parser, &block)) > 0) { + if (block.hdr != NULL || block.size == 0) { + /* Decode block */ + (void)message_decoder_decode_next_block(decoder, &block, + &decoded); + + /* Check for end of headers */ + if (block.hdr == NULL) { + save_body = is_text; + continue; + } + + /* We're interested of only Content-Type: header */ + if (strcasecmp(block.hdr->name, "Content-Type") != 0) + continue; + + /* Header can have folding whitespace. Acquire the full + value before continuing */ + if (block.hdr->continues) { + block.hdr->use_full_value = TRUE; + continue; + } + + /* Is it a text part? */ + T_BEGIN { + is_text = _is_text_content(block.hdr); + } T_END; + + continue; + } + + /* Read text body */ + if (save_body) { + (void)message_decoder_decode_next_block(decoder, &block, + &decoded); + buffer_append(mctx->body_text, decoded.data, + decoded.size); + is_text = TRUE; + } + } + + /* Cleanup */ + (void)message_parser_deinit(&parser, &parts); + message_decoder_deinit(&decoder); + + if (ret < 0 && input->stream_errno != 0) { + sieve_runtime_critical(renv, NULL, "notify action: " + "failed to read input message", + "notify action: read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + return SIEVE_EXEC_TEMP_FAILURE; + } + + /* Return status */ + *body_text_r = (const char *)buffer_get_data(mctx->body_text, + body_size_r); + return SIEVE_EXEC_OK; +} + +int ext_notify_construct_message(const struct sieve_runtime_env *renv, + const char *msg_format, + string_t *out_msg) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + struct sieve_message_context *msgctx = renv->msgctx; + const struct smtp_address *return_path = + sieve_message_get_sender(msgctx); + const char *p; + int ret; + + if (msg_format == NULL) + msg_format = "$from$: $subject$"; + + /* Scan message for substitutions */ + p = msg_format; + while (*p != '\0') { + const char *header; + + if (strncasecmp(p, "$from$", 6) == 0) { + p += 6; + + /* Fetch sender from original message */ + if ((ret = mail_get_first_header_utf8( + msgdata->mail, "from", &header)) < 0) { + return sieve_runtime_mail_error( + renv, msgdata->mail, + "failed to read header field `from'"); + } + if (ret > 0) + str_append(out_msg, header); + } else if (strncasecmp(p, "$env-from$", 10) == 0) { + p += 10; + + if (return_path != NULL) + smtp_address_write(out_msg, return_path); + } else if (strncasecmp(p, "$subject$", 9) == 0) { + p += 9; + + /* Fetch sender from oriinal message */ + if ((ret = mail_get_first_header_utf8( + msgdata->mail, "subject", &header)) < 0) { + return sieve_runtime_mail_error( + renv, msgdata->mail, + "failed to read header field `subject'"); + } + if (ret > 0) + str_append(out_msg, header); + } else if (strncasecmp(p, "$text", 5) == 0 && + (p[5] == '[' || p[5] == '$')) { + size_t num = 0; + const char *begin = p; + bool valid = TRUE; + + p += 5; + if (*p == '[') { + p += 1; + + while (i_isdigit(*p)) { + num = num * 10 + (*p - '0'); + p++; + } + + if (*p++ != ']' || *p++ != '$') { + str_append_data(out_msg, begin, + p-begin); + valid = FALSE; + } + } else { + p += 1; + } + + if (valid) { + size_t body_size; + const char *body_text; + + if ((ret = cmd_notify_extract_body_text( + renv, &body_text, &body_size)) <= 0) + return ret; + + if (num > 0 && num < body_size) { + str_append_data(out_msg, body_text, + num); + } else { + str_append_data(out_msg, body_text, + body_size); + } + } + } else { + size_t len; + + /* Find next substitution */ + len = strcspn(p + 1, "$") + 1; + + /* Copy normal text */ + str_append_data(out_msg, p, len); + p += len; + } + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.h b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.h new file mode 100644 index 0000000..09db2cb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-common.h @@ -0,0 +1,66 @@ +#ifndef EXT_NOTIFY_COMMON_H +#define EXT_NOTIFY_COMMON_H + +/* + * Extension + */ + +extern const struct sieve_extension_def notify_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_notify_old; +extern const struct sieve_command_def cmd_denotify; + +/* + * Arguments + */ + +void ext_notify_register_importance_tags( + struct sieve_validator *valdtr, + struct sieve_command_registration *cmd_reg, + const struct sieve_extension *this_ext, unsigned int id_code); + +/* + * Operations + */ + +extern const struct sieve_operation_def notify_old_operation; +extern const struct sieve_operation_def denotify_operation; + +enum ext_notify_opcode { + EXT_NOTIFY_OPERATION_NOTIFY, + EXT_NOTIFY_OPERATION_DENOTIFY, +}; + +/* + * Actions + */ + +extern const struct sieve_action_def act_notify_old; + +struct ext_notify_recipient { + const char *full; + const struct smtp_address *address; +}; + +ARRAY_DEFINE_TYPE(recipients, struct ext_notify_recipient); + +struct ext_notify_action { + const char *id; + const char *message; + sieve_number_t importance; + + ARRAY_TYPE(recipients) recipients; +}; + +/* + * Message construct + */ + +int ext_notify_construct_message(const struct sieve_runtime_env *renv, + const char *msg_format, string_t *out_msg); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-limits.h b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-limits.h new file mode 100644 index 0000000..5fab7cb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify-limits.h @@ -0,0 +1,7 @@ +#ifndef EXT_NOTIFY_LIMITS_H +#define EXT_NOTIFY_LIMITS_H + +#define EXT_NOTIFY_MAX_RECIPIENTS 8 +#define EXT_NOTIFY_MAX_MESSAGE 256 + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/notify/ext-notify.c b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify.c new file mode 100644 index 0000000..e79e049 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/notify/ext-notify.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension notify + * ---------------- + * + * Authors: Stephan Bosch + * Specification: draft-ietf-sieve-notify-00.txt + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-notify-common.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_notify_operations[] = { + ¬ify_old_operation, + &denotify_operation +}; + +/* + * Extension + */ + +static bool ext_notify_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def notify_extension = { + .name = "notify", + .validator_load = ext_notify_validator_load, + SIEVE_EXT_DEFINE_OPERATIONS(ext_notify_operations) +}; + +/* + * Extension validation + */ + +static bool ext_notify_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); +static bool ext_notify_validator_validate + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); + +const struct sieve_validator_extension notify_validator_extension = { + .ext = ¬ify_extension, + .check_conflict = ext_notify_validator_check_conflict, + .validate = ext_notify_validator_validate +}; + +static bool ext_notify_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register validator extension to check for conflict with enotify */ + sieve_validator_extension_register + (valdtr, ext, ¬ify_validator_extension, NULL); + return TRUE; +} + +static bool ext_notify_validator_check_conflict +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + /* Check for conflict with enotify */ + if ( sieve_extension_name_is(ext_other, "enotify") ) { + sieve_argument_validate_error(valdtr, require_arg, + "the (deprecated) notify extension cannot be used " + "together with the enotify extension"); + return FALSE; + } + + return TRUE; +} + +static bool ext_notify_validator_validate +(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg ATTR_UNUSED, + bool required ATTR_UNUSED) +{ + /* No conflicts: register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_notify_old); + sieve_validator_register_command(valdtr, ext, &cmd_denotify); + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/regex/Makefile.am b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.am new file mode 100644 index 0000000..eeb735e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libsieve_ext_regex.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_regex_la_SOURCES = \ + mcht-regex.c \ + ext-regex-common.c \ + ext-regex.c + +noinst_HEADERS = \ + ext-regex-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/regex/Makefile.in b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.in new file mode 100644 index 0000000..379d384 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/Makefile.in @@ -0,0 +1,688 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/regex +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_regex_la_LIBADD = +am_libsieve_ext_regex_la_OBJECTS = mcht-regex.lo ext-regex-common.lo \ + ext-regex.lo +libsieve_ext_regex_la_OBJECTS = $(am_libsieve_ext_regex_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 = +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)/ext-regex-common.Plo \ + ./$(DEPDIR)/ext-regex.Plo ./$(DEPDIR)/mcht-regex.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 = $(libsieve_ext_regex_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_regex_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@ +noinst_LTLIBRARIES = libsieve_ext_regex.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_regex_la_SOURCES = \ + mcht-regex.c \ + ext-regex-common.c \ + ext-regex.c + +noinst_HEADERS = \ + ext-regex-common.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/lib-sieve/plugins/regex/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/regex/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_regex.la: $(libsieve_ext_regex_la_OBJECTS) $(libsieve_ext_regex_la_DEPENDENCIES) $(EXTRA_libsieve_ext_regex_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_regex_la_OBJECTS) $(libsieve_ext_regex_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-regex-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-regex.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-regex.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-regex-common.Plo + -rm -f ./$(DEPDIR)/ext-regex.Plo + -rm -f ./$(DEPDIR)/mcht-regex.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-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)/ext-regex-common.Plo + -rm -f ./$(DEPDIR)/ext-regex.Plo + -rm -f ./$(DEPDIR)/mcht-regex.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/regex/ext-regex-common.c b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.c new file mode 100644 index 0000000..975f4fb --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.c @@ -0,0 +1,22 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-match-types.h" + +#include "ext-regex-common.h" + +/* + * Regex match type operand + */ + +static const struct sieve_extension_objects ext_match_types = + SIEVE_EXT_DEFINE_MATCH_TYPE(regex_match_type); + +const struct sieve_operand_def regex_match_type_operand = { + .name = "regex match", + .ext_def = ®ex_extension, + .class = &sieve_match_type_operand_class, + .interface = &ext_match_types +}; + diff --git a/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.h b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.h new file mode 100644 index 0000000..e9d809f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex-common.h @@ -0,0 +1,24 @@ +#ifndef EXT_REGEX_COMMON_H +#define EXT_REGEX_COMMON_H + +/* + * Extension + */ + +extern const struct sieve_extension_def regex_extension; + +/* + * Operand + */ + +extern const struct sieve_operand_def regex_match_type_operand; + +/* + * Match type + */ + +extern const struct sieve_match_type_def regex_match_type; + +#endif + + diff --git a/pigeonhole/src/lib-sieve/plugins/regex/ext-regex.c b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex.c new file mode 100644 index 0000000..0440b30 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/ext-regex.c @@ -0,0 +1,65 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension regex + * --------------- + * + * Authors: Stephan Bosch + * Specification: draft-murchison-sieve-regex-08 (not latest) + * Implementation: full + * Status: testing + * + */ + +/* FIXME: Regular expressions are compiled during compilation and + * again during interpretation. This is suboptimal and should be + * changed. This requires dumping the compiled regex to the binary. + * Most likely, this will only be possible when we implement regular + * expressions ourselves. + * + */ + +#include "lib.h" +#include "mempool.h" +#include "buffer.h" + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" + +#include "sieve-comparators.h" +#include "sieve-match-types.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-regex-common.h" + +#include <sys/types.h> +#include <regex.h> + +/* + * Extension + */ + +static bool ext_regex_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def regex_extension = { + .name = "regex", + .validator_load = ext_regex_validator_load, + SIEVE_EXT_DEFINE_OPERAND(regex_match_type_operand) +}; + +static bool ext_regex_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_match_type_register(valdtr, ext, ®ex_match_type); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/regex/mcht-regex.c b/pigeonhole/src/lib-sieve/plugins/regex/mcht-regex.c new file mode 100644 index 0000000..f0c630e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/regex/mcht-regex.c @@ -0,0 +1,385 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':regex' + */ + +#include "lib.h" +#include "mempool.h" +#include "buffer.h" +#include "array.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-limits.h" +#include "sieve-ast.h" +#include "sieve-stringlist.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-interpreter.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-match.h" + +#include "ext-regex-common.h" + +#include <sys/types.h> +#include <regex.h> +#include <ctype.h> + +/* + * Configuration + */ + +#define MCHT_REGEX_MAX_SUBSTITUTIONS SIEVE_MAX_MATCH_VALUES + +/* + * Match type + */ + +static bool mcht_regex_validate_context +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_match_type_context *ctx, struct sieve_ast_argument *key_arg); + +static void mcht_regex_match_init(struct sieve_match_context *mctx); +static int mcht_regex_match_keys + (struct sieve_match_context *mctx, const char *val, size_t val_size, + struct sieve_stringlist *key_list); +static void mcht_regex_match_deinit(struct sieve_match_context *mctx); + +const struct sieve_match_type_def regex_match_type = { + SIEVE_OBJECT("regex", ®ex_match_type_operand, 0), + .validate_context = mcht_regex_validate_context, + .match_init = mcht_regex_match_init, + .match_keys = mcht_regex_match_keys, + .match_deinit = mcht_regex_match_deinit +}; + +/* + * Match type validation + */ + +/* Wrapper around the regerror function for easy access */ +static const char *_regexp_error(regex_t *regexp, int errorcode) +{ + size_t errsize = regerror(errorcode, regexp, NULL, 0); + + if ( errsize > 0 ) { + char *errbuf; + + buffer_t *error_buf = + buffer_create_dynamic(pool_datastack_create(), errsize); + errbuf = buffer_get_space_unsafe(error_buf, 0, errsize); + + errsize = regerror(errorcode, regexp, errbuf, errsize); + + /* We don't want the error to start with a capital letter */ + errbuf[0] = i_tolower(errbuf[0]); + + buffer_append_space_unsafe(error_buf, errsize); + + return str_c(error_buf); + } + + return ""; +} + +static int mcht_regex_validate_regexp +(struct sieve_validator *valdtr, + struct sieve_match_type_context *mtctx ATTR_UNUSED, + struct sieve_ast_argument *key, int cflags) +{ + int ret; + regex_t regexp; + const char *regex_str = sieve_ast_argument_strc(key); + + if ( (ret=regcomp(®exp, regex_str, cflags)) != 0 ) { + sieve_argument_validate_error(valdtr, key, + "invalid regular expression '%s' for regex match: %s", + str_sanitize(regex_str, 128), _regexp_error(®exp, ret)); + + regfree(®exp); + return -1; + } + + regfree(®exp); + return 1; +} + +struct _regex_key_context { + struct sieve_validator *valdtr; + struct sieve_match_type_context *mtctx; + int cflags; +}; + +static int mcht_regex_validate_key_argument +(void *context, struct sieve_ast_argument *key) +{ + struct _regex_key_context *keyctx = (struct _regex_key_context *) context; + + /* FIXME: We can currently only handle string literal argument, so + * variables are not allowed. + */ + if ( sieve_argument_is_string_literal(key) ) { + return mcht_regex_validate_regexp + (keyctx->valdtr, keyctx->mtctx, key, keyctx->cflags); + } + + return 1; +} + +static bool mcht_regex_validate_context +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_match_type_context *mtctx, struct sieve_ast_argument *key_arg) +{ + const struct sieve_comparator *cmp = mtctx->comparator; + int cflags = REG_EXTENDED | REG_NOSUB; + struct _regex_key_context keyctx; + struct sieve_ast_argument *kitem; + + if ( cmp != NULL ) { + if ( sieve_comparator_is(cmp, i_ascii_casemap_comparator) ) + cflags = REG_EXTENDED | REG_NOSUB | REG_ICASE; + else if ( sieve_comparator_is(cmp, i_octet_comparator) ) + cflags = REG_EXTENDED | REG_NOSUB; + else { + sieve_argument_validate_error(valdtr, mtctx->argument, + "regex match type only supports " + "i;octet and i;ascii-casemap comparators" ); + return FALSE; + } + } + + /* Validate regular expression keys */ + + keyctx.valdtr = valdtr; + keyctx.mtctx = mtctx; + keyctx.cflags = cflags; + + kitem = key_arg; + if ( sieve_ast_stringlist_map(&kitem, (void *) &keyctx, + mcht_regex_validate_key_argument) <= 0 ) + return FALSE; + + return TRUE; +} + +/* + * Match type implementation + */ + +struct mcht_regex_key { + regex_t regexp; + int status; +}; + +struct mcht_regex_context { + ARRAY(struct mcht_regex_key) reg_expressions; + regmatch_t *pmatch; + size_t nmatch; + bool all_compiled:1; +}; + +static void mcht_regex_match_init +(struct sieve_match_context *mctx) +{ + pool_t pool = mctx->pool; + struct mcht_regex_context *ctx; + + /* Create context */ + ctx = p_new(pool, struct mcht_regex_context, 1); + + /* Create storage for match values if match values are requested */ + if ( sieve_match_values_are_enabled(mctx->runenv) ) { + ctx->pmatch = p_new(pool, regmatch_t, MCHT_REGEX_MAX_SUBSTITUTIONS); + ctx->nmatch = MCHT_REGEX_MAX_SUBSTITUTIONS; + } else { + ctx->pmatch = NULL; + ctx->nmatch = 0; + } + + /* Assign context */ + mctx->data = (void *) ctx; +} + +static int mcht_regex_match_key +(struct sieve_match_context *mctx, const char *val, + const regex_t *regexp) +{ + struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; + int ret; + + /* Execute regex */ + + ret = regexec(regexp, val, ctx->nmatch, ctx->pmatch, 0); + + /* Handle match values if necessary */ + + if ( ret == 0 ) { + if ( ctx->nmatch > 0 ) { + struct sieve_match_values *mvalues; + size_t i; + int skipped = 0; + string_t *subst = t_str_new(32); + + /* Start new list of match values */ + mvalues = sieve_match_values_start(mctx->runenv); + + i_assert( mvalues != NULL ); + + /* Add match values from regular expression */ + for ( i = 0; i < ctx->nmatch; i++ ) { + str_truncate(subst, 0); + + if ( ctx->pmatch[i].rm_so != -1 ) { + if ( skipped > 0 ) { + sieve_match_values_skip(mvalues, skipped); + skipped = 0; + } + + str_append_data(subst, val + ctx->pmatch[i].rm_so, + ctx->pmatch[i].rm_eo - ctx->pmatch[i].rm_so); + sieve_match_values_add(mvalues, subst); + } else + skipped++; + } + + /* Substitute the new match values */ + sieve_match_values_commit(mctx->runenv, &mvalues); + } + + return 1; + } + + return 0; +} + +static int mcht_regex_match_keys +(struct sieve_match_context *mctx, const char *val, size_t val_size ATTR_UNUSED, + struct sieve_stringlist *key_list) +{ + const struct sieve_runtime_env *renv = mctx->runenv; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; + const struct sieve_comparator *cmp = mctx->comparator; + int match; + + if ( !ctx->all_compiled ) { + string_t *key_item = NULL; + unsigned int i; + int ret; + + /* Regular expressions still need to be compiled */ + + if ( !array_is_created(&ctx->reg_expressions) ) + p_array_init(&ctx->reg_expressions, mctx->pool, 16); + + i = 0; + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) { + + T_BEGIN { + struct mcht_regex_key *rkey; + + if ( i >= array_count(&ctx->reg_expressions) ) { + int cflags; + + rkey = array_append_space(&ctx->reg_expressions); + + /* Configure case-sensitivity according to comparator */ + if ( sieve_comparator_is(cmp, i_octet_comparator) ) + cflags = REG_EXTENDED; + else if ( sieve_comparator_is(cmp, i_ascii_casemap_comparator) ) + cflags = REG_EXTENDED | REG_ICASE; + else + rkey->status = -1; /* Not supported */ + + if ( rkey->status >= 0 ) { + const char *regex_str = str_c(key_item); + int rxret; + + /* Indicate whether match values need to be produced */ + if ( ctx->nmatch == 0 ) cflags |= REG_NOSUB; + + /* Compile regular expression */ + if ( (rxret=regcomp(&rkey->regexp, regex_str, cflags)) != 0 ) { + sieve_runtime_error(renv, NULL, + "invalid regular expression '%s' for regex match: %s", + str_sanitize(regex_str, 128), + _regexp_error(&rkey->regexp, rxret)); + rkey->status = -1; + } else { + rkey->status = 1; + } + } + } else { + rkey = array_idx_modifiable(&ctx->reg_expressions, 1); + } + + if ( rkey->status > 0 ) { + match = mcht_regex_match_key(mctx, val, &rkey->regexp); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with regex `%s' [id=%d] => %d", + str_sanitize(str_c(key_item), 80), + array_count(&ctx->reg_expressions)-1, match); + } + } + } T_END; + + i++; + } + + if ( ret == 0 ) { + ctx->all_compiled = TRUE; + } else if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + + } else { + const struct mcht_regex_key *rkeys; + unsigned int i, count; + + /* Regular expressions are compiled */ + + rkeys = array_get(&ctx->reg_expressions, &count); + + i = 0; + match = 0; + while ( match == 0 && i < count ) { + if ( rkeys[i].status > 0 ) { + match = mcht_regex_match_key(mctx, val, &rkeys[i].regexp); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with compiled regex [id=%d] => %d", i, match); + } + } + + i++; + } + } + + return match; +} + +void mcht_regex_match_deinit +(struct sieve_match_context *mctx) +{ + struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; + struct mcht_regex_key *rkeys; + unsigned int count, i; + + /* Clean up compiled regular expressions */ + if ( array_is_created(&ctx->reg_expressions) ) { + rkeys = array_get_modifiable(&ctx->reg_expressions, &count); + for ( i = 0; i < count; i++ ) { + regfree(&rkeys[i].regexp); + } + } +} + diff --git a/pigeonhole/src/lib-sieve/plugins/relational/Makefile.am b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.am new file mode 100644 index 0000000..dd28cc5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.am @@ -0,0 +1,14 @@ +noinst_LTLIBRARIES = libsieve_ext_relational.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_relational_la_SOURCES = \ + ext-relational-common.c \ + mcht-value.c \ + mcht-count.c \ + ext-relational.c + +noinst_HEADERS = \ + ext-relational-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/relational/Makefile.in b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.in new file mode 100644 index 0000000..4977808 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/Makefile.in @@ -0,0 +1,694 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/relational +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_relational_la_LIBADD = +am_libsieve_ext_relational_la_OBJECTS = ext-relational-common.lo \ + mcht-value.lo mcht-count.lo ext-relational.lo +libsieve_ext_relational_la_OBJECTS = \ + $(am_libsieve_ext_relational_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 = +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)/ext-relational-common.Plo \ + ./$(DEPDIR)/ext-relational.Plo ./$(DEPDIR)/mcht-count.Plo \ + ./$(DEPDIR)/mcht-value.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 = $(libsieve_ext_relational_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_relational_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@ +noinst_LTLIBRARIES = libsieve_ext_relational.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_relational_la_SOURCES = \ + ext-relational-common.c \ + mcht-value.c \ + mcht-count.c \ + ext-relational.c + +noinst_HEADERS = \ + ext-relational-common.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/lib-sieve/plugins/relational/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/relational/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_relational.la: $(libsieve_ext_relational_la_OBJECTS) $(libsieve_ext_relational_la_DEPENDENCIES) $(EXTRA_libsieve_ext_relational_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_relational_la_OBJECTS) $(libsieve_ext_relational_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-relational-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-relational.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-count.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcht-value.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-relational-common.Plo + -rm -f ./$(DEPDIR)/ext-relational.Plo + -rm -f ./$(DEPDIR)/mcht-count.Plo + -rm -f ./$(DEPDIR)/mcht-value.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-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)/ext-relational-common.Plo + -rm -f ./$(DEPDIR)/ext-relational.Plo + -rm -f ./$(DEPDIR)/mcht-count.Plo + -rm -f ./$(DEPDIR)/mcht-value.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/relational/ext-relational-common.c b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c new file mode 100644 index 0000000..a6dd1ed --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c @@ -0,0 +1,171 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Syntax: + + MATCH-TYPE =/ COUNT / VALUE + COUNT = ":count" relational-match + VALUE = ":value" relational-match + relational-match = DQUOTE ( "gt" / "ge" / "lt" + / "le" / "eq" / "ne" ) DQUOTE + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-relational-common.h" + +/* + * Forward declarations + */ + +const struct sieve_match_type_def *rel_match_types[]; + +/* + * Validation + */ + +bool mcht_relational_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_match_type_context *ctx) +{ + struct sieve_match_type *mcht; + enum relational_match rel_match = REL_MATCH_INVALID; + pool_t pool = sieve_ast_argument_pool(ctx->argument); + string_t *rel_match_ident; + + /* Check syntax: + relational-match = DQUOTE ( "gt" / "ge" / "lt" + / "le" / "eq" / "ne" ) DQUOTE + + So, actually this must be a constant string and it is implemented as + such. + */ + + /* Did we get a string in the first place? */ + if (*arg == NULL || (*arg)->type != SAAT_STRING) { + sieve_argument_validate_error( + valdtr, (*arg == NULL ? ctx->argument : *arg), + "the :%s match-type requires a constant string argument being " + "one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", " + "but %s was found", + sieve_match_type_name(ctx->match_type), + (*arg == NULL ? + "none" : sieve_ast_argument_name(*arg))); + return FALSE; + } + + /* Check the relational match id */ + + rel_match_ident = sieve_ast_argument_str(*arg); + if (str_len(rel_match_ident) == 2) { + const char *rel_match_id = str_c(rel_match_ident); + + switch (rel_match_id[0]) { + /* "gt" or "ge" */ + case 'g': + switch (rel_match_id[1]) { + case 't': + rel_match = REL_MATCH_GREATER; + break; + case 'e': + rel_match = REL_MATCH_GREATER_EQUAL; + break; + default: + rel_match = REL_MATCH_INVALID; + } + break; + /* "lt" or "le" */ + case 'l': + switch (rel_match_id[1]) { + case 't': + rel_match = REL_MATCH_LESS; + break; + case 'e': + rel_match = REL_MATCH_LESS_EQUAL; + break; + default: + rel_match = REL_MATCH_INVALID; + } + break; + /* "eq" */ + case 'e': + if (rel_match_id[1] == 'q') + rel_match = REL_MATCH_EQUAL; + else + rel_match = REL_MATCH_INVALID; + break; + /* "ne" */ + case 'n': + if (rel_match_id[1] == 'e') + rel_match = REL_MATCH_NOT_EQUAL; + else + rel_match = REL_MATCH_INVALID; + break; + /* invalid */ + default: + rel_match = REL_MATCH_INVALID; + } + } + + if (rel_match >= REL_MATCH_INVALID) { + sieve_argument_validate_error( + valdtr, *arg, + "the :%s match-type requires a constant string argument being " + "one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", " + "but \"%s\" was found", + sieve_match_type_name(ctx->match_type), + str_sanitize(str_c(rel_match_ident), 32)); + return FALSE; + } + + /* Delete argument */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Not used just yet */ + ctx->ctx_data = (void *) rel_match; + + /* Override the actual match type with a parameter-specific one + * FIXME: ugly! + */ + mcht = p_new(pool, struct sieve_match_type, 1); + mcht->object.ext = ctx->match_type->object.ext; + SIEVE_OBJECT_SET_DEF(mcht, rel_match_types[ + REL_MATCH_INDEX(ctx->match_type->object.def->code, rel_match)]); + ctx->match_type = mcht; + + return TRUE; +} + +/* + * Relational match-type operand + */ + +const struct sieve_match_type_def *rel_match_types[] = { + &rel_match_value_gt, &rel_match_value_ge, &rel_match_value_lt, + &rel_match_value_le, &rel_match_value_eq, &rel_match_value_ne, + &rel_match_count_gt, &rel_match_count_ge, &rel_match_count_lt, + &rel_match_count_le, &rel_match_count_eq, &rel_match_count_ne, +}; + +static const struct sieve_extension_objects ext_match_types = + SIEVE_EXT_DEFINE_MATCH_TYPES(rel_match_types); + +const struct sieve_operand_def rel_match_type_operand = { + .name = "relational match", + .ext_def = &relational_extension, + .class = &sieve_match_type_operand_class, + .interface = &ext_match_types, +}; diff --git a/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.h b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.h new file mode 100644 index 0000000..c0f7d3b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.h @@ -0,0 +1,86 @@ +#ifndef EXT_RELATIONAL_COMMON_H +#define EXT_RELATIONAL_COMMON_H + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +/* + * Types + */ + +enum ext_relational_match_type { + RELATIONAL_VALUE, + RELATIONAL_COUNT +}; + +enum relational_match { + REL_MATCH_GREATER, + REL_MATCH_GREATER_EQUAL, + REL_MATCH_LESS, + REL_MATCH_LESS_EQUAL, + REL_MATCH_EQUAL, + REL_MATCH_NOT_EQUAL, + REL_MATCH_INVALID +}; + +#define REL_MATCH_INDEX(type, match) (type * REL_MATCH_INVALID + match) +#define REL_MATCH_TYPE(index) (index / REL_MATCH_INVALID) +#define REL_MATCH(index) (index % REL_MATCH_INVALID) + +/* + * Extension definitions + */ + +extern const struct sieve_extension_def relational_extension; + +/* + * Match types + */ + +/* Registered for validation */ + +extern const struct sieve_match_type_def value_match_type; +extern const struct sieve_match_type_def count_match_type; + +/* Used in byte code */ + +extern const struct sieve_match_type_def rel_match_count_gt; +extern const struct sieve_match_type_def rel_match_count_ge; +extern const struct sieve_match_type_def rel_match_count_lt; +extern const struct sieve_match_type_def rel_match_count_le; +extern const struct sieve_match_type_def rel_match_count_eq; +extern const struct sieve_match_type_def rel_match_count_ne; + +extern const struct sieve_match_type_def rel_match_value_gt; +extern const struct sieve_match_type_def rel_match_value_ge; +extern const struct sieve_match_type_def rel_match_value_lt; +extern const struct sieve_match_type_def rel_match_value_le; +extern const struct sieve_match_type_def rel_match_value_eq; +extern const struct sieve_match_type_def rel_match_value_ne; + +/* + * Operand + */ + +extern const struct sieve_operand_def rel_match_type_operand; + + +/* + * Match type validation + */ + +bool mcht_relational_validate(struct sieve_validator *validator, + struct sieve_ast_argument **arg, + struct sieve_match_type_context *ctx); + +/* + * Value match function (also used by :count) + */ + +int mcht_value_match_key(struct sieve_match_context *mctx, + const char *val, size_t val_size, + const char *key, size_t key_size); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/relational/ext-relational.c b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational.c new file mode 100644 index 0000000..28c278f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension relational + * -------------------- + * + * Author: Stephan Bosch + * Specification: RFC 3431 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-relational-common.h" + +/* + * Extension + */ + +static bool ext_relational_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def relational_extension = { + .name = "relational", + .validator_load = ext_relational_validator_load, + SIEVE_EXT_DEFINE_OPERAND(rel_match_type_operand) +}; + +static bool ext_relational_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + sieve_match_type_register(valdtr, ext, &value_match_type); + sieve_match_type_register(valdtr, ext, &count_match_type); + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c b/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c new file mode 100644 index 0000000..e31a63a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':count' + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-runtime-trace.h" +#include "sieve-match.h" + +#include "ext-relational-common.h" + +/* + * Forward declarations + */ + +static int mcht_count_match + (struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list); + +/* + * Match-type objects + */ + +const struct sieve_match_type_def count_match_type = { + SIEVE_OBJECT("count", + &rel_match_type_operand, RELATIONAL_COUNT), + .validate = mcht_relational_validate +}; + +#define COUNT_MATCH_TYPE(name, rel_match) \ +const struct sieve_match_type_def rel_match_count_ ## name = { \ + SIEVE_OBJECT("count-" #name, \ + &rel_match_type_operand, \ + REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match)), \ + .match = mcht_count_match, \ +} + +COUNT_MATCH_TYPE(gt, REL_MATCH_GREATER); +COUNT_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL); +COUNT_MATCH_TYPE(lt, REL_MATCH_LESS); +COUNT_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL); +COUNT_MATCH_TYPE(eq, REL_MATCH_EQUAL); +COUNT_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL); + +/* + * Match-type implementation + */ + +static int mcht_count_match +(struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list) +{ + const struct sieve_runtime_env *renv = mctx->runenv; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + int count; + string_t *key_item; + int match, ret; + + if ( (count=sieve_stringlist_get_length(value_list)) < 0 ) { + mctx->exec_status = value_list->exec_status; + return -1; + } + + sieve_stringlist_reset(key_list); + + string_t *value = t_str_new(20); + str_printfa(value, "%d", count); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "matching count value `%s'", str_sanitize(str_c(value), 80)); + } + + sieve_runtime_trace_descend(renv); + + /* Match to all key values */ + key_item = NULL; + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) + { + match = mcht_value_match_key + (mctx, str_c(value), str_len(value), str_c(key_item), str_len(key_item)); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with key `%s' => %d", str_sanitize(str_c(key_item), 80), ret); + } + } + + sieve_runtime_trace_ascend(renv); + + if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + + return match; +} + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/relational/mcht-value.c b/pigeonhole/src/lib-sieve/plugins/relational/mcht-value.c new file mode 100644 index 0000000..dd55590 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/mcht-value.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" + +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-match.h" + +#include "ext-relational-common.h" + +/* + * Match-type objects + */ + +const struct sieve_match_type_def value_match_type = { + SIEVE_OBJECT("value", + &rel_match_type_operand, RELATIONAL_VALUE), + .validate = mcht_relational_validate +}; + +#define VALUE_MATCH_TYPE(name, rel_match) \ +const struct sieve_match_type_def rel_match_value_ ## name = { \ + SIEVE_OBJECT("value-" #name, \ + &rel_match_type_operand, \ + REL_MATCH_INDEX(RELATIONAL_VALUE, rel_match)), \ + .match_key = mcht_value_match_key, \ +} + +VALUE_MATCH_TYPE(gt, REL_MATCH_GREATER); +VALUE_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL); +VALUE_MATCH_TYPE(lt, REL_MATCH_LESS); +VALUE_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL); +VALUE_MATCH_TYPE(eq, REL_MATCH_EQUAL); +VALUE_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL); + +/* + * Match-type implementation + */ + +int mcht_value_match_key +(struct sieve_match_context *mctx, const char *val, size_t val_size, + const char *key, size_t key_size) +{ + const struct sieve_match_type *mtch = mctx->match_type; + unsigned int rel_match = REL_MATCH(mtch->object.def->code); + int cmp_result; + + cmp_result = mctx->comparator->def-> + compare(mctx->comparator, val, val_size, key, key_size); + + switch ( rel_match ) { + case REL_MATCH_GREATER: + return ( cmp_result > 0 ? 1 : 0 ); + case REL_MATCH_GREATER_EQUAL: + return ( cmp_result >= 0 ? 1 : 0 ); + case REL_MATCH_LESS: + return ( cmp_result < 0 ? 1 : 0 ); + case REL_MATCH_LESS_EQUAL: + return ( cmp_result <= 0 ? 1 : 0 ); + case REL_MATCH_EQUAL: + return ( cmp_result == 0 ? 1 : 0); + case REL_MATCH_NOT_EQUAL: + return ( cmp_result != 0 ? 1 : 0); + } + + i_unreached(); +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.am b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.am new file mode 100644 index 0000000..6a15bdd --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_spamvirustest.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-spamvirustest.c + +libsieve_ext_spamvirustest_la_SOURCES = \ + $(tests) \ + ext-spamvirustest-common.c \ + ext-spamvirustest.c + +noinst_HEADERS = \ + ext-spamvirustest-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.in b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.in new file mode 100644 index 0000000..dca31e3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/Makefile.in @@ -0,0 +1,694 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/spamvirustest +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_spamvirustest_la_LIBADD = +am__objects_1 = tst-spamvirustest.lo +am_libsieve_ext_spamvirustest_la_OBJECTS = $(am__objects_1) \ + ext-spamvirustest-common.lo ext-spamvirustest.lo +libsieve_ext_spamvirustest_la_OBJECTS = \ + $(am_libsieve_ext_spamvirustest_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 = +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)/ext-spamvirustest-common.Plo \ + ./$(DEPDIR)/ext-spamvirustest.Plo \ + ./$(DEPDIR)/tst-spamvirustest.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 = $(libsieve_ext_spamvirustest_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_spamvirustest_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@ +noinst_LTLIBRARIES = libsieve_ext_spamvirustest.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tests = \ + tst-spamvirustest.c + +libsieve_ext_spamvirustest_la_SOURCES = \ + $(tests) \ + ext-spamvirustest-common.c \ + ext-spamvirustest.c + +noinst_HEADERS = \ + ext-spamvirustest-common.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/lib-sieve/plugins/spamvirustest/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/spamvirustest/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_spamvirustest.la: $(libsieve_ext_spamvirustest_la_OBJECTS) $(libsieve_ext_spamvirustest_la_DEPENDENCIES) $(EXTRA_libsieve_ext_spamvirustest_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_spamvirustest_la_OBJECTS) $(libsieve_ext_spamvirustest_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-spamvirustest-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-spamvirustest.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-spamvirustest.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-spamvirustest-common.Plo + -rm -f ./$(DEPDIR)/ext-spamvirustest.Plo + -rm -f ./$(DEPDIR)/tst-spamvirustest.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-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)/ext-spamvirustest-common.Plo + -rm -f ./$(DEPDIR)/ext-spamvirustest.Plo + -rm -f ./$(DEPDIR)/tst-spamvirustest.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c new file mode 100644 index 0000000..38cb5d8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c @@ -0,0 +1,674 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "strfuncs.h" +#include "mail-storage.h" + +#include "sieve-common.h" +#include "sieve-settings.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-message.h" +#include "sieve-interpreter.h" +#include "sieve-runtime-trace.h" + +#include "ext-spamvirustest-common.h" + +#include <sys/types.h> +#include <regex.h> +#include <ctype.h> + +/* + * Extension data + */ + +enum ext_spamvirustest_status_type { + EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE, + EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN, + EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT, +}; + +struct ext_spamvirustest_header_spec { + const char *header_name; + regex_t regexp; + bool regexp_match; +}; + +struct ext_spamvirustest_data { + pool_t pool; + + int reload; + + struct ext_spamvirustest_header_spec status_header; + struct ext_spamvirustest_header_spec max_header; + + enum ext_spamvirustest_status_type status_type; + + float max_value; + + const char *text_values[11]; +}; + +/* + * Regexp utility + */ + +static bool _regexp_compile +(regex_t *regexp, const char *data, const char **error_r) +{ + size_t errsize; + int ret; + + *error_r = ""; + + if ( (ret=regcomp(regexp, data, REG_EXTENDED)) == 0 ) { + return TRUE; + } + + errsize = regerror(ret, regexp, NULL, 0); + + if ( errsize > 0 ) { + char *errbuf = t_malloc0(errsize); + + (void)regerror(ret, regexp, errbuf, errsize); + + /* We don't want the error to start with a capital letter */ + errbuf[0] = i_tolower(errbuf[0]); + + *error_r = errbuf; + } + + return FALSE; +} + +static const char *_regexp_match_get_value +(const char *string, int index, regmatch_t pmatch[], int nmatch) +{ + if ( index > -1 && index < nmatch && pmatch[index].rm_so != -1 ) { + return t_strndup(string + pmatch[index].rm_so, + pmatch[index].rm_eo - pmatch[index].rm_so); + } + return NULL; +} + +/* + * Configuration parser + */ + +static bool ext_spamvirustest_header_spec_parse +(struct ext_spamvirustest_header_spec *spec, pool_t pool, const char *data, + const char **error_r) +{ + const char *p; + const char *regexp_error; + + if ( *data == '\0' ) { + *error_r = "empty header specification"; + return FALSE; + } + + /* Parse header name */ + + p = data; + + while ( *p == ' ' || *p == '\t' ) p++; + while ( *p != ':' && *p != '\0' && *p != ' ' && *p != '\t' ) p++; + + if ( *p == '\0' ) { + spec->header_name = p_strdup(pool, data); + return TRUE; + } + + spec->header_name = p_strdup_until(pool, data, p); + while ( *p == ' ' || *p == '\t' ) p++; + + if ( *p == '\0' ) { + spec->regexp_match = FALSE; + return TRUE; + } + + /* Parse and compile regular expression */ + + if ( *p != ':' ) { + *error_r = t_strdup_printf("expecting ':', but found '%c'", *p); + return FALSE; + } + p++; + while ( *p == ' ' || *p == '\t' ) p++; + + spec->regexp_match = TRUE; + if ( !_regexp_compile(&spec->regexp, p, ®exp_error) ) { + *error_r = t_strdup_printf("failed to compile regular expression '%s': " + "%s", p, regexp_error); + return FALSE; + } + + return TRUE; +} + +static void ext_spamvirustest_header_spec_free +(struct ext_spamvirustest_header_spec *spec) +{ + regfree(&spec->regexp); +} + +static bool ext_spamvirustest_parse_strlen_value +(const char *str_value, float *value_r, const char **error_r) +{ + const char *p = str_value; + char ch = *p; + + if ( *str_value == '\0' ) { + *value_r = 0; + return TRUE; + } + + while ( *p == ch ) p++; + + if ( *p != '\0' ) { + *error_r = t_strdup_printf( + "different character '%c' encountered in strlen value", + *p); + return FALSE; + } + + *value_r = ( p - str_value ); + + return TRUE; +} + +static bool ext_spamvirustest_parse_decimal_value +(const char *str_value, float *value_r, const char **error_r) +{ + const char *p = str_value; + float value; + float sign = 1; + int digits; + + if ( *p == '\0' ) { + *error_r = "empty value"; + return FALSE; + } + + if ( *p == '+' || *p == '-' ) { + if ( *p == '-' ) + sign = -1; + + p++; + } + + value = 0; + digits = 0; + while ( i_isdigit(*p) ) { + value = value*10 + (*p-'0'); + if ( digits++ > 4 ) { + *error_r = t_strdup_printf + ("decimal value has too many digits before radix point: %s", + str_value); + return FALSE; + } + p++; + } + + if ( *p == '.' || *p == ',' ) { + float radix = .1; + p++; + + digits = 0; + while ( i_isdigit(*p) ) { + value = value + (*p-'0')*radix; + + if ( digits++ > 4 ) { + *error_r = t_strdup_printf + ("decimal value has too many digits after radix point: %s", + str_value); + return FALSE; + } + radix /= 10; + p++; + } + } + + if ( *p != '\0' ) { + *error_r = t_strdup_printf + ("invalid decimal point value: %s", str_value); + return FALSE; + } + + *value_r = value * sign; + + return TRUE; +} + +/* + * Extension initialization + */ + +bool ext_spamvirustest_load +(const struct sieve_extension *ext, void **context) +{ + struct ext_spamvirustest_data *ext_data = + (struct ext_spamvirustest_data *) *context; + struct sieve_instance *svinst = ext->svinst; + const char *ext_name, *status_header, *max_header, *status_type, + *max_value; + enum ext_spamvirustest_status_type type; + const char *error; + pool_t pool; + bool result = TRUE; + int reload = 0; + + if ( *context != NULL ) { + reload = ext_data->reload + 1; + ext_spamvirustest_unload(ext); + *context = NULL; + } + + /* FIXME: + * Prevent loading of both spamtest and spamtestplus: let these share + * contexts. + */ + + if ( sieve_extension_is(ext, spamtest_extension) || + sieve_extension_is(ext, spamtestplus_extension) ) { + ext_name = spamtest_extension.name; + } else { + ext_name = sieve_extension_name(ext); + } + + /* Get settings */ + + status_header = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_status_header", NULL)); + status_type = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_status_type", NULL)); + max_header = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_max_header", NULL)); + max_value = sieve_setting_get + (svinst, t_strconcat("sieve_", ext_name, "_max_value", NULL)); + + /* Base configuration */ + + if ( status_header == NULL ) { + return TRUE; + } + + if ( status_type == NULL || strcmp(status_type, "score") == 0 ) { + type = EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE; + } else if ( strcmp(status_type, "strlen") == 0 ) { + type = EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN; + } else if ( strcmp(status_type, "text") == 0 ) { + type = EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT; + } else { + e_error(svinst->event, "%s: " + "invalid status type '%s'", ext_name, status_type); + return FALSE; + } + + /* Verify settings */ + + if ( type != EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT ) { + + if ( max_header != NULL && max_value != NULL ) { + e_error(svinst->event, "%s: " + "sieve_%s_max_header and sieve_%s_max_value " + "cannot both be configured", + ext_name, ext_name, ext_name); + return TRUE; + } + + if ( max_header == NULL && max_value == NULL ) { + e_error(svinst->event, "%s: " + "none of sieve_%s_max_header or sieve_%s_max_value " + "is configured", ext_name, ext_name, ext_name); + return TRUE; + } + } else { + if ( max_header != NULL ) { + e_warning(svinst->event, "%s: " + "setting sieve_%s_max_header has no meaning " + "for sieve_%s_status_type=text", + ext_name, ext_name, ext_name); + } + + if ( max_value != NULL ) { + e_warning(svinst->event, "%s: " + "setting sieve_%s_max_value has no meaning " + "for sieve_%s_status_type=text", + ext_name, ext_name, ext_name); + } + } + + pool = pool_alloconly_create("spamvirustest_data", 512); + ext_data = p_new(pool, struct ext_spamvirustest_data, 1); + ext_data->pool = pool; + ext_data->reload = reload; + ext_data->status_type = type; + + if ( !ext_spamvirustest_header_spec_parse + (&ext_data->status_header, ext_data->pool, status_header, &error) ) { + e_error(svinst->event, "%s: " + "invalid status header specification '%s': %s", + ext_name, status_header, error); + result = FALSE; + } + + if ( result ) { + if ( type != EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT ) { + /* Parse max header */ + + if ( max_header != NULL && !ext_spamvirustest_header_spec_parse + (&ext_data->max_header, ext_data->pool, max_header, &error) ) { + e_error(svinst->event, "%s: " + "invalid max header specification " + "'%s': %s", ext_name, max_header, + error); + result = FALSE; + } + + /* Parse max value */ + + if ( result && max_value != NULL ) { + if ( !ext_spamvirustest_parse_decimal_value + (max_value, &ext_data->max_value, &error) ) { + e_error(svinst->event, "%s: " + "invalid max value specification " + "'%s': %s", ext_name, max_value, + error); + result = FALSE; + } + } + + } else { + unsigned int i, max_text; + + max_text = ( sieve_extension_is(ext, virustest_extension) ? 5 : 10 ); + + /* Get text values */ + for ( i = 0; i <= max_text; i++ ) { + const char *value = sieve_setting_get + (svinst, t_strdup_printf("sieve_%s_text_value%d", ext_name, i)); + + if ( value != NULL && *value != '\0' ) + ext_data->text_values[i] = p_strdup(ext_data->pool, value); + } + + ext_data->max_value = 1; + } + } + + if ( result ) { + *context = (void *) ext_data; + } else { + e_warning(svinst->event, "%s: " + "extension not configured, " + "tests will always match against \"0\"", + ext_name); + ext_spamvirustest_unload(ext); + *context = NULL; + } + + return result; +} + +void ext_spamvirustest_unload(const struct sieve_extension *ext) +{ + struct ext_spamvirustest_data *ext_data = + (struct ext_spamvirustest_data *) ext->context; + + if ( ext_data != NULL ) { + ext_spamvirustest_header_spec_free(&ext_data->status_header); + ext_spamvirustest_header_spec_free(&ext_data->max_header); + pool_unref(&ext_data->pool); + } +} + +/* + * Runtime + */ + +struct ext_spamvirustest_message_context { + int reload; + float score_ratio; +}; + +static const char *ext_spamvirustest_get_score +(const struct sieve_extension *ext, float score_ratio, bool percent) +{ + int score; + + if ( score_ratio < 0 ) + return "0"; + + if ( score_ratio > 1 ) + score_ratio = 1; + + if ( percent ) + score = score_ratio * 100 + 0.001; + else if ( sieve_extension_is(ext, virustest_extension) ) + score = score_ratio * 4 + 1.001; + else + score = score_ratio * 9 + 1.001; + + return t_strdup_printf("%d", score); +} + +int ext_spamvirustest_get_value +(const struct sieve_runtime_env *renv, const struct sieve_extension *ext, + bool percent, const char **value_r) +{ + struct ext_spamvirustest_data *ext_data = + (struct ext_spamvirustest_data *) ext->context; + struct ext_spamvirustest_header_spec *status_header, *max_header; + struct sieve_message_context *msgctx = renv->msgctx; + struct ext_spamvirustest_message_context *mctx; + struct mail *mail; + regmatch_t match_values[2]; + const char *header_value, *error; + const char *status = NULL, *max = NULL; + float status_value, max_value; + unsigned int i, max_text; + pool_t pool = sieve_interpreter_pool(renv->interp); + + *value_r = "0"; + + /* + * Check whether extension is properly configured + */ + if ( ext_data == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "error: extension not configured"); + return SIEVE_EXEC_OK; + } + + /* + * Check wether a cached result is available + */ + + mctx = (struct ext_spamvirustest_message_context *) + sieve_message_context_extension_get(msgctx, ext); + + if ( mctx == NULL ) { + /* Create new context */ + mctx = p_new(pool, struct ext_spamvirustest_message_context, 1); + sieve_message_context_extension_set(msgctx, ext, (void *)mctx); + } else if ( mctx->reload == ext_data->reload ) { + /* Use cached result */ + *value_r = ext_spamvirustest_get_score(ext, mctx->score_ratio, percent); + return SIEVE_EXEC_OK; + } else { + /* Extension was reloaded (probably in testsuite) */ + } + + mctx->reload = ext_data->reload; + + /* + * Get max status value + */ + + mail = sieve_message_get_mail(renv->msgctx); + status_header = &ext_data->status_header; + max_header = &ext_data->max_header; + + if ( ext_data->status_type != EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT ) { + if ( max_header->header_name != NULL ) { + /* Get header from message */ + if ( mail_get_first_header_utf8 + (mail, max_header->header_name, &header_value) < 0 ) { + return sieve_runtime_mail_error (renv, mail, + "%s test: failed to read header field `%s'", + sieve_extension_name(ext), max_header->header_name); + } + if ( header_value == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "header '%s' not found in message", + max_header->header_name); + goto failed; + } + + if ( max_header->regexp_match ) { + /* Execute regex */ + if ( regexec(&max_header->regexp, header_value, 2, match_values, 0) + != 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp for header '%s' did not match " + "on value '%s'", max_header->header_name, header_value); + goto failed; + } + + max = _regexp_match_get_value(header_value, 1, match_values, 2); + if ( max == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp did not return match value " + "for string '%s'", header_value); + goto failed; + } + } else { + max = header_value; + } + + if ( !ext_spamvirustest_parse_decimal_value(max, &max_value, &error) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to parse maximum value: %s", error); + goto failed; + } + } else { + max_value = ext_data->max_value; + } + + if ( max_value == 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "error: max value is 0"); + goto failed; + } + } else { + max_value = ( sieve_extension_is(ext, virustest_extension) ? 5 : 10 ); + } + + /* + * Get status value + */ + + /* Get header from message */ + if ( mail_get_first_header_utf8 + (mail, status_header->header_name, &header_value) < 0 ) { + return sieve_runtime_mail_error (renv, mail, + "%s test: failed to read header field `%s'", + sieve_extension_name(ext), status_header->header_name); + } + if ( header_value == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "header '%s' not found in message", + status_header->header_name); + goto failed; + } + + /* Execute regex */ + if ( status_header->regexp_match ) { + if ( regexec(&status_header->regexp, header_value, 2, match_values, 0) + != 0 ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp for header '%s' did not match on value '%s'", + status_header->header_name, header_value); + goto failed; + } + + status = _regexp_match_get_value(header_value, 1, match_values, 2); + if ( status == NULL ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "regexp did not return match value for string '%s'", + header_value); + goto failed; + } + } else { + status = header_value; + } + + switch ( ext_data->status_type ) { + case EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE: + if ( !ext_spamvirustest_parse_decimal_value + (status, &status_value, &error) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to parse status value '%s': %s", + status, error); + goto failed; + } + break; + case EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN: + if ( !ext_spamvirustest_parse_strlen_value + (status, &status_value, &error) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to parse status value '%s': %s", + status, error); + goto failed; + } + break; + case EXT_SPAMVIRUSTEST_STATUS_TYPE_TEXT: + max_text = ( sieve_extension_is(ext, virustest_extension) ? 5 : 10 ); + status_value = 0; + + i = 0; + while ( i <= max_text ) { + if ( ext_data->text_values[i] != NULL && + strcmp(status, ext_data->text_values[i]) == 0 ) { + status_value = (float) i; + break; + } + i++; + } + + if ( i > max_text ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "failed to match textstatus value '%s'", + status); + goto failed; + } + break; + default: + i_unreached(); + break; + } + + /* Calculate value */ + if ( status_value < 0 ) + mctx->score_ratio = 0; + else if ( status_value > max_value ) + mctx->score_ratio = 1; + else + mctx->score_ratio = (status_value / max_value); + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "extracted score=%.3f, max=%.3f, ratio=%.0f %%", + status_value, max_value, mctx->score_ratio * 100); + + *value_r = ext_spamvirustest_get_score(ext, mctx->score_ratio, percent); + return SIEVE_EXEC_OK; + +failed: + mctx->score_ratio = -1; + *value_r = "0"; + return SIEVE_EXEC_OK; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h new file mode 100644 index 0000000..331a637 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h @@ -0,0 +1,35 @@ +#ifndef EXT_SPAMVIRUSTEST_COMMON_H +#define EXT_SPAMVIRUSTEST_COMMON_H + +#include "sieve-common.h" + +/* + * Extensions + */ + +extern const struct sieve_extension_def spamtest_extension; +extern const struct sieve_extension_def spamtestplus_extension; +extern const struct sieve_extension_def virustest_extension; + +bool ext_spamvirustest_load(const struct sieve_extension *ext, void **context); +void ext_spamvirustest_unload(const struct sieve_extension *ext); + +/* + * Tests + */ + +extern const struct sieve_command_def spamtest_test; +extern const struct sieve_command_def virustest_test; + +int ext_spamvirustest_get_value +(const struct sieve_runtime_env *renv, const struct sieve_extension *ext, + bool percent, const char **value_r); + +/* + * Operations + */ + +extern const struct sieve_operation_def spamtest_operation; +extern const struct sieve_operation_def virustest_operation; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c new file mode 100644 index 0000000..e0c9b54 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c @@ -0,0 +1,146 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extensions spamtest, spamtestplus and virustest + * ----------------------------------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5235 + * Implementation: full + * Status: testing + * + */ + +/* Configuration examples: + * + * # 1: X-Spam-Score: No, score=-3.2 + * + * sieve_spamtest_status_header = \ + * X-Spam-Score: [[:alnum:]]+, score=(-?[[:digit:]]+\.[[:digit:]]) + * sieve_spamtest_max_value = 5.0 + * + * # 2: X-Spam-Status: Yes + * + * sieve_spamtest_status_header = X-Spam-Status + * sieve_spamtest_status_type = yesno + * sieve_spamtest_max_value = Yes + * + * # 3: X-Spam-Score: sssssss + * sieve_spamtest_status_header = X-Spam-Score + * sieve_spamtest_status_type = strlen + * sieve_spamtest_max_value = 5 + * + * # 4: X-Spam-Score: status=3.2 required=5.0 + * + * sieve_spamtest_status_header = \ + * X-Spam-Score: score=(-?[[:digit:]]+\.[[:digit:]]).* + * sieve_spamtest_max_header = \ + * X-Spam-Score: score=-?[[:digit:]]+\.[[:digit:]] required=([[:digit:]]+\.[[:digit:]]) + * + * # 5: X-Virus-Scan: Found to be clean. + * + * sieve_virustest_status_header = \ + * X-Virus-Scan: Found to be (.+)\. + * sieve_virustest_status_type = text + * sieve_virustest_text_value1 = clean + * sieve_virustest_text_value5 = infected + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" + +#include "sieve-validator.h" + +#include "ext-spamvirustest-common.h" + +/* + * Extensions + */ + +/* Spamtest */ + +static bool ext_spamvirustest_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def spamtest_extension = { + .name = "spamtest", + .load = ext_spamvirustest_load, + .unload = ext_spamvirustest_unload, + .validator_load = ext_spamvirustest_validator_load, + SIEVE_EXT_DEFINE_OPERATION(spamtest_operation) +}; + +const struct sieve_extension_def spamtestplus_extension = { + .name = "spamtestplus", + .load = ext_spamvirustest_load, + .unload = ext_spamvirustest_unload, + .validator_load = ext_spamvirustest_validator_load, + SIEVE_EXT_DEFINE_OPERATION(spamtest_operation) +}; + +const struct sieve_extension_def virustest_extension = { + .name = "virustest", + .load = ext_spamvirustest_load, + .unload = ext_spamvirustest_unload, + .validator_load = ext_spamvirustest_validator_load, + SIEVE_EXT_DEFINE_OPERATION(virustest_operation) +}; + +/* + * Implementation + */ + +static bool ext_spamtest_validator_check_conflict + (const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required); + +const struct sieve_validator_extension spamtest_validator_extension = { + .ext = &spamtest_extension, + .check_conflict = ext_spamtest_validator_check_conflict +}; + +static bool ext_spamvirustest_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new test */ + + if ( sieve_extension_is(ext, virustest_extension) ) { + sieve_validator_register_command(valdtr, ext, &virustest_test); + } else { + if ( sieve_extension_is(ext, spamtest_extension) ) { + /* Register validator extension to warn for duplicate */ + sieve_validator_extension_register + (valdtr, ext, &spamtest_validator_extension, NULL); + } + + sieve_validator_register_command(valdtr, ext, &spamtest_test); + } + + return TRUE; +} + +static bool ext_spamtest_validator_check_conflict +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_validator *valdtr, void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + const struct sieve_extension *ext_other, + bool required ATTR_UNUSED) +{ + if ( sieve_extension_name_is(ext_other, "spamtestplus") ) { + sieve_argument_validate_warning(valdtr, require_arg, + "the spamtest and spamtestplus extensions should " + "not be specified at the same time"); + } + + return TRUE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c b/pigeonhole/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c new file mode 100644 index 0000000..26d051e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c @@ -0,0 +1,304 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-spamvirustest-common.h" + +/* + * Tests + */ + +static bool tst_spamvirustest_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_spamvirustest_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); +static bool tst_spamvirustest_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); + +/* Spamtest test + * + * Syntax: + * spamtest [":percent"] [COMPARATOR] [MATCH-TYPE] <value: string> + */ + +const struct sieve_command_def spamtest_test = { + .identifier = "spamtest", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_spamvirustest_registered, + .validate = tst_spamvirustest_validate, + .generate = tst_spamvirustest_generate +}; + +/* Virustest test + * + * Syntax: + * virustest [COMPARATOR] [MATCH-TYPE] <value: string> + */ + +const struct sieve_command_def virustest_test = { + .identifier = "virustest", + .type = SCT_TEST, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_spamvirustest_registered, + .validate = tst_spamvirustest_validate, + .generate = tst_spamvirustest_generate +}; + +/* + * Tagged arguments + */ + +static bool tst_spamtest_validate_percent_tag + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *tst); + +static const struct sieve_argument_def spamtest_percent_tag = { + .identifier = "percent", + .validate = tst_spamtest_validate_percent_tag +}; + +/* + * Spamtest and virustest operations + */ + +static bool tst_spamvirustest_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_spamvirustest_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def spamtest_operation = { + .mnemonic = "SPAMTEST", + .ext_def = &spamtest_extension, + .dump = tst_spamvirustest_operation_dump, + .execute = tst_spamvirustest_operation_execute +}; + +const struct sieve_operation_def virustest_operation = { + .mnemonic = "VIRUSTEST", + .ext_def = &virustest_extension, + .dump = tst_spamvirustest_operation_dump, + .execute = tst_spamvirustest_operation_execute +}; + +/* + * Optional operands + */ + +enum tst_spamvirustest_optional { + OPT_SPAMTEST_PERCENT = SIEVE_MATCH_OPT_LAST, + OPT_SPAMTEST_LAST +}; + +/* + * Test registration + */ + +static bool tst_spamvirustest_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); + + if ( sieve_extension_is(ext, spamtestplus_extension) || + sieve_extension_is(ext, spamtest_extension) ) { + sieve_validator_register_tag + (valdtr, cmd_reg, ext, &spamtest_percent_tag, OPT_SPAMTEST_PERCENT); + } + + return TRUE; +} + +/* + * Validation + */ + +static bool tst_spamtest_validate_percent_tag +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *tst) +{ + if ( !sieve_extension_is(tst->ext, spamtestplus_extension) ) { + sieve_argument_validate_error(valdtr, *arg, + "the spamtest test only accepts the :percent argument when " + "the spamtestplus extension is active"); + return FALSE; + } + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool tst_spamvirustest_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + + /* Check value */ + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "value", 1, SAAT_STRING) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Code generation + */ + +static bool tst_spamvirustest_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *tst) +{ + if ( sieve_command_is(tst, spamtest_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, &spamtest_operation); + else if ( sieve_command_is(tst, virustest_test) ) + sieve_operation_emit(cgenv->sblock, tst->ext, &virustest_operation); + else + i_unreached(); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, tst, NULL); +} + +/* + * Code dump + */ + +static bool tst_spamvirustest_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + int opt_code = 0; + const struct sieve_operation *op = denv->oprtn; + + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_descend(denv); + + /* Optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_SPAMTEST_PERCENT: + sieve_code_dumpf(denv, "percent"); + break; + default: + return FALSE; + } + } + + return + sieve_opr_string_dump(denv, address, "value"); +} + +/* + * Code execution + */ + +static int tst_spamvirustest_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_operation *op = renv->oprtn; + const struct sieve_extension *this_ext = op->ext; + int opt_code = 0; + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); + bool percent = FALSE; + struct sieve_stringlist *value_list, *key_list; + const char *score_value; + int match, ret; + + /* Read optional operands */ + for (;;) { + int opt; + + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; + + if ( opt == 0 ) break; + + switch ( opt_code ) { + case OPT_SPAMTEST_PERCENT: + percent = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Read value part */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "value", &key_list)) <= 0 ) + return ret; + + /* Perform test */ + + if ( sieve_operation_is(op, spamtest_operation) ) { + sieve_runtime_trace + (renv, SIEVE_TRLVL_TESTS, "spamtest test [percent=%s]", + ( percent ? "true" : "false" )); + } else { + sieve_runtime_trace + (renv, SIEVE_TRLVL_TESTS, "virustest test"); + } + + /* Get score value */ + sieve_runtime_trace_descend(renv); + if ( (ret=ext_spamvirustest_get_value + (renv, this_ext, percent, &score_value)) <= 0 ) + return ret; + sieve_runtime_trace_ascend(renv); + + /* Construct value list */ + value_list = sieve_single_stringlist_create_cstr(renv, score_value, TRUE); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.am b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.am new file mode 100644 index 0000000..0f31aee --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.am @@ -0,0 +1,22 @@ +noinst_LTLIBRARIES = libsieve_ext_special_use.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-specialuse.c + +tests = \ + tst-specialuse-exists.c + +libsieve_ext_special_use_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-special-use-common.c \ + ext-special-use.c + +headers = \ + ext-special-use-common.h + +noinst_HEADERS = $(headers) diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.in b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.in new file mode 100644 index 0000000..5032dae --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/Makefile.in @@ -0,0 +1,703 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/special-use +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_special_use_la_LIBADD = +am__objects_1 = tag-specialuse.lo +am__objects_2 = tst-specialuse-exists.lo +am_libsieve_ext_special_use_la_OBJECTS = $(am__objects_1) \ + $(am__objects_2) ext-special-use-common.lo ext-special-use.lo +libsieve_ext_special_use_la_OBJECTS = \ + $(am_libsieve_ext_special_use_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 = +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)/ext-special-use-common.Plo \ + ./$(DEPDIR)/ext-special-use.Plo ./$(DEPDIR)/tag-specialuse.Plo \ + ./$(DEPDIR)/tst-specialuse-exists.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 = $(libsieve_ext_special_use_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_special_use_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@ +noinst_LTLIBRARIES = libsieve_ext_special_use.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +tags = \ + tag-specialuse.c + +tests = \ + tst-specialuse-exists.c + +libsieve_ext_special_use_la_SOURCES = \ + $(tags) \ + $(tests) \ + ext-special-use-common.c \ + ext-special-use.c + +headers = \ + ext-special-use-common.h + +noinst_HEADERS = $(headers) +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/lib-sieve/plugins/special-use/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/special-use/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_special_use.la: $(libsieve_ext_special_use_la_OBJECTS) $(libsieve_ext_special_use_la_DEPENDENCIES) $(EXTRA_libsieve_ext_special_use_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_special_use_la_OBJECTS) $(libsieve_ext_special_use_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-special-use-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-special-use.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag-specialuse.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-specialuse-exists.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-special-use-common.Plo + -rm -f ./$(DEPDIR)/ext-special-use.Plo + -rm -f ./$(DEPDIR)/tag-specialuse.Plo + -rm -f ./$(DEPDIR)/tst-specialuse-exists.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-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)/ext-special-use-common.Plo + -rm -f ./$(DEPDIR)/ext-special-use.Plo + -rm -f ./$(DEPDIR)/tag-specialuse.Plo + -rm -f ./$(DEPDIR)/tst-specialuse-exists.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/special-use/ext-special-use-common.c b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.c new file mode 100644 index 0000000..fcaf1b5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.c @@ -0,0 +1,31 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file */ + +#include "lib.h" +#include "imap-arg.h" + +#include "ext-special-use-common.h" + +bool ext_special_use_flag_valid(const char *flag) +{ + const char *p = flag; + + /* RFC 6154, Section 6: + + use-attr = "\All" / "\Archive" / "\Drafts" / "\Flagged" / + "\Junk" / "\Sent" / "\Trash" / use-attr-ext + use-attr-ext = "\" atom + */ + + /* "\" */ + if (*p != '\\') + return FALSE; + p++; + + /* atom */ + for (; *p != '\0'; p++) { + if (!IS_ATOM_CHAR(*p)) + return FALSE; + } + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.h b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.h new file mode 100644 index 0000000..61f23d0 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use-common.h @@ -0,0 +1,43 @@ +#ifndef EXT_SPECIAL_USE_COMMON_H +#define EXT_SPECIAL_USE_COMMON_H + +#include "sieve-common.h" + +/* + * Tagged arguments + */ + +extern const struct sieve_argument_def specialuse_tag; + +/* + * Commands + */ + +extern const struct sieve_command_def specialuse_exists_test; + +/* + * Operands + */ + +extern const struct sieve_operand_def specialuse_operand; + +/* + * Operations + */ + +extern const struct sieve_operation_def specialuse_exists_operation; + +/* + * Extension + */ + +extern const struct sieve_extension_def special_use_extension; + +/* + * Flag checking + */ + +bool ext_special_use_flag_valid(const char *flag); + +#endif /* EXT_SPECIAL_USE_COMMON_H */ + diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use.c b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use.c new file mode 100644 index 0000000..acbb13e --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/ext-special-use.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file */ + +/* Extension special-use + * --------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 8579 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-special-use-common.h" + +/* + * Extension + */ + +static bool +ext_special_use_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); + +const struct sieve_extension_def special_use_extension = { + .name = "special-use", + .validator_load = ext_special_use_validator_load, + SIEVE_EXT_DEFINE_OPERATION(specialuse_exists_operation), + SIEVE_EXT_DEFINE_OPERAND(specialuse_operand) +}; + +static bool +ext_special_use_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register :specialuse tag with fileinto command and we don't care + whether this command is registered or even whether it will be + registered at all. The validator handles either situation gracefully. + */ + sieve_validator_register_external_tag( + valdtr, "fileinto", ext, &specialuse_tag, + SIEVE_OPT_SIDE_EFFECT); + + /* Register new test */ + sieve_validator_register_command(valdtr, ext, &specialuse_exists_test); + + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/tag-specialuse.c b/pigeonhole/src/lib-sieve/plugins/special-use/tag-specialuse.c new file mode 100644 index 0000000..0f6d32a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/tag-specialuse.c @@ -0,0 +1,316 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-code.h" +#include "sieve-actions.h" +#include "sieve-result.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-special-use-common.h" + +/* + * Flags tagged argument + */ + +static bool +tag_specialuse_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +tag_specialuse_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +const struct sieve_argument_def specialuse_tag = { + .identifier = "specialuse", + .validate = tag_specialuse_validate, + .generate = tag_specialuse_generate +}; + +/* + * Side effect + */ + +static bool +seff_specialuse_dump_context(const struct sieve_side_effect *seffect, + const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +seff_specialuse_read_context(const struct sieve_side_effect *seffect, + const struct sieve_runtime_env *renv, + sieve_size_t *address, void **context); + +static int +seff_specialuse_merge(const struct sieve_runtime_env *renv, + const struct sieve_action *action, + const struct sieve_side_effect *old_seffect, + const struct sieve_side_effect *new_seffect, + void **old_context); + +static void +seff_specialuse_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); + +static int +seff_specialuse_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context ATTR_UNUSED); + +const struct sieve_side_effect_def specialuse_side_effect = { + SIEVE_OBJECT("specialuse", &specialuse_operand, 0), + .precedence = 200, + .to_action = &act_store, + .dump_context = seff_specialuse_dump_context, + .read_context = seff_specialuse_read_context, + .merge = seff_specialuse_merge, + .print = seff_specialuse_print, + .pre_execute = seff_specialuse_pre_execute +}; + +/* + * Operand + */ + +static const struct sieve_extension_objects ext_side_effects = + SIEVE_EXT_DEFINE_SIDE_EFFECT(specialuse_side_effect); + +const struct sieve_operand_def specialuse_operand = { + .name = "specialuse operand", + .ext_def = &special_use_extension, + .class = &sieve_side_effect_operand_class, + .interface = &ext_side_effects +}; + +/* + * Tag validation + */ + +static bool +tag_specialuse_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_argument_next(*arg); + + /* Check syntax: + * :specialuse <special-use-flag: string> + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + if (sieve_argument_is_string_literal(*arg)) { + const char *use_flag = sieve_ast_argument_strc(*arg); + + if (!ext_special_use_flag_valid(use_flag)) { + sieve_argument_validate_error( + valdtr, *arg, "specialuse tag: " + "invalid special-use flag `%s' specified", + str_sanitize(use_flag, 64)); + return FALSE; + } + } + + tag->parameters = *arg; + + /* Detach parameter */ + *arg = sieve_ast_arguments_detach(*arg,1); + + return TRUE; +} + +/* + * Code generation + */ + +static bool +tag_specialuse_generate(const struct sieve_codegen_env *cgenv, + struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *param; + + if (sieve_ast_argument_type(arg) != SAAT_TAG) + return FALSE; + + sieve_opr_side_effect_emit(cgenv->sblock, arg->argument->ext, + &specialuse_side_effect); + + /* Explicit :specialuse tag */ + param = arg->parameters; + + /* Call the generation function for the argument */ + if (param->argument != NULL && param->argument->def != NULL && + param->argument->def->generate != NULL && + !param->argument->def->generate(cgenv, param, cmd)) + return FALSE; + + return TRUE; +} + +/* + * Side effect implementation + */ + +/* Context data */ + +struct seff_specialuse_context { + const char *special_use_flag; +}; + +/* Context coding */ + +static bool +seff_specialuse_dump_context( + const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_stringlist_dump(denv, address, "specialuse"); +} + +static int +seff_specialuse_read_context( + const struct sieve_side_effect *seffect ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address, + void **se_context) +{ + pool_t pool = sieve_result_pool(renv->result); + struct seff_specialuse_context *ctx; + string_t *special_use_flag; + const char *use_flag; + int ret; + + if ((ret = sieve_opr_string_read(renv, address, "specialuse", + &special_use_flag)) <= 0) + return ret; + + use_flag = str_c(special_use_flag); + if (!ext_special_use_flag_valid(use_flag)) { + sieve_runtime_error( + renv, NULL, "specialuse tag: " + "invalid special-use flag `%s' specified", + str_sanitize(use_flag, 64)); + return SIEVE_EXEC_FAILURE; + } + + ctx = p_new(pool, struct seff_specialuse_context, 1); + ctx->special_use_flag = p_strdup(pool, use_flag); + + *se_context = (void *) ctx; + + return SIEVE_EXEC_OK; +} + +/* Result verification */ + +static int +seff_specialuse_merge(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_side_effect *old_seffect ATTR_UNUSED, + const struct sieve_side_effect *new_seffect, + void **old_context) +{ + if (new_seffect != NULL) + *old_context = new_seffect->context; + + return 1; +} + +/* Result printing */ + +static void +seff_specialuse_print(const struct sieve_side_effect *seffect, + const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct seff_specialuse_context *ctx = + (struct seff_specialuse_context *)seffect->context; + + sieve_result_seffect_printf( + rpenv, + "use mailbox with special-use flag `%s' instead if accessible", + ctx->special_use_flag); +} + +/* Result execution */ + +static int +seff_specialuse_pre_execute(const struct sieve_side_effect *seffect, + const struct sieve_action_exec_env *aenv, + void *tr_context, void **se_tr_context ATTR_UNUSED) +{ + struct seff_specialuse_context *ctx = + (struct seff_specialuse_context *)seffect->context; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct act_store_transaction *trans = + (struct act_store_transaction *)tr_context; + struct mailbox *box; + + if (trans->box == NULL || trans->disabled) + return SIEVE_EXEC_OK; + + /* Check whether something already failed */ + switch (trans->error_code) { + case MAIL_ERROR_NONE: + break; + case MAIL_ERROR_TEMP: + return SIEVE_EXEC_TEMP_FAILURE; + default: + return SIEVE_EXEC_FAILURE; + } + + trans->error = NULL; + trans->error_code = MAIL_ERROR_NONE; + + box = mailbox_alloc_for_user(eenv->scriptenv->user, + ctx->special_use_flag, + (MAILBOX_FLAG_POST_SESSION | + MAILBOX_FLAG_SPECIAL_USE)); + + /* We still override the allocate default mailbox with ours below even + when the default and special-use mailbox are identical. Choosing + either one is (currently) equal and setting trans->mailbox_identifier + for SPECIAL-USE needs to be done either way, so we use the same code + path. */ + + /* Try to open the mailbox */ + eenv->exec_status->last_storage = mailbox_get_storage(box); + if (mailbox_open(box) == 0) { + pool_t pool = sieve_result_pool(aenv->result); + + /* Success */ + mailbox_free(&trans->box); + trans->box = box; + trans->mailbox_identifier = p_strdup_printf(pool, + "[SPECIAL-USE %s]", ctx->special_use_flag); + + } else { + /* Failure */ + if (mailbox_get_last_mail_error(box) == MAIL_ERROR_NOTFOUND) { + /* Not found; revert to default */ + mailbox_free(&box); + } else { + /* Total failure */ + mailbox_free(&trans->box); + trans->box = box; + sieve_act_store_get_storage_error(aenv, trans); + return (trans->error_code == MAIL_ERROR_TEMP ? + SIEVE_EXEC_TEMP_FAILURE : SIEVE_EXEC_FAILURE); + } + } + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c b/pigeonhole/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c new file mode 100644 index 0000000..a1aa878 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c @@ -0,0 +1,525 @@ +/* Copyright (c) 2019 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" +#include "mail-storage.h" +#include "mail-namespace.h" + +#include "sieve-common.h" +#include "sieve-actions.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-special-use-common.h" + +/* + * specialuse_exists command + * + * Syntax: + * specialuse_exists [<mailbox: string>] + * <special-use-flags: string-list> + */ + +static bool +tst_specialuse_exists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst); +static bool +tst_specialuse_exists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def specialuse_exists_test = { + .identifier = "specialuse_exists", + .type = SCT_TEST, + .positional_args = -1, /* We check positional arguments ourselves */ + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = tst_specialuse_exists_validate, + .generate = tst_specialuse_exists_generate, +}; + +/* + * Mailboxexists operation + */ + +static bool +tst_specialuse_exists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +tst_specialuse_exists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def specialuse_exists_operation = { + .mnemonic = "SPECIALUSE_EXISTS", + .ext_def = &special_use_extension, + .dump = tst_specialuse_exists_operation_dump, + .execute = tst_specialuse_exists_operation_execute, +}; + +/* + * Test validation + */ + +struct _validate_context { + struct sieve_validator *valdtr; + struct sieve_command *tst; +}; + +static int +tst_specialuse_exists_flag_validate(void *context, + struct sieve_ast_argument *arg) +{ + struct _validate_context *valctx = (struct _validate_context *)context; + + if (sieve_argument_is_string_literal(arg)) { + const char *flag = sieve_ast_argument_strc(arg); + + if (!ext_special_use_flag_valid(flag)) { + sieve_argument_validate_error( + valctx->valdtr, arg, "%s test: " + "invalid special-use flag `%s' specified", + sieve_command_identifier(valctx->tst), + str_sanitize(flag, 64)); + } + } + + return 1; +} + +static bool +tst_specialuse_exists_validate(struct sieve_validator *valdtr, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *arg2; + struct sieve_ast_argument *aarg; + struct _validate_context valctx; + + if (arg == NULL) { + sieve_command_validate_error( + valdtr, tst, "the %s %s expects at least one argument, " + "but none was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst)); + return FALSE; + } + + if (sieve_ast_argument_type(arg) != SAAT_STRING && + sieve_ast_argument_type(arg) != SAAT_STRING_LIST) { + sieve_argument_validate_error( + valdtr, arg, + "the %s %s expects either a string (mailbox) or " + "a string-list (special-use flags) as first argument, " + "but %s was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst), + sieve_ast_argument_name(arg)); + return FALSE; + } + + arg2 = sieve_ast_argument_next(arg); + if (arg2 != NULL) { + /* First, check syntax sanity */ + if (sieve_ast_argument_type(arg) != SAAT_STRING) { + sieve_argument_validate_error( + valdtr, arg, + "if a second argument is specified for the %s %s, " + "the first must be a string (mailbox), " + "but %s was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst), + sieve_ast_argument_name(arg)); + return FALSE; + } + if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) + return FALSE; + + /* Check name validity when mailbox argument is not a variable */ + if (sieve_argument_is_string_literal(arg)) { + const char *mailbox = sieve_ast_argument_strc(arg); + const char *error; + + if (!sieve_mailbox_check_name(mailbox, &error)) { + sieve_argument_validate_warning( + valdtr, arg, "%s test: " + "invalid mailbox name `%s' specified: %s", + sieve_command_identifier(tst), + str_sanitize(mailbox, 256), error); + } + } + + if (sieve_ast_argument_type(arg2) != SAAT_STRING && + sieve_ast_argument_type(arg2) != SAAT_STRING_LIST) { + sieve_argument_validate_error( + valdtr, arg2, + "the %s %s expects a string list (special-use flags) as " + "second argument when two arguments are specified, " + "but %s was found", + sieve_command_identifier(tst), + sieve_command_type_name(tst), + sieve_ast_argument_name(arg2)); + return FALSE; + } + } else + arg2 = arg; + + if (!sieve_validator_argument_activate(valdtr, tst, arg2, FALSE)) + return FALSE; + + aarg = arg2; + memset(&valctx, 0, sizeof(valctx)); + valctx.valdtr = valdtr; + valctx.tst = tst; + + return (sieve_ast_stringlist_map( + &aarg, (void*)&valctx, + tst_specialuse_exists_flag_validate) >= 0); +} + +/* + * Test generation + */ + +static bool +tst_specialuse_exists_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + struct sieve_ast_argument *arg2; + + sieve_operation_emit(cgenv->sblock, + tst->ext, &specialuse_exists_operation); + + /* Generate arguments */ + arg2 = sieve_ast_argument_next(arg); + if (arg2 != NULL) { + if (!sieve_generate_argument(cgenv, arg, tst)) + return FALSE; + } else { + sieve_opr_omitted_emit(cgenv->sblock); + arg2 = arg; + } + return sieve_generate_argument(cgenv, arg2, tst); +} + +/* + * Code dump + */ + +static bool +tst_specialuse_exists_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + struct sieve_operand oprnd; + + sieve_code_dumpf(denv, "SPECIALUSE_EXISTS"); + sieve_code_descend(denv); + + sieve_code_mark(denv); + if (!sieve_operand_read(denv->sblock, address, NULL, &oprnd)) { + sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); + return FALSE; + } + + if (!sieve_operand_is_omitted(&oprnd)) { + return (sieve_opr_string_dump_data(denv, &oprnd, + address, "mailbox") && + sieve_opr_stringlist_dump(denv, address, + "special-use-flags")); + } + + return sieve_opr_stringlist_dump(denv, address, "special-use-flags"); +} + +/* + * Code execution + */ + +static int +tst_specialuse_find_mailbox(const struct sieve_runtime_env *renv, + const char *mailbox, struct mailbox **box_r) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + enum mail_error error_code; + const char *error; + + *box_r = NULL; + + if (user == NULL) + return 0; + + /* Open the box */ + box = mailbox_alloc_for_user(user, mailbox, MAILBOX_FLAG_POST_SESSION); + if (mailbox_open(box) < 0) { + error = mailbox_get_last_internal_error(box, &error_code); + + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' cannot be opened: %s", + str_sanitize(mailbox, 256), error); + } + + mailbox_free(&box); + + if (error_code == MAIL_ERROR_TEMP) { + sieve_runtime_error( + renv, NULL, "specialuse_exists test: " + "failed to open mailbox `%s': %s", + str_sanitize(mailbox, 256), error); + return -1; + } + return 0; + } + + /* Also fail when it is readonly */ + if (mailbox_is_readonly(box)) { + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' is read-only", + str_sanitize(mailbox, 256)); + } + + mailbox_free(&box); + return 0; + } + + *box_r = box; + return 1; +} + +static int +tst_specialuse_find_specialuse(const struct sieve_runtime_env *renv, + const char *special_use) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct mail_user *user = eenv->scriptenv->user; + struct mailbox *box; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + enum mail_error error_code; + const char *error; + + if (user == NULL) + return 0; + + /* Open the box */ + box = mailbox_alloc_for_user(user, special_use, + (MAILBOX_FLAG_POST_SESSION | + MAILBOX_FLAG_SPECIAL_USE)); + if (mailbox_open(box) < 0) { + error = mailbox_get_last_internal_error(box, &error_code); + + if (trace) { + sieve_runtime_trace( + renv, 0, "mailbox with special-use flag `%s' " + "cannot be opened: %s", + str_sanitize(special_use, 64), error); + } + + mailbox_free(&box); + + if (error_code == MAIL_ERROR_TEMP) { + sieve_runtime_error( + renv, NULL, "specialuse_exists test: " + "failed to open mailbox with special-use flag`%s': %s", + str_sanitize(special_use, 64), error); + return -1; + } + return 0; + } + + /* Also fail when it is readonly */ + if (mailbox_is_readonly(box)) { + if (trace) { + sieve_runtime_trace( + renv, 0, + "mailbox with special-use flag `%s' is read-only", + str_sanitize(special_use, 64)); + } + + mailbox_free(&box); + return 0; + } + + mailbox_free(&box); + return 1; +} + +static int +tst_specialuse_exists_check_flag(const struct sieve_runtime_env *renv, + struct mailbox *box, const char *use_flag, + bool trace, bool *all_exist_r) +{ + int ret; + + if (!ext_special_use_flag_valid(use_flag)) { + sieve_runtime_error( + renv, NULL, "specialuse_exists test: " + "invalid special-use flag `%s' specified", + str_sanitize(use_flag, 64)); + return SIEVE_EXEC_FAILURE; + } + + if (box != NULL) { + /* Mailbox has this SPECIAL-USE flag? */ + if (!mailbox_has_special_use(box, use_flag)) { + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + } else { + /* Is there mailbox with this SPECIAL-USE flag? */ + ret = tst_specialuse_find_specialuse(renv, use_flag); + if (ret < 0) + return SIEVE_EXEC_TEMP_FAILURE; + if (ret == 0) { + *all_exist_r = FALSE; + return SIEVE_EXEC_OK; + } + } + + if (trace) { + sieve_runtime_trace( + renv, 0, "special-use flag `%s' exists", + str_sanitize(use_flag, 80)); + } + + return SIEVE_EXEC_OK; +} + +static int +tst_specialuse_exists_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + struct sieve_operand oprnd; + struct sieve_stringlist *special_use_flags; + string_t *mailbox, *special_use_flag; + struct mailbox *box = NULL; + const char *error; + bool trace = FALSE, all_exist = TRUE; + int ret; + + /* + * Read operands + */ + + /* Read bare operand (two types possible) */ + ret = sieve_operand_runtime_read(renv, address, NULL, &oprnd); + if (ret <= 0) + return ret; + + /* Mailbox operand (optional) */ + mailbox = NULL; + if (!sieve_operand_is_omitted(&oprnd)) { + /* Read the mailbox operand */ + ret = sieve_opr_string_read_data(renv, &oprnd, address, + "mailbox", &mailbox); + if (ret <= 0) + return ret; + + /* Read flag list */ + ret = sieve_opr_stringlist_read(renv, address, + "special-use-flags", + &special_use_flags); + if (ret <= 0) + return ret; + + /* Flag-list operand */ + } else { + /* Read flag list */ + ret = sieve_opr_stringlist_read(renv, address, + "special-use-flags", + &special_use_flags); + if (ret <= 0) + return ret; + } + + /* + * Perform operation + */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS)) { + sieve_runtime_trace(renv, 0, "specialuse_exists test"); + sieve_runtime_trace_descend(renv); + + trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + } + + if (mailbox != NULL) { + if (!sieve_mailbox_check_name(str_c(mailbox), &error)) { + sieve_runtime_warning( + renv, NULL, "specialuse_exists test: " + "invalid mailbox name `%s' specified: %s", + str_sanitize(str_c(mailbox), 256), error); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (tst_specialuse_find_mailbox(renv, str_c(mailbox), &box) < 0) + return SIEVE_EXEC_TEMP_FAILURE; + } + + if (box == NULL && mailbox != NULL) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' is not accessible", + str_sanitize(str_c(mailbox), 80)); + sieve_interpreter_set_test_result(renv->interp, FALSE); + return SIEVE_EXEC_OK; + } + + if (mailbox != NULL) { + sieve_runtime_trace( + renv, 0, "mailbox `%s' is accessible", + str_sanitize(str_c(mailbox), 80)); + } + + ret = 0; + special_use_flag = NULL; + while (all_exist && + (ret = sieve_stringlist_next_item( + special_use_flags, &special_use_flag)) > 0) { + const char *use_flag = str_c(special_use_flag); + + ret = tst_specialuse_exists_check_flag( + renv, box, use_flag, trace, &all_exist); + if (ret <= 0) { + if (box != NULL) { + /* Close mailbox */ + mailbox_free(&box); + } + return ret; + } + } + + if (box != NULL) { + /* Close mailbox */ + mailbox_free(&box); + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid special-use flag item"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if (trace) { + if (all_exist) { + sieve_runtime_trace( + renv, 0, "all special-use flags are set"); + } else { + sieve_runtime_trace( + renv, 0, "some special-use are not set"); + } + } + + sieve_interpreter_set_test_result(renv->interp, all_exist); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.am b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.am new file mode 100644 index 0000000..2bab53f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libsieve_ext_subaddress.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_subaddress_la_SOURCES = \ + ext-subaddress.c diff --git a/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.in b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.in new file mode 100644 index 0000000..c5b6b7c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/subaddress/Makefile.in @@ -0,0 +1,673 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/subaddress +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 $(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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_subaddress_la_LIBADD = +am_libsieve_ext_subaddress_la_OBJECTS = ext-subaddress.lo +libsieve_ext_subaddress_la_OBJECTS = \ + $(am_libsieve_ext_subaddress_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 = +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)/ext-subaddress.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 = $(libsieve_ext_subaddress_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_subaddress_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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@ +noinst_LTLIBRARIES = libsieve_ext_subaddress.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_subaddress_la_SOURCES = \ + ext-subaddress.c + +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/lib-sieve/plugins/subaddress/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/subaddress/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_subaddress.la: $(libsieve_ext_subaddress_la_OBJECTS) $(libsieve_ext_subaddress_la_DEPENDENCIES) $(EXTRA_libsieve_ext_subaddress_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_subaddress_la_OBJECTS) $(libsieve_ext_subaddress_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-subaddress.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) +installdirs: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-subaddress.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-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)/ext-subaddress.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/subaddress/ext-subaddress.c b/pigeonhole/src/lib-sieve/plugins/subaddress/ext-subaddress.c new file mode 100644 index 0000000..abaa7ae --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/subaddress/ext-subaddress.c @@ -0,0 +1,191 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension subaddress + * -------------------- + * + * Author: Stephan Bosch + * Specification: RFC 3598 + * Implementation: full + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-settings.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-address-parts.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include <string.h> + +/* + * Configuration + */ + +#define SUBADDRESS_DEFAULT_DELIM "+" + +struct ext_subaddress_config { + char *delimiter; +}; + +/* + * Forward declarations + */ + +const struct sieve_address_part_def user_address_part; +const struct sieve_address_part_def detail_address_part; + +static struct sieve_operand_def subaddress_operand; + +/* + * Extension + */ + +static bool ext_subaddress_load + (const struct sieve_extension *ext, void **context); +static void ext_subaddress_unload + (const struct sieve_extension *ext); +static bool ext_subaddress_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def subaddress_extension = { + .name = "subaddress", + .load = ext_subaddress_load, + .unload = ext_subaddress_unload, + .validator_load = ext_subaddress_validator_load, + SIEVE_EXT_DEFINE_OPERAND(subaddress_operand) +}; + +static bool ext_subaddress_load +(const struct sieve_extension *ext, void **context) +{ + struct ext_subaddress_config *config; + const char *delim; + + if ( *context != NULL ) { + ext_subaddress_unload(ext); + } + + delim = sieve_setting_get(ext->svinst, "recipient_delimiter"); + + if ( delim == NULL ) + delim = SUBADDRESS_DEFAULT_DELIM; + + config = i_new(struct ext_subaddress_config, 1); + config->delimiter = i_strdup(delim); + + *context = (void *) config; + + return TRUE; +} + +static void ext_subaddress_unload +(const struct sieve_extension *ext) +{ + struct ext_subaddress_config *config = + (struct ext_subaddress_config *) ext->context; + + i_free(config->delimiter); + i_free(config); +} + +static bool ext_subaddress_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_address_part_register(validator, ext, &user_address_part); + sieve_address_part_register(validator, ext, &detail_address_part); + + return TRUE; +} + +/* + * Address parts + */ + +enum ext_subaddress_address_part { + SUBADDRESS_USER, + SUBADDRESS_DETAIL +}; + +/* Forward declarations */ + +static const char *subaddress_user_extract_from + (const struct sieve_address_part *addrp, const struct smtp_address *address); +static const char *subaddress_detail_extract_from + (const struct sieve_address_part *addrp, const struct smtp_address *address); + +/* Address part objects */ + +const struct sieve_address_part_def user_address_part = { + SIEVE_OBJECT("user", + &subaddress_operand, SUBADDRESS_USER), + subaddress_user_extract_from +}; + +const struct sieve_address_part_def detail_address_part = { + SIEVE_OBJECT("detail", + &subaddress_operand, SUBADDRESS_DETAIL), + .extract_from = subaddress_detail_extract_from +}; + +/* Address part implementation */ + +static const char *subaddress_user_extract_from +(const struct sieve_address_part *addrp, const struct smtp_address *address) +{ + struct ext_subaddress_config *config = + (struct ext_subaddress_config *) addrp->object.ext->context; + const char *delim; + size_t idx; + + idx = strcspn(address->localpart, config->delimiter); + delim = address->localpart[idx] != '\0' ? address->localpart + idx : NULL; + + if ( delim == NULL ) return address->localpart; + + return t_strdup_until(address->localpart, delim); +} + +static const char *subaddress_detail_extract_from +(const struct sieve_address_part *addrp, const struct smtp_address *address) +{ + struct ext_subaddress_config *config = + (struct ext_subaddress_config *) addrp->object.ext->context; + const char *delim; + size_t idx; + + idx = strcspn(address->localpart, config->delimiter); + delim = address->localpart[idx] != '\0' ? address->localpart + idx + 1: NULL; + + /* Just to be sure */ + if ( delim == NULL || + delim > (address->localpart + strlen(address->localpart)) ) + return NULL; + return delim; +} + +/* + * Operand + */ + +const struct sieve_address_part_def *ext_subaddress_parts[] = { + &user_address_part, &detail_address_part +}; + +static const struct sieve_extension_objects ext_address_parts = + SIEVE_EXT_DEFINE_ADDRESS_PARTS(ext_subaddress_parts); + +static struct sieve_operand_def subaddress_operand = { + .name = "address-part", + .ext_def = &subaddress_extension, + .class = &sieve_address_part_operand_class, + .interface = &ext_address_parts +}; + diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.am new file mode 100644 index 0000000..09df27b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.am @@ -0,0 +1,19 @@ +noinst_LTLIBRARIES = libsieve_ext_vacation.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-vacation.c + +libsieve_ext_vacation_la_SOURCES = \ + $(cmds) \ + ext-vacation-common.c \ + ext-vacation.c \ + ext-vacation-seconds.c + +noinst_HEADERS = \ + ext-vacation-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.in new file mode 100644 index 0000000..f18806a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/Makefile.in @@ -0,0 +1,700 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/vacation +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_vacation_la_LIBADD = +am__objects_1 = cmd-vacation.lo +am_libsieve_ext_vacation_la_OBJECTS = $(am__objects_1) \ + ext-vacation-common.lo ext-vacation.lo ext-vacation-seconds.lo +libsieve_ext_vacation_la_OBJECTS = \ + $(am_libsieve_ext_vacation_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 = +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)/cmd-vacation.Plo \ + ./$(DEPDIR)/ext-vacation-common.Plo \ + ./$(DEPDIR)/ext-vacation-seconds.Plo \ + ./$(DEPDIR)/ext-vacation.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 = $(libsieve_ext_vacation_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_vacation_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@ +noinst_LTLIBRARIES = libsieve_ext_vacation.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../util \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-vacation.c + +libsieve_ext_vacation_la_SOURCES = \ + $(cmds) \ + ext-vacation-common.c \ + ext-vacation.c \ + ext-vacation-seconds.c + +noinst_HEADERS = \ + ext-vacation-common.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/lib-sieve/plugins/vacation/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vacation/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_vacation.la: $(libsieve_ext_vacation_la_OBJECTS) $(libsieve_ext_vacation_la_DEPENDENCIES) $(EXTRA_libsieve_ext_vacation_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_vacation_la_OBJECTS) $(libsieve_ext_vacation_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-vacation.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vacation-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vacation-seconds.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vacation.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-vacation.Plo + -rm -f ./$(DEPDIR)/ext-vacation-common.Plo + -rm -f ./$(DEPDIR)/ext-vacation-seconds.Plo + -rm -f ./$(DEPDIR)/ext-vacation.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-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)/cmd-vacation.Plo + -rm -f ./$(DEPDIR)/ext-vacation-common.Plo + -rm -f ./$(DEPDIR)/ext-vacation-seconds.Plo + -rm -f ./$(DEPDIR)/ext-vacation.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/vacation/cmd-vacation.c b/pigeonhole/src/lib-sieve/plugins/vacation/cmd-vacation.c new file mode 100644 index 0000000..ddc14be --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -0,0 +1,1578 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "strfuncs.h" +#include "md5.h" +#include "hostpid.h" +#include "str-sanitize.h" +#include "ostream.h" +#include "message-address.h" +#include "message-date.h" +#include "var-expand.h" +#include "ioloop.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +#include "ext-vacation-common.h" + +#include <stdio.h> + +/* + * Forward declarations + */ + +static const struct sieve_argument_def vacation_days_tag; +static const struct sieve_argument_def vacation_subject_tag; +static const struct sieve_argument_def vacation_from_tag; +static const struct sieve_argument_def vacation_addresses_tag; +static const struct sieve_argument_def vacation_mime_tag; +static const struct sieve_argument_def vacation_handle_tag; + +/* + * Vacation command + * + * Syntax: + * vacation [":days" number] [":subject" string] + * [":from" string] [":addresses" string-list] + * [":mime"] [":handle" string] <reason: string> + */ + +static bool +cmd_vacation_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_vacation_pre_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_vacation_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd); +static bool +cmd_vacation_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd); + +const struct sieve_command_def vacation_command = { + .identifier = "vacation", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_vacation_registered, + .pre_validate = cmd_vacation_pre_validate, + .validate = cmd_vacation_validate, + .generate = cmd_vacation_generate, +}; + +/* + * Vacation command tags + */ + +/* Forward declarations */ + +static bool +cmd_vacation_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_vacation_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_vacation_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); +static bool +cmd_vacation_validate_mime_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +/* Argument objects */ + +static const struct sieve_argument_def vacation_days_tag = { + .identifier = "days", + .validate = cmd_vacation_validate_number_tag +}; + +static const struct sieve_argument_def vacation_seconds_tag = { + .identifier = "seconds", + .validate = cmd_vacation_validate_number_tag +}; + +static const struct sieve_argument_def vacation_subject_tag = { + .identifier = "subject", + .validate = cmd_vacation_validate_string_tag +}; + +static const struct sieve_argument_def vacation_from_tag = { + .identifier = "from", + .validate = cmd_vacation_validate_string_tag +}; + +static const struct sieve_argument_def vacation_addresses_tag = { + .identifier = "addresses", + .validate = cmd_vacation_validate_stringlist_tag +}; + +static const struct sieve_argument_def vacation_mime_tag = { + .identifier = "mime", + .validate = cmd_vacation_validate_mime_tag +}; + +static const struct sieve_argument_def vacation_handle_tag = { + .identifier = "handle", + .validate = cmd_vacation_validate_string_tag +}; + +/* Codes for optional arguments */ + +enum cmd_vacation_optional { + OPT_END, + OPT_SECONDS, + OPT_SUBJECT, + OPT_FROM, + OPT_ADDRESSES, + OPT_MIME +}; + +/* + * Vacation operation + */ + +static bool +ext_vacation_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +ext_vacation_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def vacation_operation = { + .mnemonic = "VACATION", + .ext_def = &vacation_extension, + .dump = ext_vacation_operation_dump, + .execute = ext_vacation_operation_execute +}; + +/* + * Vacation action + */ + +/* Forward declarations */ + +static int +act_vacation_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +int act_vacation_check_conflict(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_vacation_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_vacation_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_vacation = { + .name = "vacation", + .flags = SIEVE_ACTFLAG_SENDS_RESPONSE, + .check_duplicate = act_vacation_check_duplicate, + .check_conflict = act_vacation_check_conflict, + .print = act_vacation_print, + .commit = act_vacation_commit +}; + +/* Action context information */ + +struct act_vacation_context { + const char *reason; + + sieve_number_t seconds; + const char *subject; + const char *handle; + bool mime; + const char *from; + const struct smtp_address *from_address; + const struct smtp_address *const *addresses; +}; + +/* + * Command validation context + */ + +struct cmd_vacation_context_data { + string_t *from; + string_t *subject; + + bool mime; + + struct sieve_ast_argument *handle_arg; +}; + +/* + * Tag validation + */ + +static bool +cmd_vacation_validate_number_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *ext = sieve_argument_ext(*arg); + const struct ext_vacation_config *config = + (const struct ext_vacation_config *)ext->context; + struct sieve_ast_argument *tag = *arg; + sieve_number_t period, seconds; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :days number + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_NUMBER, FALSE)) + return FALSE; + + period = sieve_ast_argument_number(*arg); + if (sieve_argument_is(tag, vacation_days_tag)) + seconds = period * (24*60*60); + else if (sieve_argument_is(tag, vacation_seconds_tag)) + seconds = period; + else + i_unreached(); + + /* Enforce :seconds >= min_period */ + if (seconds < config->min_period) { + seconds = config->min_period; + + sieve_argument_validate_warning( + valdtr, *arg, + "specified :%s value '%llu' is under the minimum", + sieve_argument_identifier(tag), + (unsigned long long)period); + /* Enforce :days <= max_period */ + } else if (config->max_period > 0 && seconds > config->max_period) { + seconds = config->max_period; + + sieve_argument_validate_warning( + valdtr, *arg, + "specified :%s value '%llu' is over the maximum", + sieve_argument_identifier(tag), + (unsigned long long)period); + } + + sieve_ast_argument_number_set(*arg, seconds); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool +cmd_vacation_validate_string_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + struct cmd_vacation_context_data *ctx_data = + (struct cmd_vacation_context_data *)cmd->data; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :subject string + * :from string + * :handle string + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING, FALSE)) + return FALSE; + + if (sieve_argument_is(tag, vacation_from_tag)) { + if (sieve_argument_is_string_literal(*arg)) { + string_t *address = sieve_ast_argument_str(*arg); + const char *error; + bool result; + + T_BEGIN { + result = sieve_address_validate_str(address, + &error); + + if (!result) { + sieve_argument_validate_error( + valdtr, *arg, + "specified :from address '%s' is invalid for vacation action: %s", + str_sanitize(str_c(address), 128), + error); + } + } T_END; + + if (!result) + return FALSE; + } + + ctx_data->from = sieve_ast_argument_str(*arg); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, vacation_subject_tag)) { + ctx_data->subject = sieve_ast_argument_str(*arg); + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + } else if (sieve_argument_is(tag, vacation_handle_tag)) { + ctx_data->handle_arg = *arg; + + /* Detach optional argument (emitted as mandatory) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + } + return TRUE; +} + +static bool +cmd_vacation_validate_stringlist_tag(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *tag = *arg; + + /* Detach the tag itself */ + *arg = sieve_ast_arguments_detach(*arg,1); + + /* Check syntax: + * :addresses string-list + */ + if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0, + SAAT_STRING_LIST, FALSE)) + return FALSE; + + /* Skip parameter */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +static bool +cmd_vacation_validate_mime_tag(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + struct cmd_vacation_context_data *ctx_data = + (struct cmd_vacation_context_data *)cmd->data; + + ctx_data->mime = TRUE; + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Command registration + */ + +static bool +cmd_vacation_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_days_tag, OPT_SECONDS); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_subject_tag, OPT_SUBJECT); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_from_tag, OPT_FROM); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_addresses_tag, OPT_ADDRESSES); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_mime_tag, OPT_MIME); + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &vacation_handle_tag, 0); + return TRUE; +} + +bool ext_vacation_register_seconds_tag( + struct sieve_validator *valdtr, + const struct sieve_extension *vacation_ext) +{ + sieve_validator_register_external_tag( + valdtr, vacation_command.identifier, vacation_ext, + &vacation_seconds_tag, OPT_SECONDS); + + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_vacation_pre_validate(struct sieve_validator *valdtr ATTR_UNUSED, + struct sieve_command *cmd) +{ + struct cmd_vacation_context_data *ctx_data; + + /* Assign context */ + ctx_data = p_new(sieve_command_pool(cmd), + struct cmd_vacation_context_data, 1); + cmd->data = ctx_data; + + return TRUE; +} + +static const char _handle_empty_subject[] = "<default-subject>"; +static const char _handle_empty_from[] = "<default-from>"; +static const char _handle_mime_enabled[] = "<MIME>"; +static const char _handle_mime_disabled[] = "<NO-MIME>"; + +static bool +cmd_vacation_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + struct cmd_vacation_context_data *ctx_data = + (struct cmd_vacation_context_data *)cmd->data; + + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "reason", 1, + SAAT_STRING)) + return FALSE; + + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + /* Construct handle if not set explicitly */ + if (ctx_data->handle_arg == NULL) { + T_BEGIN { + string_t *handle; + string_t *reason = sieve_ast_argument_str(arg); + unsigned int size = str_len(reason); + + /* Precalculate the size of it all */ + size += (ctx_data->subject == NULL ? + sizeof(_handle_empty_subject) - 1 : + str_len(ctx_data->subject)); + size += (ctx_data->from == NULL ? + sizeof(_handle_empty_from) - 1 : + str_len(ctx_data->from)); + size += (ctx_data->mime ? + sizeof(_handle_mime_enabled) - 1 : + sizeof(_handle_mime_disabled) - 1); + + /* Construct the string */ + handle = t_str_new(size); + str_append_str(handle, reason); + + if (ctx_data->subject != NULL) + str_append_str(handle, ctx_data->subject); + else + str_append(handle, _handle_empty_subject); + + if (ctx_data->from != NULL) + str_append_str(handle, ctx_data->from); + else + str_append(handle, _handle_empty_from); + + str_append(handle, (ctx_data->mime ? + _handle_mime_enabled : + _handle_mime_disabled)); + + /* Create positional handle argument */ + ctx_data->handle_arg = + sieve_ast_argument_string_create( + cmd->ast_node, handle, + sieve_ast_node_line(cmd->ast_node)); + } T_END; + + if (!sieve_validator_argument_activate( + valdtr, cmd, ctx_data->handle_arg, TRUE)) + return FALSE; + } else { + /* Attach explicit handle argument as positional */ + (void)sieve_ast_argument_attach(cmd->ast_node, + ctx_data->handle_arg); + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_vacation_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &vacation_operation); + + /* Generate arguments */ + if (!sieve_generate_arguments(cgenv, cmd, NULL)) + return FALSE; + return TRUE; +} + +/* + * Code dump + */ + +static bool +ext_vacation_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "VACATION"); + sieve_code_descend(denv); + + /* Dump optional operands */ + + for (;;) { + int opt; + bool opok = TRUE; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + opok = sieve_opr_number_dump(denv, address, "seconds"); + break; + case OPT_SUBJECT: + opok = sieve_opr_string_dump(denv, address, "subject"); + break; + case OPT_FROM: + opok = sieve_opr_string_dump(denv, address, "from"); + break; + case OPT_ADDRESSES: + opok = sieve_opr_stringlist_dump(denv, address, + "addresses"); + break; + case OPT_MIME: + sieve_code_dumpf(denv, "mime"); + break; + default: + return FALSE; + } + + if (!opok) + return FALSE; + } + + /* Dump reason and handle operands */ + return (sieve_opr_string_dump(denv, address, "reason") && + sieve_opr_string_dump(denv, address, "handle")); +} + +/* + * Code execution + */ + +static int +ext_vacation_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + const struct ext_vacation_config *config = + (const struct ext_vacation_config *)this_ext->context; + struct sieve_side_effects_list *slist = NULL; + struct act_vacation_context *act; + pool_t pool; + int opt_code = 0; + sieve_number_t seconds = config->default_period; + bool mime = FALSE; + struct sieve_stringlist *addresses = NULL; + string_t *reason, *subject = NULL, *from = NULL, *handle = NULL; + const struct smtp_address *from_address = NULL; + int ret; + + /* + * Read code + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_SECONDS: + ret = sieve_opr_number_read(renv, address, "seconds", + &seconds); + break; + case OPT_SUBJECT: + ret = sieve_opr_string_read(renv, address, "subject", + &subject); + break; + case OPT_FROM: + ret = sieve_opr_string_read(renv, address, "from", + &from); + break; + case OPT_ADDRESSES: + ret = sieve_opr_stringlist_read(renv, address, + "addresses", + &addresses); + break; + case OPT_MIME: + mime = TRUE; + ret = SIEVE_EXEC_OK; + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + ret = SIEVE_EXEC_BIN_CORRUPT; + } + + if (ret <= 0) + return ret; + } + + /* Fixed operands */ + + if ((ret =sieve_opr_string_read(renv, address, + "reason", &reason)) <= 0 || + (ret = sieve_opr_string_read(renv, address, + "handle", &handle)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Trace */ + + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "vacation action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace(renv, 0, "auto-reply with message `%s'", + str_sanitize(str_c(reason), 80)); + } + + /* Parse :from address */ + if (from != NULL) { + const char *error; + + from_address = sieve_address_parse_str(from, &error); + if (from_address == NULL) { + sieve_runtime_error( + renv, NULL, + "specified :from address '%s' is invalid for vacation action: %s", + str_sanitize(str_c(from), 128), error); + } + } + + /* Add vacation action to the result */ + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_vacation_context, 1); + act->reason = p_strdup(pool, str_c(reason)); + act->handle = p_strdup(pool, str_c(handle)); + act->seconds = seconds; + act->mime = mime; + if (subject != NULL) + act->subject = p_strdup(pool, str_c(subject)); + if (from != NULL) { + act->from = p_strdup(pool, str_c(from)); + act->from_address = smtp_address_clone(pool, from_address); + } + + /* Normalize all addresses */ + if (addresses != NULL) { + ARRAY_TYPE(smtp_address_const) addrs; + string_t *raw_address; + int ret; + + sieve_stringlist_reset(addresses); + + p_array_init(&addrs, pool, 4); + + raw_address = NULL; + while ((ret = sieve_stringlist_next_item(addresses, + &raw_address)) > 0) { + const struct smtp_address *addr; + const char *error; + + addr = sieve_address_parse_str(raw_address, &error); + if (addr != NULL) { + addr = smtp_address_clone(pool, addr); + array_append(&addrs, &addr, 1); + } else { + sieve_runtime_error( + renv, NULL, + "specified :addresses item '%s' is invalid: " + "%s for vacation action (ignored)", + str_sanitize(str_c(raw_address),128), + error); + } + } + + if (ret < 0) { + sieve_runtime_trace_error( + renv, "invalid addresses stringlist"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + (void)array_append_space(&addrs); + act->addresses = array_idx(&addrs, 0); + } + + if (sieve_result_add_action(renv, this_ext, "vacation", &act_vacation, + slist, (void *)act, 0, FALSE) < 0) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static int +act_vacation_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "duplicate vacation action not allowed " + "(previously triggered one was here: %s)", + act_other->location); + return -1; + } + + /* Not an error if executed in preceeding script */ + return 1; +} + +int act_vacation_check_conflict(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + if ((act_other->def->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0) { + if (!sieve_action_is_executed(act_other, renv->result)) { + sieve_runtime_error( + renv, act->location, + "vacation action conflicts with other action: " + "the %s action (%s) also sends a response back to the sender", + act_other->def->name, act_other->location); + return -1; + } else { + /* Not an error if executed in preceeding script */ + return 1; + } + } + + return 0; +} + +/* Result printing */ + +static void act_vacation_print(const struct sieve_action *action ATTR_UNUSED, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + struct act_vacation_context *ctx = + (struct act_vacation_context *)action->context; + + sieve_result_action_printf(rpenv, "send vacation message:"); + sieve_result_printf(rpenv, " => seconds : %llu\n", + (unsigned long long)ctx->seconds); + if (ctx->subject != NULL) { + sieve_result_printf(rpenv, " => subject : %s\n", + ctx->subject); + } + if (ctx->from != NULL) { + sieve_result_printf(rpenv, " => from : %s\n", + ctx->from); + } + if (ctx->handle != NULL) { + sieve_result_printf(rpenv, " => handle : %s\n", + ctx->handle); + } + sieve_result_printf(rpenv, "\nSTART MESSAGE\n%s\nEND MESSAGE\n", + ctx->reason); +} + +/* Result execution */ + +/* Headers known to be associated with mailing lists + */ +static const char * const _list_headers[] = { + "list-id", + "list-owner", + "list-subscribe", + "list-post", + "list-unsubscribe", + "list-help", + "list-archive", + NULL +}; + +/* Headers that should be searched for the user's own mail address(es) + */ + +static const char * const _my_address_headers[] = { + "to", + "cc", + "bcc", + "resent-to", + "resent-cc", + "resent-bcc", + NULL +}; + +/* Headers that should be searched for the full sender address + */ + +static const char * const _sender_headers[] = { + "sender", + "resent-from", + "from", + NULL +}; + +static inline bool _is_system_address(const struct smtp_address *address) +{ + if (strcasecmp(address->localpart, "MAILER-DAEMON") == 0) + return TRUE; + if (strcasecmp(address->localpart, "LISTSERV") == 0) + return TRUE; + if (strcasecmp(address->localpart, "majordomo") == 0) + return TRUE; + if (strstr(address->localpart, "-request") != NULL) + return TRUE; + if (str_begins(address->localpart, "owner-")) + return TRUE; + return FALSE; +} + +static bool +_msg_address_equals(const struct message_address *addr1, + const struct smtp_address *addr2) +{ + struct smtp_address saddr; + + i_assert(addr1->mailbox != NULL); + return (smtp_address_init_from_msg(&saddr, addr1) >= 0 && + smtp_address_equals_icase(addr2, &saddr)); +} + +static inline bool +_header_contains_my_address(const char *header_val, + const struct smtp_address *my_address) +{ + const struct message_address *msg_addr; + + msg_addr = message_address_parse(pool_datastack_create(), + (const unsigned char *)header_val, + strlen(header_val), 256, 0); + while (msg_addr != NULL) { + if (msg_addr->domain != NULL) { + if (_msg_address_equals(msg_addr, my_address)) + return TRUE; + } + + msg_addr = msg_addr->next; + } + + return FALSE; +} + +static inline bool +_contains_my_address(const char * const *headers, + const struct smtp_address *my_address) +{ + const char *const *hdsp = headers; + + while (*hdsp != NULL) { + bool result; + + T_BEGIN { + result = _header_contains_my_address(*hdsp, my_address); + } T_END; + + if (result) + return TRUE; + + hdsp++; + } + + return FALSE; +} + +static bool _contains_8bit(const char *text) +{ + const unsigned char *p = (const unsigned char *)text; + + for (; *p != '\0'; p++) { + if ((*p & 0x80) != 0) + return TRUE; + } + return FALSE; +} + +static bool +_header_get_full_reply_recipient(const struct ext_vacation_config *config, + const struct smtp_address *smtp_to, + const char *header, + struct message_address *reply_to_r) +{ + const struct message_address *addr; + + addr = message_address_parse( + pool_datastack_create(), + (const unsigned char *)header, + strlen(header), 256, 0); + + for (; addr != NULL; addr = addr->next) { + bool matched = config->to_header_ignore_envelope; + + if (addr->domain == NULL || addr->invalid_syntax) + continue; + + if (!matched) + matched = _msg_address_equals(addr, smtp_to); + + if (matched) { + *reply_to_r = *addr; + return TRUE; + } + } + return FALSE; +} + +static int +_get_full_reply_recipient(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + const struct smtp_address *smtp_to, + struct message_address *reply_to_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + const char *const *hdsp; + int ret; + + hdsp = _sender_headers; + for (; *hdsp != NULL; hdsp++) { + const char *header; + + if ((ret = mail_get_first_header(msgdata->mail, *hdsp, + &header)) < 0) { + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `%s'", *hdsp); + } + if (ret == 0 || header == NULL) + continue; + + if (_header_get_full_reply_recipient(config, smtp_to, + header, reply_to_r)) + return SIEVE_EXEC_OK; + } + + reply_to_r->mailbox = smtp_to->localpart; + reply_to_r->domain = smtp_to->domain; + return SIEVE_EXEC_OK; +} + +static const struct var_expand_table * +_get_var_expand_table(const struct sieve_action_exec_env *aenv ATTR_UNUSED, + const char *subject) +{ + const struct var_expand_table stack_tab[] = { + { '$', subject, "subject" }, + { '\0', NULL, NULL } + }; + + return p_memdup(unsafe_data_stack_pool, stack_tab, sizeof(stack_tab)); +} + +static int +act_vacation_get_default_subject(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + const char **subject_r) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + const char *header, *error; + string_t *str; + const struct var_expand_table *tab; + int ret; + + *subject_r = (config->default_subject == NULL ? + "Automated reply" : config->default_subject); + if ((ret = mail_get_first_header_utf8(msgdata->mail, "subject", + &header)) < 0) { + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `subject'"); + } + if (ret == 0) + return SIEVE_EXEC_OK; + if (config->default_subject_template == NULL) { + *subject_r = t_strconcat("Auto: ", header, NULL); + return SIEVE_EXEC_OK; + } + + str = t_str_new(256); + tab = _get_var_expand_table(aenv, header); + if (var_expand(str, config->default_subject_template, + tab, &error) <= 0) { + i_error("Failed to expand deliver_log_format=%s: %s", + config->default_subject_template, error); + *subject_r = t_strconcat("Auto: ", header, NULL); + return SIEVE_EXEC_OK; + } + + *subject_r = str_c(str); + return SIEVE_EXEC_OK; +} + +static int +act_vacation_send(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + struct act_vacation_context *ctx, + const struct smtp_address *smtp_to, + const struct smtp_address *smtp_from, + const struct message_address *reply_from) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + const struct sieve_message_data *msgdata = eenv->msgdata; + const struct sieve_script_env *senv = eenv->scriptenv; + struct sieve_smtp_context *sctx; + struct ostream *output; + string_t *msg; + struct message_address reply_to; + const char *header, *outmsgid, *subject, *error; + int ret; + + /* Check smpt functions just to be sure */ + + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning( + aenv, "vacation action has no means to send mail"); + return SIEVE_EXEC_OK; + } + + /* Make sure we have a subject for our reply */ + + if (ctx->subject == NULL || *(ctx->subject) == '\0') { + if ((ret = act_vacation_get_default_subject(aenv, config, + &subject)) <= 0) + return ret; + } else { + subject = ctx->subject; + } + + subject = str_sanitize_utf8(subject, config->max_subject_codepoints); + + /* Obtain full To address for reply */ + + i_zero(&reply_to); + reply_to.mailbox = smtp_to->localpart; + reply_to.domain = smtp_to->domain; + if ((ret = _get_full_reply_recipient(aenv, config, smtp_to, + &reply_to)) <= 0) + return ret; + + /* Open smtp session */ + + sctx = sieve_smtp_start_single(senv, smtp_to, smtp_from, &output); + + outmsgid = sieve_message_get_new_id(eenv->svinst); + + /* Produce a proper reply */ + + msg = t_str_new(512); + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Message-ID", outmsgid); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + + if (ctx->from != NULL && *(ctx->from) != '\0') { + rfc2822_header_write_address(msg, "From", ctx->from); + } else { + if (reply_from == NULL || reply_from->mailbox == NULL || + *reply_from->mailbox == '\0') + reply_from = sieve_get_postmaster(senv); + rfc2822_header_write( + msg, "From", + message_address_first_to_string(reply_from)); + } + + rfc2822_header_write(msg, "To", + message_address_first_to_string(&reply_to)); + + if (_contains_8bit(subject)) + rfc2822_header_utf8_printf(msg, "Subject", "%s", subject); + else + rfc2822_header_printf(msg, "Subject", "%s", subject); + + /* Compose proper in-reply-to and references headers */ + + if ((ret = mail_get_first_header(msgdata->mail, "references", + &header)) < 0) { + sieve_smtp_abort(sctx); + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `references'"); + } + + if (msgdata->id != NULL) { + rfc2822_header_write(msg, "In-Reply-To", msgdata->id); + + if (ret > 0 && header != NULL) { + rfc2822_header_write( + msg, "References", + t_strconcat(header, " ", msgdata->id, NULL)); + } else { + rfc2822_header_write(msg, "References", msgdata->id); + } + } else if (ret > 0 && header != NULL) { + rfc2822_header_write(msg, "References", header); + } + + rfc2822_header_write(msg, "Auto-Submitted", "auto-replied (vacation)"); + rfc2822_header_write(msg, "Precedence", "bulk"); + + /* Prevent older Microsoft products from replying to this message */ + rfc2822_header_write(msg, "X-Auto-Response-Suppress", "All"); + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + + if (!ctx->mime) { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + str_append(msg, "\r\n"); + } + + str_printfa(msg, "%s\r\n", ctx->reason); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Close smtp session */ + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to send vacation response to %s: " + "<%s> (temporary error)", + smtp_address_encode(smtp_to), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error( + aenv, "failed to send vacation response to %s: " + "<%s> (permanent error)", + smtp_address_encode(smtp_to), + str_sanitize(error, 512)); + } + /* This error will be ignored in the end */ + return SIEVE_EXEC_FAILURE; + } + + eenv->exec_status->significant_action_executed = TRUE; + return SIEVE_EXEC_OK; +} + +static void +act_vacation_hash(struct act_vacation_context *vctx, const char *sender, + unsigned char hash_r[]) +{ + const char *rpath = t_str_lcase(sender); + struct md5_context ctx; + + md5_init(&ctx); + md5_update(&ctx, rpath, strlen(rpath)); + + md5_update(&ctx, vctx->handle, strlen(vctx->handle)); + + md5_final(&ctx, hash_r); +} + +static int +act_vacation_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_extension *ext = action->ext; + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + const struct ext_vacation_config *config = + (const struct ext_vacation_config *)ext->context; + struct act_vacation_context *ctx = + (struct act_vacation_context *)action->context; + unsigned char dupl_hash[MD5_RESULTLEN]; + struct mail *mail = sieve_message_get_mail(aenv->msgctx); + const struct smtp_address *sender, *recipient; + const struct smtp_address *orig_recipient, *user_email; + const struct smtp_address *smtp_from; + struct message_address reply_from; + const char *const *hdsp, *const *headers; + int ret; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_SKIP_RESPONSES) != 0) { + sieve_result_global_log( + aenv, "not sending vacation reply (skipped)"); + return SIEVE_EXEC_OK; + } + + sender = sieve_message_get_sender(aenv->msgctx); + recipient = sieve_message_get_final_recipient(aenv->msgctx); + + i_zero(&reply_from); + smtp_from = orig_recipient = user_email = NULL; + + /* Is the recipient unset? + */ + if (smtp_address_isnull(recipient)) { + sieve_result_global_warning( + aenv, "vacation action aborted: " + "envelope recipient is <>"); + return SIEVE_EXEC_OK; + } + + /* Is the return path unset ? + */ + if (smtp_address_isnull(sender)) { + sieve_result_global_log(aenv, "discarded vacation reply to <>"); + return SIEVE_EXEC_OK; + } + + /* Are we perhaps trying to respond to ourselves ? + */ + if (smtp_address_equals_icase(sender, recipient)) { + sieve_result_global_log( + aenv, "discarded vacation reply to own address <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + + /* Are we perhaps trying to respond to one of our alternative :addresses? + */ + if (ctx->addresses != NULL) { + const struct smtp_address * const *alt_address; + + alt_address = ctx->addresses; + while (*alt_address != NULL) { + if (smtp_address_equals_icase(sender, *alt_address)) { + sieve_result_global_log( + aenv, + "discarded vacation reply to own address <%s> " + "(as specified using :addresses argument)", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + alt_address++; + } + } + + /* Did whe respond to this user before? */ + if (sieve_action_duplicate_check_available(aenv)) { + bool duplicate; + + act_vacation_hash(ctx, smtp_address_encode(sender), dupl_hash); + + ret = sieve_action_duplicate_check(aenv, dupl_hash, + sizeof(dupl_hash), + &duplicate); + if (ret < SIEVE_EXEC_OK) { + sieve_result_critical( + aenv, "failed to check for duplicate vacation response", + "failed to check for duplicate vacation response%s", + (ret == SIEVE_EXEC_TEMP_FAILURE ? + " (temporaty failure)" : "")); + return ret; + } + if (duplicate) { + sieve_result_global_log( + aenv, + "discarded duplicate vacation response to <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + } + + /* Are we trying to respond to a mailing list ? */ + hdsp = _list_headers; + while (*hdsp != NULL) { + if ((ret = mail_get_headers(mail, *hdsp, &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `%s'", *hdsp); + } + + if (ret > 0 && headers[0] != NULL) { + /* Yes, bail out */ + sieve_result_global_log( + aenv, "discarding vacation response " + "to mailinglist recipient <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + hdsp++; + } + + /* Is the message that we are replying to an automatic reply ? */ + if ((ret = mail_get_headers(mail, "auto-submitted", &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `auto-submitted'"); + } + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + hdsp = headers; + while (*hdsp != NULL) { + if (strcasecmp(*hdsp, "no") != 0) { + sieve_result_global_log( + aenv, "discarding vacation response " + "to auto-submitted message from <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + hdsp++; + } + } + + /* Check for the (non-standard) precedence header */ + if ((ret = mail_get_headers(mail, "precedence", &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, "failed to read header field `precedence'"); + } + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + hdsp = headers; + while (*hdsp != NULL) { + if (strcasecmp(*hdsp, "junk") == 0 || + strcasecmp(*hdsp, "bulk") == 0 || + strcasecmp(*hdsp, "list") == 0) { + sieve_result_global_log( + aenv, "discarding vacation response " + "to precedence=%s message from <%s>", + *hdsp, smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + hdsp++; + } + } + + /* Check for the (non-standard) Microsoft X-Auto-Response-Suppress header */ + if ((ret = mail_get_headers(mail, "x-auto-response-suppress", + &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, + "failed to read header field `x-auto-response-suppress'"); + } + /* Theoretically multiple headers could exist, so lets make sure */ + if (ret > 0) { + hdsp = headers; + while (*hdsp != NULL) { + const char *const *flags = t_strsplit(*hdsp, ","); + + while (*flags != NULL) { + const char *flag = t_str_trim(*flags, " \t"); + + if (strcasecmp(flag, "All") == 0 || + strcasecmp(flag, "OOF") == 0) { + sieve_result_global_log( + aenv, "discarding vacation response to message from <%s> " + "(`%s' flag found in x-auto-response-suppress header)", + smtp_address_encode(sender), flag); + return SIEVE_EXEC_OK; + } + flags++; + } + hdsp++; + } + } + + /* Do not reply to system addresses */ + if (_is_system_address(sender)) { + sieve_result_global_log( + aenv, "not sending vacation response to system address <%s>", + smtp_address_encode(sender)); + return SIEVE_EXEC_OK; + } + + /* Fetch original recipient if necessary */ + if (config->use_original_recipient) + orig_recipient = sieve_message_get_orig_recipient(aenv->msgctx); + /* Fetch explicitly configured user email address */ + if (svinst->user_email != NULL) + user_email = svinst->user_email; + + /* Is the original message directly addressed to the user or the addresses + * specified using the :addresses tag? + */ + hdsp = _my_address_headers; + while (*hdsp != NULL) { + if ((ret = mail_get_headers(mail, *hdsp, &headers)) < 0) { + return sieve_result_mail_error( + aenv, mail, "failed to read header field `%s'", + *hdsp); + } + if (ret > 0 && headers[0] != NULL) { + /* Final recipient directly listed in headers? */ + if (_contains_my_address(headers, recipient)) { + smtp_from = recipient; + message_address_init_from_smtp( + &reply_from, NULL, recipient); + break; + } + + /* Original recipient directly listed in headers? */ + if (!smtp_address_isnull(orig_recipient) && + _contains_my_address(headers, orig_recipient)) { + smtp_from = orig_recipient; + message_address_init_from_smtp( + &reply_from, NULL, orig_recipient); + break; + } + + /* User-provided :addresses listed in headers? */ + if (ctx->addresses != NULL) { + bool found = FALSE; + const struct smtp_address * const *my_address; + + my_address = ctx->addresses; + while (!found && *my_address != NULL) { + if ((found = _contains_my_address(headers, *my_address))) { + /* Avoid letting user determine SMTP sender directly */ + smtp_from = (orig_recipient == NULL ? + recipient : orig_recipient); + message_address_init_from_smtp( + &reply_from, NULL, *my_address); + } + my_address++; + } + + if (found) break; + } + + /* Explicitly-configured user email address directly listed in + headers? */ + if (user_email != NULL && + _contains_my_address(headers, user_email)) { + smtp_from = user_email; + message_address_init_from_smtp( + &reply_from, NULL, smtp_from); + break; + } + } + hdsp++; + } + + /* My address not found in the headers; we got an implicit delivery */ + if (*hdsp == NULL) { + if (config->dont_check_recipient) { + /* Send reply from envelope recipient address */ + smtp_from = (orig_recipient == NULL ? + recipient : orig_recipient); + if (user_email == NULL) + user_email = sieve_get_user_email(svinst); + message_address_init_from_smtp(&reply_from, + NULL, user_email); + } else { + const char *orig_rcpt_str = "", *user_email_str = ""; + + /* Bail out */ + if (config->use_original_recipient) { + orig_rcpt_str = + t_strdup_printf("original-recipient=<%s>, ", + (orig_recipient == NULL ? "UNAVAILABLE" : + smtp_address_encode(orig_recipient))); + } + + if (user_email != NULL) { + user_email_str = t_strdup_printf( + "user-email=<%s>, ", + smtp_address_encode(user_email)); + } + + sieve_result_global_log( + aenv, "discarding vacation response for implicitly delivered message; " + "no known (envelope) recipient address found in message headers " + "(recipient=<%s>, %s%sand%s additional `:addresses' are specified)", + smtp_address_encode(recipient), + orig_rcpt_str, user_email_str, + (ctx->addresses == NULL || *ctx->addresses == NULL ? + " no" : "")); + return SIEVE_EXEC_OK; + } + } + + /* Send the message */ + + T_BEGIN { + ret = act_vacation_send( + aenv, config, ctx, sender, + (config->send_from_recipient ? smtp_from : NULL), + &reply_from); + } T_END; + + if (ret == SIEVE_EXEC_OK) { + sieve_number_t seconds; + + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = + sieve_action_create_finish_event(aenv); + + sieve_result_event_log(aenv, e->event(), + "sent vacation response to <%s>", + smtp_address_encode(sender)); + + /* Check period limits once more */ + seconds = ctx->seconds; + if (seconds < config->min_period) + seconds = config->min_period; + else if (config->max_period > 0 && seconds > config->max_period) + seconds = config->max_period; + + /* Mark as replied */ + if (seconds > 0) { + sieve_action_duplicate_mark(aenv, dupl_hash, + sizeof(dupl_hash), + ioloop_time + seconds); + } + } + + if (ret == SIEVE_EXEC_TEMP_FAILURE) + return SIEVE_EXEC_TEMP_FAILURE; + + /* Ignore all other errors */ + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.c b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.c new file mode 100644 index 0000000..97be3a5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.c @@ -0,0 +1,114 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-settings.h" +#include "sieve-extensions.h" + +#include "ext-vacation-common.h" + +bool ext_vacation_load +(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_vacation_config *config; + sieve_number_t min_period, max_period, default_period; + bool use_original_recipient, dont_check_recipient, send_from_recipient, + to_header_ignore_envelope; + unsigned long long max_subject_codepoints; + const char *default_subject, *default_subject_template; + + if ( *context != NULL ) { + ext_vacation_unload(ext); + } + + if ( !sieve_setting_get_duration_value + (svinst, "sieve_vacation_min_period", &min_period) ) { + min_period = EXT_VACATION_DEFAULT_MIN_PERIOD; + } + + if ( !sieve_setting_get_duration_value + (svinst, "sieve_vacation_max_period", &max_period) ) { + max_period = EXT_VACATION_DEFAULT_MAX_PERIOD; + } + + if ( !sieve_setting_get_duration_value + (svinst, "sieve_vacation_default_period", &default_period) ) { + default_period = EXT_VACATION_DEFAULT_PERIOD; + } + + if ( max_period > 0 + && (min_period > max_period || default_period < min_period + || default_period > max_period) ) { + min_period = EXT_VACATION_DEFAULT_MIN_PERIOD; + max_period = EXT_VACATION_DEFAULT_MAX_PERIOD; + default_period = EXT_VACATION_DEFAULT_PERIOD; + + e_warning(svinst->event, "vacation extension: " + "invalid settings: violated " + "sieve_vacation_min_period < " + "sieve_vacation_default_period < " + "sieve_vacation_max_period"); + } + + default_subject = sieve_setting_get( + svinst, "sieve_vacation_default_subject"); + default_subject_template = sieve_setting_get( + svinst, "sieve_vacation_default_subject_template"); + + if ( !sieve_setting_get_uint_value + (svinst, "sieve_vacation_max_subject_codepoints", &max_subject_codepoints) ) { + max_subject_codepoints = EXT_VACATION_DEFAULT_MAX_SUBJECT_CODEPOINTS; + } + + if ( !sieve_setting_get_bool_value + (svinst, "sieve_vacation_use_original_recipient", &use_original_recipient) ) { + use_original_recipient = FALSE; + } + + if ( !sieve_setting_get_bool_value + (svinst, "sieve_vacation_dont_check_recipient", &dont_check_recipient) ) { + dont_check_recipient = FALSE; + } + + if ( !sieve_setting_get_bool_value + (svinst, "sieve_vacation_send_from_recipient", &send_from_recipient) ) { + send_from_recipient = FALSE; + } + + if ( !sieve_setting_get_bool_value(svinst, + "sieve_vacation_to_header_ignore_envelope", + &to_header_ignore_envelope) ) { + to_header_ignore_envelope = FALSE; + } + + config = i_new(struct ext_vacation_config, 1); + config->min_period = min_period; + config->max_period = max_period; + config->default_period = default_period; + config->max_subject_codepoints = max_subject_codepoints; + config->default_subject = i_strdup_empty(default_subject); + config->default_subject_template = i_strdup_empty(default_subject_template); + config->use_original_recipient = use_original_recipient; + config->dont_check_recipient = dont_check_recipient; + config->send_from_recipient = send_from_recipient; + config->to_header_ignore_envelope = to_header_ignore_envelope; + + *context = (void *) config; + + return TRUE; +} + +void ext_vacation_unload +(const struct sieve_extension *ext) +{ + struct ext_vacation_config *config = + (struct ext_vacation_config *) ext->context; + + i_free(config->default_subject); + i_free(config->default_subject_template); + i_free(config); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.h b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.h new file mode 100644 index 0000000..3a38cf6 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-common.h @@ -0,0 +1,60 @@ +#ifndef EXT_VACATION_COMMON_H +#define EXT_VACATION_COMMON_H + +#include "sieve-common.h" + +/* + * Extension configuration + */ + +#define EXT_VACATION_DEFAULT_PERIOD (7*24*60*60) +#define EXT_VACATION_DEFAULT_MIN_PERIOD (24*60*60) +#define EXT_VACATION_DEFAULT_MAX_PERIOD 0 +#define EXT_VACATION_DEFAULT_MAX_SUBJECT_CODEPOINTS 256 + +struct ext_vacation_config { + unsigned int min_period; + unsigned int max_period; + unsigned int default_period; + unsigned long long max_subject_codepoints; + char *default_subject; + char *default_subject_template; + bool use_original_recipient; + bool dont_check_recipient; + bool send_from_recipient; + bool to_header_ignore_envelope; +}; + +/* + * Commands + */ + +extern const struct sieve_command_def vacation_command; + +/* + * Operations + */ + +extern const struct sieve_operation_def vacation_operation; + +/* + * Extensions + */ + +/* Vacation */ + +extern const struct sieve_extension_def vacation_extension; + +bool ext_vacation_load + (const struct sieve_extension *ext, void **context); +void ext_vacation_unload + (const struct sieve_extension *ext); + +/* Vacation-seconds */ + +extern const struct sieve_extension_def vacation_seconds_extension; + +bool ext_vacation_register_seconds_tag + (struct sieve_validator *valdtr, const struct sieve_extension *vacation_ext); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-seconds.c b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-seconds.c new file mode 100644 index 0000000..41c0f06 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation-seconds.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vacation-seconds + * -------------------------- + * + * Authors: Stephan Bosch <stephan@rename-it.nl> + * Specification: RFC 6131 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-validator.h" + +#include "ext-vacation-common.h" + +/* + * Extension + */ + +bool ext_vacation_seconds_load + (const struct sieve_extension *ext, void **context); +static bool ext_vacation_seconds_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def vacation_seconds_extension = { + .name = "vacation-seconds", + .load = ext_vacation_seconds_load, + .validator_load = ext_vacation_seconds_validator_load, +}; + +bool ext_vacation_seconds_load +(const struct sieve_extension *ext, void **context) +{ + if ( *context == NULL ) { + /* Make sure vacation extension is registered */ + *context = (void *) + sieve_extension_require(ext->svinst, &vacation_extension, TRUE); + } + + return TRUE; +} + +static bool ext_vacation_seconds_validator_load +(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_validator *valdtr) +{ + const struct sieve_extension *vacation_ext; + + /* Load vacation extension implicitly */ + + vacation_ext = sieve_validator_extension_load_implicit + (valdtr, vacation_extension.name); + + if ( vacation_ext == NULL ) + return FALSE; + + /* Add seconds tag to vacation command */ + + return ext_vacation_register_seconds_tag(valdtr, vacation_ext); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation.c b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation.c new file mode 100644 index 0000000..8d3d9a7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vacation/ext-vacation.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vacation + * ------------------ + * + * Authors: Stephan Bosch <stephan@rename-it.nl> + * Specification: RFC 5230 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" + +#include "sieve-common.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-vacation-common.h" + +/* + * Extension + */ + +static bool +ext_vacation_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr); +static bool +ext_vacation_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +static bool +ext_vacation_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, void *context, + struct sieve_ast_argument *require_arg, + bool required); +static int +ext_vacation_interpreter_run(const struct sieve_extension *this_ext, + const struct sieve_runtime_env *renv, + void *context, bool deferred); + +const struct sieve_extension_def vacation_extension = { + .name = "vacation", + .load = ext_vacation_load, + .unload = ext_vacation_unload, + .validator_load = ext_vacation_validator_load, + .interpreter_load = ext_vacation_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(vacation_operation) +}; +const struct sieve_validator_extension +vacation_validator_extension = { + .ext = &vacation_extension, + .validate = ext_vacation_validator_validate +}; +const struct sieve_interpreter_extension +vacation_interpreter_extension = { + .ext_def = &vacation_extension, + .run = ext_vacation_interpreter_run +}; + +static bool +ext_vacation_validator_load(const struct sieve_extension *ext, + struct sieve_validator *valdtr) +{ + /* Register new command */ + sieve_validator_register_command(valdtr, ext, &vacation_command); + + sieve_validator_extension_register(valdtr, ext, + &vacation_validator_extension, NULL); + return TRUE; +} + +static bool +ext_vacation_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + sieve_interpreter_extension_register( + renv->interp, ext, &vacation_interpreter_extension, NULL); + return TRUE; +} + +static bool +ext_vacation_validator_validate(const struct sieve_extension *ext, + struct sieve_validator *valdtr, + void *context ATTR_UNUSED, + struct sieve_ast_argument *require_arg, + bool required) +{ + if (required) { + enum sieve_compile_flags flags = + sieve_validator_compile_flags(valdtr); + + if ((flags & SIEVE_COMPILE_FLAG_NO_ENVELOPE) != 0) { + sieve_argument_validate_error( + valdtr, require_arg, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + return FALSE; + } + } + return TRUE; +} + +static int +ext_vacation_interpreter_run(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + void *context ATTR_UNUSED, bool deferred) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0) { + if (!deferred) { + sieve_runtime_error( + renv, NULL, + "the %s extension cannot be used in this context " + "(needs access to message envelope)", + sieve_extension_name(ext)); + } + return SIEVE_EXEC_FAILURE; + } + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/Makefile.am b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.am new file mode 100644 index 0000000..354bad2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.am @@ -0,0 +1,41 @@ +noinst_LTLIBRARIES = libsieve_ext_variables.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-set.c + +tsts = \ + tst-string.c + +libsieve_ext_variables_la_SOURCES = \ + ext-variables-common.c \ + ext-variables-name.c \ + ext-variables-namespaces.c \ + ext-variables-arguments.c \ + ext-variables-operands.c \ + ext-variables-modifiers.c \ + ext-variables-dump.c \ + $(cmds) \ + $(tsts) \ + ext-variables.c + +public_headers = \ + sieve-ext-variables.h + +headers = \ + ext-variables-common.h \ + ext-variables-limits.h \ + ext-variables-name.h \ + ext-variables-namespaces.h \ + ext-variables-arguments.h \ + ext-variables-operands.h \ + ext-variables-modifiers.h \ + ext-variables-dump.h + +pkginc_libdir=$(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/Makefile.in b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.in new file mode 100644 index 0000000..701d574 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/Makefile.in @@ -0,0 +1,801 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/variables +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) \ + $(pkginc_lib_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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_variables_la_LIBADD = +am__objects_1 = cmd-set.lo +am__objects_2 = tst-string.lo +am_libsieve_ext_variables_la_OBJECTS = ext-variables-common.lo \ + ext-variables-name.lo ext-variables-namespaces.lo \ + ext-variables-arguments.lo ext-variables-operands.lo \ + ext-variables-modifiers.lo ext-variables-dump.lo \ + $(am__objects_1) $(am__objects_2) ext-variables.lo +libsieve_ext_variables_la_OBJECTS = \ + $(am_libsieve_ext_variables_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 = +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)/cmd-set.Plo \ + ./$(DEPDIR)/ext-variables-arguments.Plo \ + ./$(DEPDIR)/ext-variables-common.Plo \ + ./$(DEPDIR)/ext-variables-dump.Plo \ + ./$(DEPDIR)/ext-variables-modifiers.Plo \ + ./$(DEPDIR)/ext-variables-name.Plo \ + ./$(DEPDIR)/ext-variables-namespaces.Plo \ + ./$(DEPDIR)/ext-variables-operands.Plo \ + ./$(DEPDIR)/ext-variables.Plo ./$(DEPDIR)/tst-string.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 = $(libsieve_ext_variables_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_variables_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(pkginc_libdir)" +HEADERS = $(noinst_HEADERS) $(pkginc_lib_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@ +noinst_LTLIBRARIES = libsieve_ext_variables.la +AM_CPPFLAGS = \ + -I$(srcdir)/../.. \ + $(LIBDOVECOT_INCLUDE) + +cmds = \ + cmd-set.c + +tsts = \ + tst-string.c + +libsieve_ext_variables_la_SOURCES = \ + ext-variables-common.c \ + ext-variables-name.c \ + ext-variables-namespaces.c \ + ext-variables-arguments.c \ + ext-variables-operands.c \ + ext-variables-modifiers.c \ + ext-variables-dump.c \ + $(cmds) \ + $(tsts) \ + ext-variables.c + +public_headers = \ + sieve-ext-variables.h + +headers = \ + ext-variables-common.h \ + ext-variables-limits.h \ + ext-variables-name.h \ + ext-variables-namespaces.h \ + ext-variables-arguments.h \ + ext-variables-operands.h \ + ext-variables-modifiers.h \ + ext-variables-dump.h + +pkginc_libdir = $(dovecot_pkgincludedir)/sieve +pkginc_lib_HEADERS = $(public_headers) +noinst_HEADERS = $(headers) +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/lib-sieve/plugins/variables/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/variables/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_variables.la: $(libsieve_ext_variables_la_OBJECTS) $(libsieve_ext_variables_la_DEPENDENCIES) $(EXTRA_libsieve_ext_variables_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_variables_la_OBJECTS) $(libsieve_ext_variables_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-set.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-arguments.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-dump.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-modifiers.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-name.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-namespaces.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables-operands.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-variables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-string.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 +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +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)$(pkginc_libdir)"; 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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-set.Plo + -rm -f ./$(DEPDIR)/ext-variables-arguments.Plo + -rm -f ./$(DEPDIR)/ext-variables-common.Plo + -rm -f ./$(DEPDIR)/ext-variables-dump.Plo + -rm -f ./$(DEPDIR)/ext-variables-modifiers.Plo + -rm -f ./$(DEPDIR)/ext-variables-name.Plo + -rm -f ./$(DEPDIR)/ext-variables-namespaces.Plo + -rm -f ./$(DEPDIR)/ext-variables-operands.Plo + -rm -f ./$(DEPDIR)/ext-variables.Plo + -rm -f ./$(DEPDIR)/tst-string.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-pkginc_libHEADERS + +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)/cmd-set.Plo + -rm -f ./$(DEPDIR)/ext-variables-arguments.Plo + -rm -f ./$(DEPDIR)/ext-variables-common.Plo + -rm -f ./$(DEPDIR)/ext-variables-dump.Plo + -rm -f ./$(DEPDIR)/ext-variables-modifiers.Plo + -rm -f ./$(DEPDIR)/ext-variables-name.Plo + -rm -f ./$(DEPDIR)/ext-variables-namespaces.Plo + -rm -f ./$(DEPDIR)/ext-variables-operands.Plo + -rm -f ./$(DEPDIR)/ext-variables.Plo + -rm -f ./$(DEPDIR)/tst-string.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-pkginc_libHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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-pkginc_libHEADERS 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-pkginc_libHEADERS + +.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/lib-sieve/plugins/variables/cmd-set.c b/pigeonhole/src/lib-sieve/plugins/variables/cmd-set.c new file mode 100644 index 0000000..d0fdc97 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/cmd-set.c @@ -0,0 +1,235 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" + +#include "sieve-code.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-binary.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-variables-common.h" + +/* + * Set command + * + * Syntax: + * set [MODIFIER] <name: string> <value: string> + */ + +static bool cmd_set_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool cmd_set_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool cmd_set_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def cmd_set = { + .identifier = "set", + .type = SCT_COMMAND, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_set_registered, + .validate = cmd_set_validate, + .generate = cmd_set_generate, +}; + +/* + * Set operation + */ + +static bool cmd_set_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_set_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def cmd_set_operation = { + .mnemonic = "SET", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERATION_SET, + .dump = cmd_set_operation_dump, + .execute = cmd_set_operation_execute +}; + +/* + * Compiler context + */ + +struct cmd_set_context { + ARRAY_TYPE(sieve_variables_modifier) modifiers; +}; + +/* Command registration */ + +static bool cmd_set_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_variables_modifiers_link_tag(valdtr, ext, cmd_reg); + + return TRUE; +} + +/* + * Command validation + */ + +static bool cmd_set_validate(struct sieve_validator *valdtr, + struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast_argument *arg = cmd->first_positional; + pool_t pool = sieve_command_pool(cmd); + struct cmd_set_context *sctx; + + /* Create command context */ + sctx = p_new(pool, struct cmd_set_context, 1); + p_array_init(&sctx->modifiers, pool, 4); + cmd->data = (void *) sctx; + + /* Validate modifiers */ + if ( !sieve_variables_modifiers_validate + (valdtr, cmd, &sctx->modifiers) ) + return FALSE; + + /* Validate name argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "name", 1, SAAT_STRING) ) { + return FALSE; + } + if ( !sieve_variable_argument_activate + (this_ext, this_ext, valdtr, cmd, arg, TRUE) ) { + return FALSE; + } + arg = sieve_ast_argument_next(arg); + + /* Validate value argument */ + if ( !sieve_validate_positional_argument + (valdtr, cmd, arg, "value", 2, SAAT_STRING) ) { + return FALSE; + } + return sieve_validator_argument_activate + (valdtr, cmd, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_set_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_binary_block *sblock = cgenv->sblock; + struct cmd_set_context *sctx = (struct cmd_set_context *) cmd->data; + + sieve_operation_emit(sblock, this_ext, &cmd_set_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + /* Generate modifiers */ + if ( !sieve_variables_modifiers_generate + (cgenv, &sctx->modifiers) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool cmd_set_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "SET"); + sieve_code_descend(denv); + + /* Print both variable name and string value */ + if ( !sieve_opr_string_dump(denv, address, "variable") || + !sieve_opr_string_dump(denv, address, "value") ) + return FALSE; + + return sieve_variables_modifiers_code_dump(denv, address); +} + +/* + * Code execution + */ + +static int cmd_set_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct sieve_variable_storage *storage; + ARRAY_TYPE(sieve_variables_modifier) modifiers; + unsigned int var_index; + string_t *value; + int ret = SIEVE_EXEC_OK; + + /* + * Read the normal operands + */ + + if ( (ret=sieve_variable_operand_read + (renv, address, "variable", &storage, &var_index)) <= 0 ) + return ret; + + if ( (ret=sieve_opr_string_read(renv, address, "string", &value)) <= 0 ) + return ret; + + if ( (ret=sieve_variables_modifiers_code_read + (renv, this_ext, address, &modifiers)) <= 0 ) + return ret; + + /* + * Determine and assign the value + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "set command"); + sieve_runtime_trace_descend(renv); + + /* Apply modifiers */ + if ( (ret=sieve_variables_modifiers_apply + (renv, this_ext, &modifiers, &value)) <= 0 ) + return ret; + + /* Actually assign the value if all is well */ + i_assert ( value != NULL ); + if ( !sieve_variable_assign(storage, var_index, value) ) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Trace */ + if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { + const char *var_name, *var_id; + + (void)sieve_variable_get_identifier(storage, var_index, &var_name); + var_id = sieve_variable_get_varid(storage, var_index); + + sieve_runtime_trace_here(renv, 0, "assign `%s' [%s] = \"%s\"", + var_name, var_id, str_c(value)); + } + + return SIEVE_EXEC_OK; +} + + + + + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.c new file mode 100644 index 0000000..2ac773c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.c @@ -0,0 +1,420 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" +#include "ext-variables-operands.h" +#include "ext-variables-namespaces.h" +#include "ext-variables-arguments.h" + +/* + * Variable argument implementation + */ + +static bool arg_variable_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context); + +const struct sieve_argument_def variable_argument = { + .identifier = "@variable", + .generate = arg_variable_generate +}; + +static bool ext_variables_variable_argument_activate +(const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + const char *variable) +{ + struct sieve_ast *ast = arg->ast; + struct sieve_variable *var; + + var = ext_variables_validator_declare_variable(this_ext, valdtr, variable); + + if ( var == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "(implicit) declaration of new variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(var_ext)); + return FALSE; + } + + arg->argument = sieve_argument_create(ast, &variable_argument, this_ext, 0); + arg->argument->data = (void *) var; + return TRUE; +} + +static struct sieve_ast_argument *ext_variables_variable_argument_create +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *parent_arg, const char *variable) +{ + struct sieve_ast *ast = parent_arg->ast; + struct sieve_ast_argument *new_arg; + + new_arg = sieve_ast_argument_create(ast, sieve_ast_argument_line(parent_arg)); + new_arg->type = SAAT_STRING; + + if ( !ext_variables_variable_argument_activate + (this_ext, this_ext, valdtr, new_arg, variable) ) + return NULL; + + return new_arg; +} + +static bool arg_variable_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + struct sieve_argument *argument = arg->argument; + struct sieve_variable *var = (struct sieve_variable *) argument->data; + + sieve_variables_opr_variable_emit(cgenv->sblock, argument->ext, var); + + return TRUE; +} + +/* + * Match value argument implementation + */ + +static bool arg_match_value_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED); + +const struct sieve_argument_def match_value_argument = { + .identifier = "@match_value", + .generate = arg_match_value_generate +}; + +static bool ext_variables_match_value_argument_activate +(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + unsigned int index, bool assignment) +{ + struct sieve_ast *ast = arg->ast; + + if ( assignment ) { + sieve_argument_validate_error(valdtr, arg, + "cannot assign to match variable"); + return FALSE; + } + + if ( index > EXT_VARIABLES_MAX_MATCH_INDEX ) { + sieve_argument_validate_error(valdtr, arg, + "match value index %u out of range (max: %u)", index, + EXT_VARIABLES_MAX_MATCH_INDEX); + return FALSE; + } + + arg->argument = sieve_argument_create + (ast, &match_value_argument, this_ext, 0); + arg->argument->data = (void *) POINTER_CAST(index); + return TRUE; +} + +static struct sieve_ast_argument *ext_variables_match_value_argument_create +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *parent_arg, unsigned int index) +{ + struct sieve_ast *ast = parent_arg->ast; + struct sieve_ast_argument *new_arg; + + new_arg = sieve_ast_argument_create(ast, sieve_ast_argument_line(parent_arg)); + new_arg->type = SAAT_STRING; + + if ( !ext_variables_match_value_argument_activate + (this_ext, valdtr, new_arg, index, FALSE) ) { + return NULL; + } + + return new_arg; +} + +static bool arg_match_value_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED) +{ + struct sieve_argument *argument = arg->argument; + unsigned int index = POINTER_CAST_TO(argument->data, unsigned int); + + sieve_variables_opr_match_value_emit(cgenv->sblock, argument->ext, index); + + return TRUE; +} + +/* + * Variable string argument implementation + */ + +static bool arg_variable_string_validate + (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd); + +const struct sieve_argument_def variable_string_argument = { + .identifier = "@variable-string", + .validate = arg_variable_string_validate, + .generate = sieve_arg_catenated_string_generate, +}; + +static bool arg_variable_string_validate +(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, + struct sieve_command *cmd) +{ + const struct sieve_extension *this_ext = (*arg)->argument->ext; + enum { ST_NONE, ST_OPEN, ST_VARIABLE, ST_CLOSE } state = ST_NONE; + pool_t pool = sieve_ast_pool((*arg)->ast); + struct sieve_arg_catenated_string *catstr = NULL; + string_t *str = sieve_ast_argument_str(*arg); + const char *p, *strstart, *substart = NULL; + const char *strval = (const char *) str_data(str); + const char *strend = strval + str_len(str); + bool result = TRUE; + ARRAY_TYPE(sieve_variable_name) substitution; + int nelements = 0; + + T_BEGIN { + /* Initialize substitution structure */ + t_array_init(&substitution, 2); + + p = strval; + strstart = p; + while ( result && p < strend ) { + switch ( state ) { + + /* Nothing found yet */ + case ST_NONE: + if ( *p == '$' ) { + substart = p; + state = ST_OPEN; + } + p++; + break; + + /* Got '$' */ + case ST_OPEN: + if ( *p == '{' ) { + state = ST_VARIABLE; + p++; + } else + state = ST_NONE; + break; + + /* Got '${' */ + case ST_VARIABLE: + nelements = ext_variable_name_parse(&substitution, &p, strend); + + if ( nelements < 0 ) + state = ST_NONE; + else + state = ST_CLOSE; + + break; + + /* Finished parsing name, expecting '}' */ + case ST_CLOSE: + if ( *p == '}' ) { + struct sieve_ast_argument *strarg; + + /* We now know that the substitution is valid */ + + if ( catstr == NULL ) { + catstr = sieve_arg_catenated_string_create(*arg); + } + + /* Add the substring that is before the substitution to the + * variable-string AST. + * + * FIXME: For efficiency, if the variable is not found we should + * coalesce this substring with the one after the substitution. + */ + if ( substart > strstart ) { + string_t *newstr = str_new(pool, substart - strstart); + str_append_data(newstr, strstart, substart - strstart); + + strarg = sieve_ast_argument_string_create_raw + ((*arg)->ast, newstr, (*arg)->source_line); + sieve_arg_catenated_string_add_element(catstr, strarg); + + /* Give other substitution extensions a chance to do their work */ + if ( !sieve_validator_argument_activate_super + (valdtr, cmd, strarg, FALSE) ) { + result = FALSE; + break; + } + } + + /* Find the variable */ + if ( nelements == 1 ) { + const struct sieve_variable_name *cur_element = + array_idx(&substitution, 0); + + if ( cur_element->num_variable == -1 ) { + /* Add variable argument '${identifier}' */ + + strarg = ext_variables_variable_argument_create + (this_ext, valdtr, *arg, str_c(cur_element->identifier)); + + } else { + /* Add match value argument '${000}' */ + + strarg = ext_variables_match_value_argument_create + (this_ext, valdtr, *arg, cur_element->num_variable); + } + } else { + strarg = ext_variables_namespace_argument_create + (this_ext, valdtr, *arg, cmd, &substitution); + } + + if ( strarg != NULL ) + sieve_arg_catenated_string_add_element(catstr, strarg); + + strstart = p + 1; + substart = strstart; + + p++; + } + + /* Finished, reset for the next substitution */ + state = ST_NONE; + } + } + } T_END; + + /* Bail out early if substitution is invalid */ + if ( !result ) return FALSE; + + /* Check whether any substitutions were found */ + if ( catstr == NULL ) { + /* No substitutions in this string, pass it on to any other substution + * extension. + */ + return sieve_validator_argument_activate_super(valdtr, cmd, *arg, TRUE); + } + + /* Add the final substring that comes after the last substitution to the + * variable-string AST. + */ + if ( strend > strstart ) { + struct sieve_ast_argument *strarg; + string_t *newstr = str_new(pool, strend - strstart); + str_append_data(newstr, strstart, strend - strstart); + + strarg = sieve_ast_argument_string_create_raw + ((*arg)->ast, newstr, (*arg)->source_line); + sieve_arg_catenated_string_add_element(catstr, strarg); + + /* Give other substitution extensions a chance to do their work */ + if ( !sieve_validator_argument_activate_super + (valdtr, cmd, strarg, FALSE) ) + return FALSE; + } + + return TRUE; +} + +/* + * Variable argument interface + */ + +static bool _sieve_variable_argument_activate +(const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool assignment) +{ + bool result = FALSE; + string_t *variable; + const char *varstr, *varend; + ARRAY_TYPE(sieve_variable_name) vname; + int nelements = 0; + + T_BEGIN { + t_array_init(&vname, 2); + + variable = sieve_ast_argument_str(arg); + varstr = str_c(variable); + varend = PTR_OFFSET(varstr, str_len(variable)); + nelements = ext_variable_name_parse(&vname, &varstr, varend); + + /* Check whether name parsing succeeded */ + if ( nelements <= 0 || varstr != varend ) { + /* Parse failed */ + sieve_argument_validate_error(valdtr, arg, + "invalid variable name '%s'", str_sanitize(str_c(variable),80)); + } else if ( nelements == 1 ) { + /* Normal (match) variable */ + + const struct sieve_variable_name *cur_element = + array_idx(&vname, 0); + + if ( cur_element->num_variable < 0 ) { + /* Variable */ + result = ext_variables_variable_argument_activate(var_ext, + this_ext, valdtr, arg, str_c(cur_element->identifier)); + + } else { + /* Match value */ + result = ext_variables_match_value_argument_activate + (this_ext, valdtr, arg, cur_element->num_variable, assignment); + } + + } else { + /* Namespace variable */ + result = ext_variables_namespace_argument_activate + (this_ext, valdtr, arg, cmd, &vname, assignment); + } + } T_END; + + return result; +} + +bool sieve_variable_argument_activate +(const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool assignment) +{ + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + /* Single string */ + return _sieve_variable_argument_activate(var_ext, + this_ext, valdtr, cmd, arg, assignment); + + } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { + /* String list */ + struct sieve_ast_argument *stritem; + + i_assert ( !assignment ); + + stritem = sieve_ast_strlist_first(arg); + while ( stritem != NULL ) { + if ( !_sieve_variable_argument_activate(var_ext, + this_ext, valdtr, cmd, stritem, assignment) ) + return FALSE; + + stritem = sieve_ast_strlist_next(stritem); + } + + arg->argument = sieve_argument_create + (arg->ast, &string_list_argument, NULL, 0); + + return TRUE; + } + + return FALSE; +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.h new file mode 100644 index 0000000..87413c8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-arguments.h @@ -0,0 +1,24 @@ +#ifndef EXT_VARIABLES_ARGUMENTS_H +#define EXT_VARIABLES_ARGUMENTS_H + +#include "sieve-common.h" + +/* + * Variable argument + */ + +extern const struct sieve_argument_def variable_argument; + +/* + * Match value argument + */ + +extern const struct sieve_argument_def match_value_argument; + +/* + * Variable string argument + */ + +extern const struct sieve_argument_def variable_string_argument; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.c new file mode 100644 index 0000000..be9f677 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.c @@ -0,0 +1,950 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-settings.h" + +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-objects.h" +#include "sieve-match-types.h" + +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" +#include "sieve-interpreter.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" +#include "ext-variables-modifiers.h" + +/* + * Limits + */ + +unsigned int +sieve_variables_get_max_scope_size(const struct sieve_extension *var_ext) +{ + const struct ext_variables_config *config = + ext_variables_get_config(var_ext); + + return config->max_scope_size; +} + +size_t +sieve_variables_get_max_variable_size(const struct sieve_extension *var_ext) +{ + const struct ext_variables_config *config = + ext_variables_get_config(var_ext); + + return config->max_variable_size; +} + +/* + * Extension configuration + */ + +bool +ext_variables_load(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_variables_config *config; + unsigned long long int uint_setting; + size_t size_setting; + + if (*context != NULL) + ext_variables_unload(ext); + + config = i_new(struct ext_variables_config, 1); + + /* Get limits */ + config->max_scope_size = EXT_VARIABLES_DEFAULT_MAX_SCOPE_SIZE; + config->max_variable_size = EXT_VARIABLES_DEFAULT_MAX_VARIABLE_SIZE; + + if (sieve_setting_get_uint_value( + svinst, "sieve_variables_max_scope_size", &uint_setting)) { + if (uint_setting < EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE) { + e_warning(svinst->event, "variables: " + "setting sieve_variables_max_scope_size " + "is lower than required by standards " + "(>= %llu items)", + (unsigned long long)EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE); + } else { + config->max_scope_size = (unsigned int)uint_setting; + } + } + + if (sieve_setting_get_size_value( + svinst, "sieve_variables_max_variable_size", &size_setting)) { + if (size_setting < EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE) { + e_warning(svinst->event, "variables: " + "setting sieve_variables_max_variable_size " + "is lower than required by standards " + "(>= %zu bytes)", + (size_t)EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE); + } else { + config->max_variable_size = size_setting; + } + } + + *context = (void *)config; + return TRUE; +} + +void ext_variables_unload(const struct sieve_extension *ext) +{ + struct ext_variables_config *config = + (struct ext_variables_config *)ext->context; + + i_free(config); +} + +const struct ext_variables_config * +ext_variables_get_config(const struct sieve_extension *var_ext) +{ + const struct ext_variables_config *config = + (const struct ext_variables_config *)var_ext->context; + + i_assert(var_ext->def == &variables_extension); + return config; +} + +/* + * Variable scope + */ + +struct sieve_variable_scope { + pool_t pool; + int refcount; + + struct sieve_instance *svinst; + const struct sieve_extension *var_ext; + const struct sieve_extension *ext; + + struct sieve_variable *error_var; + + HASH_TABLE(const char *, struct sieve_variable *) variables; + ARRAY(struct sieve_variable *) variable_index; +}; + +struct sieve_variable_scope_binary { + struct sieve_variable_scope *scope; + + unsigned int size; + struct sieve_binary_block *sblock; + sieve_size_t address; +}; + +struct sieve_variable_scope_iter { + struct sieve_variable_scope *scope; + struct hash_iterate_context *hctx; +}; + +struct sieve_variable_scope * +sieve_variable_scope_create(struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext) +{ + struct sieve_variable_scope *scope; + pool_t pool; + + i_assert(var_ext->def == &variables_extension); + + pool = pool_alloconly_create("sieve_variable_scope", 4096); + scope = p_new(pool, struct sieve_variable_scope, 1); + scope->pool = pool; + scope->refcount = 1; + + scope->svinst = svinst; + scope->var_ext = var_ext; + scope->ext = ext; + + hash_table_create(&scope->variables, pool, 0, strcase_hash, strcasecmp); + p_array_init(&scope->variable_index, pool, 128); + + return scope; +} + +void sieve_variable_scope_ref(struct sieve_variable_scope *scope) +{ + scope->refcount++; +} + +void sieve_variable_scope_unref(struct sieve_variable_scope **_scope) +{ + struct sieve_variable_scope *scope = *_scope; + + i_assert(scope->refcount > 0); + + if (--scope->refcount != 0) + return; + + hash_table_destroy(&scope->variables); + + *_scope = NULL; + pool_unref(&scope->pool); +} + +pool_t sieve_variable_scope_pool(struct sieve_variable_scope *scope) +{ + return scope->pool; +} + +struct sieve_variable * +sieve_variable_scope_declare(struct sieve_variable_scope *scope, + const char *identifier) +{ + unsigned int max_scope_size; + struct sieve_variable *var; + + var = hash_table_lookup(scope->variables, identifier); + if (var != NULL) + return var; + + max_scope_size = sieve_variables_get_max_scope_size(scope->var_ext); + if (array_count(&scope->variable_index) >= max_scope_size) { + if (scope->error_var == NULL) { + var = p_new(scope->pool, struct sieve_variable, 1); + var->identifier = "@ERROR@"; + var->index = 0; + + scope->error_var = var; + return NULL; + } + + return scope->error_var; + } + + var = p_new(scope->pool, struct sieve_variable, 1); + var->ext = scope->ext; + var->identifier = p_strdup(scope->pool, identifier); + var->index = array_count(&scope->variable_index); + + hash_table_insert(scope->variables, var->identifier, var); + array_append(&scope->variable_index, &var, 1); + return var; +} + +struct sieve_variable * +sieve_variable_scope_get_variable(struct sieve_variable_scope *scope, + const char *identifier) +{ + return hash_table_lookup(scope->variables, identifier); +} + +struct sieve_variable * +sieve_variable_scope_import(struct sieve_variable_scope *scope, + struct sieve_variable *var) +{ + struct sieve_variable *old_var, *new_var; + + old_var = sieve_variable_scope_get_variable(scope, var->identifier); + if (old_var != NULL) { + i_assert(memcmp(old_var, var, sizeof(*var)) == 0); + return old_var; + } + + new_var = p_new(scope->pool, struct sieve_variable, 1); + memcpy(new_var, var, sizeof(*new_var)); + + hash_table_insert(scope->variables, new_var->identifier, new_var); + + /* Not entered into the index because it is an external variable + (This can be done unlimited; only limited by the size of the external + scope) + */ + return new_var; +} + +struct sieve_variable_scope_iter * +sieve_variable_scope_iterate_init(struct sieve_variable_scope *scope) +{ + struct sieve_variable_scope_iter *iter; + + iter = t_new(struct sieve_variable_scope_iter, 1); + iter->scope = scope; + iter->hctx = hash_table_iterate_init(scope->variables); + + return iter; +} + +bool sieve_variable_scope_iterate(struct sieve_variable_scope_iter *iter, + struct sieve_variable **var_r) +{ + const char *key; + + return hash_table_iterate(iter->hctx, iter->scope->variables, + &key, var_r); +} + +void sieve_variable_scope_iterate_deinit( + struct sieve_variable_scope_iter **iter) +{ + hash_table_iterate_deinit(&(*iter)->hctx); + *iter = NULL; +} + +unsigned int +sieve_variable_scope_declarations(struct sieve_variable_scope *scope) +{ + return hash_table_count(scope->variables); +} + +unsigned int sieve_variable_scope_size(struct sieve_variable_scope *scope) +{ + return array_count(&scope->variable_index); +} + +struct sieve_variable * const * +sieve_variable_scope_get_variables(struct sieve_variable_scope *scope, + unsigned int *size_r) +{ + return array_get(&scope->variable_index, size_r); +} + +struct sieve_variable * +sieve_variable_scope_get_indexed(struct sieve_variable_scope *scope, + unsigned int index) +{ + struct sieve_variable * const *var; + + if (index >= array_count(&scope->variable_index)) + return NULL; + + var = array_idx(&scope->variable_index, index); + return *var; +} + +/* Scope binary */ + +struct sieve_variable_scope * +sieve_variable_scope_binary_dump(struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + struct sieve_variable_scope *local_scope; + unsigned int i, scope_size; + sieve_size_t pc; + sieve_offset_t end_offset; + + /* Read scope size */ + sieve_code_mark(denv); + if (!sieve_binary_read_unsigned(denv->sblock, address, &scope_size)) + return NULL; + + /* Read offset */ + pc = *address; + if (!sieve_binary_read_offset(denv->sblock, address, &end_offset)) + return NULL; + + /* Create scope */ + local_scope = sieve_variable_scope_create(svinst, var_ext, ext); + + /* Read and dump scope itself */ + + sieve_code_dumpf(denv, "VARIABLES SCOPE [%u] (end: %08x)", + scope_size, (unsigned int)(pc + end_offset)); + + for (i = 0; i < scope_size; i++) { + string_t *identifier; + + sieve_code_mark(denv); + if (!sieve_binary_read_string(denv->sblock, address, + &identifier)) + return NULL; + + sieve_code_dumpf(denv, "%3d: '%s'", i, str_c(identifier)); + + (void)sieve_variable_scope_declare(local_scope, + str_c(identifier)); + } + + return local_scope; +} + +struct sieve_variable_scope_binary * +sieve_variable_scope_binary_create(struct sieve_variable_scope *scope) +{ + struct sieve_variable_scope_binary *scpbin; + + scpbin = p_new(scope->pool, struct sieve_variable_scope_binary, 1); + scpbin->scope = scope; + + return scpbin; +} + +void sieve_variable_scope_binary_ref(struct sieve_variable_scope_binary *scpbin) +{ + sieve_variable_scope_ref(scpbin->scope); +} + +void sieve_variable_scope_binary_unref( + struct sieve_variable_scope_binary **scpbin) +{ + sieve_variable_scope_unref(&(*scpbin)->scope); + *scpbin = NULL; +} + +struct sieve_variable_scope_binary * +sieve_variable_scope_binary_read(struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + struct sieve_binary_block *sblock, + sieve_size_t *address) +{ + struct sieve_variable_scope *scope; + struct sieve_variable_scope_binary *scpbin; + unsigned int scope_size, max_scope_size; + const char *ext_name = (ext == NULL ? "variables" : + sieve_extension_name(ext)); + sieve_size_t pc; + sieve_offset_t end_offset; + + /* Read scope size */ + if (!sieve_binary_read_unsigned(sblock, address, &scope_size)) { + e_error(svinst->event, "%s: " + "variable scope: failed to read size", ext_name); + return NULL; + } + + /* Check size limit */ + max_scope_size = sieve_variables_get_max_scope_size(var_ext); + if (scope_size > max_scope_size) { + e_error(svinst->event, "%s: " + "variable scope: size exceeds the limit (%u > %u)", + ext_name, scope_size, max_scope_size); + return NULL; + } + + /* Read offset */ + pc = *address; + if (!sieve_binary_read_offset(sblock, address, &end_offset)) { + e_error(svinst->event, "%s: " + "variable scope: failed to read end offset", ext_name); + return NULL; + } + + /* Create scope */ + scope = sieve_variable_scope_create(svinst, var_ext, ext); + + scpbin = sieve_variable_scope_binary_create(scope); + scpbin->size = scope_size; + scpbin->sblock = sblock; + scpbin->address = *address; + + *address = pc + end_offset; + + return scpbin; +} + +struct sieve_variable_scope * +sieve_variable_scope_binary_get(struct sieve_variable_scope_binary *scpbin) +{ + const struct sieve_extension *ext = scpbin->scope->ext; + struct sieve_instance *svinst = scpbin->scope->svinst; + const char *ext_name = (ext == NULL ? "variables" : + sieve_extension_name(ext)); + unsigned int i; + + if (scpbin->sblock != NULL) { + sieve_size_t *address = &scpbin->address; + + /* Read scope itself */ + for (i = 0; i < scpbin->size; i++) { + struct sieve_variable *var; + string_t *identifier; + + if (!sieve_binary_read_string(scpbin->sblock, address, + &identifier)) { + e_error(svinst->event, "%s: variable scope: " + "failed to read variable name", + ext_name); + return NULL; + } + + var = sieve_variable_scope_declare(scpbin->scope, + str_c(identifier)); + + i_assert(var != NULL); + i_assert(var->index == i); + } + + scpbin->sblock = NULL; + } + + return scpbin->scope; +} + +unsigned int +sieve_variable_scope_binary_get_size( + struct sieve_variable_scope_binary *scpbin) +{ + if (scpbin->sblock != NULL) + return scpbin->size; + + return array_count(&scpbin->scope->variable_index); +} + +/* + * Variable storage + */ + +struct sieve_variable_storage { + pool_t pool; + const struct sieve_extension *var_ext; + struct sieve_variable_scope *scope; + struct sieve_variable_scope_binary *scope_bin; + unsigned int max_size; + ARRAY(string_t *) var_values; +}; + +struct sieve_variable_storage * +sieve_variable_storage_create(const struct sieve_extension *var_ext, + pool_t pool, + struct sieve_variable_scope_binary *scpbin) +{ + struct sieve_variable_storage *storage; + + storage = p_new(pool, struct sieve_variable_storage, 1); + storage->pool = pool; + storage->var_ext = var_ext; + storage->scope_bin = scpbin; + storage->scope = NULL; + + storage->max_size = sieve_variable_scope_binary_get_size(scpbin); + + p_array_init(&storage->var_values, pool, 4); + + return storage; +} + +static inline bool +sieve_variable_valid(struct sieve_variable_storage *storage, + unsigned int index) +{ + if (storage->scope_bin == NULL) + return TRUE; + + return (index < storage->max_size); +} + +bool sieve_variable_get_identifier(struct sieve_variable_storage *storage, + unsigned int index, const char **identifier) +{ + struct sieve_variable * const *var; + + *identifier = NULL; + + if (storage->scope_bin == NULL) + return TRUE; + + if (storage->scope == NULL) { + storage->scope = + sieve_variable_scope_binary_get(storage->scope_bin); + if (storage->scope == NULL) + return FALSE; + } + + /* FIXME: direct invasion of the scope object is a bit ugly */ + if (index >= array_count(&storage->scope->variable_index)) + return FALSE; + + var = array_idx(&storage->scope->variable_index, index); + if (*var != NULL) + *identifier = (*var)->identifier; + return TRUE; +} + +const char * +sieve_variable_get_varid(struct sieve_variable_storage *storage, + unsigned int index) +{ + if (storage->scope_bin == NULL) + return t_strdup_printf("%ld", (long)index); + + if (storage->scope == NULL) { + storage->scope = + sieve_variable_scope_binary_get(storage->scope_bin); + if (storage->scope == NULL) + return NULL; + } + + return sieve_ext_variables_get_varid(storage->scope->ext, index); +} + +bool sieve_variable_get(struct sieve_variable_storage *storage, + unsigned int index, string_t **value) +{ + *value = NULL; + + if (index < array_count(&storage->var_values)) { + string_t * const *varent; + + varent = array_idx(&storage->var_values, index); + + *value = *varent; + } else if (!sieve_variable_valid(storage, index)) { + return FALSE; + } + + return TRUE; +} + +bool sieve_variable_get_modifiable(struct sieve_variable_storage *storage, + unsigned int index, string_t **value) +{ + string_t *dummy; + + if (value == NULL) + value = &dummy; + + if (!sieve_variable_get(storage, index, value)) + return FALSE; + + if (*value == NULL) { + *value = str_new(storage->pool, 256); + array_idx_set(&storage->var_values, index, value); + } + return TRUE; +} + +bool sieve_variable_assign(struct sieve_variable_storage *storage, + unsigned int index, const string_t *value) +{ + const struct ext_variables_config *config = + ext_variables_get_config(storage->var_ext); + string_t *varval; + + if (!sieve_variable_get_modifiable(storage, index, &varval)) + return FALSE; + + str_truncate(varval, 0); + str_append_str(varval, value); + + /* Just a precaution, caller should prevent this in the first place */ + if (str_len(varval) > config->max_variable_size) + str_truncate_utf8(varval, config->max_variable_size); + + return TRUE; +} + +bool sieve_variable_assign_cstr(struct sieve_variable_storage *storage, + unsigned int index, const char *value) +{ + const struct ext_variables_config *config = + ext_variables_get_config(storage->var_ext); + string_t *varval; + + if (!sieve_variable_get_modifiable(storage, index, &varval)) + return FALSE; + + str_truncate(varval, 0); + str_append(varval, value); + + /* Just a precaution, caller should prevent this in the first place */ + if (str_len(varval) > config->max_variable_size) + str_truncate_utf8(varval, config->max_variable_size); + + return TRUE; +} + +/* + * AST Context + */ + +static void +ext_variables_ast_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_ast *ast ATTR_UNUSED, void *context) +{ + struct sieve_variable_scope *local_scope = + (struct sieve_variable_scope *)context; + + /* Unreference main variable scope */ + sieve_variable_scope_unref(&local_scope); +} + +static const struct sieve_ast_extension variables_ast_extension = { + &variables_extension, + ext_variables_ast_free +}; + +static struct sieve_variable_scope * +ext_variables_create_local_scope(const struct sieve_extension *this_ext, + struct sieve_ast *ast) +{ + struct sieve_variable_scope *scope; + + scope = sieve_variable_scope_create(this_ext->svinst, this_ext, NULL); + + sieve_ast_extension_register(ast, this_ext, &variables_ast_extension, + (void *)scope); + return scope; +} + +static struct sieve_variable_scope * +ext_variables_ast_get_local_scope(const struct sieve_extension *this_ext, + struct sieve_ast *ast) +{ + struct sieve_variable_scope *local_scope = + (struct sieve_variable_scope *) + sieve_ast_extension_get_context(ast, this_ext); + + return local_scope; +} + +/* + * Validator context + */ + +static struct ext_variables_validator_context * +ext_variables_validator_context_create(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr) +{ + pool_t pool = sieve_validator_pool(valdtr); + struct ext_variables_validator_context *ctx; + struct sieve_ast *ast = sieve_validator_ast(valdtr); + + ctx = p_new(pool, struct ext_variables_validator_context, 1); + ctx->modifiers = sieve_validator_object_registry_create(valdtr); + ctx->namespaces = sieve_validator_object_registry_create(valdtr); + ctx->local_scope = ext_variables_create_local_scope(this_ext, ast); + + sieve_validator_extension_set_context(valdtr, this_ext, (void *)ctx); + return ctx; +} + +struct ext_variables_validator_context * +ext_variables_validator_context_get(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr) +{ + struct ext_variables_validator_context *ctx; + + i_assert(sieve_extension_is(this_ext, variables_extension)); + ctx = (struct ext_variables_validator_context *) + sieve_validator_extension_get_context(valdtr, this_ext); + + if (ctx == NULL) + ctx = ext_variables_validator_context_create(this_ext, valdtr); + return ctx; +} + +void ext_variables_validator_initialize(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr) +{ + struct ext_variables_validator_context *ctx; + + /* Create our context */ + ctx = ext_variables_validator_context_get(this_ext, valdtr); + + ext_variables_register_core_modifiers(this_ext, ctx); + + ctx->active = TRUE; +} + +struct sieve_variable *ext_variables_validator_get_variable( + const struct sieve_extension *this_ext, + struct sieve_validator *validator, const char *variable) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(this_ext, validator); + + return sieve_variable_scope_get_variable(ctx->local_scope, variable); +} + +struct sieve_variable * +ext_variables_validator_declare_variable(const struct sieve_extension *this_ext, + struct sieve_validator *validator, + const char *variable) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(this_ext, validator); + + return sieve_variable_scope_declare(ctx->local_scope, variable); +} + +struct sieve_variable_scope * +sieve_ext_variables_get_local_scope(const struct sieve_extension *var_ext, + struct sieve_validator *validator) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, validator); + + return ctx->local_scope; +} + +bool sieve_ext_variables_is_active(const struct sieve_extension *var_ext, + struct sieve_validator *valdtr) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + return (ctx != NULL && ctx->active); +} + +/* + * Code generation + */ + +bool ext_variables_generator_load(const struct sieve_extension *ext, + const struct sieve_codegen_env *cgenv) +{ + struct sieve_variable_scope *local_scope = + ext_variables_ast_get_local_scope(ext, cgenv->ast); + unsigned int count = sieve_variable_scope_size(local_scope); + sieve_size_t jump; + + sieve_binary_emit_unsigned(cgenv->sblock, count); + + jump = sieve_binary_emit_offset(cgenv->sblock, 0); + + if (count > 0) { + unsigned int size, i; + struct sieve_variable *const *vars = + sieve_variable_scope_get_variables(local_scope, &size); + + for (i = 0; i < size; i++) { + sieve_binary_emit_cstring(cgenv->sblock, + vars[i]->identifier); + } + } + + sieve_binary_resolve_offset(cgenv->sblock, jump); + return TRUE; +} + +/* + * Interpreter context + */ + +struct ext_variables_interpreter_context { + pool_t pool; + + struct sieve_variable_scope *local_scope; + struct sieve_variable_scope_binary *local_scope_bin; + + struct sieve_variable_storage *local_storage; + ARRAY(struct sieve_variable_storage *) ext_storages; +}; + +static void +ext_variables_interpreter_free(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, + void *context) +{ + struct ext_variables_interpreter_context *ctx = + (struct ext_variables_interpreter_context *)context; + + sieve_variable_scope_binary_unref(&ctx->local_scope_bin); +} + +static struct sieve_interpreter_extension +variables_interpreter_extension = { + .ext_def = &variables_extension, + .free = ext_variables_interpreter_free +}; + +static struct ext_variables_interpreter_context * +ext_variables_interpreter_context_create( + const struct sieve_extension *this_ext, + struct sieve_interpreter *interp, + struct sieve_variable_scope_binary *scpbin) +{ + pool_t pool = sieve_interpreter_pool(interp); + struct ext_variables_interpreter_context *ctx; + + ctx = p_new(pool, struct ext_variables_interpreter_context, 1); + ctx->pool = pool; + ctx->local_scope = NULL; + ctx->local_scope_bin = scpbin; + ctx->local_storage = + sieve_variable_storage_create(this_ext, pool, scpbin); + p_array_init(&ctx->ext_storages, pool, + sieve_extensions_get_count(this_ext->svinst)); + + sieve_interpreter_extension_register(interp, this_ext, + &variables_interpreter_extension, + (void *)ctx); + return ctx; +} + +bool ext_variables_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + struct sieve_variable_scope_binary *scpbin; + + scpbin = sieve_variable_scope_binary_read(eenv->svinst, ext, NULL, + renv->sblock, address); + if (scpbin == NULL) + return FALSE; + + /* Create our context */ + (void)ext_variables_interpreter_context_create(ext, renv->interp, + scpbin); + + /* Enable support for match values */ + (void)sieve_match_values_set_enabled(renv, TRUE); + + return TRUE; +} + +static inline struct ext_variables_interpreter_context * +ext_variables_interpreter_context_get(const struct sieve_extension *this_ext, + struct sieve_interpreter *interp) +{ + struct ext_variables_interpreter_context *ctx; + + i_assert(sieve_extension_is(this_ext, variables_extension)); + ctx = (struct ext_variables_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); + return ctx; +} + +struct sieve_variable_storage * +sieve_ext_variables_runtime_get_storage(const struct sieve_extension *var_ext, + const struct sieve_runtime_env *renv, + const struct sieve_extension *ext) +{ + struct ext_variables_interpreter_context *ctx = + ext_variables_interpreter_context_get(var_ext, renv->interp); + struct sieve_variable_storage * const *storage; + + if (ext == NULL) + return ctx->local_storage; + + if (ext->id >= (int)array_count(&ctx->ext_storages)) + storage = NULL; + else + storage = array_idx(&ctx->ext_storages, ext->id); + + if (storage == NULL) + return NULL; + return *storage; +} + +void sieve_ext_variables_runtime_set_storage( + const struct sieve_extension *var_ext, + const struct sieve_runtime_env *renv, const struct sieve_extension *ext, + struct sieve_variable_storage *storage) +{ + struct ext_variables_interpreter_context *ctx = + ext_variables_interpreter_context_get(var_ext, renv->interp); + + if (ctx == NULL || ext == NULL || storage == NULL) + return; + if (ext->id < 0) + return; + + array_idx_set(&ctx->ext_storages, (unsigned int) ext->id, &storage); +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.h new file mode 100644 index 0000000..401d943 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-common.h @@ -0,0 +1,102 @@ +#ifndef EXT_VARIABLES_COMMON_H +#define EXT_VARIABLES_COMMON_H + +#include "sieve-common.h" +#include "sieve-validator.h" + +#include "sieve-ext-variables.h" + +/* + * Extension + */ + +struct ext_variables_config { + /* Maximum number of variables (in a scope) */ + unsigned int max_scope_size; + /* Maximum size of variable value */ + size_t max_variable_size; +}; + +extern const struct sieve_extension_def variables_extension; + +bool ext_variables_load(const struct sieve_extension *ext, void **context); +void ext_variables_unload(const struct sieve_extension *ext); + +const struct ext_variables_config * +ext_variables_get_config(const struct sieve_extension *var_ext); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_set; +extern const struct sieve_command_def tst_string; + +/* + * Operands + */ + +enum ext_variables_operand { + EXT_VARIABLES_OPERAND_VARIABLE, + EXT_VARIABLES_OPERAND_MATCH_VALUE, + EXT_VARIABLES_OPERAND_NAMESPACE_VARIABLE, + EXT_VARIABLES_OPERAND_MODIFIER +}; + +/* + * Operations + */ + +extern const struct sieve_operation_def cmd_set_operation; +extern const struct sieve_operation_def tst_string_operation; + +enum ext_variables_opcode { + EXT_VARIABLES_OPERATION_SET, + EXT_VARIABLES_OPERATION_STRING +}; + +/* + * Validator context + */ + +struct ext_variables_validator_context { + bool active; + + struct sieve_validator_object_registry *modifiers; + struct sieve_validator_object_registry *namespaces; + + struct sieve_variable_scope *local_scope; +}; + +void ext_variables_validator_initialize(const struct sieve_extension *this_ext, + struct sieve_validator *validator); + +struct ext_variables_validator_context * +ext_variables_validator_context_get(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr); + +struct sieve_variable * +ext_variables_validator_get_variable(const struct sieve_extension *this_ext, + struct sieve_validator *validator, + const char *variable); +struct sieve_variable * +ext_variables_validator_declare_variable(const struct sieve_extension *this_ext, + struct sieve_validator *validator, + const char *variable); + +/* + * Code generation + */ + +bool ext_variables_generator_load(const struct sieve_extension *ext, + const struct sieve_codegen_env *cgenv); + +/* + * Interpreter context + */ + +bool ext_variables_interpreter_load(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.c new file mode 100644 index 0000000..26bd015 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.c @@ -0,0 +1,137 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-dump.h" +#include "sieve-binary.h" +#include "sieve-code.h" + +#include "ext-variables-common.h" +#include "ext-variables-dump.h" + +/* + * Code dumper extension + */ + +static void ext_variables_code_dumper_free + (struct sieve_code_dumper *dumper, void *context); + +static const struct sieve_code_dumper_extension +variables_dump_extension = { + &variables_extension, + ext_variables_code_dumper_free +}; + +/* + * Code dump context + */ + +struct ext_variables_dump_context { + struct sieve_variable_scope *local_scope; + ARRAY(struct sieve_variable_scope *) ext_scopes; +}; + +static void ext_variables_code_dumper_free +(struct sieve_code_dumper *dumper ATTR_UNUSED, void *context) +{ + struct ext_variables_dump_context *dctx = + (struct ext_variables_dump_context *) context; + + if ( dctx == NULL || dctx->local_scope == NULL ) + return; + + sieve_variable_scope_unref(&dctx->local_scope); +} + +static struct ext_variables_dump_context *ext_variables_dump_get_context +(const struct sieve_extension *this_ext, const struct sieve_dumptime_env *denv) +{ + struct sieve_code_dumper *dumper = denv->cdumper; + struct ext_variables_dump_context *dctx; + pool_t pool; + + i_assert( sieve_extension_is(this_ext, variables_extension) ); + dctx = sieve_dump_extension_get_context(dumper, this_ext); + + if ( dctx == NULL ) { + /* Create dumper context */ + pool = sieve_code_dumper_pool(dumper); + dctx = p_new(pool, struct ext_variables_dump_context, 1); + p_array_init(&dctx->ext_scopes, pool, + sieve_extensions_get_count(this_ext->svinst)); + + sieve_dump_extension_register + (dumper, this_ext, &variables_dump_extension, dctx); + } + + return dctx; +} + +bool ext_variables_code_dump +(const struct sieve_extension *ext, + const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct ext_variables_dump_context *dctx; + struct sieve_variable_scope *local_scope; + + local_scope = sieve_variable_scope_binary_dump + (ext->svinst, ext, NULL, denv, address); + + dctx = ext_variables_dump_get_context(ext, denv); + dctx->local_scope = local_scope; + + return TRUE; +} + +/* + * Scope registry + */ + +void sieve_ext_variables_dump_set_scope +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, struct sieve_variable_scope *scope) +{ + struct ext_variables_dump_context *dctx = + ext_variables_dump_get_context(var_ext, denv); + + if ( ext->id < 0 ) return; + + array_idx_set(&dctx->ext_scopes, (unsigned int) ext->id, &scope); +} + +/* + * Variable identifier dump + */ + +const char *ext_variables_dump_get_identifier +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, unsigned int index) +{ + struct ext_variables_dump_context *dctx = + ext_variables_dump_get_context(var_ext, denv); + struct sieve_variable_scope *scope; + struct sieve_variable *var; + + if ( ext == NULL ) + scope = dctx->local_scope; + else { + struct sieve_variable_scope *const *ext_scope; + + if ( ext->id < 0 || ext->id >= (int) array_count(&dctx->ext_scopes) ) + return NULL; + + ext_scope = array_idx(&dctx->ext_scopes, (unsigned int) ext->id); + scope = *ext_scope; + } + + if ( scope == NULL ) + return NULL; + + var = sieve_variable_scope_get_indexed(scope, index); + + return var->identifier; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.h new file mode 100644 index 0000000..da72a5d --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-dump.h @@ -0,0 +1,22 @@ +#ifndef EXT_VARIABLES_DUMP_H +#define EXT_VARIABLES_DUMP_H + +#include "sieve-common.h" + +/* + * Code dump context + */ + +bool ext_variables_code_dump + (const struct sieve_extension *ext, const struct sieve_dumptime_env *denv, + sieve_size_t *address); + +/* + * Variable identifier dump + */ + +const char *ext_variables_dump_get_identifier +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, unsigned int index); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-limits.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-limits.h new file mode 100644 index 0000000..61260c8 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-limits.h @@ -0,0 +1,35 @@ +#ifndef EXT_VARIABLES_LIMITS_H +#define EXT_VARIABLES_LIMITS_H + +#include "sieve-limits.h" + +/* From RFC 5229: + * + * 6. Implementation Limits + * + * An implementation of this document MUST support at least 128 distinct + * variables. The supported length of variable names MUST be at least + * 32 characters. Each variable MUST be able to hold at least 4000 + * characters. Attempts to set the variable to a value larger than what + * the implementation supports SHOULD be reported as an error at + * compile-time if possible. If the attempt is discovered during run- + * time, the value SHOULD be truncated, and it MUST NOT be treated as an + * error. + + * Match variables ${1} through ${9} MUST be supported. References to + * higher indices than those the implementation supports MUST be treated + * as a syntax error, which SHOULD be discovered at compile-time. + */ + +#define EXT_VARIABLES_DEFAULT_MAX_SCOPE_SIZE 255 +#define EXT_VARIABLES_DEFAULT_MAX_VARIABLE_SIZE (4 * 1024) + +#define EXT_VARIABLES_REQUIRED_MAX_SCOPE_SIZE 128 +#define EXT_VARIABLES_REQUIRED_MAX_VARIABLE_SIZE 4000 + +#define EXT_VARIABLES_MAX_VARIABLE_NAME_LEN 64 +#define EXT_VARIABLES_MAX_NAMESPACE_ELEMENTS 10 + +#define EXT_VARIABLES_MAX_MATCH_INDEX SIEVE_MAX_MATCH_VALUES + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.c new file mode 100644 index 0000000..dd21c88 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.c @@ -0,0 +1,578 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "unichar.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-runtime.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-modifiers.h" + +#include <ctype.h> + +/* + * Core modifiers + */ + +extern const struct sieve_variables_modifier_def lower_modifier; +extern const struct sieve_variables_modifier_def upper_modifier; +extern const struct sieve_variables_modifier_def lowerfirst_modifier; +extern const struct sieve_variables_modifier_def upperfirst_modifier; +extern const struct sieve_variables_modifier_def quotewildcard_modifier; +extern const struct sieve_variables_modifier_def length_modifier; + +enum ext_variables_modifier_code { + EXT_VARIABLES_MODIFIER_LOWER, + EXT_VARIABLES_MODIFIER_UPPER, + EXT_VARIABLES_MODIFIER_LOWERFIRST, + EXT_VARIABLES_MODIFIER_UPPERFIRST, + EXT_VARIABLES_MODIFIER_QUOTEWILDCARD, + EXT_VARIABLES_MODIFIER_LENGTH +}; + +const struct sieve_variables_modifier_def *ext_variables_core_modifiers[] = { + &lower_modifier, + &upper_modifier, + &lowerfirst_modifier, + &upperfirst_modifier, + "ewildcard_modifier, + &length_modifier +}; + +const unsigned int ext_variables_core_modifiers_count = + N_ELEMENTS(ext_variables_core_modifiers); + +#define ext_variables_modifier_name(modf) \ + (modf)->object->def->name +#define ext_variables_modifiers_equal(modf1, modf2) \ + ( (modf1)->def == (modf2)->def ) +#define ext_variables_modifiers_equal_precedence(modf1, modf2) \ + ( (modf1)->def->precedence == (modf2)->def->precendence ) + +/* + * Modifier registry + */ + +void sieve_variables_modifier_register +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_modifier_def *smodf_def) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + sieve_validator_object_registry_add(ctx->modifiers, ext, &smodf_def->obj_def); +} + +bool ext_variables_modifier_exists +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + return sieve_validator_object_registry_find(ctx->modifiers, identifier, NULL); +} + +const struct sieve_variables_modifier *ext_variables_modifier_create_instance +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + struct sieve_object object; + struct sieve_variables_modifier *modf; + pool_t pool; + + if ( !sieve_validator_object_registry_find + (ctx->modifiers, identifier, &object) ) + return NULL; + + pool = sieve_command_pool(cmd); + modf = p_new(pool, struct sieve_variables_modifier, 1); + modf->object = object; + modf->var_ext = var_ext; + modf->def = (const struct sieve_variables_modifier_def *) object.def; + + return modf; +} + +void ext_variables_register_core_modifiers +(const struct sieve_extension *ext, struct ext_variables_validator_context *ctx) +{ + unsigned int i; + + /* Register core modifiers*/ + for ( i = 0; i < ext_variables_core_modifiers_count; i++ ) { + sieve_validator_object_registry_add + (ctx->modifiers, ext, &(ext_variables_core_modifiers[i]->obj_def)); + } +} + +/* + * Core modifiers + */ + +/* Forward declarations */ + +static bool +mod_lower_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_upper_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_lowerfirst_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_upperfirst_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_length_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +static bool +mod_quotewildcard_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); + +/* Modifier objects */ + +const struct sieve_variables_modifier_def lower_modifier = { + SIEVE_OBJECT("lower", &modifier_operand, EXT_VARIABLES_MODIFIER_LOWER), + 40, + mod_lower_modify +}; + +const struct sieve_variables_modifier_def upper_modifier = { + SIEVE_OBJECT("upper", &modifier_operand, EXT_VARIABLES_MODIFIER_UPPER), + 40, + mod_upper_modify +}; + +const struct sieve_variables_modifier_def lowerfirst_modifier = { + SIEVE_OBJECT + ("lowerfirst", &modifier_operand, EXT_VARIABLES_MODIFIER_LOWERFIRST), + 30, + mod_lowerfirst_modify +}; + +const struct sieve_variables_modifier_def upperfirst_modifier = { + SIEVE_OBJECT + ("upperfirst", &modifier_operand, EXT_VARIABLES_MODIFIER_UPPERFIRST), + 30, + mod_upperfirst_modify +}; + +const struct sieve_variables_modifier_def quotewildcard_modifier = { + SIEVE_OBJECT + ("quotewildcard", &modifier_operand, EXT_VARIABLES_MODIFIER_QUOTEWILDCARD), + 20, + mod_quotewildcard_modify +}; + +const struct sieve_variables_modifier_def length_modifier = { + SIEVE_OBJECT("length", &modifier_operand, EXT_VARIABLES_MODIFIER_LENGTH), + 10, + mod_length_modify +}; + +/* Modifier implementations */ + +static bool +mod_upperfirst_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + content[0] = i_toupper(content[0]); + + return TRUE; +} + +static bool +mod_lowerfirst_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + content[0] = i_tolower(content[0]); + + return TRUE; +} + +static bool +mod_upper_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + (void)str_ucase(content); + + return TRUE; +} + +static bool +mod_lower_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + char *content; + + if ( str_len(in) == 0 ) { + *result = in; + return TRUE; + } + + *result = t_str_new(str_len(in)); + str_append_str(*result, in); + + content = str_c_modifiable(*result); + (void)str_lcase(content); + + return TRUE; +} + +static bool +mod_length_modify(const struct sieve_variables_modifier *modf ATTR_UNUSED, + string_t *in, string_t **result) +{ + *result = t_str_new(64); + str_printfa(*result, "%llu", (unsigned long long) + uni_utf8_strlen_n(str_data(in), str_len(in))); + return TRUE; +} + +static bool +mod_quotewildcard_modify(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result) +{ + size_t max_var_size = + sieve_variables_get_max_variable_size(modf->var_ext); + const unsigned char *p, *poff, *pend; + size_t new_size; + + if ( str_len(in) == 0 ) { + /* empty string */ + *result = in; + return TRUE; + } + + /* allocate new string */ + new_size = str_len(in) + 16; + if (new_size > max_var_size) + new_size = max_var_size; + *result = t_str_new(new_size + 1); + + /* escape string */ + p = str_data(in); + pend = p + str_len(in); + poff = p; + while (p < pend) { + unsigned int n = uni_utf8_char_bytes((char)*p); + + if (n == 1 && (*p == '*' || *p == '?' || *p == '\\')) { + str_append_data(*result, poff, p - poff); + poff = p; + + if (str_len(*result) + 2 > max_var_size) + break; + + str_append_c(*result, '\\'); + } else if ((str_len(*result) + (p - poff) + n) > max_var_size) { + break; + } + if (p + n > pend) { + p = pend; + break; + } + p += n; + } + + str_append_data(*result, poff, p - poff); + + return TRUE; +} + +/* + * Modifier argument + */ + +/* [MODIFIER]: + * ":lower" / ":upper" / ":lowerfirst" / ":upperfirst" / + * ":quotewildcard" / ":length" + */ + +/* Forward declarations */ + +static bool tag_modifier_is_instance_of + (struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **context); + +/* Modifier tag object */ + +static const struct sieve_argument_def modifier_tag = { + .identifier = "MODIFIER", + .flags = SIEVE_ARGUMENT_FLAG_MULTIPLE, + .is_instance_of = tag_modifier_is_instance_of +}; + +/* Modifier tag implementation */ + +static bool tag_modifier_is_instance_of +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const struct sieve_extension *ext, const char *identifier, void **data) +{ + const struct sieve_variables_modifier *modf; + + if ( data == NULL ) { + return ext_variables_modifier_exists(ext, valdtr, identifier); + } + + if ( (modf=ext_variables_modifier_create_instance + (ext, valdtr, cmd, identifier)) == NULL ) + return FALSE; + + *data = (void *) modf; + + return TRUE; +} + +/* Registration */ + +void sieve_variables_modifiers_link_tag +(struct sieve_validator *valdtr, const struct sieve_extension *var_ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, var_ext, &modifier_tag, 0); +} + +/* Validation */ + +bool sieve_variables_modifiers_validate +(struct sieve_validator *valdtr, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variables_modifier) *modifiers) +{ + struct sieve_ast_argument *arg; + + arg = sieve_command_first_argument(cmd); + while ( arg != NULL && arg != cmd->first_positional ) { + const struct sieve_variables_modifier *modfs; + const struct sieve_variables_modifier *modf; + unsigned int i, modf_count; + bool inserted; + + if ( !sieve_argument_is(arg, modifier_tag) ) { + arg = sieve_ast_argument_next(arg); + continue; + } + modf = (const struct sieve_variables_modifier *) + arg->argument->data; + + inserted = FALSE; + modfs = array_get(modifiers, &modf_count); + for ( i = 0; i < modf_count && !inserted; i++ ) { + + if ( modfs[i].def->precedence == modf->def->precedence ) { + sieve_argument_validate_error(valdtr, arg, + "modifiers :%s and :%s specified for the set command conflict " + "having equal precedence", + modfs[i].def->obj_def.identifier, modf->def->obj_def.identifier); + return FALSE; + } + + if ( modfs[i].def->precedence < modf->def->precedence ) { + array_insert(modifiers, i, modf, 1); + inserted = TRUE; + } + } + + if ( !inserted ) + array_append(modifiers, modf, 1); + + /* Added to modifier list; + self-destruct to prevent implicit code generation */ + arg = sieve_ast_arguments_detach(arg, 1); + } + return TRUE; +} + +bool sieve_variables_modifiers_generate +(const struct sieve_codegen_env *cgenv, + ARRAY_TYPE(sieve_variables_modifier) *modifiers) +{ + struct sieve_binary_block *sblock = cgenv->sblock; + const struct sieve_variables_modifier *modfs; + unsigned int i, modf_count; + + sieve_binary_emit_byte(sblock, array_count(modifiers)); + + modfs = array_get(modifiers, &modf_count); + for ( i = 0; i < modf_count; i++ ) { + ext_variables_opr_modifier_emit(sblock, + modfs[i].object.ext, modfs[i].def); + } + return TRUE; +} + +/* + * Modifier coding + */ + +const struct sieve_operand_class sieve_variables_modifier_operand_class = + { "modifier" }; + +static const struct sieve_extension_objects core_modifiers = + SIEVE_VARIABLES_DEFINE_MODIFIERS(ext_variables_core_modifiers); + +const struct sieve_operand_def modifier_operand = { + .name = "modifier", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_MODIFIER, + .class = &sieve_variables_modifier_operand_class, + .interface = &core_modifiers +}; + +bool sieve_variables_modifiers_code_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + unsigned int mdfs, i; + + /* Read the number of applied modifiers we need to read */ + if ( !sieve_binary_read_byte(denv->sblock, address, &mdfs) ) + return FALSE; + + /* Print all modifiers (sorted during code generation already) */ + for ( i = 0; i < mdfs; i++ ) { + if ( !ext_variables_opr_modifier_dump(denv, address) ) + return FALSE; + } + return TRUE; +} + +int sieve_variables_modifiers_code_read( + const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, sieve_size_t *address, + ARRAY_TYPE(sieve_variables_modifier) *modifiers) +{ + unsigned int lprec, mdfs, i; + + if ( !sieve_binary_read_byte(renv->sblock, address, &mdfs) ) { + sieve_runtime_trace_error(renv, "invalid modifier count"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + t_array_init(modifiers, mdfs); + + lprec = (unsigned int)-1; + for ( i = 0; i < mdfs; i++ ) { + struct sieve_variables_modifier modf; + + if ( !ext_variables_opr_modifier_read(renv, var_ext, + address, &modf) ) + return SIEVE_EXEC_BIN_CORRUPT; + if ( modf.def != NULL ) { + if ( modf.def->precedence >= lprec ) { + sieve_runtime_trace_error(renv, + "unsorted modifier precedence"); + return SIEVE_EXEC_BIN_CORRUPT; + } + lprec = modf.def->precedence; + } + + array_append(modifiers, &modf, 1); + } + + return SIEVE_EXEC_OK; +} + +/* + * Modifier application + */ + +int sieve_variables_modifiers_apply +(const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, + ARRAY_TYPE(sieve_variables_modifier) *modifiers, + string_t **value) +{ + const struct ext_variables_config *config = + ext_variables_get_config(var_ext); + const struct sieve_variables_modifier *modfs; + unsigned int i, modf_count; + + /* Hold value within limits */ + if ( str_len(*value) > config->max_variable_size ) { + /* assume variable originates from code, so copy it first */ + string_t *new_value = t_str_new(config->max_variable_size+3); + str_append_str(new_value, *value); + *value = new_value; + str_truncate_utf8(*value, config->max_variable_size); + } + + if ( !array_is_created(modifiers) ) + return SIEVE_EXEC_OK; + + modfs = array_get(modifiers, &modf_count); + if ( modf_count == 0 ) + return SIEVE_EXEC_OK; + + for ( i = 0; i < modf_count; i++ ) { + string_t *new_value; + const struct sieve_variables_modifier *modf = &modfs[i]; + + if ( modf->def != NULL && modf->def->modify != NULL ) { + if ( !modf->def->modify(modf, *value, &new_value) ) + return SIEVE_EXEC_FAILURE; + + *value = new_value; + if ( *value == NULL ) + return SIEVE_EXEC_FAILURE; + + sieve_runtime_trace_here + (renv, SIEVE_TRLVL_COMMANDS, + "modify :%s \"%s\" => \"%s\"", + sieve_variables_modifier_name(modf), + str_sanitize(str_c(*value), 256), + str_sanitize(str_c(new_value), 256)); + + /* Hold value within limits */ + if ( str_len(*value) > config->max_variable_size ) + str_truncate_utf8(*value, config->max_variable_size); + } + } + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.h new file mode 100644 index 0000000..50b4256 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-modifiers.h @@ -0,0 +1,66 @@ +#ifndef EXT_VARIABLES_MODIFIERS_H +#define EXT_VARIABLES_MODIFIERS_H + +#include "sieve-common.h" +#include "sieve-runtime-trace.h" + +#include "ext-variables-common.h" + +#define ext_variables_namespace_name(nspc) \ + (nspc)->object->def->name +#define ext_variables_namespaces_equal(nspc1, nspc2) \ + ( (nspc1)->def == (nspc2)->def )) + +/* + * Modifier registry + */ + +bool ext_variables_modifier_exists + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier); +const struct sieve_variables_modifier *ext_variables_modifier_create_instance + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier); + +void ext_variables_register_core_modifiers + (const struct sieve_extension *var_ext, + struct ext_variables_validator_context *ctx); + +/* + * Modifier operand + */ + +extern const struct sieve_operand_def modifier_operand; + +static inline void ext_variables_opr_modifier_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + const struct sieve_variables_modifier_def *modf_def) +{ + sieve_opr_object_emit(sblock, ext, &modf_def->obj_def); +} + +static inline bool +ext_variables_opr_modifier_read(const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, + sieve_size_t *address, + struct sieve_variables_modifier *modf) +{ + if ( !sieve_opr_object_read + (renv, &sieve_variables_modifier_operand_class, address, &modf->object) ) { + sieve_runtime_trace_error(renv, "invalid modifier operand"); + return FALSE; + } + + modf->def = (const struct sieve_variables_modifier_def *) modf->object.def; + modf->var_ext = var_ext; + return TRUE; +} + +static inline bool ext_variables_opr_modifier_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_variables_modifier_operand_class, address, NULL); +} + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.c new file mode 100644 index 0000000..fac0b71 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" + +#include <ctype.h> + +bool sieve_variable_identifier_is_valid(const char *identifier) +{ + const char *p = identifier; + size_t plen = strlen(identifier); + const char *pend; + + if ( plen == 0 || plen >= EXT_VARIABLES_MAX_VARIABLE_NAME_LEN ) + return FALSE; + + pend = PTR_OFFSET(identifier, plen); + + if ( *p == '_' || i_isalpha(*p) ) { + p++; + + while ( p < pend && (*p == '_' || i_isalnum(*p)) ) { + p++; + } + } + + return ( p == pend ); +} + +int ext_variable_name_parse +(ARRAY_TYPE(sieve_variable_name) *vname, const char **str, const char *strend) +{ + const char *p = *str; + + array_clear(vname); + + while ( p < strend ) { + struct sieve_variable_name *cur_element; + string_t *cur_ident; + + /* Acquire current position in the array */ + + if ( array_count(vname) >= EXT_VARIABLES_MAX_NAMESPACE_ELEMENTS ) + return -1; + + cur_element = array_append_space(vname); + cur_ident = cur_element->identifier = t_str_new(32); + + /* Parse element */ + + /* Identifier */ + if ( *p == '_' || i_isalpha(*p) ) { + cur_element->num_variable = -1; + str_truncate(cur_ident, 0); + str_append_c(cur_ident, *p); + p++; + + while ( p < strend && (*p == '_' || i_isalnum(*p)) ) { + if ( str_len(cur_ident) >= EXT_VARIABLES_MAX_VARIABLE_NAME_LEN ) + return -1; + str_append_c(cur_ident, *p); + p++; + } + + /* Num-variable */ + } else if ( i_isdigit(*p) ) { + cur_element->num_variable = *p - '0'; + p++; + + while ( p < strend && i_isdigit(*p) ) { + cur_element->num_variable = cur_element->num_variable*10 + (*p - '0'); + p++; + } + + /* If a num-variable is first, no more elements can follow because no + * namespace is specified. + */ + if ( array_count(vname) == 1 ) { + *str = p; + return 1; + } + } else { + *str = p; + return -1; + } + + /* Check whether next name element is present */ + if ( p < strend && *p == '.' ) { + p++; + + /* It may not be empty */ + if ( p >= strend ) + return -1; + } else + break; + } + + *str = p; + return array_count(vname); +} + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.h new file mode 100644 index 0000000..289a978 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-name.h @@ -0,0 +1,43 @@ +#ifndef EXT_VARIABLES_NAME_H +#define EXT_VARIABLES_NAME_H + +/* Variable Substitution + * --------------------- + * + * The variable strings are preprocessed into an AST list consisting of variable + * substitutions and constant parts of the string. The variables to which + * the substitutions link are looked up and their index in their scope storage + * is what is added to the list and eventually emitted as byte code. So, in + * bytecode a variable string will look as a series of substrings interrupted by + * integer operands that refer to variables. During execution, the strings and + * the looked-up variables are concatenated to obtain the desired result. The + * the variable references are simple indexes into an array of variables, so + * looking these up during execution is a trivial process. + * + * However (RFC 5229): + * Tests or actions in future extensions may need to access the + * unexpanded version of the string argument and, e.g., do the expansion + * after setting variables in its namespace. The design of the + * implementation should allow this. + * + * Various options exist to provide this feature. If the extension is entirely + * namespace-based there is actually not very much of a problem. The variable + * list can easily be extended with new argument-types that refer to a variable + * identifier instead of an index in the variable's storage. + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-common.h" + +#include "ext-variables-common.h" + +/* + * Variable name parsing + */ + +int ext_variable_name_parse + (ARRAY_TYPE(sieve_variable_name) *vname, const char **str, const char *strend); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.c new file mode 100644 index 0000000..4df62e2 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.c @@ -0,0 +1,236 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "ext-variables-common.h" +#include "ext-variables-namespaces.h" + +#include <ctype.h> + +/* + * Namespace registry + */ + +void sieve_variables_namespace_register +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + sieve_validator_object_registry_add(ctx->namespaces, ext, &nspc_def->obj_def); +} + +bool ext_variables_namespace_exists +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + + return sieve_validator_object_registry_find + (ctx->namespaces, identifier, NULL); +} + +const struct sieve_variables_namespace *ext_variables_namespace_create_instance +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier) +{ + struct ext_variables_validator_context *ctx = + ext_variables_validator_context_get(var_ext, valdtr); + struct sieve_object object; + struct sieve_variables_namespace *nspc; + pool_t pool; + + if ( !sieve_validator_object_registry_find + (ctx->namespaces, identifier, &object) ) + return NULL; + + pool = sieve_command_pool(cmd); + nspc = p_new(pool, struct sieve_variables_namespace, 1); + nspc->object = object; + nspc->def = (const struct sieve_variables_namespace_def *) object.def; + + return nspc; +} + +/* + * Namespace variable argument + */ + +struct arg_namespace_variable { + const struct sieve_variables_namespace *namespace; + + void *data; +}; + +static bool arg_namespace_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *context ATTR_UNUSED); + +const struct sieve_argument_def namespace_argument = { + .identifier = "@namespace", + .generate = arg_namespace_generate +}; + +bool ext_variables_namespace_argument_activate +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, bool assignment) +{ + pool_t pool = sieve_command_pool(cmd); + struct sieve_ast *ast = arg->ast; + const struct sieve_variables_namespace *nspc; + struct arg_namespace_variable *var; + const struct sieve_variable_name *name_element = array_idx(var_name, 0); + void *var_data = NULL; + + nspc = ext_variables_namespace_create_instance + (this_ext, valdtr, cmd, str_c(name_element->identifier)); + if ( nspc == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "referring to variable in unknown namespace '%s'", + str_c(name_element->identifier)); + return FALSE; + } + + if ( nspc->def != NULL && nspc->def->validate != NULL && + !nspc->def->validate + (valdtr, nspc, arg, cmd, var_name, &var_data, assignment) ) { + return FALSE; + } + + var = p_new(pool, struct arg_namespace_variable, 1); + var->namespace = nspc; + var->data = var_data; + + arg->argument = sieve_argument_create(ast, &namespace_argument, this_ext, 0); + arg->argument->data = (void *) var; + + return TRUE; +} + +struct sieve_ast_argument *ext_variables_namespace_argument_create +(const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *parent_arg, + struct sieve_command *cmd, ARRAY_TYPE(sieve_variable_name) *var_name) +{ + struct sieve_ast *ast = parent_arg->ast; + struct sieve_ast_argument *new_arg; + + new_arg = sieve_ast_argument_create(ast, sieve_ast_argument_line(parent_arg)); + new_arg->type = SAAT_STRING; + + if ( !ext_variables_namespace_argument_activate + (this_ext, valdtr, new_arg, cmd, var_name, FALSE) ) + return NULL; + + return new_arg; +} + +static bool arg_namespace_generate +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + struct sieve_argument *argument = arg->argument; + struct arg_namespace_variable *var = + (struct arg_namespace_variable *) argument->data; + const struct sieve_variables_namespace *nspc = var->namespace; + + if ( nspc->def != NULL && nspc->def->generate != NULL ) + return nspc->def->generate(cgenv, nspc, arg, cmd, var->data); + + return TRUE; +} + +/* + * Namespace variable operands + */ + +const struct sieve_operand_class sieve_variables_namespace_operand_class = + { "variable-namespace" }; + +static bool opr_namespace_variable_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_namespace_variable_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +static const struct sieve_opr_string_interface namespace_variable_interface = { + opr_namespace_variable_dump, + opr_namespace_variable_read +}; + +const struct sieve_operand_def namespace_variable_operand = { + .name = "namespace", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_NAMESPACE_VARIABLE, + .class = &string_class, + .interface = &namespace_variable_interface +}; + +void sieve_variables_opr_namespace_variable_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def) +{ + i_assert( sieve_extension_is(var_ext, variables_extension) ); + sieve_operand_emit(sblock, var_ext, &namespace_variable_operand); + sieve_opr_object_emit(sblock, ext, &nspc_def->obj_def); +} + +static bool opr_namespace_variable_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + struct sieve_variables_namespace nspc; + struct sieve_operand nsoprnd; + + if ( !sieve_operand_read(denv->sblock, address, NULL, &nsoprnd) ) { + return FALSE; + } + + if ( !sieve_opr_object_read_data + (denv->sblock, &nsoprnd, &sieve_variables_namespace_operand_class, address, + &nspc.object) ) { + return FALSE; + } + + nspc.def = (const struct sieve_variables_namespace_def *) nspc.object.def; + + if ( nspc.def == NULL || nspc.def->dump_variable == NULL ) + return FALSE; + + return nspc.def->dump_variable(denv, &nspc, oprnd, address); +} + +static int opr_namespace_variable_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + struct sieve_variables_namespace nspc; + + if ( !sieve_opr_object_read + (renv, &sieve_variables_namespace_operand_class, address, &nspc.object) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable namespace operand corrupt: failed to read"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + nspc.def = (const struct sieve_variables_namespace_def *) nspc.object.def; + + if ( nspc.def == NULL || nspc.def->read_variable == NULL ) + return SIEVE_EXEC_FAILURE; + + return nspc.def->read_variable(renv, &nspc, oprnd, address, str_r); +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.h new file mode 100644 index 0000000..a687582 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-namespaces.h @@ -0,0 +1,43 @@ +#ifndef EXT_VARIABLES_NAMESPACES_H +#define EXT_VARIABLES_NAMESPACES_H + +#include "sieve-common.h" + +#include "ext-variables-common.h" +#include "sieve-ext-variables.h" + +/* + * Namespace registry + */ + +bool ext_variables_namespace_exists + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const char *identifier); +const struct sieve_variables_namespace *ext_variables_namespace_create_instance + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + struct sieve_command *cmd, const char *identifier); + +void ext_variables_register_core_namespaces + (const struct sieve_extension *var_ext, + struct ext_variables_validator_context *ctx); + +/* + * Namespace argument + */ + +struct sieve_ast_argument *ext_variables_namespace_argument_create + (const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_ast_argument *parent_arg, + struct sieve_command *cmd, ARRAY_TYPE(sieve_variable_name) *var_name); +bool ext_variables_namespace_argument_activate + (const struct sieve_extension *this_ext, struct sieve_validator *valdtr, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, bool assignment); + +/* + * Namespace operand + */ + +extern const struct sieve_operand_def namespace_variable_operand; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.c new file mode 100644 index 0000000..359f3bf --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.c @@ -0,0 +1,279 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "hash.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-match-types.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-dump.h" +#include "sieve-interpreter.h" + +#include "ext-variables-common.h" +#include "ext-variables-limits.h" +#include "ext-variables-name.h" +#include "ext-variables-dump.h" +#include "ext-variables-operands.h" + +/* + * Variable operand + */ + +static bool opr_variable_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_variable_read_value + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +const struct sieve_opr_string_interface variable_interface = { + opr_variable_dump, + opr_variable_read_value +}; + +const struct sieve_operand_def variable_operand = { + .name = "variable", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_VARIABLE, + .class = &string_class, + .interface = &variable_interface +}; + +void sieve_variables_opr_variable_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + struct sieve_variable *var) +{ + i_assert( sieve_extension_is(var_ext, variables_extension) ); + + if ( var->ext == NULL ) { + /* Default variable storage */ + (void) sieve_operand_emit(sblock, var_ext, &variable_operand); + (void) sieve_binary_emit_byte(sblock, 0); /* Default */ + (void) sieve_binary_emit_unsigned(sblock, var->index); + return; + } + + (void) sieve_operand_emit(sblock, var_ext, &variable_operand); + (void) sieve_binary_emit_extension(sblock, var->ext, 1); /* Extension */ + (void) sieve_binary_emit_unsigned(sblock, var->index); +} + +static bool opr_variable_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = oprnd->ext; + unsigned int index = 0; + const struct sieve_extension *ext; + unsigned int code = 1; /* Initially set to offset value */ + const char *identifier; + + if ( !sieve_binary_read_extension(denv->sblock, address, &code, &ext) ) + return FALSE; + + if ( !sieve_binary_read_unsigned(denv->sblock, address, &index) ) + return FALSE; + + identifier = ext_variables_dump_get_identifier(this_ext, denv, ext, index); + identifier = identifier == NULL ? "??" : identifier; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: VAR[%s] ${%s}", + oprnd->field_name, sieve_ext_variables_get_varid(ext, index), identifier); + else + sieve_code_dumpf(denv, "VAR[%s] ${%s}", + sieve_ext_variables_get_varid(ext, index), identifier); + + return TRUE; +} + +static int opr_variable_read_value +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + const struct sieve_extension *this_ext = oprnd->ext; + const struct sieve_extension *ext; + unsigned int code = 1; /* Initially set to offset value */ + struct sieve_variable_storage *storage; + unsigned int index = 0; + + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid extension byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + storage = sieve_ext_variables_runtime_get_storage + (this_ext, renv, ext); + if ( storage == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: extension has no storage"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + /* Parameter str can be NULL if we are requested to only skip and not + * actually read the argument. + */ + if ( str_r != NULL ) { + if ( !sieve_variable_get(storage, index, str_r) ) + return SIEVE_EXEC_FAILURE; + + if ( *str_r == NULL ) *str_r = t_str_new(0); + } + + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid variable index"); + return SIEVE_EXEC_BIN_CORRUPT; +} + +int sieve_variable_operand_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, + struct sieve_variable_storage **storage_r, unsigned int *var_index_r) +{ + const struct sieve_extension *ext; + unsigned int code = 1; /* Initially set to offset value */ + unsigned int idx = 0; + + oprnd->field_name = field_name; + + if ( !sieve_operand_is_variable(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "expected variable operand but found %s", sieve_operand_name(oprnd)); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid extension byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + *storage_r = sieve_ext_variables_runtime_get_storage + (oprnd->ext, renv, ext); + if ( *storage_r == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: extension has no storage"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( !sieve_binary_read_unsigned(renv->sblock, address, &idx) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid variable index"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + *var_index_r = idx; + return SIEVE_EXEC_OK; +} + +int sieve_variable_operand_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_variable_storage **storage_r, + unsigned int *var_index_r) +{ + struct sieve_operand operand; + int ret; + + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0) + return ret; + + return sieve_variable_operand_read_data + (renv, &operand, address, field_name, storage_r, var_index_r); +} + +/* + * Match value operand + */ + +static bool opr_match_value_dump + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_match_value_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +const struct sieve_opr_string_interface match_value_interface = { + opr_match_value_dump, + opr_match_value_read +}; + +const struct sieve_operand_def match_value_operand = { + .name = "match-value", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERAND_MATCH_VALUE, + .class = &string_class, + .interface = &match_value_interface +}; + +void sieve_variables_opr_match_value_emit +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + unsigned int index) +{ + i_assert( sieve_extension_is(var_ext, variables_extension) ); + (void) sieve_operand_emit(sblock, var_ext, &match_value_operand); + (void) sieve_binary_emit_unsigned(sblock, index); +} + +static bool opr_match_value_dump +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) +{ + unsigned int index = 0; + + if (sieve_binary_read_unsigned(denv->sblock, address, &index) ) { + if ( oprnd->field_name != NULL ) + sieve_code_dumpf + (denv, "%s: MATCHVAL %lu", oprnd->field_name, (unsigned long) index); + else + sieve_code_dumpf(denv, "MATCHVAL %lu", (unsigned long) index); + + return TRUE; + } + + return FALSE; +} + +static int opr_match_value_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + const struct sieve_extension *this_ext = oprnd->ext; + const struct ext_variables_config *config = + ext_variables_get_config(this_ext); + unsigned int index = 0; + + if ( sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + /* Parameter str can be NULL if we are requested to only skip and not + * actually read the argument. + */ + if ( str_r != NULL ) { + sieve_match_values_get(renv, index, str_r); + + if ( *str_r == NULL ) + *str_r = t_str_new(0); + else if ( str_len(*str_r) > config->max_variable_size ) + str_truncate_utf8(*str_r, config->max_variable_size); + } + + return SIEVE_EXEC_OK; + } + + sieve_runtime_trace_operand_error(renv, oprnd, + "match value operand corrupt: invalid index data"); + return SIEVE_EXEC_BIN_CORRUPT; +} diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.h b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.h new file mode 100644 index 0000000..64a7781 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables-operands.h @@ -0,0 +1,37 @@ +#ifndef EXT_VARIABLES_OPERANDS_H +#define EXT_VARIABLES_OPERANDS_H + +#include "lib.h" +#include "hash.h" +#include "str.h" +#include "array.h" + +#include "sieve-common.h" +#include "ext-variables-common.h" + +/* + * Variable operand + */ + +extern const struct sieve_operand_def variable_operand; + +bool ext_variables_opr_variable_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + struct sieve_variable_storage **storage, unsigned int *var_index); + +/* + * Match value operand + */ + +extern const struct sieve_operand_def match_value_operand; + +/* + * Variable string operand + */ + +void ext_variables_opr_variable_string_emit + (struct sieve_binary *sbin, unsigned int elements); + + +#endif + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/ext-variables.c b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables.c new file mode 100644 index 0000000..6bdef58 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/ext-variables.c @@ -0,0 +1,84 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension variables + * ------------------- + * + * Authors: Stephan Bosch + * Specification: RFC 5229 + * Implementation: full + * Status: testing + * + */ + +#include "lib.h" +#include "str.h" +#include "unichar.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" + +#include "sieve-validator.h" + +#include "ext-variables-common.h" +#include "ext-variables-arguments.h" +#include "ext-variables-operands.h" +#include "ext-variables-namespaces.h" +#include "ext-variables-modifiers.h" +#include "ext-variables-dump.h" + +/* + * Operations + */ + +const struct sieve_operation_def *ext_variables_operations[] = { + &cmd_set_operation, + &tst_string_operation +}; + +/* + * Operands + */ + +const struct sieve_operand_def *ext_variables_operands[] = { + &variable_operand, + &match_value_operand, + &namespace_variable_operand, + &modifier_operand +}; + +/* + * Extension + */ + +static bool ext_variables_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); + +const struct sieve_extension_def variables_extension = { + .name = "variables", + .load = ext_variables_load, + .unload = ext_variables_unload, + .validator_load = ext_variables_validator_load, + .generator_load = ext_variables_generator_load, + .interpreter_load = ext_variables_interpreter_load, + .code_dump = ext_variables_code_dump, + SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations), + SIEVE_EXT_DEFINE_OPERANDS(ext_variables_operands) +}; + +static bool ext_variables_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + sieve_validator_argument_override + (validator, SAT_VAR_STRING, ext, &variable_string_argument); + + sieve_validator_register_command(validator, ext, &cmd_set); + sieve_validator_register_command(validator, ext, &tst_string); + + ext_variables_validator_initialize(ext, validator); + + return TRUE; +} + diff --git a/pigeonhole/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/pigeonhole/src/lib-sieve/plugins/variables/sieve-ext-variables.h new file mode 100644 index 0000000..ce0d0bc --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -0,0 +1,364 @@ +#ifndef SIEVE_EXT_VARIABLES_H +#define SIEVE_EXT_VARIABLES_H + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" +#include "sieve-objects.h" +#include "sieve-code.h" + +/* Public interface for other extensions to use + */ + +/* + * Limits + */ + +unsigned int +sieve_variables_get_max_scope_size(const struct sieve_extension *var_ext); +size_t +sieve_variables_get_max_variable_size(const struct sieve_extension *var_ext); + +/* + * Variable extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def variables_extension; + +static inline const struct sieve_extension *sieve_ext_variables_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_register(svinst, &variables_extension, FALSE); +} + +/* + * Variable name + */ + +struct sieve_variable_name { + string_t *identifier; + int num_variable; +}; + +ARRAY_DEFINE_TYPE(sieve_variable_name, struct sieve_variable_name); + +bool sieve_variable_identifier_is_valid(const char *identifier); + +/* + * Variable scope + */ + +struct sieve_variable { + const char *identifier; + unsigned int index; + + const struct sieve_extension *ext; + void *context; +}; + +struct sieve_variable_scope; + +struct sieve_variable_scope *sieve_variable_scope_create + (struct sieve_instance *svinst, const struct sieve_extension *var_ext, + const struct sieve_extension *ext); +void sieve_variable_scope_ref + (struct sieve_variable_scope *scope); +void sieve_variable_scope_unref + (struct sieve_variable_scope **scope); +pool_t sieve_variable_scope_pool + (struct sieve_variable_scope *scope); + +struct sieve_variable *sieve_variable_scope_declare + (struct sieve_variable_scope *scope, const char *identifier); +struct sieve_variable *sieve_variable_scope_import + (struct sieve_variable_scope *scope, struct sieve_variable *var); +struct sieve_variable *sieve_variable_scope_get_variable + (struct sieve_variable_scope *scope, const char *identifier); +struct sieve_variable *sieve_variable_scope_get_indexed + (struct sieve_variable_scope *scope, unsigned int index); + +/* Binary */ + +struct sieve_variable_scope_binary *sieve_variable_scope_binary_create + (struct sieve_variable_scope *scope); + +void sieve_variable_scope_binary_ref + (struct sieve_variable_scope_binary *scpbin); +void sieve_variable_scope_binary_unref + (struct sieve_variable_scope_binary **scpbin); + +struct sieve_variable_scope *sieve_variable_scope_binary_dump + (struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_dumptime_env *denv, sieve_size_t *address); +struct sieve_variable_scope_binary *sieve_variable_scope_binary_read + (struct sieve_instance *svinst, + const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + struct sieve_binary_block *sblock, sieve_size_t *address); + +struct sieve_variable_scope *sieve_variable_scope_binary_get + (struct sieve_variable_scope_binary *scpbin); +unsigned int sieve_variable_scope_binary_get_size + (struct sieve_variable_scope_binary *scpbin); + +/* + * Variable namespaces + */ + +struct sieve_variables_namespace; + +struct sieve_variables_namespace_def { + struct sieve_object_def obj_def; + + bool (*validate) + (struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); + bool (*generate) + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + void *var_data); + + bool (*dump_variable) + (const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); + int (*read_variable) + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str); +}; + +#define SIEVE_VARIABLES_DEFINE_NAMESPACE(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_VARIABLES_DEFINE_NAMESPACES(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +struct sieve_variables_namespace { + struct sieve_object object; + + const struct sieve_variables_namespace_def *def; +}; + +void sieve_variables_namespace_register +(const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def); + +extern const struct sieve_operand_class sieve_variables_namespace_operand_class; + +void sieve_variables_opr_namespace_variable_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + const struct sieve_extension *ext, + const struct sieve_variables_namespace_def *nspc_def); + +/* Iteration over all declared variables */ + +struct sieve_variable_scope_iter; + +struct sieve_variable_scope_iter *sieve_variable_scope_iterate_init + (struct sieve_variable_scope *scope); +bool sieve_variable_scope_iterate + (struct sieve_variable_scope_iter *iter, struct sieve_variable **var_r); +void sieve_variable_scope_iterate_deinit + (struct sieve_variable_scope_iter **iter); + +/* Statistics */ + +unsigned int sieve_variable_scope_declarations + (struct sieve_variable_scope *scope); +unsigned int sieve_variable_scope_size + (struct sieve_variable_scope *scope); + +/* Get all native variables */ + +struct sieve_variable * const *sieve_variable_scope_get_variables + (struct sieve_variable_scope *scope, unsigned int *size_r); + +/* + * Variable storage + */ + +struct sieve_variable_storage; + +struct sieve_variable_storage *sieve_variable_storage_create + (const struct sieve_extension *var_ext, pool_t pool, + struct sieve_variable_scope_binary *scpbin); +bool sieve_variable_get + (struct sieve_variable_storage *storage, unsigned int index, + string_t **value); +bool sieve_variable_get_modifiable + (struct sieve_variable_storage *storage, unsigned int index, + string_t **value); +bool sieve_variable_assign + (struct sieve_variable_storage *storage, unsigned int index, + const string_t *value); +bool sieve_variable_assign_cstr + (struct sieve_variable_storage *storage, unsigned int index, + const char *value); +bool sieve_variable_get_identifier + (struct sieve_variable_storage *storage, unsigned int index, + const char **identifier); +const char *sieve_variable_get_varid + (struct sieve_variable_storage *storage, unsigned int index); + +/* + * Variables access + */ + +bool sieve_ext_variables_is_active + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr); + +struct sieve_variable_scope *sieve_ext_variables_get_local_scope + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr); + +/* Runtime */ + +static inline const char *sieve_ext_variables_get_varid +(const struct sieve_extension *ext, unsigned int index) +{ + if ( ext == NULL ) + return t_strdup_printf("%ld", (long) index); + + return t_strdup_printf("%s:%ld", sieve_extension_name(ext), (long) index); +} + +struct sieve_variable_storage *sieve_ext_variables_runtime_get_storage + (const struct sieve_extension *var_ext, const struct sieve_runtime_env *renv, + const struct sieve_extension *ext); +void sieve_ext_variables_runtime_set_storage + (const struct sieve_extension *var_ext, const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, struct sieve_variable_storage *storage); + +const char *sieve_ext_variables_runtime_get_identifier +(const struct sieve_extension *var_ext, const struct sieve_runtime_env *renv, + const struct sieve_extension *ext, unsigned int index); + +/* + * Variable arguments + */ + +bool sieve_variable_argument_activate + (const struct sieve_extension *var_ext, + const struct sieve_extension *this_ext, + struct sieve_validator *valdtr, struct sieve_command *cmd, + struct sieve_ast_argument *arg, bool assignment); + +/* + * Variable operands + */ + +extern const struct sieve_operand_def variable_operand; + +void sieve_variables_opr_variable_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + struct sieve_variable *var); +void sieve_variables_opr_match_value_emit + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, + unsigned int index); + +int sieve_variable_operand_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name, + struct sieve_variable_storage **storage_r, unsigned int *var_index_r); +int sieve_variable_operand_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_variable_storage **storage_r, + unsigned int *var_index_r); + +static inline bool sieve_operand_is_variable +(const struct sieve_operand *operand) +{ + return ( operand != NULL && operand->def != NULL && + operand->def == &variable_operand ); +} + +/* + * Modifiers + */ + +/* Definition */ + +struct sieve_variables_modifier; + +struct sieve_variables_modifier_def { + struct sieve_object_def obj_def; + + unsigned int precedence; + + bool (*modify)(const struct sieve_variables_modifier *modf, + string_t *in, string_t **result); +}; + +struct sieve_variables_modifier { + struct sieve_object object; + const struct sieve_extension *var_ext; + + const struct sieve_variables_modifier_def *def; +}; + +#define SIEVE_VARIABLES_DEFINE_MODIFIER(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_VARIABLES_DEFINE_MODIFIERS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +#define sieve_variables_modifier_name(smodf) \ + ( (smodf)->object.def->identifier ) + +ARRAY_DEFINE_TYPE(sieve_variables_modifier, + struct sieve_variables_modifier); + +/* Registry */ + +void sieve_variables_modifier_register + (const struct sieve_extension *var_ext, struct sieve_validator *valdtr, + const struct sieve_extension *ext, + const struct sieve_variables_modifier_def *smodf); + +/* Tagged argument */ + +void sieve_variables_modifiers_link_tag + (struct sieve_validator *valdtr, const struct sieve_extension *var_ext, + struct sieve_command_registration *cmd_reg); + +bool sieve_variables_modifiers_validate + (struct sieve_validator *valdtr, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variables_modifier) *modifiers); + +bool sieve_variables_modifiers_generate + (const struct sieve_codegen_env *cgenv, + ARRAY_TYPE(sieve_variables_modifier) *modifiers); + +/* Coding */ + +extern const struct sieve_operand_class + sieve_variables_modifier_operand_class; + +bool sieve_variables_modifiers_code_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +int sieve_variables_modifiers_code_read( + const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, sieve_size_t *address, + ARRAY_TYPE(sieve_variables_modifier) *modifiers); + +/* Application */ + +int sieve_variables_modifiers_apply +(const struct sieve_runtime_env *renv, + const struct sieve_extension *var_ext, + ARRAY_TYPE(sieve_variables_modifier) *modifiers, + string_t **value); + +/* + * Code dumping + */ + +void sieve_ext_variables_dump_set_scope +(const struct sieve_extension *var_ext, const struct sieve_dumptime_env *denv, + const struct sieve_extension *ext, struct sieve_variable_scope *scope); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/variables/tst-string.c b/pigeonhole/src/lib-sieve/plugins/variables/tst-string.c new file mode 100644 index 0000000..91b0b82 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/variables/tst-string.c @@ -0,0 +1,271 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "sieve-common.h" +#include "sieve-commands.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-match.h" + +#include "ext-variables-common.h" + +/* + * String test + * + * Syntax: + * string [COMPARATOR] [MATCH-TYPE] + * <source: string-list> <key-list: string-list> + */ + +static bool tst_string_registered + (struct sieve_validator *valdtr, const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool tst_string_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool tst_string_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def tst_string = { + .identifier = "string", + .type = SCT_TEST, + .positional_args = 2, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = tst_string_registered, + .validate = tst_string_validate, + .generate = tst_string_generate +}; + +/* + * String operation + */ + +static bool tst_string_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int tst_string_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def tst_string_operation = { + .mnemonic = "STRING", + .ext_def = &variables_extension, + .code = EXT_VARIABLES_OPERATION_STRING, + .dump = tst_string_operation_dump, + .execute = tst_string_operation_execute +}; + +/* + * Optional arguments + */ + +enum tst_string_optional { + OPT_END, + OPT_COMPARATOR, + OPT_MATCH_TYPE +}; + +/* + * Test registration + */ + +static bool tst_string_registered +(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_command_registration *cmd_reg) +{ + /* The order of these is not significant */ + sieve_comparators_link_tag(valdtr, cmd_reg, OPT_COMPARATOR); + sieve_match_types_link_tags(valdtr, cmd_reg, OPT_MATCH_TYPE); + + return TRUE; +} + +/* + * Test validation + */ + +static bool tst_string_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + const struct sieve_match_type mcht_default = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + const struct sieve_comparator cmp_default = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "source", 1, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + arg = sieve_ast_argument_next(arg); + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) { + return FALSE; + } + + if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) ) + return FALSE; + + /* Validate the key argument to a specified match type */ + return sieve_match_type_validate + (valdtr, tst, arg, &mcht_default, &cmp_default); +} + +/* + * Test generation + */ + +static bool tst_string_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_string_operation); + + /* Generate arguments */ + if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) + return FALSE; + + return TRUE; +} + +/* + * Code dump + */ + +static bool tst_string_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "STRING-TEST"); + sieve_code_descend(denv); + + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) + return FALSE; + + return + sieve_opr_stringlist_dump(denv, address, "source") && + sieve_opr_stringlist_dump(denv, address, "key list"); +} + +/* + * Code execution + */ + +static int tst_string_stringlist_next_item + (struct sieve_stringlist *_strlist, string_t **str_r); +static void tst_string_stringlist_reset + (struct sieve_stringlist *_strlist); +static int tst_string_stringlist_get_length + (struct sieve_stringlist *_strlist); + +struct tst_string_stringlist { + struct sieve_stringlist strlist; + + struct sieve_stringlist *value_list; +}; + +static struct sieve_stringlist *tst_string_stringlist_create +(const struct sieve_runtime_env *renv, struct sieve_stringlist *value_list) +{ + struct tst_string_stringlist *strlist; + + strlist = t_new(struct tst_string_stringlist, 1); + strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; + strlist->strlist.next_item = tst_string_stringlist_next_item; + strlist->strlist.reset = tst_string_stringlist_reset; + strlist->strlist.get_length = tst_string_stringlist_get_length; + strlist->value_list = value_list; + + return &strlist->strlist; +} + +static int tst_string_stringlist_next_item +(struct sieve_stringlist *_strlist, string_t **str_r) +{ + struct tst_string_stringlist *strlist = + (struct tst_string_stringlist *)_strlist; + + return sieve_stringlist_next_item(strlist->value_list, str_r); +} + +static void tst_string_stringlist_reset +(struct sieve_stringlist *_strlist) +{ + struct tst_string_stringlist *strlist = + (struct tst_string_stringlist *)_strlist; + + sieve_stringlist_reset(strlist->value_list); +} + +static int tst_string_stringlist_get_length +(struct sieve_stringlist *_strlist) +{ + struct tst_string_stringlist *strlist = + (struct tst_string_stringlist *)_strlist; + string_t *item; + int length = 0; + int ret; + + while ( (ret=sieve_stringlist_next_item(strlist->value_list, &item)) > 0 ) { + if ( str_len(item) > 0 ) + length++; + } + + return ( ret < 0 ? -1 : length ); +} + +static int tst_string_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + struct sieve_match_type mcht = + SIEVE_MATCH_TYPE_DEFAULT(is_match_type); + struct sieve_comparator cmp = + SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); + struct sieve_stringlist *source, *value_list, *key_list; + int match, ret; + + /* + * Read operands + */ + + /* Handle match-type and comparator operands */ + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; + + /* Read source */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "source", &source)) <= 0 ) + return ret; + + /* Read key-list */ + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "string test"); + + /* Create wrapper string list wich does not count empty string items */ + value_list = tst_string_stringlist_create(renv, source); + + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.am new file mode 100644 index 0000000..f409e2b --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = debug environment report + diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.in new file mode 100644 index 0000000..43680f1 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/vnd.dovecot +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 $(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_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 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +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 +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +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@ +SUBDIRS = debug environment report +all: all-recursive + +.SUFFIXES: +$(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/lib-sieve/plugins/vnd.dovecot/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(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-recursive + +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-recursive + +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 + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean 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-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 \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.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/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am new file mode 100644 index 0000000..1e08946 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libsieve_ext_debug.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-debug-log.c + +libsieve_ext_debug_la_SOURCES = \ + $(commands) \ + ext-debug.c + +noinst_HEADERS = \ + ext-debug-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.in new file mode 100644 index 0000000..f9b5450 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/Makefile.in @@ -0,0 +1,687 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/vnd.dovecot/debug +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_debug_la_LIBADD = +am__objects_1 = cmd-debug-log.lo +am_libsieve_ext_debug_la_OBJECTS = $(am__objects_1) ext-debug.lo +libsieve_ext_debug_la_OBJECTS = $(am_libsieve_ext_debug_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 = +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)/cmd-debug-log.Plo \ + ./$(DEPDIR)/ext-debug.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 = $(libsieve_ext_debug_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_debug_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@ +noinst_LTLIBRARIES = libsieve_ext_debug.la +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-debug-log.c + +libsieve_ext_debug_la_SOURCES = \ + $(commands) \ + ext-debug.c + +noinst_HEADERS = \ + ext-debug-common.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/lib-sieve/plugins/vnd.dovecot/debug/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/debug/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_debug.la: $(libsieve_ext_debug_la_OBJECTS) $(libsieve_ext_debug_la_DEPENDENCIES) $(EXTRA_libsieve_ext_debug_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_debug_la_OBJECTS) $(libsieve_ext_debug_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-debug-log.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-debug.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-debug-log.Plo + -rm -f ./$(DEPDIR)/ext-debug.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-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)/cmd-debug-log.Plo + -rm -f ./$(DEPDIR)/ext-debug.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c new file mode 100644 index 0000000..355daa5 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-code.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-debug-common.h" + +/* + * Debug_log command + * + * Syntax + * debug_log <message: string> + */ + +static bool cmd_debug_log_validate + (struct sieve_validator *valdtr, struct sieve_command *tst); +static bool cmd_debug_log_generate + (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx); + +const struct sieve_command_def debug_log_command = { + .identifier = "debug_log", + .type = SCT_COMMAND, + .positional_args = 1, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .validate = cmd_debug_log_validate, + .generate = cmd_debug_log_generate +}; + +/* + * Body operation + */ + +static bool cmd_debug_log_operation_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address); +static int cmd_debug_log_operation_execute + (const struct sieve_runtime_env *renv, sieve_size_t *address); + +const struct sieve_operation_def debug_log_operation = { + .mnemonic = "DEBUG_LOG", + .ext_def = &vnd_debug_extension, + .dump = cmd_debug_log_operation_dump, + .execute = cmd_debug_log_operation_execute +}; + +/* + * Validation + */ + +static bool cmd_debug_log_validate +(struct sieve_validator *valdtr, struct sieve_command *tst) +{ + struct sieve_ast_argument *arg = tst->first_positional; + + if ( !sieve_validate_positional_argument + (valdtr, tst, arg, "message", 1, SAAT_STRING) ) { + return FALSE; + } + + return sieve_validator_argument_activate(valdtr, tst, arg, FALSE); +} + +/* + * Code generation + */ + +static bool cmd_debug_log_generate +(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) +{ + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &debug_log_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool cmd_debug_log_operation_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + sieve_code_dumpf(denv, "DEBUG_LOG"); + sieve_code_descend(denv); + + return sieve_opr_string_dump(denv, address, "key list"); +} + +/* + * Interpretation + */ + +static int cmd_debug_log_operation_execute +(const struct sieve_runtime_env *renv, sieve_size_t *address) +{ + string_t *message; + int ret; + + /* + * Read operands + */ + + /* Read message */ + + if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 ) + return ret; + + /* + * Perform operation + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "debug_log \"%s\"", + str_sanitize(str_c(message), 80)); + + sieve_runtime_log(renv, NULL, "DEBUG: %s", str_c(message)); + + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h new file mode 100644 index 0000000..88ae3db --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h @@ -0,0 +1,22 @@ +#ifndef EXT_DEBUG_COMMON_H +#define EXT_DEBUG_COMMON_H + +/* + * Extensions + */ + +extern const struct sieve_extension_def vnd_debug_extension; + +/* + * Commands + */ + +extern const struct sieve_command_def debug_log_command; + +/* + * Operations + */ + +extern const struct sieve_operation_def debug_log_operation; + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c new file mode 100644 index 0000000..2781e83 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension debug + * --------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; spec-bosch-sieve-debug + * Implementation: full + * Status: experimental + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-debug-common.h" + +/* + * Extension + */ + +static bool ext_debug_validator_load + (const struct sieve_extension *ext, struct sieve_validator *validator); +static bool ext_debug_interpreter_load + (const struct sieve_extension *ext ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED); + + +const struct sieve_extension_def vnd_debug_extension = { + .name = "vnd.dovecot.debug", + .validator_load = ext_debug_validator_load, + .interpreter_load = ext_debug_interpreter_load, + SIEVE_EXT_DEFINE_OPERATION(debug_log_operation), +}; + +static bool ext_debug_validator_load +(const struct sieve_extension *ext, struct sieve_validator *validator) +{ + /* Register new test */ + sieve_validator_register_command(validator, ext, &debug_log_command); + + return TRUE; +} + +static bool ext_debug_interpreter_load +(const struct sieve_extension *ext ATTR_UNUSED, + const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) +{ + if ( renv->ehandler != NULL ) { + sieve_error_handler_accept_infolog(renv->ehandler, TRUE); + } + + return TRUE; +} + + + diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am new file mode 100644 index 0000000..96618ff --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES = libsieve_ext_vnd_environment.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../environment \ + -I$(srcdir)/../../variables \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_vnd_environment_la_SOURCES = \ + ext-vnd-environment.c \ + ext-vnd-environment-items.c \ + ext-vnd-environment-variables.c + +noinst_HEADERS = \ + ext-vnd-environment-common.h + diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.in new file mode 100644 index 0000000..b5d8b20 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/Makefile.in @@ -0,0 +1,692 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/vnd.dovecot/environment +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_vnd_environment_la_LIBADD = +am_libsieve_ext_vnd_environment_la_OBJECTS = ext-vnd-environment.lo \ + ext-vnd-environment-items.lo ext-vnd-environment-variables.lo +libsieve_ext_vnd_environment_la_OBJECTS = \ + $(am_libsieve_ext_vnd_environment_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 = +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)/ext-vnd-environment-items.Plo \ + ./$(DEPDIR)/ext-vnd-environment-variables.Plo \ + ./$(DEPDIR)/ext-vnd-environment.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 = $(libsieve_ext_vnd_environment_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_vnd_environment_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@ +noinst_LTLIBRARIES = libsieve_ext_vnd_environment.la +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../environment \ + -I$(srcdir)/../../variables \ + $(LIBDOVECOT_INCLUDE) + +libsieve_ext_vnd_environment_la_SOURCES = \ + ext-vnd-environment.c \ + ext-vnd-environment-items.c \ + ext-vnd-environment-variables.c + +noinst_HEADERS = \ + ext-vnd-environment-common.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/lib-sieve/plugins/vnd.dovecot/environment/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/environment/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_vnd_environment.la: $(libsieve_ext_vnd_environment_la_OBJECTS) $(libsieve_ext_vnd_environment_la_DEPENDENCIES) $(EXTRA_libsieve_ext_vnd_environment_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_vnd_environment_la_OBJECTS) $(libsieve_ext_vnd_environment_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-environment-items.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-environment-variables.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-environment.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ext-vnd-environment-items.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment-variables.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment.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-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)/ext-vnd-environment-items.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment-variables.Plo + -rm -f ./$(DEPDIR)/ext-vnd-environment.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h new file mode 100644 index 0000000..980c830 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-common.h @@ -0,0 +1,37 @@ +#ifndef EXT_VND_ENVIRONMENT_COMMON_H +#define EXT_VND_ENVIRONMENT_COMMON_H + +#include "sieve-ext-environment.h" + +/* + * Extension + */ + +struct ext_vnd_environment_context { + const struct sieve_extension *env_ext; + const struct sieve_extension *var_ext; +}; + +extern const struct sieve_extension_def vnd_environment_extension; + +/* + * Operands + */ + +extern const struct sieve_operand_def environment_namespace_operand; + +/* + * Environment items + */ + +void ext_vnd_environment_items_register +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv); + +/* + * Variables + */ + +void ext_environment_variables_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c new file mode 100644 index 0000000..af03255 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-items.c @@ -0,0 +1,95 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-settings.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "ext-vnd-environment-common.h" + +/* + * Environment items + */ + +/* default_mailbox */ + +static const char * +envit_default_mailbox_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + i_assert(eenv->scriptenv->default_mailbox != NULL); + return eenv->scriptenv->default_mailbox; +} + +const struct sieve_environment_item default_mailbox_env_item = { + .name = "vnd.dovecot.default-mailbox", + .get_value = envit_default_mailbox_get_value +}; + +/* username */ + +static const char * +envit_username_get_value(const struct sieve_runtime_env *renv, + const char *name ATTR_UNUSED) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return eenv->svinst->username; +} + +const struct sieve_environment_item username_env_item = { + .name = "vnd.dovecot.username", + .get_value = envit_username_get_value +}; + +/* config.* */ + +static const char * +envit_config_get_value(const struct sieve_runtime_env *renv, const char *name) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + if (*name == '\0') + return NULL; + + return sieve_setting_get(eenv->svinst, + t_strconcat("sieve_env_", name, NULL)); +} + +const struct sieve_environment_item config_env_item = { + .name = "vnd.dovecot.config", + .prefix = TRUE, + .get_value = envit_config_get_value +}; + +/* + * Register + */ + +void ext_vnd_environment_items_register(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv) +{ + struct ext_vnd_environment_context *ectx = + (struct ext_vnd_environment_context *)ext->context; + + sieve_environment_item_register(ectx->env_ext, renv->interp, + &default_mailbox_env_item); + sieve_environment_item_register(ectx->env_ext, renv->interp, + &username_env_item); + sieve_environment_item_register(ectx->env_ext, renv->interp, + &config_env_item); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c new file mode 100644 index 0000000..1466ee7 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c @@ -0,0 +1,206 @@ +/* Copyright (c) 2015-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-vnd-environment-common.h" + +static bool vnspc_vnd_environment_validate + (struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +static bool vnspc_vnd_environment_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, + struct sieve_command *cmd, void *var_data); +static bool vnspc_vnd_environment_dump_variable + (const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); +static int vnspc_vnd_environment_read_variable + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); + +static const struct sieve_variables_namespace_def +environment_namespace = { + SIEVE_OBJECT("env", &environment_namespace_operand, 0), + .validate = vnspc_vnd_environment_validate, + .generate = vnspc_vnd_environment_generate, + .dump_variable = vnspc_vnd_environment_dump_variable, + .read_variable = vnspc_vnd_environment_read_variable +}; + +static bool vnspc_vnd_environment_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment) +{ + struct sieve_ast *ast = arg->ast; + const struct sieve_variable_name *name_elements; + unsigned int i, count; + const char *variable; + string_t *name; + + /* Compose environment name from parsed variable name */ + name = t_str_new(64); + name_elements = array_get(var_name, &count); + i_assert(count > 1); + for (i = 1; i < count; i++) { + if ( name_elements[i].num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "vnd.dovecot.environment: invalid variable name within " + "env namespace `env.%d': " + "encountered numeric variable name", + name_elements[i].num_variable); + return FALSE; + } + if (str_len(name) > 0) + str_append_c(name, '.'); + str_append_str(name, name_elements[i].identifier); + } + + variable = str_c(name); + + if ( assignment ) { + sieve_argument_validate_error(valdtr, arg, + "vnd.dovecot.environment: cannot assign to environment " + "variable `env.%s'", variable); + return FALSE; + } + + *var_data = (void *) p_strdup(sieve_ast_pool(ast), variable); + return TRUE; +} + +static bool vnspc_vnd_environment_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + const char *variable = (const char *) var_data; + struct ext_vnd_environment_context *ext_data; + + if ( this_ext == NULL ) + return FALSE; + + ext_data = (struct ext_vnd_environment_context *) this_ext->context; + + sieve_variables_opr_namespace_variable_emit + (cgenv->sblock, ext_data->var_ext, this_ext, &environment_namespace); + sieve_binary_emit_cstring(cgenv->sblock, variable); + + return TRUE; +} + +static bool vnspc_vnd_environment_dump_variable +(const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + const struct sieve_operand *oprnd, sieve_size_t *address) +{ + string_t *var_name; + + if ( !sieve_binary_read_string(denv->sblock, address, &var_name) ) + return FALSE; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: VAR ${env.%s}", + oprnd->field_name, str_c(var_name)); + else + sieve_code_dumpf(denv, "VAR ${env.%s}", + str_c(var_name)); + + return TRUE; +} + +static int vnspc_vnd_environment_read_variable +(const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, + string_t **str_r) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct ext_vnd_environment_context *ectx = + (struct ext_vnd_environment_context *) this_ext->context; + string_t *var_name; + const char *ext_value; + + if ( !sieve_binary_read_string(renv->sblock, address, &var_name) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "environment variable operand corrupt: invalid name"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( str_r != NULL ) { + const char *vname = str_c(var_name); + + ext_value = ext_environment_item_get_value + (ectx->env_ext, renv, vname); + + if ( ext_value == NULL && strchr(vname, '_') != NULL) { + char *p, *aname; + + /* Try again with '_' replaced with '-' */ + aname = t_strdup_noconst(vname); + for (p = aname; *p != '\0'; p++) { + if (*p == '_') + *p = '-'; + } + ext_value = ext_environment_item_get_value + (ectx->env_ext, renv, aname); + } + + if ( ext_value == NULL ) { + *str_r = t_str_new_const("", 0); + return SIEVE_EXEC_OK; + } + + *str_r = t_str_new_const(ext_value, strlen(ext_value)); + } + return SIEVE_EXEC_OK; +} + +/* + * Namespace registration + */ + +static const struct sieve_extension_objects environment_namespaces = + SIEVE_VARIABLES_DEFINE_NAMESPACE(environment_namespace); + +const struct sieve_operand_def environment_namespace_operand = { + .name = "env-namespace", + .ext_def = &vnd_environment_extension, + .class = &sieve_variables_namespace_operand_class, + .interface = &environment_namespaces +}; + +void ext_environment_variables_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_vnd_environment_context *ext_data = + (struct ext_vnd_environment_context *) this_ext->context; + + sieve_variables_namespace_register + (ext_data->var_ext, valdtr, this_ext, &environment_namespace); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c new file mode 100644 index 0000000..f8c7028 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment.c @@ -0,0 +1,112 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension vnd.dovecot.environment + * --------------------------------- + * + * Authors: Stephan Bosch + * Specification: vendor-defined; + * spec-bosch-sieve-dovecot-environment + * Implementation: preliminary + * Status: experimental + * + */ + +#include "lib.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-address-parts.h" + +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-vnd-environment-common.h" + +/* + * Extension + */ + +static bool ext_vnd_environment_load + (const struct sieve_extension *ext, void **context); +static void ext_vnd_environment_unload + (const struct sieve_extension *ext); +static bool ext_vnd_environment_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_vnd_environment_interpreter_load + (const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_extension_def vnd_environment_extension = { + .name = "vnd.dovecot.environment", + .load = ext_vnd_environment_load, + .unload = ext_vnd_environment_unload, + .validator_load = ext_vnd_environment_validator_load, + .interpreter_load = ext_vnd_environment_interpreter_load, + SIEVE_EXT_DEFINE_OPERAND(environment_namespace_operand) +}; + +static bool ext_vnd_environment_load +(const struct sieve_extension *ext, void **context) +{ + struct ext_vnd_environment_context *ectx; + + if ( *context != NULL ) + ext_vnd_environment_unload(ext); + + ectx = i_new(struct ext_vnd_environment_context, 1); + ectx->env_ext = sieve_ext_environment_require_extension(ext->svinst); + ectx->var_ext = sieve_ext_variables_get_extension(ext->svinst); + *context = (void *) ectx; + + return TRUE; +} + +static void ext_vnd_environment_unload +(const struct sieve_extension *ext) +{ + struct ext_vnd_environment_context *ectx = + (struct ext_vnd_environment_context *) ext->context; + + i_free(ectx); +} + +/* + * Validator + */ + +static bool ext_vnd_environment_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + const struct sieve_extension *env_ext; + + /* Load environment extension implicitly */ + + env_ext = sieve_validator_extension_load_implicit + (valdtr, environment_extension.name); + if ( env_ext == NULL ) + return FALSE; + + ext_environment_variables_init(ext, valdtr); + return TRUE; +} + +/* + * Interpreter + */ + +static bool ext_vnd_environment_interpreter_load +(const struct sieve_extension *ext, const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_vnd_environment_items_register(ext, renv); + return TRUE; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am new file mode 100644 index 0000000..599765f --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libsieve_ext_vnd_report.la + +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-report.c + +libsieve_ext_vnd_report_la_SOURCES = \ + ext-vnd-report.c \ + ext-vnd-report-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-vnd-report-common.h diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.in b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.in new file mode 100644 index 0000000..1c2ec8c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/Makefile.in @@ -0,0 +1,695 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/lib-sieve/plugins/vnd.dovecot/report +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 = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libsieve_ext_vnd_report_la_LIBADD = +am__objects_1 = cmd-report.lo +am_libsieve_ext_vnd_report_la_OBJECTS = ext-vnd-report.lo \ + ext-vnd-report-common.lo $(am__objects_1) +libsieve_ext_vnd_report_la_OBJECTS = \ + $(am_libsieve_ext_vnd_report_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 = +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)/cmd-report.Plo \ + ./$(DEPDIR)/ext-vnd-report-common.Plo \ + ./$(DEPDIR)/ext-vnd-report.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 = $(libsieve_ext_vnd_report_la_SOURCES) +DIST_SOURCES = $(libsieve_ext_vnd_report_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@ +noinst_LTLIBRARIES = libsieve_ext_vnd_report.la +AM_CPPFLAGS = \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../../../util \ + $(LIBDOVECOT_INCLUDE) + +commands = \ + cmd-report.c + +libsieve_ext_vnd_report_la_SOURCES = \ + ext-vnd-report.c \ + ext-vnd-report-common.c \ + $(commands) + +noinst_HEADERS = \ + ext-vnd-report-common.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/lib-sieve/plugins/vnd.dovecot/report/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-sieve/plugins/vnd.dovecot/report/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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_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}; \ + } + +libsieve_ext_vnd_report.la: $(libsieve_ext_vnd_report_la_OBJECTS) $(libsieve_ext_vnd_report_la_DEPENDENCIES) $(EXTRA_libsieve_ext_vnd_report_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libsieve_ext_vnd_report_la_OBJECTS) $(libsieve_ext_vnd_report_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd-report.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-report-common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext-vnd-report.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: +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-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/cmd-report.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report-common.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report.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-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)/cmd-report.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report-common.Plo + -rm -f ./$(DEPDIR)/ext-vnd-report.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: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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-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 + +.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/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c new file mode 100644 index 0000000..af53e42 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c @@ -0,0 +1,692 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ioloop.h" +#include "hostpid.h" +#include "str-sanitize.h" +#include "istream.h" +#include "ostream.h" +#include "message-date.h" +#include "message-size.h" +#include "mail-storage.h" + +#include "rfc2822.h" + +#include "sieve-common.h" +#include "sieve-stringlist.h" +#include "sieve-code.h" +#include "sieve-address.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-message.h" +#include "sieve-actions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" +#include "sieve-result.h" +#include "sieve-address.h" +#include "sieve-message.h" +#include "sieve-smtp.h" + +#include "ext-vnd-report-common.h" + +#include <ctype.h> + +/* Report command + * + * Syntax: + * report [:headers_only] <feedback-type: string> + * <message: string> <address: string> + * + */ + +static bool +cmd_report_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg); +static bool +cmd_report_validate(struct sieve_validator *valdtr, struct sieve_command *cmd); +static bool +cmd_report_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *ctx); + +const struct sieve_command_def cmd_report = { + .identifier = "report", + .type = SCT_COMMAND, + .positional_args = 3, + .subtests = 0, + .block_allowed = FALSE, + .block_required = FALSE, + .registered = cmd_report_registered, + .validate = cmd_report_validate, + .generate = cmd_report_generate +}; + +/* + * Tagged arguments + */ + +static const struct sieve_argument_def report_headers_only_tag = { + .identifier = "headers_only" +}; + +/* + * Report operation + */ + +static bool +cmd_report_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address); +static int +cmd_report_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address); + +const struct sieve_operation_def report_operation = { + .mnemonic = "REPORT", + .ext_def = &vnd_report_extension, + .code = 0, + .dump = cmd_report_operation_dump, + .execute = cmd_report_operation_execute +}; + +/* Codes for optional operands */ + +enum cmd_report_optional { + OPT_END, + OPT_HEADERS_ONLY +}; + +/* + * Report action + */ + +/* Forward declarations */ + +static int +act_report_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other); +static void +act_report_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, bool *keep); +static int +act_report_commit(const struct sieve_action_exec_env *aenv, void *tr_context); + +/* Action object */ + +const struct sieve_action_def act_report = { + .name = "report", + .check_duplicate = act_report_check_duplicate, + .print = act_report_print, + .commit = act_report_commit +}; + +/* Action data */ + +struct act_report_data { + const char *feedback_type; + const char *message; + struct smtp_address *to_address; + bool headers_only:1; +}; + +/* + * Command registration + */ + +static bool +cmd_report_registered(struct sieve_validator *valdtr, + const struct sieve_extension *ext, + struct sieve_command_registration *cmd_reg) +{ + sieve_validator_register_tag(valdtr, cmd_reg, ext, + &report_headers_only_tag, + OPT_HEADERS_ONLY); + return TRUE; +} + +/* + * Command validation + */ + +static bool +cmd_report_validate(struct sieve_validator *valdtr, struct sieve_command *cmd) +{ + struct sieve_ast_argument *arg = cmd->first_positional; + + /* type */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, + "feedback-type", 1, + SAAT_STRING)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + if (sieve_argument_is_string_literal(arg)) { + string_t *fbtype = sieve_ast_argument_str(arg); + const char *feedback_type; + + T_BEGIN { + /* Check feedback type */ + feedback_type = + ext_vnd_report_parse_feedback_type(str_c(fbtype)); + + if (feedback_type == NULL) { + sieve_argument_validate_error( + valdtr, arg, + "specified feedback type `%s' is invalid", + str_sanitize(str_c(fbtype),128)); + } + } T_END; + + if (feedback_type == NULL) + return FALSE; + } + arg = sieve_ast_argument_next(arg); + + /* message */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "message", + 2, SAAT_STRING)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + arg = sieve_ast_argument_next(arg); + + /* address */ + if (!sieve_validate_positional_argument(valdtr, cmd, arg, "address", + 3, SAAT_STRING)) + return FALSE; + if (!sieve_validator_argument_activate(valdtr, cmd, arg, FALSE)) + return FALSE; + + /* We can only assess the validity of the outgoing address when it is a + string literal. For runtime-generated strings this needs to be done + at runtime. + */ + if (sieve_argument_is_string_literal(arg)) { + string_t *raw_address = sieve_ast_argument_str(arg); + const char *error; + bool result; + + T_BEGIN { + /* Parse the address */ + result = sieve_address_validate_str(raw_address, &error); + if (!result) { + sieve_argument_validate_error( + valdtr, arg, + "specified report address '%s' is invalid: %s", + str_sanitize(str_c(raw_address),128), + error); + } + } T_END; + + return result; + } + + return TRUE; +} + +/* + * Code generation + */ + +static bool +cmd_report_generate(const struct sieve_codegen_env *cgenv, + struct sieve_command *cmd) +{ + sieve_operation_emit(cgenv->sblock, cmd->ext, &report_operation); + + /* Generate arguments */ + return sieve_generate_arguments(cgenv, cmd, NULL); +} + +/* + * Code dump + */ + +static bool +cmd_report_operation_dump(const struct sieve_dumptime_env *denv, + sieve_size_t *address) +{ + int opt_code = 0; + + sieve_code_dumpf(denv, "REPORT"); + sieve_code_descend(denv); + + /* Dump optional operands */ + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_dump(denv, address, + &opt_code)) < 0) + return FALSE; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_HEADERS_ONLY: + sieve_code_dumpf(denv, "headers_only"); + break; + default: + return FALSE; + } + } + + return (sieve_opr_string_dump(denv, address, "feedback-type") && + sieve_opr_string_dump(denv, address, "message") && + sieve_opr_string_dump(denv, address, "address")); +} + +/* + * Code execution + */ + + +static int +cmd_report_operation_execute(const struct sieve_runtime_env *renv, + sieve_size_t *address) +{ + const struct sieve_extension *this_ext = renv->oprtn->ext; + struct act_report_data *act; + string_t *fbtype, *message, *to_address; + const char *feedback_type, *error; + const struct smtp_address *parsed_address; + int opt_code = 0, ret = 0; + bool headers_only = FALSE; + pool_t pool; + + /* + * Read operands + */ + + /* Optional operands */ + + for (;;) { + int opt; + + if ((opt = sieve_opr_optional_read(renv, address, + &opt_code)) < 0) + return SIEVE_EXEC_BIN_CORRUPT; + + if (opt == 0) + break; + + switch (opt_code) { + case OPT_HEADERS_ONLY: + headers_only = TRUE; + break; + default: + sieve_runtime_trace_error( + renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + } + + /* Fixed operands */ + + if ((ret = sieve_opr_string_read(renv, address, "feedback-type", + &fbtype)) <= 0) + return ret; + if ((ret = sieve_opr_string_read(renv, address, "message", + &message)) <= 0) + return ret; + if ((ret = sieve_opr_string_read(renv, address, "address", + &to_address)) <= 0) + return ret; + + /* + * Perform operation + */ + + /* Verify and trim feedback type */ + feedback_type = ext_vnd_report_parse_feedback_type(str_c(fbtype)); + if (feedback_type == NULL) { + sieve_runtime_error( + renv, NULL, + "specified report feedback type `%s' is invalid", + str_sanitize(str_c(fbtype), 256)); + return SIEVE_EXEC_FAILURE; + } + + /* Verify and normalize the address to 'local_part@domain' */ + parsed_address = sieve_address_parse_str(to_address, &error); + if (parsed_address == NULL) { + sieve_runtime_error( + renv, NULL, + "specified report address '%s' is invalid: %s", + str_sanitize(str_c(to_address),128), error); + return SIEVE_EXEC_FAILURE; + } + + /* Trace */ + if (sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS)) { + sieve_runtime_trace(renv, 0, "report action"); + sieve_runtime_trace_descend(renv); + sieve_runtime_trace( + renv, 0, "report incoming message as `%s' to address %s", + str_sanitize(str_c(fbtype), 32), + smtp_address_encode_path(parsed_address)); + } + + /* Add report action to the result */ + + pool = sieve_result_pool(renv->result); + act = p_new(pool, struct act_report_data, 1); + act->headers_only = headers_only; + act->feedback_type = p_strdup(pool, feedback_type); + act->message = p_strdup(pool, str_c(message)); + act->to_address = smtp_address_clone(pool, parsed_address); + + if (sieve_result_add_action(renv, this_ext, "report", &act_report, NULL, + (void *)act, 0, TRUE) < 0) + return SIEVE_EXEC_FAILURE; + return SIEVE_EXEC_OK; +} + +/* + * Action + */ + +/* Runtime verification */ + +static bool +act_report_equals(const struct sieve_script_env *senv ATTR_UNUSED, + const struct sieve_action *act1, + const struct sieve_action *act2) +{ + struct act_report_data *rdd1 = (struct act_report_data *)act1->context; + struct act_report_data *rdd2 = (struct act_report_data *)act2->context; + + /* Address is already normalized */ + return (smtp_address_equals(rdd1->to_address, rdd2->to_address)); +} + +static int +act_report_check_duplicate(const struct sieve_runtime_env *renv, + const struct sieve_action *act, + const struct sieve_action *act_other) +{ + const struct sieve_execute_env *eenv = renv->exec_env; + + return (act_report_equals(eenv->scriptenv, act, act_other) ? 1 : 0); +} + +/* Result printing */ + +static void +act_report_print(const struct sieve_action *action, + const struct sieve_result_print_env *rpenv, + bool *keep ATTR_UNUSED) +{ + const struct act_report_data *rdd = + (struct act_report_data *)action->context; + + sieve_result_action_printf(rpenv, + "report incoming message as `%s' to: %s", + str_sanitize(rdd->feedback_type, 32), + smtp_address_encode_path(rdd->to_address)); +} + +/* Result execution */ + +static bool _contains_8bit(const char *msg) +{ + const unsigned char *s = (const unsigned char *)msg; + + for (; *s != '\0'; s++) { + if ((*s & 0x80) != 0) + return TRUE; + } + return FALSE; +} + +static int +act_report_send(const struct sieve_action_exec_env *aenv, + const struct ext_report_config *config, + const struct act_report_data *act) +{ + const struct sieve_execute_env *eenv = aenv->exec_env; + struct sieve_instance *svinst = eenv->svinst; + struct sieve_message_context *msgctx = aenv->msgctx; + const struct sieve_script_env *senv = eenv->scriptenv; + const struct sieve_message_data *msgdata = eenv->msgdata; + struct sieve_address_source report_from = config->report_from; + const struct smtp_address *sender, *user; + struct sieve_smtp_context *sctx; + struct istream *input; + struct ostream *output; + string_t *msg; + const char *const *headers; + const char *outmsgid, *boundary, *error, *subject, *from; + int ret; + + /* Just to be sure */ + if (!sieve_smtp_available(senv)) { + sieve_result_global_warning( + aenv, "report action has no means to send mail"); + return SIEVE_EXEC_OK; + } + + /* Make sure we have a subject for our report */ + if ((ret = mail_get_headers_utf8(msgdata->mail, "subject", + &headers)) < 0) { + return sieve_result_mail_error( + aenv, msgdata->mail, + "failed to read header field `subject'"); + } + if (ret > 0 && headers[0] != NULL) + subject = t_strconcat("Report: ", headers[0], NULL); + else + subject = "Report: (message without subject)"; + + /* Determine from address */ + if (report_from.type == SIEVE_ADDRESS_SOURCE_POSTMASTER) { + report_from.type = SIEVE_ADDRESS_SOURCE_DEFAULT; + report_from.address = NULL; + } + if (sieve_address_source_get_address( + &report_from, svinst, senv, msgctx, eenv->flags, + &sender) > 0 && sender != NULL) + from = smtp_address_encode_path(sender); + else + from = sieve_get_postmaster_address(senv); + + /* Start message */ + sctx = sieve_smtp_start_single(senv, act->to_address, NULL, &output); + + outmsgid = sieve_message_get_new_id(svinst); + boundary = t_strdup_printf("%s/%s", my_pid, svinst->hostname); + + /* Compose main report headers */ + msg = t_str_new(512); + rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION); + rfc2822_header_write(msg, "Message-ID", outmsgid); + rfc2822_header_write(msg, "Date", message_date_create(ioloop_time)); + + rfc2822_header_write(msg, "From", from); + rfc2822_header_write(msg, "To", + smtp_address_encode_path(act->to_address)); + + if (_contains_8bit(subject)) + rfc2822_header_utf8_printf(msg, "Subject", "%s", subject); + else + rfc2822_header_printf(msg, "Subject", "%s", subject); + + rfc2822_header_write(msg, "Auto-Submitted", "auto-generated (report)"); + + rfc2822_header_write(msg, "MIME-Version", "1.0"); + rfc2822_header_printf(msg, "Content-Type", + "multipart/report; report-type=feedback-report;\n" + "boundary=\"%s\"", boundary); + + str_append(msg, "\r\nThis is a MIME-encapsulated message\r\n\r\n"); + + /* Human-readable report */ + str_printfa(msg, "--%s\r\n", boundary); + if (_contains_8bit(act->message)) { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=utf-8"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit"); + } else { + rfc2822_header_write(msg, "Content-Type", + "text/plain; charset=us-ascii"); + rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); + } + rfc2822_header_write(msg, "Content-Disposition", "inline"); + + str_printfa(msg, "\r\n%s\r\n\r\n", act->message); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Machine-readable report */ + str_truncate(msg, 0); + str_printfa(msg, "--%s\r\n", boundary); + rfc2822_header_write(msg, "Content-Type", "message/feedback-report"); + str_append(msg, "\r\n"); + + rfc2822_header_write(msg, "Version", "1"); + rfc2822_header_write(msg, "Feedback-Type", act->feedback_type); + rfc2822_header_write(msg, "User-Agent", + PACKAGE_NAME "/" PACKAGE_VERSION " " + PIGEONHOLE_NAME "/" PIGEONHOLE_VERSION); + + if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) { + const struct smtp_address *sender, *orig_recipient; + + sender = sieve_message_get_sender(msgctx); + orig_recipient = sieve_message_get_orig_recipient(msgctx); + + rfc2822_header_write(msg, "Original-Mail-From", + smtp_address_encode_path(sender)); + if (orig_recipient != NULL) { + rfc2822_header_write( + msg, "Original-Rcpt-To", + smtp_address_encode_path(orig_recipient)); + } + } + if (svinst->user_email != NULL) + user = svinst->user_email; + else if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0 || + (user = sieve_message_get_orig_recipient(msgctx)) == NULL) + user = sieve_get_user_email(svinst); + if (user != NULL) { + rfc2822_header_write(msg, "Dovecot-Reporting-User", + smtp_address_encode_path(user)); + } + str_append(msg, "\r\n"); + + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Original message */ + str_truncate(msg, 0); + str_printfa(msg, "--%s\r\n", boundary); + if (act->headers_only) { + rfc2822_header_write(msg, "Content-Type", + "text/rfc822-headers"); + } else { + rfc2822_header_write(msg, "Content-Type", "message/rfc822"); + } + rfc2822_header_write(msg, "Content-Disposition", "attachment"); + str_append(msg, "\r\n"); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + if (act->headers_only) { + struct message_size hdr_size; + ret = mail_get_hdr_stream(msgdata->mail, &hdr_size, &input); + if (ret >= 0) { + input = i_stream_create_limit( + input, hdr_size.physical_size); + } + } else { + ret = mail_get_stream(msgdata->mail, NULL, NULL, &input); + if (ret >= 0) + i_stream_ref(input); + } + if (ret < 0) { + sieve_smtp_abort(sctx); + return sieve_result_mail_error(aenv, msgdata->mail, + "failed to read input message"); + } + + o_stream_nsend_istream(output, input); + + if (input->stream_errno != 0) { + /* Error; clean up */ + sieve_result_critical(aenv, "failed to read input message", + "read(%s) failed: %s", + i_stream_get_name(input), + i_stream_get_error(input)); + i_stream_unref(&input); + sieve_smtp_abort(sctx); + return SIEVE_EXEC_OK; + } + i_stream_unref(&input); + + str_truncate(msg, 0); + if (!act->headers_only) + str_printfa(msg, "\r\n"); + str_printfa(msg, "\r\n--%s--\r\n", boundary); + o_stream_nsend(output, str_data(msg), str_len(msg)); + + /* Finish sending message */ + if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) { + if (ret < 0) { + sieve_result_global_error( + aenv, "failed to send `%s' report to <%s>: %s " + "(temporary failure)", + str_sanitize(act->feedback_type, 32), + smtp_address_encode(act->to_address), + str_sanitize(error, 512)); + } else { + sieve_result_global_log_error( + aenv, "failed to send `%s' report to <%s>: %s " + "(permanent failure)", + str_sanitize(act->feedback_type, 32), + smtp_address_encode(act->to_address), + str_sanitize(error, 512)); + } + } else { + eenv->exec_status->significant_action_executed = TRUE; + + struct event_passthrough *e = + sieve_action_create_finish_event(aenv)-> + add_str("report_target", + smtp_address_encode(act->to_address))-> + add_str("report_type", + str_sanitize(act->feedback_type, 32)); + + sieve_result_event_log(aenv, e->event(), + "sent `%s' report to <%s>", + str_sanitize(act->feedback_type, 32), + smtp_address_encode(act->to_address)); + } + + return SIEVE_EXEC_OK; +} + +static int +act_report_commit(const struct sieve_action_exec_env *aenv, + void *tr_context ATTR_UNUSED) +{ + const struct sieve_action *action = aenv->action; + const struct sieve_extension *ext = action->ext; + const struct ext_report_config *config = + (const struct ext_report_config *)ext->context; + const struct act_report_data *act = + (const struct act_report_data *)action->context; + int ret; + + T_BEGIN { + ret = act_report_send(aenv, config, act); + } T_END; + + if (ret == SIEVE_EXEC_TEMP_FAILURE) + return SIEVE_EXEC_TEMP_FAILURE; + + /* Ignore all other errors */ + return SIEVE_EXEC_OK; +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c new file mode 100644 index 0000000..d22ad16 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "rfc822-parser.h" + +#include "sieve-common.h" +#include "sieve-extensions.h" + +#include "ext-vnd-report-common.h" + +bool ext_report_load +(const struct sieve_extension *ext, void **context) +{ + struct sieve_instance *svinst = ext->svinst; + struct ext_report_config *config; + + config = p_new(svinst->pool, struct ext_report_config, 1); + + (void)sieve_address_source_parse_from_setting(svinst, + svinst->pool, "sieve_report_from", &config->report_from); + + *context = (void *) config; + return TRUE; +} + +const char * +ext_vnd_report_parse_feedback_type(const char *feedback_type) +{ + struct rfc822_parser_context parser; + string_t *token; + + /* Initialize parsing */ + rfc822_parser_init(&parser, + (const unsigned char *)feedback_type, strlen(feedback_type), NULL); + (void)rfc822_skip_lwsp(&parser); + + /* Parse MIME token */ + token = t_str_new(64); + if (rfc822_parse_mime_token(&parser, token) < 0) + return NULL; + + /* Content-type value must end here, otherwise it is invalid after all */ + (void)rfc822_skip_lwsp(&parser); + if ( parser.data != parser.end ) + return NULL; + + /* Success */ + return str_c(token); +} diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h new file mode 100644 index 0000000..11a3757 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report-common.h @@ -0,0 +1,40 @@ +#ifndef EXT_REPORT_COMMON_H +#define EXT_REPORT_COMMON_H + +/* + * Extension configuration + */ + +struct ext_report_config { + struct sieve_address_source report_from; +}; + +/* + * Extension + */ + +extern const struct sieve_extension_def vnd_report_extension; + +bool ext_report_load + (const struct sieve_extension *ext, void **context); + +/* + * Commands + */ + +extern const struct sieve_command_def cmd_report; + +/* + * Operations + */ + +extern const struct sieve_operation_def report_operation; + +/* + * RFC 5965 feedback-type + */ + +const char * +ext_vnd_report_parse_feedback_type(const char *feedback_type); + +#endif diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c new file mode 100644 index 0000000..a5fb64c --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/report/ext-vnd-report.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2016-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Extension report + * ---------------- + * + * Authors: Stephan Bosch + * Specification: draft-ietf-sieve-report-00.txt + * Implementation: full, but deprecated; provided for backwards compatibility + * Status: testing + * + */ + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-actions.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-result.h" + +#include "ext-vnd-report-common.h" + +/* + * Extension + */ + +static bool ext_report_validator_load + (const struct sieve_extension *ext, struct sieve_validator *valdtr); + +const struct sieve_extension_def vnd_report_extension = { + .name = "vnd.dovecot.report", + .load = ext_report_load, + .validator_load = ext_report_validator_load, + SIEVE_EXT_DEFINE_OPERATION(report_operation) +}; + +/* + * Extension validation + */ + +static bool ext_report_validator_load +(const struct sieve_extension *ext, struct sieve_validator *valdtr) +{ + /* Register new commands */ + sieve_validator_register_command(valdtr, ext, &cmd_report); + + return TRUE; +} |