rpms/cyrus-imapd/F-7 cyrus-imapd-2.3.8-getgrouplist.patch, NONE, 1.1 cyrus-imapd-2.3.9-autocreate-0.10-0.diff, NONE, 1.1 cyrus-imapd-2.3.9-autosieve-0.6.0.diff, NONE, 1.1 cyrus-imapd-2.3.9-openmacro.patch, NONE, 1.1 cyrus-imapd-2.3.9-rmquota+deletemailbox-0.2-1.diff, NONE, 1.1 .cvsignore, 1.7, 1.8 cyrus-imapd.spec, 1.25, 1.26 sources, 1.9, 1.10

Tomas Janousek (tjanouse) fedora-extras-commits at redhat.com
Tue Aug 28 11:44:43 UTC 2007


Author: tjanouse

Update of /cvs/extras/rpms/cyrus-imapd/F-7
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv27275

Modified Files:
	.cvsignore cyrus-imapd.spec sources 
Added Files:
	cyrus-imapd-2.3.8-getgrouplist.patch 
	cyrus-imapd-2.3.9-autocreate-0.10-0.diff 
	cyrus-imapd-2.3.9-autosieve-0.6.0.diff 
	cyrus-imapd-2.3.9-openmacro.patch 
	cyrus-imapd-2.3.9-rmquota+deletemailbox-0.2-1.diff 
Log Message:
* Wed Aug 22 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.9-6
- update to latest upstream
- updated all patches from uoa and reenabled rmquota+deletemailbox

* Thu Aug 16 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.9-5.rc2
- update to latest upstream beta

* Tue Aug 14 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.9-4.rc1
- update to latest upstream beta
- temporarily dropped the rmquota+deletemailbox patch (doesn't apply)
- fixed to compile with newer glibc
- added the getgrouplist patch from RHEL-4, dropped groupcache patch
- dropped the allow_auth_plain patch
- buildrequire perl-devel


cyrus-imapd-2.3.8-getgrouplist.patch:

--- NEW FILE cyrus-imapd-2.3.8-getgrouplist.patch ---
diff -Naur cyrus-imapd-2.3.8.orig/configure.in cyrus-imapd-2.3.8/configure.in
--- cyrus-imapd-2.3.8.orig/configure.in	Thu Nov 30 18:11:16 2006
+++ cyrus-imapd-2.3.8/configure.in	Tue Jun 12 15:40:12 2007
@@ -119,7 +119,7 @@
 
 AC_CHECK_HEADERS(unistd.h sys/select.h sys/param.h stdarg.h)
 AC_REPLACE_FUNCS(memmove strcasecmp ftruncate strerror)
-AC_CHECK_FUNCS(strlcat strlcpy)
+AC_CHECK_FUNCS(strlcat strlcpy getgrouplist)
 AC_HEADER_DIRENT
 
 dnl do this before Berkeley DB/IPv6 detection
diff -Naur cyrus-imapd-2.3.8.orig/lib/auth_unix.c cyrus-imapd-2.3.8/lib/auth_unix.c
--- cyrus-imapd-2.3.8.orig/lib/auth_unix.c	Thu Nov 30 18:11:22 2006
+++ cyrus-imapd-2.3.8/lib/auth_unix.c	Tue Jun 12 15:42:22 2007
@@ -224,6 +224,12 @@
     struct passwd *pwd;
     struct group *grp;
     char **mem;
+#ifdef HAVE_GETGROUPLIST
+    gid_t gid;
+    int ret, ngroups;
+    gid_t *groupids = 0;
+    int i;
+#endif
 
     identifier = mycanonifyid(identifier, 0);
     if (!identifier) return 0;
@@ -239,7 +245,45 @@
 	return newstate;
 
     pwd = getpwnam(identifier);
-	
+#ifdef HAVE_GETGROUPLIST
+    gid = pwd ? pwd->pw_gid : (gid_t) -1;
+
+    // get number of groups user is member of into newstate->ngroups
+    getgrouplist(identifier, gid, NULL, &(newstate->ngroups));
+    // get the actual group ids.
+    do {
+	if (groupids)
+	    free(groupids);
+	groupids = (gid_t *)xmalloc(newstate->ngroups * sizeof(gid_t));
+
+	ngroups = newstate->ngroups;
+	ret = getgrouplist(identifier, gid, groupids, &(newstate->ngroups));
+	/*
+	 * This is tricky. We do this as long as getgrouplist tells us to
+	 * realloc _and_ the number of groups changes. It tells us to realloc
+	 * also in the case of failure...
+	 */
+    } while (ret != -1 && ngroups != newstate->ngroups);
+
+    if (ret == -1) {
+	newstate->ngroups = 0;
+	newstate->group = NULL;
+	goto err;
+    }
+
+    newstate->group = (char **)xmalloc(newstate->ngroups * sizeof(char *));
+    for (i = 0; i < newstate->ngroups; ++i ) {
+	struct group *group;
+
+	if (pwd || groupids[i] != gid) {
+	    if ((group = getgrgid(groupids[i])))
+		newstate->group[i] = xstrdup(group->gr_name);
+	}
+    }
+
+err:
+    free( groupids );
+#else
     setgrent();
     while ((grp = getgrent())) {
 	for (mem = grp->gr_mem; *mem; mem++) {
@@ -254,6 +298,8 @@
 	}
     }
     endgrent();
+#endif
+
     return newstate;
 }
 

cyrus-imapd-2.3.9-autocreate-0.10-0.diff:

--- NEW FILE cyrus-imapd-2.3.9-autocreate-0.10-0.diff ---
diff -Naur cyrus-imapd-2.3.9/README.autocreate cyrus-imapd-2.3.9-autocreate.uncompiled/README.autocreate
--- cyrus-imapd-2.3.9/README.autocreate	1970-01-01 02:00:00.000000000 +0200
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/README.autocreate	2007-08-21 14:59:22.000000000 +0300
@@ -0,0 +1,211 @@
+Cyrus IMAP autocreate Inbox patch
+----------------------------------
+
+NOTE : This patch has been created at the University of Athens. For more info, as well 
+as more patches on Cyrus IMAPD server, please visit http://email.uoa.gr/ 
+
+The design of Cyrus IMAP server does not predict the automatic creation of users'
+INBOX folders. The creation of a user's INBOX is considered to be an external task,
+that has to be completed as part of the user email account creation procedure. 
+Hence, to create a new email account the site administrator has to:
+
+  a) Include the new account in the user database for the authentication procedure
+     (e.g. sasldb, shadow, mysql, ldap).
+  b) Create the corresponding INBOX folder. 
+
+Alternatively, the user, if succesfully authenticated, may create his own INBOX folder,
+as long as the configuration of the site allows it (see "autocreatequota" in imapd.conf).
+Unlike what not careful readers may think, enabling the "autocreatequota" option, doesn't 
+lead to the automatic INBOX folder creation by Cyrus IMAP server.
+In fact, "autocreate" means that the IMAP clients are allowed to automatically create 
+the user INBOX. 
+
+This patch adds the functionality of automatic creation of the users' INBOX folders into
+the Cyrus IMAP server. It is implemented as two features, namely the  "create on login"
+and "create on post".
+ 
+
+
+Create on login
+===============
+This feauture provides automatic creation of a user's INBOX folder when all of the 
+following requirements are met:
+
+i)  The user has succesfully passed the authentication procedure.
+
+ii) The user's authorisation ID (typically the same as the user's
+authentication ID)  doesn't belong to the imap_admins or admins
+accounts (see imapd.conf).
+
+iii) The "autocreatequota" option in the imap configuration file 
+has been set to a non zero value. 
+
+iv) The corresponding to the user's authorisation ID INBOX folder
+does not exist.
+
+The user's first login is the most typical case when all four requirements are met. 
+Note that if the authenticated ID is allowed to proxy to another account for which 
+all of the above requirements are met, the corresponding INBOX folder for that account 
+will be created.
+
+
+
+Create on post
+==============
+This feauture provides automatic creation of a user's INBOX folder when all of the 
+following requirements are met. 
+
+i) An email message addressed to the user has been received.  
+
+ii) The recipient is not any of the imap_admins or admins accounts. 
+Note that passing emails to admins or imap_admins accounts from 
+the MTA to LMTP should be avoided in any case.
+
+iii) The recipient's INBOX does not exist.
+
+iv) The "autocreatequota" option in the imap configuration file 
+has been set to a non zero value. 
+
+v) The "createonpost" option in the imap configuration file 
+has been switched on. 
+
+
+Besides the automatic creation of INBOX folder, additional functionalities are
+provided:
+
+  (A) Automatic creation of INBOX subfolders controlled by "autocreateinboxfolders"
+configuration option. eg 
+
+autocreateinboxfolders: sent|drafts|spam|templates
+
+  (B) Automatic subscription of INBOX subfolders controlled by "autosubscribeinboxfolders"
+configuration option. eg
+
+autosubscribeinboxfolders: sent|spam
+
+Obviously, only subscription to subfolders included in the "autocreateinboxfolder"
+list is meaningful. 
+
+  (C) Automatic subscription to shared folders (bulletin boards). The user gets
+automatically subscribed to the shared folders declared in the "autosubscribesharedfolders"
+configuration option in imapd.conf.
+eg autosubscribesharedfolders: public_folder | public_folder.subfolder
+
+In order the above action to succeed, the shared folder has to pre-exist the INBOX creation
+and the user must have the appropriate permissions in order to be able to subscribe to the
+shared folder.
+
+* A new config option has been added. 'autosubscribe_all_sharedfolders' is a yes/no
+option. When set to yes, the user is automatically subscribed to all shared folders one 
+has permission to subscribe to. Please, note that when this option is set to yes, then
+'autosubscribesharedfolders' option is overriden.
+
+  (D) Automatic creation of a predefined default sieve script.
+
+This is very useful when a default sieve script is used for every user. Usually, a
+default anti-spam script may me be written in a file and copied to each user
+sieve scripts upon the INBOX creation. The imapd.conf options that have been added
+are 'autocreate_sieve_script', 'autocreate_sieve_compiledscript' and 
+'generate_compiled_sieve_script'. 
+
+autocreate_sieve_script configuration option refers to the full path of the file 
+that contains the sieve script. The default value is null and if no file is defined,
+then no default script is created upon INBOX creation. (The feature is disabled)
+eg autocreate_sieve_script: /etc/default_sieve_script
+
+autocreate_sieve_compiledscript configuration option refers to the full path of the
+file that contains the bytecode compiled sieve script. If this filename is defined
+in imapd.conf and the file exists, then it is automatically copied in the user's sieve
+directory. If it is not defined, then a bytecode sieve script gets on the fly compiled
+by the daemon. 
+eg autocreate_sieve_compiledscript: /etc/default_sieve_script.bc
+
+generate_compiled_sieve_script is a boolean option that triggers the compilation of the 
+source sieve script to bytecode sieve script. The file that the bytecode script will
+be saved is pointed by autocreate_sieve_compiledscript.
+
+Ways of compiling a sieve script : 
+1. Compile a sieve script using the standard sievec utility, distributed by CMU
+2. Compile a sieve script using the compile_sieve utility, released by UoA. This 
+   tool is almost identical to the sievec utility, with the difference that it 
+   reads the input and output file from autocreate_sieve_script and 
+   autocreate_sieve_compiledscript options in imapd.conf
+3. Let cyrus create a compiled sieve script using a source script. Cyrus can be
+   instructed to save the compiled script any time a compiled script does not exist.
+
+NOTES : 
+1. In order this functionality to work, the following requirements must have been met:
+   - 'sieveusehomedir' option must be 'no' in the configuration (default).
+   - 'sievedir' option must have a valid value.
+2. Currently, this patch checks the validity of the source script while generating a 
+   bytecode compiled script, but not the validity of the bytecode sieve script file.
+   The administrator should make sure that the provided files contain a valid sieve
+   script as well as the compiled script is updated every time the source script changes.
+
+
+  (E) The administrator may control for which users and/or groups may the INBOXes 
+automatically be created. The autocreate_users option restricts the groups
+for which the patch will create the mailboxes. 
+
+The default value of autocreate_users is anyone. So, if not set at all, the patch will 
+work for all users. However, one may set:
+
+autocreate_users: user1 user2 group:group1 group:group2
+
+In that case, the INBOX will be created only for user1, user2 and the users that belong 
+to group1 and group2. 
+
+More refined control per service is provided by the options imap_autocreate_users,
+pop3_autocreate_users and lmtp_autocreate_users. These options override the 
+autocreate_users option and offer per service control.
+
+Example: 
+One may want to restrict the create on post functionality only for a specific group
+of users. To achieve this, the following lines must be added in the imapd.conf file:
+
+createonpost: yes
+lmtp_autocreate_users: group:groupname
+
+
+
+Issues to be considered 
+=======================
+
+I) In order to use the create on post feauture one should be absolutely sure that: 
+a) The MTA checks the validity of the email recipient before sending the email to
+LMTP. This is an RFC821 requirement. This usually expands to "the mta should be 
+able to use the account database as user mailbox database". 
+b) Only authorised accounts/services can talk to LMTP.
+
+II) Especially in the case of imap logins, the current patch implementation checks
+for the INBOX folder existence upon login, causing an extra mailbox lookup in most 
+of the cases. 
+A better approach would be to chase the "IMAP_MAILBOX_NONEXISTENT" error code and
+check if the error is associated with an INBOX folder. However, this would mess up
+Cyrus code. The way it was implemented may not have been the most performance
+optimised, but it produces a much cleaner and simple patch.
+
+
+
+Virtual Domains Support
+=======================
+
+Virtual domains are supported by all versions of the patch for cyrus-imapd-2.2.1-BETA and 
+later. However, it is not possible to declare different INBOX subfolders to be created or 
+shared folders to be subscribed to for every domain.
[...1975 lines suppressed...]
+
 #endif
 
 struct auth_mech auth_krb = 
