diff --git a/.cvsignore b/.cvsignore index ccc5846..22c4f84 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,3 +1,2 @@ -cyrus-imapd-2.2.12.tar.gz -cyrus-imapd-README.HOWTO-recover-mailboxes.db +cyrus-imapd-2.3.1.tar.gz cyrus_sharedbackup-0.1.tar.gz diff --git a/README.autocreate-cyrus-2.2 b/README.autocreate-cyrus-2.2 deleted file mode 100644 index f7d8291..0000000 --- a/README.autocreate-cyrus-2.2 +++ /dev/null @@ -1,181 +0,0 @@ -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 e-mail account creation procedure. -Hence, to create a new e-mail 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 uncareful 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 authorization 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 authorizationID 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 authenticatedID 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 e-mail message addressed to the user has been received. - -ii) The recipient is not any of the imap_admins or admins accounts. -Note that passing e-mails 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 meaningfull. - -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 apropriate 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. - - - -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 e-mail recipient before sending the e-mail 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 authorized 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 -optimized, 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. - - - -Things to be done -================= - -1. Support MURDER architecture. - - -For more information and updates please visit http://email.uoa.gr/autocreate - diff --git a/README.autocreate-cyrus-2.3 b/README.autocreate-cyrus-2.3 new file mode 100644 index 0000000..7a7087e --- /dev/null +++ b/README.autocreate-cyrus-2.3 @@ -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. + + + +Things to be done +================= + +1. Support MUPDATE + +It is within the developers' intentions to support the mupdate protocol, but serious +design issues on future cyrus releases have to resolved first. + +2. Select different attributes (quota, partition, sieve filter, etc) depending on the group +a user belongs to. + +For more information and updates please visit http://email.uoa.gr/projects/cyrus/autocreate + diff --git a/allow_auth_plain_proxying.patch b/allow_auth_plain_proxying.patch new file mode 100644 index 0000000..33e067c --- /dev/null +++ b/allow_auth_plain_proxying.patch @@ -0,0 +1,28 @@ +--- imap/imapd.c ++++ imap/imapd.c 2004/01/16 12:25:51 +@@ -578,8 +578,11 @@ + fatal("SASL failed initializing: sasl_server_new()", EC_TEMPFAIL); + } + +- /* never allow plaintext, since IMAP has the LOGIN command */ +- secprops = mysasl_secprops(SASL_SEC_NOPLAINTEXT); ++ if( (config_getswitch(IMAPOPT_ALLOWPLAINWITHOUTTLS) == 0) ) { ++ secprops = mysasl_secprops(SASL_SEC_NOPLAINTEXT); ++ } else { ++ secprops = mysasl_secprops(0); ++ } + sasl_setprop(imapd_saslconn, SASL_SEC_PROPS, secprops); + sasl_setprop(imapd_saslconn, SASL_SSF_EXTERNAL, &extprops_ssf); + +--- lib/imapoptions ++++ lib/imapoptions 2004/01/16 12:27:52 +@@ -684,6 +684,9 @@ + to set this to yes, especially if OpenLDAP is used as authentication + source. */ + ++{ "allowplainwithouttls", 0, SWITCH } ++/* Allow plain login mechanism without an encrypted connection. */ ++ + /* + .SH SEE ALSO + .PP diff --git a/cyrus-imapd-2.1.9-fdatasync.patch b/cyrus-imapd-2.1.9-fdatasync.patch deleted file mode 100644 index c2d4607..0000000 --- a/cyrus-imapd-2.1.9-fdatasync.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- lib/cyrusdb_skiplist.c.orig Tue Apr 23 20:25:48 2002 -+++ lib/cyrusdb_skiplist.c Wed May 8 13:49:23 2002 -@@ -69,6 +69,11 @@ - - #define PROB (0.5) - -+#ifdef __FreeBSD__ -+/* #define fdatasync(fd) fsync(fd) */ -+#define O_DSYNC 0 -+#endif -+ - /* - * - * disk format; all numbers in network byte order diff --git a/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.1.diff b/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.1.diff deleted file mode 100644 index a003fc9..0000000 --- a/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.1.diff +++ /dev/null @@ -1,491 +0,0 @@ -diff -Naur cyrus-imapd-2.2.10/imap/ctl_cyrusdb.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/ctl_cyrusdb.c ---- cyrus-imapd-2.2.10/imap/ctl_cyrusdb.c 2004-07-13 05:34:20.000000000 +0300 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/ctl_cyrusdb.c 2004-11-24 13:30:54.000000000 +0200 -@@ -136,7 +136,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.2.10/imap/ctl_mboxlist.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/ctl_mboxlist.c ---- cyrus-imapd-2.2.10/imap/ctl_mboxlist.c 2004-05-22 06:45:48.000000000 +0300 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/ctl_mboxlist.c 2004-11-24 13:30:54.000000000 +0200 -@@ -456,7 +456,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) { - fprintf(stderr, "couldn't delete defunct mailbox %s\n", - me->mailbox); -diff -Naur cyrus-imapd-2.2.10/imap/imapd.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/imapd.c ---- cyrus-imapd-2.2.10/imap/imapd.c 2004-11-18 00:29:03.000000000 +0200 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/imapd.c 2004-11-24 13:30:54.000000000 +0200 -@@ -3725,7 +3725,7 @@ - - r = mboxlist_deletemailbox(name, imapd_userisadmin, - imapd_userid, imapd_authstate, -- 0, 0, 0); -+ 0, 0, 0, 1); - - if(r) { - prot_printf(imapd_out, "* NO delete %s: %s\r\n", -@@ -3744,6 +3744,12 @@ - char mailboxname[MAX_MAILBOX_NAME+1]; - char *p; - int domainlen = 0; -+ int keepQuota = 1; -+ -+ if(name && *name == '+') { -+ keepQuota = 0; -+ name++; -+ } - - r = (*imapd_namespace.mboxname_tointernal)(&imapd_namespace, name, - imapd_userid, mailboxname); -@@ -3754,7 +3760,7 @@ - - r = mboxlist_deletemailbox(mailboxname, imapd_userisadmin, - imapd_userid, imapd_authstate, 1, -- localonly, 0); -+ localonly, 0, keepQuota); - } - - /* was it a top-level user mailbox? */ -@@ -4715,6 +4721,7 @@ - { - int newquota = -1; - int badresource = 0; -+ int rmquota = 0; - int c; - int force = 0; - static struct buf arg; -@@ -4729,7 +4736,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; -@@ -4766,7 +4774,10 @@ - imapd_userid, mailboxname); - - if (!r) { -- r = mboxlist_setquota(mailboxname, newquota, force); -+ if(!rmquota) -+ r = mboxlist_setquota(mailboxname, newquota, force); -+ else -+ r = mboxlist_unsetquota(mailboxname); - } - } - -@@ -6413,7 +6424,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.2.10/imap/mailbox.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mailbox.c ---- cyrus-imapd-2.2.10/imap/mailbox.c 2004-05-22 06:45:51.000000000 +0300 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mailbox.c 2004-11-24 13:30:54.000000000 +0200 -@@ -2117,27 +2117,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 %lu bytes in quota %s", -- mailbox->quota_mailbox_used, mailbox->quota.root); -- } -- else -- quota_commit(&tid); -- } -+ mailbox_updatequota(mailbox,NULL); - - /* remove all files in directory */ - strlcpy(buf, mailbox->path, sizeof(buf)); -@@ -2751,3 +2731,49 @@ - 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.2.10/imap/mailbox.h cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mailbox.h ---- cyrus-imapd-2.2.10/imap/mailbox.h 2004-01-22 23:17:09.000000000 +0200 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mailbox.h 2004-11-24 13:30:54.000000000 +0200 -@@ -305,6 +305,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 *newpath, - bit32 *olduidvalidityp, bit32 *newuidvalidityp, -diff -Naur cyrus-imapd-2.2.10/imap/mboxlist.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mboxlist.c ---- cyrus-imapd-2.2.10/imap/mboxlist.c 2004-07-26 21:08:03.000000000 +0300 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mboxlist.c 2004-11-24 13:30:54.000000000 +0200 -@@ -93,6 +93,11 @@ - 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, -@@ -100,6 +105,7 @@ - - struct change_rock { - struct quota *quota; -+ struct quota *oldquota; - struct txn **tid; - }; - -@@ -893,9 +899,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; -@@ -907,6 +913,7 @@ - int deleteright = get_deleteright(); - const char *p; - mupdate_handle *mupdate_h = NULL; -+ char *quotaroot = NULL; - - if(!isadmin && force) return IMAP_PERMISSION_DENIED; - -@@ -1018,13 +1025,44 @@ - - 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) { -+ 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 )) -+ 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: -@@ -2357,6 +2395,7 @@ - if (r) return r; - - crock.quota = "a; -+ crock.oldquota = NULL; - crock.tid = &tid; - /* top level mailbox */ - if(have_mailbox) -@@ -2375,17 +2414,21 @@ - */ - 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("a, NULL, 0); -+ r = quota_read("a, crock.tid, 0); - if (r == IMAP_QUOTAROOT_NONEXISTENT) { - /* already unset */ - return 0; -@@ -2402,13 +2445,45 @@ - } - else - strlcat(pattern, ".*", sizeof(pattern)); -- -- /* 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); - -- r = quota_delete("a, NULL); -+ r = quota_delete("a, 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; - } -@@ -2506,6 +2581,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); -@@ -2523,27 +2599,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 %lu 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); -@@ -2553,18 +2626,24 @@ - mboxlist_newquota->used += mailbox.quota_mailbox_used; - mailbox_close(&mailbox); - return 0; -- -+ - 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)); -+ name, mboxlist_newquota->root, error_message(r)); - - /* Note, we're a callback, and it's not a huge tragedy if we - * fail, so we don't ever return a failure */ - return 0; - } - -+ - /* must be called after cyrus_init */ - void mboxlist_init(int myflags) - { -diff -Naur cyrus-imapd-2.2.10/imap/mboxlist.h cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mboxlist.h ---- cyrus-imapd-2.2.10/imap/mboxlist.h 2004-03-17 20:07:49.000000000 +0200 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mboxlist.h 2004-11-24 13:30:54.000000000 +0200 -@@ -122,7 +122,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.2.10/imap/mupdate.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mupdate.c ---- cyrus-imapd-2.2.10/imap/mupdate.c 2004-05-29 08:18:21.000000000 +0300 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/mupdate.c 2004-11-24 13:30:54.000000000 +0200 -@@ -2191,7 +2191,7 @@ - remote_boxes.head = r->next; - } else if (ret < 0) { - /* Local without corresponding remote, delete it */ -- mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0); -+ mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0, 1); - local_boxes.head = l->next; - } else /* (ret > 0) */ { - /* Remote without corresponding local, insert it */ -@@ -2206,7 +2206,7 @@ - if(l && !r) { - /* we have more deletes to do */ - while(l) { -- mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0); -+ mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0, 1); - local_boxes.head = l->next; - l = local_boxes.head; - } -diff -Naur cyrus-imapd-2.2.10/imap/nntpd.c cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/nntpd.c ---- cyrus-imapd-2.2.10/imap/nntpd.c 2004-09-09 19:21:26.000000000 +0300 -+++ cyrus-imapd-2.2.10.rmquota+deletemailbox.uncompiled/imap/nntpd.c 2004-11-24 13:30:54.000000000 +0200 -@@ -3234,7 +3234,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); - - return r; - } diff --git a/cyrus-imapd-2.2.12-autocreate-0.9.2.diff b/cyrus-imapd-2.2.12-autocreate-0.9.2.diff deleted file mode 100644 index b9458dc..0000000 --- a/cyrus-imapd-2.2.12-autocreate-0.9.2.diff +++ /dev/null @@ -1,2159 +0,0 @@ -diff -Naur cyrus-imapd-2.2.12/README.autocreate cyrus-imapd-2.2.12-autocreate.uncompiled/README.autocreate ---- cyrus-imapd-2.2.12/README.autocreate 1970-01-01 02:00:00 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/README.autocreate 2005-02-15 13:57:19 +0200 -@@ -0,0 +1,181 @@ -+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 e-mail account creation procedure. -+Hence, to create a new e-mail 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 uncareful 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 authorization 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 authorizationID 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 authenticatedID 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 e-mail message addressed to the user has been received. -+ -+ii) The recipient is not any of the imap_admins or admins accounts. -+Note that passing e-mails 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 meaningfull. -+ -+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 apropriate 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. -+ -+ -+ -+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 e-mail recipient before sending the e-mail 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 authorized 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 -+optimized, 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. -+ -+ -+ -+Things to be done -+================= -+ -+1. Support MURDER architecture. -+ -+ -+For more information and updates please visit http://email.uoa.gr/autocreate -+ -diff -Naur cyrus-imapd-2.2.12/imap/Makefile.in cyrus-imapd-2.2.12-autocreate.uncompiled/imap/Makefile.in ---- cyrus-imapd-2.2.12/imap/Makefile.in 2004-05-28 21:03:02 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/Makefile.in 2005-02-15 13:57:19 +0200 -@@ -104,7 +104,7 @@ - convert_code.o duplicate.o saslclient.o saslserver.o signals.o \ - annotate.o search_engines.o squat.o squat_internal.o mbdump.o \ - imapparse.o telemetry.o user.o notify.o protocol.o quota_db.o \ -- $(SEEN) $(IDLE) -+ autosieve.o $(SEEN) $(IDLE) - - IMAPDOBJS=pushstats.o backend.o imapd.o index.o tls.o version.o - -@@ -122,7 +122,7 @@ - fud smmapd reconstruct quota mbpath ipurge \ - cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \ - ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \ -- @IMAP_PROGS@ -+ compile_sieve @IMAP_PROGS@ - - BUILTSOURCES = imap_err.c imap_err.h pushstats.c pushstats.h \ - lmtpstats.c lmtpstats.h xversion.h mupdate_err.c mupdate_err.h \ -@@ -188,7 +188,7 @@ - ### Services - idled: idled.o mutex_fake.o libimap.a $(DEPLIBS) - $(CC) $(LDFLAGS) -o idled \ -- idled.o mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) -+ idled.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - - lmtpd: lmtpd.o $(LMTPOBJS) $(SIEVE_OBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) \ - $(DEPLIBS) $(SERVICE) -@@ -214,10 +214,10 @@ - $(SERVICE) lmtpproxyd.o backend.o $(LMTPOBJS) mutex_fake.o \ - libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - --imapd: xversion $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) -+imapd: xversion $(IMAPDOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) - $(CC) $(LDFLAGS) -o imapd \ - $(SERVICE) $(IMAPDOBJS) mutex_fake.o \ -- libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - - imapd.pure: $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) - $(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o imapd.pure \ -@@ -232,7 +232,7 @@ - proxyd: $(PROXYDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) - $(CC) $(LDFLAGS) -o proxyd \ - $(SERVICE) $(PROXYDOBJS) mutex_fake.o libimap.a \ -- $(DEPLIBS) $(LIBS) $(LIB_WRAP) -+ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - - proxyd.pure: $(PROXYDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) - $(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o proxyd.pure \ -@@ -244,7 +244,7 @@ - $(CC) $(LDFLAGS) -o mupdate \ - $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \ - mutex_pthread.o tls.o libimap.a \ -- $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread -+ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread - - mupdate.pure: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o \ - libimap.a $(DEPLIBS) -@@ -252,92 +252,96 @@ - $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \ - mutex_pthread.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread - --pop3d: pop3d.o backend.o tls.o mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) -+pop3d: pop3d.o backend.o tls.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) - $(CC) $(LDFLAGS) -o pop3d pop3d.o backend.o tls.o $(SERVICE) \ -- mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -+ mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - - nntpd: nntpd.o backend.o index.o smtpclient.o spool.o tls.o \ - mutex_fake.o nntp_err.o libimap.a $(DEPLIBS) $(SERVICE) - $(CC) $(LDFLAGS) -o nntpd nntpd.o backend.o index.o spool.o \ - smtpclient.o tls.o $(SERVICE) mutex_fake.o nntp_err.o \ -- libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - --fud: fud.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) -+fud: fud.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) - $(CC) $(LDFLAGS) -o fud $(SERVICE) fud.o mutex_fake.o libimap.a \ -- $(DEPLIBS) $(LIBS) $(LIB_WRAP) -+ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - --smmapd: smmapd.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) -+smmapd: smmapd.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) - $(CC) $(LDFLAGS) -o smmapd $(SERVICE) smmapd.o mutex_fake.o libimap.a \ -- $(DEPLIBS) $(LIBS) $(LIB_WRAP) -+ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) - - ### Command Line Utilities --arbitron: arbitron.o $(CLIOBJS) libimap.a $(DEPLIBS) -+arbitron: arbitron.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o arbitron arbitron.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) -+ -+compile_sieve: compile_sieve.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) -+ $(CC) $(LDFLAGS) -o compile_sieve compile_sieve.o $(CLIOBJS) \ -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(DEPLIBS) -+cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o cvt_cyrusdb cvt_cyrusdb.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(DEPLIBS) -+chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o chk_cyrus chk_cyrus.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --deliver: deliver.o backend.o $(LMTPOBJS) mutex_fake.o libimap.a $(DEPLIBS) -+deliver: deliver.o backend.o $(LMTPOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o deliver deliver.o backend.o $(LMTPOBJS) \ -- mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) -+ mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) -+ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o \ -- $@ ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ $@ ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(DEPLIBS) -+ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o $@ ctl_mboxlist.o mupdate-client.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) -+ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o \ -- $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(DEPLIBS) -+cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o $@ cyr_expire.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) -+fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o \ -- $@ fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ $@ fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(DEPLIBS) -+squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o squatter squatter.o index.o squat_build.o \ -- $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --mbpath: mbpath.o $(CLIOBJS) libimap.a $(DEPLIBS) -+mbpath: mbpath.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o mbpath mbpath.o $(CLIOBJS) libimap.a \ -- $(DEPLIBS) $(LIBS) -+ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --ipurge: ipurge.o $(CLIOBJS) libimap.a $(DEPLIBS) -+ipurge: ipurge.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o ipurge ipurge.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(DEPLIBS) -+cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o cyrdump cyrdump.o index.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) -+mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o \ -- mbexamine mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ mbexamine mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) -+reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o \ -- reconstruct reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ reconstruct reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --quota: quota.o $(CLIOBJS) libimap.a $(DEPLIBS) -+quota: quota.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o quota quota.o $(CLIOBJS) \ -- libimap.a $(DEPLIBS) $(LIBS) -+ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - --tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) -+tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) - $(CC) $(LDFLAGS) -o \ -- $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) -+ $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) - - ### Other Misc Targets - -diff -Naur cyrus-imapd-2.2.12/imap/autosieve.c cyrus-imapd-2.2.12-autocreate.uncompiled/imap/autosieve.c ---- cyrus-imapd-2.2.12/imap/autosieve.c 1970-01-01 02:00:00 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/autosieve.c 2005-02-15 13:57:19 +0200 -@@ -0,0 +1,587 @@ -+#include -+#include -+#include -+ -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "global.h" -+#include "util.h" -+#include "mailbox.h" -+#include "imap_err.h" -+#include "sieve_interface.h" -+#include "script.h" -+ -+#define TIMSIEVE_FAIL -1 -+#define TIMSIEVE_OK 0 -+#define MAX_FILENAME 1024 -+ -+static int get_script_name(char *sievename, size_t buflen, const char *filename); -+static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir); -+int autoadd_sieve(char *userid, const char *source_script); -+ -+static void fatal(const char *s, int code); -+static void foo(void); -+static int sieve_notify(void *ac __attribute__((unused)), -+ void *interp_context __attribute__((unused)), -+ void *script_context __attribute__((unused)), -+ void *message_context __attribute__((unused)), -+ const char **errmsg __attribute__((unused))); -+static int mysieve_error(int lineno, const char *msg, -+ void *i __attribute__((unused)), void *s); -+static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret); -+ -+ -+sieve_vacation_t vacation2 = { -+ 0, /* min response */ -+ 0, /* max response */ -+ (sieve_callback *) &foo, /* autorespond() */ -+ (sieve_callback *) &foo /* send_response() */ -+}; -+ -+ -+/* -+ * Find the name of the sieve script -+ * given the source script and compiled script names -+ */ -+static int get_script_name(char *sievename, size_t buflen, const char *filename) -+{ -+ char *p; -+ int r; -+ -+ p = strrchr(filename, '/'); -+ if (p == NULL) -+ p = (char *) filename; -+ else -+ p++; -+ -+ r = strlcpy(sievename, p, buflen) - buflen; -+ return (r >= 0 || r == -buflen ? 1 : 0); -+} -+ -+ -+/* -+ * Find the directory where the sieve scripts of the user -+ * reside -+ */ -+static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir) -+{ -+ char *user = NULL, *domain = NULL; -+ -+ /* Setup the user and the domain */ -+ if(config_virtdomains && (domain = strchr(userid, '@'))) { -+ user = (char *) xmalloc((domain - userid +1) * sizeof(char)); -+ strlcpy(user, userid, domain - userid + 1); -+ domain++; -+ } else -+ user = userid; -+ -+ /* Find the dir path where the sieve scripts of the user will reside */ -+ if (config_virtdomains && domain) { -+ if(snprintf(sieve_script_dir, buflen, "%s%s%c/%s/%c/%s/", -+ sieve_dir, FNAME_DOMAINDIR, dir_hash_c(domain), domain, dir_hash_c(user), user) >= buflen) { -+ free(user); -+ return 1; -+ } -+ } else { -+ if(snprintf(sieve_script_dir, buflen, "%s/%c/%s/", -+ sieve_dir, dir_hash_c(user), user) >= buflen) -+ return 1; -+ } -+ -+ /* Free the xmalloced user memory, reserved above */ -+ if(user != userid) -+ free(user); -+ -+ return 0; -+} -+ -+int autoadd_sieve(char *userid, const char *source_script) -+{ -+ sieve_script_t *s = NULL; -+ bytecode_info_t *bc = NULL; -+ char *err = NULL; -+ FILE *in_stream, *out_fp; -+ int out_fd, in_fd, r, k; -+ int do_compile = 0; -+ const char *sieve_dir = NULL; -+ const char *compiled_source_script = NULL; -+ char sievename[MAX_FILENAME]; -+ char sieve_script_name[MAX_FILENAME]; -+ char sieve_script_dir[MAX_FILENAME]; -+ char sieve_bcscript_name[MAX_FILENAME]; -+ char sieve_default[MAX_FILENAME]; -+ char sieve_tmpname[MAX_FILENAME]; -+ char sieve_bctmpname[MAX_FILENAME]; -+ char sieve_bclink_name[MAX_FILENAME]; -+ char buf[4096]; -+ mode_t oldmask; -+ struct stat statbuf; -+ -+ /* We don't support using the homedirectory, like timsieved */ -+ if (config_getswitch(IMAPOPT_SIEVEUSEHOMEDIR)) { -+ syslog(LOG_WARNING,"autocreate_sieve: autocreate_sieve does not work with sieveusehomedir option in imapd.conf"); -+ return 1; -+ } -+ -+ /* Check if sievedir is defined in imapd.conf */ -+ if(!(sieve_dir = config_getstring(IMAPOPT_SIEVEDIR))) { -+ syslog(LOG_WARNING, "autocreate_sieve: sievedir option is not defined. Check imapd.conf"); -+ return 1; -+ } -+ -+ /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */ -+ if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { -+ syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it"); -+ do_compile = 1; -+ } -+ -+ if(get_script_dir(sieve_script_dir, sizeof(sieve_script_dir), userid, sieve_dir)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Cannot find sieve scripts directory"); -+ return 1; -+ } -+ -+ if (get_script_name(sievename, sizeof(sievename), source_script)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve script %s", source_script); -+ return 1; -+ } -+ -+ if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s%s.script.NEW",sieve_script_dir, sievename) >= sizeof(sieve_tmpname)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); -+ return 1; -+ } -+ if(snprintf(sieve_bctmpname, sizeof(sieve_bctmpname), "%s%s.bc.NEW",sieve_script_dir, sievename) >= sizeof(sieve_bctmpname)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); -+ return 1; -+ } -+ if(snprintf(sieve_script_name, sizeof(sieve_script_name), "%s%s.script",sieve_script_dir, sievename) >= sizeof(sieve_script_name)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); -+ return 1; -+ } -+ if(snprintf(sieve_bcscript_name, sizeof(sieve_bcscript_name), "%s%s.bc",sieve_script_dir, sievename) >= sizeof(sieve_bcscript_name)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); -+ return 1; -+ } -+ if(snprintf(sieve_default, sizeof(sieve_default), "%s%s",sieve_script_dir,"defaultbc") >= sizeof(sieve_default)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); -+ return 1; -+ } -+ if(snprintf(sieve_bclink_name, sizeof(sieve_bclink_name), "%s.bc", sievename) >= sizeof(sieve_bclink_name)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); -+ return 1; -+ } -+ -+ /* Check if a default sieve filter alrady exists */ -+ if(!stat(sieve_default,&statbuf)) { -+ syslog(LOG_WARNING,"autocreate_sieve: Default sieve script already exists"); -+ fclose(in_stream); -+ return 1; -+ } -+ -+ /* Open the source script. if there is a problem with that exit */ -+ in_stream = fopen(source_script, "r"); -+ if(!in_stream) { -+ syslog(LOG_WARNING,"autocreate_sieve: Unable to open sieve script %s. Check permissions",source_script); -+ return 1; -+ } -+ -+ -+ /* -+ * At this point we start the modifications of the filesystem -+ */ -+ -+ /* Create the directory where the sieve scripts will reside */ -+ r = cyrus_mkdir(sieve_script_dir, 0755); -+ if(r == -1) { -+ /* If this fails we just leave */ -+ syslog(LOG_WARNING,"autocreate_sieve: Unable to create directory %s. Check permissions",sieve_script_name); -+ return 1; -+ } -+ -+ /* -+ * We open the file that will be used as the bc file. If this file exists, overwrite it -+ * since something bad has happened. We open the file here so that this error checking is -+ * done before we try to open the rest of the files to start copying etc. -+ */ -+ out_fd = open(sieve_bctmpname, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); -+ if(out_fd < 0) { -+ if(errno == EEXIST) { -+ syslog(LOG_WARNING,"autocreate_sieve: File %s already exists. Probaly left over. Ignoring",sieve_bctmpname); -+ } else if (errno == EACCES) { -+ syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_bctmpname); -+ fclose(in_stream); -+ return 1; -+ } else { -+ syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s. Unknown error",sieve_bctmpname); -+ fclose(in_stream); -+ return 1; -+ } -+ } -+ -+ if(!do_compile && compiled_source_script && (in_fd = open(compiled_source_script, O_RDONLY)) != -1) { -+ while((r = read(in_fd, buf, sizeof(buf))) > 0) { -+ if((k=write(out_fd, buf,r)) < 0) { -+ syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_bctmpname, errno); -+ close(out_fd); -+ close(in_fd); -+ fclose(in_stream); -+ unlink(sieve_bctmpname); -+ return 1; -+ } -+ } -+ -+ if(r == 0) { /* EOF */ -+ close(out_fd); -+ close(in_fd); -+ } else if (r < 0) { -+ syslog(LOG_WARNING, "autocreate_sieve: Error reading compiled script file: %s. Will try to compile it", -+ compiled_source_script); -+ close(in_fd); -+ do_compile = 1; -+ if(lseek(out_fd, 0, SEEK_SET)) { -+ syslog(LOG_WARNING, "autocreate_sieve: Major IO problem. Aborting"); -+ return 1; -+ } -+ } -+ close(in_fd); -+ } else { -+ if(compiled_source_script) -+ syslog(LOG_WARNING,"autocreate_sieve: Problem opening compiled script file: %s. Compiling it", compiled_source_script); -+ do_compile = 1; -+ } -+ -+ -+ /* Because we failed to open a precompiled bc sieve script, we compile one */ -+ if(do_compile) { -+ if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { -+ if(err && *err) { -+ syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script %s.",err); -+ free(err); -+ } else -+ syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script"); -+ -+ unlink(sieve_bctmpname); -+ fclose(in_stream); -+ close(out_fd); -+ return 1; -+ } -+ -+ /* generate the bytecode */ -+ if(sieve_generate_bytecode(&bc, s) == TIMSIEVE_FAIL) { -+ syslog(LOG_WARNING,"autocreate_sieve: problem compiling sieve script"); -+ /* removing the copied script and cleaning up memory */ -+ unlink(sieve_bctmpname); -+ sieve_script_free(&s); -+ fclose(in_stream); -+ close(out_fd); -+ return 1; -+ } -+ -+ if(sieve_emit_bytecode(out_fd, bc) == TIMSIEVE_FAIL) { -+ syslog(LOG_WARNING,"autocreate_sieve: problem emiting sieve script"); -+ /* removing the copied script and cleaning up memory */ -+ unlink(sieve_bctmpname); -+ sieve_free_bytecode(&bc); -+ sieve_script_free(&s); -+ fclose(in_stream); -+ close(out_fd); -+ return 1; -+ } -+ -+ /* clean up the memory */ -+ sieve_free_bytecode(&bc); -+ sieve_script_free(&s); -+ } -+ -+ close(out_fd); -+ rewind(in_stream); -+ -+ /* Copy the initial script */ -+ oldmask = umask(077); -+ if((out_fp = fopen(sieve_tmpname, "w")) == NULL) { -+ syslog(LOG_WARNING,"autocreate_sieve: Unable to open %s destination sieve script", sieve_tmpname); -+ unlink(sieve_bctmpname); -+ umask(oldmask); -+ fclose(in_stream); -+ return 1; -+ } -+ umask(oldmask); -+ -+ while((r = fread(buf,sizeof(char), sizeof(buf), in_stream))) { -+ if( fwrite(buf,sizeof(char), r, out_fp) != r) { -+ syslog(LOG_WARNING,"autocreate_sieve: Problem writing to sieve script file: %s",sieve_tmpname); -+ fclose(out_fp); -+ unlink(sieve_tmpname); -+ unlink(sieve_bctmpname); -+ fclose(in_stream); -+ return 1; -+ } -+ } -+ -+ if(feof(in_stream)) { -+ fclose(out_fp); -+ } else { /* ferror */ -+ fclose(out_fp); -+ unlink(sieve_tmpname); -+ unlink(sieve_bctmpname); -+ fclose(in_stream); -+ return 1; -+ } -+ -+ /* Renaming the necessary stuff */ -+ if(rename(sieve_tmpname, sieve_script_name)) { -+ unlink(sieve_tmpname); -+ unlink(sieve_bctmpname); -+ return 1; -+ } -+ -+ if(rename(sieve_bctmpname, sieve_bcscript_name)) { -+ unlink(sieve_bctmpname); -+ unlink(sieve_bcscript_name); -+ return 1; -+ } -+ -+ /* end now with the symlink */ -+ if(symlink(sieve_bclink_name, sieve_default)) { -+ if(errno != EEXIST) { -+ syslog(LOG_WARNING, "autocreate_sieve: problem making the default link."); -+ /* Lets delete the files */ -+ unlink(sieve_script_name); -+ unlink(sieve_bcscript_name); -+ } -+ } -+ -+ /* -+ * If everything has succeeded AND we have compiled the script AND we have requested -+ * to generate the global script so that it is not compiled each time then we create it. -+ */ -+ if(do_compile && -+ config_getswitch(IMAPOPT_GENERATE_COMPILED_SIEVE_SCRIPT)) { -+ -+ if(!compiled_source_script) { -+ syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf"); -+ return 0; -+ } -+ -+ if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script) >= sizeof(sieve_tmpname)) -+ return 0; -+ -+ /* -+ * Copy everything from the newly created bc sieve sieve script. -+ */ -+ if((in_fd = open(sieve_bcscript_name, O_RDONLY))<0) { -+ return 0; -+ } -+ -+ if((out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { -+ if(errno == EEXIST) { -+ /* Someone is already doing this so just bail out. */ -+ syslog(LOG_WARNING, "autocreate_sieve: %s already exists. Some other instance processing it, or it is left over", sieve_tmpname); -+ close(in_fd); -+ return 0; -+ } else if (errno == EACCES) { -+ syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_tmpname); -+ close(in_fd); -+ return 0; -+ } else { -+ syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s",sieve_tmpname); -+ close(in_fd); -+ return 0; -+ } -+ } -+ -+ while((r = read(in_fd, buf, sizeof(buf))) > 0) { -+ if((k = write(out_fd,buf,r)) < 0) { -+ syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno); -+ close(out_fd); -+ close(in_fd); -+ unlink(sieve_tmpname); -+ return 0; -+ } -+ } -+ -+ if(r == 0 ) { /*EOF */ -+ close(out_fd); -+ close(in_fd); -+ } else if (r < 0) { -+ syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno); -+ close(out_fd); -+ close(in_fd); -+ unlink(sieve_tmpname); -+ return 0; -+ } -+ -+ /* Rename the temporary created sieve script to its final name. */ -+ if(rename(sieve_tmpname, compiled_source_script)) { -+ if(errno != EEXIST) { -+ unlink(sieve_tmpname); -+ unlink(compiled_source_script); -+ } -+ return 0; -+ } -+ -+ syslog(LOG_NOTICE, "autocreate_sieve: Compiled sieve script was successfully saved in %s", compiled_source_script); -+ } -+ -+ return 0; -+} -+ -+static void fatal(const char *s, int code) -+{ -+ printf("Fatal error: %s (%d)\r\n", s, code); -+ exit(1); -+} -+ -+/* to make larry's stupid functions happy :) */ -+static void foo(void) -+{ -+ fatal("stub function called", 0); -+} -+ -+static int sieve_notify(void *ac __attribute__((unused)), -+ void *interp_context __attribute__((unused)), -+ void *script_context __attribute__((unused)), -+ void *message_context __attribute__((unused)), -+ const char **errmsg __attribute__((unused))) -+{ -+ fatal("stub function called", 0); -+ return SIEVE_FAIL; -+} -+ -+static int mysieve_error(int lineno, const char *msg, -+ void *i __attribute__((unused)), void *s) -+{ -+ char buf[1024]; -+ char **errstr = (char **) s; -+ -+ snprintf(buf, 80, "line %d: %s\r\n", lineno, msg); -+ *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30); -+ syslog(LOG_DEBUG, "%s", buf); -+ strcat(*errstr, buf); -+ -+ return SIEVE_OK; -+} -+ -+/* end the boilerplate */ -+ -+/* returns TRUE or FALSE */ -+int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret) -+{ -+ sieve_interp_t *i; -+ sieve_script_t *s; -+ int res; -+ -+ res = sieve_interp_alloc(&i, NULL); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_interp_alloc() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_redirect(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_redirect() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_discard(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_discard() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_reject(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_reject() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_fileinto(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_fileinto() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_keep(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_keep() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_imapflags(i, NULL); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_imapflags() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_size(i, (sieve_get_size *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_size() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_header(i, (sieve_get_header *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_header() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_envelope(i, (sieve_get_envelope *) &foo); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_envelope() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_vacation(i, &vacation2); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_vacation() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_notify(i, &sieve_notify); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_notify() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_parse_error(i, &mysieve_error); -+ if (res != SIEVE_OK) { -+ syslog(LOG_WARNING, "sieve_register_parse_error() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ rewind(stream); -+ -+ *errstr = (char *) xmalloc(20 * sizeof(char)); -+ strcpy(*errstr, "script errors:\r\n"); -+ -+ res = sieve_script_parse(i, stream, errstr, &s); -+ -+ if (res == SIEVE_OK) { -+ if(ret) { -+ *ret = s; -+ } else { -+ sieve_script_free(&s); -+ } -+ free(*errstr); -+ *errstr = NULL; -+ } -+ -+ /* free interpreter */ -+ sieve_interp_free(&i); -+ -+ return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL; -+} -+ -+/* -+ * Btw the initial date of this patch is Sep, 02 2004 which is the birthday of -+ * Pavlos. Author of cyrusmaster. So consider this patch as his birthday present -+ */ -+ -diff -Naur cyrus-imapd-2.2.12/imap/compile_sieve.c cyrus-imapd-2.2.12-autocreate.uncompiled/imap/compile_sieve.c ---- cyrus-imapd-2.2.12/imap/compile_sieve.c 1970-01-01 02:00:00 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/compile_sieve.c 2005-02-15 13:57:19 +0200 -@@ -0,0 +1,364 @@ -+/* This tool compiles the sieve script from a command -+line so that it can be used wby the autoadd patch */ -+#include -+#include -+ -+#include -+#include -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "global.h" -+ -+#include "util.h" -+#include "mailbox.h" -+#include "imap_err.h" -+#include "sieve_interface.h" -+#include "script.h" -+ -+#include -+ -+#define TIMSIEVE_FAIL -1 -+#define TIMSIEVE_OK 0 -+#define MAX_FILENAME_SIZE 100 -+ -+/* Needed by libconfig */ -+const int config_need_data = 0; -+ -+static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret); -+ -+static void fatal(const char *s, int code) -+{ -+ printf("Fatal error: %s (%d)\r\n", s, code); -+ -+ exit(1); -+} -+ -+void usage(void) -+{ -+ fprintf(stderr, -+ "Usage:\n\tcompile_sieve [-C ] [-i -o ]\n"); -+ exit(-1); -+} -+ -+ -+int main (int argc, char **argv) -+{ -+ -+ sieve_script_t *s = NULL; -+ bytecode_info_t *bc = NULL; -+ char *err = NULL; -+ FILE *in_stream; -+ int out_fd,r, k, opt; -+ char *source_script = NULL; -+ char *compiled_source_script = NULL; -+ mode_t oldmask; -+ struct stat statbuf; -+ char *alt_config = NULL; -+ extern char *optarg; -+ char sieve_tmpname[MAX_MAILBOX_NAME+1]; -+ -+ if (geteuid() == 0) fatal("must run as the Cyrus user", EC_USAGE); -+ -+ while((opt = getopt(argc, argv, "C:i:o:")) != EOF) { -+ switch (opt) { -+ case 'C': /* alt config file */ -+ alt_config = optarg; -+ break; -+ case 'i': /* input script file */ -+ source_script = optarg; -+ break; -+ case 'o': /* output script file */ -+ compiled_source_script = optarg; -+ break; -+ default: -+ usage(); -+ break; -+ } -+ } -+ -+ if(source_script && !compiled_source_script) { -+ fprintf(stderr, "No output file was defined\n"); -+ usage(); -+ } else if (!source_script && compiled_source_script) { -+ fprintf(stderr, "No input file was defined\n"); -+ usage(); -+ } -+ -+ /* -+ * If no has been defined, then read them from -+ * the configuration file. -+ */ -+ if (!source_script && !compiled_source_script) { -+ cyrus_init(alt_config, "compile_sieve", 0); -+ -+ /* Initially check if we want to have the sieve script created */ -+ if(!(source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT))) { -+ fprintf(stderr,"autocreate_sieve_script option not defined. Check imapd.conf\n"); -+ return 1; -+ } -+ -+ /* Check if we have an already compiled sieve script*/ -+ if(!(compiled_source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { -+ fprintf(stderr, "autocreate_sieve_compiledscript option not defined. Check imapd.conf\n"); -+ return 1; -+ } -+ -+ if(!strrchr(source_script,'/') || !strrchr(compiled_source_script,'/')) { -+ /* -+ * At this point the only think that is inconsistent is the directory -+ * that was created. But if the user will have any sieve scripts then -+ * they will eventually go there, so no big deal -+ */ -+ fprintf(stderr, -+ "In imapd.conf the full path of the filenames must be defined\n"); -+ return 1; -+ } -+ } -+ -+ printf("input file : %s, output file : %s\n", source_script, compiled_source_script); -+ -+ -+ if(strlen(compiled_source_script) + sizeof(".NEW") + 1 > sizeof(sieve_tmpname)) { -+ fprintf(stderr, "Filename %s is too big\n", compiled_source_script); -+ return 1; -+ } -+ -+ snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script); -+ -+ in_stream = fopen(source_script,"r"); -+ -+ if(!in_stream) { -+ fprintf(stderr,"Unable to open %s source sieve script\n",source_script); -+ return; -+ } -+ -+ /* -+ * We open the file that will be used as the bc file. If this file exists, overwrite it -+ * since something bad has happened. We open the file here so that this error checking is -+ * done before we try to open the rest of the files to start copying etc. -+ */ -+ out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); -+ if(out_fd < 0) { -+ if(errno == EEXIST) { -+ fprintf(stderr, "File %s already exists\n", sieve_tmpname); -+ } else if (errno == EACCES) { -+ fprintf(stderr,"No access to create file %s. Please check that you have the correct permissions\n", -+ sieve_tmpname); -+ } else { -+ fprintf(stderr,"Unable to create %s. Please check that you have the correct permissions\n", -+ sieve_tmpname); -+ } -+ -+ fclose(in_stream); -+ return 1; -+ } -+ -+ if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { -+ if(err && *err) { -+ fprintf(stderr, "Error while parsing script %s\n",err); -+ free(err); -+ } -+ else -+ fprintf(stderr,"Error while parsing script\n"); -+ unlink(sieve_tmpname); -+ fclose(in_stream); -+ close(out_fd); -+ return; -+ } -+ -+ -+ /* generate the bytecode */ -+ if(sieve_generate_bytecode(&bc,s) == TIMSIEVE_FAIL) { -+ fprintf(stderr,"Error occured while compiling sieve script\n"); -+ /* removing the copied script and cleaning up memory */ -+ unlink(sieve_tmpname); -+ sieve_script_free(&s); -+ fclose(in_stream); -+ close(out_fd); -+ return; -+ } -+ if(sieve_emit_bytecode(out_fd,bc) == TIMSIEVE_FAIL) { -+ fprintf(stderr, "Error occured while emitting sieve script\n"); -+ unlink(sieve_tmpname); -+ sieve_free_bytecode(&bc); -+ sieve_script_free(&s); -+ fclose(in_stream); -+ close(out_fd); -+ return; -+ } -+ -+ /* clean up the memory */ -+ sieve_free_bytecode(&bc); -+ sieve_script_free(&s); -+ -+ close(out_fd); -+ -+ if(rename(sieve_tmpname, compiled_source_script)) { -+ if(errno != EEXIST) { -+ unlink(sieve_tmpname); -+ unlink(compiled_source_script); -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+ -+/* to make larry's stupid functions happy :) */ -+static void foo(void) -+{ -+ fatal("stub function called", 0); -+} -+ -+extern sieve_vacation_t vacation2;/* = { -+ 0, / min response / -+ 0, / max response / -+ (sieve_callback *) &foo, / autorespond() / -+ (sieve_callback *) &foo / send_response() / -+}; */ -+ -+static int sieve_notify(void *ac __attribute__((unused)), -+ void *interp_context __attribute__((unused)), -+ void *script_context __attribute__((unused)), -+ void *message_context __attribute__((unused)), -+ const char **errmsg __attribute__((unused))) -+{ -+ fatal("stub function called", 0); -+ return SIEVE_FAIL; -+} -+ -+static int mysieve_error(int lineno, const char *msg, -+ void *i __attribute__((unused)), void *s) -+{ -+ char buf[1024]; -+ char **errstr = (char **) s; -+ -+ snprintf(buf, 80, "line %d: %s\r\n", lineno, msg); -+ *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30); -+ fprintf(stderr, "%s\n", buf); -+ strcat(*errstr, buf); -+ -+ return SIEVE_OK; -+} -+ -+/* end the boilerplate */ -+ -+/* returns TRUE or FALSE */ -+int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret) -+{ -+ sieve_interp_t *i; -+ sieve_script_t *s; -+ int res; -+ -+ res = sieve_interp_alloc(&i, NULL); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_interp_alloc() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_redirect(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_redirect() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_discard(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_discard() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_reject(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_reject() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_fileinto(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_fileinto() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ res = sieve_register_keep(i, (sieve_callback *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_keep() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_imapflags(i, NULL); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_imapflags() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_size(i, (sieve_get_size *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_size() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_header(i, (sieve_get_header *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_header() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_envelope(i, (sieve_get_envelope *) &foo); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_envelope() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_vacation(i, &vacation2); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_vacation() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_notify(i, &sieve_notify); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_notify() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ res = sieve_register_parse_error(i, &mysieve_error); -+ if (res != SIEVE_OK) { -+ fprintf(stderr, "sieve_register_parse_error() returns %d\n", res); -+ return TIMSIEVE_FAIL; -+ } -+ -+ rewind(stream); -+ -+ *errstr = (char *) xmalloc(20 * sizeof(char)); -+ strcpy(*errstr, "script errors:\r\n"); -+ -+ res = sieve_script_parse(i, stream, errstr, &s); -+ -+ if (res == SIEVE_OK) { -+ if(ret) { -+ *ret = s; -+ } else { -+ sieve_script_free(&s); -+ } -+ free(*errstr); -+ *errstr = NULL; -+ } -+ -+ /* free interpreter */ -+ sieve_interp_free(&i); -+ -+ return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL; -+} -+ -+ -+ -+ -+ -+ -diff -Naur cyrus-imapd-2.2.12/imap/imapd.c cyrus-imapd-2.2.12-autocreate.uncompiled/imap/imapd.c ---- cyrus-imapd-2.2.12/imap/imapd.c 2005-02-14 08:39:55 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/imapd.c 2005-02-15 13:57:19 +0200 -@@ -158,6 +158,7 @@ - void motd_file(int fd); - void shut_down(int code); - void fatal(const char *s, int code); -+void autocreate_inbox(void); - - void cmdloop(void); - void cmd_login(char *tag, char *user); -@@ -1693,6 +1694,42 @@ - } - - /* -+ * Autocreate Inbox and subfolders upon login -+ */ -+void autocreate_inbox() -+{ -+ char inboxname[MAX_MAILBOX_NAME+1]; -+ int autocreatequota; -+ int r; -+ -+ /* -+ * Exlude admin's accounts -+ */ -+ if (imapd_userisadmin || imapd_userisproxyadmin) -+ return; -+ -+ /* -+ * Exclude anonymous -+ */ -+ if (!strcmp(imapd_userid, "anonymous")) -+ return; -+ -+ if ((autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) { -+ /* This is actyally not required -+ as long as the lenght of userid is ok */ -+ r = (*imapd_namespace.mboxname_tointernal) (&imapd_namespace, -+ "INBOX", imapd_userid, inboxname); -+ if (!r) -+ r = mboxlist_lookup(inboxname, NULL, NULL, NULL); -+ -+ if (r == IMAP_MAILBOX_NONEXISTENT) -+ mboxlist_autocreateinbox(&imapd_namespace, imapd_userid, -+ imapd_authstate, inboxname, autocreatequota); -+ } -+} -+ -+ -+/* - * Perform a LOGIN command - */ - void cmd_login(char *tag, char *user) -@@ -1848,6 +1885,9 @@ - strcspn(imapd_userid, "@") : 0); - - freebuf(&passwdbuf); -+ -+ autocreate_inbox(); -+ - return; - } - -@@ -1993,6 +2033,8 @@ - config_virtdomains ? - strcspn(imapd_userid, "@") : 0); - -+ autocreate_inbox(); -+ - return; - } - -diff -Naur cyrus-imapd-2.2.12/imap/lmtpd.c cyrus-imapd-2.2.12-autocreate.uncompiled/imap/lmtpd.c ---- cyrus-imapd-2.2.12/imap/lmtpd.c 2004-12-17 18:32:15 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/lmtpd.c 2005-02-15 13:57:19 +0200 -@@ -106,6 +106,8 @@ - static FILE *spoolfile(message_data_t *msgdata); - static void removespool(message_data_t *msgdata); - -+static int autocreate_inbox(char *rcpt_userid); -+ - /* current namespace */ - static struct namespace lmtpd_namespace; - -@@ -504,10 +506,55 @@ - exit(code); - } - -+/* -+ * Autocreate Inbox and subfolders upon login -+ */ -+int autocreate_inbox(char *rcpt_userid) -+{ -+ struct auth_state *authstate; -+ char inboxname[MAX_MAILBOX_NAME+1]; -+ int rcptisadmin; -+ int autocreatequota; -+ int r; -+ -+ if(rcpt_userid == NULL) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ /* -+ * Exclude anonymous -+ */ -+ if (!strcmp(rcpt_userid, "anonymous")) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ /* -+ * Check for autocreatequota and createonpost -+ */ -+ if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)) || -+ !(config_getswitch(IMAPOPT_CREATEONPOST))) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ /* -+ * Exclude admin's accounts -+ */ -+ authstate = auth_newstate(rcpt_userid); -+ rcptisadmin = global_authisa(authstate, IMAPOPT_ADMINS); -+ if (rcptisadmin) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ r = (*lmtpd_namespace.mboxname_tointernal) (&lmtpd_namespace, -+ "INBOX", rcpt_userid, inboxname); -+ if (!r) -+ r = mboxlist_autocreateinbox(&lmtpd_namespace, rcpt_userid, -+ authstate, inboxname, autocreatequota); -+ return r; -+} -+ -+ - static int verify_user(const char *user, const char *domain, const char *mailbox, - long quotacheck, struct auth_state *authstate) - { - char namebuf[MAX_MAILBOX_NAME+1] = ""; -+ char *userinbox = NULL; - int r = 0; - - if ((!user && !mailbox) || -@@ -545,6 +592,28 @@ - */ - r = append_check(namebuf, MAILBOX_FORMAT_NORMAL, authstate, - !user ? ACL_POST : 0, quotacheck > 0 ? 0 : quotacheck); -+ if (r == IMAP_MAILBOX_NONEXISTENT) { -+ if(domain) { -+ int k; -+ userinbox = (char *)xmalloc((strlen(user)+strlen(domain)+2)*sizeof(char)); -+ k = strlcpy(userinbox, user, strlen(user)+1); -+ *(userinbox + k) = '@'; -+ strlcpy(userinbox+k+1, domain, strlen(domain)+1); -+ } -+ else userinbox = user; -+ /* -+ * Try to create automatically the mailbox, if -+ * autocreate inbox option is enabled. -+ */ -+ r = autocreate_inbox(userinbox); -+ -+ if(userinbox != user) -+ free(userinbox); -+ if (!r) -+ r = append_check(namebuf, MAILBOX_FORMAT_NORMAL, authstate, -+ 0, quotacheck > 0 ? 0 : quotacheck); -+ } -+ - } - - if (r) syslog(LOG_DEBUG, "verify_user(%s) failed: %s", namebuf, -diff -Naur cyrus-imapd-2.2.12/imap/mboxlist.c cyrus-imapd-2.2.12-autocreate.uncompiled/imap/mboxlist.c ---- cyrus-imapd-2.2.12/imap/mboxlist.c 2004-07-26 21:08:03 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/mboxlist.c 2005-02-15 13:57:19 +0200 -@@ -81,6 +81,12 @@ - #include "mboxlist.h" - #include "quota.h" - -+#ifdef USE_SIEVE -+extern int autoadd_sieve(char *userid, -+ const char *source_script); -+#endif -+ -+ - #define DB config_mboxlist_db - #define SUBDB config_subscription_db - -@@ -98,11 +104,29 @@ - static int mboxlist_changequota(const char *name, int matchlen, int maycreate, - void *rock); - -+static int mboxlist_autochangesub(char *name, int matchlen, int maycreate, -+ void *rock); -+ -+static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace, -+ char *userid, char *auth_userid, -+ struct auth_state *auth_state); -+ - struct change_rock { - struct quota *quota; - struct txn **tid; - }; - -+/* -+ * Struct needed to be passed as void *rock to -+ * mboxlist_autochangesub(); -+ */ -+struct changesub_rock_st { -+ char *userid; -+ char *auth_userid; -+ struct auth_state *auth_state; -+}; -+ -+ - #define FNAME_SUBSSUFFIX ".sub" - - /* -@@ -3124,3 +3148,338 @@ - - return DB->abort(mbdb, tid); - } -+ -+/* -+ * Automatically subscribe user to *ALL* shared folders, -+ * one has permissions to be subscribed to. -+ * INBOX subfolders are excluded. -+ */ -+static int mboxlist_autochangesub(char *name, int matchlen, int maycreate, -+ void *rock) { -+ -+ struct changesub_rock_st *changesub_rock = (struct changesub_rock_st *) rock; -+ char *userid = changesub_rock->userid; -+ char *auth_userid = changesub_rock->auth_userid; -+ struct auth_state *auth_state = changesub_rock->auth_state; -+ int r; -+ -+ -+ if((strlen(name) == 5 && !strncmp(name, "INBOX", 5)) || /* Exclude INBOX */ -+ (strlen(name) > 5 && !strncmp(name, "INBOX.",6)) || /* Exclude INBOX subfolders */ -+ (strlen(name) > 4 && !strncmp(name, "user.", 5))) /* Exclude other users' folders */ -+ return 0; -+ -+ -+ r = mboxlist_changesub(name, userid, auth_state, 1, 0); -+ -+ if (r) { -+ syslog(LOG_WARNING, -+ "autosubscribe: User %s to folder %s, subscription failed: %s", -+ auth_userid, name, error_message(r)); -+ } else { -+ syslog(LOG_NOTICE, -+ "autosubscribe: User %s to folder %s, subscription succeeded", -+ auth_userid, name); -+ } -+ -+ return 0; -+} -+ -+#define SEP '|' -+ -+/* -+ * Automatically subscribe user to a shared folder. -+ * Subscription is done successfully, if the shared -+ * folder exists and the user has the necessary -+ * permissions. -+ */ -+static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace, -+ char *userid, char *auth_userid, -+ struct auth_state *auth_state) { -+ -+ const char *sub ; -+ char *p, *q, *next_sub; -+ char folder[MAX_MAILBOX_NAME+1], name[MAX_MAILBOX_NAME+1], mailboxname[MAX_MAILBOX_NAME+1]; -+ int len; -+ int r = 0; -+ int subscribe_all_sharedfolders = 0; -+ -+ subscribe_all_sharedfolders = config_getswitch(IMAPOPT_AUTOSUBSCRIBE_ALL_SHAREDFOLDERS); -+ -+ /* -+ * If subscribeallsharedfolders is set to yes in imapd.conf, then -+ * subscribe user to every shared folder one has the apropriate -+ * permissions. -+ */ -+ if(subscribe_all_sharedfolders) { -+ char pattern[MAX_MAILBOX_PATH+1]; -+ struct changesub_rock_st changesub_rock; -+ -+ strcpy(pattern, "*"); -+ changesub_rock.userid = userid; -+ changesub_rock.auth_userid = auth_userid; -+ changesub_rock.auth_state = auth_state; -+ -+ r = mboxlist_findall(namespace, pattern, 0, userid, -+ auth_state, mboxlist_autochangesub, &changesub_rock); -+ -+ return r; -+ } -+ -+ if ((sub=config_getstring(IMAPOPT_AUTOSUBSCRIBESHAREDFOLDERS)) == NULL) -+ return r; -+ -+ next_sub = (char *) sub; -+ while (*next_sub) { -+ for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++); -+ for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++); -+ for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--); -+ if (!*p ) continue; -+ -+ len = q - p + 1; -+ /* Check for folder length */ -+ if (len > sizeof(folder)-1) -+ continue; -+ -+ if (!r) { -+ strncpy(folder, p, len); -+ folder[len] = '\0'; -+ -+ strlcpy(name, namespace->prefix[NAMESPACE_SHARED], sizeof(name)); -+ len = strlcat(name, folder, sizeof(name)); -+ -+ r = (namespace->mboxname_tointernal) (namespace, name, userid, -+ mailboxname); -+ } -+ -+ if (!r) -+ r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 0); -+ -+ if (!r) { -+ syslog(LOG_NOTICE, "autosubscribe: User %s to %s succeeded", -+ userid, folder); -+ } else { -+ syslog(LOG_WARNING, "autosubscribe: User %s to %s failed: %s", -+ userid, folder, error_message(r)); -+ r = 0; -+ } -+ } -+ -+ return r; -+} -+ -+ -+ -+int mboxlist_autocreateinbox(struct namespace *namespace, -+ char *userid, -+ struct auth_state *auth_state, -+ char *mailboxname, int autocreatequota) { -+ char name [MAX_MAILBOX_NAME+1]; -+ char folder [MAX_MAILBOX_NAME+1]; -+ char *auth_userid = NULL; -+ char *partition = NULL; -+ const char *crt; -+ const char *sub; -+ char *p, *q, *next_crt, *next_sub; -+ int len; -+ int r = 0; -+ int numcrt = 0; -+ int numsub = 0; -+#ifdef USE_SIEVE -+ const char *source_script; -+#endif -+ -+ /* -+ * While this is not needed for admins -+ * and imap_admins accounts, it would be -+ * better to separate *all* admins and -+ * proxyservers from normal accounts -+ * (accounts that have mailboxes). -+ * UOA Specific note(1): Even if we do not -+ * exclude these servers-classes here, -+ * UOA specific code, will neither return -+ * role, nor create INBOX, because none of these -+ * administrative accounts belong to the -+ * mailRecipient objectclass, or have imapPartition. -+ * UOA Specific note(2): Another good reason for doing -+ * this, is to prevent the code, from getting into -+ * cyrus_ldap.c because of the continues MSA logins to LMTPd. -+ */ -+ -+ /* -+ * admins and the coresponding imap -+ * service, had already been excluded. -+ */ -+ -+ /* -+ * Do we really need group membership -+ * for admins or service_admins? -+ */ -+ if (global_authisa(auth_state, IMAPOPT_ADMINS)) return 0; -+ if (global_authisa(auth_state, IMAPOPT_ADMINS)) return 0; -+ -+ /* -+ * Do we really need group membership -+ * for proxyservers? -+ */ -+ if (global_authisa(auth_state, IMAPOPT_PROXYSERVERS)) return 0; -+ if (global_authisa(auth_state, IMAPOPT_PROXYSERVERS)) return 0; -+ -+ auth_userid = auth_canonuser(auth_state); -+ -+ if (auth_userid == NULL) { -+ /* -+ * Couldn't get cannon userid -+ */ -+ syslog(LOG_ERR, -+ "Could not get cannon userid for user %s", auth_userid); -+ return IMAP_PARTITION_UNKNOWN; -+ } -+ -+#if 0 -+ /* -+ * Get Partition info or return. -+ * (Here you should propably use -+ * you own "get_partition(char *userid)" -+ * function. Otherwise all new INBOXes will be -+ * created into whatever partition has been declared -+ * as default in your imapd.conf) -+ */ -+ -+ partition = get_partition(userid); -+ -+ if (partition == NULL) { -+ /* -+ * Couldn't get partition info -+ */ -+ syslog(LOG_ERR, -+ "Could not get imapPartition info for user %s", userid); -+ return IMAP_PARTITION_UNKNOWN; -+ } -+#endif -+ -+ r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL, -+ 1, userid, auth_state, 0, 0, 0); -+ -+ if (!r && autocreatequota > 0) -+ r = mboxlist_setquota(mailboxname, autocreatequota, 0); -+ -+ if (!r) -+ r = mboxlist_changesub(mailboxname, userid, -+ auth_state, 1, 1); -+ -+ if (!r) { -+ syslog(LOG_NOTICE, "autocreateinbox: User %s, INBOX was successfully created in partition %s", -+ auth_userid, partition == NULL ? "default" : partition); -+ } else { -+ syslog(LOG_ERR, "autocreateinbox: User %s, INBOX failed. %s", -+ auth_userid, error_message(r)); -+ } -+ -+ -+#if 0 -+ /* Allocated from get_partition, and not needed any more */ -+ free_partition(partition); -+#endif -+ -+ if (r) return r; -+ -+ -+ /* INBOX's subfolders */ -+ if ((crt=config_getstring(IMAPOPT_AUTOCREATEINBOXFOLDERS))) -+ sub=config_getstring(IMAPOPT_AUTOSUBSCRIBEINBOXFOLDERS); -+ -+ /* Roll through crt */ -+ next_crt = (char *) crt; -+ while (next_crt!=NULL && *next_crt) { -+ for (p = next_crt ; isspace((int) *p) || *p == SEP ; p++); -+ for (next_crt = p ; *next_crt && *next_crt != SEP ; next_crt++); -+ for (q = next_crt ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--); -+ -+ if (!*p) continue; -+ -+ len = q - p + 1; -+ -+ /* First time we check for length */ -+ if (len > sizeof(folder) - 5) -+ r = IMAP_MAILBOX_BADNAME; -+ -+ if (!r) { -+ strncpy(folder, p, len); -+ folder[len] = '\0'; -+ -+ strlcpy(name, namespace->prefix[NAMESPACE_INBOX], sizeof(name)); -+ len = strlcat(name, folder, sizeof(name)); -+ } -+ -+ if (!r) -+ r = (namespace->mboxname_tointernal) (namespace, name, userid, -+ mailboxname); -+ if (!r) -+ r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL, -+ 1, userid, auth_state, 0, 0, 0); -+ -+ if (!r) { -+ numcrt++; -+ syslog(LOG_NOTICE, "autocreateinbox: User %s, subfolder %s creation succeeded.", -+ auth_userid, name); -+ } else { -+ syslog(LOG_WARNING, "autocreateinbox: User %s, subfolder %s creation failed. %s", -+ auth_userid, name, error_message(r)); -+ r=0; -+ continue; -+ } -+ -+ /* Roll through sub */ -+ next_sub = (char *) sub; -+ while (next_sub!=NULL && *next_sub) { -+ for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++); -+ for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++); -+ for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--); -+ if (!*p ) continue; -+ -+ len = q - p + 1; -+ -+ if (len != strlen(folder) || strncmp(folder, p, len)) -+ continue; -+ -+ r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 1); -+ -+ if (!r) { -+ numsub++; -+ syslog(LOG_NOTICE,"autocreateinbox: User %s, subscription to %s succeeded", -+ auth_userid, name); -+ } else -+ syslog(LOG_WARNING, "autocreateinbox: User %s, subscription to %s failed. %s", -+ auth_userid, name, error_message(r)); -+ -+ break; -+ } -+ } -+ -+ if (crt!=NULL && *crt) -+ syslog(LOG_INFO, "User %s, Inbox subfolders, created %d, subscribed %d", -+ auth_userid, numcrt, numsub); -+ -+ /* -+ * Check if shared folders are available for subscription. -+ */ -+ mboxlist_autosubscribe_sharedfolders(namespace, userid, auth_userid, auth_state); -+ -+#ifdef USE_SIEVE -+ /* -+ * Here the autocreate sieve script feature is iniated from. -+ */ -+ source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT); -+ -+ if (source_script) { -+ if (!autoadd_sieve(userid, source_script)) -+ syslog(LOG_NOTICE, "autocreate_sieve: User %s, default sieve script creation succeeded", auth_userid); -+ else -+ syslog(LOG_WARNING, "autocreate_sieve: User %s, default sieve script creation failed", auth_userid); -+ } -+#endif -+ -+ return r; -+} -+ -diff -Naur cyrus-imapd-2.2.12/imap/mboxlist.h cyrus-imapd-2.2.12-autocreate.uncompiled/imap/mboxlist.h ---- cyrus-imapd-2.2.12/imap/mboxlist.h 2004-03-17 20:07:49 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/mboxlist.h 2005-02-15 13:57:19 +0200 -@@ -197,4 +197,10 @@ - int mboxlist_commit(struct txn *tid); - int mboxlist_abort(struct txn *tid); - -+int mboxlist_autocreateinbox(struct namespace *namespace, -+ char *userid, -+ struct auth_state *auth_state, -+ char *mailboxname, int autocreatequota); -+ -+ - #endif -diff -Naur cyrus-imapd-2.2.12/imap/pop3d.c cyrus-imapd-2.2.12-autocreate.uncompiled/imap/pop3d.c ---- cyrus-imapd-2.2.12/imap/pop3d.c 2005-01-04 17:06:13 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/imap/pop3d.c 2005-02-15 13:57:19 +0200 -@@ -152,6 +152,8 @@ - static char popd_apop_chal[45 + MAXHOSTNAMELEN + 1]; /* */ - static void cmd_apop(char *response); - -+static int autocreate_inbox(char *inboxname, char *userid); -+ - static void cmd_auth(char *arg); - static void cmd_capa(void); - static void cmd_pass(char *pass); -@@ -1084,6 +1086,7 @@ - popd_userid = xstrdup(p); - prot_printf(popd_out, "+OK Name is a valid mailbox\r\n"); - } -+ - } - - void cmd_pass(char *pass) -@@ -1328,6 +1331,46 @@ - } - - /* -+ * Autocreate Inbox and subfolders upon login -+ */ -+int autocreate_inbox(char *inboxname, char *auth_userid) -+{ -+ struct auth_state *authstate; -+ int userisadmin; -+ int autocreatequota; -+ int r; -+ -+ if(inboxname == NULL || auth_userid == NULL) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ /* -+ * Exclude anonymous -+ */ -+ if (!strcmp(popd_userid, "anonymous")) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ /* -+ * Check for autocreatequota -+ */ -+ if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ /* -+ * Exclude admin's accounts -+ */ -+ -+ authstate = auth_newstate(popd_userid); -+ userisadmin = global_authisa(authstate, IMAPOPT_ADMINS); -+ if (userisadmin) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ r = mboxlist_autocreateinbox(&popd_namespace, auth_userid, -+ authstate, inboxname, autocreatequota); -+ return r; -+} -+ -+ -+/* - * Complete the login process by opening and locking the user's inbox - */ - int openinbox(void) -@@ -1349,6 +1392,10 @@ - userid, inboxname); - - if (!r) r = mboxlist_detail(inboxname, &type, NULL, &server, &acl, NULL); -+ /* Try once again after autocreate_inbox */ -+ if (r == IMAP_MAILBOX_NONEXISTENT && !(r = autocreate_inbox(inboxname, userid))) -+ r = mboxlist_detail(inboxname, &type, NULL, &server, &acl, NULL); -+ - if (!r && (config_popuseacl = config_getswitch(IMAPOPT_POPUSEACL)) && - (!acl || - !((myrights = cyrus_acl_myrights(popd_authstate, acl)) & ACL_READ))) { -diff -Naur cyrus-imapd-2.2.12/lib/auth.h cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth.h ---- cyrus-imapd-2.2.12/lib/auth.h 2003-10-22 21:50:12 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth.h 2005-02-15 13:57:19 +0200 -@@ -60,4 +60,6 @@ - extern struct auth_state *auth_newstate(const char *identifier); - extern void auth_freestate(struct auth_state *auth_state); - -+extern char *auth_canonuser(struct auth_state *auth_state); -+ - #endif /* INCLUDED_AUTH_H */ -diff -Naur cyrus-imapd-2.2.12/lib/auth_krb.c cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_krb.c ---- cyrus-imapd-2.2.12/lib/auth_krb.c 2003-11-11 05:26:00 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_krb.c 2005-02-15 13:57:19 +0200 -@@ -338,3 +338,11 @@ - free((char *)auth_state); - } - -+char * -+auth_canonuser(struct auth_state *auth_state) -+{ -+ if (auth_state) -+ return auth_state->userid; -+ return NULL; -+} -+ -diff -Naur cyrus-imapd-2.2.12/lib/auth_krb5.c cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_krb5.c ---- cyrus-imapd-2.2.12/lib/auth_krb5.c 2004-01-16 17:28:58 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_krb5.c 2005-02-15 13:57:19 +0200 -@@ -193,4 +193,11 @@ - free(auth_state); - } - -+char * -+auth_canonuser(struct auth_state *auth_state) -+{ -+ if (auth_state) -+ return auth_state->userid; -+ return NULL; -+} - -diff -Naur cyrus-imapd-2.2.12/lib/auth_pts.c cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_pts.c ---- cyrus-imapd-2.2.12/lib/auth_pts.c 2004-02-25 01:11:37 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_pts.c 2005-02-15 13:57:19 +0200 -@@ -349,3 +349,11 @@ - { - free(auth_state); - } -+ -+char *auth_canonuser(struct auth_state *auth_state) -+{ -+ if (auth_state) -+ return auth_state->userid.id; -+ return NULL; -+} -+ -diff -Naur cyrus-imapd-2.2.12/lib/auth_unix.c cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_unix.c ---- cyrus-imapd-2.2.12/lib/auth_unix.c 2004-09-14 01:49:29 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/lib/auth_unix.c 2005-02-15 13:57:19 +0200 -@@ -267,4 +267,11 @@ - free((char *)auth_state); - } - -+char *auth_canonuser(struct auth_state *auth_state) -+{ -+ if (auth_state) -+ return auth_state->userid; -+ -+ return NULL; -+} - -diff -Naur cyrus-imapd-2.2.12/lib/imapoptions cyrus-imapd-2.2.12-autocreate.uncompiled/lib/imapoptions ---- cyrus-imapd-2.2.12/lib/imapoptions 2004-07-21 22:07:45 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/lib/imapoptions 2005-02-15 13:57:19 +0200 -@@ -169,6 +169,51 @@ - /* Number of seconds to wait before returning a timeout failure when - performing a client connection (e.g. in a murder enviornment) */ - -+{ "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 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 the it. Otherwise the subscription fails. */ -+ -+{ "autosubscribe_all_sharedfolders", 0, SWITCH } -+/* If set to yes then 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 then the sieve script that is -+ compiled on the fly will be saved in the file name that autocreate_sieve_compiledscript -+ option points. In order a compiled script to be generated, autocreate_sieve_script and -+ autocreate_sieve_compiledscript must have valid values */ -+ - { "configdirectory", NULL, STRING } - /* The pathname of the IMAP configuration directory. This field is - required. */ -diff -Naur cyrus-imapd-2.2.12/notifyd/Makefile.in cyrus-imapd-2.2.12-autocreate.uncompiled/notifyd/Makefile.in ---- cyrus-imapd-2.2.12/notifyd/Makefile.in 2004-05-28 21:03:06 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/notifyd/Makefile.in 2005-02-15 13:57:19 +0200 -@@ -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.2.12/notifyd/notifyd.c cyrus-imapd-2.2.12-autocreate.uncompiled/notifyd/notifyd.c ---- cyrus-imapd-2.2.12/notifyd/notifyd.c 2004-12-17 18:32:25 +0200 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/notifyd/notifyd.c 2005-02-15 13:57:19 +0200 -@@ -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.2.12/ptclient/Makefile.in cyrus-imapd-2.2.12-autocreate.uncompiled/ptclient/Makefile.in ---- cyrus-imapd-2.2.12/ptclient/Makefile.in 2004-05-28 21:03:08 +0300 -+++ cyrus-imapd-2.2.12-autocreate.uncompiled/ptclient/Makefile.in 2005-02-15 13:57:19 +0200 -@@ -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@ diff --git a/cyrus-imapd-2.2.12-autosievefolder-0.6.diff b/cyrus-imapd-2.2.12-autosievefolder-0.6.diff deleted file mode 100644 index ce672d3..0000000 --- a/cyrus-imapd-2.2.12-autosievefolder-0.6.diff +++ /dev/null @@ -1,193 +0,0 @@ -diff -Naur cyrus-imapd-2.2.12/README.autosievefolder cyrus-imapd-2.2.12-autosieve.uncompiled/README.autosievefolder ---- cyrus-imapd-2.2.12/README.autosievefolder 1970-01-01 02:00:00 +0200 -+++ cyrus-imapd-2.2.12-autosieve.uncompiled/README.autosievefolder 2005-02-15 13:59:51 +0200 -@@ -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.2.12/imap/lmtp_sieve.c cyrus-imapd-2.2.12-autosieve.uncompiled/imap/lmtp_sieve.c ---- cyrus-imapd-2.2.12/imap/lmtp_sieve.c 2004-06-01 16:47:16 +0300 -+++ cyrus-imapd-2.2.12-autosieve.uncompiled/imap/lmtp_sieve.c 2005-02-15 13:59:51 +0200 -@@ -72,6 +72,8 @@ - #include "util.h" - #include "version.h" - #include "xmalloc.h" -+#include "imap_err.h" -+ - - static int sieve_usehomedir = 0; - static const char *sieve_dir = NULL; -@@ -98,6 +100,9 @@ - int quotaoverride, - int acloverride); - -+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]; -@@ -312,6 +317,7 @@ - } - - -+ - static int sieve_redirect(void *ac, - void *ic __attribute__((unused)), - void *sc, void *mc, const char **errmsg) -@@ -444,7 +450,18 @@ - sd->username, mdata->notifyheader, - namebuf, quotaoverride, 0); - } -- -+ if (ret == IMAP_MAILBOX_NONEXISTENT) { -+ /* if "plus" folder under INBOX, then try to create it */ -+ syslog(LOG_DEBUG, "calling autosieve folder for : %s", namebuf); -+ ret = autosieve_subfolder((char *) sd->username, sd->authstate, namebuf, mdata->namespace); -+ -+ if (!ret) -+ ret = deliver_mailbox(md->data, 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; -@@ -882,3 +899,77 @@ - - 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(subfolder == NULL || userid == NULL) -+ return IMAP_MAILBOX_NONEXISTENT; -+ -+ 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.2.12/lib/imapoptions cyrus-imapd-2.2.12-autosieve.uncompiled/lib/imapoptions ---- cyrus-imapd-2.2.12/lib/imapoptions 2004-07-21 22:07:45 +0300 -+++ cyrus-imapd-2.2.12-autosieve.uncompiled/lib/imapoptions 2005-02-15 13:59:51 +0200 -@@ -752,6 +752,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, lmtpd and nntpd attempt to only write one copy of a message per - partition and create hard links, resulting in a potentially large diff --git a/cyrus-imapd-2.2.12-dam_invalid_id-christos.patch b/cyrus-imapd-2.2.12-dam_invalid_id-christos.patch new file mode 100644 index 0000000..687f6fd --- /dev/null +++ b/cyrus-imapd-2.2.12-dam_invalid_id-christos.patch @@ -0,0 +1,62 @@ +--- cyrus-imapd-2.2.12/lib/acl_afs.c.orig 2005-07-14 17:12:53 +0300 ++++ cyrus-imapd-2.2.12/lib/acl_afs.c 2005-07-14 17:17:44 +0300 +@@ -119,12 +119,17 @@ + char *thisid, *nextid; + int oldaccess = 0; + char *rights; ++ int identifier_found = 0; ++ int identifier_overridden = 0; + + /* Convert 'identifier' into canonical form */ + if (*identifier == '-') { + char *canonid = auth_canonifyid(identifier+1, 0); +- if (!canonid) { ++ if (!canonid && access != 0L) { + return -1; ++ } else if (!canonid && access == 0L) { ++ canonid = identifier+1; ++ identifier_overridden = 1; + } + newidentifier = xmalloc(strlen(canonid)+2); + newidentifier[0] = '-'; +@@ -135,9 +140,15 @@ + } + } + else { ++ newidentifier = xmalloc(strlen(identifier)+1); ++ strlcpy(newidentifier, identifier, strlen(identifier)+1); ++ + identifier = auth_canonifyid(identifier, 0); +- if (!identifier) { ++ if (!identifier && access != 0L) { + return -1; ++ } else if(!identifier && access == 0L) { ++ identifier = newidentifier; ++ identifier_overridden = 1; + } + if (canonproc) { + access = canonproc(canonrock, identifier, access); +@@ -165,6 +176,7 @@ + *nextid++ = '\0'; + + if (strcmp(identifier, thisid) == 0) { ++ identifier_found = 1; + oldaccess = cyrus_acl_strtomask(rights); + break; + } +@@ -172,6 +184,15 @@ + nextid[-1] = '\t'; + } + ++ /* ++ * In case we have overridden the canonification of the ++ * identifier, but still the identifier does not exist in ++ * the mailboxdb, then return error as normally expected. ++ */ ++ if(identifier_overridden && !identifier_found) { ++ return -1; ++ } ++ + switch (mode) { + case ACL_MODE_SET: + break; diff --git a/cyrus-imapd-2.2.12-munge8bit.patch b/cyrus-imapd-2.2.12-munge8bit.patch new file mode 100644 index 0000000..d6f1484 --- /dev/null +++ b/cyrus-imapd-2.2.12-munge8bit.patch @@ -0,0 +1,133 @@ +diff -Naur cyrus-imapd-2.2.12/doc/man/deliver.8.html cyrus-imapd-2.2.12.munge8bit/doc/man/deliver.8.html +--- cyrus-imapd-2.2.12/doc/man/deliver.8.html 2005-02-14 19:02:17.000000000 +0100 ++++ cyrus-imapd-2.2.12.munge8bit/doc/man/deliver.8.html 2005-06-18 19:02:39.000000000 +0200 +@@ -223,13 +223,15 @@ + + +

