Index: head/mail/postfix211/Makefile =================================================================== --- head/mail/postfix211/Makefile (revision 447910) +++ head/mail/postfix211/Makefile (revision 447911) @@ -1,357 +1,358 @@ # Created by: Torsten Blum # $FreeBSD$ PORTNAME= postfix -PORTVERSION= 2.11.8 +PORTVERSION= 2.11.10 PORTEPOCH= 1 CATEGORIES= mail ipv6 MASTER_SITES= ftp://ftp.porcupine.org/mirrors/postfix-release/ \ http://de.postfix.org/ftpmirror/ \ http://cdn.postfix.johnriley.me/mirrors/postfix-release/ \ http://www.artfiles.org/postfix.org/postfix-release/ \ http://mirror.lhsolutions.nl/postfix-release/ \ ftp://postfix.mirrors.pair.com/ MASTER_SITES:= ${MASTER_SITES:S|$|official/|} PKGNAMESUFFIX?= 211 DIST_SUBDIR= ${PORTNAME} MAINTAINER= ohauer@FreeBSD.org COMMENT= Secure alternative to widely-used Sendmail LICENSE= IPL10 LICENSE_NAME= IBM PUBLIC LICENSE VERSION 1.0 LICENSE_FILE= ${WRKSRC}/LICENSE LICENSE_PERMS= dist-mirror dist-sell pkg-mirror pkg-sell auto-accept PORTSCOUT= limit:^2\.11\. -VDAVERSION= 2.10.0 CONFLICTS_INSTALL?= courier-0.* opensmtpd-[0-9]* \ sendmail-8.* sendmail+*-8.* smail-3.* zmailer-2.* \ postfix2?-* postfix-3.* postfix-current-* USERS= postfix GROUPS= mail maildrop postfix USES= shebangfix cpe SHEBANG_FILES= auxiliary/qshape/qshape.pl USE_RC_SUBR= postfix USE_SUBMAKE= yes SCRIPTS_ENV+= POSTFIX_DEFAULT_MTA="${POSTFIX_DEFAULT_MTA}" OPTIONS_SUB= yes OPTIONS_DEFINE= BDB CDB DOCS INST_BASE LDAP LDAP_SASL LMDB MYSQL \ NIS PCRE PGSQL SASL SPF SQLITE TEST TLS VDA OPTIONS_RADIO= RG1 OPTIONS_RADIO_RG1= SASLKRB5 SASLKMIT OPTIONS_DEFAULT= PCRE TLS BDB_USES= bdb CDB_LIB_DEPENDS= libcdb.so:databases/tinycdb LDAP_USE= OPENLDAP=yes LMDB_LIB_DEPENDS= liblmdb.so:databases/lmdb MYSQL_USE= MYSQL=yes PCRE_LIB_DEPENDS= libpcre.so:devel/pcre PGSQL_USES= pgsql SASLKMIT_LIB_DEPENDS= libkrb5.so:security/krb5 SASL_LIB_DEPENDS= libsasl2.so:security/cyrus-sasl2 SPF_LIB_DEPENDS= libspf2.so:mail/libspf2 SQLITE_USES= sqlite TLS_USES= ssl CDB_DESC= CDB maps lookups INST_BASE_DESC= Install into /usr and /etc/postfix LDAP_DESC= LDAP maps (uses WITH_OPENLDAP_VER) LDAP_SASL_DESC= LDAP client-to-server SASL auth LMDB_DESC= LMDB maps SPF_DESC= SPF support (via libspf2 1.2.x) TEST_DESC= SMTP/LMTP test server and generator VDA_DESC= VDA (Virtual Delivery Agent) SASL_DESC= Cyrus SASL support (Dovecot SASL is always built in) RG1_DESC= Kerberos network authentication protocol type SASLKRB5_DESC= If your SASL req. Kerberos5, select this SASLKMIT_DESC= If your SASL req. MIT Kerberos5, select this .include HTML1= body_checks.5.html bounce.5.html postfix-power.png \ scache.8.html tlsmgr.8.html STRIP_LIBEXEC= anvil bounce cleanup discard dnsblog error flush lmtp local master \ nqmgr oqmgr pickup pipe postscreen proxymap qmgr qmqpd scache showq \ smtp smtpd spawn tlsmgr tlsproxy trivial-rewrite verify virtual .if !defined(BATCH) && !defined(PACKAGE_BUILDING) && exists(/etc/mail/mailer.conf) OLD_MAILER!= ${GREP} -m 1 '^purgestat' /etc/mail/mailer.conf || ${ECHO_CMD} .if !empty(OLD_MAILER) IS_INTERACTIVE= yes .endif .endif .if !defined(DEBUG) MAKEFILEFLAGS+= DEBUG= .endif MAKEFILEFLAGS+= CC="${CC}" OPT="${CFLAGS}" .if ${PORT_OPTIONS:MINST_BASE} .if defined(SASL_SLAVE) PKGNAMESUFFIX= 211-base-sasl .else PKGNAMESUFFIX= 211-base .endif PREFIX= /usr ETCDIR= /etc/postfix PLIST_SUB+= BMAN="share/" .else PLIST_SUB+= BMAN="" .endif PLIST_SUB+= PFETC=${ETCDIR} # check if mailwrapper supports $LOCALBASE .if ${OPSYS} == FreeBSD && (${OSVERSION} >= 1002506 || ${OSVERSION} >= 1100094) SUB_LIST+= USE_LOCALBASE_MAILER_CONF="yes" MC_PREFIX=${LOCALBASE} .else SUB_LIST+= USE_LOCALBASE_MAILER_CONF="no" MC_PREFIX="" .endif .if ${PORT_OPTIONS:MDOCS} PORTDOCS= * READMEDIR= ${DOCSDIR} .else READMEDIR= no .endif DAEMONDIR= ${PREFIX}/libexec/postfix SUB_LIST+= REQUIRE="${_REQUIRE}" READMEDIR="${READMEDIR}" \ DAEMONDIR="${DAEMONDIR}" SUB_FILES+= pkg-install pkg-message mailer.conf.postfix POSTFIX_CCARGS+= -DDEF_CONFIG_DIR=\\\"${ETCDIR}\\\" \ -DDEF_DAEMON_DIR=\\\"${DAEMONDIR}\\\" \ -DDEF_COMMAND_DIR=\\\"${PREFIX}/sbin\\\" \ -DDEF_SENDMAIL_PATH=\\\"${PREFIX}/sbin/sendmail\\\" \ -DDEF_NEWALIAS_PATH=\\\"${PREFIX}/bin/newaliases\\\" \ -DDEF_MAILQ_PATH=\\\"${PREFIX}/bin/mailq\\\" \ -DDEF_MANPAGE_DIR=\\\"${MANPREFIX}/man\\\" \ -DDEF_README_DIR=\\\"${READMEDIR}\\\" \ -DDEF_HTML_DIR=\\\"${READMEDIR}\\\" \ -DDEF_QUEUE_DIR=\\\"/var/spool/postfix\\\" \ -DDEF_DATA_DIR=\\\"/var/db/postfix\\\" \ -DDEF_MAIL_OWNER=\\\"postfix\\\" \ -DDEF_SGID_GROUP=\\\"maildrop\\\" \ -Wmissing-prototypes -Wformat -Wno-comment # Default requirement for postfix rc script _REQUIRE= LOGIN cleanvar dovecot # Always build with Dovecot SASL support, Cyrus is optional # see Postfix HISTORY 20051222 POSTFIX_CCARGS+= -DUSE_SASL_AUTH .if ${PORT_OPTIONS:MPCRE} POSTFIX_CCARGS+= -DHAS_PCRE -I${LOCALBASE}/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -lpcre .else POSTFIX_CCARGS+= -DNO_PCRE .endif .if ${PORT_OPTIONS:MSASL} POSTFIX_CCARGS+= -DUSE_CYRUS_SASL -I${LOCALBASE}/include -I${LOCALBASE}/include/sasl POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -lsasl2 -lpam -lcrypt .else POSTFIX_CCARGS+= -DDEF_SERVER_SASL_TYPE=\\\"dovecot\\\" .endif .if ${PORT_OPTIONS:MSASLKRB5} POSTFIX_AUXLIBS+= -lkrb5 -lhx509 -lcrypto -lcrypt -lcom_err -lasn1 -lroken .endif .if ${PORT_OPTIONS:MSASLKMIT} POSTFIX_AUXLIBS+= -Wl,--rpath,$${KRB5_HOME:-${LOCALBASE}}/lib -lkrb5 -lcrypto -lcrypt -lcom_err .endif .if ${PORT_OPTIONS:MTLS} POSTFIX_CCARGS+= -DUSE_TLS -I${OPENSSLINC} POSTFIX_AUXLIBS+= -L${OPENSSLLIB} ${LDFLAGS} -lssl -lcrypto .else POSTFIX_CCARGS+= -DNO_TLS .endif .if ${PORT_OPTIONS:MSPF} PATCH_SITES+= LOCAL/mm PATCHFILES+= postfix-2.8.0-libspf2-1.2.x-0.patch.gz:-p1 POSTFIX_CCARGS+= -DHAVE_NS_TYPE -DHAS_SPF -I${LOCALBASE}/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -lspf2 .endif .if ${PORT_OPTIONS:MBDB} INVALID_BDB_VER= 6 POSTFIX_CCARGS+= -I${BDB_INCLUDE_DIR} POSTFIX_AUXLIBS+= -L${BDB_LIB_DIR} -l${BDB_LIB_NAME} .endif .if ${PORT_OPTIONS:MMYSQL} POSTFIX_CCARGS+= -DHAS_MYSQL -I${LOCALBASE}/include/mysql POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib/mysql -lmysqlclient -lz -lcrypt -lm _REQUIRE+= mysql .endif .if ${PORT_OPTIONS:MPGSQL} POSTFIX_CCARGS+= -DHAS_PGSQL -I${LOCALBASE}/include -I${LOCALBASE}/pgsql/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -L${LOCALBASE}/pgsql/lib -lpq -lcrypt _REQUIRE+= postgresql .endif .if ${PORT_OPTIONS:MSQLITE} POSTFIX_CCARGS+= -DHAS_SQLITE -I${LOCALBASE}/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -lsqlite3 .endif .if ${PORT_OPTIONS:MLDAP} . if defined(WITH_OPENLDAP_VER) WANT_OPENLDAP_VER= ${WITH_OPENLDAP_VER} . endif POSTFIX_CCARGS+= -DHAS_LDAP -I${LOCALBASE}/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -lldap -llber _REQUIRE+= slapd . if ${PORT_OPTIONS:MLDAP_SASL} . if ! ${PORT_OPTIONS:MSASL} LIB_DEPENDS+= libsasl2.so:security/cyrus-sasl2 . endif WANT_OPENLDAP_SASL= yes POSTFIX_CCARGS+= -I${LOCALBASE}/include/sasl -DUSE_LDAP_SASL . endif .endif .if ${PORT_OPTIONS:MCDB} POSTFIX_CCARGS+= -DHAS_CDB -I${LOCALBASE}/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -lcdb .endif .if ${PORT_OPTIONS:MNIS} POSTFIX_CCARGS+= -DHAS_NIS _REQUIRE+= ypserv .endif .if ${PORT_OPTIONS:MVDA} -PATCH_SITES+= http://vda.sourceforge.net/VDA/:vda -PATCHFILES+= postfix-vda-v13-${VDAVERSION}.patch:-p1:vda +EXTRA_PATCHES+= ${FILESDIR}/extra-patch-postfix-vda-v13-2.11.x .endif .if ${PORT_OPTIONS:MTEST} BINTEST= qmqp-sink qmqp-source smtp-sink smtp-source MANTEST= qmqp-sink.1 qmqp-source.1 smtp-sink.1 smtp-source.1 .endif .if ${PORT_OPTIONS:MLMDB} POSTFIX_CCARGS+= -DHAS_LMDB -I${LOCALBASE}/include POSTFIX_AUXLIBS+= -L${LOCALBASE}/lib -llmdb .endif # sed script for files in ${WRKSRC}/README_FILES ${WRKSRC}/conf ${WRKSRC}/man REINPLACE= s!^PATH=.*!PATH=/bin:/sbin:/usr/bin:/usr/sbin:${PREFIX}/bin:${PREFIX}/sbin!;\ s!(_directory = )/usr/!\1${PREFIX}/!g;\ s!^(data_directory = /var/)lib/!\1db/!g;\ s!^\#(mynetworks_style = host)!\1!g;\ s!^(sendmail_path =)!\1 ${PREFIX}/sbin/sendmail!g;\ s!^(newaliases_path =)!\1 ${PREFIX}/bin/newaliases!g;\ s!^(mailq_path =)!\1 ${PREFIX}/bin/mailq!g;\ s!^(setgid_group =)!\1 maildrop!g;\ s!^(manpage_directory =)!\1 ${MANPREFIX}/man!g;\ s!^((html|readme)_directory =)!\1 ${READMEDIR}!g;\ \!^\#alias_database = dbm:/etc/mail/aliases$$!d;\ s!(:|= )/etc/postfix!\1$$config_directory!g;\ s!/etc/postfix!${ETCDIR}!g;\ s!^(sample_directory =)!\1 ${ETCDIR}!g;\ s!($config_directory/(access|aliases|canonical|generic|header_checks|relocated|transport|virtual):f:root:-:644:)p1!\1o!; pre-patch: .if ${PORT_OPTIONS:MSASL} && ! ${PORT_OPTIONS:MMYSQL} && exists(${LOCALBASE}/lib/libsasl2.a) @if /usr/bin/nm ${LOCALBASE}/lib/libsasl2.a | ${GREP} -wq "mysql_init"; then \ ${ECHO_MSG}; \ ${ECHO_MSG} "Your SASL library it's compiled with MYSQL"; \ ${ECHO_MSG} "If you use MYSQL in ${PORTNAME} consider CTRL+C and"; \ ${ECHO_MSG} "select MYSQL OPTION in config menu."; \ ${ECHO_MSG} "# make clean config"; \ ${ECHO_MSG}; \ sleep 5; \ fi .endif @${ECHO} 'See header_checks.5.html' \ > ${WRKSRC}/html/body_checks.5.html @${REINPLACE_CMD} -E -e 's!^(#define DEF_SGID_GROUP[^"]+)"postdrop"$$!\1"maildrop"!' \ ${WRKSRC}/src/global/mail_params.h @${FIND} -X ${WRKSRC}/README_FILES ${WRKSRC}/conf ${WRKSRC}/man \ -type f -a ! \( -name INSTALL -o -name aliases \) | ${XARGS} \ ${REINPLACE_CMD} -E -e '${REINPLACE}' post-patch: .for f in ${HTML1} @${ECHO} '$$html_directory/$f:f:root:-:644' \ >> ${WRKSRC}/conf/postfix-files .endfor @${ECHO} '$$manpage_directory/man1/posttls-finger.1:f:root:-:644' \ >> ${WRKSRC}/conf/postfix-files @${ECHO} '$$command_directory/posttls-finger:f:root:-:755' \ >> ${WRKSRC}/conf/postfix-files post-patch-SPF-on: @${ECHO} '$$readme_directory/SPF_README:f:root:-:644' \ >> ${WRKSRC}/conf/postfix-files @${REINPLACE_CMD} -E -e '${REINPLACE}' \ ${WRKSRC}/README_FILES/SPF_README post-patch-VDA-on: @${ECHO} '$$readme_directory/VDA_README:f:root:-:644' \ >> ${WRKSRC}/conf/postfix-files @${REINPLACE_CMD} -E -e '${REINPLACE}' \ ${WRKSRC}/README_FILES/VDA_README do-configure: (cd ${WRKSRC} && ${MAKE} -f Makefile.init makefiles \ ${MAKEFILEFLAGS} CCARGS="${POSTFIX_CCARGS}" \ AUXLIBS="${POSTFIX_AUXLIBS}" && \ ${ECHO} "all: default" >> Makefile) + +post-stage-VDA-on: + ${HEAD} -n 17 ${FILESDIR}/extra-patch-postfix-vda-v13-2.11.x >> ${WRKDIR}/pkg-message pre-install-INST_BASE-on: ${MKDIR} ${STAGEDIR}/etc/rc.d do-install: @(cd ${WRKSRC} && ${MAKE} non-interactive-package \ install_root=${STAGEDIR} tempdir=${WRKDIR} \ config_directory=${ETCDIR} \ command_directory=${PREFIX}/sbin \ daemon_directory=${DAEMONDIR} \ html_directory=${READMEDIR} \ mailq_path=${PREFIX}/bin/mailq \ manpage_directory=${MANPREFIX}/man \ newaliases_path=${PREFIX}/bin/newaliases \ readme_directory=${READMEDIR} \ sendmail_path=${PREFIX}/sbin/sendmail ) ${INSTALL_SCRIPT} ${WRKSRC}/auxiliary/rmail/rmail ${STAGEDIR}${PREFIX}/bin/rmail ${INSTALL_SCRIPT} ${WRKSRC}/auxiliary/qshape/qshape.pl ${STAGEDIR}${PREFIX}/bin/qshape ${INSTALL_MAN} ${WRKSRC}/man/man1/qshape.1 ${STAGEDIR}${MANPREFIX}/man/man1 # == do not overwrite existing config ${MV} ${STAGEDIR}${ETCDIR}/main.cf ${STAGEDIR}${ETCDIR}/main.cf.sample ${MV} ${STAGEDIR}${ETCDIR}/master.cf ${STAGEDIR}${ETCDIR}/master.cf.sample ${MKDIR} ${STAGEDIR}${DATADIR} ${INSTALL_DATA} ${WRKDIR}/mailer.conf.postfix ${STAGEDIR}${DATADIR} # Fix compressed man pages and strip executables ${SED} -i '' -E -e "s|(man[158]/.*.[158]):|\1.gz:|g" ${STAGEDIR}${DAEMONDIR}/postfix-files -@${STRIP_CMD} ${STRIP_LIBEXEC:S|^|${STAGEDIR}${DAEMONDIR}/|} -@${STRIP_CMD} ${STAGEDIR}${PREFIX}/sbin/* do-install-TEST-on: ${INSTALL_PROGRAM} ${BINTEST:S|^|${WRKSRC}/bin/|} ${STAGEDIR}${PREFIX}/bin ${INSTALL_MAN} ${MANTEST:S|^|${WRKSRC}/man/man1/|} ${STAGEDIR}${MANPREFIX}/man/man1 .include Index: head/mail/postfix211/distinfo =================================================================== --- head/mail/postfix211/distinfo (revision 447910) +++ head/mail/postfix211/distinfo (revision 447911) @@ -1,7 +1,7 @@ -TIMESTAMP = 1463402666 -SHA256 (postfix/postfix-2.11.8.tar.gz) = 3c4ece0846b519e2e800608f3009e929a3c2a1c7841bf07397ec9edc7463c923 -SIZE (postfix/postfix-2.11.8.tar.gz) = 4032263 +TIMESTAMP = 1383475619 +SHA256 (postfix/postfix-2.11.10.tar.gz) = 4d9dca8a6f08adcb70fc02a00bde0f8057f062bc16dfa32acd6bbec2b0ffb9dd +SIZE (postfix/postfix-2.11.10.tar.gz) = 4033890 SHA256 (postfix/postfix-2.8.0-libspf2-1.2.x-0.patch.gz) = e5c38e5bc226cab109c02a4e530ab1aefd3bb06f2169f3e052bdf83d2727aacc SIZE (postfix/postfix-2.8.0-libspf2-1.2.x-0.patch.gz) = 8191 SHA256 (postfix/postfix-vda-v13-2.10.0.patch) = 6208021eb0b37ac6482e334e538ed5700cc22c4d4dd66ed9e975ae5f20bf935f SIZE (postfix/postfix-vda-v13-2.10.0.patch) = 55701 Index: head/mail/postfix211/files/extra-patch-postfix-vda-v13-2.11.x =================================================================== --- head/mail/postfix211/files/extra-patch-postfix-vda-v13-2.11.x (nonexistent) +++ head/mail/postfix211/files/extra-patch-postfix-vda-v13-2.11.x (revision 447911) @@ -0,0 +1,1385 @@ + +VDA patch against postfix-2.11.10+ + +It seems the upstream VDA project is no longer maintained, the last +changes against postfix-2.x could also be archived by using the -p1 +parameter. This is an updated patch against 2.11.10 and it will be +the last VDA patch for the postfix ports. + +Users using the VDA patch should adopt dovecot-lda which has also quota +support. As alternative users can jump on the wagon and try to become +an active maintainer of the SF.net VDA project (or a fork) + +The 2.11 port will be deprecated at the time postfix-2.11.x is no longer +supported by the postfix author (Wietse Venema), this will happen with +the release of postfix-3.3.x. + +=========================================================================== +--- README_FILES/VDA_README.orig 1970-01-01 01:00:00.000000000 +0100 ++++ README_FILES/VDA_README +@@ -0,0 +1,10 @@ ++Postfix VDA patch for maildir++ quota support by ++ Anderson Nadal ++ Tomas Macek ++ Lucca Longinotti ++ ++See VDA patch official website http://vda.sf.net for instructions ++howto patch the Postfix's sourcetree and configure the options ++provided by this patch. ++ ++ +--- src/global/mail_params.h.orig 2017-08-13 09:19:28 UTC ++++ src/global/mail_params.h +@@ -2413,6 +2413,54 @@ extern char *var_virt_uid_maps; + #define DEF_VIRT_GID_MAPS "" + extern char *var_virt_gid_maps; + ++#define VAR_VIRT_MAILBOX_LIMIT_MAPS "virtual_mailbox_limit_maps" ++#define DEF_VIRT_MAILBOX_LIMIT_MAPS "" ++extern char *var_virt_mailbox_limit_maps; ++ ++#define VAR_VIRT_MAILBOX_LIMIT_INBOX "virtual_mailbox_limit_inbox" ++#define DEF_VIRT_MAILBOX_LIMIT_INBOX 0 ++extern bool var_virt_mailbox_limit_inbox; ++ ++#define VAR_VIRT_MAILBOX_LIMIT_OVERRIDE "virtual_mailbox_limit_override" ++#define DEF_VIRT_MAILBOX_LIMIT_OVERRIDE 0 ++extern bool var_virt_mailbox_limit_override; ++ ++#define VAR_VIRT_MAILDIR_EXTENDED "virtual_maildir_extended" ++#define DEF_VIRT_MAILDIR_EXTENDED 0 ++extern bool var_virt_maildir_extended; ++ ++#define VAR_VIRT_OVERQUOTA_BOUNCE "virtual_overquota_bounce" ++#define DEF_VIRT_OVERQUOTA_BOUNCE 0 ++extern bool var_virt_overquota_bounce; ++ ++#define VAR_VIRT_MAILDIR_LIMIT_MESSAGE "virtual_maildir_limit_message" ++#define DEF_VIRT_MAILDIR_LIMIT_MESSAGE "Sorry, the user's maildir has overdrawn his diskspace quota, please try again later." ++extern char *var_virt_maildir_limit_message; ++ ++#define VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS "virtual_maildir_limit_message_maps" ++#define DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS "" ++extern char *var_virt_maildir_limit_message_maps; ++ ++#define VAR_VIRT_MAILDIR_SUFFIX "virtual_maildir_suffix" ++#define DEF_VIRT_MAILDIR_SUFFIX "" ++extern char *var_virt_maildir_suffix; ++ ++#define VAR_VIRT_TRASH_COUNT "virtual_trash_count" ++#define DEF_VIRT_TRASH_COUNT 0 ++extern bool var_virt_trash_count; ++ ++#define VAR_VIRT_TRASH_NAME "virtual_trash_name" ++#define DEF_VIRT_TRASH_NAME ".Trash" ++extern char *var_virt_trash_name; ++ ++#define VAR_VIRT_MAILDIR_FILTER "virtual_maildir_filter" ++#define DEF_VIRT_MAILDIR_FILTER 0 ++extern bool var_virt_maildir_filter; ++ ++#define VAR_VIRT_MAILDIR_FILTER_MAPS "virtual_maildir_filter_maps" ++#define DEF_VIRT_MAILDIR_FILTER_MAPS "" ++extern char *var_virt_maildir_filter_maps; ++ + #define VAR_VIRT_MINUID "virtual_minimum_uid" + #define DEF_VIRT_MINUID 100 + extern int var_virt_minimum_uid; +--- src/util/file_limit.c.orig 2003-10-22 18:48:36 UTC ++++ src/util/file_limit.c +@@ -85,7 +85,11 @@ void set_file_limit(off_t limit) + #else + struct rlimit rlim; + +- rlim.rlim_cur = rlim.rlim_max = limit; ++ /* rlim_max can only be changed by root. */ ++ if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) ++ msg_fatal("getrlimit: %m"); ++ rlim.rlim_cur = limit; ++ + if (setrlimit(RLIMIT_FSIZE, &rlim) < 0) + msg_fatal("setrlimit: %m"); + #ifdef SIGXFSZ +--- src/virtual/mailbox.c.orig 2016-08-22 21:24:31 UTC ++++ src/virtual/mailbox.c +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + + /* Global library. */ + +@@ -70,6 +71,70 @@ + #define YES 1 + #define NO 0 + ++/* change_mailbox_limit - change limit for mailbox file */ ++static int change_mailbox_limit(LOCAL_STATE state, USER_ATTR usr_attr) ++{ ++ char *myname = "change_mailbox_limit"; ++ const char *limit_res; ++ long n = 0; ++ int status = NO; ++ ++ /* ++ * Look up the virtual mailbox limit size for this user. ++ * Fall back to virtual_mailbox_limit in case lookup failed. ++ * If virtual mailbox limit size is negative, fall back to virtual_mailbox_limit. ++ * If it's 0, set the mailbox limit to 0, which means unlimited. ++ * If it's more than 0 (positive int), check if the value is smaller than the maximum message size, ++ * if it is and the virtual mailbox limit can't be overridden, fall back to virtual_mailbox_limit and ++ * warn the user, else use the value directly as the mailbox limit. ++ */ ++ if (*var_virt_mailbox_limit_maps != 0 && (limit_res = mail_addr_find(virtual_mailbox_limit_maps, state.msg_attr.user, (char **) NULL)) != 0) { ++ n = atol(limit_res); ++ if (n > 0) { ++ if ((n < var_message_limit) && (!var_virt_mailbox_limit_override)) { ++ set_file_limit(var_virt_mailbox_limit); ++ status = NO; ++ ++ msg_warn("%s: recipient %s - virtual mailbox limit is " ++ "smaller than %s in %s - falling back to %s", ++ myname, ++ state.msg_attr.user, ++ VAR_MESSAGE_LIMIT, ++ virtual_mailbox_limit_maps->title, ++ VAR_VIRT_MAILBOX_LIMIT); ++ } ++ else { ++ set_file_limit((off_t) n); ++ status = YES; ++ ++ if (msg_verbose) ++ msg_info("%s: set virtual mailbox limit size for %s to %ld", ++ myname, usr_attr.mailbox, n); ++ } ++ } ++ else if (n == 0) { ++ set_file_limit(OFF_T_MAX); ++ status = YES; ++ ++ if (msg_verbose) ++ msg_info("%s: set virtual mailbox limit size for %s to %ld", ++ myname, usr_attr.mailbox, OFF_T_MAX); ++ } ++ else { ++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */ ++ set_file_limit(var_virt_mailbox_limit); ++ status = NO; ++ } ++ } ++ else { ++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */ ++ set_file_limit(var_virt_mailbox_limit); ++ status = NO; ++ } ++ ++ return(status); ++} ++ + /* deliver_mailbox_file - deliver to recipient mailbox */ + + static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr) +@@ -214,62 +279,72 @@ int deliver_mailbox(LOCAL_STATE stat + * Look up the mailbox owner rights. Defer in case of trouble. + */ + uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user, +- IGNORE_EXTENSION); +- if (uid_res == 0) { +- msg_warn("recipient %s: not found in %s", +- state.msg_attr.user, virtual_uid_maps->title); +- dsb_simple(why, "4.3.5", "mail system configuration error"); +- *statusp = defer_append(BOUNCE_FLAGS(state.request), +- BOUNCE_ATTR(state.msg_attr)); +- RETURN(YES); ++ IGNORE_EXTENSION); ++ ++ if ((uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user, (char **) 0)) == 0) { ++ if ((uid_res = maps_find(virtual_uid_maps, strchr(state.msg_attr.user, '@'), DICT_FLAG_FIXED)) == 0) { ++ msg_warn("recipient %s: not found in %s", state.msg_attr.user, virtual_uid_maps->title); ++ dsb_simple(why, "4.3.5", "mail system configuration error"); ++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); ++ RETURN(YES); ++ } + } ++ + if ((n = atol(uid_res)) < var_virt_minimum_uid) { +- msg_warn("recipient %s: bad uid %s in %s", +- state.msg_attr.user, uid_res, virtual_uid_maps->title); +- dsb_simple(why, "4.3.5", "mail system configuration error"); +- *statusp = defer_append(BOUNCE_FLAGS(state.request), +- BOUNCE_ATTR(state.msg_attr)); +- RETURN(YES); ++ msg_warn("recipient %s: bad uid %s in %s", state.msg_attr.user, uid_res, virtual_uid_maps->title); ++ dsb_simple(why, "4.3.5", "mail system configuration error"); ++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); ++ RETURN(YES); + } ++ + usr_attr.uid = (uid_t) n; + + /* + * Look up the mailbox group rights. Defer in case of trouble. + */ + gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user, +- IGNORE_EXTENSION); +- if (gid_res == 0) { +- msg_warn("recipient %s: not found in %s", +- state.msg_attr.user, virtual_gid_maps->title); +- dsb_simple(why, "4.3.5", "mail system configuration error"); +- *statusp = defer_append(BOUNCE_FLAGS(state.request), +- BOUNCE_ATTR(state.msg_attr)); +- RETURN(YES); ++ IGNORE_EXTENSION); ++ ++ if ((gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user, (char **) 0)) == 0) { ++ if ((gid_res = maps_find(virtual_gid_maps, strchr(state.msg_attr.user, '@'), DICT_FLAG_FIXED)) == 0) { ++ msg_warn("recipient %s: not found in %s", state.msg_attr.user, virtual_gid_maps->title); ++ dsb_simple(why, "4.3.5", "mail system configuration error"); ++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); ++ RETURN(YES); ++ } + } ++ + if ((n = atol(gid_res)) <= 0) { +- msg_warn("recipient %s: bad gid %s in %s", +- state.msg_attr.user, gid_res, virtual_gid_maps->title); +- dsb_simple(why, "4.3.5", "mail system configuration error"); +- *statusp = defer_append(BOUNCE_FLAGS(state.request), +- BOUNCE_ATTR(state.msg_attr)); +- RETURN(YES); ++ msg_warn("recipient %s: bad gid %s in %s", state.msg_attr.user, gid_res, virtual_gid_maps->title); ++ dsb_simple(why, "4.3.5", "mail system configuration error"); ++ *statusp = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); ++ RETURN(YES); + } ++ + usr_attr.gid = (gid_t) n; + + if (msg_verbose) +- msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u", +- myname, state.level, usr_attr.mailbox, +- (unsigned) usr_attr.uid, (unsigned) usr_attr.gid); ++ msg_info("%s[%d]: set user_attr: %s, uid = %u, gid = %u", ++ myname, state.level, usr_attr.mailbox, ++ (unsigned) usr_attr.uid, (unsigned) usr_attr.gid); + + /* + * Deliver to mailbox or to maildir. + */ + #define LAST_CHAR(s) (s[strlen(s) - 1]) + +- if (LAST_CHAR(usr_attr.mailbox) == '/') +- *statusp = deliver_maildir(state, usr_attr); +- else +- *statusp = deliver_mailbox_file(state, usr_attr); ++ if (LAST_CHAR(usr_attr.mailbox) == '/') { ++ *statusp = deliver_maildir(state, usr_attr); ++ } ++ else { ++ int changed_limit; ++ ++ changed_limit = change_mailbox_limit(state, usr_attr); ++ *statusp = deliver_mailbox_file(state, usr_attr); ++ ++ if (changed_limit) ++ set_file_limit(var_virt_mailbox_limit); ++ } + + /* + * Cleanup. +--- src/virtual/maildir.c.orig 2012-01-25 00:41:08 UTC ++++ src/virtual/maildir.c +@@ -64,28 +64,420 @@ + #include + #include + ++/* Patch library. */ ++ ++#include /* opendir(3), stat(2) */ ++#include /* stat(2) */ ++#include /* opendir(3) */ ++#include /* stat(2) */ ++#include /* atol(3) */ ++#include /* strrchr(3) */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ + /* Application-specific. */ + + #include "virtual.h" + +-/* deliver_maildir - delivery to maildir-style mailbox */ ++/* Maildirsize maximal size. */ + +-int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) ++#define SIZEFILE_MAX 5120 ++ ++/* ++ * Chris Stratford ++ * Read the maildirsize file to get quota info. ++ * ++ * Arguments: ++ * dirname: the maildir ++ * countptr: number of messages ++ * ++ * Returns the size of all mails as read from maildirsize, ++ * zero if it couldn't read the file. ++ */ ++static long read_maildirsize(char *filename, long *sumptr, long *countptr) ++{ ++ char *myname = "read_maildirsize"; ++ struct stat statbuf; ++ VSTREAM *sizefile; ++ char *p; ++ int len, first; ++ long sum = 0, count = 0, ret_value = -1; ++ ++ if (msg_verbose) ++ msg_info("%s: we will use sizefile = '%s'", myname, filename); ++ ++ sizefile = vstream_fopen(filename, O_RDONLY, 0); ++ if (!sizefile) { ++ if (msg_verbose) ++ msg_info("%s: cannot open %s: %m (maybe file does not exist)", myname, filename); ++ ++ return -1; ++ } else if (stat(filename, &statbuf) < 0 || statbuf.st_size > SIZEFILE_MAX) { ++ if (sizefile) { ++ vstream_fclose(sizefile); ++ unlink(filename); ++ } ++ ++ if (msg_verbose) ++ msg_info("%s: stat() returned < 0 or filesize > SIZEFILE_MAX (filename = %s, filesize = %ld)", myname, filename, statbuf.st_size); ++ ++ return -1; ++ } ++ ++ VSTRING *sizebuf = vstring_alloc(SIZEFILE_MAX); ++ len = vstream_fread(sizefile, STR(sizebuf), SIZEFILE_MAX); ++ ++ p = STR(sizebuf); ++ *(p + len) = '\0'; ++ first = 1; ++ ++ while (*p) { ++ long n = 0, c = 0; ++ char *q = p; ++ ++ while (*p) { ++ if (*p++ == '\n') { ++ p[-1] = 0; ++ break; ++ } ++ } ++ ++ if (first) { ++ first = 0; ++ continue; ++ } ++ ++ if (sscanf(q, "%ld %ld", &n, &c) == 2) { ++ sum += n; ++ count += c; ++ /* if (msg_verbose) ++ msg_info("%s: we read line '%s', totals: sum = %ld, count = %ld", myname, q, sum, count); */ ++ } ++ else { ++ vstream_fclose(sizefile); ++ unlink(filename); ++ msg_warn("%s: invalid line '%s' found in %s, removing maildirsize file", myname, q, filename); ++ vstring_free(sizebuf); ++ ++ return -1; ++ } ++ } ++ ++ *countptr = count; ++ *sumptr = sum; ++ ++ if (sum < 0 || count < 0 || (sum == 0 && count != 0) || (sum != 0 && count == 0)) { ++ if (msg_verbose) { ++ msg_info("%s: we will return -1 and unlink %s, because file count or sum is <= 0 (sum = %ld, count = %ld)", myname, filename, sum, count); ++ } ++ ++ unlink(filename); ++ ret_value = -1; ++ } else { ++ if (msg_verbose) ++ msg_info("%s: we will return Maildir size = %ld, count = %ld", myname, *sumptr, *countptr); ++ ++ ret_value = sum; ++ } ++ ++ vstream_fclose(sizefile); ++ vstring_free(sizebuf); ++ ++ return ret_value; ++} ++ ++/* ++ * Gives the size of the file according to the Maildir++ extension ++ * present in the filename (code taken from courier-imap). ++ * ++ * Arguments: ++ * n: filename ++ * ++ * Returns the size given in ",S=" in the filename, ++ * zero if it cannot find ",S=" in the filename. ++ */ ++static long maildir_parsequota(const char *n) ++{ ++ const char *o; ++ int yes = 0; ++ ++ if ((o = strrchr(n, '/')) == 0) ++ o = n; ++ ++ for (; *o; o++) { ++ if (*o == ':') ++ break; ++ } ++ ++ for (; o >= n; --o) { ++ if (*o == '/') ++ break; ++ ++ if (*o == ',' && o[1] == 'S' && o[2] == '=') { ++ yes = 1; ++ o += 3; ++ break; ++ } ++ } ++ ++ if (yes) { ++ long s = 0; ++ ++ while (*o >= '0' && *o <= '9') ++ s = s*10 + (*o++ - '0'); ++ ++ return s; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Computes quota usage for a directory (taken from exim). ++ * ++ * This function is called to determine the exact quota usage of a virtual ++ * maildir box. To achieve maximum possible speed while doing this, it takes ++ * advantage of the maildirsize file and the Maildir++ extensions to filenames, ++ * when applicable and configured to be used. In all other cases it simply ++ * stats all the files as needed to get the size information. ++ * ++ * Arguments: ++ * dirname: the name of the directory ++ * countptr: where to add the file count (because this function recurses) ++ * ++ * Returns the sum of the sizes of all measurable files, ++ * zero if the directory could not be opened. ++ */ ++static long check_dir_size(char *dirname, long *countptr) ++{ ++ char *myname = "check_dir_size"; ++ DIR *dir; ++ long sum = 0; ++ struct dirent *ent; ++ struct stat statbuf; ++ ++ dir = opendir(dirname); ++ if (dir == NULL) { ++ if (make_dirs(dirname, 0700) == 0) { /* Try to create the dirs. */ ++ dir = opendir(dirname); /* Reopen the dir. */ ++ if (dir == NULL) { ++ msg_warn("%s: cannot reopen directory: %s", myname, dirname); ++ return 0; ++ } ++ } ++ else { ++ msg_warn("%s: cannot open directory: %s", myname, dirname); ++ return 0; ++ } ++ } ++ ++ while ((ent = readdir(dir)) != NULL) { ++ char *name = ent->d_name; ++ long tmpsum = 0; ++ VSTRING *buffer; ++ ++ /* do not count dot a double-dot dirs */ ++ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) ++ continue; ++ /* do not count if this is the trash subdir and if we should NOT count it */ ++ else if (var_virt_trash_count == 0 && strcmp(name, var_virt_trash_name) == 0) ++ continue; ++ ++ /* ++ * Here comes the real logic behind this function. ++ * Optimized to be the most efficient possible, ++ * depending on the settings given. ++ * See above for a more detailed description. ++ */ ++ if (var_virt_mailbox_limit_inbox) { ++ if (var_virt_maildir_extended && (tmpsum = maildir_parsequota(name))) { ++ sum += tmpsum; ++ (*countptr)++; ++ } ++ else { ++ buffer = vstring_alloc(1024); ++ vstring_sprintf(buffer, "%s/%s", dirname, name); ++ ++ if (stat(STR(buffer), &statbuf) < 0) { ++ vstring_free(buffer); ++ continue; ++ } ++ if ((statbuf.st_mode & S_IFREG) != 0) { ++ sum += (long) statbuf.st_size; ++ (*countptr)++; ++ } ++ ++ vstring_free(buffer); ++ } ++ } ++ else { ++ buffer = vstring_alloc(1024); ++ vstring_sprintf(buffer, "%s/%s", dirname, name); ++ ++ if (stat(STR(buffer), &statbuf) < 0) { ++ vstring_free(buffer); ++ continue; ++ } ++ if ((statbuf.st_mode & S_IFREG) != 0) { ++ if (strcmp(dirname + strlen(dirname) - 3, "new") == 0 || strcmp(dirname + strlen(dirname) - 3, "cur") == 0 || strcmp(dirname + strlen(dirname) - 3, "tmp") == 0) { ++ sum += (long) statbuf.st_size; ++ (*countptr)++; ++ } ++ } ++ else if ((statbuf.st_mode & S_IFDIR) != 0) { ++ sum += check_dir_size(STR(buffer), countptr); ++ } ++ ++ vstring_free(buffer); ++ } ++ } ++ closedir(dir); ++ ++ if (msg_verbose) ++ msg_info("%s: full scan done: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); ++ ++ return sum; ++} ++ ++/* Cut all occurrences of pattern from string. */ ++static char *strcut(char *str, const char *pat) ++{ ++ char *ptr, *loc, *ret; ++ ret = str; ++ loc = str; ++ ++ /* No match, return original string. */ ++ if (!strstr(loc, pat)) ++ return(str); ++ ++ while (*loc && (ptr = strstr(loc, pat))) { ++ while (loc < ptr) ++ *str++ = *loc++; ++ loc += strlen(pat); ++ } ++ ++ while (*loc) ++ *str++ = *loc++; ++ ++ *str = 0; ++ ++ return(ret); ++} ++ ++/* Check if maildirfilter file is up-to-date compared to SQL, (re)write it if not. */ ++static long sql2file(char *filename, char *user) ++{ ++ char *myname = "sql2file"; ++ char *filter_sqlres; ++ char filter_fileres[128]; ++ long sqlmtime = 0, filemtime = 0, retval = 0; ++ int filterfile, size_sqlres, i; ++ struct stat statbuf; ++ ++ if (*var_virt_maildir_filter_maps != 0) { ++ filter_sqlres = (char *) mymalloc(16000); ++ filter_sqlres = (char *) mail_addr_find(virtual_maildir_filter_maps, user, (char **) 0); ++ ++ if (filter_sqlres) { ++ strcut(filter_sqlres, "\r"); ++ if (filter_sqlres[0] == '#' && filter_sqlres[1] == ' ' && filter_sqlres[2] == 'M') { ++ size_sqlres = strlen(filter_sqlres); ++ ++ for (i = 4; i <= size_sqlres; i++) { ++ if(filter_sqlres[i] == '/' && filter_sqlres[i+1] == '^') { ++ filter_sqlres[i-1] = '\n'; ++ } ++ } ++ ++ filter_sqlres[(size_sqlres+1)] = '\0'; ++ ++ sqlmtime = atol(filter_sqlres+3); ++ retval = sqlmtime; ++ ++ filterfile = open(filename, O_RDONLY, 0); ++ if (filterfile) { ++ read(filterfile, (void *) filter_fileres, 127); ++ close(filterfile); ++ ++ filemtime = atol(filter_fileres+3); ++ } ++ ++ if (msg_verbose) ++ msg_info("%s: filter data: sql_size=%li sql_mtime=%ld file_mtime=%ld", myname, strlen(filter_sqlres), sqlmtime, filemtime); ++ } ++ if (sqlmtime != filemtime && sqlmtime != 0) { ++ if ((filterfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640))) { ++ if (msg_verbose) ++ msg_info("%s: updating filter file: %s", myname, filename); ++ write(filterfile, filter_sqlres, strlen(filter_sqlres)); ++ close(filterfile); ++ } ++ else { ++ msg_warn("%s: can't create filter file: %s", myname, filename); ++ retval = 0; ++ } ++ } ++ } ++ } ++ else { ++ if (stat(filename, &statbuf) == 0) ++ retval = (long) statbuf.st_mtime; ++ if (msg_verbose) ++ msg_info("%s: processing filter file: file_mtime=%ld", myname, retval); ++ } ++ ++ return retval; ++} ++ ++/* deliver_maildir - delivery to maildir-style mailbox */ ++int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) + { + const char *myname = "deliver_maildir"; +- char *newdir; +- char *tmpdir; +- char *curdir; +- char *tmpfile; +- char *newfile; ++ char *newdir; ++ char *tmpdir; ++ char *curdir; ++ char *newfile; ++ char *tmpfile; + DSN_BUF *why = state.msg_attr.why; + VSTRING *buf; + VSTREAM *dst; +- int mail_copy_status; +- int deliver_status; +- int copy_flags; +- struct stat st; +- struct timeval starttime; ++ int mail_copy_status; ++ int deliver_status; ++ int copy_flags; ++ struct stat st; ++ struct timeval starttime; ++ ++ /* Maildir Quota. */ ++ const char *limit_res; /* Limit from map. */ ++ char *sizefilename = (char *) 0; /* Maildirsize file name. */ ++ VSTRING *filequota; /* Quota setting from the maildirsize file. */ ++ VSTREAM *sizefile; /* Maildirsize file handle. */ ++ long n = 0; /* Limit in long integer format. */ ++ long saved_count = 0; /* The total number of files. */ ++ long saved_size = 0; /* The total quota of all files. */ ++ struct stat mail_stat; /* To check the size of the mail to be written. */ ++ struct stat sizefile_stat; /* To check the size of the maildirsize file. */ ++ time_t tm; /* To check the age of the maildirsize file. */ ++ ++ /* Maildir Filters. */ ++ const char *value, *cmd_text; /* Filter values. */ ++ char *filtername; ++ char *header; ++ char *bkpnewfile; ++ char *mdffilename = (char *) 0; /* Maildirfolder file name. */ ++ VSTRING *fltstr; ++ VSTREAM *tmpfilter; ++ VSTREAM *mdffile; /* Maildirfolder file handle. */ ++ DICT *FILTERS; ++ long sqlmtime; /* Latest modification time from sql2file(). */ ++ int cmd_len; ++ int read_mds = -1; /* read_maildirsize() returned value */ ++ struct stat mdffile_stat; /* To check if the maildirfolder file exists. */ + + GETTIMEOFDAY(&starttime); + +@@ -94,15 +486,14 @@ int deliver_maildir(LOCAL_STATE stat + */ + state.level++; + if (msg_verbose) +- MSG_LOG_STATE(myname, state); ++ MSG_LOG_STATE(myname, state); + + /* + * Don't deliver trace-only requests. + */ + if (DEL_REQ_TRACE_ONLY(state.request->flags)) { +- dsb_simple(why, "2.0.0", "delivers to maildir"); +- return (sent(BOUNCE_FLAGS(state.request), +- SENT_ATTR(state.msg_attr))); ++ dsb_simple(why, "2.0.0", "delivers to maildir"); ++ return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr))); + } + + /* +@@ -110,18 +501,116 @@ int deliver_maildir(LOCAL_STATE stat + * attribute to reflect the final recipient. + */ + if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0) +- msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp)); ++ msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp)); + state.msg_attr.delivered = state.msg_attr.rcpt.address; + mail_copy_status = MAIL_COPY_STAT_WRITE; + buf = vstring_alloc(100); + +- copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH +- | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT; ++ copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH | MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT; + +- newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0); +- tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0); +- curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0); ++ /* ++ * Concatenate the maildir suffix (if set). ++ */ ++ if (*var_virt_maildir_suffix == 0) { ++ newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0); ++ tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0); ++ curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0); ++ } ++ else { ++ newdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); ++ tmpdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); ++ curdir = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); ++ newdir = concatenate(newdir, "new/", (char *) 0); ++ tmpdir = concatenate(tmpdir, "tmp/", (char *) 0); ++ curdir = concatenate(curdir, "cur/", (char *) 0); ++ } ++ ++ /* get the sizefilename, no matter if we use var_virt_maildir_extended */ ++ if (*var_virt_maildir_suffix == 0) { ++ sizefilename = concatenate(usr_attr.mailbox, "maildirsize", (char *) 0); ++ } else { ++ sizefilename = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); ++ sizefilename = concatenate(sizefilename, "maildirsize", (char *) 0); ++ } ++ ++ /* ++ * Look up the virtual maildir limit size for this user. ++ * Fall back to virtual_mailbox_limit in case lookup failed. ++ * If virtual maildir limit size is negative, fall back to virtual_mailbox_limit. ++ * If it's 0, set the mailbox limit to 0, which means unlimited. ++ * If it's more than 0 (positive int), check if the value is smaller than the maximum message size, ++ * if it is and the virtual maildir limit can't be overridden, fall back to virtual_mailbox_limit and ++ * warn the user, else use the value directly as the maildir limit. ++ */ ++ if (*var_virt_mailbox_limit_maps != 0 && (limit_res = mail_addr_find(virtual_mailbox_limit_maps, state.msg_attr.user, (char **) NULL)) != 0) { ++ n = atol(limit_res); ++ if (n > 0) { ++ if ((n < var_message_limit) && (!var_virt_mailbox_limit_override)) { ++ n = var_virt_mailbox_limit; ++ ++ msg_warn("%s: recipient %s - virtual maildir limit is smaller than %s in %s - falling back to %s", ++ myname, state.msg_attr.user, VAR_MESSAGE_LIMIT, virtual_mailbox_limit_maps->title, ++ VAR_VIRT_MAILBOX_LIMIT); ++ } ++ else { ++ if (msg_verbose) ++ msg_info("%s: set virtual maildir limit size for %s to %ld", ++ myname, usr_attr.mailbox, n); ++ } ++ } ++ else if (n == 0) { ++ if (msg_verbose) ++ msg_info("%s: set virtual maildir limit size for %s to %ld", ++ myname, usr_attr.mailbox, n); ++ } ++ else { ++ if (msg_verbose) ++ msg_info("%s: quota is negative (%ld), using default virtual_mailbox_limit (%ld)", ++ myname, n, var_virt_mailbox_limit); ++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */ ++ n = var_virt_mailbox_limit; ++ } ++ } ++ else { ++ if (msg_verbose) ++ msg_info("%s: no limit found in the maps, using default virtual_mailbox_limit (%ld)", ++ myname, var_virt_mailbox_limit); ++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */ ++ n = var_virt_mailbox_limit; ++ } + ++ /* If there should is a quota on maildir generaly, check it before delivering the mail */ ++ if (n != 0) { ++ set_eugid(usr_attr.uid, usr_attr.gid); ++ /* try to read the quota from maildirsize file. Returned values by read_maildirsize: ++ x < 0 = something failed ++ x >= 0 = reading successfully finished - sum si returned, so sum size of Maildir was 0 or more */ ++ if (!var_virt_mailbox_limit_inbox && var_virt_maildir_extended && (read_mds = read_maildirsize(sizefilename, &saved_size, &saved_count)) >= 0) { ++ if (msg_verbose) ++ msg_info("%s: maildirsize used=%s sum=%ld count=%ld", myname, sizefilename, saved_size, saved_count); ++ } else { ++ if (msg_verbose) ++ msg_info("%s: We will recount the quota (var_virt_mailbox_limit = %ld, var_virt_maildir_extended = %d, read_maildirsize = %d)", ++ myname, var_virt_mailbox_limit, var_virt_maildir_extended, read_mds); ++ ++ /* sanity */ ++ saved_size = 0; ++ saved_count = 0; ++ ++ if (var_virt_mailbox_limit_inbox) { ++ /* Check Inbox only (new, cur and tmp dirs). */ ++ saved_size = check_dir_size(newdir, &saved_count); ++ saved_size += check_dir_size(curdir, &saved_count); ++ saved_size += check_dir_size(tmpdir, &saved_count); ++ } else { ++ /* Check all boxes. */ ++ saved_size = check_dir_size(usr_attr.mailbox, &saved_count); ++ } ++ ++ set_eugid(var_owner_uid, var_owner_gid); ++ } ++ } ++ + /* + * Create and write the file as the recipient, so that file quota work. + * Create any missing directories on the fly. The file name is chosen +@@ -175,46 +664,288 @@ int deliver_maildir(LOCAL_STATE stat + * [...] + */ + set_eugid(usr_attr.uid, usr_attr.gid); +- vstring_sprintf(buf, "%lu.P%d.%s", +- (unsigned long) starttime.tv_sec, var_pid, get_hostname()); ++ vstring_sprintf(buf, "%lu.P%d.%s", (unsigned long) starttime.tv_sec, var_pid, get_hostname()); + tmpfile = concatenate(tmpdir, STR(buf), (char *) 0); + newfile = 0; ++ bkpnewfile = 0; + if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0 +- && (errno != ENOENT +- || make_dirs(tmpdir, 0700) < 0 +- || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) { +- dsb_simple(why, mbox_dsn(errno, "4.2.0"), +- "create maildir file %s: %m", tmpfile); +- } else if (fstat(vstream_fileno(dst), &st) < 0) { ++ && (errno != ENOENT ++ || make_dirs(tmpdir, 0700) < 0 ++ || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) { ++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", tmpfile); ++ } ++ else if (fstat(vstream_fileno(dst), &st) < 0) { ++ /* ++ * Coverity 200604: file descriptor leak in code that never executes. ++ * Code replaced by msg_fatal(), as it is not worthwhile to continue ++ * after an impossible error condition. ++ */ ++ msg_fatal("fstat %s: %m", tmpfile); ++ } ++ else { ++ vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s", ++ (unsigned long) starttime.tv_sec, ++ (unsigned long) st.st_dev, ++ (unsigned long) st.st_ino, ++ (unsigned long) starttime.tv_usec, ++ get_hostname()); ++ newfile = concatenate(newdir, STR(buf), (char *) 0); ++ bkpnewfile = concatenate(STR(buf), (char *) 0); /* Will need it later, if we MOVE to other folders. */ + +- /* +- * Coverity 200604: file descriptor leak in code that never executes. +- * Code replaced by msg_fatal(), as it is not worthwhile to continue +- * after an impossible error condition. +- */ +- msg_fatal("fstat %s: %m", tmpfile); +- } else { +- vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s", +- (unsigned long) starttime.tv_sec, +- (unsigned long) st.st_dev, +- (unsigned long) st.st_ino, +- (unsigned long) starttime.tv_usec, +- get_hostname()); +- newfile = concatenate(newdir, STR(buf), (char *) 0); +- if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), +- dst, copy_flags, "\n", +- why)) == 0) { +- if (sane_link(tmpfile, newfile) < 0 +- && (errno != ENOENT +- || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0 +- || sane_link(tmpfile, newfile) < 0)) { +- dsb_simple(why, mbox_dsn(errno, "4.2.0"), +- "create maildir file %s: %m", newfile); +- mail_copy_status = MAIL_COPY_STAT_WRITE; +- } +- } +- if (unlink(tmpfile) < 0) +- msg_warn("remove %s: %m", tmpfile); ++ if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) { ++ /* ++ * Add a ",S=" to the newly written file according to the ++ * Maildir++ specifications: http://www.inter7.com/courierimap/README.maildirquota.html ++ * This needs a stat(2) of the tempfile and modification of the ++ * name of the file. ++ */ ++ if (stat(tmpfile, &mail_stat) == 0) { ++ if (n != 0) { ++ saved_size += (long) mail_stat.st_size; ++ saved_count++; ++ } ++ if (var_virt_maildir_extended) { ++ /* Append the size of the file to newfile. */ ++ vstring_sprintf(buf, ",S=%ld", (long) mail_stat.st_size); ++ newfile = concatenate(newfile, STR(buf), (char *) 0); ++ bkpnewfile = concatenate(bkpnewfile, STR(buf), (char *) 0); ++ } ++ } ++ ++ /* ++ * Now we have the maildir size in saved_size, compare it to the max ++ * quota value and eventually issue a message that we've overdrawn it. ++ */ ++ if (saved_size > n) { ++ mail_copy_status = MAIL_COPY_STAT_WRITE; ++ if (((long) mail_stat.st_size > n) || (var_virt_overquota_bounce)) ++ errno = EFBIG; ++ else ++ errno = EDQUOT; ++ } ++ else { ++ /* Maildirfilter code by rk@demiurg.net. */ ++ if (var_virt_maildir_filter) { ++ if (msg_verbose) ++ msg_info("%s: loading DICT filters", myname); ++ ++#define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0) ++#define MAIL_COPY_STAT_REJECT (1<<3) ++#define MAIL_COPY_STAT_DISCARD (1<<4) ++ ++ /* Read filters. */ ++ filtername = concatenate("regexp:", usr_attr.mailbox, "maildirfilter", (char *) 0); ++ sqlmtime = sql2file(strchr(filtername, '/'), state.msg_attr.user); ++ ++ /* Check if this filter is already registered as dictionary. */ ++ if (msg_verbose) ++ msg_info("%s: checking DICT filters for %s", myname, filtername); ++ ++ if ((FILTERS = dict_handle(filtername))) { ++ if (msg_verbose) ++ msg_info("%s: DICT filter found", myname); ++ ++ /* ++ * If we have mtime in our DICT structure, check it against sqlmtime ++ * and reload the filters if they differ. ++ */ ++ if (FILTERS->mtime > 0 && sqlmtime > 0 && FILTERS->mtime != sqlmtime) { ++ if (msg_verbose) ++ msg_info("%s: reloading DICT filters (dict_mtime=%ld != sql_mtime=%ld)", ++ myname, FILTERS->mtime, sqlmtime); ++ ++ dict_unregister(filtername); ++ FILTERS = dict_open(filtername, O_RDONLY, DICT_FLAG_LOCK); ++ dict_register(filtername, FILTERS); ++ FILTERS->mtime = sqlmtime; ++ } ++ } ++ else { ++ if (sqlmtime > 0) { ++ /* Registering filter as new dictionary. */ ++ if (msg_verbose) ++ msg_info("%s: loading DICT filters from %s (mtime=%ld)", ++ myname, filtername, sqlmtime); ++ ++ FILTERS = dict_open(filtername, O_RDONLY, DICT_FLAG_LOCK); ++ dict_register(filtername, FILTERS); ++ FILTERS->mtime = sqlmtime; ++ } ++ } ++ ++ if (FILTERS && (tmpfilter = vstream_fopen(tmpfile, O_RDONLY, 0))) { ++ fltstr = vstring_alloc(1024); ++ header = (char *) malloc(8192); /* !!!INSECURE!!! See 7168-hack below. */ ++ header[0] = 0; ++ vstring_get_nonl_bound(fltstr, tmpfilter, 1023); ++ header = concatenate(header, STR(fltstr), (char *) 0); ++ ++ while(!vstream_feof(tmpfilter) && fltstr->vbuf.data[0] && strlen(header) < 7168 ) { ++ vstring_get_nonl_bound(fltstr, tmpfilter, 1023); ++ /* Glue multiline headers, replacing leading TAB with space. */ ++ if (msg_verbose) ++ msg_info("%s: fltstr value: %s", myname, STR(fltstr)); ++ ++ if (fltstr->vbuf.data[0] == ' ' || fltstr->vbuf.data[0] == '\t' ) { ++ if (fltstr->vbuf.data[0] == '\t') ++ fltstr->vbuf.data[0] = ' '; ++ header = concatenate(header, STR(fltstr), (char *) 0); ++ } ++ else { ++ header = concatenate(header, "\n", STR(fltstr), (char *) 0); ++ } ++ } ++ ++ if (msg_verbose) ++ msg_info("%s: checking filter CMD for %s", myname, filtername); ++ ++ /* Check whole header part with regexp maps. */ ++ if ((value = dict_get(FILTERS, lowercase(header))) != 0) { ++ if (msg_verbose) ++ msg_info("%s: preparing filter CMD", myname); ++ ++ cmd_text = value + strcspn(value, " \t"); ++ cmd_len = cmd_text - value; ++ while (*cmd_text && ISSPACE(*cmd_text)) ++ cmd_text++; ++ ++ if (msg_verbose) ++ msg_info("%s: executing filter CMD", myname); ++ ++ if (STREQUAL(value, "REJECT", cmd_len)) { ++ if (msg_verbose) ++ msg_info("%s: executing filter CMD REJECT", myname); ++ ++ mail_copy_status = MAIL_COPY_STAT_REJECT; ++ vstring_sprintf(why->reason, "%s", cmd_text); ++ dsb_simple(why, "5.0.0", "User filter - REJECT"); ++ } ++ ++ if (STREQUAL(value, "DISCARD", cmd_len)) { ++ if (msg_verbose) ++ msg_info("%s: executing filter CMD DISCARD", myname); ++ ++ mail_copy_status = MAIL_COPY_STAT_DISCARD; ++ vstring_sprintf(why->reason, "%s", cmd_text); ++ dsb_simple(why, "5.0.0", "User filter - DISCARD"); ++ } ++ ++ if (var_virt_maildir_extended) { ++ if (STREQUAL(value, "MOVE", cmd_len)) { ++ if (msg_verbose) ++ msg_info("%s: executing filter CMD MOVE", myname); ++ ++ strcut((char *) cmd_text, " "); ++ strcut((char *) cmd_text, "\t"); ++ strcut((char *) cmd_text, "/"); ++ strcut((char *) cmd_text, ".."); ++ ++ if (*var_virt_maildir_suffix == 0) { ++ newfile = concatenate(usr_attr.mailbox, (char *) 0); ++ } ++ else { ++ newfile = concatenate(usr_attr.mailbox, var_virt_maildir_suffix, (char *) 0); ++ } ++ ++ if (cmd_text[0] != '.') { ++ newfile = concatenate(newfile, ".", (char *) 0); ++ } ++ newdir = concatenate(newfile, cmd_text, "/", "new/", (char *) 0); ++ tmpdir = concatenate(newfile, cmd_text, "/", "tmp/", (char *) 0); ++ curdir = concatenate(newfile, cmd_text, "/", "cur/", (char *) 0); ++ mdffilename = concatenate(newfile, cmd_text, "/", "maildirfolder", (char *) 0); ++ newfile = concatenate(newfile, cmd_text, "/", "new/", bkpnewfile, (char *) 0); ++ } ++ } ++ ++ if (STREQUAL(value, "LOG", cmd_len) || STREQUAL(value, "WARN", cmd_len)) { ++ msg_warn("%s: header check warning: %s", myname, cmd_text); ++ } ++ ++ if (STREQUAL(value, "INFO", cmd_len)) { ++ msg_info("%s: header check info: %s", myname, cmd_text); ++ } ++ ++ if (msg_verbose) ++ msg_info("%s: exiting filter CMD", myname); ++ } /* End-Of-Check */ ++ ++ myfree(header); ++ vstring_free(fltstr); ++ vstream_fclose(tmpfilter); ++ } ++ ++ myfree(filtername); ++ } /* End-Of-Maildirfilter */ ++ ++ /* Deliver to curdir. */ ++ if (mail_copy_status == 0) { ++ if (sane_link(tmpfile, newfile) < 0 ++ && (errno != ENOENT ++ || (make_dirs(curdir, 0700), make_dirs(newdir, 0700), make_dirs(tmpdir, 0700)) < 0 ++ || sane_link(tmpfile, newfile) < 0)) { ++ dsb_simple(why, mbox_dsn(errno, "4.2.0"), "create maildir file %s: %m", newfile); ++ mail_copy_status = MAIL_COPY_STAT_WRITE; ++ } ++ ++ if (var_virt_maildir_extended) { ++ time(&tm); ++ ++ /* Check if the quota in the file is the same as the current one, if not, delete the file. */ ++ sizefile = vstream_fopen(sizefilename, O_RDONLY, 0); ++ if (sizefile) { ++ filequota = vstring_alloc(128); ++ vstring_get_null_bound(filequota, sizefile, 127); ++ vstream_fclose(sizefile); ++ if (atol(vstring_export(filequota)) != n) ++ unlink(sizefilename); ++ } ++ ++ /* Open maildirsize file to append this transaction. */ ++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_APPEND, 0640); ++ ++ /* If the open fails (maildirsize doesn't exist), or it's too large, or too old, overwrite it. */ ++ if(!sizefile || (stat(sizefilename, &sizefile_stat) < 0) || (sizefile_stat.st_size > SIZEFILE_MAX) || (sizefile_stat.st_mtime + 15*60 < tm)) { ++ /* If the file exists, sizefile has been opened above, so close it first. */ ++ if (sizefile) { ++ vstream_fclose(sizefile); ++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_TRUNC, 0640); ++ } ++ else { ++ sizefile = vstream_fopen(sizefilename, O_WRONLY | O_CREAT, 0640); ++ } ++ ++ /* If the creation worked, write to the file, otherwise just give up. */ ++ if (sizefile) { ++ vstream_fprintf(sizefile, "%ldS\n%ld %ld\n", n, saved_size, saved_count); ++ vstream_fclose(sizefile); ++ } ++ } ++ else { ++ /* We opened maildirsize, so let's just append this transaction and close it. */ ++ vstream_fprintf(sizefile, "%ld 1\n", (long) mail_stat.st_size); ++ vstream_fclose(sizefile); ++ } ++ ++ /* ++ * 1) mdffilename != 0, so the maildirfilter code went through the MOVE to subfolder rule. ++ * 2) stat() failed, maybe the file does not exist? Try to create it. ++ */ ++ if (mdffilename && (stat(mdffilename, &mdffile_stat) < 0)) { ++ mdffile = vstream_fopen(mdffilename, O_WRONLY | O_CREAT, 0600); ++ if (mdffile) { ++ vstream_fclose(mdffile); ++ } ++ else { ++ msg_warn("Cannot create maildirfolder file '%s': %s", mdffilename, strerror(errno)); ++ } ++ } ++ } ++ } ++ } ++ } ++ if (unlink(tmpfile) < 0) ++ msg_warn("remove %s: %m", tmpfile); + } + set_eugid(var_owner_uid, var_owner_gid); + +@@ -224,31 +955,64 @@ int deliver_maildir(LOCAL_STATE stat + * location possibly under user control. + */ + if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) { +- deliver_status = DEL_STAT_DEFER; +- } else if (mail_copy_status != 0) { +- if (errno == EACCES) { +- msg_warn("maildir access problem for UID/GID=%lu/%lu: %s", +- (long) usr_attr.uid, (long) usr_attr.gid, +- STR(why->reason)); +- msg_warn("perhaps you need to create the maildirs in advance"); +- } +- vstring_sprintf_prepend(why->reason, "maildir delivery failed: "); +- deliver_status = +- (STR(why->status)[0] == '4' ? +- defer_append : bounce_append) +- (BOUNCE_FLAGS(state.request), +- BOUNCE_ATTR(state.msg_attr)); +- } else { +- dsb_simple(why, "2.0.0", "delivered to maildir"); +- deliver_status = sent(BOUNCE_FLAGS(state.request), +- SENT_ATTR(state.msg_attr)); ++ deliver_status = DEL_STAT_DEFER; + } ++ else if (mail_copy_status != 0) { ++ if (errno == EACCES) { ++ msg_warn("maildir access problem for UID/GID=%lu/%lu: %s", ++ (long) usr_attr.uid, (long) usr_attr.gid, STR(why->reason)); ++ msg_warn("perhaps you need to create the maildirs in advance"); ++ } ++ ++ /* Support per-recipient bounce messages. */ ++ const char *limit_message; ++ int errnored = errno; /* Seems like mail_addr_find resets errno ... */ ++ ++ if (*var_virt_maildir_limit_message_maps != 0 && (limit_message = mail_addr_find(virtual_maildir_limit_message_maps, state.msg_attr.user, (char **) NULL)) != 0) { ++ errno = errnored; ++ if (errno == EFBIG) { ++ dsb_simple(why, "5.2.2", limit_message, NULL); ++ } ++ if (errno == EDQUOT) { ++ dsb_simple(why, "4.2.2", limit_message, NULL); ++ } ++ } ++ else { ++ errno = errnored; ++ if (errno == EFBIG) { ++ dsb_simple(why, "5.2.2", var_virt_maildir_limit_message, NULL); ++ } ++ if (errno == EDQUOT) { ++ dsb_simple(why, "4.2.2", var_virt_maildir_limit_message, NULL); ++ } ++ } ++ ++ vstring_sprintf_prepend(why->reason, "maildir delivery failed: "); ++ deliver_status = ++ (STR(why->status)[0] == '4' ? defer_append : bounce_append) ++ (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); ++ } ++ else { ++ dsb_simple(why, "2.0.0", "delivered to maildir"); ++ deliver_status = sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr)); ++ } ++ + vstring_free(buf); ++ + myfree(newdir); + myfree(tmpdir); + myfree(curdir); ++ ++ if (sizefilename) ++ myfree(sizefilename); ++ if (mdffilename) ++ myfree(mdffilename); ++ + myfree(tmpfile); + if (newfile) +- myfree(newfile); ++ myfree(newfile); ++ if (bkpnewfile) ++ myfree(bkpnewfile); ++ + return (deliver_status); + } +--- src/virtual/virtual.c.orig 2011-02-19 00:46:06 UTC ++++ src/virtual/virtual.c +@@ -335,12 +335,30 @@ long var_virt_mailbox_limit; + char *var_mail_spool_dir; /* XXX dependency fix */ + bool var_strict_mbox_owner; + ++char *var_virt_mailbox_limit_maps; ++bool var_virt_mailbox_limit_inbox; ++bool var_virt_mailbox_limit_override; ++bool var_virt_maildir_extended; ++bool var_virt_overquota_bounce; ++char *var_virt_maildir_limit_message; ++char *var_virt_maildir_limit_message_maps; ++char *var_virt_maildir_suffix; ++bool var_virt_trash_count; ++char *var_virt_trash_name; ++bool var_virt_maildir_filter; ++char *var_virt_maildir_filter_maps; ++ ++ + /* + * Mappings. + */ + MAPS *virtual_mailbox_maps; + MAPS *virtual_uid_maps; + MAPS *virtual_gid_maps; ++MAPS *virtual_mailbox_limit_maps; ++MAPS *virtual_maildir_limit_message_maps; ++MAPS *virtual_maildir_filter_maps; ++ + + /* + * Bit masks. +@@ -450,15 +468,28 @@ static void post_init(char *unused_name, + */ + virtual_mailbox_maps = + maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps, +- DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++ DICT_FLAG_LOCK); + + virtual_uid_maps = + maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps, +- DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++ DICT_FLAG_LOCK); + + virtual_gid_maps = + maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps, +- DICT_FLAG_LOCK | DICT_FLAG_PARANOID); ++ DICT_FLAG_LOCK); ++ ++ virtual_mailbox_limit_maps = ++ maps_create(VAR_VIRT_MAILBOX_LIMIT_MAPS, var_virt_mailbox_limit_maps, ++ DICT_FLAG_LOCK); ++ ++ virtual_maildir_limit_message_maps = ++ maps_create(VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, var_virt_maildir_limit_message_maps, ++ DICT_FLAG_LOCK); ++ ++ virtual_maildir_filter_maps = ++ maps_create(VAR_VIRT_MAILDIR_FILTER_MAPS, var_virt_maildir_filter_maps, ++ DICT_FLAG_LOCK); ++ + + virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock); + } +@@ -510,10 +541,22 @@ int main(int argc, char **argv) + VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, + VAR_VIRT_MAILBOX_BASE, DEF_VIRT_MAILBOX_BASE, &var_virt_mailbox_base, 1, 0, + VAR_VIRT_MAILBOX_LOCK, DEF_VIRT_MAILBOX_LOCK, &var_virt_mailbox_lock, 1, 0, ++ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_maps, 0, 0, ++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE, DEF_VIRT_MAILDIR_LIMIT_MESSAGE, &var_virt_maildir_limit_message, 1, 0, ++ VAR_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, DEF_VIRT_MAILDIR_LIMIT_MESSAGE_MAPS, &var_virt_maildir_limit_message_maps, 0, 0, ++ VAR_VIRT_MAILDIR_SUFFIX, DEF_VIRT_MAILDIR_SUFFIX, &var_virt_maildir_suffix, 0, 0, ++ VAR_VIRT_TRASH_NAME, DEF_VIRT_TRASH_NAME, &var_virt_trash_name, 0, 0, ++ VAR_VIRT_MAILDIR_FILTER_MAPS, DEF_VIRT_MAILDIR_FILTER_MAPS, &var_virt_maildir_filter_maps, 0, 0, + 0, + }; + static const CONFIG_BOOL_TABLE bool_table[] = { + VAR_STRICT_MBOX_OWNER, DEF_STRICT_MBOX_OWNER, &var_strict_mbox_owner, ++ VAR_VIRT_MAILBOX_LIMIT_INBOX, DEF_VIRT_MAILBOX_LIMIT_INBOX, &var_virt_mailbox_limit_inbox, ++ VAR_VIRT_MAILBOX_LIMIT_OVERRIDE, DEF_VIRT_MAILBOX_LIMIT_OVERRIDE, &var_virt_mailbox_limit_override, ++ VAR_VIRT_MAILDIR_EXTENDED, DEF_VIRT_MAILDIR_EXTENDED, &var_virt_maildir_extended, ++ VAR_VIRT_OVERQUOTA_BOUNCE, DEF_VIRT_OVERQUOTA_BOUNCE, &var_virt_overquota_bounce, ++ VAR_VIRT_TRASH_COUNT, DEF_VIRT_TRASH_COUNT, &var_virt_trash_count, ++ VAR_VIRT_MAILDIR_FILTER, DEF_VIRT_MAILDIR_FILTER, &var_virt_maildir_filter, + 0, + }; + +@@ -530,6 +573,7 @@ int main(int argc, char **argv) + MAIL_SERVER_PRE_INIT, pre_init, + MAIL_SERVER_POST_INIT, post_init, + MAIL_SERVER_PRE_ACCEPT, pre_accept, ++ MAIL_SERVER_BOOL_TABLE, bool_table, + MAIL_SERVER_PRIVILEGED, + 0); + } +--- src/virtual/virtual.h.orig 2006-01-07 23:59:47 UTC ++++ src/virtual/virtual.h +@@ -34,6 +34,9 @@ + extern MAPS *virtual_mailbox_maps; + extern MAPS *virtual_uid_maps; + extern MAPS *virtual_gid_maps; ++extern MAPS *virtual_mailbox_limit_maps; ++extern MAPS *virtual_maildir_limit_message_maps; ++extern MAPS *virtual_maildir_filter_maps; + + /* + * User attributes: these control the privileges for delivery to external Property changes on: head/mail/postfix211/files/extra-patch-postfix-vda-v13-2.11.x ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property