@@ -376,4 +392,5 @@
     &mymemberof,
     &mynewstate,
     &myfreestate,
+    &mycanonuser,
 };
diff -Naur cyrus-imapd-2.3.9/lib/auth_krb5.c cyrus-imapd-2.3.9-autocreate.uncompiled/lib/auth_krb5.c
--- cyrus-imapd-2.3.9/lib/auth_krb5.c	2006-11-30 19:11:22.000000000 +0200
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/lib/auth_krb5.c	2007-08-21 14:59:22.000000000 +0300
@@ -197,6 +197,14 @@
     free(auth_state);
 }
 
+static char *mycanonuser(struct auth_state *auth_state)
+{
+    if (auth_state)
+       return auth_state->userid;
+
+    return NULL;
+}
+
 #else /* HAVE_GSSAPI_H */
 
 static int mymemberof(
@@ -225,6 +233,12 @@
 	fatal("Authentication mechanism (krb5) not compiled in", EC_CONFIG);
 }
 
+static char *mycanonuser(
+    struct auth_state *auth_state __attribute__((unused)))
+{
+        fatal("Authentication mechanism (krb5) not compiled in", EC_CONFIG);
+}
+
 #endif
 
 struct auth_mech auth_krb5 = 
@@ -235,4 +249,5 @@
     &mymemberof,
     &mynewstate,
     &myfreestate,
+    &mycanonuser,
 };
diff -Naur cyrus-imapd-2.3.9/lib/auth_pts.c cyrus-imapd-2.3.9-autocreate.uncompiled/lib/auth_pts.c
--- cyrus-imapd-2.3.9/lib/auth_pts.c	2007-08-15 20:20:57.000000000 +0300
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/lib/auth_pts.c	2007-08-21 14:59:22.000000000 +0300
@@ -511,6 +511,14 @@
     free(auth_state);
 }
 
+static char *mycanonuser(struct auth_state *auth_state)
+{
+    if (auth_state)
+       return auth_state->userid.id;
+
+    return NULL;
+}
+
 struct auth_mech auth_pts = 
 {
     "pts",		/* name */
@@ -519,4 +527,5 @@
     &mymemberof,
     &mynewstate,
     &myfreestate,
+    &mycanonuser,
 };
diff -Naur cyrus-imapd-2.3.9/lib/auth_unix.c cyrus-imapd-2.3.9-autocreate.uncompiled/lib/auth_unix.c
--- cyrus-imapd-2.3.9/lib/auth_unix.c	2007-02-13 18:42:49.000000000 +0200
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/lib/auth_unix.c	2007-08-21 14:59:22.000000000 +0300
@@ -269,6 +269,16 @@
     free((char *)auth_state);
 }
 
+static char *mycanonuser(auth_state)
+    struct auth_state *auth_state;
+{
+    if (auth_state)
+         return auth_state->userid;
+
+    return NULL;
+}
+
+
 
 struct auth_mech auth_unix = 
 {
@@ -278,4 +288,5 @@
     &mymemberof,
     &mynewstate,
     &myfreestate,
+    &mycanonuser,
 };
diff -Naur cyrus-imapd-2.3.9/lib/imapoptions cyrus-imapd-2.3.9-autocreate.uncompiled/lib/imapoptions
--- cyrus-imapd-2.3.9/lib/imapoptions	2007-03-30 21:51:02.000000000 +0300
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/lib/imapoptions	2007-08-21 14:59:22.000000000 +0300
@@ -177,6 +177,55 @@
 /* Number of seconds to wait before returning a timeout failure when
    performing a client connection (e.g. in a murder environment) */
 
+{ "createonpost", 0, SWITCH }
+/* If yes, when lmtpd receives an incoming mail for an INBOX that does not exist,
+   then the INBOX is automatically created by lmtpd. */
+
+{ "autocreateinboxfolders", NULL, STRING }
+/* If a user does not have an INBOX created then the INBOX as well as some INBOX 
+   subfolders are created under two conditions.
+     1. The user logins via the IMAP or the POP3 protocol. (autocreatequota option must have a nonzero value)
+     2. A message arrives for the user through the LMTPD protocol.(createonpost option must be yes)
+   autocreateinboxfolders is a list of INBOX's subfolders separated by a "|", that 
+   are automatically created by the server under the previous two situations. */
+
+{ "autosubscribeinboxfolders", NULL, STRING }
+/* A list of folder names, separated by "|", that the users get automatically subscribed to, 
+   when their INBOX is created. These folder names must have been included in the 
+   autocreateinboxfolders option of the imapd.conf. */
+
+{ "autosubscribesharedfolders", NULL, STRING }
+/* A list of shared folders (bulletin boards), separated by "|", that the users get
+   automatically subscribed to, after their INBOX is created. The shared folder must 
+   have been created and the user must have the required permissions to get subscribed 
+   to it. Otherwise, subscribing to the shared folder fails. */
+
+{ "autosubscribe_all_sharedfolders", 0, SWITCH }
+/* If set to yes, the user is automatically subscribed to all shared folders, one has permission
+   to subscribe to. */
+
+{ "autocreate_sieve_script", NULL, STRING }
+/* The full path of a file that contains a sieve script. This script automatically becomes a
+   user's initial default sieve filter script. When this option is not defined, no default 
+   sieve filter is created. The file must be readable by the cyrus daemon. */
+
+{ "autocreate_sieve_compiledscript", NULL, STRING }
+/* The full path of a file that contains a compiled in bytecode sieve script. This script 
+   automatically becomes a user's initial default sieve filter script.  If this option is 
+   not specified, or the filename doesn't exist then the script defined by 
+   autocreate_sieve_script is compiled on the fly and installed as the user's default
+   sieve script */
+
+{ "generate_compiled_sieve_script", 0, SWITCH }
+/* If set to yes and no compiled sieve script file exists, the sieve script which is 
+   compiled on the fly will be saved in the file name that autocreate_sieve_compiledscript 
+   option points to. In order a compiled script to be generated, autocreate_sieve_script and 
+   autocreate_sieve_compiledscript must have valid values */
+
+{ "autocreate_users", "anyone", STRING }
+/* A space separated list of users and/or groups that are allowed their INBOX to be
+   automatically created. */
+
 { "configdirectory", NULL, STRING }
 /* The pathname of the IMAP configuration directory.  This field is
    required. */
diff -Naur cyrus-imapd-2.3.9/notifyd/Makefile.in cyrus-imapd-2.3.9-autocreate.uncompiled/notifyd/Makefile.in
--- cyrus-imapd-2.3.9/notifyd/Makefile.in	2006-11-30 19:11:23.000000000 +0200
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/notifyd/Makefile.in	2007-08-21 14:59:22.000000000 +0300
@@ -69,10 +69,11 @@
 SERVICE=../master/service.o
 
 IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@
+SIEVE_LIBS = @SIEVE_LIBS@
 IMAP_COM_ERR_LIBS = @IMAP_COM_ERR_LIBS@
 LIB_WRAP = @LIB_WRAP@
 LIBS = @ZEPHYR_LIBS@ @LIBS@ $(IMAP_COM_ERR_LIBS)
-DEPLIBS=../imap/mutex_fake.o ../imap/libimap.a ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@
+DEPLIBS=../imap/mutex_fake.o ../imap/libimap.a $(SIEVE_LIBS) ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@
 
 PURIFY=/usr/local/bin/purify
 PUREOPT=-best-effort
diff -Naur cyrus-imapd-2.3.9/notifyd/notifyd.c cyrus-imapd-2.3.9-autocreate.uncompiled/notifyd/notifyd.c
--- cyrus-imapd-2.3.9/notifyd/notifyd.c	2006-11-30 19:11:23.000000000 +0200
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/notifyd/notifyd.c	2007-08-21 14:59:22.000000000 +0300
@@ -97,7 +97,7 @@
 
 #define NOTIFY_MAXSIZE 8192
 