Depending on the setting of reject8bit in +-imapd.conf(5), deliver either rejects messages with +-8-bit-set characters in the headers or changes these +-characters to ‘X’. This is because such +-characters can’t be interpreted since the character +-set is not known, although some communities not well-served +-by US-ASCII assume that those characters can be used to +-represent characters not present in US-ASCII.

++imapd.conf(5), deliver either rejects/accepts ++messages with 8-bit-set characters in the headers. If we ++accept messages with 8-bit-set characters in the headers, ++then depending on the setting of munge8bit, these ++characters are either left un-touched or changed to ‘X’. This ++is because such characters can’t be interpreted since ++the character set is not known, although some communities ++not well-served by US-ASCII assume that those characters can ++be used to represent characters not present in US-ASCII.

+ +

A method for encoding 8-bit-set characters is provided by + RFC 2047.

+diff -Naur cyrus-imapd-2.2.12/doc/man/imapd.conf.5.html cyrus-imapd-2.2.12.munge8bit/doc/man/imapd.conf.5.html +--- cyrus-imapd-2.2.12/doc/man/imapd.conf.5.html 2005-02-14 19:02:18.000000000 +0100 ++++ cyrus-imapd-2.2.12.munge8bit/doc/man/imapd.conf.5.html 2005-06-18 18:59:46.000000000 +0200 +@@ -2562,7 +2562,7 @@ + +

