diff options
Diffstat (limited to 'vda')
-rw-r--r-- | vda/postfix-2.5.1-vda-ng-r1.patch.gz | bin | 28964 -> 18383 bytes | |||
-rw-r--r-- | vda/postfix-2.5.1-vda-ng.patch | 1443 |
2 files changed, 0 insertions, 1443 deletions
diff --git a/vda/postfix-2.5.1-vda-ng-r1.patch.gz b/vda/postfix-2.5.1-vda-ng-r1.patch.gz Binary files differindex e16ea02..3429b88 100644 --- a/vda/postfix-2.5.1-vda-ng-r1.patch.gz +++ b/vda/postfix-2.5.1-vda-ng-r1.patch.gz diff --git a/vda/postfix-2.5.1-vda-ng.patch b/vda/postfix-2.5.1-vda-ng.patch index f3b5731..6d3a23f 100644 --- a/vda/postfix-2.5.1-vda-ng.patch +++ b/vda/postfix-2.5.1-vda-ng.patch @@ -99,1449 +99,6 @@ diff -Nru postfix-2.5.1/README_FILES/VDA_README postfix-2.5.1-vda-ng/README_FILE +user2@domain.com.br # M2007022617 /^subject:.*Viagra.*/m REJECT /^subject:.*trash.*/m MOVE SpamFolder /^subject:.*pharmacy.*/m DISCARD + +More informations can be found at http://vda.sourceforge.net -diff -Nru postfix-2.5.1/postfix-2.4.6-vda-ng.patch postfix-2.5.1-vda-ng/postfix-2.4.6-vda-ng.patch ---- postfix-2.5.1/postfix-2.4.6-vda-ng.patch 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.5.1-vda-ng/postfix-2.4.6-vda-ng.patch 2008-03-15 15:05:52.167991798 +0100 -@@ -0,0 +1,1439 @@ -+diff -Nru postfix-2.4.6/README_FILES/VDA_README postfix-2.4.6-vda-ng/README_FILES/VDA_README -+--- postfix-2.4.6/README_FILES/VDA_README 1970-01-01 01:00:00.000000000 +0100 -++++ postfix-2.4.6-vda-ng/README_FILES/VDA_README 2007-11-24 12:48:53.000000000 +0100 -+@@ -0,0 +1,97 @@ -++Installation: -++ -++1 - Get the Postfix source code ( http://www.postfix.org/ ) -++2 - Get this software ( http://vda.sourceforge.net ) for your Postfix version -++3 - Unpack the source code: tar -xvzf postfix-VERSION.tar.gz -++4 - Unpack the patch: gunzip postfix-VERSION-vda-ng-rREV.patch.gz -++5 - Apply the patch: cd postfix-VERSION; patch -p1 < ../postfix-VERSION-vda-ng-rREV.patch -++6 - Configure -++7 - Make -++ -++Configuration: -++ -++#### Postfix main.cf -++ -++# I use only virtual as local delivery -++mailbox_transport = virtual -++ -++# Base directory where the mailboxes are located -++virtual_mailbox_base = /var/virtualmail -++ -++# Virtual users maps -++virtual_mailbox_maps = hash:/etc/postfix/vmailbox -++transport_maps = hash:/etc/postfix/vtransport -++ -++# Minimal permitted UID value (for virtual_uid_maps) -++virtual_minimum_uid = 1000 -++ -++# GIDs and UIDs to run as -++# Can also be stored in hash, mysql, ... -++virtual_uid_maps = static:4000 -++virtual_gid_maps = static:4000 -++ -++# A maximum size limit for a mailbox -++virtual_mailbox_limit = 100000000 -++ -++# Quota values maps -++virtual_mailbox_limit_maps = hash:/etc/postfix/vquota -++ -++# Limit only the INBOX -++# (useful for when you have IMAP users) -++virtual_mailbox_limit_inbox = no -++ -++# Enable limits smaller than maximum message size -++virtual_mailbox_limit_override = yes -++ -++# Enable Maildir++ extensions for faster maildir quota calculation -++# (maildirsize file and ",S=<size>" filename extension) -++# Needs Maildir++ compatible IMAP servers, like Courier-IMAP -++virtual_maildir_extended = yes -++ -++# Always bounce the message when quota reached -++virtual_overquota_bounce = yes -++ -++# Custom message to send when bouncing -++#virtual_maildir_limit_message = "Sorry, maximum quota reached!" -++ -++# Custom message maps for the bounces -++#virtual_maildir_limit_message_maps = hash:/etc/postfix/vmsg -++ -++# Also count the Trash folder when calculating quotas? -++virtual_trash_count = yes -++ -++# The name of the Trash folder -++# (if it doesn't need to be calculated) -++#virtual_trash_name = ".Trash" -++ -++# Enable the Maildirfilter feature -++virtual_maildir_filter = yes -++ -++# Maildirfilter maps -++virtual_maildir_filter_maps = hash:/etc/postfix/vfilter -++ -++#### Mailbox users file - vmailbox -++user@domain.com.br /path/to/mailbox - path relative to virtual_mailbox_base -++user1@domain.com.br /domain.com.br/user1 - no trailing slash, user has a MAILBOX -++user2@domain.com.br /domain.com.br/user2 - no trailing slash, user has a MAILBOX -++user1@domain.net.br /domain.net.br/user1/ - trailing slash, user has a MAILDIR -++user2@domain.net.br /domain.net.br/user2/ - trailing slash, user has a MAILDIR -++ -++#### Quota users file - vquota -++user@domain.com.br QUOTA IN BYTES -++user1@domain.com.br 2048000 -++user2@domain.com.br 2048000 -++user1@domain.net.br 5192000 -++user2@domain.net.br 0 - NO QUOTA -++ -++#### Maildirfilter file - vfilter -++# ATTENTION: the syntax for maildirfilter values is the following: -++# the # sign, followed by a space, followed by a M (uppercase), then a modification time value -++# (you need to change this when you change the regexps) made of a maximum of 10 digits, then a -++# space again and an arbitrary number of regexps (a regexp always starts with /^ and ends with -++# a space) and their corresponding actions -++user@domain.com.br # M<timestamp> regexp1 action1 regexp2 action2 ... -++user1@domain.net.br # M2007022701 /^subject:.*BAD.*/m DISCARD /^from:.*user@domain.com.br*/m MOVE Trash -++user2@domain.com.br # M2007022617 /^subject:.*Viagra.*/m REJECT /^subject:.*trash.*/m MOVE SpamFolder /^subject:.*pharmacy.*/m DISCARD -++ -++More informations can be found at http://vda.sourceforge.net -+diff -Nru postfix-2.4.6/src/global/mail_params.h postfix-2.4.6-vda-ng/src/global/mail_params.h -+--- postfix-2.4.6/src/global/mail_params.h 2007-07-11 01:47:45.000000000 +0200 -++++ postfix-2.4.6-vda-ng/src/global/mail_params.h 2007-11-24 12:48:53.000000000 +0100 -+@@ -2106,6 +2106,54 @@ -+ #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; -+diff -Nru postfix-2.4.6/src/util/file_limit.c postfix-2.4.6-vda-ng/src/util/file_limit.c -+--- postfix-2.4.6/src/util/file_limit.c 2003-10-22 20:48:36.000000000 +0200 -++++ postfix-2.4.6-vda-ng/src/util/file_limit.c 2007-11-24 12:48:53.000000000 +0100 -+@@ -85,7 +85,11 @@ -+ #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 -+diff -Nru postfix-2.4.6/src/virtual/mailbox.c postfix-2.4.6-vda-ng/src/virtual/mailbox.c -+--- postfix-2.4.6/src/virtual/mailbox.c 2006-06-26 14:59:19.000000000 +0200 -++++ postfix-2.4.6-vda-ng/src/virtual/mailbox.c 2007-11-26 12:30:21.000000000 +0100 -+@@ -70,6 +70,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) -+@@ -207,62 +271,72 @@ -+ * 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. -+diff -Nru postfix-2.4.6/src/virtual/maildir.c postfix-2.4.6-vda-ng/src/virtual/maildir.c -+--- postfix-2.4.6/src/virtual/maildir.c 2006-06-26 14:59:19.000000000 +0200 -++++ postfix-2.4.6-vda-ng/src/virtual/maildir.c 2007-11-24 13:20:57.000000000 +0100 -+@@ -63,28 +63,406 @@ -+ #include <mbox_open.h> -+ #include <dsn_util.h> -+ -++/* Patch library. */ -++ -++#include <sys/types.h> /* opendir(3), stat(2) */ -++#include <sys/stat.h> /* stat(2) */ -++#include <dirent.h> /* opendir(3) */ -++#include <unistd.h> /* stat(2) */ -++#include <stdlib.h> /* atol(3) */ -++#include <string.h> /* strrchr(3) */ -++#include <vstring_vstream.h> -++#include <dict.h> -++#include <dict_regexp.h> -++#include <ctype.h> -++#include <stdio.h> -++#include <sys_defs.h> -++#include <mail_addr_find.h> -++ -+ /* Application-specific. */ -+ -+ #include "virtual.h" -+ -+-/* deliver_maildir - delivery to maildir-style mailbox */ -++/* Maildirsize maximal size. */ -++ -++#define SIZEFILE_MAX 5120 -++ -++/* -++ * Chris Stratford <chriss@pipex.net> -++ * 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 *dirname, long *countptr) -++{ -++ struct stat statbuf; -++ VSTRING *sizefilename = vstring_alloc(1024); -++ VSTREAM *sizefile; -++ char *p; -++ int len, first; -++ long sum = 0, count = 0; -++ -++ vstring_sprintf(sizefilename, "%s/%s", dirname, "maildirsize"); -++ -++ sizefile = vstream_fopen(STR(sizefilename), O_RDONLY, 0); -++ if (!sizefile || (stat(STR(sizefilename), &statbuf) < 0) || (statbuf.st_size > SIZEFILE_MAX)) { -++ if (sizefile) { -++ vstream_fclose(sizefile); -++ unlink(STR(sizefilename)); -++ } -++ vstring_free(sizefilename); -++ -++ return 0; -++ } -++ -++ 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; -++ } -++ else { -++ vstream_fclose(sizefile); -++ unlink(STR(sizefilename)); -++ -++ msg_warn("read_maildirsize: invalid line '%s' found in %s, removing maildirsize file", q, STR(sizefilename)); -++ -++ vstring_free(sizefilename); -++ vstring_free(sizebuf); -++ -++ return 0; -++ } -++ } -++ -++ vstream_fclose(sizefile); -++ vstring_free(sizefilename); -++ vstring_free(sizebuf); -++ -++ *countptr = count; -++ -++ return sum; -++} -++ -++/* -++ * 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=<size>" in the filename, -++ * zero if it cannot find ",S=<size>" in the filename. -++ */ -++static long maildir_parsequota(const char *n) -++{ -++ const char *o; -++ int yes = 0; -+ -+-int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) -++ 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; -++ -++ if (!var_virt_mailbox_limit_inbox && var_virt_maildir_extended && (sum = read_maildirsize(dirname, countptr))) { -++ if (msg_verbose) -++ msg_info("%s: maildirsize used: dir=%s sum=%ld count=%ld", myname, dirname, sum, *countptr); -++ return sum; -++ } -++ -++ 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; -++ -++ if (var_virt_trash_count) { -++ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) -++ continue; -++ } -++ else { -++ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 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=%d 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; -++ struct stat mdffile_stat; /* To check if the maildirfolder file exists. */ -+ -+ GETTIMEOFDAY(&starttime); -+ -+@@ -93,15 +471,14 @@ -+ */ -+ 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))); -+ } -+ -+ /* -+@@ -109,17 +486,91 @@ -+ * 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); -++ } -++ -++ /* -++ * 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 { -++ /* Invalid limit size (negative). Use default virtual_mailbox_limit. */ -++ n = var_virt_mailbox_limit; -++ } -++ } -++ else { -++ /* There is no limit in the maps. Use default virtual_mailbox_limit. */ -++ n = var_virt_mailbox_limit; -++ } -++ -++ /* -++ * Check quota before delivering the mail. -++ */ -++ if (n != 0) { -++ set_eugid(usr_attr.uid, usr_attr.gid); -++ 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. -+@@ -174,46 +625,296 @@ -+ * [...] -+ */ -+ 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) { -+- -+- /* -+- * 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); -++ && (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. */ -++ -++ if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), dst, copy_flags, "\n", why)) == 0) { -++ /* -++ * Add a ",S=<sizeoffile>" 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); -++ -++ 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); -++ } -++ -++ /* 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); -+ -+@@ -223,31 +924,64 @@ -+ * 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.3", limit_message); -++ } -++ if (errno == EDQUOT) { -++ dsb_simple(why, "4.2.2", limit_message); -++ } -++ } -++ else { -++ errno = errnored; -++ if (errno == EFBIG) { -++ dsb_simple(why, "5.2.3", var_virt_maildir_limit_message); -++ } -++ if (errno == EDQUOT) { -++ dsb_simple(why, "4.2.2", var_virt_maildir_limit_message); -++ } -++ } -++ -++ 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); -+ } -+diff -Nru postfix-2.4.6/src/virtual/virtual.c postfix-2.4.6-vda-ng/src/virtual/virtual.c -+--- postfix-2.4.6/src/virtual/virtual.c 2007-03-27 02:07:43.000000000 +0200 -++++ postfix-2.4.6-vda-ng/src/virtual/virtual.c 2007-11-24 12:48:53.000000000 +0100 -+@@ -330,12 +330,28 @@ -+ int var_virt_mailbox_limit; -+ char *var_mail_spool_dir; /* XXX dependency fix */ -+ -++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. -+@@ -445,15 +461,24 @@ -+ */ -+ 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); -+ } -+@@ -495,16 +520,33 @@ -+ VAR_VIRT_MAILBOX_LIMIT, DEF_VIRT_MAILBOX_LIMIT, &var_virt_mailbox_limit, 0, 0, -+ 0, -+ }; -+- static CONFIG_STR_TABLE str_table[] = { -+- VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, -+- VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, -+- VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, -+- 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, -+- 0, -++ -++ static CONFIG_BOOL_TABLE bool_table[] = { -++ 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, -+ }; -+ -++ static CONFIG_STR_TABLE str_table[] = { -++ VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0, -++ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, -++ VAR_VIRT_UID_MAPS, DEF_VIRT_UID_MAPS, &var_virt_uid_maps, 0, 0, -++ VAR_VIRT_GID_MAPS, DEF_VIRT_GID_MAPS, &var_virt_gid_maps, 0, 0, -++ VAR_VIRT_MAILBOX_LIMIT_MAPS, DEF_VIRT_MAILBOX_LIMIT_MAPS, &var_virt_mailbox_limit_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_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, -++ }; -++ -+ /* -+ * Fingerprint executables and core dumps. -+ */ -+@@ -516,6 +558,7 @@ -+ 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); -+ } -+diff -Nru postfix-2.4.6/src/virtual/virtual.h postfix-2.4.6-vda-ng/src/virtual/virtual.h -+--- postfix-2.4.6/src/virtual/virtual.h 2006-01-08 00:59:47.000000000 +0100 -++++ postfix-2.4.6-vda-ng/src/virtual/virtual.h 2007-11-24 12:48:53.000000000 +0100 -+@@ -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 diff -Nru postfix-2.5.1/src/global/mail_params.h postfix-2.5.1-vda-ng/src/global/mail_params.h --- postfix-2.5.1/src/global/mail_params.h 2008-01-24 02:10:19.000000000 +0100 +++ postfix-2.5.1-vda-ng/src/global/mail_params.h 2008-03-15 15:06:00.095731675 +0100 |