-int do_notify()
+static int do_notify()
 {
     struct sockaddr_un sun_data;
     socklen_t sunlen = sizeof(sun_data);
diff -Naur cyrus-imapd-2.3.9/ptclient/Makefile.in cyrus-imapd-2.3.9-autocreate.uncompiled/ptclient/Makefile.in
--- cyrus-imapd-2.3.9/ptclient/Makefile.in	2006-11-30 19:11:24.000000000 +0200
+++ cyrus-imapd-2.3.9-autocreate.uncompiled/ptclient/Makefile.in	2007-08-21 14:59:22.000000000 +0300
@@ -57,10 +57,11 @@
 AFS_LDFLAGS = @AFS_LDFLAGS@ @COM_ERR_LDFLAGS@
 AFS_LIBS = @AFS_LIBS@
 IMAP_LIBS = @IMAP_LIBS@ @LIB_RT@
+SIEVE_LIBS = @SIEVE_LIBS@
 LIBS = $(IMAP_LIBS) @COM_ERR_LIBS@
 LIB_SASL = @LIB_SASL@
 LIB_WRAP = @LIB_WRAP@
-DEPLIBS = ../imap/libimap.a ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@
+DEPLIBS = ../imap/libimap.a $(SIEVE_LIBS) ../lib/libcyrus.a ../lib/libcyrus_min.a @DEPLIBS@ 
 UTIL_LIBS = ../imap/mutex_fake.o ../imap/cli_fatal.o
 
 LDAP_LIBS=@LDAP_LIBS@

cyrus-imapd-2.3.9-autosieve-0.6.0.diff:

--- NEW FILE cyrus-imapd-2.3.9-autosieve-0.6.0.diff ---
diff -Naur cyrus-imapd-2.3.9/README.autosievefolder cyrus-imapd-2.3.9-autosieve.uncompiled/README.autosievefolder
--- cyrus-imapd-2.3.9/README.autosievefolder	1970-01-01 02:00:00.000000000 +0200
+++ cyrus-imapd-2.3.9-autosieve.uncompiled/README.autosievefolder	2007-08-21 16:04:08.000000000 +0300
@@ -0,0 +1,42 @@
+Cyrus IMAP autosievefolder patch
+----------------------------------
+
+NOTE : This patch has been created at the University of Athens. For more info, as well 
+as more patches on Cyrus IMAPD server, please visit http://email.uoa.gr 
+
+
+  When the lmtpd daemon receives an email message prior to delivering it to the 
+INBOX folder of the user, checks if the user has specified sieve filters. If the
+user has specified sieve filters the filters are evaluated. If the message matches
+any of the filters the action that is specified in the filter is executed. If the action 
+is FileInto it is stored in the subfolder specified in the filter. If the 
+subfolder doesn't exist then the message is sent to the INBOX folder of the user.
+
+  With this patch if the folder doesn't exist AND the name of the subfolder is 
+specified in the autosievefolders option, OR the anysievefolder is set to 
+yes in the cyrus-imap configuration file then the subfolder is created and the mail 
+is stored there.
+
+
+Check the following options of the imapd.conf file
+==================================================
+
+* anysievefolder : It must be "yes" in order to permit the autocreation of any 
+INBOX subfolder requested by a sieve filter, through the "fileinto" action. (default = no)
+* autosievefolders : It is a "|" separated list of subfolders of INBOX that will be 
+automatically created, if requested by a sieve filter, through the "fileinto" 
+action. (default = null)
+	i.e. autosievefolders: Junk | Spam
+
+WARNING: anysievefolder, takes precedence over autosievefolders . Which means that if 
+anysievefolder is set to "yes", cyrus will create any INBOX subfolder requested, no-matter what the value of autosievefolders is.
+
+
+Things to be done
+=================
+
+1. Support cyrus wildcards in the autosievefolders option. 
+
+
+For more information and updates please visit http://email.uoa.gr/projects/cyrus/autosievefolder
+
diff -Naur cyrus-imapd-2.3.9/imap/lmtp_sieve.c cyrus-imapd-2.3.9-autosieve.uncompiled/imap/lmtp_sieve.c
--- cyrus-imapd-2.3.9/imap/lmtp_sieve.c	2007-03-27 22:53:08.000000000 +0300
+++ cyrus-imapd-2.3.9-autosieve.uncompiled/imap/lmtp_sieve.c	2007-08-21 16:04:08.000000000 +0300
@@ -88,6 +88,9 @@
     struct auth_state *authstate;
 } script_data_t;
 
+static int autosieve_subfolder(char *userid, struct auth_state *auth_state,
+                               char *subfolder, struct namespace *namespace);
+
 static char *make_sieve_db(const char *user)
 {
     static char buf[MAX_MAILBOX_PATH+1];
@@ -484,7 +487,20 @@
 			      sd->username, mdata->notifyheader,
 			      namebuf, quotaoverride, 0);
     }
-
+    
+    if (ret == IMAP_MAILBOX_NONEXISTENT) {
+        /* if "plus" folder under INBOX, then try to create it */
+        ret = autosieve_subfolder((char *) sd->username, sd->authstate, namebuf, mdata->namespace);
+
+	/* Try to deliver the mail again. */
+        if (!ret)
+            ret = deliver_mailbox(md->f, mdata->content, mdata->stage, md->size,
+                                  fc->imapflags->flag, fc->imapflags->nflags,
+                                  (char *) sd->username, sd->authstate, md->id,
+                                  sd->username, mdata->notifyheader,
+                                  namebuf, quotaoverride, 0);
+    }
+    
     if (!ret) {
 	snmp_increment(SIEVE_FILEINTO, 1);
 	return SIEVE_OK;
@@ -936,3 +952,80 @@
        we'll do normal delivery */
     return r;
 }
+
+
+#define SEP '|'
+
+static int autosieve_subfolder(char *userid, struct auth_state *auth_state,
+                               char *subfolder, struct namespace *namespace)
+{
+     char option_name_external[MAX_MAILBOX_NAME + 1];
+     char option_name_internal[MAX_MAILBOX_NAME + 1];
+     const char *subf ;
+     char *p, *q, *next_subf;
+     int len, r = 0;
+     int createsievefolder = 0;
+
+    /* Check if subfolder or userid are NULL */
+    if(userid == NULL || subfolder == NULL)
+         return IMAP_MAILBOX_NONEXISTENT;
+
+    syslog(LOG_DEBUG, "autosievefolder: autosieve_subfolder() was called for user %s, folder %s", 
+		    userid, subfolder);
+
+    if (config_getswitch(IMAPOPT_ANYSIEVEFOLDER)) {
+         createsievefolder = 1;
+    } else if ((subf = config_getstring(IMAPOPT_AUTOSIEVEFOLDERS)) != NULL) {
+         /* Roll through subf */
+         next_subf = (char *) subf;
+         while (*next_subf) {
+              for (p = next_subf ; isspace((int) *p) || *p == SEP ; p++);
+              for (next_subf = p ; *next_subf && *next_subf != SEP ; next_subf++);
+              for (q = next_subf ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--);
+
+              if (!*p) continue;
+                    
+              len = q - p + 1;
+             /*
+              * This is a preliminary length check based on the assumption
+              * that the *final* internal format will be something
+              * like user.userid.subfolder(s).
+              */
+              if (len > sizeof(option_name_external) - strlen(userid) - 5)
+                   return IMAP_MAILBOX_BADNAME;
+
+              strlcpy(option_name_external, namespace->prefix[NAMESPACE_INBOX], sizeof(option_name_external));
+	      strncat(option_name_external, p, len);
+                    
+              /* 
+               * Transform the option folder name to internal namespace and compare it
+	       * with what must be created.
+               */
+              r = namespace->mboxname_tointernal(namespace, option_name_external, userid, option_name_internal);
+              if (r) continue;
+
+              if (!strcmp(option_name_internal, subfolder)) {
+                  createsievefolder = 1;
+                  break;
+              }
+         }
+    }
+
+    if (createsievefolder) {
+        /* Folder is already in internal namespace format */
+        r = mboxlist_createmailbox(subfolder, MAILBOX_FORMAT_NORMAL, NULL,
+                                           1, userid, auth_state, 0, 0, 0);
+        if (!r) {
+            mboxlist_changesub(subfolder, userid, auth_state, 1, 1);
+            syslog(LOG_DEBUG, "autosievefolder: User %s, folder %s creation succeeded",
+                                                   userid, subfolder);
+            return 0;
+        } else {
+            syslog(LOG_ERR, "autosievefolder: User %s, folder %s creation failed. %s",
+                                                  userid, subfolder,error_message(r));
+            return r;
+        }
+    } else
+        return IMAP_MAILBOX_NONEXISTENT;
+}
+
diff -Naur cyrus-imapd-2.3.9/lib/imapoptions cyrus-imapd-2.3.9-autosieve.uncompiled/lib/imapoptions
--- cyrus-imapd-2.3.9/lib/imapoptions	2007-03-30 21:51:02.000000000 +0300
+++ cyrus-imapd-2.3.9-autosieve.uncompiled/lib/imapoptions	2007-08-21 16:04:08.000000000 +0300
@@ -884,6 +884,15 @@
 /* If enabled, lmtpd will look for Sieve scripts in user's home
    directories: ~user/.sieve. */
 
+{ "anysievefolder", 0, SWITCH }
+/* It must be "yes" in order to permit the autocreation of any INBOX subfolder 
+   requested by a sieve filter, through the "fileinto" action. (default = no) */
+
+{ "autosievefolders", NULL, STRING }
+/* It is a "|" separated list of subfolders of INBOX that will be automatically created, 
+   if requested by a sieve filter, through the "fileinto" action. (default = null)
+   i.e. autosievefolders: Junk | Spam */
+
 { "singleinstancestore", 1, SWITCH }
 /* If enabled, imapd, lmtpd and nntpd attempt to only write one copy
    of a message per partition and create hard links, resulting in a

cyrus-imapd-2.3.9-openmacro.patch:

--- NEW FILE cyrus-imapd-2.3.9-openmacro.patch ---
--- cyrus-imapd-2.3.9/imap/quota_db.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/quota_db.c	2007-08-14 16:31:48.000000000 +0200
@@ -251,7 +251,7 @@
 	strlcat(fname, FNAME_QUOTADB, fname_len);
     }
 
-    ret = QDB->open(fname, CYRUSDB_CREATE, &qdb);
+    ret = (QDB->open)(fname, CYRUSDB_CREATE, &qdb);
     if (ret != 0) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
 	       cyrusdb_strerror(ret));
@@ -270,7 +270,7 @@
     int r;
 
     if (quota_dbopen) {
-	r = QDB->close(qdb);
+	r = (QDB->close)(qdb);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing quotas: %s",
 		   cyrusdb_strerror(r));
--- cyrus-imapd-2.3.9/imap/seen_bigdb.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/seen_bigdb.c	2007-08-14 16:32:03.000000000 +0200
@@ -104,7 +104,7 @@
     strcpy(fname, config_dir);
     strcat(fname, FNAME_SEENDB);
 
-    r = DB->open(fname, CYRUSDB_CREATE, &bigdb);
+    r = (DB->open)(fname, CYRUSDB_CREATE, &bigdb);
     if (r != 0) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
 	       cyrusdb_strerror(r));
@@ -385,7 +385,7 @@
     int r;
 
     if (seen_inited) {
-	r = DB->close(bigdb);
+	r = (DB->close)(bigdb);
 	if (r != 0) {
 	    syslog(LOG_ERR, "DBERROR: closing seen database: %s",
 		   cyrusdb_strerror(r));
--- cyrus-imapd-2.3.9/imap/mboxkey.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/mboxkey.c	2007-08-14 16:31:01.000000000 +0200
@@ -150,7 +150,7 @@
     /* otherwise, close the existing database */
     if (mboxkeydb) {
 	abortcurrent(mboxkeydb);
-	r = DB->close(mboxkeydb->db);
+	r = (DB->close)(mboxkeydb->db);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing mboxkeydb: %s", 
 		   cyrusdb_strerror(r));