If enabled, lmtpd rejects messages with 8-bit characters + in the headers. Otherwise, 8-bit characters are changed to +-‘X’. (A proper soultion to non-ASCII characters ++‘X’. (A proper solution to non-ASCII characters + in headers is offered by RFC 2047 and its predecessors.)

+ + +diff -Naur cyrus-imapd-2.2.12/imap/message.c cyrus-imapd-2.2.12.munge8bit/imap/message.c +--- cyrus-imapd-2.2.12/imap/message.c 2004-09-16 19:58:54.000000000 +0200 ++++ cyrus-imapd-2.2.12.munge8bit/imap/message.c 2005-06-18 18:58:33.000000000 +0200 +@@ -227,6 +227,7 @@ + int n; + int sawcr = 0, sawnl; + int reject8bit = config_getswitch(IMAPOPT_REJECT8BIT); ++ int munge8bit = config_getswitch(IMAPOPT_MUNGE8BIT); + int inheader = 1, blankline = 1; + + while (size) { +@@ -262,7 +263,7 @@ + /* We have been configured to reject all mail of this + form. */ + if (!r) r = IMAP_MESSAGE_CONTAINS8BIT; +- } else { ++ } else if (munge8bit) { + /* We have been configured to munge all mail of this + form. */ + *p = 'X'; +diff -Naur cyrus-imapd-2.2.12/imap/spool.c cyrus-imapd-2.2.12.munge8bit/imap/spool.c +--- cyrus-imapd-2.2.12/imap/spool.c 2004-10-27 22:40:50.000000000 +0200 ++++ cyrus-imapd-2.2.12.munge8bit/imap/spool.c 2005-06-18 18:58:33.000000000 +0200 +@@ -140,6 +140,7 @@ + state s = NAME_START; + int r = 0; + int reject8bit = config_getswitch(IMAPOPT_REJECT8BIT); ++ int munge8bit = config_getswitch(IMAPOPT_MUNGE8BIT); + const char **skip = NULL; + + if (namelen == 0) { +@@ -266,7 +267,7 @@ + form. */ + r = IMAP_MESSAGE_CONTAINS8BIT; + goto ph_error; +- } else { ++ } else if (munge8bit) { + /* We have been configured to munge all mail of this + form. */ + c = 'X'; +diff -Naur cyrus-imapd-2.2.12/lib/imapoptions cyrus-imapd-2.2.12.munge8bit/lib/imapoptions +--- cyrus-imapd-2.2.12/lib/imapoptions 2004-07-21 21:07:45.000000000 +0200 ++++ cyrus-imapd-2.2.12.munge8bit/lib/imapoptions 2005-06-18 18:58:33.000000000 +0200 +@@ -458,6 +458,12 @@ + { "mboxlist_db", "skiplist", STRINGLIST("flat", "berkeley", "skiplist")} + /* The cyrusdb backend to use for the mailbox list. */ + ++{ "munge8bit", 1, SWITCH } ++/* If enabled, lmtpd munges messages with 8-bit characters. These characters ++ are changed to `X'. If \fBreject8bit\fR is enabled, setting \fBmunge8bit\fR ++ has no effect. (A proper solution to non-ASCII characters in headers is ++ offered by RFC 2047 and its predecessors.) */ ++ + # xxx badly worded + { "mupdate_connections_max", 128, INT } + /* The max number of connections that a mupdate process will allow, this +@@ -670,9 +676,7 @@ + + { "reject8bit", 0, SWITCH } + /* If enabled, lmtpd rejects messages with 8-bit characters in the +- headers. Otherwise, 8-bit characters are changed to `X'. (A +- proper soultion to non-ASCII characters in headers is offered by +- RFC 2047 and its predecessors.) */ ++ headers. */ + + { "rfc2046_strict", 0, SWITCH } + /* If enabled, imapd will be strict (per RFC 2046) when matching MIME +diff -Naur cyrus-imapd-2.2.12/man/deliver.8 cyrus-imapd-2.2.12.munge8bit/man/deliver.8 +--- cyrus-imapd-2.2.12/man/deliver.8 2004-06-21 20:40:10.000000000 +0200 ++++ cyrus-imapd-2.2.12.munge8bit/man/deliver.8 2005-06-18 18:58:33.000000000 +0200 +@@ -147,8 +147,10 @@ + Accept messages using the LMTP protocol. + .SH NOTES + Depending on the setting of \fBreject8bit\fR in \fBimapd.conf(5)\fR, deliver +-either rejects messages with 8-bit-set characters in the headers or +-changes these characters to `X'. ++either rejects/accepts messages with 8-bit-set characters in the headers. ++If we accept messages with 8-bit-set characters in the headers, then depending ++on the setting of \fBmunge8bit\fR, these characters are either left un-touched ++or changed to . + This is because such characters can't be interpreted since the + character set is not known, although some communities not well-served by + US-ASCII assume that those characters can be used to represent characters not +diff -Naur cyrus-imapd-2.2.12/man/imapd.conf.5 cyrus-imapd-2.2.12.munge8bit/man/imapd.conf.5 +--- cyrus-imapd-2.2.12/man/imapd.conf.5 2005-02-14 19:02:16.000000000 +0100 ++++ cyrus-imapd-2.2.12.munge8bit/man/imapd.conf.5 2005-06-18 18:59:08.000000000 +0200 +@@ -551,7 +551,7 @@ + .IP "\fBreject8bit:\fR 0" 5 + If enabled, lmtpd rejects messages with 8-bit characters in the + headers. Otherwise, 8-bit characters are changed to `X'. (A +-proper soultion to non-ASCII characters in headers is offered by ++proper solution to non-ASCII characters in headers is offered by + RFC 2047 and its predecessors.) + .IP "\fBrfc2046_strict:\fR 0" 5 + If enabled, imapd will be strict (per RFC 2046) when matching MIME diff --git a/cyrus-imapd-2.2.12-no_transfig.patch b/cyrus-imapd-2.2.12-no_transfig.patch new file mode 100644 index 0000000..dd78906 --- /dev/null +++ b/cyrus-imapd-2.2.12-no_transfig.patch @@ -0,0 +1,13 @@ +diff -Naur cyrus-imapd-2.2.12.orig/doc/Makefile.dist cyrus-imapd-2.2.12/doc/Makefile.dist +--- cyrus-imapd-2.2.12.orig/doc/Makefile.dist Wed Oct 22 20:50:04 2003 ++++ cyrus-imapd-2.2.12/doc/Makefile.dist Wed Nov 9 13:23:58 2005 +@@ -13,7 +13,7 @@ + + rm -f groff-html-*.png pod2htm* + +- fig2dev -L png murder.fig murder.png +- fig2dev -L png netnews.fig netnews.png ++# fig2dev -L png murder.fig murder.png ++# fig2dev -L png netnews.fig netnews.png + + (cd text; make) diff --git a/cyrus-imapd-2.2.12-notify_sms.patch b/cyrus-imapd-2.2.12-notify_sms.patch new file mode 100644 index 0000000..de4e18b --- /dev/null +++ b/cyrus-imapd-2.2.12-notify_sms.patch @@ -0,0 +1,304 @@ +diff -Naur cyrus-imapd-2.2.12.orig/doc/man/imapd.conf.5.html cyrus-imapd-2.2.12/doc/man/imapd.conf.5.html +--- cyrus-imapd-2.2.12.orig/doc/man/imapd.conf.5.html 2005-02-14 19:02:18.000000000 +0100 ++++ cyrus-imapd-2.2.12/doc/man/imapd.conf.5.html 2005-08-16 13:32:36.000000000 +0200 +@@ -2751,6 +2751,24 @@ + + + ++

sendsms: /usr/bin/sendsms

++

++ ++ ++ ++ ++ ++
++

The pathname of the sendsms executable. Sieve invokes ++sendsms for sending SMS notifications.

++
++ ++

++ ++ ++ +
+

servername: <none>

+ +diff -Naur cyrus-imapd-2.2.12.orig/doc/man/notifyd.8.html cyrus-imapd-2.2.12/doc/man/notifyd.8.html +--- cyrus-imapd-2.2.12.orig/doc/man/notifyd.8.html 2005-02-14 19:02:19.000000000 +0100 ++++ cyrus-imapd-2.2.12/doc/man/notifyd.8.html 2005-08-16 13:17:33.000000000 +0200 +@@ -181,6 +181,18 @@ + + + ++

sms

++ ++ ++ ++

Send the notification as SMS. This method can ONLY be used in ++a Sieve ’notify’ action as it requires a ++sms: URL to be specified as an :option.

++ ++ ++ ++ ++ +

zephyr

+ + +diff -Naur cyrus-imapd-2.2.12.orig/lib/imapoptions cyrus-imapd-2.2.12/lib/imapoptions +--- cyrus-imapd-2.2.12.orig/lib/imapoptions 2004-07-21 21:07:45.000000000 +0200 ++++ cyrus-imapd-2.2.12/lib/imapoptions 2005-08-16 13:27:08.000000000 +0200 +@@ -721,6 +721,10 @@ + /* The pathname of the sendmail executable. Sieve invokes sendmail + for sending rejections, redirects and vacation responses. */ + ++{ "sendsms", "/usr/bin/sendsms", STRING } ++/* The pathname of the sendsms executable. Sieve invokes sendsms ++ for sending SMS notifications. */ ++ + { "servername", NULL, STRING } + /* This is the hostname visible in the greeting messages of the POP, + IMAP and LMTP daemons. If it is unset, then the result returned +diff -Naur cyrus-imapd-2.2.12.orig/man/imapd.conf.5 cyrus-imapd-2.2.12/man/imapd.conf.5 +--- cyrus-imapd-2.2.12.orig/man/imapd.conf.5 2005-02-14 19:02:16.000000000 +0100 ++++ cyrus-imapd-2.2.12/man/imapd.conf.5 2005-08-16 13:35:40.000000000 +0200 +@@ -590,6 +590,9 @@ + .IP "\fBsendmail:\fR /usr/lib/sendmail" 5 + The pathname of the sendmail executable. Sieve invokes sendmail + for sending rejections, redirects and vacation responses. ++.IP "\fBsendsms:\fR /usr/bin/sendsms" 5 ++The pathname of the sendsms executable. Sieve invokes sendsms ++for sending SMS notifications. + .IP "\fBservername:\fR " 5 + This is the hostname visible in the greeting messages of the POP, + IMAP and LMTP daemons. If it is unset, then the result returned +diff -Naur cyrus-imapd-2.2.12.orig/man/notifyd.8 cyrus-imapd-2.2.12/man/notifyd.8 +--- cyrus-imapd-2.2.12.orig/man/notifyd.8 2003-08-10 01:43:14.000000000 +0200 ++++ cyrus-imapd-2.2.12/man/notifyd.8 2005-08-16 13:18:03.000000000 +0200 +@@ -110,6 +110,11 @@ + Sieve 'notify' action as it requires a \fImailto:\fR URL to be + specified as an \fI:option\fR. + .TP ++.B sms ++Send the notification as SMS. This method can ONLY be used in a ++Sieve 'notify' action as it requires a \fIsms:\fR URL to be ++specified as an \fI:option\fR. ++.TP + .B zephyr + Send the notification as a zephyrgram. If used in a Sieve 'notify' + action, additional recipients can be specified as \fI:options\fR. +diff -Naur cyrus-imapd-2.2.12.orig/notifyd/Makefile.in cyrus-imapd-2.2.12/notifyd/Makefile.in +--- cyrus-imapd-2.2.12.orig/notifyd/Makefile.in 2004-05-28 20:03:06.000000000 +0200 ++++ cyrus-imapd-2.2.12/notifyd/Makefile.in 2005-08-16 15:18:45.000000000 +0200 +@@ -82,7 +82,7 @@ + install: + $(INSTALL) -m 755 notifyd $(DESTDIR)$(service_path) + +-OBJS= notifyd.o notify_null.o notify_log.o notify_mailto.o notify_zephyr.o ++OBJS= notifyd.o notify_null.o notify_log.o notify_mailto.o notify_sms.o notify_zephyr.o + + notifytest: notifytest.o + $(CC) $(LDFLAGS) -o notifytest \ +diff -Naur cyrus-imapd-2.2.12.orig/notifyd/notifyd.h cyrus-imapd-2.2.12/notifyd/notifyd.h +--- cyrus-imapd-2.2.12.orig/notifyd/notifyd.h 2003-02-13 21:15:48.000000000 +0100 ++++ cyrus-imapd-2.2.12/notifyd/notifyd.h 2005-08-16 12:58:17.000000000 +0200 +@@ -48,6 +48,7 @@ + #include "notify_null.h" + #include "notify_log.h" + #include "notify_mailto.h" ++#include "notify_sms.h" + #include "notify_zephyr.h" + + /* Notify method dispatch table definition */ +@@ -64,6 +65,7 @@ + { "null", notify_null }, /* do nothing */ + { "log", notify_log }, /* use syslog (for testing) */ + { "mailto", notify_mailto }, /* send an email */ ++ { "sms", notify_sms }, /* send an sms */ + #ifdef HAVE_ZEPHYR + { "zephyr", notify_zephyr }, /* send a zephyrgram */ + #endif +diff -Naur cyrus-imapd-2.2.12.orig/notifyd/notify_sms.c cyrus-imapd-2.2.12/notifyd/notify_sms.c +--- cyrus-imapd-2.2.12.orig/notifyd/notify_sms.c 1970-01-01 01:00:00.000000000 +0100 ++++ cyrus-imapd-2.2.12/notifyd/notify_sms.c 2005-08-16 18:43:56.000000000 +0200 +@@ -0,0 +1,111 @@ ++/* notify_sms.c -- SMS notification method ++ * Simon Matter ++ */ ++/* ++ * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The name "Carnegie Mellon University" must not be used to ++ * endorse or promote products derived from this software without ++ * prior written permission. For permission or any other legal ++ * details, please contact ++ * Office of Technology Transfer ++ * Carnegie Mellon University ++ * 5000 Forbes Avenue ++ * Pittsburgh, PA 15213-3890 ++ * (412) 268-4387, fax: (412) 268-7395 ++ * tech-transfer@andrew.cmu.edu ++ * ++ * 4. Redistributions of any form whatsoever must retain the following ++ * acknowledgment: ++ * "This product includes software developed by Computing Services ++ * at Carnegie Mellon University (http://www.cmu.edu/computing/)." ++ * ++ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO ++ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE ++ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ++ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * notify_sms is based on code from notify_mailto by Ken Murchison. ++ * Copyright (c) 2005 Simon Matter, Invoca Systems. ++ * Release 2005081600/2.2.12 ++*/ ++ ++#include ++ ++#include "notify_sms.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "global.h" ++#include "libconfig.h" ++#include "sieve_interface.h" ++ ++static int global_outgoing_count = 0; ++ ++char* notify_sms(const char *class __attribute__((unused)), ++ const char *priority __attribute__((unused)), ++ const char *user __attribute__((unused)), ++ const char *mailbox __attribute__((unused)), ++ int nopt, char **options, ++ const char *message) ++{ ++ FILE *sm; ++ const char *smbuf[10]; ++ int sm_stat; ++ pid_t sm_pid; ++ int fds[2]; ++ ++ /* XXX check/parse options (sms URI) */ ++ if (nopt < 1) ++ return strdup("NO sms URI not specified"); ++ ++ smbuf[0] = "sendsms"; ++ smbuf[1] = options[0]; ++ smbuf[2] = NULL; ++ ++ pipe(fds); ++ if ((sm_pid = fork()) == 0) { ++ /* i'm the child! run sendsms! */ ++ close(fds[1]); ++ /* make the pipe be stdin */ ++ dup2(fds[0], 0); ++ execv(config_getstring(IMAPOPT_SENDSMS), (char **) smbuf); ++ ++ /* if we're here we suck */ ++ return strdup("NO sms couldn't exec"); ++ } ++ /* i'm the parent */ ++ close(fds[0]); ++ sm = fdopen(fds[1], "w"); ++ ++ if (!sm) ++ return strdup("NO sms could not spawn sendsms process"); ++ ++ fprintf(sm, message); ++ ++ fclose(sm); ++ while (waitpid(sm_pid, &sm_stat, 0) < 0); ++ ++ /* XXX check for sendsms exit code */ ++ ++ return strdup("OK sms notification successful"); ++} +diff -Naur cyrus-imapd-2.2.12.orig/notifyd/notify_sms.h cyrus-imapd-2.2.12/notifyd/notify_sms.h +--- cyrus-imapd-2.2.12.orig/notifyd/notify_sms.h 1970-01-01 01:00:00.000000000 +0100 ++++ cyrus-imapd-2.2.12/notifyd/notify_sms.h 2005-08-16 14:57:16.000000000 +0200 +@@ -0,0 +1,62 @@ ++/* notify_sms.h -- SMS notification method ++ * Simon Matter ++ */ ++/* ++ * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The name "Carnegie Mellon University" must not be used to ++ * endorse or promote products derived from this software without ++ * prior written permission. For permission or any other legal ++ * details, please contact ++ * Office of Technology Transfer ++ * Carnegie Mellon University ++ * 5000 Forbes Avenue ++ * Pittsburgh, PA 15213-3890 ++ * (412) 268-4387, fax: (412) 268-7395 ++ * tech-transfer@andrew.cmu.edu ++ * ++ * 4. Redistributions of any form whatsoever must retain the following ++ * acknowledgment: ++ * "This product includes software developed by Computing Services ++ * at Carnegie Mellon University (http://www.cmu.edu/computing/)." ++ * ++ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO ++ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE ++ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ++ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * notify_sms is based on code from notify_mailto by Ken Murchison. ++ * Copyright (c) 2005 Simon Matter, Invoca Systems. ++ * Release 2005081600/2.2.12 ++ * ++ */ ++ ++#ifndef _NOTIFY_SMS_H_ ++#define _NOTIFY_SMS_H_ ++ ++#include ++ ++/* the only option should be a sms URI */ ++char* notify_sms(const char *class __attribute__((unused)), ++ const char *priority __attribute__((unused)), ++ const char *user __attribute__((unused)), ++ const char *mailbox __attribute__((unused)), ++ int nopt, char **options, ++ const char *message); ++ ++#endif /* _NOTIFY_SMS_H_ */ diff --git a/cyrus-imapd-2.2.12.tar.gz.sig b/cyrus-imapd-2.2.12.tar.gz.sig deleted file mode 100644 index 86a0de7..0000000 Binary files a/cyrus-imapd-2.2.12.tar.gz.sig and /dev/null differ diff --git a/cyrus-imapd-2.2.4-OE-seenstate.patch b/cyrus-imapd-2.2.4-OE-seenstate.patch deleted file mode 100644 index b6d0f46..0000000 --- a/cyrus-imapd-2.2.4-OE-seenstate.patch +++ /dev/null @@ -1,104 +0,0 @@ -# Small patch to Cyrus IMAP 2.2.4 which modifies \Seen state handling to -# make it compatible with Outlook Express. OE makes two connections to a -# given mailfolder: one generates indexes while the other fetches messages. -# Unfortunately it gets confused if \Seen updates caused by the message -# stream aren't immediately flushed and picked up by the index stream. -# -# This patch is a 2.2.4 port from the patch found here: -# http://www-uxsup.csx.cam.ac.uk/~dpc22/cyrus/patches/2.1.16/OutLookExpress-seenstate.patch -# -diff -Naur cyrus-imapd-2.2.4.orig/imap/imapd.c cyrus-imapd-2.2.4/imap/imapd.c ---- cyrus-imapd-2.2.4.orig/imap/imapd.c Thu May 6 20:46:21 2004 -+++ cyrus-imapd-2.2.4/imap/imapd.c Fri May 21 02:10:25 2004 -@@ -3063,6 +3063,10 @@ - snprintf(mytime, sizeof(mytime), "%2.3f", - (clock() - start) / (double) CLOCKS_PER_SEC); - -+ /* Checkpoint \Seen immediately after each FETCH completes. Checks for -+ * changes from other processes at the same time */ -+ index_check_existing(imapd_mailbox, usinguid, 1); -+ - if (r) { - prot_printf(imapd_out, "%s NO %s (%s sec)\r\n", tag, - error_message(r), mytime); -@@ -3184,7 +3188,7 @@ - - index_fetch(imapd_mailbox, msgno, 0, &fetchargs, &fetchedsomething); - -- index_check(imapd_mailbox, 0, 0); -+ index_check_existing(imapd_mailbox, 0, 1); - - if (fetchedsomething) { - prot_printf(imapd_out, "%s OK %s\r\n", tag, -@@ -3321,7 +3325,9 @@ - flag, nflags); - - if (usinguid) { -- index_check(imapd_mailbox, 1, 0); -+ index_check(imapd_mailbox, 1, 1); /* Check \Seen too */ -+ } else { -+ index_check_existing(imapd_mailbox, 0, 1); - } - - if (r) { -diff -Naur cyrus-imapd-2.2.4.orig/imap/imapd.h cyrus-imapd-2.2.4/imap/imapd.h ---- cyrus-imapd-2.2.4.orig/imap/imapd.h Wed Oct 22 20:50:07 2003 -+++ cyrus-imapd-2.2.4/imap/imapd.h Fri May 21 02:06:02 2004 -@@ -233,6 +233,8 @@ - extern void index_operatemailbox(struct mailbox *mailbox); - extern void index_check(struct mailbox *mailbox, int usinguid, - int checkseen); -+extern void -+index_check_existing(struct mailbox *mailbox, int usinguid, int checkseen); - extern void index_checkseen(struct mailbox *mailbox, int quiet, - int usinguid, int oldexists); - -diff -Naur cyrus-imapd-2.2.4.orig/imap/index.c cyrus-imapd-2.2.4/imap/index.c ---- cyrus-imapd-2.2.4.orig/imap/index.c Wed Apr 21 19:40:48 2004 -+++ cyrus-imapd-2.2.4/imap/index.c Fri May 21 02:06:02 2004 -@@ -425,6 +425,45 @@ - } - } - -+/* Nasty hack to report system + user flags updates without checking for -+ * new mail or expunge (relies on index atomic rewrite+rename for expunge). -+ * -+ * Needed to keep Outlook Express happy without breaking IMAP concurrent -+ * access regime which (quite correctly) prohibits unsolicited EXPUNGE and -+ * EXIST responses for non-UID versions of FETCH and STORE. Otherwise you -+ * can end up with hilarous situations such as: -+ * -+ * . FETCH 2 fast -+ * * EXPUNGE 1 <-- from concurrent session. -+ * . FETCH (data relating to previous message _3_, if it exists) -+ * -+ */ -+ -+void -+index_check_existing(struct mailbox *mailbox, int usinguid, int checkseen) -+{ -+ int msgno, i; -+ bit32 user_flags[MAX_USER_FLAGS/32]; -+ -+ if (imapd_exists == -1) -+ return; -+ -+ if (checkseen) -+ index_checkseen(mailbox, 0, usinguid, imapd_exists); -+ -+ for (msgno = 1; msgno <= imapd_exists; msgno++) { -+ if (flagreport[msgno] < LAST_UPDATED(msgno)) { -+ for (i = 0; i < VECTOR_SIZE(user_flags); i++) { -+ user_flags[i] = USER_FLAGS(msgno, i); -+ } -+ index_fetchflags(mailbox, msgno, SYSTEM_FLAGS(msgno), user_flags, -+ LAST_UPDATED(msgno)); -+ if (usinguid) prot_printf(imapd_out, " UID %u", UID(msgno)); -+ prot_printf(imapd_out, ")\r\n"); -+ } -+ } -+} -+ - /* - * Checkpoint the user's \Seen state - * diff --git a/cyrus-imapd-2.2.4-munge8bit.patch b/cyrus-imapd-2.2.4-munge8bit.patch deleted file mode 100644 index d83c9b0..0000000 --- a/cyrus-imapd-2.2.4-munge8bit.patch +++ /dev/null @@ -1,109 +0,0 @@ -diff -Naur cyrus-imapd-2.2.4.orig/doc/man/deliver.8.html cyrus-imapd-2.2.4/doc/man/deliver.8.html ---- cyrus-imapd-2.2.4.orig/doc/man/deliver.8.html Sun May 16 23:05:05 2004 -+++ cyrus-imapd-2.2.4/doc/man/deliver.8.html Thu May 20 19:21:15 2004 -@@ -221,13 +221,15 @@ - - -

Depending on the setting of reject8bit in --imapd.conf(5), deliver either rejects messages with --8-bit-set characters in the headers or changes these --characters to ‘X’. This is because such --characters can’t be interpreted since the character --set is not known, although some communities not well-served --by US-ASCII assume that those characters can be used to --represent characters not present in US-ASCII.

-+imapd.conf(5), deliver either rejects/accepts -+messages with 8-bit-set characters in the headers. If we -+accept messages with 8-bit-set characters in the headers, -+then depending on the setting of munge8bit, these -+characters are either left un-touched or changed to . This -+is because such characters can’t be interpreted since -+the character set is not known, although some communities -+not well-served by US-ASCII assume that those characters can -+be used to represent characters not present in US-ASCII.

- -

A method for encoding 8-bit-set characters is provided by - RFC 2047.

-diff -Naur cyrus-imapd-2.2.4.orig/imap/message.c cyrus-imapd-2.2.4/imap/message.c ---- cyrus-imapd-2.2.4.orig/imap/message.c Fri Feb 27 18:44:55 2004 -+++ cyrus-imapd-2.2.4/imap/message.c Thu May 20 19:15:23 2004 -@@ -227,6 +227,7 @@ - int n; - int sawcr = 0, sawnl; - int reject8bit = config_getswitch(IMAPOPT_REJECT8BIT); -+ int munge8bit = config_getswitch(IMAPOPT_MUNGE8BIT); - int inheader = 1, blankline = 1; - - while (size) { -@@ -262,7 +263,7 @@ - /* We have been configured to reject all mail of this - form. */ - if (!r) r = IMAP_MESSAGE_CONTAINS8BIT; -- } else { -+ } else if (munge8bit) { - /* We have been configured to munge all mail of this - form. */ - *p = 'X'; -diff -Naur cyrus-imapd-2.2.4.orig/imap/spool.c cyrus-imapd-2.2.4/imap/spool.c ---- cyrus-imapd-2.2.4.orig/imap/spool.c Thu Mar 4 17:09:34 2004 -+++ cyrus-imapd-2.2.4/imap/spool.c Thu May 20 19:16:52 2004 -@@ -140,6 +140,7 @@ - state s = NAME_START; - int r = 0; - int reject8bit = config_getswitch(IMAPOPT_REJECT8BIT); -+ int munge8bit = config_getswitch(IMAPOPT_MUNGE8BIT); - const char **skip = NULL; - - if (namelen == 0) { -@@ -266,7 +267,7 @@ - form. */ - r = IMAP_MESSAGE_CONTAINS8BIT; - goto ph_error; -- } else { -+ } else if (munge8bit) { - /* We have been configured to munge all mail of this - form. */ - c = 'X'; -diff -Naur cyrus-imapd-2.2.4.orig/lib/imapoptions cyrus-imapd-2.2.4/lib/imapoptions ---- cyrus-imapd-2.2.4.orig/lib/imapoptions Wed May 5 20:53:09 2004 -+++ cyrus-imapd-2.2.4/lib/imapoptions Thu May 20 19:15:23 2004 -@@ -454,6 +454,12 @@ - { "mboxlist_db", "skiplist", STRINGLIST("flat", "berkeley", "skiplist")} - /* The cyrusdb backend to use for the mailbox list. */ - -+{ "munge8bit", 1, SWITCH } -+/* If enabled, lmtpd munges messages with 8-bit characters. These characters -+ are changed to . If \fBreject8bit\fR is enabled, setting \fBmunge8bit\fR -+ has no effect. (A proper soultion to non-ASCII characters in headers is -+ offered by RFC 2047 and its predecessors.) */ -+ - # xxx badly worded - { "mupdate_connections_max", 128, INT } - /* The max number of connections that a mupdate process will allow, this -@@ -654,9 +660,7 @@ - - { "reject8bit", 0, SWITCH } - /* If enabled, lmtpd rejects messages with 8-bit characters in the -- headers. Otherwise, 8-bit characters are changed to `X'. (A -- proper soultion to non-ASCII characters in headers is offered by -- RFC 2047 and its predecessors.) */ -+ headers. */ - - { "rfc2046_strict", 0, SWITCH } - /* If enabled, imapd will be strict (per RFC 2046) when matching MIME -diff -Naur cyrus-imapd-2.2.4.orig/man/deliver.8 cyrus-imapd-2.2.4/man/deliver.8 ---- cyrus-imapd-2.2.4.orig/man/deliver.8 Sat May 25 21:57:47 2002 -+++ cyrus-imapd-2.2.4/man/deliver.8 Thu May 20 19:15:23 2004 -@@ -147,8 +147,10 @@ - Accept messages using the LMTP protocol. - .SH NOTES - Depending on the setting of \fBreject8bit\fR in \fBimapd.conf(5)\fR, deliver --either rejects messages with 8-bit-set characters in the headers or --changes these characters to `X'. -+either rejects/accepts messages with 8-bit-set characters in the headers. -+If we accept messages with 8-bit-set characters in the headers, then depending -+on the setting of \fBmunge8bit\fR, these characters are either left un-touched -+or changed to . - This is because such characters can't be interpreted since the - character set is not known, although some communities not well-served by - US-ASCII assume that those characters can be used to represent characters not diff --git a/cyrus-imapd-2.3.1-authid_normalize.patch b/cyrus-imapd-2.3.1-authid_normalize.patch new file mode 100644 index 0000000..9ebffd7 --- /dev/null +++ b/cyrus-imapd-2.3.1-authid_normalize.patch @@ -0,0 +1,81 @@ +diff -Naur cyrus-imapd-2.3.1.orig/lib/auth_unix.c cyrus-imapd-2.3.1/lib/auth_unix.c +--- cyrus-imapd-2.3.1.orig/lib/auth_unix.c Wed Feb 16 22:06:50 2005 ++++ cyrus-imapd-2.3.1/lib/auth_unix.c Wed Dec 21 13:50:05 2005 +@@ -157,10 +157,12 @@ + size_t len; + { + static char retbuf[81]; ++ char backup[81]; + struct group *grp; + char sawalpha; + char *p; + int username_tolower = 0; ++ int ic,rbc; + + if(!len) len = strlen(identifier); + if(len >= sizeof(retbuf)) return NULL; +@@ -210,6 +212,22 @@ + /* now we don't */ + /* if (!sawalpha) return NULL; */ + ++ if( (libcyrus_config_getswitch(CYRUSOPT_NORMALIZEUID) == 1) ) { ++ strcpy(backup,retbuf); ++ /* remove leading blanks */ ++ for(ic=0; isblank(backup[ic]); ic++); ++ for(rbc=0; backup[ic]; ic++) { ++ retbuf[rbc] = ( isalpha(backup[ic]) ? ++ tolower(backup[ic]) : backup[ic] ); ++ rbc++; ++ } ++ retbuf[rbc] = '\0'; ++ /* remove trailing blanks */ ++ for(--rbc; isblank(retbuf[rbc]); rbc--) { ++ retbuf[rbc] = '\0'; ++ } ++ } ++ + return retbuf; + } + +diff -Naur cyrus-imapd-2.3.1.orig/lib/imapoptions cyrus-imapd-2.3.1/lib/imapoptions +--- cyrus-imapd-2.3.1.orig/lib/imapoptions Tue Dec 13 20:36:11 2005 ++++ cyrus-imapd-2.3.1/lib/imapoptions Wed Dec 21 13:50:05 2005 +@@ -990,6 +990,11 @@ + interface, otherwise the user is assumed to be in the default + domain (if set). */ + ++{ "normalizeuid", 0, SWITCH } ++/* Lowercase uid and strip leading and trailing blanks. It is recommended ++ to set this to yes, especially if OpenLDAP is used as authentication ++ source. */ ++ + /* + .SH SEE ALSO + .PP +diff -Naur cyrus-imapd-2.3.1.orig/lib/libcyr_cfg.c cyrus-imapd-2.3.1/lib/libcyr_cfg.c +--- cyrus-imapd-2.3.1.orig/lib/libcyr_cfg.c Tue Dec 13 20:36:12 2005 ++++ cyrus-imapd-2.3.1/lib/libcyr_cfg.c Wed Dec 21 13:50:05 2005 +@@ -127,6 +127,11 @@ + CFGVAL(const char *, "c"), + CYRUS_OPT_STRING }, + ++ { CYRUSOPT_NORMALIZEUID, ++ CFGVAL(long, 1), ++ CYRUS_OPT_SWITCH }, ++ ++ + { CYRUSOPT_LAST, { NULL }, CYRUS_OPT_NOTOPT } + }; + +diff -Naur cyrus-imapd-2.3.1.orig/lib/libcyr_cfg.h cyrus-imapd-2.3.1/lib/libcyr_cfg.h +--- cyrus-imapd-2.3.1.orig/lib/libcyr_cfg.h Tue Dec 13 20:36:12 2005 ++++ cyrus-imapd-2.3.1/lib/libcyr_cfg.h Wed Dec 21 13:51:37 2005 +@@ -101,6 +101,8 @@ + CYRUSOPT_BERKELEY_TXNS_MAX, + /* RFC 2086 right which allows DELETE ("c") */ + CYRUSOPT_DELETERIGHT, ++ /* Lowercase uid and strip leading and trailing blanks (OFF) */ ++ CYRUSOPT_NORMALIZEUID, + + CYRUSOPT_LAST + diff --git a/cyrus-imapd-2.3.1-autocreate-0.10-0.diff b/cyrus-imapd-2.3.1-autocreate-0.10-0.diff new file mode 100644 index 0000000..48aa75d --- /dev/null +++ b/cyrus-imapd-2.3.1-autocreate-0.10-0.diff @@ -0,0 +1,2348 @@ +diff -Naur cyrus-imapd-2.3.1/README.autocreate cyrus-imapd-2.3.1-autocreate/README.autocreate +--- cyrus-imapd-2.3.1/README.autocreate 1970-01-01 02:00:00 +0200 ++++ cyrus-imapd-2.3.1-autocreate/README.autocreate 2006-01-19 03:53:40 +0200 +@@ -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. ++ ++ ++ ++Things to be done ++================= ++ ++1. Support MUPDATE ++ ++It is within the developers' intentions to support the mupdate protocol, but serious ++design issues on future cyrus releases have to resolved first. ++ ++2. Select different attributes (quota, partition, sieve filter, etc) depending on the group ++a user belongs to. ++ ++For more information and updates please visit http://email.uoa.gr/projects/cyrus/autocreate ++ +diff -Naur cyrus-imapd-2.3.1/imap/Makefile.in cyrus-imapd-2.3.1-autocreate/imap/Makefile.in +--- cyrus-imapd-2.3.1/imap/Makefile.in 2005-12-13 17:28:43 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/Makefile.in 2006-01-19 03:53:41 +0200 +@@ -101,7 +101,7 @@ + convert_code.o duplicate.o saslclient.o saslserver.o signals.o \ + annotate.o search_engines.o squat.o squat_internal.o mbdump.o \ + imapparse.o telemetry.o user.o notify.o protocol.o idle.o quota_db.o \ +- sync_log.o $(SEEN) mboxkey.o ++ sync_log.o autosieve.o $(SEEN) mboxkey.o + + IMAPDOBJS=pushstats.o backend.o imapd.o proxy.o imap_proxy.o index.o \ + tls.o version.o +@@ -118,7 +118,7 @@ + fud smmapd reconstruct quota mbpath ipurge \ + cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \ + ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \ +- unexpunge @IMAP_PROGS@ ++ unexpunge compile_sieve @IMAP_PROGS@ + + BUILTSOURCES = imap_err.c imap_err.h pushstats.c pushstats.h \ + lmtpstats.c lmtpstats.h xversion.h mupdate_err.c mupdate_err.h \ +@@ -185,7 +185,7 @@ + ### Services + idled: idled.o mutex_fake.o libimap.a $(DEPLIBS) + $(CC) $(LDFLAGS) -o idled \ +- idled.o mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) ++ idled.o mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + + lmtpd: lmtpd.o proxy.o $(LMTPOBJS) $(SIEVE_OBJS) mutex_fake.o \ + libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) +@@ -199,10 +199,10 @@ + $(SERVICE) lmtpd.o proxy.o $(LMTPOBJS) $(SIEVE_OBJS) \ + mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + +-imapd: xversion $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) ++imapd: xversion $(IMAPDOBJS) mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) + $(CC) $(LDFLAGS) -o imapd \ + $(SERVICE) $(IMAPDOBJS) mutex_fake.o \ +- libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + + imapd.pure: $(IMAPDOBJS) mutex_fake.o libimap.a $(DEPLIBS) $(SERVICE) + $(PURIFY) $(PUREOPT) $(CC) $(LDFLAGS) -o imapd.pure \ +@@ -219,7 +219,7 @@ + $(CC) $(LDFLAGS) -o mupdate \ + $(SERVICETHREAD) mupdate.o mupdate-slave.o mupdate-client.o \ + mutex_pthread.o tls.o libimap.a \ +- $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread ++ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread + + mupdate.pure: mupdate.o mupdate-slave.o mupdate-client.o mutex_pthread.o \ + libimap.a $(DEPLIBS) +@@ -228,118 +228,122 @@ + mutex_pthread.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) -lpthread + + pop3d: pop3d.o proxy.o backend.o tls.o mutex_fake.o libimap.a \ +- $(DEPLIBS) $(SERVICE) ++ $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) + $(CC) $(LDFLAGS) -o pop3d pop3d.o proxy.o backend.o tls.o $(SERVICE) \ +- mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) ++ mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + + nntpd: nntpd.o proxy.o backend.o index.o smtpclient.o spool.o tls.o \ +- mutex_fake.o nntp_err.o libimap.a $(DEPLIBS) $(SERVICE) ++ mutex_fake.o nntp_err.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(SERVICE) + $(CC) $(LDFLAGS) -o nntpd nntpd.o proxy.o backend.o index.o spool.o \ + smtpclient.o tls.o $(SERVICE) mutex_fake.o nntp_err.o \ +- libimap.a $(DEPLIBS) $(LIBS) $(LIB_WRAP) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + +-fud: fud.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) ++fud: fud.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o fud $(SERVICE) fud.o mutex_fake.o libimap.a \ +- $(DEPLIBS) $(LIBS) $(LIB_WRAP) ++ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + +-smmapd: smmapd.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) ++smmapd: smmapd.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o smmapd $(SERVICE) smmapd.o mutex_fake.o libimap.a \ +- $(DEPLIBS) $(LIBS) $(LIB_WRAP) ++ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + + sync_server: sync_server.o sync_support.o sync_commit.o \ +- imapparse.o tls.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) ++ imapparse.o tls.o libimap.a mutex_fake.o $(DEPLIBS) $(SERVICE) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ + sync_server sync_server.o sync_support.o sync_commit.o \ + imapparse.o tls.o $(SERVICE) libimap.a mutex_fake.o \ +- $(DEPLIBS) $(LIBS) $(LIB_WRAP) ++ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) $(LIB_WRAP) + + ### Command Line Utilities +-arbitron: arbitron.o $(CLIOBJS) libimap.a $(DEPLIBS) ++arbitron: arbitron.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o arbitron arbitron.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(DEPLIBS) ++cvt_cyrusdb: cvt_cyrusdb.o mutex_fake.o libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o cvt_cyrusdb cvt_cyrusdb.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(DEPLIBS) ++chk_cyrus: chk_cyrus.o mutex_fake.o libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o chk_cyrus chk_cyrus.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-deliver: deliver.o $(LMTPOBJS) proxy.o mutex_fake.o libimap.a $(DEPLIBS) ++deliver: deliver.o $(LMTPOBJS) proxy.o mutex_fake.o libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o deliver deliver.o $(LMTPOBJS) proxy.o \ +- mutex_fake.o libimap.a $(DEPLIBS) $(LIBS) ++ mutex_fake.o libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) ++ctl_deliver: ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ +- $@ ctl_deliver.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ $@ ctl_deliver.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(DEPLIBS) ++ctl_mboxlist: ctl_mboxlist.o mupdate-client.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o $@ ctl_mboxlist.o mupdate-client.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) ++ctl_cyrusdb: ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ +- $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ $@ ctl_cyrusdb.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(DEPLIBS) ++cyr_expire: cyr_expire.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o $@ cyr_expire.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) ++fetchnews: fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ +- $@ fetchnews.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ $@ fetchnews.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(DEPLIBS) ++squatter: squatter.o index.o squat_build.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o squatter squatter.o index.o squat_build.o \ +- $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-mbpath: mbpath.o $(CLIOBJS) libimap.a $(DEPLIBS) ++mbpath: mbpath.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o mbpath mbpath.o $(CLIOBJS) libimap.a \ +- $(DEPLIBS) $(LIBS) +- +-ipurge: ipurge.o $(CLIOBJS) libimap.a $(DEPLIBS) ++ $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) ++ ++ipurge: ipurge.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o ipurge ipurge.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(DEPLIBS) ++cyrdump: cyrdump.o index.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o cyrdump cyrdump.o index.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) ++mbexamine: mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ +- mbexamine mbexamine.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ mbexamine mbexamine.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) ++reconstruct: reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ +- reconstruct reconstruct.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ reconstruct reconstruct.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-quota: quota.o $(CLIOBJS) libimap.a $(DEPLIBS) ++quota: quota.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o quota quota.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) ++tls_prune: tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ +- $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(DEPLIBS) $(LIBS) ++ $@ tls_prune.o tls.o $(CLIOBJS) libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-unexpunge: unexpunge.o $(CLIOBJS) libimap.a $(DEPLIBS) ++unexpunge: unexpunge.o $(CLIOBJS) libimap.a $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o $@ unexpunge.o $(CLIOBJS) \ +- libimap.a $(DEPLIBS) $(LIBS) ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + +-make_md5: make_md5.o libimap.a mutex_fake.o $(DEPLIBS) +- $(CC) $(LDFLAGS) -o make_md5 make_md5.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS) ++make_md5: make_md5.o libimap.a mutex_fake.o $(DEPLIBS) $(SIEVE_LIBS) ++ $(CC) $(LDFLAGS) -o make_md5 make_md5.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + + sync_client: sync_client.o sync_support.o \ +- backend.o tls.o imapparse.o libimap.a mutex_fake.o $(DEPLIBS) ++ backend.o tls.o imapparse.o libimap.a mutex_fake.o $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ + sync_client sync_client.o sync_support.o \ +- backend.o tls.o imapparse.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS) ++ backend.o tls.o imapparse.o libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + + sync_reset: sync_reset.o sync_support.o sync_commit.o \ +- libimap.a mutex_fake.o $(DEPLIBS) ++ libimap.a mutex_fake.o $(DEPLIBS) $(SIEVE_LIBS) + $(CC) $(LDFLAGS) -o \ + sync_reset sync_reset.o sync_support.o sync_commit.o \ +- libimap.a mutex_fake.o $(DEPLIBS) $(LIBS) ++ libimap.a mutex_fake.o $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) ++ ++compile_sieve: compile_sieve.o libimap.a $(DEPLIBS) $(SIEVE_LIBS) ++ $(CC) $(LDFLAGS) -o compile_sieve compile_sieve.o $(CLIOBJS) \ ++ libimap.a $(SIEVE_LIBS) $(DEPLIBS) $(LIBS) + + ### Other Misc Targets + +diff -Naur cyrus-imapd-2.3.1/imap/autosieve.c cyrus-imapd-2.3.1-autocreate/imap/autosieve.c +--- cyrus-imapd-2.3.1/imap/autosieve.c 1970-01-01 02:00:00 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/autosieve.c 2006-01-19 03:53:41 +0200 +@@ -0,0 +1,587 @@ ++#include ++#include ++#include ++ ++#ifdef HAVE_UNISTD_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "global.h" ++#include "util.h" ++#include "mailbox.h" ++#include "imap_err.h" ++#include "sieve_interface.h" ++#include "script.h" ++ ++#define TIMSIEVE_FAIL -1 ++#define TIMSIEVE_OK 0 ++#define MAX_FILENAME 1024 ++ ++static int get_script_name(char *sievename, size_t buflen, const char *filename); ++static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir); ++int autoadd_sieve(char *userid, const char *source_script); ++ ++static void fatal(const char *s, int code); ++static void foo(void); ++static int sieve_notify(void *ac __attribute__((unused)), ++ void *interp_context __attribute__((unused)), ++ void *script_context __attribute__((unused)), ++ void *message_context __attribute__((unused)), ++ const char **errmsg __attribute__((unused))); ++static int mysieve_error(int lineno, const char *msg, ++ void *i __attribute__((unused)), void *s); ++static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret); ++ ++ ++sieve_vacation_t vacation2 = { ++ 0, /* min response */ ++ 0, /* max response */ ++ (sieve_callback *) &foo, /* autorespond() */ ++ (sieve_callback *) &foo /* send_response() */ ++}; ++ ++ ++/* ++ * Find the name of the sieve script ++ * given the source script and compiled script names ++ */ ++static int get_script_name(char *sievename, size_t buflen, const char *filename) ++{ ++ char *p; ++ int r; ++ ++ p = strrchr(filename, '/'); ++ if (p == NULL) ++ p = (char *) filename; ++ else ++ p++; ++ ++ r = strlcpy(sievename, p, buflen) - buflen; ++ return (r >= 0 || r == -buflen ? 1 : 0); ++} ++ ++ ++/* ++ * Find the directory where the sieve scripts of the user ++ * reside ++ */ ++static int get_script_dir(char *sieve_script_dir, size_t buflen, char *userid, const char *sieve_dir) ++{ ++ char *user = NULL, *domain = NULL; ++ ++ /* Setup the user and the domain */ ++ if(config_virtdomains && (domain = strchr(userid, '@'))) { ++ user = (char *) xmalloc((domain - userid +1) * sizeof(char)); ++ strlcpy(user, userid, domain - userid + 1); ++ domain++; ++ } else ++ user = userid; ++ ++ /* Find the dir path where the sieve scripts of the user will reside */ ++ if (config_virtdomains && domain) { ++ if(snprintf(sieve_script_dir, buflen, "%s%s%c/%s/%c/%s/", ++ sieve_dir, FNAME_DOMAINDIR, dir_hash_c(domain), domain, dir_hash_c(user), user) >= buflen) { ++ free(user); ++ return 1; ++ } ++ } else { ++ if(snprintf(sieve_script_dir, buflen, "%s/%c/%s/", ++ sieve_dir, dir_hash_c(user), user) >= buflen) ++ return 1; ++ } ++ ++ /* Free the xmalloced user memory, reserved above */ ++ if(user != userid) ++ free(user); ++ ++ return 0; ++} ++ ++int autoadd_sieve(char *userid, const char *source_script) ++{ ++ sieve_script_t *s = NULL; ++ bytecode_info_t *bc = NULL; ++ char *err = NULL; ++ FILE *in_stream, *out_fp; ++ int out_fd, in_fd, r, k; ++ int do_compile = 0; ++ const char *sieve_dir = NULL; ++ const char *compiled_source_script = NULL; ++ char sievename[MAX_FILENAME]; ++ char sieve_script_name[MAX_FILENAME]; ++ char sieve_script_dir[MAX_FILENAME]; ++ char sieve_bcscript_name[MAX_FILENAME]; ++ char sieve_default[MAX_FILENAME]; ++ char sieve_tmpname[MAX_FILENAME]; ++ char sieve_bctmpname[MAX_FILENAME]; ++ char sieve_bclink_name[MAX_FILENAME]; ++ char buf[4096]; ++ mode_t oldmask; ++ struct stat statbuf; ++ ++ /* We don't support using the homedirectory, like timsieved */ ++ if (config_getswitch(IMAPOPT_SIEVEUSEHOMEDIR)) { ++ syslog(LOG_WARNING,"autocreate_sieve: autocreate_sieve does not work with sieveusehomedir option in imapd.conf"); ++ return 1; ++ } ++ ++ /* Check if sievedir is defined in imapd.conf */ ++ if(!(sieve_dir = config_getstring(IMAPOPT_SIEVEDIR))) { ++ syslog(LOG_WARNING, "autocreate_sieve: sievedir option is not defined. Check imapd.conf"); ++ return 1; ++ } ++ ++ /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */ ++ if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { ++ syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it"); ++ do_compile = 1; ++ } ++ ++ if(get_script_dir(sieve_script_dir, sizeof(sieve_script_dir), userid, sieve_dir)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Cannot find sieve scripts directory"); ++ return 1; ++ } ++ ++ if (get_script_name(sievename, sizeof(sievename), source_script)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve script %s", source_script); ++ return 1; ++ } ++ ++ if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s%s.script.NEW",sieve_script_dir, sievename) >= sizeof(sieve_tmpname)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); ++ return 1; ++ } ++ if(snprintf(sieve_bctmpname, sizeof(sieve_bctmpname), "%s%s.bc.NEW",sieve_script_dir, sievename) >= sizeof(sieve_bctmpname)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); ++ return 1; ++ } ++ if(snprintf(sieve_script_name, sizeof(sieve_script_name), "%s%s.script",sieve_script_dir, sievename) >= sizeof(sieve_script_name)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); ++ return 1; ++ } ++ if(snprintf(sieve_bcscript_name, sizeof(sieve_bcscript_name), "%s%s.bc",sieve_script_dir, sievename) >= sizeof(sieve_bcscript_name)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); ++ return 1; ++ } ++ if(snprintf(sieve_default, sizeof(sieve_default), "%s%s",sieve_script_dir,"defaultbc") >= sizeof(sieve_default)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); ++ return 1; ++ } ++ if(snprintf(sieve_bclink_name, sizeof(sieve_bclink_name), "%s.bc", sievename) >= sizeof(sieve_bclink_name)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_dir, sievename, userid); ++ return 1; ++ } ++ ++ /* Check if a default sieve filter alrady exists */ ++ if(!stat(sieve_default,&statbuf)) { ++ syslog(LOG_WARNING,"autocreate_sieve: Default sieve script already exists"); ++ fclose(in_stream); ++ return 1; ++ } ++ ++ /* Open the source script. if there is a problem with that exit */ ++ in_stream = fopen(source_script, "r"); ++ if(!in_stream) { ++ syslog(LOG_WARNING,"autocreate_sieve: Unable to open sieve script %s. Check permissions",source_script); ++ return 1; ++ } ++ ++ ++ /* ++ * At this point we start the modifications of the filesystem ++ */ ++ ++ /* Create the directory where the sieve scripts will reside */ ++ r = cyrus_mkdir(sieve_script_dir, 0755); ++ if(r == -1) { ++ /* If this fails we just leave */ ++ syslog(LOG_WARNING,"autocreate_sieve: Unable to create directory %s. Check permissions",sieve_script_name); ++ return 1; ++ } ++ ++ /* ++ * We open the file that will be used as the bc file. If this file exists, overwrite it ++ * since something bad has happened. We open the file here so that this error checking is ++ * done before we try to open the rest of the files to start copying etc. ++ */ ++ out_fd = open(sieve_bctmpname, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); ++ if(out_fd < 0) { ++ if(errno == EEXIST) { ++ syslog(LOG_WARNING,"autocreate_sieve: File %s already exists. Probaly left over. Ignoring",sieve_bctmpname); ++ } else if (errno == EACCES) { ++ syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_bctmpname); ++ fclose(in_stream); ++ return 1; ++ } else { ++ syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s. Unknown error",sieve_bctmpname); ++ fclose(in_stream); ++ return 1; ++ } ++ } ++ ++ if(!do_compile && compiled_source_script && (in_fd = open(compiled_source_script, O_RDONLY)) != -1) { ++ while((r = read(in_fd, buf, sizeof(buf))) > 0) { ++ if((k=write(out_fd, buf,r)) < 0) { ++ syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_bctmpname, errno); ++ close(out_fd); ++ close(in_fd); ++ fclose(in_stream); ++ unlink(sieve_bctmpname); ++ return 1; ++ } ++ } ++ ++ if(r == 0) { /* EOF */ ++ close(out_fd); ++ close(in_fd); ++ } else if (r < 0) { ++ syslog(LOG_WARNING, "autocreate_sieve: Error reading compiled script file: %s. Will try to compile it", ++ compiled_source_script); ++ close(in_fd); ++ do_compile = 1; ++ if(lseek(out_fd, 0, SEEK_SET)) { ++ syslog(LOG_WARNING, "autocreate_sieve: Major IO problem. Aborting"); ++ return 1; ++ } ++ } ++ close(in_fd); ++ } else { ++ if(compiled_source_script) ++ syslog(LOG_WARNING,"autocreate_sieve: Problem opening compiled script file: %s. Compiling it", compiled_source_script); ++ do_compile = 1; ++ } ++ ++ ++ /* Because we failed to open a precompiled bc sieve script, we compile one */ ++ if(do_compile) { ++ if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { ++ if(err && *err) { ++ syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script %s.",err); ++ free(err); ++ } else ++ syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script"); ++ ++ unlink(sieve_bctmpname); ++ fclose(in_stream); ++ close(out_fd); ++ return 1; ++ } ++ ++ /* generate the bytecode */ ++ if(sieve_generate_bytecode(&bc, s) == TIMSIEVE_FAIL) { ++ syslog(LOG_WARNING,"autocreate_sieve: problem compiling sieve script"); ++ /* removing the copied script and cleaning up memory */ ++ unlink(sieve_bctmpname); ++ sieve_script_free(&s); ++ fclose(in_stream); ++ close(out_fd); ++ return 1; ++ } ++ ++ if(sieve_emit_bytecode(out_fd, bc) == TIMSIEVE_FAIL) { ++ syslog(LOG_WARNING,"autocreate_sieve: problem emiting sieve script"); ++ /* removing the copied script and cleaning up memory */ ++ unlink(sieve_bctmpname); ++ sieve_free_bytecode(&bc); ++ sieve_script_free(&s); ++ fclose(in_stream); ++ close(out_fd); ++ return 1; ++ } ++ ++ /* clean up the memory */ ++ sieve_free_bytecode(&bc); ++ sieve_script_free(&s); ++ } ++ ++ close(out_fd); ++ rewind(in_stream); ++ ++ /* Copy the initial script */ ++ oldmask = umask(077); ++ if((out_fp = fopen(sieve_tmpname, "w")) == NULL) { ++ syslog(LOG_WARNING,"autocreate_sieve: Unable to open %s destination sieve script", sieve_tmpname); ++ unlink(sieve_bctmpname); ++ umask(oldmask); ++ fclose(in_stream); ++ return 1; ++ } ++ umask(oldmask); ++ ++ while((r = fread(buf,sizeof(char), sizeof(buf), in_stream))) { ++ if( fwrite(buf,sizeof(char), r, out_fp) != r) { ++ syslog(LOG_WARNING,"autocreate_sieve: Problem writing to sieve script file: %s",sieve_tmpname); ++ fclose(out_fp); ++ unlink(sieve_tmpname); ++ unlink(sieve_bctmpname); ++ fclose(in_stream); ++ return 1; ++ } ++ } ++ ++ if(feof(in_stream)) { ++ fclose(out_fp); ++ } else { /* ferror */ ++ fclose(out_fp); ++ unlink(sieve_tmpname); ++ unlink(sieve_bctmpname); ++ fclose(in_stream); ++ return 1; ++ } ++ ++ /* Renaming the necessary stuff */ ++ if(rename(sieve_tmpname, sieve_script_name)) { ++ unlink(sieve_tmpname); ++ unlink(sieve_bctmpname); ++ return 1; ++ } ++ ++ if(rename(sieve_bctmpname, sieve_bcscript_name)) { ++ unlink(sieve_bctmpname); ++ unlink(sieve_bcscript_name); ++ return 1; ++ } ++ ++ /* end now with the symlink */ ++ if(symlink(sieve_bclink_name, sieve_default)) { ++ if(errno != EEXIST) { ++ syslog(LOG_WARNING, "autocreate_sieve: problem making the default link."); ++ /* Lets delete the files */ ++ unlink(sieve_script_name); ++ unlink(sieve_bcscript_name); ++ } ++ } ++ ++ /* ++ * If everything has succeeded AND we have compiled the script AND we have requested ++ * to generate the global script so that it is not compiled each time then we create it. ++ */ ++ if(do_compile && ++ config_getswitch(IMAPOPT_GENERATE_COMPILED_SIEVE_SCRIPT)) { ++ ++ if(!compiled_source_script) { ++ syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf"); ++ return 0; ++ } ++ ++ if(snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script) >= sizeof(sieve_tmpname)) ++ return 0; ++ ++ /* ++ * Copy everything from the newly created bc sieve sieve script. ++ */ ++ if((in_fd = open(sieve_bcscript_name, O_RDONLY))<0) { ++ return 0; ++ } ++ ++ if((out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { ++ if(errno == EEXIST) { ++ /* Someone is already doing this so just bail out. */ ++ syslog(LOG_WARNING, "autocreate_sieve: %s already exists. Some other instance processing it, or it is left over", sieve_tmpname); ++ close(in_fd); ++ return 0; ++ } else if (errno == EACCES) { ++ syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_tmpname); ++ close(in_fd); ++ return 0; ++ } else { ++ syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s",sieve_tmpname); ++ close(in_fd); ++ return 0; ++ } ++ } ++ ++ while((r = read(in_fd, buf, sizeof(buf))) > 0) { ++ if((k = write(out_fd,buf,r)) < 0) { ++ syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno); ++ close(out_fd); ++ close(in_fd); ++ unlink(sieve_tmpname); ++ return 0; ++ } ++ } ++ ++ if(r == 0 ) { /*EOF */ ++ close(out_fd); ++ close(in_fd); ++ } else if (r < 0) { ++ syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s, error: %d", sieve_tmpname, errno); ++ close(out_fd); ++ close(in_fd); ++ unlink(sieve_tmpname); ++ return 0; ++ } ++ ++ /* Rename the temporary created sieve script to its final name. */ ++ if(rename(sieve_tmpname, compiled_source_script)) { ++ if(errno != EEXIST) { ++ unlink(sieve_tmpname); ++ unlink(compiled_source_script); ++ } ++ return 0; ++ } ++ ++ syslog(LOG_NOTICE, "autocreate_sieve: Compiled sieve script was successfully saved in %s", compiled_source_script); ++ } ++ ++ return 0; ++} ++ ++static void fatal(const char *s, int code) ++{ ++ printf("Fatal error: %s (%d)\r\n", s, code); ++ exit(1); ++} ++ ++/* to make larry's stupid functions happy :) */ ++static void foo(void) ++{ ++ fatal("stub function called", 0); ++} ++ ++static int sieve_notify(void *ac __attribute__((unused)), ++ void *interp_context __attribute__((unused)), ++ void *script_context __attribute__((unused)), ++ void *message_context __attribute__((unused)), ++ const char **errmsg __attribute__((unused))) ++{ ++ fatal("stub function called", 0); ++ return SIEVE_FAIL; ++} ++ ++static int mysieve_error(int lineno, const char *msg, ++ void *i __attribute__((unused)), void *s) ++{ ++ char buf[1024]; ++ char **errstr = (char **) s; ++ ++ snprintf(buf, 80, "line %d: %s\r\n", lineno, msg); ++ *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30); ++ syslog(LOG_DEBUG, "%s", buf); ++ strcat(*errstr, buf); ++ ++ return SIEVE_OK; ++} ++ ++/* end the boilerplate */ ++ ++/* returns TRUE or FALSE */ ++int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret) ++{ ++ sieve_interp_t *i; ++ sieve_script_t *s; ++ int res; ++ ++ res = sieve_interp_alloc(&i, NULL); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_interp_alloc() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_redirect(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_redirect() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_discard(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_discard() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_reject(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_reject() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_fileinto(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_fileinto() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_keep(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_keep() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_imapflags(i, NULL); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_imapflags() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_size(i, (sieve_get_size *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_size() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_header(i, (sieve_get_header *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_header() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_envelope(i, (sieve_get_envelope *) &foo); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_envelope() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_vacation(i, &vacation2); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_vacation() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_notify(i, &sieve_notify); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_notify() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_parse_error(i, &mysieve_error); ++ if (res != SIEVE_OK) { ++ syslog(LOG_WARNING, "sieve_register_parse_error() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ rewind(stream); ++ ++ *errstr = (char *) xmalloc(20 * sizeof(char)); ++ strcpy(*errstr, "script errors:\r\n"); ++ ++ res = sieve_script_parse(i, stream, errstr, &s); ++ ++ if (res == SIEVE_OK) { ++ if(ret) { ++ *ret = s; ++ } else { ++ sieve_script_free(&s); ++ } ++ free(*errstr); ++ *errstr = NULL; ++ } ++ ++ /* free interpreter */ ++ sieve_interp_free(&i); ++ ++ return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL; ++} ++ ++/* ++ * Btw the initial date of this patch is Sep, 02 2004 which is the birthday of ++ * Pavlos. Author of cyrusmaster. So consider this patch as his birthday present ++ */ ++ +diff -Naur cyrus-imapd-2.3.1/imap/compile_sieve.c cyrus-imapd-2.3.1-autocreate/imap/compile_sieve.c +--- cyrus-imapd-2.3.1/imap/compile_sieve.c 1970-01-01 02:00:00 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/compile_sieve.c 2006-01-19 03:53:41 +0200 +@@ -0,0 +1,364 @@ ++/* This tool compiles the sieve script from a command ++line so that it can be used wby the autoadd patch */ ++#include ++#include ++ ++#include ++#include ++#ifdef HAVE_UNISTD_H ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "global.h" ++ ++#include "util.h" ++#include "mailbox.h" ++#include "imap_err.h" ++#include "sieve_interface.h" ++#include "script.h" ++ ++#include ++ ++#define TIMSIEVE_FAIL -1 ++#define TIMSIEVE_OK 0 ++#define MAX_FILENAME_SIZE 100 ++ ++/* Needed by libconfig */ ++const int config_need_data = 0; ++ ++static int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret); ++ ++static void fatal(const char *s, int code) ++{ ++ printf("Fatal error: %s (%d)\r\n", s, code); ++ ++ exit(1); ++} ++ ++void usage(void) ++{ ++ fprintf(stderr, ++ "Usage:\n\tcompile_sieve [-C ] [-i -o ]\n"); ++ exit(-1); ++} ++ ++ ++int main (int argc, char **argv) ++{ ++ ++ sieve_script_t *s = NULL; ++ bytecode_info_t *bc = NULL; ++ char *err = NULL; ++ FILE *in_stream; ++ int out_fd,r, k, opt; ++ char *source_script = NULL; ++ char *compiled_source_script = NULL; ++ mode_t oldmask; ++ struct stat statbuf; ++ char *alt_config = NULL; ++ extern char *optarg; ++ char sieve_tmpname[MAX_MAILBOX_NAME+1]; ++ ++ if (geteuid() == 0) fatal("must run as the Cyrus user", EC_USAGE); ++ ++ while((opt = getopt(argc, argv, "C:i:o:")) != EOF) { ++ switch (opt) { ++ case 'C': /* alt config file */ ++ alt_config = optarg; ++ break; ++ case 'i': /* input script file */ ++ source_script = optarg; ++ break; ++ case 'o': /* output script file */ ++ compiled_source_script = optarg; ++ break; ++ default: ++ usage(); ++ break; ++ } ++ } ++ ++ if(source_script && !compiled_source_script) { ++ fprintf(stderr, "No output file was defined\n"); ++ usage(); ++ } else if (!source_script && compiled_source_script) { ++ fprintf(stderr, "No input file was defined\n"); ++ usage(); ++ } ++ ++ /* ++ * If no has been defined, then read them from ++ * the configuration file. ++ */ ++ if (!source_script && !compiled_source_script) { ++ cyrus_init(alt_config, "compile_sieve", 0); ++ ++ /* Initially check if we want to have the sieve script created */ ++ if(!(source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT))) { ++ fprintf(stderr,"autocreate_sieve_script option not defined. Check imapd.conf\n"); ++ return 1; ++ } ++ ++ /* Check if we have an already compiled sieve script*/ ++ if(!(compiled_source_script = (char *) config_getstring(IMAPOPT_AUTOCREATE_SIEVE_COMPILEDSCRIPT))) { ++ fprintf(stderr, "autocreate_sieve_compiledscript option not defined. Check imapd.conf\n"); ++ return 1; ++ } ++ ++ if(!strrchr(source_script,'/') || !strrchr(compiled_source_script,'/')) { ++ /* ++ * At this point the only think that is inconsistent is the directory ++ * that was created. But if the user will have any sieve scripts then ++ * they will eventually go there, so no big deal ++ */ ++ fprintf(stderr, ++ "In imapd.conf the full path of the filenames must be defined\n"); ++ return 1; ++ } ++ } ++ ++ printf("input file : %s, output file : %s\n", source_script, compiled_source_script); ++ ++ ++ if(strlen(compiled_source_script) + sizeof(".NEW") + 1 > sizeof(sieve_tmpname)) { ++ fprintf(stderr, "Filename %s is too big\n", compiled_source_script); ++ return 1; ++ } ++ ++ snprintf(sieve_tmpname, sizeof(sieve_tmpname), "%s.NEW", compiled_source_script); ++ ++ in_stream = fopen(source_script,"r"); ++ ++ if(!in_stream) { ++ fprintf(stderr,"Unable to open %s source sieve script\n",source_script); ++ return; ++ } ++ ++ /* ++ * We open the file that will be used as the bc file. If this file exists, overwrite it ++ * since something bad has happened. We open the file here so that this error checking is ++ * done before we try to open the rest of the files to start copying etc. ++ */ ++ out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); ++ if(out_fd < 0) { ++ if(errno == EEXIST) { ++ fprintf(stderr, "File %s already exists\n", sieve_tmpname); ++ } else if (errno == EACCES) { ++ fprintf(stderr,"No access to create file %s. Please check that you have the correct permissions\n", ++ sieve_tmpname); ++ } else { ++ fprintf(stderr,"Unable to create %s. Please check that you have the correct permissions\n", ++ sieve_tmpname); ++ } ++ ++ fclose(in_stream); ++ return 1; ++ } ++ ++ if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { ++ if(err && *err) { ++ fprintf(stderr, "Error while parsing script %s\n",err); ++ free(err); ++ } ++ else ++ fprintf(stderr,"Error while parsing script\n"); ++ unlink(sieve_tmpname); ++ fclose(in_stream); ++ close(out_fd); ++ return; ++ } ++ ++ ++ /* generate the bytecode */ ++ if(sieve_generate_bytecode(&bc,s) == TIMSIEVE_FAIL) { ++ fprintf(stderr,"Error occured while compiling sieve script\n"); ++ /* removing the copied script and cleaning up memory */ ++ unlink(sieve_tmpname); ++ sieve_script_free(&s); ++ fclose(in_stream); ++ close(out_fd); ++ return; ++ } ++ if(sieve_emit_bytecode(out_fd,bc) == TIMSIEVE_FAIL) { ++ fprintf(stderr, "Error occured while emitting sieve script\n"); ++ unlink(sieve_tmpname); ++ sieve_free_bytecode(&bc); ++ sieve_script_free(&s); ++ fclose(in_stream); ++ close(out_fd); ++ return; ++ } ++ ++ /* clean up the memory */ ++ sieve_free_bytecode(&bc); ++ sieve_script_free(&s); ++ ++ close(out_fd); ++ ++ if(rename(sieve_tmpname, compiled_source_script)) { ++ if(errno != EEXIST) { ++ unlink(sieve_tmpname); ++ unlink(compiled_source_script); ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++ ++/* to make larry's stupid functions happy :) */ ++static void foo(void) ++{ ++ fatal("stub function called", 0); ++} ++ ++extern sieve_vacation_t vacation2;/* = { ++ 0, / min response / ++ 0, / max response / ++ (sieve_callback *) &foo, / autorespond() / ++ (sieve_callback *) &foo / send_response() / ++}; */ ++ ++static int sieve_notify(void *ac __attribute__((unused)), ++ void *interp_context __attribute__((unused)), ++ void *script_context __attribute__((unused)), ++ void *message_context __attribute__((unused)), ++ const char **errmsg __attribute__((unused))) ++{ ++ fatal("stub function called", 0); ++ return SIEVE_FAIL; ++} ++ ++static int mysieve_error(int lineno, const char *msg, ++ void *i __attribute__((unused)), void *s) ++{ ++ char buf[1024]; ++ char **errstr = (char **) s; ++ ++ snprintf(buf, 80, "line %d: %s\r\n", lineno, msg); ++ *errstr = (char *) xrealloc(*errstr, strlen(*errstr) + strlen(buf) + 30); ++ fprintf(stderr, "%s\n", buf); ++ strcat(*errstr, buf); ++ ++ return SIEVE_OK; ++} ++ ++/* end the boilerplate */ ++ ++/* returns TRUE or FALSE */ ++int is_script_parsable(FILE *stream, char **errstr, sieve_script_t **ret) ++{ ++ sieve_interp_t *i; ++ sieve_script_t *s; ++ int res; ++ ++ res = sieve_interp_alloc(&i, NULL); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_interp_alloc() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_redirect(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_redirect() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_discard(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_discard() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_reject(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_reject() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_fileinto(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_fileinto() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ res = sieve_register_keep(i, (sieve_callback *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_keep() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_imapflags(i, NULL); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_imapflags() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_size(i, (sieve_get_size *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_size() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_header(i, (sieve_get_header *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_header() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_envelope(i, (sieve_get_envelope *) &foo); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_envelope() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_vacation(i, &vacation2); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_vacation() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_notify(i, &sieve_notify); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_notify() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ res = sieve_register_parse_error(i, &mysieve_error); ++ if (res != SIEVE_OK) { ++ fprintf(stderr, "sieve_register_parse_error() returns %d\n", res); ++ return TIMSIEVE_FAIL; ++ } ++ ++ rewind(stream); ++ ++ *errstr = (char *) xmalloc(20 * sizeof(char)); ++ strcpy(*errstr, "script errors:\r\n"); ++ ++ res = sieve_script_parse(i, stream, errstr, &s); ++ ++ if (res == SIEVE_OK) { ++ if(ret) { ++ *ret = s; ++ } else { ++ sieve_script_free(&s); ++ } ++ free(*errstr); ++ *errstr = NULL; ++ } ++ ++ /* free interpreter */ ++ sieve_interp_free(&i); ++ ++ return (res == SIEVE_OK) ? TIMSIEVE_OK : TIMSIEVE_FAIL; ++} ++ ++ ++ ++ ++ ++ +diff -Naur cyrus-imapd-2.3.1/imap/imapd.c cyrus-imapd-2.3.1-autocreate/imap/imapd.c +--- cyrus-imapd-2.3.1/imap/imapd.c 2005-12-13 21:35:50 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/imapd.c 2006-01-19 03:53:41 +0200 +@@ -193,6 +193,7 @@ + void motd_file(int fd); + void shut_down(int code); + void fatal(const char *s, int code); ++void autocreate_inbox(void); + + void cmdloop(void); + void cmd_login(char *tag, char *user); +@@ -1889,6 +1890,43 @@ + } + + /* ++ * Autocreate Inbox and subfolders upon login ++ */ ++void autocreate_inbox() ++{ ++ char inboxname[MAX_MAILBOX_NAME+1]; ++ int autocreatequota; ++ int r; ++ ++ /* ++ * Exlude admin's accounts ++ */ ++ if (imapd_userisadmin || imapd_userisproxyadmin) ++ return; ++ ++ /* ++ * Exclude anonymous ++ */ ++ if (!strcmp(imapd_userid, "anonymous")) ++ return; ++ ++ if ((autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) { ++ /* This is actyally not required ++ as long as the lenght of userid is ok */ ++ r = (*imapd_namespace.mboxname_tointernal) (&imapd_namespace, ++ "INBOX", imapd_userid, inboxname); ++ if (!r) ++ r = mboxlist_lookup(inboxname, NULL, NULL); ++ ++ if (r == IMAP_MAILBOX_NONEXISTENT) { ++ mboxlist_autocreateinbox(&imapd_namespace, imapd_userid, ++ imapd_authstate, inboxname, autocreatequota); ++ } ++ } ++} ++ ++ ++/* + * Perform a LOGIN command + */ + void cmd_login(char *tag, char *user) +@@ -2047,6 +2085,9 @@ + strcspn(imapd_userid, "@") : 0); + + freebuf(&passwdbuf); ++ ++ autocreate_inbox(); ++ + return; + } + +@@ -2195,6 +2236,8 @@ + config_virtdomains ? + strcspn(imapd_userid, "@") : 0); + ++ autocreate_inbox(); ++ + return; + } + +diff -Naur cyrus-imapd-2.3.1/imap/lmtpd.c cyrus-imapd-2.3.1-autocreate/imap/lmtpd.c +--- cyrus-imapd-2.3.1/imap/lmtpd.c 2005-12-13 01:10:59 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/lmtpd.c 2006-01-19 03:53:41 +0200 +@@ -114,6 +114,8 @@ + static FILE *spoolfile(message_data_t *msgdata); + static void removespool(message_data_t *msgdata); + ++static int autocreate_inbox(const char *user, const char *domain); ++ + /* current namespace */ + static struct namespace lmtpd_namespace; + +@@ -924,6 +926,86 @@ + exit(code); + } + ++ ++/* ++ * Autocreate Inbox and subfolders upon login ++ */ ++int autocreate_inbox(const char *user, const char *domain) ++{ ++ struct auth_state *auth_state; ++ char inboxname[MAX_MAILBOX_NAME+1]; ++ char *rcpt_userid = NULL; ++ int autocreatequota; ++ int r = 0; ++ ++ if (user == NULL) ++ return IMAP_MAILBOX_NONEXISTENT; ++ ++ if (domain != NULL) { ++ int k; ++ ++ rcpt_userid = (char *) xmalloc((strlen(user) + strlen(domain) + 2) * sizeof(char)); ++ k = strlcpy(rcpt_userid, user, strlen(user) + 1); ++ *(rcpt_userid + k) = '@'; ++ strlcpy(rcpt_userid + k + 1, domain, strlen(domain) + 1); ++ } else { ++ rcpt_userid = (char *) user; ++ } ++ ++ ++ /* ++ * Exclude anonymous ++ */ ++ if (!strcmp(rcpt_userid, "anonymous")) { ++ if (rcpt_userid != user) { ++ free(rcpt_userid); ++ } ++ ++ return IMAP_MAILBOX_NONEXISTENT; ++ } ++ ++ /* ++ * Check for autocreatequota and createonpost ++ */ ++ if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA)) || ++ !(config_getswitch(IMAPOPT_CREATEONPOST))) { ++ ++ if (rcpt_userid != user) { ++ free(rcpt_userid); ++ } ++ ++ return IMAP_MAILBOX_NONEXISTENT; ++ } ++ ++ ++ /* ++ * Exclude admin's accounts ++ */ ++ auth_state = auth_newstate(rcpt_userid); ++ ++ if (global_authisa(auth_state, IMAPOPT_ADMINS)) { ++ if (rcpt_userid != user) { ++ free(rcpt_userid); ++ } ++ ++ return IMAP_MAILBOX_NONEXISTENT; ++ } ++ ++ r = (*lmtpd_namespace.mboxname_tointernal) (&lmtpd_namespace, ++ "INBOX", rcpt_userid, inboxname); ++ ++ if (!r) ++ r = mboxlist_autocreateinbox(&lmtpd_namespace, rcpt_userid, ++ auth_state, inboxname, autocreatequota); ++ ++ if (rcpt_userid != user) { ++ free(rcpt_userid); ++ } ++ ++ return r; ++} ++ ++ + static int verify_user(const char *user, const char *domain, char *mailbox, + long quotacheck, struct auth_state *authstate) + { +@@ -967,6 +1049,15 @@ + */ + r = mlookup(namebuf, &server, &acl, NULL); + ++ /* If user mailbox does not exist, then invoke autocreate inbox function */ ++ if (r == IMAP_MAILBOX_NONEXISTENT) { ++ r = autocreate_inbox(user, domain); ++ ++ /* Try to locate the mailbox again */ ++ if (!r) ++ r = mlookup(namebuf, &server, &acl, NULL); ++ } ++ + if (r == IMAP_MAILBOX_NONEXISTENT && !user && + config_getswitch(IMAPOPT_LMTP_FUZZY_MAILBOX_MATCH) && + /* see if we have a mailbox whose name is close */ +@@ -993,6 +1084,7 @@ + aclcheck, (quotacheck < 0) + || config_getswitch(IMAPOPT_LMTP_STRICT_QUOTA) ? + quotacheck : 0); ++ + } + } + +diff -Naur cyrus-imapd-2.3.1/imap/mboxlist.c cyrus-imapd-2.3.1-autocreate/imap/mboxlist.c +--- cyrus-imapd-2.3.1/imap/mboxlist.c 2005-12-13 21:36:03 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/mboxlist.c 2006-01-19 03:53:41 +0200 +@@ -81,6 +81,12 @@ + #include "mboxlist.h" + #include "quota.h" + ++#ifdef USE_SIEVE ++extern int autoadd_sieve(char *userid, ++ const char *source_script); ++#endif ++ ++ + #define DB config_mboxlist_db + #define SUBDB config_subscription_db + +@@ -98,11 +104,29 @@ + static int mboxlist_changequota(const char *name, int matchlen, int maycreate, + void *rock); + ++static int mboxlist_autochangesub(char *name, int matchlen, int maycreate, ++ void *rock); ++ ++static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace, ++ char *userid, char *auth_userid, ++ struct auth_state *auth_state); ++ + struct change_rock { + struct quota *quota; + struct txn **tid; + }; + ++/* ++ * Struct needed to be passed as void *rock to ++ * mboxlist_autochangesub(); ++ */ ++struct changesub_rock_st { ++ char *userid; ++ char *auth_userid; ++ struct auth_state *auth_state; ++}; ++ ++ + #define FNAME_SUBSSUFFIX ".sub" + + /* +@@ -3245,3 +3269,349 @@ + + return DB->abort(mbdb, tid); + } ++ ++/* ++ * Automatically subscribe user to *ALL* shared folders, ++ * one has permissions to be subscribed to. ++ * INBOX subfolders are excluded. ++ */ ++static int mboxlist_autochangesub(char *name, int matchlen, int maycreate, ++ void *rock) { ++ ++ struct changesub_rock_st *changesub_rock = (struct changesub_rock_st *) rock; ++ char *userid = changesub_rock->userid; ++ char *auth_userid = changesub_rock->auth_userid; ++ struct auth_state *auth_state = changesub_rock->auth_state; ++ int r; ++ ++ ++ if((strlen(name) == 5 && !strncmp(name, "INBOX", 5)) || /* Exclude INBOX */ ++ (strlen(name) > 5 && !strncmp(name, "INBOX.",6)) || /* Exclude INBOX subfolders */ ++ (strlen(name) > 4 && !strncmp(name, "user.", 5))) /* Exclude other users' folders */ ++ return 0; ++ ++ ++ r = mboxlist_changesub(name, userid, auth_state, 1, 0); ++ ++ if (r) { ++ syslog(LOG_WARNING, ++ "autosubscribe: User %s to folder %s, subscription failed: %s", ++ auth_userid, name, error_message(r)); ++ } else { ++ syslog(LOG_NOTICE, ++ "autosubscribe: User %s to folder %s, subscription succeeded", ++ auth_userid, name); ++ } ++ ++ return 0; ++} ++ ++#define SEP '|' ++ ++/* ++ * Automatically subscribe user to a shared folder. ++ * Subscription is done successfully, if the shared ++ * folder exists and the user has the necessary ++ * permissions. ++ */ ++static int mboxlist_autosubscribe_sharedfolders(struct namespace *namespace, ++ char *userid, char *auth_userid, ++ struct auth_state *auth_state) { ++ ++ const char *sub ; ++ char *p, *q, *next_sub; ++ char folder[MAX_MAILBOX_NAME+1], name[MAX_MAILBOX_NAME+1], mailboxname[MAX_MAILBOX_NAME+1]; ++ int len; ++ int r = 0; ++ int subscribe_all_sharedfolders = 0; ++ ++ subscribe_all_sharedfolders = config_getswitch(IMAPOPT_AUTOSUBSCRIBE_ALL_SHAREDFOLDERS); ++ ++ /* ++ * If subscribeallsharedfolders is set to yes in imapd.conf, then ++ * subscribe user to every shared folder one has the apropriate ++ * permissions. ++ */ ++ if(subscribe_all_sharedfolders) { ++ char pattern[MAX_MAILBOX_PATH+1]; ++ struct changesub_rock_st changesub_rock; ++ ++ strcpy(pattern, "*"); ++ changesub_rock.userid = userid; ++ changesub_rock.auth_userid = auth_userid; ++ changesub_rock.auth_state = auth_state; ++ ++ r = mboxlist_findall(namespace, pattern, 0, userid, ++ auth_state, mboxlist_autochangesub, &changesub_rock); ++ ++ return r; ++ } ++ ++ if ((sub=config_getstring(IMAPOPT_AUTOSUBSCRIBESHAREDFOLDERS)) == NULL) ++ return r; ++ ++ next_sub = (char *) sub; ++ while (*next_sub) { ++ for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++); ++ for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++); ++ for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--); ++ if (!*p ) continue; ++ ++ len = q - p + 1; ++ /* Check for folder length */ ++ if (len > sizeof(folder)-1) ++ continue; ++ ++ if (!r) { ++ strncpy(folder, p, len); ++ folder[len] = '\0'; ++ ++ strlcpy(name, namespace->prefix[NAMESPACE_SHARED], sizeof(name)); ++ len = strlcat(name, folder, sizeof(name)); ++ ++ r = (namespace->mboxname_tointernal) (namespace, name, userid, ++ mailboxname); ++ } ++ ++ if (!r) ++ r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 0); ++ ++ if (!r) { ++ syslog(LOG_NOTICE, "autosubscribe: User %s to %s succeeded", ++ userid, folder); ++ } else { ++ syslog(LOG_WARNING, "autosubscribe: User %s to %s failed: %s", ++ userid, folder, error_message(r)); ++ r = 0; ++ } ++ } ++ ++ return r; ++} ++ ++ ++ ++int mboxlist_autocreateinbox(struct namespace *namespace, ++ char *userid, ++ struct auth_state *auth_state, ++ char *mailboxname, int autocreatequota) { ++ char name [MAX_MAILBOX_NAME+1]; ++ char folder [MAX_MAILBOX_NAME+1]; ++ char *auth_userid = NULL; ++ char *partition = NULL; ++ const char *crt; ++ const char *sub; ++ char *p, *q, *next_crt, *next_sub; ++ int len; ++ int r = 0; ++ int numcrt = 0; ++ int numsub = 0; ++#ifdef USE_SIEVE ++ const char *source_script; ++#endif ++ ++ ++ ++ auth_userid = auth_canonuser(auth_state); ++ if (auth_userid == NULL) { ++ /* ++ * Couldn't get cannon userid ++ */ ++ syslog(LOG_ERR, ++ "autocreateinbox: Could not get canonified userid for user %s", userid); ++ return IMAP_PARTITION_UNKNOWN; ++ } ++ ++ /* Added this for debug information. */ ++ syslog(LOG_DEBUG, "autocreateinbox: autocreate inbox for user %s was called", auth_userid); ++ ++ /* ++ * While this is not needed for admins ++ * and imap_admins accounts, it would be ++ * better to separate *all* admins and ++ * proxyservers from normal accounts ++ * (accounts that have mailboxes). ++ * UOA Specific note(1): Even if we do not ++ * exclude these servers-classes here, ++ * UOA specific code, will neither return ++ * role, nor create INBOX, because none of these ++ * administrative accounts belong to the ++ * mailRecipient objectclass, or have imapPartition. ++ * UOA Specific note(2): Another good reason for doing ++ * this, is to prevent the code, from getting into ++ * cyrus_ldap.c because of the continues MSA logins to LMTPd. ++ */ ++ ++ /* ++ * admins and the coresponding imap ++ * service, had already been excluded. ++ */ ++ ++ /* ++ * Do we really need group membership ++ * for admins or service_admins? ++ */ ++ if (global_authisa(auth_state, IMAPOPT_ADMINS)) return 0; ++ ++ /* ++ * Do we really need group membership ++ * for proxyservers? ++ */ ++ if (global_authisa(auth_state, IMAPOPT_PROXYSERVERS)) return 0; ++ ++ /* ++ * Check if user belongs to the autocreate_users group. This option ++ * controls for whom the mailbox may be automatically created. Default ++ * value for this option is 'anyone'. So, if not declared, all mailboxes ++ * will be created. ++ */ ++ if (!global_authisa(auth_state, IMAPOPT_AUTOCREATE_USERS)) { ++ syslog(LOG_DEBUG, "autocreateinbox: User %s does not belong to the autocreate_users. No mailbox is created", ++ auth_userid); ++ return IMAP_MAILBOX_NONEXISTENT; ++ } ++ ++#if 0 ++ /* ++ * Get Partition info or return. ++ * (Here you should propably use ++ * you own "get_partition(char *userid)" ++ * function. Otherwise all new INBOXes will be ++ * created into whatever partition has been declared ++ * as default in your imapd.conf) ++ */ ++ ++ partition = get_partition(userid); ++ if (partition == NULL) { ++ /* ++ * Couldn't get partition info ++ */ ++ syslog(LOG_ERR, ++ "Could not get imapPartition info for user %s", userid); ++ return IMAP_PARTITION_UNKNOWN; ++ } ++#endif ++ ++ r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL, ++ 1, userid, auth_state, 0, 0, 0); ++ ++ if (!r && autocreatequota > 0) ++ r = mboxlist_setquota(mailboxname, autocreatequota, 0); ++ ++ if (!r) ++ r = mboxlist_changesub(mailboxname, userid, ++ auth_state, 1, 1); ++ ++ if (!r) { ++ syslog(LOG_NOTICE, "autocreateinbox: User %s, INBOX was successfully created in partition %s", ++ auth_userid, partition == NULL ? "default" : partition); ++ } else { ++ syslog(LOG_ERR, "autocreateinbox: User %s, INBOX failed. %s", ++ auth_userid, error_message(r)); ++ } ++ ++#if 0 ++ /* Allocated from get_partition, and not needed any more */ ++ free_partition(partition); ++#endif ++ ++ if (r) return r; ++ ++ /* INBOX's subfolders */ ++ if ((crt=config_getstring(IMAPOPT_AUTOCREATEINBOXFOLDERS))) ++ sub=config_getstring(IMAPOPT_AUTOSUBSCRIBEINBOXFOLDERS); ++ ++ /* Roll through crt */ ++ next_crt = (char *) crt; ++ while (next_crt!=NULL && *next_crt) { ++ for (p = next_crt ; isspace((int) *p) || *p == SEP ; p++); ++ for (next_crt = p ; *next_crt && *next_crt != SEP ; next_crt++); ++ for (q = next_crt ; q > p && (isspace((int) *q) || *q == SEP || !*q); q--); ++ ++ if (!*p) continue; ++ ++ len = q - p + 1; ++ ++ /* First time we check for length */ ++ if (len > sizeof(folder) - 5) ++ r = IMAP_MAILBOX_BADNAME; ++ ++ if (!r) { ++ strncpy(folder, p, len); ++ folder[len] = '\0'; ++ ++ strlcpy(name, namespace->prefix[NAMESPACE_INBOX], sizeof(name)); ++ len = strlcat(name, folder, sizeof(name)); ++ } ++ ++ if (!r) ++ r = (namespace->mboxname_tointernal) (namespace, name, userid, ++ mailboxname); ++ if (!r) ++ r = mboxlist_createmailbox(mailboxname, MAILBOX_FORMAT_NORMAL, NULL, ++ 1, userid, auth_state, 0, 0, 0); ++ ++ if (!r) { ++ numcrt++; ++ syslog(LOG_NOTICE, "autocreateinbox: User %s, subfolder %s creation succeeded.", ++ auth_userid, name); ++ } else { ++ syslog(LOG_WARNING, "autocreateinbox: User %s, subfolder %s creation failed. %s", ++ auth_userid, name, error_message(r)); ++ r=0; ++ continue; ++ } ++ ++ /* Roll through sub */ ++ next_sub = (char *) sub; ++ while (next_sub!=NULL && *next_sub) { ++ for (p = next_sub ; isspace((int) *p) || *p == SEP ; p++); ++ for (next_sub = p ; *next_sub && *next_sub != SEP ; next_sub++); ++ for (q = next_sub ; q > p && (isspace((int) *q) || *q == SEP || !*q) ; q--); ++ if (!*p ) continue; ++ ++ len = q - p + 1; ++ ++ if (len != strlen(folder) || strncmp(folder, p, len)) ++ continue; ++ ++ r = mboxlist_changesub(mailboxname, userid, auth_state, 1, 1); ++ ++ if (!r) { ++ numsub++; ++ syslog(LOG_NOTICE,"autocreateinbox: User %s, subscription to %s succeeded", ++ auth_userid, name); ++ } else ++ syslog(LOG_WARNING, "autocreateinbox: User %s, subscription to %s failed. %s", ++ auth_userid, name, error_message(r)); ++ ++ break; ++ } ++ } ++ ++ if (crt!=NULL && *crt) ++ syslog(LOG_INFO, "User %s, Inbox subfolders, created %d, subscribed %d", ++ auth_userid, numcrt, numsub); ++ ++ /* ++ * Check if shared folders are available for subscription. ++ */ ++ mboxlist_autosubscribe_sharedfolders(namespace, userid, auth_userid, auth_state); ++ ++#ifdef USE_SIEVE ++ /* ++ * Here the autocreate sieve script feature is iniated from. ++ */ ++ source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT); ++ ++ if (source_script) { ++ if (!autoadd_sieve(userid, source_script)) ++ syslog(LOG_NOTICE, "autocreate_sieve: User %s, default sieve script creation succeeded", auth_userid); ++ else ++ syslog(LOG_WARNING, "autocreate_sieve: User %s, default sieve script creation failed", auth_userid); ++ } ++#endif ++ ++ return r; ++} ++ +diff -Naur cyrus-imapd-2.3.1/imap/mboxlist.h cyrus-imapd-2.3.1-autocreate/imap/mboxlist.h +--- cyrus-imapd-2.3.1/imap/mboxlist.h 2005-02-21 21:25:40 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/mboxlist.h 2006-01-19 03:53:41 +0200 +@@ -203,4 +203,10 @@ + int mboxlist_commit(struct txn *tid); + int mboxlist_abort(struct txn *tid); + ++int mboxlist_autocreateinbox(struct namespace *namespace, ++ char *userid, ++ struct auth_state *auth_state, ++ char *mailboxname, int autocreatequota); ++ ++ + #endif +diff -Naur cyrus-imapd-2.3.1/imap/pop3d.c cyrus-imapd-2.3.1-autocreate/imap/pop3d.c +--- cyrus-imapd-2.3.1/imap/pop3d.c 2005-12-13 21:36:08 +0200 ++++ cyrus-imapd-2.3.1-autocreate/imap/pop3d.c 2006-01-19 03:53:41 +0200 +@@ -155,6 +155,8 @@ + static char popd_apop_chal[45 + MAXHOSTNAMELEN + 1]; /* */ + static void cmd_apop(char *response); + ++static int autocreate_inbox(char *inboxname, char *userid); ++ + static void cmd_auth(char *arg); + static void cmd_capa(void); + static void cmd_pass(char *pass); +@@ -1206,6 +1208,7 @@ + popd_userid = xstrdup(userbuf); + prot_printf(popd_out, "+OK Name is a valid mailbox\r\n"); + } ++ + } + + void cmd_pass(char *pass) +@@ -1477,6 +1480,43 @@ + } + + /* ++ * Autocreate Inbox and subfolders upon login ++ */ ++int autocreate_inbox(char *inboxname, char *auth_userid) ++{ ++ struct auth_state *auth_state; ++ int autocreatequota; ++ int r; ++ ++ if (inboxname == NULL || auth_userid == NULL) ++ return IMAP_MAILBOX_NONEXISTENT; ++ ++ /* ++ * Exclude anonymous ++ */ ++ if (!strcmp(popd_userid, "anonymous")) ++ return IMAP_MAILBOX_NONEXISTENT; ++ ++ /* ++ * Check for autocreatequota ++ */ ++ if (!(autocreatequota = config_getint(IMAPOPT_AUTOCREATEQUOTA))) ++ return IMAP_MAILBOX_NONEXISTENT; ++ ++ /* ++ * Exclude admin's accounts ++ */ ++ auth_state = auth_newstate(popd_userid); ++ if (global_authisa(auth_state, IMAPOPT_ADMINS)) ++ return IMAP_MAILBOX_NONEXISTENT; ++ ++ r = mboxlist_autocreateinbox(&popd_namespace, auth_userid, ++ auth_state, inboxname, autocreatequota); ++ return r; ++} ++ ++ ++/* + * Complete the login process by opening and locking the user's inbox + */ + int openinbox(void) +@@ -1505,6 +1545,12 @@ + + if (!r) r = mboxlist_detail(inboxname, &type, NULL, NULL, + &server, &acl, NULL); ++ ++ /* Try once again after autocreate_inbox */ ++ if (r == IMAP_MAILBOX_NONEXISTENT && !(r = autocreate_inbox(inboxname, userid))) ++ r = mboxlist_detail(inboxname, &type, NULL, NULL, ++ &server, &acl, NULL); ++ + if (!r && (config_popuseacl = config_getswitch(IMAPOPT_POPUSEACL)) && + (!acl || + !((myrights = cyrus_acl_myrights(popd_authstate, acl)) & ACL_READ))) { +diff -Naur cyrus-imapd-2.3.1/lib/auth.c cyrus-imapd-2.3.1-autocreate/lib/auth.c +--- cyrus-imapd-2.3.1/lib/auth.c 2005-02-16 23:06:50 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/auth.c 2006-01-19 03:53:42 +0200 +@@ -117,3 +117,11 @@ + + auth->freestate(auth_state); + } ++ ++char *auth_canonuser(struct auth_state *auth_state) ++{ ++ struct auth_mech *auth = auth_fromname(); ++ ++ return auth->auth_canonuser(auth_state); ++} ++ +diff -Naur cyrus-imapd-2.3.1/lib/auth.h cyrus-imapd-2.3.1-autocreate/lib/auth.h +--- cyrus-imapd-2.3.1/lib/auth.h 2005-02-16 23:06:50 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/auth.h 2006-01-19 03:53:42 +0200 +@@ -54,6 +54,7 @@ + const char *identifier); + struct auth_state *(*newstate)(const char *identifier); + void (*freestate)(struct auth_state *auth_state); ++ char *(*auth_canonuser)(struct auth_state *auth_state); + }; + + extern struct auth_mech *auth_mechs[]; +@@ -76,5 +77,6 @@ + const char *identifier); + struct auth_state *auth_newstate(const char *identifier); + void auth_freestate(struct auth_state *auth_state); ++char *auth_canonuser(struct auth_state *auth_state); + + #endif /* INCLUDED_AUTH_H */ +diff -Naur cyrus-imapd-2.3.1/lib/auth_krb.c cyrus-imapd-2.3.1-autocreate/lib/auth_krb.c +--- cyrus-imapd-2.3.1/lib/auth_krb.c 2005-12-14 15:52:09 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/auth_krb.c 2006-01-19 03:53:42 +0200 +@@ -339,6 +339,15 @@ + free((char *)auth_state); + } + ++static char *mycanonuser(struct auth_state *auth_state) ++{ ++ if (auth_state) ++ return auth_state->userid; ++ ++ return NULL; ++} ++ ++ + #else /* HAVE_KRB */ + + static int mymemberof( +@@ -367,6 +376,13 @@ + fatal("Authentication mechanism (krb) not compiled in", EC_CONFIG); + } + ++static char *mycanonuser( ++ struct auth_state *auth_state __attribute__((unused))) ++{ ++ fatal("Authentication mechanism (krb) not compiled in", EC_CONFIG); ++} ++ ++ + #endif + + struct auth_mech auth_krb = +@@ -377,4 +393,5 @@ + &mymemberof, + &mynewstate, + &myfreestate, ++ &mycanonuser, + }; +diff -Naur cyrus-imapd-2.3.1/lib/auth_krb5.c cyrus-imapd-2.3.1-autocreate/lib/auth_krb5.c +--- cyrus-imapd-2.3.1/lib/auth_krb5.c 2005-02-16 23:06:50 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/auth_krb5.c 2006-01-19 03:53:42 +0200 +@@ -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.1/lib/auth_pts.c cyrus-imapd-2.3.1-autocreate/lib/auth_pts.c +--- cyrus-imapd-2.3.1/lib/auth_pts.c 2005-02-20 05:23:45 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/auth_pts.c 2006-01-19 03:53:42 +0200 +@@ -347,6 +347,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 */ +@@ -355,4 +363,5 @@ + &mymemberof, + &mynewstate, + &myfreestate, ++ &mycanonuser, + }; +diff -Naur cyrus-imapd-2.3.1/lib/auth_unix.c cyrus-imapd-2.3.1-autocreate/lib/auth_unix.c +--- cyrus-imapd-2.3.1/lib/auth_unix.c 2005-02-16 23:06:50 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/auth_unix.c 2006-01-19 03:53:42 +0200 +@@ -264,6 +264,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 = + { +@@ -273,4 +283,5 @@ + &mymemberof, + &mynewstate, + &myfreestate, ++ &mycanonuser, + }; +diff -Naur cyrus-imapd-2.3.1/lib/imapoptions cyrus-imapd-2.3.1-autocreate/lib/imapoptions +--- cyrus-imapd-2.3.1/lib/imapoptions 2005-12-13 21:36:11 +0200 ++++ cyrus-imapd-2.3.1-autocreate/lib/imapoptions 2006-01-19 03:53:42 +0200 +@@ -172,6 +172,55 @@ + /* Number of seconds to wait before returning a timeout failure when + performing a client connection (e.g. in a murder enviornment) */ + ++{ "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.1/notifyd/Makefile.in cyrus-imapd-2.3.1-autocreate/notifyd/Makefile.in +--- cyrus-imapd-2.3.1/notifyd/Makefile.in 2004-05-31 21:22:59 +0300 ++++ cyrus-imapd-2.3.1-autocreate/notifyd/Makefile.in 2006-01-19 03:53:42 +0200 +@@ -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.1/notifyd/notifyd.c cyrus-imapd-2.3.1-autocreate/notifyd/notifyd.c +--- cyrus-imapd-2.3.1/notifyd/notifyd.c 2005-04-13 18:43:36 +0300 ++++ cyrus-imapd-2.3.1-autocreate/notifyd/notifyd.c 2006-01-19 03:53:42 +0200 +@@ -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.1/ptclient/Makefile.in cyrus-imapd-2.3.1-autocreate/ptclient/Makefile.in +--- cyrus-imapd-2.3.1/ptclient/Makefile.in 2005-02-17 20:43:03 +0200 ++++ cyrus-imapd-2.3.1-autocreate/ptclient/Makefile.in 2006-01-19 03:53:42 +0200 +@@ -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@ diff --git a/cyrus-imapd-2.3.1-autosievefolder-0.6-0.diff b/cyrus-imapd-2.3.1-autosievefolder-0.6-0.diff new file mode 100644 index 0000000..b46af02 --- /dev/null +++ b/cyrus-imapd-2.3.1-autosievefolder-0.6-0.diff @@ -0,0 +1,181 @@ +diff -Naur cyrus-imapd-2.3.1/README.autosievefolder cyrus-imapd-2.3.1-autosieve/README.autosievefolder +--- cyrus-imapd-2.3.1/README.autosievefolder 1970-01-01 02:00:00 +0200 ++++ cyrus-imapd-2.3.1-autosieve/README.autosievefolder 2006-01-19 03:29:08 +0200 +@@ -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.1/imap/lmtp_sieve.c cyrus-imapd-2.3.1-autosieve/imap/lmtp_sieve.c +--- cyrus-imapd-2.3.1/imap/lmtp_sieve.c 2005-11-21 18:26:54 +0200 ++++ cyrus-imapd-2.3.1-autosieve/imap/lmtp_sieve.c 2006-01-19 03:29:13 +0200 +@@ -86,6 +86,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]; +@@ -487,7 +490,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; +@@ -939,3 +955,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.1/lib/imapoptions cyrus-imapd-2.3.1-autosieve/lib/imapoptions +--- cyrus-imapd-2.3.1/lib/imapoptions 2005-12-13 21:36:11 +0200 ++++ cyrus-imapd-2.3.1-autosieve/lib/imapoptions 2006-01-19 03:29:15 +0200 +@@ -856,6 +856,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 diff --git a/cyrus-imapd-2.3.1-backend_sigsegv.patch b/cyrus-imapd-2.3.1-backend_sigsegv.patch new file mode 100644 index 0000000..fd37a20 --- /dev/null +++ b/cyrus-imapd-2.3.1-backend_sigsegv.patch @@ -0,0 +1,12 @@ +diff -Naur cyrus-imapd-2.3.1.orig/imap/backend.c cyrus-imapd-2.3.1/imap/backend.c +--- cyrus-imapd-2.3.1.orig/imap/backend.c 2005-02-25 07:46:14.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/backend.c 2006-01-25 08:10:20.000000000 +0100 +@@ -274,7 +274,7 @@ + /* need to (re)establish connection to server or create one */ + int sock = -1; + int r; +- int err; ++ int err = -1; + struct addrinfo hints, *res0 = NULL, *res1 = NULL, *res; + struct sockaddr_un sunsock; + char buf[2048], *mechlist = NULL; diff --git a/cyrus-imapd-2.3.1-config_defaults.patch b/cyrus-imapd-2.3.1-config_defaults.patch new file mode 100644 index 0000000..f9f202d --- /dev/null +++ b/cyrus-imapd-2.3.1-config_defaults.patch @@ -0,0 +1,94 @@ +diff -Naur cyrus-imapd-2.3.1.orig/lib/imapoptions cyrus-imapd-2.3.1/lib/imapoptions +--- cyrus-imapd-2.3.1.orig/lib/imapoptions 2005-12-13 20:36:11.000000000 +0100 ++++ cyrus-imapd-2.3.1/lib/imapoptions 2006-01-13 10:17:26.000000000 +0100 +@@ -198,9 +198,12 @@ + grant the user the ability to delete a mailbox. If a user has this + right, they will automatically be given the new 'x' right. */ + +-{ "duplicate_db", "berkeley-nosync", STRINGLIST("berkeley", "berkeley-nosync", "skiplist") } ++{ "duplicate_db", "skiplist", STRINGLIST("berkeley", "berkeley-nosync", "skiplist") } + /* The cyrusdb backend to use for the duplicate delivery suppression +- and sieve. */ ++ and sieve. ++.PP ++ Note: This Invoca RPM build uses \fIskiplist\fR by default instead of ++ \fIberkeley-nosync\fR for \fBduplicate_db\fR. */ + + { "duplicatesuppression", 1, SWITCH } + /* If enabled, lmtpd will suppress delivery of a message to a mailbox if +@@ -220,12 +223,15 @@ + result in greater responsiveness for the client, especially when + expunging a large number of messages. */ + +-{ "flushseenstate", 0, SWITCH } ++{ "flushseenstate", 1, SWITCH } + /* If enabled, changes to the seen state will be flushed to disk + immediately, otherwise changes will be cached and flushed when the + mailbox is closed. This option may be used to fix the problem of + previously read messages being marked as unread in Microsoft +- Outlook, at the expense of a loss of performance/scalability. */ ++ Outlook, at the expense of a loss of performance/scalability. ++.PP ++ Note: This Invoca RPM build uses \fI1\fR by default instead of ++ \fI0\fR for \fBflushseenstate\fR. */ + + { "foolstupidclients", 0, SWITCH } + /* If enabled, only list the personal namespace when a LIST "*" is performed. +@@ -735,8 +741,11 @@ + /* Unix domain socket that ptloader listens on. + (defaults to configdir/ptclient/ptsock) */ + +-{ "ptscache_db", "berkeley", STRINGLIST("berkeley", "skiplist") } +-/* The cyrusdb backend to use for the pts cache. */ ++{ "ptscache_db", "skiplist", STRINGLIST("berkeley", "skiplist") } ++/* The cyrusdb backend to use for the pts cache. ++.PP ++ Note: This Invoca RPM build uses \fIskiplist\fR by default instead of ++ \fIberkeley\fR for \fBptscache_db\fR. */ + + { "ptscache_timeout", 10800, INT } + /* The timeout (in seconds) for the PTS cache database when using the +@@ -813,9 +822,12 @@ + { "seenstate_db", "skiplist", STRINGLIST("flat", "berkeley", "skiplist") } + /* The cyrusdb backend to use for the seen state. */ + +-{ "sendmail", "/usr/lib/sendmail", STRING } ++{ "sendmail", "/usr/sbin/sendmail", STRING } + /* The pathname of the sendmail executable. Sieve invokes sendmail +- for sending rejections, redirects and vacation responses. */ ++ for sending rejections, redirects and vacation responses. ++.PP ++ Note: This Invoca RPM build uses \fI/usr/sbin/sendmail\fR by default ++ instead of \fI/usr/lib/sendmail\fR for \fBsendmail\fR. */ + + { "servername", NULL, STRING } + /* This is the hostname visible in the greeting messages of the POP, +@@ -842,9 +854,12 @@ + /* Maximum number of sieve scripts any user may have, enforced at + submission by timsieved(8). */ + +-{ "sievedir", "/usr/sieve", STRING } ++{ "sievedir", "/var/lib/imap/sieve", STRING } + /* If sieveusehomedir is false, this directory is searched for Sieve +- scripts. */ ++ scripts. ++.PP ++ Note: This Invoca RPM build uses \fI/var/lib/imap/sieve\fR by default ++ instead of \fI/usr/sieve\fR for \fBsievedir\fR. */ + + { "sievenotifier", NULL, STRING } + /* Notifyd(8) method to use for "SIEVE" notifications. If not set, "SIEVE" +@@ -934,8 +949,11 @@ + have filenames with the hashed value of the certificate (see + openssl(XXX)). */ + +-{ "tlscache_db", "berkeley-nosync", STRINGLIST("berkeley", "berkeley-nosync", "skiplist") } +-/* The cyrusdb backend to use for the TLS cache. */ ++{ "tlscache_db", "skiplist", STRINGLIST("berkeley", "berkeley-nosync", "skiplist") } ++/* The cyrusdb backend to use for the TLS cache. ++.PP ++ Note: This Invoca RPM build uses \fIskiplist\fR by default instead of ++ \fIberkeley-nosync\fR for \fBtlscache_db\fR. */ + + { "tls_cert_file", NULL, STRING } + /* File containing the certificate presented for server authentication diff --git a/cyrus-imapd-2.3.1-make_md5.patch b/cyrus-imapd-2.3.1-make_md5.patch new file mode 100644 index 0000000..127d220 --- /dev/null +++ b/cyrus-imapd-2.3.1-make_md5.patch @@ -0,0 +1,18 @@ +diff -Naur cyrus-imapd-2.3.1.orig/imap/make_md5.c cyrus-imapd-2.3.1/imap/make_md5.c +--- cyrus-imapd-2.3.1.orig/imap/make_md5.c 2005-12-13 16:31:08.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/make_md5.c 2006-01-18 20:21:14.000000000 +0100 +@@ -391,7 +391,13 @@ + FILE *file; + int i; + +- if ((file=fopen(name, "w")) == NULL) ++ file = fopen(name, "w"); ++ if (file == NULL && errno == ENOENT) { ++ if (cyrus_mkdir(name, 0750) == 0) { ++ file = fopen(name, "w"); ++ } ++ } ++ if (file == NULL) + return(IMAP_IOERROR); + + for (mailbox = list->head ; mailbox ; mailbox = mailbox->next) { diff --git a/cyrus-imapd-2.3.1-make_md5_defaults.patch b/cyrus-imapd-2.3.1-make_md5_defaults.patch new file mode 100644 index 0000000..36cd3bc --- /dev/null +++ b/cyrus-imapd-2.3.1-make_md5_defaults.patch @@ -0,0 +1,32 @@ +diff -Naur cyrus-imapd-2.3.1.orig/imap/make_md5.c cyrus-imapd-2.3.1/imap/make_md5.c +--- cyrus-imapd-2.3.1.orig/imap/make_md5.c 2005-12-13 16:31:08.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/make_md5.c 2006-01-16 11:27:29.000000000 +0100 +@@ -811,7 +811,7 @@ + if (!md5_dir) md5_dir = config_getstring(IMAPOPT_MD5_DIR); + + if (!md5_dir) +- md5_dir = xstrdup("/var/imap/md5"); ++ md5_dir = xstrdup("/var/lib/imap/md5"); + + if (((uid_file = config_getstring(IMAPOPT_MD5_USER_MAP)) != NULL) && + ((uid_fd=open(uid_file, O_RDONLY)) < 0)) { +diff -Naur cyrus-imapd-2.3.1.orig/lib/imapoptions cyrus-imapd-2.3.1/lib/imapoptions +--- cyrus-imapd-2.3.1.orig/lib/imapoptions 2005-12-13 20:36:11.000000000 +0100 ++++ cyrus-imapd-2.3.1/lib/imapoptions 2006-01-16 11:26:54.000000000 +0100 +@@ -527,10 +527,14 @@ + mailspool, but each have their own "replicated" copy of + mailboxes.db. */ + +-{ "md5_dir", NULL, STRING } ++{ "md5_dir", "/var/lib/imap/md5", STRING } + /* Top level directory for MD5 store manipulated by make_md5. File + structure within this directory is one file for each user on the system, +- hashed on the first letter of the userid (e.g: /var/imap/md5/d/dpc22). */ ++ hashed on the first letter of the ++ userid (e.g: /var/lib/imap/md5/d/dpc22). ++.PP ++ Note: This Invoca RPM build uses \fI/var/lib/imap/md5\fR by default ++ instead of \fI/var/imap/md5\fR for \fBmd5_dir\fR. */ + + { "md5_user_map", NULL, STRING } + /* Map file (cdb) to allow partial make_md5 runs. Maps username to UID */ diff --git a/cyrus-imapd-2.3.1-replication_policycheck.patch b/cyrus-imapd-2.3.1-replication_policycheck.patch new file mode 100644 index 0000000..85ea970 --- /dev/null +++ b/cyrus-imapd-2.3.1-replication_policycheck.patch @@ -0,0 +1,20 @@ +diff -Naur cyrus-imapd-2.3.1.orig/imap/sync_commit.c cyrus-imapd-2.3.1/imap/sync_commit.c +--- cyrus-imapd-2.3.1.orig/imap/sync_commit.c 2005-12-13 16:31:10.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/sync_commit.c 2006-01-25 10:18:50.000000000 +0100 +@@ -834,9 +834,15 @@ + /* Must be atleast MAX_PARTITION_LEN + 30 for partition, need + * MAX_PARTITION_LEN + HOSTNAME_SIZE + 2 for mupdate location */ + char buf[MAX_PARTITION_LEN + HOSTNAME_SIZE + 2]; ++ char *mbox = name; ++ char *p; + + /* Need an extra sanity check here as normal ACL logic is bypassed */ +- r = mboxname_policycheck(name); ++ if (config_virtdomains && (p = strchr(name, '!'))) { ++ /* pointer to mailbox w/o domain prefix */ ++ mbox = p + 1; ++ } ++ r = mboxname_policycheck(mbox); + if (r) return r; + + if (!uniqueid) { diff --git a/cyrus-imapd-2.3.1-rmquota+deletemailbox-0.2-1.diff b/cyrus-imapd-2.3.1-rmquota+deletemailbox-0.2-1.diff new file mode 100644 index 0000000..6810fba --- /dev/null +++ b/cyrus-imapd-2.3.1-rmquota+deletemailbox-0.2-1.diff @@ -0,0 +1,548 @@ +diff -Naur cyrus-imapd-2.3.1.orig/imap/ctl_cyrusdb.c cyrus-imapd-2.3.1/imap/ctl_cyrusdb.c +--- cyrus-imapd-2.3.1.orig/imap/ctl_cyrusdb.c 2005-02-16 22:06:18.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/ctl_cyrusdb.c 2006-01-16 11:10:56.000000000 +0100 +@@ -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.1.orig/imap/ctl_mboxlist.c cyrus-imapd-2.3.1/imap/ctl_mboxlist.c +--- cyrus-imapd-2.3.1.orig/imap/ctl_mboxlist.c 2005-11-23 14:41:24.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/ctl_mboxlist.c 2006-01-16 11:10:56.000000000 +0100 +@@ -457,7 +457,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) { + fprintf(stderr, "couldn't delete defunct mailbox %s\n", + me->mailbox); +diff -Naur cyrus-imapd-2.3.1.orig/imap/imapd.c cyrus-imapd-2.3.1/imap/imapd.c +--- cyrus-imapd-2.3.1.orig/imap/imapd.c 2005-12-13 20:35:50.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/imapd.c 2006-01-16 11:10:56.000000000 +0100 +@@ -4707,7 +4707,7 @@ + + r = mboxlist_deletemailbox(name, imapd_userisadmin, + imapd_userid, imapd_authstate, +- 0, 0, 0); ++ 0, 0, 0, 1); + + if (!r) sync_log_mailbox(name); + +@@ -4731,6 +4731,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); +@@ -4789,7 +4795,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? */ +@@ -6149,6 +6155,7 @@ + { + int newquota = -1; + int badresource = 0; ++ int rmquota = 0; + int c; + int force = 0; + static struct buf arg; +@@ -6165,7 +6172,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; +@@ -6234,7 +6242,10 @@ + quotaroot++; + } + +- r = mboxlist_setquota(mailboxname, newquota, force); ++ if(!rmquota) ++ r = mboxlist_setquota(mailboxname, newquota, force); ++ else ++ r = mboxlist_unsetquota(mailboxname); + } + + imapd_check(NULL, 0, 0); +@@ -7931,7 +7942,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.1.orig/imap/mailbox.c cyrus-imapd-2.3.1/imap/mailbox.c +--- cyrus-imapd-2.3.1.orig/imap/mailbox.c 2005-11-10 07:04:55.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/mailbox.c 2006-01-16 11:10:56.000000000 +0100 +@@ -2622,27 +2622,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); + + /* remove data (message file) directory */ + path = mailbox->path; +@@ -3263,3 +3243,49 @@ + 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.1.orig/imap/mailbox.h cyrus-imapd-2.3.1/imap/mailbox.h +--- cyrus-imapd-2.3.1.orig/imap/mailbox.h 2005-05-27 19:40:54.000000000 +0200 ++++ cyrus-imapd-2.3.1/imap/mailbox.h 2006-01-16 11:10:56.000000000 +0100 +@@ -329,6 +329,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.1.orig/imap/mboxlist.c cyrus-imapd-2.3.1/imap/mboxlist.c +--- cyrus-imapd-2.3.1.orig/imap/mboxlist.c 2005-12-13 20:36:03.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/mboxlist.c 2006-01-16 11:10:56.000000000 +0100 +@@ -93,6 +93,11 @@ + 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, +@@ -100,6 +105,7 @@ + + struct change_rock { + struct quota *quota; ++ struct quota *oldquota; + struct txn **tid; + }; + +@@ -891,9 +897,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; +@@ -904,6 +910,7 @@ + int mbtype; + const char *p; + mupdate_handle *mupdate_h = NULL; ++ char *quotaroot = NULL; + + if(!isadmin && force) return IMAP_PERMISSION_DENIED; + +@@ -1016,13 +1023,44 @@ + + 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) { ++ 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, NULL, 0 )) ++ 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: +@@ -2478,6 +2516,7 @@ + if (r) return r; + + crock.quota = "a; ++ crock.oldquota = NULL; + crock.tid = &tid; + /* top level mailbox */ + if(have_mailbox) +@@ -2496,17 +2535,21 @@ + */ + 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("a, NULL, 0); ++ r = quota_read("a, crock.tid, 0); + if (r == IMAP_QUOTAROOT_NONEXISTENT) { + /* already unset */ + return 0; +@@ -2523,13 +2566,45 @@ + } + else + strlcat(pattern, ".*", sizeof(pattern)); +- +- /* 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); + +- r = quota_delete("a, NULL); ++ r = quota_delete("a, 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; + } +@@ -2627,6 +2702,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); +@@ -2644,27 +2720,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; ++ if(mboxlist_oldquota) { ++ if (strlen(mailbox.quota.root) > strlen(mboxlist_oldquota->root)) { ++ /* Part of a child quota root */ ++ mailbox_close(&mailbox); ++ return 0; ++ } + } + 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); ++ if (strlen(mailbox.quota.root) >= strlen(mboxlist_newquota->root)) { ++ /* Part of a child quota root */ ++ mailbox_close(&mailbox); ++ return 0; ++ } + } +- free(mailbox.quota.root); ++ ++ r = mailbox_updatequota(&mailbox,tid); ++ if (r) ++ goto error; + } + + mailbox.quota.root = xstrdup(mboxlist_newquota->root); +@@ -2674,18 +2747,24 @@ + mboxlist_newquota->used += mailbox.quota_mailbox_used; + mailbox_close(&mailbox); + return 0; +- ++ + 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)); ++ name, mboxlist_newquota->root, error_message(r)); + + /* Note, we're a callback, and it's not a huge tragedy if we + * fail, so we don't ever return a failure */ + return 0; + } + ++ + /* must be called after cyrus_init */ + void mboxlist_init(int myflags) + { +diff -Naur cyrus-imapd-2.3.1.orig/imap/mboxlist.h cyrus-imapd-2.3.1/imap/mboxlist.h +--- cyrus-imapd-2.3.1.orig/imap/mboxlist.h 2005-02-21 20:25:40.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/mboxlist.h 2006-01-16 11:10:56.000000000 +0100 +@@ -125,7 +125,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.1.orig/imap/mupdate.c cyrus-imapd-2.3.1/imap/mupdate.c +--- cyrus-imapd-2.3.1.orig/imap/mupdate.c 2005-11-04 14:34:23.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/mupdate.c 2006-01-16 11:10:56.000000000 +0100 +@@ -2297,7 +2297,7 @@ + remote_boxes.head = r->next; + } else if (ret < 0) { + /* Local without corresponding remote, delete it */ +- mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0); ++ mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0, 1); + local_boxes.head = l->next; + } else /* (ret > 0) */ { + /* Remote without corresponding local, insert it */ +@@ -2312,7 +2312,7 @@ + if(l && !r) { + /* we have more deletes to do */ + while(l) { +- mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0); ++ mboxlist_deletemailbox(l->mailbox, 1, "", NULL, 0, 0, 0, 1); + local_boxes.head = l->next; + l = local_boxes.head; + } +diff -Naur cyrus-imapd-2.3.1.orig/imap/nntpd.c cyrus-imapd-2.3.1/imap/nntpd.c +--- cyrus-imapd-2.3.1.orig/imap/nntpd.c 2005-12-13 20:36:06.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/nntpd.c 2006-01-16 11:10:56.000000000 +0100 +@@ -3342,7 +3342,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.1.orig/imap/sync_reset.c cyrus-imapd-2.3.1/imap/sync_reset.c +--- cyrus-imapd-2.3.1.orig/imap/sync_reset.c 2005-12-13 16:31:10.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/sync_reset.c 2006-01-16 11:12:34.000000000 +0100 +@@ -254,7 +254,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; + } +@@ -270,7 +270,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; + } +@@ -278,7 +278,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.1.orig/imap/sync_server.c cyrus-imapd-2.3.1/imap/sync_server.c +--- cyrus-imapd-2.3.1.orig/imap/sync_server.c 2005-12-20 16:54:43.000000000 +0100 ++++ cyrus-imapd-2.3.1/imap/sync_server.c 2006-01-16 11:13:02.000000000 +0100 +@@ -1569,7 +1569,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; + } +@@ -1579,7 +1579,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))) +@@ -2501,7 +2501,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", diff --git a/cyrus-imapd-2.3.1.tar.gz.sig b/cyrus-imapd-2.3.1.tar.gz.sig new file mode 100644 index 0000000..9e892dd Binary files /dev/null and b/cyrus-imapd-2.3.1.tar.gz.sig differ diff --git a/cyrus-imapd-README.RPM b/cyrus-imapd-README.RPM index 097d6c6..8e30f01 100644 --- a/cyrus-imapd-README.RPM +++ b/cyrus-imapd-README.RPM @@ -7,7 +7,7 @@ This is a _very_ 'quick and dirty' install howto. The following steps should lead you to a running Cyrus IMAP server: 1) Install on a distribution which is supported by this RPM. Don't install - on a dirty system, where you have previously tried to install from source. + on a dirty system, where you have previously installed from source. 2) Don't install if you have a previous Cyrus IMAPd installation <=2.1.x on your box. Upgrading any Invoca rpm based installation should be fine. 3) Make sure you understand that this RPM installs in FHS compliant @@ -17,7 +17,8 @@ The following steps should lead you to a running Cyrus IMAP server: needed and do 'chkconfig saslauthd on ; service saslauthd start' 6) Install the cyrus-imapd RPMs. 7) If it's your first install of Cyrus IMAPd, then set a password for the - cyrus user in whatever database you are using to authenticate. + cyrus user in whatever database you are using to authenticate. When + using a local account, this should be 'passwd cyrus'. 8) Make sure your MTA delivers to Cyrus IMAPd, I recommend LMTP for this. 9) Start Cyrus IMAPd with 'service cyrus-imapd start' 10) Run cyradm and create a user. Usually it's something like this: @@ -30,4 +31,7 @@ The following steps should lead you to a running Cyrus IMAP server: info priority with something like 'mail.info /var/log/maillog' in /etc/syslog.conf. +Read the file "README.buildoptions" in this directory to find out which +build time options have been used to build this package. + Enjoy! diff --git a/cyrus-imapd-README.skiplist_recovery b/cyrus-imapd-README.skiplist_recovery new file mode 100644 index 0000000..b997cc1 --- /dev/null +++ b/cyrus-imapd-README.skiplist_recovery @@ -0,0 +1,21 @@ +From http://article.gmane.org/gmane.mail.imap.cyrus/18840 + +We have also seen skiplist corruption in seen databases. I don't have a +recovery tool, but I have been able to manually recover seen db's to the +point of corruption so that at least most of the users mails are in the +correct 'read' state. Typically, you will see errors like: + +DBERROR: skiplist recovery /usr/local/imap/user/k/kdelaney.seen: 0D2C +should be ADD or DELETE + +If you truncate the file at this point, it should fix the problem, and +the users mail read state will be valid upto the point of corruption. +To do this, convert the hex to decimal (above would be 1372) and use the +dd command: + +dd if=kdelaney.seen of=kdelaney.seen.fixed bs=1 count=1372 + +replace the corrupted .seen file with the fixed one and have user log in +and should be ok. + +Seems to work on the couple I have tried it on. diff --git a/cyrus-imapd-db.cfg b/cyrus-imapd-db.cfg deleted file mode 100644 index cf2e01a..0000000 --- a/cyrus-imapd-db.cfg +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_DB_DUPLICATE=berkeley -CONFIG_DB_MBOX=skiplist -CONFIG_DB_SEEN=skiplist -CONFIG_DB_SUBS=flat -CONFIG_DB_TLS=berkeley -CONFIG_DB_ANNOTATION=skiplist -CONFIG_DB_SIEVE=2.2.3 diff --git a/cyrus-imapd-gcc4.patch b/cyrus-imapd-gcc4.patch deleted file mode 100644 index b868abe..0000000 --- a/cyrus-imapd-gcc4.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- cyrus-imapd-2.2.10/tools/config2header.orig 2005-03-04 17:18:04.519026273 -0500 -+++ cyrus-imapd-2.2.10/tools/config2header 2005-03-04 17:19:45.234962450 -0500 -@@ -214,7 +214,6 @@ - print HFILE < # - use runuser instead of su if available +# +# v1.0.13, Jul 15 2005 Simon Matter +# - don't use flat in the two step conversion, use skiplist instead +# +# v1.0.14, Jul 18 2005 Simon Matter +# - replace the order of the magic files in the file call to make +# sure skiplist is detected correctly. +# +# v1.0.15, Aug 17 2005 Simon Matter +# - add functionality to export all berkeley db files to skiplist +# +# v1.1.0, Aug 18 2005 Simon Matter +# - fix export functionality, try to recover Berkeley databases +# as much as possible before any conversion. +# +# v1.1.1, Dec 05 2005 Simon Matter +# - run db_checkpoint in background with a timeout to prevent +# that cyrus-imapd doesn't start at all if it hangs. +# +# v1.1.2, Dec 06 2005 Simon Matter +# - make handling of db_checkpoint more robust +# +# v1.2.0, Jan 12 2006 Simon Matter +# - adopt for cyrus-imapd-2.3 +# +# v1.2.1, Jan 13 2006 Simon Matter +# - code cleanup + +VERSION=1.2.1 if [ -n "$(/sbin/pidof cyrus-master)" ]; then echo "ERROR: cyrus-master is running, unable to convert mailboxes!" @@ -90,12 +119,18 @@ fi # force cyrus user for security reasons if [ ! $(whoami) = "cyrus" ]; then - exec $RUNUSER - cyrus -c "cd $PWD < /dev/null ; $0" + exec $RUNUSER - cyrus -c "cd $PWD < /dev/null ; $0 $*" fi +# special function for migration +EXPORT=$1 + # files get mode 0600 umask 166 +# show version info in log files +echo "cvt_cyrusdb_all version: $VERSION" + # get_config [config default] # extracts config option from config file get_config() { @@ -107,13 +142,16 @@ get_config() { } # where to find files and directories +data_dir=/usr/share/cyrus-imapd/rpm +lib_dir=/usr/lib/cyrus-imapd system_magic=$(file --version | awk '/magic file/ {print $4}') -cyrus_magic=/usr/share/cyrus-imapd/rpm/magic -cvt_cyrusdb=/usr/lib/cyrus-imapd/cvt_cyrusdb -sievec=/usr/lib/cyrus-imapd/sievec +cyrus_magic=${data_dir}/magic +cvt_cyrusdb=${lib_dir}/cvt_cyrusdb +sievec=${lib_dir}/sievec +masssievec=${lib_dir}/masssievec imap_prefix=$(get_config configdirectory /var/lib/imap) sieve_dir=$(get_config sievedir /var/lib/imap/sieve) -db_cfg=/usr/share/cyrus-imapd/rpm/db.cfg +db_cfg=${data_dir}/db.cfg db_current=${imap_prefix}/rpm/db.cfg.current db_cache=${imap_prefix}/rpm/db.cfg.cache @@ -121,27 +159,33 @@ db_cache=${imap_prefix}/rpm/db.cfg.cache . $db_cfg # get configured db backend config -CONFIG_DB_DUPLICATE=$(get_config duplicate_db $CONFIG_DB_DUPLICATE) -CONFIG_DB_MBOX=$(get_config mboxlist_db $CONFIG_DB_MBOX) -CONFIG_DB_SEEN=$(get_config seenstate_db $CONFIG_DB_SEEN) -CONFIG_DB_SUBS=$(get_config subscription_db $CONFIG_DB_SUBS) -CONFIG_DB_TLS=$(get_config tlscache_db $CONFIG_DB_TLS) -CONFIG_DB_ANNOTATION=$(get_config annotation_db $CONFIG_DB_ANNOTATION) +duplicate_db=$(get_config duplicate_db $duplicate_db) +mboxlist_db=$(get_config mboxlist_db $mboxlist_db) +seenstate_db=$(get_config seenstate_db $seenstate_db) +subscription_db=$(get_config subscription_db $subscription_db) +tlscache_db=$(get_config tlscache_db $tlscache_db) +annotation_db=$(get_config annotation_db $annotation_db) +mboxkey_db=$(get_config mboxkey_db $mboxkey_db) +ptscache_db=$(get_config ptscache_db $ptscache_db) +quota_db=$(get_config quota_db $quota_db) # remember current db backend config { -echo "CONFIG_DB_DUPLICATE=$CONFIG_DB_DUPLICATE" -echo "CONFIG_DB_MBOX=$CONFIG_DB_MBOX" -echo "CONFIG_DB_SEEN=$CONFIG_DB_SEEN" -echo "CONFIG_DB_SUBS=$CONFIG_DB_SUBS" -echo "CONFIG_DB_TLS=$CONFIG_DB_TLS" -echo "CONFIG_DB_ANNOTATION=$CONFIG_DB_ANNOTATION" -echo "CONFIG_DB_SIEVE=$CONFIG_DB_SIEVE" -} > $db_current +echo "duplicate_db=$duplicate_db" +echo "mboxlist_db=$mboxlist_db" +echo "seenstate_db=$seenstate_db" +echo "subscription_db=$subscription_db" +echo "tlscache_db=$tlscache_db" +echo "annotation_db=$annotation_db" +echo "mboxkey_db=$mboxkey_db" +echo "ptscache_db=$ptscache_db" +echo "quota_db=$quota_db" +echo "sieve_version=$sieve_version" +} | sort > $db_current # file_type [file] file_type() { - this_type=$(file -b -m "$system_magic:$cyrus_magic" "$1" 2> /dev/null) + this_type=$(file -b -m "$cyrus_magic:$system_magic" "$1" 2> /dev/null) if echo "$this_type" | grep -qi skip > /dev/null 2>&1; then echo skiplist elif echo "$this_type" | grep -qi text > /dev/null 2>&1; then @@ -160,32 +204,32 @@ cvt_file() { if [ ! "$old_db" = "$new_db" ]; then # The two-step conversion is paranoia against the filenames being encoded # inside the database or logfiles (berkeley does this, for example). - rm -f "${target}.flat" - if [ "$old_db" = "flat" ]; then - cp -a "$target" "${target}.flat" + rm -f "${target}.skiplist" + if [ "$old_db" = "skiplist" ]; then + cp -a "$target" "${target}.skiplist" else - $cvt_cyrusdb "$target" "$old_db" "${target}.flat" flat + $cvt_cyrusdb "$target" "$old_db" "${target}.skiplist" skiplist fi RETVAL=$? ERRVAL=$[ $ERRVAL + $RETVAL ] if [ $RETVAL -eq 0 ]; then rm -f "$target" - if [ -s "${target}.flat" ]; then - if [ "$new_db" = "flat" ]; then - cp -a "${target}.flat" "$target" + if [ -s "${target}.skiplist" ]; then + if [ "$new_db" = "skiplist" ]; then + cp -a "${target}.skiplist" "$target" else - $cvt_cyrusdb "${target}.flat" flat "$target" "$new_db" + $cvt_cyrusdb "${target}.skiplist" skiplist "$target" "$new_db" fi fi RETVAL=$? ERRVAL=$[ $ERRVAL + $RETVAL ] if [ $RETVAL -eq 0 ]; then - rm -f "${target}.flat" + rm -f "${target}.skiplist" else - echo "ERROR: unable to convert ${target}.flat from flat to $new_db" + echo "ERROR: unable to convert ${target}.skiplist from skiplist to $new_db" fi else - echo "ERROR: unable to convert $target from $old_db to flat" + echo "ERROR: unable to convert $target from $old_db to skiplist" fi fi fi @@ -211,27 +255,77 @@ cvt_to_utf8() { ERRVAL=0 -# do we need to convert databases ? -if ! cmp -s $db_current $db_cache; then - # we treat sieve scripts the same way like db files - find ${sieve_dir}/ -name "*.script" -type f | while read db_file trash; do - cvt_to_utf8 "$db_file" - done - /usr/lib/cyrus-imapd/masssievec /usr/lib/cyrus-imapd/sievec - # convert all db files - cvt_file $imap_prefix/deliver.db "$CONFIG_DB_DUPLICATE" - cvt_file $imap_prefix/mailboxes.db "$CONFIG_DB_MBOX" - cvt_file $imap_prefix/tls_sessions.db "$CONFIG_DB_TLS" - cvt_file $imap_prefix/annotations.db "$CONFIG_DB_ANNOTATION" - find ${imap_prefix}/user/ -name "*.seen" -type f | while read db_file trash; do - cvt_file "$db_file" "$CONFIG_DB_SEEN" - done - find ${imap_prefix}/user/ -name "*.sub" -type f | while read db_file trash; do - cvt_file "$db_file" "$CONFIG_DB_SUBS" - done +# make sure our Berkeley databases are in a sane state +# wait for db_checkpoint to end successfully or kill it after a timeout +db_checkpoint -v -1 -h $imap_prefix/db & +DB_CHECK_PID=$! +CNT=0 +while [ $CNT -lt 60 ]; do + if ! kill -0 $DB_CHECK_PID > /dev/null 2>&1; then + break + fi + sleep 1 + let CNT+=1 +done +if kill -0 $DB_CHECK_PID > /dev/null 2>&1; then + kill -USR1 $DB_CHECK_PID > /dev/null 2>&1 + sleep 1 + kill -KILL $DB_CHECK_PID > /dev/null 2>&1 + wait $DB_CHECK_PID > /dev/null 2>&1 +fi + +# do a normal recovery +db_recover -v -h $imap_prefix/db +RETVAL=$? +if [ $RETVAL -ne 0 ]; then + # try a catastrophic recovery instead of normal recovery + db_recover -v -c -h $imap_prefix/db + RETVAL=$? + ERRVAL=$[ $ERRVAL + $RETVAL ] + if [ $RETVAL -ne 0 ]; then + echo "ERROR: catastrophic recovery of Berkeley databases failed" + fi +fi + +if [ "$EXPORT" = "export" ]; then + # convert all db files to skiplist for migration + # TODO: quota_db, we don't touch it for now + cvt_file $imap_prefix/deliver.db "skiplist" + cvt_file $imap_prefix/mailboxes.db "skiplist" + cvt_file $imap_prefix/tls_sessions.db "skiplist" + cvt_file $imap_prefix/annotations.db "skiplist" + cvt_file $imap_prefix/ptclient/ptscache.db "skiplist" + rm -vf $imap_prefix/db/log.* + rm -vf $imap_prefix/db/__db.* +else + # always convert db files which have been converted to skiplist + # TODO: quota_db, we don't touch it for now + cvt_file $imap_prefix/deliver.db "$duplicate_db" + cvt_file $imap_prefix/mailboxes.db "$mboxlist_db" + cvt_file $imap_prefix/tls_sessions.db "$tlscache_db" + cvt_file $imap_prefix/annotations.db "$annotation_db" + cvt_file $imap_prefix/ptclient/ptscache.db "$ptscache_db" + # do we have to convert all databases? + if ! cmp -s $db_current $db_cache; then + # we treat sieve scripts the same way like db files + find ${sieve_dir}/ -name "*.script" -type f | while read db_file trash; do + cvt_to_utf8 "$db_file" + done + $masssievec $sievec + # convert all db files left + find ${imap_prefix}/user/ -name "*.seen" -type f | while read db_file trash; do + cvt_file "$db_file" "$seenstate_db" + done + find ${imap_prefix}/user/ -name "*.sub" -type f | while read db_file trash; do + cvt_file "$db_file" "$subscription_db" + done + find ${imap_prefix}/user/ -name "*.mboxkey" -type f | while read db_file trash; do + cvt_file "$db_file" "$mboxkey_db" + done + fi fi -# copy the current config file so we can check whether something has changed +# update the config cache file so we can check whether something has changed if [ $ERRVAL -eq 0 ]; then mv -f $db_current $db_cache else diff --git a/cyrus-imapd.imap-2.2.x-conf b/cyrus-imapd.imap-2.2.x-conf deleted file mode 100644 index 1d2f16a..0000000 --- a/cyrus-imapd.imap-2.2.x-conf +++ /dev/null @@ -1,11 +0,0 @@ -configdirectory: /var/lib/imap -partition-default: /var/spool/imap -admins: cyrus -sievedir: /var/lib/imap/sieve -sendmail: /usr/sbin/sendmail -hashimapspool: true -sasl_pwcheck_method: saslauthd -sasl_mech_list: PLAIN -tls_cert_file: /usr/share/ssl/certs/cyrus-imapd.pem -tls_key_file: /usr/share/ssl/certs/cyrus-imapd.pem -tls_ca_file: /usr/share/ssl/certs/ca-bundle.crt diff --git a/cyrus-imapd.imap-2.3.x-conf b/cyrus-imapd.imap-2.3.x-conf new file mode 100644 index 0000000..1d2f16a --- /dev/null +++ b/cyrus-imapd.imap-2.3.x-conf @@ -0,0 +1,11 @@ +configdirectory: /var/lib/imap +partition-default: /var/spool/imap +admins: cyrus +sievedir: /var/lib/imap/sieve +sendmail: /usr/sbin/sendmail +hashimapspool: true +sasl_pwcheck_method: saslauthd +sasl_mech_list: PLAIN +tls_cert_file: /usr/share/ssl/certs/cyrus-imapd.pem +tls_key_file: /usr/share/ssl/certs/cyrus-imapd.pem +tls_ca_file: /usr/share/ssl/certs/ca-bundle.crt diff --git a/cyrus-imapd.init b/cyrus-imapd.init index 441035d..dc0e545 100644 --- a/cyrus-imapd.init +++ b/cyrus-imapd.init @@ -7,22 +7,9 @@ # config: /etc/imapd.conf # pidfile: /var/run/cyrus-master.pid -# author: Simon Matter, Invoca Systems -# version: 2005010600 -# changed: 2002020200 chkconfig modified -# 2002042500 rewrote start function -# 2002091800 added auto db converting functionality -# 2003020400 modified to use builtin daemon mode -# 2003050200 modified exec path -# 2003050900 return RETVAL from rhstatus(), did some cleanup -# 2003060700 added umask for cvt_cyrusdb_all log -# 2004012300 modified auto db converting functionality for 2.2 -# 2004012700 fixed startup procedure -# 2004022400 change su within init script to get input from -# /dev/null, this prevents hang when running in SELinux -# 2004052000 don't enable cyrus-imapd per default -# 2004111900 use runuser instead of su if available -# 2005010600 removed LIB placeholder +# author: Simon Matter, Invoca Systems +# version: 2005111100 +# changed: add quickstart/stop option to init script to bypass db import/export # Source function library if [ -f /etc/init.d/functions ]; then @@ -50,48 +37,67 @@ if [ -L $0 ]; then BASENAME=$(basename $BASENAME) fi -# fallback to su if runuser not available -if [ -x /sbin/runuser ]; then - RUNUSER=runuser +# Source service configuration. +if [ -f /etc/sysconfig/$BASENAME ]; then + . /etc/sysconfig/$BASENAME else - RUNUSER=su + echo "$BASENAME: configfile /etc/sysconfig/$BASENAME does NOT exist !" + exit 1 fi +# get_config [config default] +# extracts config option from config file +get_config() { + if config=$(grep "^$1" /etc/imapd.conf); then + echo $config | cut -d: -f2 + else + echo $2 + fi +} + +# where to find files and directories +CONFIGDIRECTORY=$(get_config configdirectory /var/lib/imap) CYRUSMASTER=/usr/lib/cyrus-imapd/cyrus-master CYRUS_PROC_NAME=$(basename $CYRUSMASTER) ALWAYS_CONVERT=1 -# Source service configuration. -if [ -f /etc/sysconfig/$BASENAME ]; then - . /etc/sysconfig/$BASENAME +# fallback to su if runuser not available +if [ -x /sbin/runuser ]; then + RUNUSER=runuser else - echo "$BASENAME: configfile /etc/sysconfig/$BASENAME does NOT exist !" - exit 1 + RUNUSER=su fi RETVAL=0 +RETVAL2=1 +QUICK=0 start() { - echo -n $"Starting $BASENAME: " if [ $(/sbin/pidof -s $CYRUSMASTER) ]; then echo -n $"$BASENAME already running." false + echo else - echo -n $"preparing databases... " - $RUNUSER - cyrus -c "umask 166 ; /usr/lib/cyrus-imapd/cvt_cyrusdb_all > /var/lib/imap/rpm/cvt_cyrusdb_all.log 2>&1" < /dev/null - RETVAL=$? + if [ $QUICK -eq 0 ]; then + echo -n $"Importing $BASENAME databases: " + cd $CONFIGDIRECTORY + $RUNUSER - cyrus -c "umask 166 ; /usr/lib/cyrus-imapd/cvt_cyrusdb_all > ${CONFIGDIRECTORY}/rpm/db_import.log 2>&1" < /dev/null + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + success $"$BASENAME importing databases" + else + failure $"$BASENAME error importing databases, check ${CONFIGDIRECTORY}/rpm/db_import.log" + fi + echo + fi if [ $RETVAL -eq 0 ]; then - echo -n $"done. " + echo -n $"Starting $BASENAME: " daemon $CYRUSMASTER -d $CYRUSOPTIONS - else - echo -n $"error! " - initlog -n $BASENAME -s "error converting databases, check /var/lib/imap/rpm/cvt_cyrusdb_all.log" - failure $"$BASENAME startup" + RETVAL2=$? + echo fi fi - RETVAL=$? - echo - [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$BASENAME + [ $RETVAL -eq 0 -a $RETVAL2 -eq 0 ] && touch /var/lock/subsys/$BASENAME return $RETVAL } @@ -99,8 +105,22 @@ stop() { echo -n $"Shutting down $BASENAME: " killproc $CYRUSMASTER RETVAL=$? - [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$BASENAME + if [ $QUICK -eq 0 ]; then + if [ ! $(/sbin/pidof -s $CYRUSMASTER) ]; then + echo + echo -n $"Exporting $BASENAME databases: " + cd $CONFIGDIRECTORY + $RUNUSER - cyrus -c "umask 166 ; /usr/lib/cyrus-imapd/cvt_cyrusdb_all export > ${CONFIGDIRECTORY}/rpm/db_export.log 2>&1" < /dev/null + RETVAL2=$? + if [ $RETVAL2 -eq 0 ]; then + success $"$BASENAME exporting databases" + else + failure $"$BASENAME error exporting databases, check ${CONFIGDIRECTORY}/rpm/db_export.log" + fi + fi + fi echo + [ $RETVAL -eq 0 -a $RETVAL2 -eq 0 ] && rm -f /var/lock/subsys/$BASENAME return $RETVAL } @@ -146,8 +166,16 @@ case "$1" in status) rhstatus ;; + quickstart) + QUICK=1 + start + ;; + quickstop) + QUICK=1 + stop + ;; *) - echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status}" + echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|quickstart|quickstop}" RETVAL=1 esac diff --git a/cyrus-imapd.rpm_set_permissions b/cyrus-imapd.rpm_set_permissions index ab8ea2d..b5de70e 100644 --- a/cyrus-imapd.rpm_set_permissions +++ b/cyrus-imapd.rpm_set_permissions @@ -8,18 +8,18 @@ if [ "x$CONFDIR" = "x" ]; then fi find $CONFDIR -type d ! -name "lost+found" -exec chmod 700 {} \; -exec chown cyrus:mail {} \; -grep -se "^partition-.*:" $IMAPCONF | cut -d":" -f2 | while read SPOOLDIR; do +grep -sE "^(meta|)partition-.*:" $IMAPCONF | cut -d":" -f2 | while read SPOOLDIR; do if [ "x$SPOOLDIR" = "x" ]; then - echo "$0 warning: invalid partition configuration in /etc/imapd.conf found!" + echo "$0 warning: invalid (meta)partition configuration in /etc/imapd.conf found!" else find $SPOOLDIR -type d ! -name "lost+found" -exec chmod 700 {} \; -exec chown cyrus:mail {} \; fi done find $CONFDIR -type f ! -name "lost+found" -exec chmod 600 {} \; -exec chown cyrus:mail {} \; -grep -se "^partition-.*:" $IMAPCONF | cut -d":" -f2 | while read SPOOLDIR; do +grep -sE "^(meta|)partition-.*:" $IMAPCONF | cut -d":" -f2 | while read SPOOLDIR; do if [ "x$SPOOLDIR" = "x" ]; then - echo "$0 warning: invalid partition configuration in /etc/imapd.conf found!" + echo "$0 warning: invalid (meta)partition configuration in /etc/imapd.conf found!" else find $SPOOLDIR -type f ! -name "lost+found" -exec chmod 600 {} \; -exec chown cyrus:mail {} \; fi diff --git a/cyrus-imapd.spec b/cyrus-imapd.spec index 491d1fd..99591d3 100644 --- a/cyrus-imapd.spec +++ b/cyrus-imapd.spec @@ -1,6 +1,6 @@ -Name: cyrus-imapd -Version: 2.2.12 -Release: 1.fc5 +Name: cyrus-imapd +Version: 2.3.1 +Release: 2.fc5 # ********************** BUILD TIME OPTIONS START ********************** @@ -8,139 +8,150 @@ Release: 1.fc5 # rpm --rebuild --define='SEEN_DB skiplist' cyrus-imapd-2.x.x-x.src.rpm # use saslauth group -%{!?SASLGROUP: %define SASLGROUP 0} - +%{!?SASLGROUP: %define SASLGROUP 0} # include deliver-wrapper -%{!?DEL_WRAP: %define DEL_WRAP 0} - +%{!?DEL_WRAP: %define DEL_WRAP 0} # use preforking cyrus.conf -%{!?PREFORK: %define PREFORK 1} - +%{!?PREFORK: %define PREFORK 1} # enable Netscape hack (recommended) -%{!?NETSCAPEHACK: %define NETSCAPEHACK 1} - +%{!?NETSCAPEHACK: %define NETSCAPEHACK 1} # enable IMAP4 LIST extensions -%{!?LISTEXT: %define LISTEXT 1} - +%{!?LISTEXT: %define LISTEXT 1} # enable IDLED support -%{!?IDLED: %define IDLED 1} - +%{!?IDLED: %define IDLED 1} +# enable SNMP support +%{!?SNMP: %define SNMP 0} # force syncronous updates on ext3 -%{!?FORCESYNCEXT3: %define FORCESYNCEXT3 0} - +%{!?FORCESYNCEXT3: %define FORCESYNCEXT3 0} # include autocreate feature -%{!?AUTOCREATE: %define AUTOCREATE 1} - +%{!?AUTOCREATE: %define AUTOCREATE 1} # include groupcache feature -%{!?GROUPCACHE: %define GROUPCACHE 1} - +%{!?GROUPCACHE: %define GROUPCACHE 1} # don't check for RFC compliant line termination (bare newlines) -%{!?NO_BARE_NL: %define NO_BARE_NL 0} - +%{!?NO_BARE_NL: %define NO_BARE_NL 0} # used syslog facility for logging -%{!?SYSLOGFACILITY: %define SYSLOGFACILITY MAIL} - +%{!?SYSLOGFACILITY: %define SYSLOGFACILITY MAIL} # use -fpie for linking -%{!?USEPIE: %define USEPIE 0} - -# OutlookExpress seenstate patch -%{!?OE_SEEN_ST: %define OE_SEEN_ST 1} - -# use authorization module METHOD [unix|krb5] -%{!?AUTH_METHOD: %define AUTH_METHOD unix} +%{!?USEPIE: %define USEPIE 0} # ********************** BUILD TIME OPTIONS END ************************ -%define _use_internal_dependency_generator 0 -%define _rhver %(eval rpm -q --queryformat '%{VERSION}' $(rpm -qf /etc/redhat-release)) -%define _rhrelease %(eval %{__cat} /etc/redhat-release) -%define _dbver db4 -%define _dbrpmver %(eval "rpm -q %{_dbver}") +%define _acversion 2.59 +%define _use_internal_dependency_generator 0 +%define _rhver %(eval rpm -q --queryformat '%{VERSION}' $(rpm -qf /etc/redhat-release)) +%define _rhrelease %(eval %{__cat} /etc/redhat-release) +%define _dbver db4 +%define _dbrpmver %(eval "rpm -q %{_dbver}") # Do we need the perl install hack for RedHat > 7.3 ? -%define _perlhack %(eval [ %{_rhver} = "6.2" -o %{_rhver} = "7.0" -o %{_rhver} = "7.1" -o %{_rhver} = "7.2" -o %{_rhver} = "7.3" -o %{_rhver} = "2.1AS" -o %{_rhver} = "2.1ES" ] && echo 0 || echo 1) -%define _perl_man3dir %(eval "$(perl -V:man3dir)"; echo $man3dir) +%define _perlhack %(eval [ %{_rhver} = "6.2" -o %{_rhver} = "7.0" -o %{_rhver} = "7.1" -o %{_rhver} = "7.2" -o %{_rhver} = "7.3" -o %{_rhver} = "2.1AS" -o %{_rhver} = "2.1ES" ] && echo 0 || echo 1) +%define _perl_man3dir %(eval "$(perl -V:man3dir)"; echo $man3dir) +%define _withldap %(eval "rpm -q --requires openldap | grep -q ^libsasl2 && echo 1 || echo 0") +%define _snmpver %(eval "rpm -q --quiet ucd-snmp && echo ucd || echo net") # Disable -debuginfo package generation -#define debug_package %{nil} +#define debug_package %{nil} +# Do we have filesystem >= 2.3.2 (new pki location) ? +%define use_etc_pki %(eval [ $(rpm -q --queryformat '%{VERSION}' filesystem \| sed -e "s/\\.//g") -ge 232 ] && echo 1 || echo 0 ) +%if %{use_etc_pki} +%define certs_dir %{_sysconfdir}/pki/tls/certs %define pki_dir %{_sysconfdir}/pki/%{name} +%else +%define certs_dir %{_datadir}/ssl/certs +%define pki_dir %{_datadir}/ssl/certs +%endif %define ssl_pem_file %{pki_dir}/%{name}.pem - -Summary: A high-performance mail server with IMAP, POP3, NNTP and SIEVE support. -License: BSD -Group: System Environment/Daemons -URL: http://asg.web.cmu.edu/cyrus/imapd/ -#Packager: Simon Matter -#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 -Source2: cyrus-procmailrc -Source3: cyrus-deliver-wrapper.c -Source4: cyrus-user-procmailrc.template -Source5: cyrus-imapd.logrotate -Source6: cyrus-imapd.imap-2.2.x-conf -Source7: cyrus-imapd.pam-config -Source8: http://email.uoa.gr/projects/cyrus/autocreate/README.autocreate-cyrus-2.2 -Source9: http://email.uoa.gr/projects/cyrus/autosievefolder/README.autosievefolder -Source10: cyrus-imapd-db.cfg -Source11: cyrus-imapd.init -Source12: cyrus-imapd.sysconfig -Source13: cyrus-imapd.cvt_cyrusdb_all -Source14: cyrus-imapd.magic -Source15: http://clement.hermann.free.fr/scripts/Cyrus/imapcreate.pl -Source16: http://eu.dl.sourceforge.net/cyrus-utils/cyrus_ldap_quota.pl -Source17: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/batchreconstruct -Source18: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/bsd2cyrus -Source19: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/cpmsg -Source20: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/folderxfer -Source21: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/inboxfer -Source22: http://email.uoa.gr/download/cyrus/cyrus_sharedbackup/cyrus_sharedbackup-0.1.tar.gz -Source23: cyrus-imapd-README.RPM -Source24: cyrus-imapd-README.HOWTO-recover-mailboxes.db -Source25: cyrus-imapd.cron-daily -Source27: cyrus-imapd-procmail+cyrus.mc -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 -Patch0: cyrus-imapd-2.1.9-fdatasync.patch -Patch1: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.2.12/cyrus-imapd-2.2.12-autocreate-0.9.2.diff -Patch2: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.2.12/cyrus-imapd-2.2.12-autosievefolder-0.6.diff -Patch3: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.2.10/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.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.4-munge8bit.patch -Patch6: cyrus-imapd-2.1.16-getrlimit.patch -Patch7: cyrus-imapd-2.1.15-nobarenewlinescheck.patch -Patch8: cyrus-imapd-2.2.10-groupcache.patch -Patch9: cyrus-imapd-2.2.4-OE-seenstate.patch -Patch10: cyrus-imapd-acceptinvalidfrom.patch -Patch50: cyrus-imapd-gcc4.patch -# Patches >= 100 are fixed in CVS -BuildRoot: %{_tmppath}/%{name}-%{version}-root -Prereq: e2fsprogs, diffutils, /sbin/chkconfig, /sbin/service -Requires: cyrus-sasl >= 2.1.15, file >= 3.35-1 -Requires: filesystem >= 2.3.2-1 -Requires: openssl >= 0.9.7f-4 -BuildPrereq: cyrus-sasl-devel >= 2.1.15-1, perl, tcp_wrappers, %{_dbver}-devel, openssl-devel -BuildPrereq: flex, bison, groff >= 1.15-8, autoconf - -%define uid 76 +%define uid 76 %if %{SASLGROUP} -%define gid 76 -%define _saslgroup saslauth +%define gid 76 +%define _saslgroup saslauth %endif -%define _cyrususer cyrus -%define _cyrusgroup mail -%define _vardata %{_var}/lib/imap -%define _spooldata %{_var}/spool/imap -%define _cyrexecdir %{_exec_prefix}/lib/%{name} -%define _confdir master/conf -%define _contribdir doc/contrib +%define _cyrususer cyrus +%define _cyrusgroup mail +%define _vardata %{_var}/lib/imap +%define _spooldata %{_var}/spool/imap +%define _cyrexecdir %{_exec_prefix}/lib/%{name} +%define _confdir master/conf +%define _contribdir doc/contrib %if %{PREFORK} -%define _cyrusconf %{_confdir}/prefork.conf +%define _cyrusconf %{_confdir}/prefork.conf %else -%define _cyrusconf %{_confdir}/normal.conf +%define _cyrusconf %{_confdir}/normal.conf +%endif + +Summary: A high-performance mail server with IMAP, POP3, NNTP and SIEVE support. +License: BSD +Group: System Environment/Daemons +URL: http://asg.web.cmu.edu/cyrus/imapd/ +#Packager: Simon Matter +#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 +Source2: http://ftp.gnu.org/gnu/autoconf/autoconf-%{_acversion}.tar.gz +Source3: cyrus-deliver-wrapper.c +Source4: cyrus-user-procmailrc.template +Source5: cyrus-imapd.logrotate +Source6: cyrus-imapd.imap-2.3.x-conf +Source7: cyrus-imapd.pam-config +Source8: http://email.uoa.gr/projects/cyrus/autocreate/README.autocreate-cyrus-2.3 +Source9: http://email.uoa.gr/projects/cyrus/autosievefolder/README.autosievefolder +Source10: http://oss.netfarm.it/download/skiplist.py +Source11: cyrus-imapd.init +Source12: cyrus-imapd.sysconfig +Source13: cyrus-imapd.cvt_cyrusdb_all +Source14: cyrus-imapd.magic +Source15: http://clement.hermann.free.fr/scripts/Cyrus/imapcreate.pl +Source16: http://eu.dl.sourceforge.net/cyrus-utils/cyrus_ldap_quota.pl +Source17: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/batchreconstruct +Source18: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/bsd2cyrus +Source19: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/cpmsg +Source20: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/folderxfer +Source21: ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/inboxfer +Source22: http://email.uoa.gr/download/cyrus/cyrus_sharedbackup/cyrus_sharedbackup-0.1.tar.gz +Source23: cyrus-imapd-README.RPM +Source24: cyrus-imapd-README.HOWTO-recover-mailboxes.db +Source25: cyrus-imapd.cron-daily +Source26: cyrus-procmailrc +Source27: cyrus-imapd-procmail+cyrus.mc +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.1/cyrus-imapd-2.3.1-autocreate-0.10-0.diff +Patch2: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.1/cyrus-imapd-2.3.1-autosievefolder-0.6-0.diff +Patch3: http://email.uoa.gr/download/cyrus/cyrus-imapd-2.3.1/cyrus-imapd-2.3.1-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.1.15-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 +Patch12: cyrus-imapd-2.2.12-notify_sms.patch +Patch13: allow_auth_plain_proxying.patch +Patch14: cyrus-imapd-2.3.1-authid_normalize.patch +Patch15: cyrus-imapd-2.3.1-make_md5_defaults.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}-root +BuildPrereq: cyrus-sasl-devel >= 2.1.15-1, perl, tcp_wrappers +BuildPrereq: %{_dbver}-devel, openssl-devel, pkgconfig +BuildPrereq: flex, bison, groff >= 1.15-8, automake +%if %{_withldap} +BuildPrereq: openldap-devel +%endif +%if %{SNMP} +BuildPrereq: %{_snmpver}-snmp-devel, lm_sensors-devel %endif +Prereq: e2fsprogs, /sbin/chkconfig, /sbin/service +Prereq: %{name}-utils = %{version}-%{release} +Requires: cyrus-sasl >= 2.1.15, file >= 3.35-1, %{_dbver}-utils +Obsoletes: %{name}-murder, %{name}-nntp %description The %{name} package contains the core of the Cyrus IMAP server. @@ -151,33 +162,24 @@ internet mail technologies. A full Cyrus IMAP implementation allows a seamless mail and bulletin board environment to be set up across multiple servers. It differs from other IMAP server implementations in that it is run on "sealed" -servers, where users are not normally permitted to log in. The mailbox -database is stored in parts of the filesystem that are private to the -Cyrus IMAP server. All user access to mail is through software using -the IMAP, POP3, or KPOP protocols. TLSv1 and SSL are supported for -security. - -%package murder -Group: System Environment/Daemons -Summary: Cyrus IMAP server murder aggregator system files. -Requires: %{name} = %{version}-%{release} - -%description murder -The %{name}-murder package contains the Cyrus murder aggregator system, -i.e. IMAP, POP3 and LMTP proxies, and the mupdate mailbox master daemon. -It allows for cluster setups where there are many backend Cyrus spools -and frontend proxy servers. - -%package nntp -Group: System Environment/Daemons -Summary: Cyrus IMAP server NNTP system files. -Requires: %{name} = %{version}-%{release} - -%description nntp -The %{name}-nntp package contains the Cyrus NNTP server component. -Cyrus has the ability to export Usenet via IMAP and/or export shared IMAP -mailboxes via NNTP. This is made possible by a new NNTP daemon which is -included with Cyrus. +servers, where users are not normally permitted to log in and have no +system account on the server. The mailbox database is stored in parts +of the filesystem that are private to the Cyrus IMAP server. All user +access to mail is through software using the IMAP, POP3 or KPOP +protocols. It also includes support for virtual domains, NNTP, +mailbox annotations, and much more. The private mailbox database design +gives the server large advantages in efficiency, scalability and +administratability. Multiple concurrent read/write connections to the +same mailbox are permitted. The server supports access control lists on +mailboxes and storage quotas on mailbox hierarchies. + +The Cyrus IMAP server supports the IMAP4rev1 protocol described +in RFC 3501. IMAP4rev1 has been approved as a proposed standard. +It supports any authentication mechanism available from the SASL +library, imaps/pop3s/nntps (IMAP/POP3/NNTP encrypted using SSL and +TLSv1) can be used for security. The server supports single instance +store where possible when an email message is addressed to multiple +recipients, SIEVE provides server side email filtering. %package devel Group: Development/Libraries @@ -199,6 +201,7 @@ Cyrus IMAP server administration utilities. %package utils Group: Applications/System Summary: Cyrus IMAP server administration utilities. +Prereq: diffutils, findutils, grep, sed Requires: perl-Cyrus = %{version}-%{release} %description utils @@ -207,8 +210,8 @@ Cyrus IMAP server. It can be installed on systems other than the one running the server. %prep -%setup -q -%patch0 -p0 -b .fdatasync +%setup -q -a 2 +%patch0 -p1 -b .no_transfig %if %{AUTOCREATE} %patch1 -p1 -b .autocreate %patch2 -p1 -b .autosievefolder @@ -223,18 +226,37 @@ one running the server. %if %{GROUPCACHE} %patch8 -p1 -b .groupcache %endif -%if %{OE_SEEN_ST} -%patch9 -p1 -b .oeseenstate -%endif +%patch9 -p1 -b .config_defaults %patch10 -p1 -b .acceptinvalidfrom -%patch50 -p1 +%patch11 -p1 -b .dam_invalid_id +%patch12 -p1 -b .notify_sms +%patch13 -p0 -b .allow_auth_plain +%patch14 -p1 -b .authid_normalize +%patch15 -p1 -b .make_md5_defaults +%patch100 -p1 -b .make_md5 +%patch101 -p1 -b .backend_sigsegv +%patch102 -p1 -b .replication_policycheck + +# build and run private autoconf +autodir=$(pwd)/auto-instroot +pushd autoconf-%{_acversion} +./configure --prefix=$autodir +make all install +popd +PATH=${autodir}/bin:${PATH} +aclocal -I cmulocal +autoheader +autoconf -f %build -# kerberos include is needed (because of openssl-0.9.7 ?) -CPPFLAGS="-I%{_includedir}/et -I%{_prefix}/kerberos/include"; export CPPFLAGS +CPPFLAGS="-I%{_includedir}/et"; export CPPFLAGS CFLAGS="$RPM_OPT_FLAGS -fPIC"; export CFLAGS +if pkg-config openssl; then + CPPFLAGS="$(pkg-config --cflags-only-I openssl) $CPPFLAGS"; export CPPFLAGS + CFLAGS="$(pkg-config --cflags openssl) $CFLAGS"; export CFLAGS + LDFLAGS="$(pkg-config --libs-only-L openssl) $LDFLAGS"; export LDFLAGS +fi CCDLFLAGS="-rdynamic"; export CCDLFLAGS -LDFLAGS="-L%{_prefix}/kerberos/%{_lib}"; export LDFLAGS %if %{USEPIE} %ifnarch ppc ppc64 LDFLAGS="$LDFLAGS -pie"; export LDFLAGS @@ -249,20 +271,30 @@ LDFLAGS="$LDFLAGS -pie"; export LDFLAGS --enable-listext \ %endif %if %{IDLED} - --with-idle=idled \ + --enable-idled \ +%endif +%if %{_withldap} + --with-ldap \ +%endif +%if %{SNMP} + --with-snmp \ +%else + --without-snmp \ %endif --enable-murder \ + --enable-replication \ --enable-nntp \ - --without-snmp \ --with-perl=%{__perl} \ --with-cyrus-prefix=%{_cyrexecdir} \ --with-service-path=%{_cyrexecdir} \ - --with-auth=%{AUTH_METHOD} \ --with-bdb-incdir=%{_includedir}/%{_dbver} \ --with-extraident="Invoca-RPM-%{version}-%{release}" \ --with-syslogfacility=%{SYSLOGFACILITY} +%{__make} -C man -f Makefile.dist +%{__make} -C doc -f Makefile.dist %{__make} +%{__make} -C notifyd notifytest %if %{DEL_WRAP} %{__cc} $CFLAGS -DLIBEXECDIR=\"%{_cyrexecdir}\" -Wall -o deliver-wrapper %{SOURCE3} %endif @@ -286,15 +318,15 @@ find . -type f -name "*.pl" -exec %{__chmod} 755 {} \; # Cleanup of doc dir find doc perl -name CVS -type d | xargs -r %{__rm} -fr +find doc perl -name .cvsignore -type f | xargs -r %{__rm} -f find doc -name "*~" -type f | xargs -r %{__rm} -f -%{__rm} -f doc/Makefile.dist +find doc -name "*.html.*" -type f | xargs -r %{__rm} -f +%{__rm} -f doc/Makefile.dist* %{__rm} -f doc/text/htmlstrip.c # Create README.buildoptions %{__cat} << EOF >> doc/README.buildoptions -This RPM has been compiled on %{_rhrelease} using -Berkeley DB version %{_dbrpmver} with the following source -RPM build options: +This RPM has been built on %{_rhrelease} using the following options: use saslauth group SASLGROUP : %{SASLGROUP} @@ -314,6 +346,9 @@ LISTEXT : %{LISTEXT} enable IDLED support IDLED : %{IDLED} +enable SNMP support +SNMP : %{SNMP} + force syncronous updates on ext3 FORCESYNCEXT3 : %{FORCESYNCEXT3} @@ -332,11 +367,11 @@ SYSLOGFACILITY : %{SYSLOGFACILITY} used -fpie for linking USEPIE : %{USEPIE} -include OutlookExpress seenstate patch -OE_SEEN_ST : %{OE_SEEN_ST} +enable LDAP support +(autodetected) : %{_withldap} -use authorization module METHOD [unix|krb5] -AUTH_METHOD : %{AUTH_METHOD} +Berkeley DB version +(autodetected) : %{_dbrpmver} To modify parameters, edit the .spec file or build like this: @@ -348,12 +383,13 @@ EOF %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 %{__install} -m 644 %{SOURCE9} doc/README.autosievefolder %endif %{__install} -d doc/m4 -%{__install} -m 644 %{SOURCE2} doc/m4/cyrus-procmailrc +%{__install} -m 644 %{SOURCE26} doc/m4/cyrus-procmailrc %{__install} -m 644 %{SOURCE4} doc/m4/cyrus-user-procmailrc.template %{__install} -m 644 %{SOURCE27} doc/m4/%{name}-procmail+cyrus.mc %{__install} -m 644 %{SOURCE29} doc/m4/%{name}-sendmail-8.12.9-cyrusv2.m4 @@ -389,10 +425,11 @@ popd %endif %if %{DEL_WRAP} -%{__install} -m 2755 deliver-wrapper %{buildroot}%{_cyrexecdir}/ +%{__install} -m 2755 deliver-wrapper %{buildroot}%{_cyrexecdir}/ %endif -%{__install} -m 755 imtest/imtest %{buildroot}%{_cyrexecdir}/ -%{__install} -m 755 perl/imap/cyradm %{buildroot}%{_cyrexecdir}/ +%{__install} -m 755 imtest/imtest %{buildroot}%{_bindir}/ +%{__install} -m 755 notifyd/notifytest %{buildroot}%{_bindir}/ +%{__install} -m 755 perl/imap/cyradm %{buildroot}%{_bindir}/ # Install tools for tool in tools/* ; do @@ -403,9 +440,11 @@ done %{__install} -d \ %{buildroot}%{_sysconfdir}/{rc.d/init.d,logrotate.d,pam.d,sysconfig,cron.daily} \ %{buildroot}%{_libdir}/sasl \ - %{buildroot}%{_bindir} \ %{buildroot}%{_spooldata} \ - %{buildroot}%{_vardata}/{user,quota,proc,log,msg,socket,db,sieve,rpm,backup} \ + %{buildroot}%{_vardata}/{user,quota,proc,log,msg,socket,db,sieve,sync,md5,rpm,backup} \ +%if %{_withldap} + %{buildroot}%{_vardata}/ptclient \ +%endif %{buildroot}%{_datadir}/%{name}/rpm \ %{buildroot}%{pki_dir} \ %{_contribdir} @@ -417,7 +456,7 @@ done %endif %{__install} -m 755 %{SOURCE28} %{buildroot}%{_cyrexecdir}/rpm_set_permissions %{__install} -m 644 %{SOURCE14} %{buildroot}%{_datadir}/%{name}/rpm/magic -%{__install} -m 644 %{SOURCE10} %{buildroot}%{_datadir}/%{name}/rpm/db.cfg +%{__install} -m 644 %{SOURCE10} %{_contribdir}/ %{__install} -m 644 %{SOURCE15} %{_contribdir}/imapcreate %{__install} -m 644 %{SOURCE16} %{_contribdir}/cyrus_ldap_quota %{__install} -m 644 %{SOURCE17} %{_contribdir}/batchreconstruct @@ -437,6 +476,7 @@ done %{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/mupdate %{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/lmtp %{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/nntp +%{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/csync %{__install} -m 644 %{SOURCE12} %{buildroot}%{_sysconfdir}/sysconfig/%{name} %{__install} -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/logrotate.d/%{name} %{__install} -m 755 %{SOURCE25} %{buildroot}%{_sysconfdir}/cron.daily/%{name} @@ -446,14 +486,20 @@ done %{__install} -m 755 -d doc/conf %{__install} -m 644 %{_confdir}/*.conf doc/conf/ +# Generate db config file +( grep '^{' lib/imapoptions | grep _db | cut -d'"' -f 2,4 | \ + sed -e 's/^ *//' -e 's/-nosync//' -e 's/ *$//' -e 's/"/=/' + echo sieve_version=2.2.3 ) | sort > %{buildroot}%{_datadir}/%{name}/rpm/db.cfg + # create the ghost pem file touch %{buildroot}%{ssl_pem_file} +%if %{use_etc_pki} # change config file so ssl certificates are under /etc rather than /usr/share %{__perl} -pi -e \ -'s@/usr/share/ssl/certs/cyrus-imapd.pem@%{ssl_pem_file}@g; \ +'s@/usr/share/ssl/certs/%{name}.pem@%{ssl_pem_file}@g; \ s@/usr/share/ssl/certs/ca-bundle.crt@/etc/pki/tls/certs/ca-bundle.crt@' \ %{buildroot}%{_sysconfdir}/imapd.conf - +%endif # Rename 'master' binary and manpage to avoid crash with postfix %{__mv} -f %{buildroot}%{_cyrexecdir}/master %{buildroot}%{_cyrexecdir}/cyrus-master @@ -477,10 +523,6 @@ touch %{buildroot}%{ssl_pem_file} %{__perl} -pi -e 's/Fetchnews/Cyrfetchnews/g' doc/man/cyrfetchnews.8.html %{__perl} -pi -e 's/FETCHNEWS/CYRFETCHNEWS/g' doc/man/cyrfetchnews.8.html -# Create symlinks -%{__ln_s} -f %{_exec_prefix}/lib/%{name}/cyradm %{buildroot}%{_bindir}/ -%{__ln_s} -f %{_exec_prefix}/lib/%{name}/imtest %{buildroot}%{_bindir}/ - # Create filelist for perl package, compress manpages before [ -x /usr/lib/rpm/brp-compress ] && /usr/lib/rpm/brp-compress find %{buildroot}%{perl_sitearch}/Cyrus %{buildroot}%{perl_sitearch}/auto/Cyrus -type f -print | @@ -499,7 +541,7 @@ fi # Remove installed but not packaged files %{__rm} -f %{buildroot}%{_cyrexecdir}/not-mkdep -%{__rm} -f %{buildroot}%{_cyrexecdir}/config2header +%{__rm} -f %{buildroot}%{_cyrexecdir}/config2header* %{__rm} -f %{buildroot}%{_cyrexecdir}/config2man %{__rm} -f %{buildroot}%{_cyrexecdir}/pop3proxyd find %{buildroot} -name "perllocal.pod" -exec %{__rm} -f {} \; @@ -508,6 +550,9 @@ find %{buildroot} -name ".packlist" -exec %{__rm} -f {} \; %{__rm} -f %{buildroot}%{_mandir}/man8/idled.8* %{__rm} -f doc/man/idled.8.html %endif +%{__rm} -f doc/text/Makefile +%{__rm} -f %{buildroot}%{_mandir}/man8/syncnews.8* +%{__rm} -f doc/man/syncnews.8.html # On RedHat 7.3, this file is created here %{__rm} -f /perllocal.pod @@ -516,15 +561,6 @@ find %{buildroot} -name ".packlist" -exec %{__rm} -f {} \; [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} %pre -# Create 'cyrus' user on target host -%if %{SASLGROUP} -/usr/sbin/groupadd -g %{gid} -r %{_saslgroup} 2> /dev/null || : -/usr/sbin/useradd -c "Cyrus IMAP Server" -d %{_vardata} -g %{_cyrusgroup} \ - -G %{_saslgroup} -s /bin/bash -u %{uid} -r %{_cyrususer} 2> /dev/null || : -%else -/usr/sbin/useradd -c "Cyrus IMAP Server" -d %{_vardata} -g %{_cyrusgroup} \ - -s /bin/bash -u %{uid} -r %{_cyrususer} 2> /dev/null || : -%endif # Let postun know whether cyrus-imapd was running if [ -e /var/lock/subsys/cyrus-imapd ]; then /sbin/service %{name} stop >/dev/null 2>&1 || : @@ -534,30 +570,6 @@ fi %post /sbin/chkconfig --add %{name} -# Create SSL certificates -exec > /dev/null 2> /dev/null -# if the certificate is only in the old location, move it to the new location -if [ -f %{_datadir}/ssl/certs/%{name}.pem -a ! %{ssl_pem_file} ]; then -mv %{_datadir}/ssl/certs/%{name}.pem %{ssl_pem_file} -fi -if [ ! -f %{ssl_pem_file} ]; then -pushd /etc/pki/tls/certs -umask 077 -%{__cat} << EOF | make %{name}.pem --- -SomeState -SomeCity -SomeOrganization -SomeOrganizationalUnit -localhost.localdomain -root@localhost.localdomain -EOF -%{__chown} root.%{_cyrusgroup} %{name}.pem -%{__chmod} 640 %{name}.pem -mv %{name}.pem %{ssl_pem_file} -popd -fi - # Force synchronous updates, usually only on ext2 filesystems for i in %{_vardata}/{user,quota} %{_spooldata} do @@ -586,14 +598,104 @@ fi fi %endif +%if %{use_etc_pki} +# change existing config so ssl certificates are under /etc rather than /usr/share +%{__perl} -pi -e \ +'s@/usr/share/ssl/certs/%{name}.pem@%{ssl_pem_file}@g; \ + s@/usr/share/ssl/certs/ca-bundle.crt@/etc/pki/tls/certs/ca-bundle.crt@' \ + %{_sysconfdir}/imapd.conf +%endif + %preun if [ $1 = 0 ]; then /sbin/service %{name} stop >/dev/null 2>&1 || : /sbin/chkconfig --del %{name} - %{__rm} -f %{_vardata}/socket/lmtp 2> /dev/null + %{__rm} -f %{_vardata}/socket/* 2> /dev/null + %{__rm} -f %{_vardata}/proc/* 2> /dev/null +%if %{_withldap} + %{__rm} -f %{_vardata}/ptclient/ptsock 2> /dev/null +%endif fi %postun +if [ $1 != 0 ]; then + /sbin/service %{name} condrestart >/dev/null 2>&1 || : +fi + +%pre utils +# Create 'cyrus' user on target host +%if %{SASLGROUP} +/usr/sbin/groupadd -g %{gid} -r %{_saslgroup} 2> /dev/null || : +/usr/sbin/useradd -c "Cyrus IMAP Server" -d %{_vardata} -g %{_cyrusgroup} \ + -G %{_saslgroup} -s /bin/bash -u %{uid} -r %{_cyrususer} 2> /dev/null || : +%else +/usr/sbin/useradd -c "Cyrus IMAP Server" -d %{_vardata} -g %{_cyrusgroup} \ + -s /bin/bash -u %{uid} -r %{_cyrususer} 2> /dev/null || : +%endif + +%post utils +# Create SSL certificates +exec > /dev/null 2> /dev/null +%if %{use_etc_pki} +# if the certificate is only in the old location, move it to the new location +if [ -f %{_datadir}/ssl/certs/%{name}.pem -a ! -f %{ssl_pem_file} ]; then +mv %{_datadir}/ssl/certs/%{name}.pem %{ssl_pem_file} +fi +%endif +if [ ! -f %{ssl_pem_file} ]; then +pushd %{certs_dir} +umask 077 +%{__cat} << EOF | make %{name}.pem +-- +SomeState +SomeCity +SomeOrganization +SomeOrganizationalUnit +localhost.localdomain +root@localhost.localdomain +EOF +%{__chown} root.%{_cyrusgroup} %{name}.pem +%{__chmod} 640 %{name}.pem +%if %{use_etc_pki} +mv %{name}.pem %{ssl_pem_file} +%endif +popd +fi + +# Add service entries if necessary +if ! %{__grep} -q ^lmtp %{_sysconfdir}/services; then + echo -e 'lmtp\t\t24/tcp\t\t\t\t# LMTP Mail Delivery over TCP' >> %{_sysconfdir}/services + echo -e 'lmtp\t\t24/udp\t\t\t\t# LMTP Mail Delivery over TCP' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^nntps %{_sysconfdir}/services; then + echo -e 'nntps\t\t563/tcp\t\t\t\t# NNTP over SSL' >> %{_sysconfdir}/services + echo -e 'nntps\t\t563/udp\t\t\t\t# NNTP over SSL' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^pop3s %{_sysconfdir}/services; then + echo -e 'pop3s\t\t995/tcp\t\t\t\t# POP-3 over SSL' >> %{_sysconfdir}/services + echo -e 'pop3s\t\t995/udp\t\t\t\t# POP-3 over SSL' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^imaps %{_sysconfdir}/services; then + echo -e 'imaps\t\t993/tcp\t\t\t\t# IMAP over SSL' >> %{_sysconfdir}/services + echo -e 'imaps\t\t993/udp\t\t\t\t# IMAP over SSL' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^sieve %{_sysconfdir}/services; then + echo -e 'sieve\t\t2000/tcp\t\t\t# Sieve Mail Filter Daemon' >> %{_sysconfdir}/services + echo -e 'sieve\t\t2000/udp\t\t\t# Sieve Mail Filter Daemon' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^csync %{_sysconfdir}/services; then + echo -e 'csync\t\t2005/tcp\t\t\t# Cyrus IMAP Replication Daemon' >> %{_sysconfdir}/services + echo -e 'csync\t\t2005/udp\t\t\t# Cyrus IMAP Replication Daemon' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^mupdate %{_sysconfdir}/services; then + echo -e 'mupdate\t\t3905/tcp\t\t\t# Cyrus IMAP Mupdate Daemon' >> %{_sysconfdir}/services + echo -e 'mupdate\t\t3905/udp\t\t\t# Cyrus IMAP Mupdate Daemon' >> %{_sysconfdir}/services +fi +if ! %{__grep} -q ^fud %{_sysconfdir}/services; then + echo -e 'fud\t\t4201/udp\t\t\t# Cyrus IMAP FUD Daemon' >> %{_sysconfdir}/services +fi + +%postun utils if [ $1 = 0 ]; then /usr/sbin/userdel %{_cyrususer} 2> /dev/null || : %if %{SASLGROUP} @@ -601,8 +703,6 @@ if [ $1 = 0 ]; then /usr/sbin/groupdel %{_saslgroup} 2> /dev/null || : fi %endif -else - /sbin/service %{name} condrestart >/dev/null 2>&1 || : fi %files @@ -616,6 +716,9 @@ fi %config(noreplace) %{_sysconfdir}/pam.d/imap %config(noreplace) %{_sysconfdir}/pam.d/sieve %config(noreplace) %{_sysconfdir}/pam.d/lmtp +%config(noreplace) %{_sysconfdir}/pam.d/mupdate +%config(noreplace) %{_sysconfdir}/pam.d/csync +%config(noreplace) %{_sysconfdir}/pam.d/nntp %attr(0755,root,root) %config %{_sysconfdir}/cron.daily/%{name} %dir %{_cyrexecdir} %attr(0755,root,root) %{_cyrexecdir}/arbitron @@ -638,6 +741,7 @@ fi %attr(0755,root,root) %{_cyrexecdir}/masssievec %attr(0755,root,root) %{_cyrexecdir}/mbexamine %attr(0755,root,root) %{_cyrexecdir}/mbpath +%attr(0755,root,root) %{_cyrexecdir}/migrate-metadata %attr(0755,root,root) %{_cyrexecdir}/mkimap %attr(0755,root,root) %{_cyrexecdir}/mknewsgroups %attr(0755,root,root) %{_cyrexecdir}/notifyd @@ -652,6 +756,7 @@ fi %attr(0755,root,root) %{_cyrexecdir}/tls_prune %attr(0755,root,root) %{_cyrexecdir}/translatesieve %attr(0755,root,root) %{_cyrexecdir}/undohash +%attr(0755,root,root) %{_cyrexecdir}/unexpunge %attr(0755,root,root) %{_cyrexecdir}/upgradesieve %attr(0755,root,root) %{_cyrexecdir}/cvt_cyrusdb_all %if %{GROUPCACHE} @@ -664,6 +769,20 @@ fi %if %{AUTOCREATE} %attr(0755,root,root) %{_cyrexecdir}/compile_sieve %endif +%attr(0755,root,root) %{_cyrexecdir}/mupdate +%attr(0755,root,root) %{_cyrexecdir}/mupdate-loadgen.pl +%attr(0755,root,root) %{_cyrexecdir}/proxyd +%attr(0755,root,root) %{_cyrexecdir}/make_md5 +%attr(0755,root,root) %{_cyrexecdir}/sync_client +%attr(0755,root,root) %{_cyrexecdir}/sync_reset +%attr(0755,root,root) %{_cyrexecdir}/sync_server +%attr(0755,root,root) %{_cyrexecdir}/cyrfetchnews +%attr(0755,root,root) %{_cyrexecdir}/nntpd +%if %{_withldap} +%attr(0755,root,root) %{_cyrexecdir}/ptdump +%attr(0755,root,root) %{_cyrexecdir}/ptexpire +%attr(0755,root,root) %{_cyrexecdir}/ptloader +%endif %if %{DEL_WRAP} %attr(2755,%{_cyrususer},%{_cyrusgroup}) %{_cyrexecdir}/deliver-wrapper %endif @@ -676,8 +795,13 @@ fi %attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/msg %attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/db %attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/sieve +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/sync +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/md5 %attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/rpm %attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/backup +%if %{_withldap} +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/ptclient +%endif %attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_spooldata} %dir %{_datadir}/%{name} %dir %{_datadir}/%{name}/rpm @@ -686,22 +810,11 @@ fi %{_mandir}/man8/* %doc COPYRIGHT README %doc doc/* +%if %{use_etc_pki} %dir %{pki_dir} +%endif %attr(0640,root,%{_cyrusgroup}) %ghost %config(missingok,noreplace) %verify(not md5 size mtime) %{ssl_pem_file} -%files murder -%defattr(0644,root,root,0755) -%config(noreplace) %{_sysconfdir}/pam.d/mupdate -%attr(0755,root,root) %{_cyrexecdir}/lmtpproxyd -%attr(0755,root,root) %{_cyrexecdir}/mupdate -%attr(0755,root,root) %{_cyrexecdir}/proxyd - -%files nntp -%defattr(0644,root,root,0755) -%config(noreplace) %{_sysconfdir}/pam.d/nntp -%attr(0755,root,root) %{_cyrexecdir}/cyrfetchnews -%attr(0755,root,root) %{_cyrexecdir}/nntpd - %files devel %defattr(0644,root,root,0755) %{_includedir}/cyrus @@ -716,13 +829,158 @@ fi %files utils %defattr(0644,root,root,0755) -%attr(0755,root,root) %{_cyrexecdir}/cyradm -%attr(0755,root,root) %{_cyrexecdir}/imtest -%attr(0755,root,root) %{_cyrexecdir}/mupdate-loadgen.pl %attr(0755,root,root) %{_bindir}/* %{_mandir}/man1/* %changelog +* Wed Jan 25 2006 Simon Matter 2.3.1-2 +- add backend_sigsegv patch +- add replication_policycheck patch + +* Mon Jan 23 2006 Simon Matter 2.3.1-1 +- update to official autocreate and autosievefolder patches + +* Thu Jan 19 2006 Simon Matter 2.3.1-0.18 +- update rpm_set_permissions script +- add snmp support as build time option, disabled by default + because it doesn't build on older distributions + +* Wed Jan 18 2006 Simon Matter 2.3.1-0.15 +- add make_md5 patch + +* Mon Jan 16 2006 Simon Matter 2.3.1-0.13 +- add autosievefolder patch +- add rmquota+deletemailbox patch +- change default path for make_md5, add md5 directory + +* Fri Jan 13 2006 Simon Matter 2.3.1-0.10 +- spec file cleanup +- add more cvt_cyrusdb_all fixes +- fix pre/post scripts +- fix requirements +- add patch to set Invoca RPM config defaults +- add sync directory used for replication +- add autocreate patch + +* Thu Jan 12 2006 Simon Matter 2.3.1-0.8 +- update cvt_cyrusdb_all script +- build db.cfg on the fly + +* Thu Jan 05 2006 Simon Matter 2.3.1-0.5 +- create ptclient directory if ldap enabled + +* Wed Jan 04 2006 Simon Matter 2.3.1-0.4 +- build without ldap support if openldap is linked against SASLv1 + +* Tue Jan 03 2006 Simon Matter 2.3.1-0.3 +- fix ldap support + +* Mon Jan 02 2006 Simon Matter 2.3.1-0.2 +- add openldap-devel to buildprereq, build with ldap support + +* Wed Dec 21 2005 Simon Matter 2.3.1-0.1 +- update to 2.3.1, officially called BETA-quality release + +* Fri Dec 16 2005 Simon Matter 2.3.0-0.4 +- add skiplist.py to contrib/ +- port authid_normalize patch + +* Thu Dec 15 2005 Simon Matter 2.3.0-0.3 +- reintroduce subpackage utils, fix requirements +- move some utils to %{_bindir}/ + +* Wed Dec 14 2005 Simon Matter 2.3.0-0.2 +- integrate subpackages murder, nntp, replication, utils + +* Tue Dec 13 2005 Simon Matter 2.3.0-0.1 +- update to 2.3.0, officially called BETA-quality release +- add replication subpackage + +* Fri Dec 09 2005 Simon Matter 2.2.12-15.1 +- add missing automake to buildprereq +- change package description + +* Tue Dec 06 2005 Simon Matter 2.2.12-15 +- update cvt_cyrusdb_all script +- update autocreate patches + +* Mon Dec 05 2005 Simon Matter 2.2.12-14 +- update cvt_cyrusdb_all script + +* Mon Nov 14 2005 Simon Matter 2.2.12-13 +- add 64bit quota support backported from 2.3 + +* Fri Nov 11 2005 Simon Matter 2.2.12-12 +- add quickstart/stop option to init script to bypass db import/export +- add authid_normalize patch +- add allow_auth_plain_proxying patch +- update gcc4 patch +- remove useless fdatasync patch +- add private autoconf used for build, remove autoconf dependency +- generate correct docs including man pages +- remove unneeded files from doc directory + +* Fri Nov 04 2005 Simon Matter 2.2.12-11 +- add mupdate thread-safe patch + +* Mon Oct 24 2005 Simon Matter 2.2.12-9.4 +- add spool patch, which is already fixed in CVS + +* Tue Aug 30 2005 Simon Matter 2.2.12-9.2 +- pull in CPPFLAGS and LDFLAGS from openssl's pkg-config data, if it exists + +* Wed Aug 24 2005 Simon Matter 2.2.12-9.1 +- add timsieved_reset_sasl_conn patch + +* Mon Aug 22 2005 Simon Matter 2.2.12-9 +- cosmetic changes in pre and post scripts + +* Fri Aug 19 2005 Simon Matter 2.2.12-8 +- add more pki dir fixes for inplace upgrades + +* Thu Aug 18 2005 Simon Matter 2.2.12-7 +- include requirement for Berkeley DB utils + +* Thu Aug 18 2005 Simon Matter 2.2.12-6 +- fix recovery problems with db4, which do not exist with db3 +- fix logic for handling ssl certs +- remove initlog from init script + +* Wed Aug 17 2005 Simon Matter 2.2.12-5 +- add notifytest to the distribution +- add functionality to convert all berkeley databases to skiplist + on shutdown and convert them back as needed on startup. This should + solve the upgrade problems with Berkeley databases. + +* Tue Aug 16 2005 Simon Matter 2.2.12-4.14 +- add gcc4 patch +- determine and handle pki directory for openssl correctly +- add skiplist recovery docs +- add notify_sms patch + +* Mon Jul 18 2005 Simon Matter 2.2.12-4.10 +- update cvt_cyrusdb_all script +- update autocreate patches + +* Fri Jul 15 2005 Simon Matter 2.2.12-4.9 +- add patch to remove ACLs with invalid identifier +- update cvt_cyrusdb_all script + +* Sat Jun 18 2005 Simon Matter 2.2.12-4.1 +- update munge8bit patch + +* Wed Jun 08 2005 Simon Matter 2.2.12-4 +- updated seenstate patch + +* Thu Jun 02 2005 Simon Matter +- removed nolinkimapspool patch, added singleinstancestore patch instead + +* Thu Jun 02 2005 Simon Matter +- added nolinkimapspool patch +- fix debug_package macro, it was still being expanded, + comments don't hide macro expansion +- change license field to BSD, its not exact BSD, but BSD is the closest + * Fri Apr 22 2005 John Dennis - 2.2.12-6.fc4 - the openssl package moved all its certs, CA, Makefile, etc. to /etc/pki now we are consistent with the openssl directory changes. @@ -748,6 +1006,9 @@ fi * Mon Apr 4 2005 John Dennis - 2.2.12-1.1.fc4 - bring up to 2.2.12, includes security fix for CAN-2005-0546 +* Mon Mar 07 2005 Simon Matter +- updated rmquota+deletemailbox patches + * Fri Mar 4 2005 John Dennis - 2.2.10-11.4.fc4 - fix gcc4 build problems @@ -830,7 +1091,7 @@ fi fixes bug #139382, security advisories: CAN-2004-1011 CAN-2004-1012 CAN-2004-1013 CAN-2004-1015 -* Tue Nov 24 2004 Simon Matter +* Wed Nov 24 2004 Simon Matter - updated to 2.2.10 * Tue Nov 23 2004 Simon Matter diff --git a/skiplist.py b/skiplist.py new file mode 100644 index 0000000..b0a9cfb --- /dev/null +++ b/skiplist.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# -*- Mode: Python; tab-width: 4 -*- +# +# Cyrus Imapd Skiplist db recovery tool +# +# Copyright (C) 2004 Gianluigi Tiesi +# Copyright (C) 2004 NetFarm S.r.l. [http://www.netfarm.it] +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# ====================================================================== + +__version__= '0.1' +__doc__="""Cyrus skiplist db recover""" + +from sys import argv,exit,stdout,stderr +from struct import unpack +from time import localtime, strftime + +### User Conf +debug = 0 +### + +TIMEFMT ='%a, %d %b %Y %H:%M:%S %z' +PADDING = '\xff' * 4 +INORDER = 1 +ADD = 2 +DELETE = 4 +COMMIT = 255 +DUMMY = 257 +HEADER = -1 +MAIN = -2 + +types = { + 1: 'INORDER', + 2: 'ADD', + 4: 'DELETE', + 255: 'COMMIT', + 257: 'DUMMY', + -1: 'HEADER', + -2: '*' + } + +def log(rtype, text): + global debug + if debug: + out = '[%s] %s\n' % (types[rtype], text) + stdout.write(out) + stdout.flush() + +def roundto4(value): + if value % 4: + return ((value / 4) + 1) * 4 + return value + +def get_header(fp): + #### Magic ?? + fp.seek(4) + + sign = fp.read(16) + log(HEADER, sign[:-3]) + + version = unpack('>I', fp.read(4))[0] + version_minor = unpack('>I', fp.read(4))[0] + + log(HEADER, 'Version %d,%d' % (version, version_minor)) + + maxlevel = unpack('>I', fp.read(4))[0] + curlevel = unpack('>I', fp.read(4))[0] + + log(HEADER, 'Level %d/%d' % (curlevel, maxlevel)) + + listsize = unpack('>I', fp.read(4))[0] + log(HEADER, 'List size %d' % listsize) + + logstart = unpack('>I', fp.read(4))[0] + log(HEADER, 'Offset %d' % logstart) + + lastrecovery = localtime(unpack('>I', fp.read(4))[0]) + lastrecovery = strftime(TIMEFMT, lastrecovery) + + log(HEADER, 'Last Recovery %s' % lastrecovery) + + return { 'version' : [version, version_minor], + 'level' : [curlevel, maxlevel], + 'listsize' : listsize, + 'logstart' : logstart, + 'lastrecover': lastrecovery + } + +def getkeys(fp): + values = [] + keys = {} + keystring = '' + datastring = '' + + while 1: + log(MAIN, '-'*78) + + stype = fp.read(4) + + ### EOF + if len(stype) != 4: + break + + rtype = unpack('>I', stype)[0] + if not types.has_key(rtype): + log(MAIN, 'Invalid type %d' % rtype) + continue + + log(rtype, 'Record type %s' % types[rtype]) + + if rtype == DELETE: + ptr = unpack('>I', fp.read(4))[0] + log(rtype, 'DELETE %d (0x%x)' % (ptr, ptr)) + continue + + if rtype == COMMIT: + continue + + ksize = unpack('>I', fp.read(4))[0] + log(rtype, 'Key size %d (%d)' % (ksize, roundto4(ksize))) + + if ksize: + keystring = fp.read(roundto4(ksize))[:ksize] + log(rtype, 'Key String %s' % keystring) + + datasize = unpack('>I', fp.read(4))[0] + log(rtype, 'Data size %d (%d)' % (datasize, roundto4(datasize))) + + if datasize: + datastring = fp.read(roundto4(datasize))[:datasize] + log(rtype, 'Data String %s' % datastring) + + n = 0 + while 1: + str_p = fp.read(4) + if str_p == PADDING: + break + spointer = unpack('>I', str_p)[0] + n = n +1 + if spointer: log(rtype, 'Skip pointer %d' % spointer) + + log(rtype, 'Total Skip pointers: %d' % n) + + if rtype != DUMMY: + if keystring not in values: + values.append(keystring) + keys[keystring] = datastring + + return values, keys + +if __name__ == '__main__': + if len(argv) != 2: + print 'Usage: %s skiplist.file' % argv[0] + exit() + + fp = open(argv[1], 'rb') + header = get_header(fp) + values, keys = getkeys(fp) + fp.close() + + if debug: exit() + for v in values: + print '%s\t%s' % (v, keys[v]) diff --git a/sources b/sources index 2e4c021..3cf4528 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -70b3bba526a8d36d3bb23a87d37e9188 cyrus-imapd-2.2.12.tar.gz +cde15876d5c953bba9ad9f7811aff695 cyrus-imapd-2.3.1.tar.gz 8f7a26b0556369827bb5c8084a3e3ea1 cyrus_sharedbackup-0.1.tar.gz