@@ -164,7 +164,7 @@
 
     /* open the mboxkeydb corresponding to user */
     fname = mboxkey_getpath(user);
-    r = DB->open(fname, (flags & MBOXKEY_CREATE) ? CYRUSDB_CREATE : 0,
+    r = (DB->open)(fname, (flags & MBOXKEY_CREATE) ? CYRUSDB_CREATE : 0,
 		 &mboxkeydb->db);
     if (r != 0) {
 	int level = (flags & MBOXKEY_CREATE) ? LOG_ERR : LOG_DEBUG;
@@ -325,7 +325,7 @@
 
 	/* free the old database hanging around */
 	abortcurrent(lastmboxkey);
-	r = DB->close(lastmboxkey->db);
+	r = (DB->close)(lastmboxkey->db);
 	if (r != CYRUSDB_OK) {
 	    syslog(LOG_ERR, "DBERROR: error closing lastmboxkey: %s",
 		   cyrusdb_strerror(r));
@@ -409,7 +409,7 @@
 
     if (lastmboxkey) {
 	abortcurrent(lastmboxkey);
-	r = DB->close(lastmboxkey->db);
+	r = (DB->close)(lastmboxkey->db);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing lastmboxkey: %s",
 		   cyrusdb_strerror(r));
@@ -482,10 +482,10 @@
     struct mboxkey_merge_rock rock;
 
     /* xxx does this need to be CYRUSDB_CREATE? */
-    r = DB->open(tmpfile, CYRUSDB_CREATE, &tmp);
+    r = (DB->open)(tmpfile, CYRUSDB_CREATE, &tmp);
     if(r) goto done;
 	    
-    r = DB->open(tgtfile, CYRUSDB_CREATE, &tgt);
+    r = (DB->open)(tgtfile, CYRUSDB_CREATE, &tgt);
     if(r) goto done;
 
     rock.db = tgt;
@@ -498,8 +498,8 @@
 
  done:
 
-    if(tgt) DB->close(tgt);
-    if(tmp) DB->close(tmp);
+    if(tgt) (DB->close)(tgt);
+    if(tmp) (DB->close)(tmp);
     
     return r;
 }
--- cyrus-imapd-2.3.9/imap/tls.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/tls.c	2007-08-14 16:33:15.000000000 +0200
@@ -650,7 +650,7 @@
 	strlcpy(dbdir, config_dir, sizeof(dbdir));
 	strlcat(dbdir, FNAME_TLSSESSIONS, sizeof(dbdir));
 
-	r = DB->open(dbdir, CYRUSDB_CREATE, &sessdb);
+	r = (DB->open)(dbdir, CYRUSDB_CREATE, &sessdb);
 	if (r != 0) {
 	    syslog(LOG_ERR, "DBERROR: opening %s: %s",
 		   dbdir, cyrusdb_strerror(ret));
@@ -931,7 +931,7 @@
     int r;
 
     if (tls_serverengine && sess_dbopen) {
-	r = DB->close(sessdb);
+	r = (DB->close)(sessdb);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing tlsdb: %s",
 		   cyrusdb_strerror(r));
@@ -1008,7 +1008,7 @@
     strlcpy(dbdir, config_dir, sizeof(dbdir));
     strlcat(dbdir, FNAME_TLSSESSIONS, sizeof(dbdir));
 
-    ret = DB->open(dbdir, CYRUSDB_CREATE, &sessdb);
+    ret = (DB->open)(dbdir, CYRUSDB_CREATE, &sessdb);
     if (ret != CYRUSDB_OK) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s",
 	       dbdir, cyrusdb_strerror(ret));
@@ -1019,7 +1019,7 @@
 	sess_dbopen = 1;
 	prock.count = prock.deletions = 0;
 	DB->foreach(sessdb, "", 0, &prune_p, &prune_cb, &prock, NULL);
-	DB->close(sessdb);
+	(DB->close)(sessdb);
 	sessdb = NULL;
 	sess_dbopen = 0;
 
--- cyrus-imapd-2.3.9/imap/duplicate.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/duplicate.c	2007-08-14 16:30:03.000000000 +0200
@@ -105,7 +105,7 @@
 	    strcat(fname, FNAME_DELIVERDB);
 	}
 
-	r = DB->open(fname, CYRUSDB_CREATE, &dupdb);
+	r = (DB->open)(fname, CYRUSDB_CREATE, &dupdb);
 	if (r != 0)
 	    syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
 		   cyrusdb_strerror(r));
@@ -395,7 +395,7 @@
     int r = 0;
 
     if (duplicate_dbopen) {
-	r = DB->close(dupdb);
+	r = (DB->close)(dupdb);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing deliverdb: %s",
 		   cyrusdb_strerror(r));
--- cyrus-imapd-2.3.9/imap/cvt_cyrusdb.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/cvt_cyrusdb.c	2007-08-14 16:29:32.000000000 +0200
@@ -157,10 +157,10 @@
     printf("Converting from %s (%s) to %s (%s)\n", old_db, DB_OLD->name,
 	   new_db, DB_NEW->name);
 
-    r = DB_OLD->open(old_db, 0, &odb);
+    r = (DB_OLD->open)(old_db, 0, &odb);
     if(r != CYRUSDB_OK)
 	fatal("can't open old database", EC_TEMPFAIL);
-    r = DB_NEW->open(new_db, CYRUSDB_CREATE, &ndb);
+    r = (DB_NEW->open)(new_db, CYRUSDB_CREATE, &ndb);
     if(r != CYRUSDB_OK)
 	fatal("can't open new database", EC_TEMPFAIL);
 
@@ -173,8 +173,8 @@
 	fprintf(stderr, "Warning: apparently empty database converted.\n");
     
 
-    DB_OLD->close(odb);
-    DB_NEW->close(ndb);
+    (DB_OLD->close)(odb);
+    (DB_NEW->close)(ndb);
     
     cyrus_done();
 
--- cyrus-imapd-2.3.9/imap/annotate.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/annotate.c	2007-08-14 16:28:42.000000000 +0200
@@ -253,7 +253,7 @@
 	strcat(fname, FNAME_ANNOTATIONS);
     }
 
-    ret = DB->open(fname, CYRUSDB_CREATE, &anndb);
+    ret = (DB->open)(fname, CYRUSDB_CREATE, &anndb);
     if (ret != 0) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
 	       cyrusdb_strerror(ret));
@@ -270,7 +270,7 @@
     int r;
 
     if (annotate_dbopen) {
-	r = DB->close(anndb);
+	r = (DB->close)(anndb);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing annotations: %s",
 		   cyrusdb_strerror(r));
--- cyrus-imapd-2.3.9/imap/arbitron.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/arbitron.c	2007-08-14 16:29:11.000000000 +0200
@@ -419,14 +419,14 @@
     int r;    
     struct db *tmp = NULL;
 
-    r = DB->open(path, 0, &tmp);
+    r = (DB->open)(path, 0, &tmp);
     if(r) goto done;
     
     DB->foreach(tmp, "", 0, process_user_p, process_user_cb,
 		(void *) user, NULL);
 
  done:
-    if(tmp) DB->close(tmp);
+    if(tmp) (DB->close)(tmp);
 }
 
 static int process_subs_cb(void *rockp __attribute__((unused)),
@@ -475,14 +475,14 @@
     int r;    
     struct db *tmp = NULL;
 
-    r = SUBDB->open(path, 0, &tmp);
+    r = (SUBDB->open)(path, 0, &tmp);
     if(r) goto done;
     
     SUBDB->foreach(tmp, "", 0, process_subs_p, process_subs_cb,
 		   (void *) user, NULL);
 
  done:
-    if(tmp) SUBDB->close(tmp);
+    if(tmp) (SUBDB->close)(tmp);
 }
 
 void report_users(struct user_list *u)
--- cyrus-imapd-2.3.9/imap/mboxlist.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/mboxlist.c	2007-08-14 16:31:28.000000000 +0200
@@ -2746,7 +2746,7 @@
 	flags |= CYRUSDB_MBOXSORT;
     }
 
-    ret = DB->open(fname, flags, &mbdb);
+    ret = (DB->open)(fname, flags, &mbdb);
     if (ret != 0) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
 	       cyrusdb_strerror(ret));
@@ -2765,7 +2765,7 @@
     int r;
 
     if (mboxlist_dbopen) {
-	r = DB->close(mbdb);
+	r = (DB->close)(mbdb);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing mailboxes: %s",
 		   cyrusdb_strerror(r));
@@ -2825,7 +2825,7 @@
 	flags |= CYRUSDB_MBOXSORT;
     }
 
-    r = SUBDB->open(subsfname, flags, ret);
+    r = (SUBDB->open)(subsfname, flags, ret);
     if (r != CYRUSDB_OK) {
 	r = IMAP_IOERROR;
     }
@@ -2839,7 +2839,7 @@
  */
 static void mboxlist_closesubs(struct db *sub)
 {
-    SUBDB->close(sub);
+    (SUBDB->close)(sub);
 }
 
 /*
--- cyrus-imapd-2.3.9/imap/cyr_dbtool.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/cyr_dbtool.c	2007-08-14 16:29:52.000000000 +0200
@@ -203,7 +203,7 @@
     cyrus_init(alt_config, "cyr_dbtool", 0);
 
 
-    r = DB_OLD->open(old_db, db_flags, &odb);
+    r = (DB_OLD->open)(old_db, db_flags, &odb);
     if(r != CYRUSDB_OK)
 	fatal("can't open database", EC_TEMPFAIL);
 
@@ -250,7 +250,7 @@
         printf("Unknown action %s\n", action);
     }
 
-    DB_OLD->close(odb);
+    (DB_OLD->close)(odb);
     
     cyrus_done();
 
--- cyrus-imapd-2.3.9/imap/seen_db.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/seen_db.c	2007-08-14 16:32:46.000000000 +0200
@@ -157,7 +157,7 @@
     /* otherwise, close the existing database */
     if (seendb) {
 	abortcurrent(seendb);
-	r = DB->close(seendb->db);
+	r = (DB->close)(seendb->db);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing seendb: %s", 
 		   cyrusdb_strerror(r));
@@ -170,7 +170,7 @@
 
     /* open the seendb corresponding to user */
     fname = seen_getpath(user);
-    r = DB->open(fname, (flags & SEEN_CREATE) ? CYRUSDB_CREATE : 0,
+    r = (DB->open)(fname, (flags & SEEN_CREATE) ? CYRUSDB_CREATE : 0,
 		 &seendb->db);
     if (r != 0) {
 	int level = (flags & SEEN_CREATE) ? LOG_ERR : LOG_DEBUG;
@@ -416,7 +416,7 @@
 
 	/* free the old database hanging around */
 	abortcurrent(lastseen);
-	r = DB->close(lastseen->db);
+	r = (DB->close)(lastseen->db);
 	if (r != CYRUSDB_OK) {
 	    syslog(LOG_ERR, "DBERROR: error closing lastseen: %s",
 		   cyrusdb_strerror(r));
@@ -555,7 +555,7 @@
 
     if (lastseen) {
 	abortcurrent(lastseen);
-	r = DB->close(lastseen->db);
+	r = (DB->close)(lastseen->db);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing lastseen: %s",
 		   cyrusdb_strerror(r));
@@ -653,10 +653,10 @@
     struct seen_merge_rock rock;
 
     /* xxx does this need to be CYRUSDB_CREATE? */
-    r = DB->open(tmpfile, CYRUSDB_CREATE, &tmp);
+    r = (DB->open)(tmpfile, CYRUSDB_CREATE, &tmp);
     if(r) goto done;
 	    
-    r = DB->open(tgtfile, CYRUSDB_CREATE, &tgt);
+    r = (DB->open)(tgtfile, CYRUSDB_CREATE, &tgt);
     if(r) goto done;
 
     rock.db = tgt;
@@ -669,8 +669,8 @@
 
  done:
 
-    if(tgt) DB->close(tgt);
-    if(tmp) DB->close(tmp);
+    if(tgt) (DB->close)(tgt);
+    if(tmp) (DB->close)(tmp);
     
     return r;
 }
--- cyrus-imapd-2.3.9/imap/fetchnews.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/imap/fetchnews.c	2007-08-14 16:30:14.000000000 +0200
@@ -94,7 +94,7 @@
 	    strcat(fname, FNAME_NEWSRCDB);
 	}
 
-	r = DB->open(fname, CYRUSDB_CREATE, &newsrc_db);
+	r = (DB->open)(fname, CYRUSDB_CREATE, &newsrc_db);
 	if (r != 0)
 	    syslog(LOG_ERR, "DBERROR: opening %s: %s", fname,
 		   cyrusdb_strerror(r));
@@ -112,7 +112,7 @@
     int r = 0;
 
     if (newsrc_dbopen) {
-	r = DB->close(newsrc_db);
+	r = (DB->close)(newsrc_db);
 	if (r) {
 	    syslog(LOG_ERR, "DBERROR: error closing fetchnews.db: %s",
 		   cyrusdb_strerror(r));
--- cyrus-imapd-2.3.9/lib/auth_pts.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/lib/auth_pts.c	2007-08-14 16:33:28.000000000 +0200
@@ -359,7 +359,7 @@
     
     strcpy(fnamebuf, config_dir);
     strcat(fnamebuf, PTS_DBFIL);
-    r = the_ptscache_db->open(fnamebuf, CYRUSDB_CREATE, &ptdb);
+    r = (the_ptscache_db->open)(fnamebuf, CYRUSDB_CREATE, &ptdb);
     if (r != 0) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s", fnamebuf,
 	       cyrusdb_strerror(ret));
@@ -501,7 +501,7 @@
     }
 
     /* close and unlock the database */
-    the_ptscache_db->close(ptdb);
+    (the_ptscache_db->close)(ptdb);
 
     return rc;
 }
--- cyrus-imapd-2.3.9/lib/test/rnddb.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/lib/test/rnddb.c	2007-08-14 16:34:50.000000000 +0200
@@ -133,7 +133,7 @@
 	srand(atoi(argv[2]));
     }
 
-    TRY(DB->open("scratch", &db));
+    TRY((DB->open)("scratch", &db));
 
     if (DB->consistent) {
 	TRY(DB->consistent(db));
@@ -291,7 +291,7 @@
 #endif
     }
 
-    TRY(DB->close(db));
+    TRY((DB->close)(db));
     TRY(DB->done());
 
     do_report();
--- cyrus-imapd-2.3.9/lib/test/cyrusdb.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/lib/test/cyrusdb.c	2007-08-14 16:34:37.000000000 +0200
@@ -70,15 +70,15 @@
 	    char *fname = buf + 5;
 
 	    if (db) { /* close it */
-		TRY(DB->close(db));
+		TRY((DB->close)(db));
 	    }
-	    TRY(DB->open(fname, 1, &db));
+	    TRY((DB->open)(fname, 1, &db));
 
 	    printf("ok\n");
 	} else if (!db) {
 	    TRY(db == NULL);
 	} else if (!strncasecmp(buf, "close", 5)) {
-	    TRY(DB->close(db));
+	    TRY((DB->close)(db));
 	    db = NULL;
 	    printf("ok\n");
 	} else if (!strncasecmp(buf, "put ", 4)) {
--- cyrus-imapd-2.3.9/lib/cyrusdb_berkeley.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/lib/cyrusdb_berkeley.c	2007-08-14 16:34:19.000000000 +0200
@@ -212,7 +212,7 @@
 	r = dbenv->set_cachesize(dbenv, 0, opt * 1024, 0);
 	if (r) {
 	    dbenv->err(dbenv, r, "set_cachesize");
-	    dbenv->close(dbenv, 0);
+	    (dbenv->close)(dbenv, 0);
 	    syslog(LOG_ERR, "DBERROR: set_cachesize(): %s", db_strerror(r));
 	    return CYRUSDB_IOERROR;
 	}
@@ -223,9 +223,9 @@
     flags |= DB_INIT_LOCK | DB_INIT_MPOOL | 
 	     DB_INIT_LOG | DB_INIT_TXN;
 #if (DB_VERSION_MAJOR > 3) || ((DB_VERSION_MAJOR == 3) && (DB_VERSION_MINOR > 0))
-    r = dbenv->open(dbenv, dbdir, flags, 0644); 
+    r = (dbenv->open)(dbenv, dbdir, flags, 0644); 
 #else
-    r = dbenv->open(dbenv, dbdir, NULL, flags, 0644); 
+    r = (dbenv->open)(dbenv, dbdir, NULL, flags, 0644); 
 #endif
     if (r) {
         if (do_retry && (r == ENOENT)) {
@@ -264,7 +264,7 @@
 
     if (--dbinit) return 0;
 
-    r = dbenv->close(dbenv, 0);
+    r = (dbenv->close)(dbenv, 0);
     dbinit = 0;
     if (r) {
 	syslog(LOG_ERR, "DBERROR: error exiting application: %s",
@@ -412,15 +412,15 @@
     if (flags & CYRUSDB_MBOXSORT) db->set_bt_compare(db, mbox_compar);
 
 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1
-    r = db->open(db, NULL, fname, NULL, type, dbflags | DB_AUTO_COMMIT, 0664);
+    r = (db->open)(db, NULL, fname, NULL, type, dbflags | DB_AUTO_COMMIT, 0664);
 #else
-    r = db->open(db, fname, NULL, type, dbflags, 0664);
+    r = (db->open)(db, fname, NULL, type, dbflags, 0664);
 #endif
 
     if (r != 0) {
 	int level = (flags & CYRUSDB_CREATE) ? LOG_ERR : LOG_DEBUG;
 	syslog(level, "DBERROR: opening %s: %s", fname, db_strerror(r));
-	r = db->close(db, DB_NOSYNC);
+	r = (db->close)(db, DB_NOSYNC);
         if (r != 0) {
             syslog(level, "DBERROR: closing %s: %s", fname, db_strerror(r));
         }
@@ -450,7 +450,7 @@
     assert(dbinit && db);
 
     /* since we're using txns, we can supply DB_NOSYNC */
-    r = a->close(a, DB_NOSYNC);
+    r = (a->close)(a, DB_NOSYNC);
     if (r != 0) {
 	syslog(LOG_ERR, "DBERROR: error closing: %s", db_strerror(r));
 	r = CYRUSDB_IOERROR;
--- cyrus-imapd-2.3.9/ptclient/ptloader.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/ptclient/ptloader.c	2007-08-14 16:35:25.000000000 +0200
@@ -167,7 +167,7 @@
 
     strcpy(fnamebuf, config_dir);
     strcat(fnamebuf, PTS_DBFIL);
-    r = DB->open(fnamebuf, CYRUSDB_CREATE, &ptsdb);
+    r = (DB->open)(fnamebuf, CYRUSDB_CREATE, &ptsdb);
     if (r != 0) {
 	syslog(LOG_ERR, "DBERROR: opening %s: %s", fnamebuf,
 	       cyrusdb_strerror(ret));
@@ -184,7 +184,7 @@
 {
     int r;
 
-    r = DB->close(ptsdb);
+    r = (DB->close)(ptsdb);
     if (r) {
 	syslog(LOG_ERR, "DBERROR: error closing ptsdb: %s",
 	       cyrusdb_strerror(r));
--- cyrus-imapd-2.3.9/ptclient/ptdump.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/ptclient/ptdump.c	2007-08-14 16:35:02.000000000 +0200
@@ -100,7 +100,7 @@
     /* open database */
     strcpy(fnamebuf, config_dir);
     strcat(fnamebuf, PTS_DBFIL);
-    r = config_ptscache_db->open(fnamebuf, CYRUSDB_CREATE, &ptdb);
+    r = (config_ptscache_db->open)(fnamebuf, CYRUSDB_CREATE, &ptdb);
     if(r != CYRUSDB_OK) {
 	fprintf(stderr,"error opening %s (%s)", fnamebuf,
 	       cyrusdb_strerror(r));
@@ -110,7 +110,7 @@
     /* iterate through db, wiping expired entries */
     config_ptscache_db->foreach(ptdb, "", 0, NULL, dump_cb, ptdb, NULL);
 
-    config_ptscache_db->close(ptdb);
+    (config_ptscache_db->close)(ptdb);
 
     cyrus_done();
 
--- cyrus-imapd-2.3.9/ptclient/ptexpire.c.openmacro	2007-08-14 16:21:29.000000000 +0200
+++ cyrus-imapd-2.3.9/ptclient/ptexpire.c	2007-08-14 16:35:14.000000000 +0200
@@ -148,7 +148,7 @@
     /* open database */
     strcpy(fnamebuf, config_dir);
     strcat(fnamebuf, PTS_DBFIL);
-    r = config_ptscache_db->open(fnamebuf, CYRUSDB_CREATE, &ptdb);
+    r = (config_ptscache_db->open)(fnamebuf, CYRUSDB_CREATE, &ptdb);
     if(r != CYRUSDB_OK) {
 	syslog(LOG_ERR, "error opening %s (%s)", fnamebuf,
 	       cyrusdb_strerror(r));
@@ -158,7 +158,7 @@
     /* iterate through db, wiping expired entries */
     config_ptscache_db->foreach(ptdb, "", 0, expire_p, expire_cb, ptdb, NULL);
 
-    config_ptscache_db->close(ptdb);
+    (config_ptscache_db->close)(ptdb);
 
     cyrus_done();
 

cyrus-imapd-2.3.9-rmquota+deletemailbox-0.2-1.diff:

--- NEW FILE cyrus-imapd-2.3.9-rmquota+deletemailbox-0.2-1.diff ---
diff -Naur cyrus-imapd-2.3.9/imap/ctl_cyrusdb.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/ctl_cyrusdb.c
--- cyrus-imapd-2.3.9/imap/ctl_cyrusdb.c	2007-03-30 21:40:20.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/ctl_cyrusdb.c	2007-08-21 16:49:06.000000000 +0300
@@ -133,7 +133,7 @@
     /* if it is MBTYPE_RESERVED, unset it & call mboxlist_delete */
     if(!r && (mbtype & MBTYPE_RESERVE)) {
 	if(!r) {
-	    r = mboxlist_deletemailbox(name, 1, NULL, NULL, 0, 0, 1);
+	    r = mboxlist_deletemailbox(name, 1, NULL, NULL, 0, 0, 1, 1);
 	    if(r) {
 		/* log the error */
 		syslog(LOG_ERR,
diff -Naur cyrus-imapd-2.3.9/imap/ctl_mboxlist.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/ctl_mboxlist.c
--- cyrus-imapd-2.3.9/imap/ctl_mboxlist.c	2007-07-18 21:56:11.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/ctl_mboxlist.c	2007-08-21 16:49:06.000000000 +0300
@@ -484,7 +484,7 @@
 	    
 	    wipe_head = wipe_head->next;
 	    
-	    ret = mboxlist_deletemailbox(me->mailbox, 1, "", NULL, 0, 1, 1);
+	    ret = mboxlist_deletemailbox(me->mailbox, 1, "", NULL, 0, 1, 1, 1);
 	    if(!ret) sync_log_mailbox(me->mailbox);
 	    if(ret) {
 		fprintf(stderr, "couldn't delete defunct mailbox %s\n",
diff -Naur cyrus-imapd-2.3.9/imap/imapd.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/imapd.c
--- cyrus-imapd-2.3.9/imap/imapd.c	2007-08-02 17:18:51.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/imapd.c	2007-08-21 16:49:28.000000000 +0300
@@ -4994,7 +4994,7 @@
 
     r = mboxlist_deletemailbox(name, imapd_userisadmin,
 			       imapd_userid, imapd_authstate,
-			       0, 0, 0);
+			       0, 0, 0, 1);
     
     if (!r) sync_log_mailbox(name);
 
@@ -5018,6 +5018,12 @@
     char *p;
     int domainlen = 0;
     int sync_lockfd = (-1);
+    int keepQuota = 1;
+
+    if(name && *name == '+') {
+        keepQuota = 0;
+        name++;
+    }
 
     r = (*imapd_namespace.mboxname_tointernal)(&imapd_namespace, name,
 					       imapd_userid, mailboxname);
@@ -5076,7 +5082,7 @@
 
 	r = mboxlist_deletemailbox(mailboxname, imapd_userisadmin,
 				   imapd_userid, imapd_authstate, 1-force,
-				   localonly, 0);
+				   localonly, 0, keepQuota);
     }
 
     /* was it a top-level user mailbox? */
@@ -6434,6 +6440,7 @@
 {
     int newquota = -1;
     int badresource = 0;
+    int rmquota = 0;
     int c;
     int force = 0;
     static struct buf arg;
@@ -6450,7 +6457,8 @@
     if (c != ')' || arg.s[0] != '\0') {
 	for (;;) {
 	    if (c != ' ') goto badlist;
-	    if (strcasecmp(arg.s, "storage") != 0) badresource = 1;
+	    if (strcasecmp(arg.s, "remove") == 0) rmquota = 1;
+	    else if (strcasecmp(arg.s, "storage") != 0) badresource = 1;
 	    c = getword(imapd_in, &arg);
 	    if (c != ' ' && c != ')') goto badlist;
 	    if (arg.s[0] == '\0') goto badlist;
@@ -6519,7 +6527,10 @@
 
     /* local mailbox */
     if (!r || (r == IMAP_MAILBOX_NONEXISTENT)) {
-	r = mboxlist_setquota(mailboxname, newquota, force);
+        if(!rmquota) 
+	    r = mboxlist_setquota(mailboxname, newquota, force);
+	else 
+	    r = mboxlist_unsetquota(mailboxname);
     }
 
     imapd_check(NULL, 0, 0);
@@ -8237,7 +8248,7 @@
 	    /* note also that we need to remember to let proxyadmins do this */
 	    r = mboxlist_deletemailbox(mailboxname,
 				       imapd_userisadmin || imapd_userisproxyadmin,
-				       imapd_userid, imapd_authstate, 0, 1, 0);
+				       imapd_userid, imapd_authstate, 0, 1, 0, 1);
 	    if(r) syslog(LOG_ERR,
 			 "Could not delete local mailbox during move of %s",
 			 mailboxname);
diff -Naur cyrus-imapd-2.3.9/imap/mailbox.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mailbox.c
--- cyrus-imapd-2.3.9/imap/mailbox.c	2007-07-20 17:21:57.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mailbox.c	2007-08-21 16:49:06.000000000 +0300
@@ -2745,27 +2745,7 @@
 
     seen_delete_mailbox(mailbox);
 
-    if (delete_quota_root && !rquota) {
-	quota_delete(&mailbox->quota, &tid);
-	free(mailbox->quota.root);
-	mailbox->quota.root = NULL;
-    } else if (!rquota) {
-	/* Free any quota being used by this mailbox */
-	if (mailbox->quota.used >= mailbox->quota_mailbox_used) {
-	    mailbox->quota.used -= mailbox->quota_mailbox_used;
-	}
-	else {
-	    mailbox->quota.used = 0;
-	}
-	r = quota_write(&mailbox->quota, &tid);
-	if (r) {
-	    syslog(LOG_ERR,
-		   "LOSTQUOTA: unable to record free of " UQUOTA_T_FMT " bytes in quota %s",
-		   mailbox->quota_mailbox_used, mailbox->quota.root);
-	}
-	else
-	    quota_commit(&tid);
-    }
+    mailbox_updatequota(mailbox,NULL);
 
     /* Flush data (message file) directory */
     mailbox_delete_files(mailbox->path);
@@ -3394,3 +3374,48 @@
 	if (*p == '.') *p = '/';
     }
 }
+
+/* This function is used to update the quota. Can be used to replace
+ * identical parts of the code, and can be quite handy some times
+ * The tid is used in order to make possible to make the quota update
+ * being a part of a bigger transaction to the quota db */
+int mailbox_updatequota(struct mailbox *mailbox, struct txn **tid)
+{
+    int r = 0, havetid = 0;
+    struct txn **ltid = NULL;
+
+    if(tid) {
+        ltid = tid;
+        havetid = 1;
+    }
+    /* Ensure that we are locked */
+    if(!mailbox->header_lock_count) return IMAP_INTERNAL;
+
+
+    if(mailbox->quota.root) {
+        r = quota_read(&mailbox->quota, ltid, 1);
+        if( r == 0 ) {
+            if (mailbox->quota.used >= mailbox->quota_mailbox_used) {
+                mailbox->quota.used -= mailbox->quota_mailbox_used;
+            }
+            else {
+                mailbox->quota.used = 0;
+            }
+            r = quota_write(&mailbox->quota, ltid);
+            if (r) {
+                syslog(LOG_ERR,
+                   "LOSTQUOTA: unable to record free of %lu bytes in quota %s",
+                   mailbox->quota_mailbox_used, mailbox->quota.root);
+            }
+            else if(!havetid)
+                quota_commit(tid);
+        }
+        /* It is not a big mistake not to have quota .. just remove from the mailbox */
+        else if ( r == IMAP_QUOTAROOT_NONEXISTENT) {
+                free(mailbox->quota.root);
+                r = 0;
+        }
+    }
+    return r;
+}
+
diff -Naur cyrus-imapd-2.3.9/imap/mailbox.h cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mailbox.h
--- cyrus-imapd-2.3.9/imap/mailbox.h	2006-11-30 19:11:19.000000000 +0200
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mailbox.h	2007-08-21 16:49:06.000000000 +0300
@@ -364,6 +364,8 @@
 			  struct mailbox *mailboxp);
 extern int mailbox_delete(struct mailbox *mailbox, int delete_quota_root);
 
+extern int mailbox_updatequota(struct mailbox *mailbox, struct txn **tid);
+
 extern int mailbox_rename_copy(struct mailbox *oldmailbox, 
 			       const char *newname, char *newpartition,
 			       bit32 *olduidvalidityp, bit32 *newuidvalidityp,
diff -Naur cyrus-imapd-2.3.9/imap/mboxlist.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mboxlist.c
--- cyrus-imapd-2.3.9/imap/mboxlist.c	2007-08-15 20:20:55.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mboxlist.c	2007-08-21 16:49:06.000000000 +0300
@@ -95,6 +95,12 @@
 static int mboxlist_opensubs();
 static void mboxlist_closesubs();
 
+static int child_cb(char *name,
+                    int matchlen __attribute__((unused)),
+                    int maycreate __attribute__((unused)),
+                    void *rock);
+
+
 static int mboxlist_rmquota(const char *name, int matchlen, int maycreate,
 			    void *rock);
 static int mboxlist_changequota(const char *name, int matchlen, int maycreate,
@@ -102,6 +108,7 @@
 
 struct change_rock {
     struct quota *quota;
+    struct quota *oldquota;
     struct txn **tid;
 };
 
@@ -889,9 +896,9 @@
  */
 int mboxlist_deletemailbox(const char *name, int isadmin, char *userid, 
 			   struct auth_state *auth_state, int checkacl,
-			   int local_only, int force)
+			   int local_only, int force, int keepQuota)
 {
-    int r;
+    int r, has_children = 0;
     char *acl;
     long access;
     struct mailbox mailbox;
@@ -902,6 +909,7 @@
     int mbtype;
     const char *p;
     mupdate_handle *mupdate_h = NULL;
+    char *quotaroot = NULL;
 
     if(!isadmin && force) return IMAP_PERMISSION_DENIED;
 
@@ -1014,15 +1022,47 @@
 
     if ((r && !force) || isremote) goto done;
 
-    if (!r || force) r = mailbox_delete(&mailbox, deletequotaroot);
+    if (!r || force) {
+        /* first we have to keep the previous quota root in order to delete it */
+        if(mailbox.quota.root)
+                quotaroot = xstrdup(mailbox.quota.root);
+        r = mailbox_delete(&mailbox, deletequotaroot);
+    }
+
 
     /*
      * See if we have to remove mailbox's quota root
      */
-    if (!r && mailbox.quota.root != NULL) {
-	/* xxx look for any other mailboxes in this quotaroot */
+    if (!r && quotaroot != NULL) {
+        /* xxx look for any other mailboxes in this quotaroot */
+        /* If we have not asked to remove the quota (default behaviour), we check
+         * whether there are any subfolders beneeth the quota root. If there aren't
+         * any subfolders the reasonable thing is to delete the quota */
+        if(keepQuota) {
+            char pattern[MAX_MAILBOX_PATH+1];
+            strlcpy(pattern, quotaroot, sizeof(pattern));
+            if (config_virtdomains && name[strlen(name)-1] == '!') {
+                strlcat(pattern, "*", sizeof(pattern));
+            }
+            else {
+                strlcat(pattern, ".*", sizeof(pattern));
+            }   
+                /* find if there are subfolders. Then we want to
+                 * keep the existing quota */
+            mboxlist_findall(NULL, pattern, isadmin, userid,
+                    auth_state, child_cb, (void *) &has_children);
+
+            if(!has_children)
+                if(!mboxlist_mylookup(quotaroot, NULL, NULL, NULL, NULL, NULL, 0, 1))
+                    has_children = 1;
+        }
+        /* If we want to remove the quota explicitely or the quota root folder has no subfolders
+         * we execute the rmquota patch */
+        if(!keepQuota || !has_children )
+            mboxlist_unsetquota(quotaroot);
+        free(quotaroot);
     }
-
+    
  done:
     if(r && tid && !force) {
 	/* Abort the transaction if it is still in progress */
@@ -2483,6 +2523,7 @@
     if (r) return r;
 
     crock.quota = "a;
+    crock.oldquota = NULL;
     crock.tid = &tid;
     /* top level mailbox */
     if(have_mailbox)
@@ -2501,15 +2542,19 @@
  */
 int mboxlist_unsetquota(const char *root)
 {
+    char newquota[MAX_MAILBOX_PATH+1];
     char pattern[MAX_MAILBOX_PATH+1];
     struct quota quota;
-    int r=0;
+    struct change_rock crock;
+    int r=0, k=0;
 
     if (!root[0] || root[0] == '.' || strchr(root, '/')
 	|| strchr(root, '*') || strchr(root, '%') || strchr(root, '?')) {
 	return IMAP_MAILBOX_BADNAME;
     }
     
+    crock.tid=NULL;
+    
     quota.root = (char *) root;
     r = quota_read(&quota, NULL, 0);
     if (r == IMAP_QUOTAROOT_NONEXISTENT) {
@@ -2534,9 +2579,47 @@
     /* submailboxes - we're using internal names here */
     mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_rmquota, (void *)root);
 
-    r = quota_delete(&quota, NULL);
+    r = quota_delete(&quota, crock.tid);
+
+    /* If we cannot delete the quota then abort the operation */
+    if(!r) {
+       /* quota_findroot performs several checks that we can
+        * assume that are already done, and don't have to perform
+        * them again. One of them is that it returns 1 only if
+        * quotaroot exists.
+        */
+        if(quota_findroot(newquota, sizeof(newquota), root)) {
+            struct quota rootquota;
+            rootquota.root = newquota;
+            k = quota_read(&rootquota, crock.tid, 0);
+            if (!k) {
+                crock.quota = &rootquota;
+                crock.oldquota = "a;
+                /* top level mailbox */
+                k = mboxlist_changequota(root, 0, 0, &crock);
+            }
+            /* submailboxes - we're using internal names here */
+            if (!k)
+                k = mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_changequota, &crock);
+            if(!k)
+                k = quota_write(&rootquota, crock.tid);
+
+         }
+         else {
+           /* top level mailbox */
+           mboxlist_rmquota(root, 0, 0, (void *)root);
+           /* submailboxes - we're using internal names here */
+           mboxlist_findall(NULL, pattern, 1, 0, 0, mboxlist_rmquota, (void *)root);
+       }
+    }
+
+    if(!r && !k)
+        quota_commit(crock.tid);
+    else
+        quota_abort(crock.tid);
 
     return r;
+
 }
 
 /*
@@ -2632,6 +2715,7 @@
     struct mailbox mailbox;
     struct change_rock *crock = (struct change_rock *) rock;
     struct quota *mboxlist_newquota = crock->quota;
+    struct quota *mboxlist_oldquota = crock->oldquota;
     struct txn **tid = crock->tid;
 
     assert(rock != NULL);
@@ -2649,27 +2733,24 @@
     if (r) goto error;
 
     if (mailbox.quota.root) {
-	if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) {
-	    /* Part of a child quota root */
-	    mailbox_close(&mailbox);
-	    return 0;
-	}
-
-	r = quota_read(&mailbox.quota, tid, 1);
-	if (r) goto error;
-	if (mailbox.quota.used >= mailbox.quota_mailbox_used) {
-	    mailbox.quota.used -= mailbox.quota_mailbox_used;
-	}
-	else {
-	    mailbox.quota.used = 0;
-	}
-	r = quota_write(&mailbox.quota, tid);
-	if (r) {
-	    syslog(LOG_ERR,
-		   "LOSTQUOTA: unable to record free of " UQUOTA_T_FMT " bytes in quota %s",
-		   mailbox.quota_mailbox_used, mailbox.quota.root);
-	}
-	free(mailbox.quota.root);
+        if(mboxlist_oldquota) {
+            if (strlen(mailbox.quota.root) > strlen(mboxlist_oldquota->root)) {
+                /* Part of a child quota root */
+                mailbox_close(&mailbox);
+                return 0;
+            }
+        }
+        else {
+            if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) {
+                /* Part of a child quota root */
+                mailbox_close(&mailbox);
+                return 0;
+            }
+        }
+
+        r = mailbox_updatequota(&mailbox,tid);
+        if (r)
+            goto error;
     }
 
     mailbox.quota.root = xstrdup(mboxlist_newquota->root);
@@ -2682,6 +2763,11 @@
 
  error:
     mailbox_close(&mailbox);
+    syslog(LOG_ERR, "LOSTQUOTA: unable to change quota root for %s to %s: %s. \
+                        Command aborted. Run reconstruct to make sure mailboxes \
+                         are in consistent state",
+           name, mboxlist_newquota->root, error_message(r));
+    return 1;
  error_noclose:
     syslog(LOG_ERR, "LOSTQUOTA: unable to change quota root for %s to %s: %s",
 	   name, mboxlist_newquota->root, error_message(r));
diff -Naur cyrus-imapd-2.3.9/imap/mboxlist.h cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mboxlist.h
--- cyrus-imapd-2.3.9/imap/mboxlist.h	2006-11-30 19:11:19.000000000 +0200
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/mboxlist.h	2007-08-21 16:49:06.000000000 +0300
@@ -126,7 +126,7 @@
  * the planet */
 int mboxlist_deletemailbox(const char *name, int isadmin, char *userid, 
 			   struct auth_state *auth_state, int checkacl,
-			   int local_only, int force);
+			   int local_only, int force, int keepQuota);
 
 /* Rename/move a mailbox (hierarchical) */
 int mboxlist_renamemailbox(char *oldname, char *newname, char *partition, 
diff -Naur cyrus-imapd-2.3.9/imap/nntpd.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/nntpd.c
--- cyrus-imapd-2.3.9/imap/nntpd.c	2007-03-30 21:51:01.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/nntpd.c	2007-08-21 16:49:06.000000000 +0300
@@ -3358,7 +3358,7 @@
     /* XXX should we delete right away, or wait until empty? */
 
     r = mboxlist_deletemailbox(mailboxname, 0,
-			       newsmaster, newsmaster_authstate, 1, 0, 0);
+			       newsmaster, newsmaster_authstate, 1, 0, 0, 1);
 
     if (!r) sync_log_mailbox(mailboxname);
 
diff -Naur cyrus-imapd-2.3.9/imap/sync_reset.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/sync_reset.c
--- cyrus-imapd-2.3.9/imap/sync_reset.c	2007-03-30 21:40:21.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/sync_reset.c	2007-08-21 16:49:06.000000000 +0300
@@ -258,7 +258,7 @@
     if (r) goto fail;
 
     for (item = list->head ; item ; item = item->next) {
-        r=mboxlist_deletemailbox(item->name, 1, NULL, sync_authstate, 1, 0, 0);
+        r=mboxlist_deletemailbox(item->name, 1, NULL, sync_authstate, 1, 0, 0, 1);
 
         if (r) goto fail;
     }
@@ -274,7 +274,7 @@
     if (r) goto fail;
 
     for (item = list->head ; item ; item = item->next) {
-        r=mboxlist_deletemailbox(item->name, 1, NULL, sync_authstate, 1, 0, 0);
+        r=mboxlist_deletemailbox(item->name, 1, NULL, sync_authstate, 1, 0, 0, 1);
 
         if (r) goto fail;
     }
@@ -282,7 +282,7 @@
 
     /* Nuke inbox (recursive nuke possible?) */
     snprintf(buf, sizeof(buf)-1, "user.%s", user);
-    r = mboxlist_deletemailbox(buf, 1, "cyrus", sync_authstate, 1, 0, 0);
+    r = mboxlist_deletemailbox(buf, 1, "cyrus", sync_authstate, 1, 0, 0, 1);
     if (r && (r != IMAP_MAILBOX_NONEXISTENT)) goto fail;
 
     if ((r=user_deletedata(user, sync_userid, sync_authstate, 1)))
diff -Naur cyrus-imapd-2.3.9/imap/sync_server.c cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/sync_server.c
--- cyrus-imapd-2.3.9/imap/sync_server.c	2007-08-01 22:19:03.000000000 +0300
+++ cyrus-imapd-2.3.9-rmquota+deletemailbox.uncompiled/imap/sync_server.c	2007-08-21 16:49:06.000000000 +0300
@@ -1590,7 +1590,7 @@
 
     for (item = list->head ; item ; item = item->next) {
         r=mboxlist_deletemailbox(item->name, sync_userisadmin, sync_userid,
-				 sync_authstate, 0, 0, 1);
+				 sync_authstate, 0, 0, 1, 1);
 
         if (r) goto fail;
     }
@@ -1600,7 +1600,7 @@
     (sync_namespacep->mboxname_tointernal)(sync_namespacep, "INBOX",
 					   user, buf);
     r = mboxlist_deletemailbox(buf, sync_userisadmin, sync_userid,
-			       sync_authstate, 0, 0, 1);
+			       sync_authstate, 0, 0, 1, 1);
     if (r && (r != IMAP_MAILBOX_NONEXISTENT)) goto fail;
 
     if ((r=user_deletedata(user, sync_userid, sync_authstate, 1)))
@@ -2546,7 +2546,7 @@
 
     /* Delete with admin priveleges */
     r = mboxlist_deletemailbox(name, sync_userisadmin, sync_userid,
-			       sync_authstate, 0, 0, 1);
+			       sync_authstate, 0, 0, 1, 1);
 
     if (r)
         prot_printf(sync_out, "NO Failed to delete %s: %s\r\n",


Index: .cvsignore
===================================================================
RCS file: /cvs/extras/rpms/cyrus-imapd/F-7/.cvsignore,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- .cvsignore	4 Apr 2007 15:18:08 -0000	1.7
+++ .cvsignore	28 Aug 2007 11:44:11 -0000	1.8
@@ -1,3 +1,3 @@
 cyrus_sharedbackup-0.1.tar.gz
-cyrus-imapd-2.3.8.tar.gz
-cyrus-imapd-2.3.8.tar.gz.sig
+cyrus-imapd-2.3.9.tar.gz
+cyrus-imapd-2.3.9.tar.gz.sig


Index: cyrus-imapd.spec
===================================================================
RCS file: /cvs/extras/rpms/cyrus-imapd/F-7/cyrus-imapd.spec,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- cyrus-imapd.spec	23 Jul 2007 12:38:38 -0000	1.25
+++ cyrus-imapd.spec	28 Aug 2007 11:44:11 -0000	1.26
@@ -1,6 +1,7 @@
+%define upstream_ver 2.3.9
 Name: cyrus-imapd
-Version: 2.3.8
-Release: 3.2%{?dist}
+Version: 2.3.9
+Release: 6%{?dist}
 
 # ********************** BUILD TIME OPTIONS START **********************
 
@@ -25,8 +26,6 @@
 %{!?FORCESYNCEXT3: %define FORCESYNCEXT3 0}
 # include autocreate feature
 %{!?AUTOCREATE: %define AUTOCREATE 1}
-# include groupcache feature
-%{!?GROUPCACHE: %define GROUPCACHE 1}
 # don't check for RFC compliant line termination (bare newlines)
 %{!?NO_BARE_NL: %define NO_BARE_NL 0}
 # used syslog facility for logging
@@ -90,14 +89,16 @@
 %endif
 
 Summary: A high-performance mail server with IMAP, POP3, NNTP and SIEVE support
-License: BSD
+# BSD with advertising: imap/setproctitle.c, lib/mkgmtime.c, lib/sysexits.h
+# the rest is CMU
+License: MIT and BSD with advertising
 Group: System Environment/Daemons
 URL: http://cyrusimap.web.cmu.edu/
 #Packager: Simon Matter <simon.matter at invoca.ch>
 #Vendor: Invoca Systems
 #Distribution: Invoca Linux Server
-Source0: ftp://ftp.andrew.cmu.edu/pub/cyrus/%{name}-%{version}.tar.gz
-Source1: ftp://ftp.andrew.cmu.edu/pub/cyrus/%{name}-%{version}.tar.gz.sig
+Source0: ftp://ftp.andrew.cmu.edu/pub/cyrus/%{name}-%{upstream_ver}.tar.gz
+Source1: ftp://ftp.andrew.cmu.edu/pub/cyrus/%{name}-%{upstream_ver}.tar.gz.sig
 #Source2: http://ftp.gnu.org/gnu/autoconf/autoconf-%{_acversion}.tar.gz
 Source3: cyrus-deliver-wrapper.c
 Source4: cyrus-user-procmailrc.template
@@ -127,18 +128,15 @@
 Source28: cyrus-imapd.rpm_set_permissions
 Source29: cyrus-imapd-sendmail-8.12.9-cyrusv2.m4
 Source30: cyrus-imapd-README.contrib
-Source31: cyrus-imapd-README.groupcache
-Source32: cyrus-imapd.upd_groupcache
 Source33: cyrus-imapd-README.skiplist_recovery
 Patch0: cyrus-imapd-2.2.12-no_transfig.patch
-Patch1: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-autocreate-0.10-0.diff
-Patch2: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-autosieve-0.6.0.diff
-Patch3: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.8/cyrus-imapd-2.3.8-rmquota+deletemailbox-0.2-1.diff
+Patch1: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.9/cyrus-imapd-2.3.9-autocreate-0.10-0.diff
+Patch2: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.9/cyrus-imapd-2.3.9-autosieve-0.6.0.diff
+Patch3: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.9/cyrus-imapd-2.3.9-rmquota+deletemailbox-0.2-1.diff
 Patch4: http://servercc.oakton.edu/~jwade/cyrus/cyrus-imapd-2.1.3/cyrus-imapd-2.1.3-flock.patch
 Patch5: cyrus-imapd-2.2.12-munge8bit.patch
 Patch6: cyrus-imapd-2.1.16-getrlimit.patch
 Patch7: cyrus-imapd-2.3.7-nobarenewlinescheck.patch
-Patch8: cyrus-imapd-2.2.10-groupcache.patch
 Patch9: cyrus-imapd-2.3.1-config_defaults.patch
 Patch10: cyrus-imapd-acceptinvalidfrom.patch
 Patch11: cyrus-imapd-2.2.12-dam_invalid_id-christos.patch
@@ -149,13 +147,14 @@
 Patch16: cyrus-imapd-2.3.7-db4.5.patch
 Patch17: cyrus-imapd-2.3.7-makeinstallfix.patch
 Patch18: cyrus-imapd-2.3.7-krb4.patch
+Patch20: cyrus-imapd-2.3.8-getgrouplist.patch
 # Patches >= 100 are / will be fixed in CVS
 Patch100: cyrus-imapd-2.3.1-make_md5.patch
 Patch101: cyrus-imapd-2.3.1-backend_sigsegv.patch
 Patch102: cyrus-imapd-2.3.1-replication_policycheck.patch
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
 BuildRequires: autoconf >= 2.59
-BuildRequires: cyrus-sasl-devel >= 2.1.15-1, perl, tcp_wrappers
+BuildRequires: cyrus-sasl-devel >= 2.1.15-1, perl, perl-devel, tcp_wrappers
 BuildRequires: %{_dbver}-devel, openssl-devel, pkgconfig
 BuildRequires: flex, bison, groff >= 1.15-8, automake
 BuildRequires: openldap-devel
@@ -246,20 +245,18 @@
 %if %{NO_BARE_NL}
 %patch7 -p1 -b .nobarenewlinescheck
 %endif
-%if %{GROUPCACHE}
-%patch8 -p1 -b .groupcache
-%endif
 #%patch9 -p1 -b .config_defaults
 %patch10 -p1 -b .acceptinvalidfrom
 # fixed upstream already
 #%patch11 -p1 -b .dam_invalid_id
 %patch12 -p1 -b .notify_sms
-%patch13 -p0 -b .allow_auth_plain
+#%patch13 -p0 -b .allow_auth_plain
 %patch14 -p1 -b .authid_normalize
 %patch15 -p1 -b .make_md5_defaults
-%patch16 -p1 -b .db4.5
-%patch17 -p1 -b .makeinstallfix
+#%patch16 -p1 -b .db4.5
+#%patch17 -p1 -b .makeinstallfix
 %patch18 -p1 -b .krb4
+%patch20 -p1 -b .getgrouplist
 # fixed upstream
 #%patch100 -p1 -b .make_md5
 # fixed upstream
@@ -354,9 +351,6 @@
 
 %{__install} -m 644 %{SOURCE23}	doc/README.RPM
 %{__install} -m 644 %{SOURCE24}	doc/README.HOWTO-recover-mailboxes.db
-%if %{GROUPCACHE}
-%{__install} -m 644 %{SOURCE31}	doc/README.groupcache
-%endif
 %{__install} -m 644 %{SOURCE33} doc/README.skiplist_recovery
 %if %{AUTOCREATE}
 %{__install} -m 644 %{SOURCE8}  doc/README.autocreate
@@ -425,9 +419,6 @@
 
 # Install additional files
 %{__install} -m 755 %{SOURCE13}   %{buildroot}%{_cyrexecdir}/cvt_cyrusdb_all
-%if %{GROUPCACHE}
-%{__install} -m 755 %{SOURCE32}   %{buildroot}%{_cyrexecdir}/upd_groupcache
-%endif
 %{__install} -m 755 %{SOURCE28}   %{buildroot}%{_cyrexecdir}/rpm_set_permissions
 %{__install} -m 644 %{SOURCE14}   %{buildroot}%{_datadir}/%{name}/rpm/magic
 %{__install} -m 644 %{SOURCE10}   %{_contribdir}/
@@ -735,9 +726,6 @@
 %attr(0755,root,root) %{_cyrexecdir}/unexpunge
 %attr(0755,root,root) %{_cyrexecdir}/upgradesieve
 %attr(0755,root,root) %{_cyrexecdir}/cvt_cyrusdb_all
-%if %{GROUPCACHE}
-%attr(0755,root,root) %{_cyrexecdir}/upd_groupcache
-%endif
 %attr(0755,root,root) %{_cyrexecdir}/rpm_set_permissions
 %if %{IDLED}
 %attr(0755,root,root) %{_cyrexecdir}/idled
@@ -810,6 +798,21 @@
 %{_mandir}/man1/*
 
 %changelog
+* Wed Aug 22 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.9-6
+- update to latest upstream
+- updated all patches from uoa and reenabled rmquota+deletemailbox
+
+* Thu Aug 16 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.9-5.rc2
+- update to latest upstream beta
+
+* Tue Aug 14 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.9-4.rc1
+- update to latest upstream beta
+- temporarily dropped the rmquota+deletemailbox patch (doesn't apply)
+- fixed to compile with newer glibc
+- added the getgrouplist patch from RHEL-4, dropped groupcache patch
+- dropped the allow_auth_plain patch
+- buildrequire perl-devel
+
 * Mon Jul 23 2007 Tomas Janousek <tjanouse at redhat.com> - 2.3.8-3.2
 - removed the lm_sensors-devel dependency, since it's properly required in
   net-snmp-devel


Index: sources
===================================================================
RCS file: /cvs/extras/rpms/cyrus-imapd/F-7/sources,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- sources	12 Mar 2007 16:40:35 -0000	1.9
+++ sources	28 Aug 2007 11:44:11 -0000	1.10
@@ -1,3 +1,3 @@
 8f7a26b0556369827bb5c8084a3e3ea1  cyrus_sharedbackup-0.1.tar.gz
-ac03b02c1ae08d52f807b58c488b204f  cyrus-imapd-2.3.8.tar.gz
-5e2d00f15ca5389d9717ed637fd6c476  cyrus-imapd-2.3.8.tar.gz.sig
+113433c1fdc777e3b0466b5ce643b8bc  cyrus-imapd-2.3.9.tar.gz
+030f3c404f6a2e8d53cd08722bca0176  cyrus-imapd-2.3.9.tar.gz.sig




More information about the fedora-extras-commits mailing list