From d0d307a19fc263c8fabf0392ad88eeaf27d3f4e3 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Apr 15 2005 20:24:15 +0000 Subject: auto-import cyrus-imapd-2.2.12-1.2.fc4 on branch devel from cyrus-imapd-2.2.12-1.2.fc4.src.rpm --- diff --git a/.cvsignore b/.cvsignore index e69de29..ccc5846 100644 --- a/.cvsignore +++ b/.cvsignore @@ -0,0 +1,3 @@ +cyrus-imapd-2.2.12.tar.gz +cyrus-imapd-README.HOWTO-recover-mailboxes.db +cyrus_sharedbackup-0.1.tar.gz diff --git a/README.autocreate-cyrus-2.2 b/README.autocreate-cyrus-2.2 new file mode 100644 index 0000000..f7d8291 --- /dev/null +++ b/README.autocreate-cyrus-2.2 @@ -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 --git a/README.autosievefolder b/README.autosievefolder new file mode 100644 index 0000000..3482bb1 --- /dev/null +++ b/README.autosievefolder @@ -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 --git a/batchreconstruct b/batchreconstruct new file mode 100644 index 0000000..1b5f7ae --- /dev/null +++ b/batchreconstruct @@ -0,0 +1,32 @@ +#!/usr/bin/perl +# +# Usage: batchreconstruct inputfile +# +# Purpose: Runs the Cyrus reconstruct command on each newly-created +# Cyrus mailbox created by folderxfer +# +# Input: List of usernames, one per line +# +#$Id: batchreconstruct,v 1.1 2005/04/15 20:24:15 jdennis Exp $ + +#$whoami = "/usr/ucb/whoami"; # Solaris +$whoami = "/usr/bin/whoami"; +$reconstruct = "/usr/lib/cyrus-imapd/reconstruct"; +$cmd = "$reconstruct -r"; + +chop ($iam = `$whoami`); +if ($iam ne "cyrus" ) { + die "You must be cyrus to run this script!\n"; +} + +$users = "$ARGV[0]"; +if (!$users) { die "Usage: $0 input_file\n"; } + +open(MB,"$users") || die "can't open $users"; + +while () { + chop; + system("$cmd user.$_"); +} +close MB; + diff --git a/bsd2cyrus b/bsd2cyrus new file mode 100644 index 0000000..35f91a1 --- /dev/null +++ b/bsd2cyrus @@ -0,0 +1,81 @@ +#!/usr/bin/perl + eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}' + if $running_under_some_shell; +# +# Usage: bsd2cyrus inputfile +# +# Purpose: Maps a user's Berkeley-format mail folder names into the +# Cyrus namespace +# +# Input: List of usernames, one per line +# +# Output: Lines of the format +# username:Cyrus-mailbox-name:BSD-mailbox-name +# +#$Id: bsd2cyrus,v 1.1 2004/02/04 12:59:42 karsten Exp $ + +require "find.pl"; + +# User's subdirectory where personal mail folders are stored +# (typically $HOME/mail) +$maildir = "mail"; + +$inputfile = "$ARGV[0]"; +if (! $inputfile) { die "Usage: $0 inputfile\n"; } + +open (DATA, $inputfile) || die "can't open $inputfile"; +while () { + chop; + ($user,$pw,$uid,$gid,$quota,$cmnt,$gcos,$home) = getpwnam $_; + next if $home eq ""; + &find("$home/$maildir"); +} +close DATA; + +foreach (@folders) { + + ($user,$folder) = split(/:/,$_,2); + if (! rfc822($folder) ) { next; } + @tokens = split(/\//, $folder); + $mailbox = $tokens[$#tokens]; + + # Sanity checks - earlier tests should have caught these. + + next if ($mailbox =~ /\.gz$/); # Skip gzipped files + next if ($mailbox =~ /\.Z$/); # Skip compressed files + next if ($mailbox =~ /^\./); # Skip hidden files + + # Replace "bad" characters with an underscore followed by + # the ASCII representation of the "bad" character. + + $mailbox = rm_badchars($mailbox); + print "$user:user.$user.$mailbox:$folder\n"; +} + +sub wanted { + (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && + -f _; + if ($_ ne '.') { push @folders, "$user:$dir/$_"; } +} + +sub rfc822 { + + my ($file) = @_; + my ($rc) = 1; + if (-d $file || -z $file || -B $file || -x $file) { + $rc = 0; + } + return $rc; +} + +sub rm_badchars { + + my ($mailbox) = @_; + $mailbox =~ s/ /_040/g; + $mailbox =~ s/\!/_041/g; + $mailbox =~ s/\"/_042/g; + $mailbox =~ s/\#/_043/g; + + return $mailbox; +} + diff --git a/cpmsg b/cpmsg new file mode 100644 index 0000000..205714c --- /dev/null +++ b/cpmsg @@ -0,0 +1,26 @@ +#!/usr/bin/perl +# +# Usage: cat mailbox.txt | formail -s cpmsg +# +# where 'cpmsg' is the name of this script +# +# Purpose: Called by formail once for each mail message in a Berkeley- +# format mailbox +# +#$Id: cpmsg,v 1.1 2004/02/04 12:59:42 karsten Exp $ + +$maildir = "$ARGV[0]"; +if (!$maildir) { die "Usage: $0 $maildir"; } + +# Formail increments this number for each message. The +# leading "0"'s must be removed (e.g. 001 becomes 1) + +$filenum = ($ENV{FILENO} - 0) + 1; + +open (OUTFILE,">$maildir/$filenum."); +while () { + chop; + print OUTFILE "$_\015\012"; # Add CRLF to each line! +} +close OUTFILE; + diff --git a/cyrus-deliver-wrapper.c b/cyrus-deliver-wrapper.c new file mode 100644 index 0000000..c69dc50 --- /dev/null +++ b/cyrus-deliver-wrapper.c @@ -0,0 +1,34 @@ +/* + * Wrapper for cyrus 'deliver' to allow anyone to run it - + * I hope this is secure! Should be setgid mail. + */ + +#include +#include +#include +#include +#include + +#ifndef LIBEXECDIR +#define LIBEXECDIR "/usr/lib/cyrus-imapd" +#endif + +int main(int argc, char *argv[]) +{ + char *const envp[] = { NULL }; + struct passwd *ent = getpwuid(getuid()); + const char *uname = (ent && ent->pw_name && ent->pw_name[0]) + ? ent->pw_name : "anonymous"; + + if (argc != 2) { + fprintf(stderr, "Usage: %s mailbox\n", argv[0]); + return EX_USAGE; + } + + execle(LIBEXECDIR"/deliver", "deliver", "-e", + "-a", uname, "-m", argv[1], + NULL, envp); + + perror("exec "LIBEXECDIR"/deliver"); + return EX_OSERR; +} diff --git a/cyrus-imapd-2.1.15-nobarenewlinescheck.patch b/cyrus-imapd-2.1.15-nobarenewlinescheck.patch new file mode 100644 index 0000000..9c3990f --- /dev/null +++ b/cyrus-imapd-2.1.15-nobarenewlinescheck.patch @@ -0,0 +1,12 @@ +--- cyrus-imapd-2.1.15/imap/message.c.orig 2003-11-11 15:45:11.000000000 +0100 ++++ cyrus-imapd-2.1.15/imap/message.c 2003-11-11 15:35:11.000000000 +0100 +@@ -246,7 +246,8 @@ + + for (p = (unsigned char *)buf; *p; p++) { + if (*p == '\n') { +- if (!sawcr) r = IMAP_MESSAGE_CONTAINSNL; ++ /* Do *NOT* check for RFC compliant line breaks (bare newlines) */ ++ /* if (!sawcr) r = IMAP_MESSAGE_CONTAINSNL; */ + sawcr = 0; + if (blankline) { + inheader = 0; diff --git a/cyrus-imapd-2.1.16-getrlimit.patch b/cyrus-imapd-2.1.16-getrlimit.patch new file mode 100644 index 0000000..08b7c3c --- /dev/null +++ b/cyrus-imapd-2.1.16-getrlimit.patch @@ -0,0 +1,23 @@ +--- cyrus-imapd-2.1.16/master/master.c.getrlimit 2003-12-28 17:32:46.000000000 +0100 ++++ cyrus-imapd-2.1.16/master/master.c 2003-12-28 17:43:56.000000000 +0100 +@@ -1208,12 +1208,10 @@ + rl.rlim_cur = x; + rl.rlim_max = x; + if (setrlimit(RLIMIT_NUMFDS, &rl) < 0) { +- syslog(LOG_ERR, "setrlimit: Unable to set file descriptors limit to %ld: %m", x); + + #ifdef HAVE_GETRLIMIT + + if (!getrlimit(RLIMIT_NUMFDS, &rl)) { +- syslog(LOG_ERR, "retrying with %ld (current max)", rl.rlim_max); + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_NUMFDS, &rl) < 0) { + syslog(LOG_ERR, "setrlimit: Unable to set file descriptors limit to %ld: %m", x); +@@ -1228,6 +1226,7 @@ + rl.rlim_max); + } + #else ++ syslog(LOG_ERR, "setrlimit: Unable to set file descriptors limit to %ld: %m", x); + } + #endif /* HAVE_GETRLIMIT */ + } diff --git a/cyrus-imapd-2.1.3-flock.patch b/cyrus-imapd-2.1.3-flock.patch new file mode 100644 index 0000000..b74b99d --- /dev/null +++ b/cyrus-imapd-2.1.3-flock.patch @@ -0,0 +1,77 @@ +--- cyrus-imapd-2.1.3/lib/lock_flock.c Tue Oct 2 16:08:13 2001 ++++ cyrus-imapd-2.1.3-patched/lib/lock_flock.c Tue Apr 16 09:44:58 2002 +@@ -51,6 +51,10 @@ + #endif + + #include "lock.h" ++#include ++ ++/* Locking timeout parameter */ ++#define MAXTIME 99 + + const char *lock_method_desc = "flock"; + +@@ -69,6 +73,18 @@ + * 'failaction' is provided, it is filled in with a pointer to a fixed + * string naming the action that failed. + * ++ * Modified by jwade 4/16/2002 to work around seen file locking problem ++ * Added locking timeout parameter to allow processes that are ++ * waiting for a lock to eventually time out ++ * ++ * Calls flock() in non-blocking fashion and then retries until a ++ * maximum delay is reached or the lock succeeds. ++ * ++ * As written, uses a quadratic backoff on retries with MAXTIME being ++ * the longest interval delay. Total delay time is the sum of the squares ++ * of all integers whose square is less than MAXTIME. In the case of ++ * MAXTIME = 99 this is 0+1+4+9+16+25+36+49+64+81= 285 Seconds ++ * This time is arbitrary and can be adjusted + */ + int lock_reopen(fd, filename, sbuf, failaction) + int fd; +@@ -79,17 +95,29 @@ + int r; + struct stat sbuffile, sbufspare; + int newfd; ++ int delay=0, i=0; + + if (!sbuf) sbuf = &sbufspare; + +- for (;;) { +- r = flock(fd, LOCK_EX); ++ for(i=0,delay=0;;) { ++ r = flock(fd, LOCK_EX|LOCK_NB); + if (r == -1) { +- if (errno == EINTR) continue; +- if (failaction) *failaction = "locking"; ++ if (errno == EINTR) { ++ continue; ++ } ++ else if ((errno == EWOULDBLOCK) && (delay < MAXTIME)) { ++ syslog(LOG_DEBUG, "lock: reopen-blocked sleeping for %d on interval %d (%d, %s)" , delay, i, fd, filename); ++ sleep(delay); ++ i++; ++ delay = i*i; ++ continue; ++ } ++ if (failaction) { ++ if (delay >= MAXTIME) *failaction = "locking_timeout"; ++ else *failaction = "locking"; ++ } + return -1; + } +- + fstat(fd, sbuf); + r = stat(filename, &sbuffile); + if (r == -1) { +@@ -97,9 +125,7 @@ + flock(fd, LOCK_UN); + return -1; + } +- + if (sbuf->st_ino == sbuffile.st_ino) return 0; +- + newfd = open(filename, O_RDWR); + if (newfd == -1) { + if (failaction) *failaction = "opening"; diff --git a/cyrus-imapd-2.1.9-fdatasync.patch b/cyrus-imapd-2.1.9-fdatasync.patch new file mode 100644 index 0000000..c2d4607 --- /dev/null +++ b/cyrus-imapd-2.1.9-fdatasync.patch @@ -0,0 +1,14 @@ +--- 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-groupcache.patch b/cyrus-imapd-2.2.10-groupcache.patch new file mode 100644 index 0000000..4d1a04e --- /dev/null +++ b/cyrus-imapd-2.2.10-groupcache.patch @@ -0,0 +1,43 @@ +diff -Naur cyrus-imapd-2.2.10.orig/lib/auth_unix.c cyrus-imapd-2.2.10/lib/auth_unix.c +--- cyrus-imapd-2.2.10.orig/lib/auth_unix.c Tue Sep 14 00:49:29 2004 ++++ cyrus-imapd-2.2.10/lib/auth_unix.c Thu Dec 16 08:36:32 2004 +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -226,6 +227,10 @@ + struct passwd *pwd; + struct group *grp; + char **mem; ++ FILE *groupcache; ++ char fnamebuf[1024]; ++ const char *config_dir = ++ libcyrus_config_getstring(CYRUSOPT_CONFIG_DIR); + + identifier = auth_canonifyid(identifier, 0); + if (!identifier) return 0; +@@ -242,8 +247,11 @@ + + pwd = getpwnam(identifier); + ++ strcpy(fnamebuf, config_dir); ++ strcat(fnamebuf, "/group.cache"); ++ groupcache = fopen(fnamebuf, "r"); + setgrent(); +- while ((grp = getgrent())) { ++ while (grp = ( (groupcache) ? fgetgrent(groupcache) : getgrent() )) { + for (mem = grp->gr_mem; *mem; mem++) { + if (!strcmp(*mem, identifier)) break; + } +@@ -256,6 +264,7 @@ + } + } + endgrent(); ++ if (groupcache) fclose(groupcache); + return newstate; + } + diff --git a/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.1.diff b/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.1.diff new file mode 100644 index 0000000..a003fc9 --- /dev/null +++ b/cyrus-imapd-2.2.10-rmquota+deletemailbox-0.1.diff @@ -0,0 +1,491 @@ +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 new file mode 100644 index 0000000..b9458dc --- /dev/null +++ b/cyrus-imapd-2.2.12-autocreate-0.9.2.diff @@ -0,0 +1,2159 @@ +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 new file mode 100644 index 0000000..ce672d3 --- /dev/null +++ b/cyrus-imapd-2.2.12-autosievefolder-0.6.diff @@ -0,0 +1,193 @@ +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.tar.gz.sig b/cyrus-imapd-2.2.12.tar.gz.sig new file mode 100644 index 0000000..86a0de7 Binary files /dev/null and b/cyrus-imapd-2.2.12.tar.gz.sig differ diff --git a/cyrus-imapd-2.2.4-OE-seenstate.patch b/cyrus-imapd-2.2.4-OE-seenstate.patch new file mode 100644 index 0000000..b6d0f46 --- /dev/null +++ b/cyrus-imapd-2.2.4-OE-seenstate.patch @@ -0,0 +1,104 @@ +# 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 new file mode 100644 index 0000000..d83c9b0 --- /dev/null +++ b/cyrus-imapd-2.2.4-munge8bit.patch @@ -0,0 +1,109 @@ +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-README.RPM b/cyrus-imapd-README.RPM new file mode 100644 index 0000000..097d6c6 --- /dev/null +++ b/cyrus-imapd-README.RPM @@ -0,0 +1,33 @@ +--------------- +Cyrus IMAPd RPM +--------------- + +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. +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 + directories, like /var/lib/imap and /var/spool/imap +4) Make sure cyrus-sasl 2.x is installed. +5) Make sure saslauthd is running. If not, edit /etc/sysconfig/saslauthd as + 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. +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: + 'cyradm --user=cyrus --auth=login localhost' +11) If you're using sendmail, be aware that cyrusv2.m4 included in standard + sendmail distribution uses socket /var/imap/socket/lmtp while this rpm + uses /var/lib/imap/socket/lmtp. +12) Check your syslog configuration. This RPM uses the mail facility to log + messages. On busy sites you may want to limit the mail facility to the + info priority with something like 'mail.info /var/log/maillog' in + /etc/syslog.conf. + +Enjoy! diff --git a/cyrus-imapd-README.contrib b/cyrus-imapd-README.contrib new file mode 100644 index 0000000..e9a0941 --- /dev/null +++ b/cyrus-imapd-README.contrib @@ -0,0 +1,10 @@ +The programs provided here in the contrib directory are taken from +various places on the net. Sometimes I even don't know where I found +them and the license may also be unclear. If the creator of one of the +scripts doesn't like to see it included in this contrib section, let +me know and I'll remove it from the package. + +I have never used any of the scripts here so I really don't know how +they work or whether there are better ways to complete a task. I've +been told that there are better tools to migrate from UW-IMAP. So be +warned, use at your own risk. diff --git a/cyrus-imapd-README.groupcache b/cyrus-imapd-README.groupcache new file mode 100644 index 0000000..6688541 --- /dev/null +++ b/cyrus-imapd-README.groupcache @@ -0,0 +1,30 @@ +If you have a lot of groups or very large groups, cyrus-imapd login can become +quite slow due to the way cyrus-imapd handles groups. This may become worse +when using nss_ldap or other slow nss backends to resolve groups. +Caching using nscd can increase speed dramatically but unfortunately not for +all functions cyrus-imapd uses. nscd helps speeding up getgrnam() calls but not +getgrent() calls, which are used by cyrus-imapd to get a complete list of all +groups available. +The groupfile patch implements a quick fix to the problem by using a separate +group.cache file to speed up those operations using getgrent() calls. +Calls to getgrnam() are not touched which means that the group.cache +file must be kept in sync with the group source you are using with nss +configured in /etc/nsswitch.conf. If group.cache doesn't exist, +the patch has no effect and cyrus-imapd handles groups through getgrent(). + +Quick HOWTO: +- configure group lookup in /etc/nsswitch.conf if not already done +- configure name service cache in /etc/nscd.conf (not mandatory) +- start nscd with "service nscd start" (not mandatory) +- configure a service which periodically updates the group.cache file using the + upd_groupcache script. Either set up a cronjob or use a event in the cyrus + configuration. + +Sample /etc/cyrus.conf event to update the group cache every 10 minutes: +EVENTS { + # some events removed here *** + ...........................*** + + # this is only necessary if using group cache feature + groupcache cmd="upd_groupcache" period=10 +} diff --git a/cyrus-imapd-acceptinvalidfrom.patch b/cyrus-imapd-acceptinvalidfrom.patch new file mode 100644 index 0000000..b44ab59 --- /dev/null +++ b/cyrus-imapd-acceptinvalidfrom.patch @@ -0,0 +1,34 @@ +--- cyrus-imapd-2.2.6/imap/message.c.acceptinvalidfrom 2004-10-30 15:03:02.220642392 -0700 ++++ cyrus-imapd-2.2.6/imap/message.c 2004-10-30 15:06:01.838336352 -0700 +@@ -229,6 +229,8 @@ + int reject8bit = config_getswitch(IMAPOPT_REJECT8BIT); + int munge8bit = config_getswitch(IMAPOPT_MUNGE8BIT); + int inheader = 1, blankline = 1; ++ char is_from; ++ static const char * from_header = "From "; + + while (size) { + n = prot_read(from, buf, size > 4096 ? 4096 : size); +@@ -294,8 +296,20 @@ + /* Check for valid header name */ + if (sawnl && buf[0] != ' ' && buf[0] != '\t') { + if (buf[0] == ':') return IMAP_MESSAGE_BADHEADER; +- for (p = (unsigned char *)buf; *p != ':'; p++) { +- if (*p <= ' ') return IMAP_MESSAGE_BADHEADER; ++ p = (unsigned char *) buf; ++ if (*p == '>') ++ p++; ++ if (*p == from_header[0]) ++ is_from = 0; ++ else ++ is_from = -1; ++ for (; *p != ':' && is_from < 5; p++) { ++ if (is_from > 0 && *p != from_header[is_from]) ++ is_from = -1; ++ if (is_from >= 0) ++ is_from++; ++ else ++ if (*p <= ' ') return IMAP_MESSAGE_BADHEADER; + } + } + diff --git a/cyrus-imapd-db.cfg b/cyrus-imapd-db.cfg new file mode 100644 index 0000000..cf2e01a --- /dev/null +++ b/cyrus-imapd-db.cfg @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000..b868abe --- /dev/null +++ b/cyrus-imapd-gcc4.patch @@ -0,0 +1,18 @@ +--- 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 < $#cyrusbb $: $1 diff --git a/cyrus-imapd-sendmail-8.12.9-cyrusv2.m4 b/cyrus-imapd-sendmail-8.12.9-cyrusv2.m4 new file mode 100644 index 0000000..7c79f82 --- /dev/null +++ b/cyrus-imapd-sendmail-8.12.9-cyrusv2.m4 @@ -0,0 +1,29 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 2002 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# Contributed by Kenneth Murchison. +# + +_DEFIFNOT(`_DEF_CYRUSV2_MAILER_FLAGS', `lsDFMnqXz') +_DEFIFNOT(`CYRUSV2_MAILER_FLAGS', `A@/:|m') +ifdef(`CYRUSV2_MAILER_ARGS',, `define(`CYRUSV2_MAILER_ARGS', `FILE /var/imap/socket/lmtp')') +define(`_CYRUSV2_QGRP', `ifelse(defn(`CYRUSV2_MAILER_QGRP'),`',`', ` Q=CYRUSV2_MAILER_QGRP,')')dnl + +POPDIVERT + +######################################### +### Cyrus V2 Mailer specification ### +######################################### + +VERSIONID(`$Id: cyrus-imapd-sendmail-8.12.9-cyrusv2.m4,v 1.1 2004/02/04 12:59:42 karsten Exp $') + +Mcyrusv2, P=[IPC], F=_MODMF_(CONCAT(_DEF_CYRUSV2_MAILER_FLAGS, CYRUSV2_MAILER_FLAGS), `CYRUSV2'), + S=EnvFromSMTP/HdrFromL, R=EnvToL/HdrToL, E=\r\n, + _OPTINS(`CYRUSV2_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`CYRUSV2_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`CYRUSV2_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,_CYRUSV2_QGRP + A=CYRUSV2_MAILER_ARGS diff --git a/cyrus-imapd.cron-daily b/cyrus-imapd.cron-daily new file mode 100644 index 0000000..341673e --- /dev/null +++ b/cyrus-imapd.cron-daily @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This file is run on a daily basis to perform a backup of your +# mailbox list which can be used to recreate mailboxes.db from backup. +# Restore is done using ctl_mboxlist after uncompressing the file. + +BACKDIR="/var/lib/imap/backup" +MBOXLIST="${BACKDIR}/mboxlist" +ROTATE=6 + +# fallback to su if runuser not available +if [ -x /sbin/runuser ]; then + RUNUSER=runuser +else + RUNUSER=su +fi + +# source custom configuration +if [ -f /etc/sysconfig/cyrus-imapd ]; then + . /etc/sysconfig/cyrus-imapd +fi + +[ -x /usr/lib/cyrus-imapd/ctl_mboxlist ] || exit 0 + +# rotate mailbox lists +seq $[ $ROTATE - 1 ] 1 | while read i; do + [ -f ${MBOXLIST}.${i}.gz ] && mv -f ${MBOXLIST}.${i}.gz ${MBOXLIST}.$[ $i + 1 ].gz +done +[ -f ${MBOXLIST}.gz ] && mv -f ${MBOXLIST}.gz ${MBOXLIST}.1.gz + +# export mailboxes.db +$RUNUSER - cyrus -c "umask 077 < /dev/null ; /usr/lib/cyrus-imapd/ctl_mboxlist -d | gzip > ${MBOXLIST}.gz" + +exit 0 +# EOF diff --git a/cyrus-imapd.cvt_cyrusdb_all b/cyrus-imapd.cvt_cyrusdb_all new file mode 100644 index 0000000..31c421e --- /dev/null +++ b/cyrus-imapd.cvt_cyrusdb_all @@ -0,0 +1,242 @@ +#!/bin/sh + +# 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 of the License, 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 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# This script converts all db files of a cyrus installation from their +# existing format to the format required by the current installation. +# The format of current db files is determined using the 'file' command +# with a magic file added for skiplist db, the new format is read from +# a config file usually in /usr/share/cyrus-imapd/rpm/db.cfg, which is +# created while compiling. After converting, the db.cfg file is +# copied to a cache file usually at /var/lib/imap/rpm/db.cfg.cache to +# allow bypassing this converting script if both files are identical. +# While this is a bit less secure, it may be useful on big server where +# db converting is done automatically. +# +# This script can safely be run as root, it will reexec itself as user +# cyrus if needed. +# +# author: Simon Matter, Invoca Systems + +# changelog +# v1.0.1, Oct 22 2002 Simon Matter +# - added two-step conversion method +# +# v1.0.2, Jan 10 2003 Simon Matter +# - fixed a bug where cvt_cyrusdb was called to convert empty or +# nonexistent files +# +# v1.0.3, Mar 14 2003 Simon Matter +# - fixed a problem with new versions of the file command +# +# v1.0.4 +# - added GPL license +# +# v1.0.5, May 02 2003 Simon Matter +# - modified exec path +# +# v1.0.6, Jul 18 2003 Simon Matter +# - changed db3 to berkeley +# - added new db backends for 2.2 +# +# v1.0.7, Jan 23 2004 Simon Matter +# - included some modifications from Luca Olivetti +# - added masssievec functionality +# +# v1.0.8, Jan 28 2004 Simon Matter +# - convert sieve scripts to UTF-8 before calling masssievec +# +# v1.0.9, Jan 29 2004 Simon Matter +# - convert sieve scripts to UTF-8 only if sievec failed before +# +# v1.0.10, Feb 24 2004 Simon Matter +# - change su within init script to get input from +# /dev/null, this prevents hang when running in SELinux +# +# v1.0.11, Mar 02 2004 Simon Matter +# - fixed SELinux fix +# +# v1.0.12, Dec 16 2004 Simon Matter +# - use runuser instead of su if available + +if [ -n "$(/sbin/pidof cyrus-master)" ]; then + echo "ERROR: cyrus-master is running, unable to convert mailboxes!" + exit 1 +fi + +if [ ! -f /etc/imapd.conf ]; then + echo "ERROR: configuration file not found." + exit 1 +fi + +# fallback to su if runuser not available +if [ -x /sbin/runuser ]; then + RUNUSER=runuser +else + RUNUSER=su +fi + +# force cyrus user for security reasons +if [ ! $(whoami) = "cyrus" ]; then + exec $RUNUSER - cyrus -c "cd $PWD < /dev/null ; $0" +fi + +# files get mode 0600 +umask 166 + +# 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 | sed -e 's/^ *//' -e 's/-nosync//' -e 's/ *$//' + else + echo $2 + fi +} + +# where to find files and directories +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 +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_current=${imap_prefix}/rpm/db.cfg.current +db_cache=${imap_prefix}/rpm/db.cfg.cache + +# source default db backend config +. $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) + +# 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 + +# file_type [file] +file_type() { + this_type=$(file -b -m "$system_magic:$cyrus_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 + echo flat + else + echo berkeley + fi +} + +# cvt_file [file] [db] +cvt_file() { + target="$1" + new_db="$2" + if [ -s "$target" ]; then + old_db=$(file_type "$target") + 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" + else + $cvt_cyrusdb "$target" "$old_db" "${target}.flat" flat + 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" + else + $cvt_cyrusdb "${target}.flat" flat "$target" "$new_db" + fi + fi + RETVAL=$? + ERRVAL=$[ $ERRVAL + $RETVAL ] + if [ $RETVAL -eq 0 ]; then + rm -f "${target}.flat" + else + echo "ERROR: unable to convert ${target}.flat from flat to $new_db" + fi + else + echo "ERROR: unable to convert $target from $old_db to flat" + fi + fi + fi +} + +# cvt_to_utf8 [file] +cvt_to_utf8() { + target="$1" + if [ -s "$target" ]; then + if ! $sievec "$target" "${target}.sievec"; then + iconv --from-code=ISO-8859-1 --to-code=UTF-8 --output="${target}.UTF-8" "$target" + if [ -s "${target}.UTF-8" ]; then + # preserve timestamp + touch --reference="$target" "${target}.UTF-8" + mv -f "${target}.UTF-8" "$target" + else + ERRVAL=$[ $ERRVAL + 1 ] + fi + fi + rm -f "${target}.sievec" + fi +} + +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 +fi + +# copy the current config file so we can check whether something has changed +if [ $ERRVAL -eq 0 ]; then + mv -f $db_current $db_cache +else + rm -f $db_cache + rm -f $db_current +fi + +exit $ERRVAL diff --git a/cyrus-imapd.imap-2.2.x-conf b/cyrus-imapd.imap-2.2.x-conf new file mode 100644 index 0000000..1d2f16a --- /dev/null +++ b/cyrus-imapd.imap-2.2.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 new file mode 100644 index 0000000..441035d --- /dev/null +++ b/cyrus-imapd.init @@ -0,0 +1,154 @@ +#!/bin/sh +# +# chkconfig: - 65 35 +# description: The Cyrus IMAPD master serves as a master process for the Cyrus \ +# IMAP and POP servers. +# config: /etc/cyrus.conf +# 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 + +# Source function library +if [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +elif [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +else + exit 0 +fi + +# Source networking configuration. +. /etc/sysconfig/network + +# Check that networking is up. +[ ${NETWORKING} = "no" ] && exit 0 + +# check if the config files are present +[ -f /etc/cyrus.conf ] || exit 0 +[ -f /etc/imapd.conf ] || exit 0 + +# This is our service name +BASENAME=$(basename $0) +if [ -L $0 ]; then + BASENAME=$(find $0 -name $BASENAME -printf %l) + BASENAME=$(basename $BASENAME) +fi + +# fallback to su if runuser not available +if [ -x /sbin/runuser ]; then + RUNUSER=runuser +else + RUNUSER=su +fi + +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 +else + echo "$BASENAME: configfile /etc/sysconfig/$BASENAME does NOT exist !" + exit 1 +fi + +RETVAL=0 + +start() { + echo -n $"Starting $BASENAME: " + if [ $(/sbin/pidof -s $CYRUSMASTER) ]; then + echo -n $"$BASENAME already running." + false + 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 [ $RETVAL -eq 0 ]; then + echo -n $"done. " + 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" + fi + fi + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$BASENAME + return $RETVAL +} + +stop() { + echo -n $"Shutting down $BASENAME: " + killproc $CYRUSMASTER + RETVAL=$? + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$BASENAME + echo + return $RETVAL +} + +restart() { + stop + start +} + +reload() { + echo -n $"Reloading cyrus.conf file: " + killproc $CYRUSMASTER -HUP + RETVAL=$? + echo + return $RETVAL +} + +condrestart() { + [ -e /var/lock/subsys/$BASENAME ] && restart || : +} + +rhstatus() { + status $CYRUSMASTER + RETVAL=$? + return $RETVAL +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + reload) + reload + ;; + condrestart) + condrestart + ;; + status) + rhstatus + ;; + *) + echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status}" + RETVAL=1 +esac + +exit $RETVAL diff --git a/cyrus-imapd.logrotate b/cyrus-imapd.logrotate new file mode 100644 index 0000000..d5c9b7a --- /dev/null +++ b/cyrus-imapd.logrotate @@ -0,0 +1,7 @@ +/var/log/imapd.log /var/log/auth.log { + missingok + sharedscripts + postrotate + /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true + endscript +} diff --git a/cyrus-imapd.magic b/cyrus-imapd.magic new file mode 100644 index 0000000..85831fb --- /dev/null +++ b/cyrus-imapd.magic @@ -0,0 +1,9 @@ +# Magic +# Magic data for file(1) command. +# Format is described in magic(files), where: +# files is 5 on V7 and BSD, 4 on SV, and ?? in the SVID. + +#------------------------------------------------------------------------------ +# skiplist: file(1) magic Cyrus skiplist DB +# +0 string \241\002\213\015skiplist\ file\0\0\0 Cyrus skiplist DB diff --git a/cyrus-imapd.pam-config b/cyrus-imapd.pam-config new file mode 100644 index 0000000..6452ee0 --- /dev/null +++ b/cyrus-imapd.pam-config @@ -0,0 +1,3 @@ +#%PAM-1.0 +auth required pam_stack.so service=system-auth +account required pam_stack.so service=system-auth diff --git a/cyrus-imapd.rpm_set_permissions b/cyrus-imapd.rpm_set_permissions new file mode 100644 index 0000000..ab8ea2d --- /dev/null +++ b/cyrus-imapd.rpm_set_permissions @@ -0,0 +1,30 @@ +#!/bin/sh +IMAPCONF=/etc/imapd.conf + +CONFDIR=$(grep -se "^configdirectory:" $IMAPCONF | cut -d":" -f2) +if [ "x$CONFDIR" = "x" ]; then + echo "$0 error: configdirectory not found in /etc/imapd.conf, exiting!" + exit 1 +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 + if [ "x$SPOOLDIR" = "x" ]; then + echo "$0 warning: invalid 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 + if [ "x$SPOOLDIR" = "x" ]; then + echo "$0 warning: invalid partition configuration in /etc/imapd.conf found!" + else + find $SPOOLDIR -type f ! -name "lost+found" -exec chmod 600 {} \; -exec chown cyrus:mail {} \; + fi +done + +# lmtp socket must be accessible by group mail +chmod 750 $CONFDIR +chmod 750 ${CONFDIR}/socket diff --git a/cyrus-imapd.spec b/cyrus-imapd.spec new file mode 100644 index 0000000..454fecb --- /dev/null +++ b/cyrus-imapd.spec @@ -0,0 +1,1266 @@ +Name: cyrus-imapd +Version: 2.2.12 +Release: 1.2.fc4 + +# ********************** BUILD TIME OPTIONS START ********************** + +# To modify parameters, edit the .spec file or build like this: +# rpm --rebuild --define='SEEN_DB skiplist' cyrus-imapd-2.x.x-x.src.rpm + +# use saslauth group +%{!?SASLGROUP: %define SASLGROUP 0} + +# include deliver-wrapper +%{!?DEL_WRAP: %define DEL_WRAP 0} + +# use preforking cyrus.conf +%{!?PREFORK: %define PREFORK 1} + +# enable Netscape hack (recommended) +%{!?NETSCAPEHACK: %define NETSCAPEHACK 1} + +# enable IMAP4 LIST extensions +%{!?LISTEXT: %define LISTEXT 1} + +# enable IDLED support +%{!?IDLED: %define IDLED 1} + +# force syncronous updates on ext3 +%{!?FORCESYNCEXT3: %define FORCESYNCEXT3 0} + +# include autocreate feature +%{!?AUTOCREATE: %define AUTOCREATE 1} + +# include groupcache feature +%{!?GROUPCACHE: %define GROUPCACHE 1} + +# don't check for RFC compliant line termination (bare newlines) +%{!?NO_BARE_NL: %define NO_BARE_NL 0} + +# used syslog facility for logging +%{!?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} + +# ********************** 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}") +# 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) +# Disable -debuginfo package generation +#define debug_package %{nil} + +Summary: A high-performance mail server with IMAP, POP3, NNTP and SIEVE support. +License: OSI Approved +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 +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 +%if %{SASLGROUP} +%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 +%if %{PREFORK} +%define _cyrusconf %{_confdir}/prefork.conf +%else +%define _cyrusconf %{_confdir}/normal.conf +%endif + +%description +The %{name} package contains the core of the Cyrus IMAP server. +It is a scaleable enterprise mail system designed for use from +small to large enterprise environments using standards-based +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. + +%package devel +Group: Development/Libraries +Summary: Cyrus IMAP server development files. +Requires: %{name} = %{version}-%{release} + +%description devel +The %{name}-devel package contains header files and libraries +necessary for developing applications which use the imclient library. + +%package -n perl-Cyrus +Group: System Environment/Libraries +Summary: Cyrus IMAP server utility Perl modules. + +%description -n perl-Cyrus +The perl-Cyrus package contains Perl modules necessary to use the +Cyrus IMAP server administration utilities. + +%package utils +Group: Applications/System +Summary: Cyrus IMAP server administration utilities. +Requires: perl-Cyrus = %{version}-%{release} + +%description utils +The %{name}-utils package contains administrative tools for the +Cyrus IMAP server. It can be installed on systems other than the +one running the server. + +%prep +%setup -q +%patch0 -p0 -b .fdatasync +%if %{AUTOCREATE} +%patch1 -p1 -b .autocreate +%patch2 -p1 -b .autosievefolder +%patch3 -p1 -b .rmquota +%endif +%patch4 -p1 -b .flock +%patch5 -p1 -b .munge8bit +%patch6 -p1 -b .getrlimit +%if %{NO_BARE_NL} +%patch7 -p1 -b .nobarenewlinescheck +%endif +%if %{GROUPCACHE} +%patch8 -p1 -b .groupcache +%endif +%if %{OE_SEEN_ST} +%patch9 -p1 -b .oeseenstate +%endif +%patch10 -p1 -b .acceptinvalidfrom +%patch50 -p1 + +%build +# kerberos include is needed (because of openssl-0.9.7 ?) +CPPFLAGS="-I%{_includedir}/et -I%{_prefix}/kerberos/include"; export CPPFLAGS +CFLAGS="$RPM_OPT_FLAGS -fPIC"; export CFLAGS +CCDLFLAGS="-rdynamic"; export CCDLFLAGS +LDFLAGS="-L%{_prefix}/kerberos/%{_lib}"; export LDFLAGS +%if %{USEPIE} +%ifnarch ppc ppc64 +LDFLAGS="$LDFLAGS -pie"; export LDFLAGS +%endif +%endif + +%{configure} \ +%if %{NETSCAPEHACK} + --enable-netscapehack \ +%endif +%if %{LISTEXT} + --enable-listext \ +%endif +%if %{IDLED} + --with-idle=idled \ +%endif + --enable-murder \ + --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} +%if %{DEL_WRAP} +%{__cc} $CFLAGS -DLIBEXECDIR=\"%{_cyrexecdir}\" -Wall -o deliver-wrapper %{SOURCE3} +%endif + +# Modify docs master --> cyrus-master +pushd man + %{__perl} -pi -e "s@master\(8\)@cyrus-master(8)@" $(ls *5 *8) +popd +pushd doc + %{__perl} -pi -e "s@master@cyrus-master@g;" man.html +popd +pushd doc/man + %{__perl} -pi -e "s@master\(8\)@cyrus-master(8)@;" $(ls *html) +popd + +# Modify path in perl scripts +%{__perl} -pi -e "s@/usr/local/bin/perl@%{__perl}@" $(find . -type f -name "*.pl") + +# Fix permissions on perl programs +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 -name "*~" -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: + +use saslauth group +SASLGROUP : %{SASLGROUP} + +include deliver-wrapper +DEL_WRAP : %{DEL_WRAP} + +use preforking cyrus.conf +PREFORK : %{PREFORK} + +enable Netscape hack (recommended) +NETSCAPEHACK : %{NETSCAPEHACK} + +enable IMAP4 LIST extensions +LISTEXT : %{LISTEXT} + +enable IDLED support +IDLED : %{IDLED} + +force syncronous updates on ext3 +FORCESYNCEXT3 : %{FORCESYNCEXT3} + +include autocreate feature +AUTOCREATE : %{AUTOCREATE} + +include groupcache feature +GROUPCACHE : %{GROUPCACHE} + +include nobarenewlinescheck patch +NO_BARE_NL : %{NO_BARE_NL} + +used syslog facility for logging +SYSLOGFACILITY : %{SYSLOGFACILITY} + +used -fpie for linking +USEPIE : %{USEPIE} + +include OutlookExpress seenstate patch +OE_SEEN_ST : %{OE_SEEN_ST} + +use authorization module METHOD [unix|krb5] +AUTH_METHOD : %{AUTH_METHOD} + + +To modify parameters, edit the .spec file or build like this: +rpm --rebuild --define='FULLDIRHASH 1' %{name}-%{version}-%{release}.src.rpm +EOF + +%{__install} -m 644 %{SOURCE23} doc/README.RPM +%{__install} -m 644 %{SOURCE24} doc/README.HOWTO-recover-mailboxes.db +%if %{GROUPCACHE} +%{__install} -m 644 %{SOURCE31} doc/README.groupcache +%endif +%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 %{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 + +# modify lmtp socket path in .conf files +%{__perl} -pi -e "s@/var/imap/@%{_vardata}/@" %{_confdir}/*.conf doc/cyrusv2.mc doc/m4/%{name}-sendmail-8.12.9-cyrusv2.m4 + +# enable/disable idled in .conf files to prevent error messages +%if %{IDLED} + %{__perl} -pi -e "s/# idled/ idled/" %{_confdir}/*.conf +%else + %{__perl} -pi -e "s/ idled/# idled/" %{_confdir}/*.conf +%endif + +%install +[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} + +# This hack is needed on RedHat > 7.3 to install the perl files correctly +%if %{_perlhack} +pushd perl/imap + %{__perl} Makefile.PL PREFIX=%{buildroot}%{_prefix} +popd +pushd perl/sieve/managesieve + %{__perl} Makefile.PL PREFIX=%{buildroot}%{_prefix} +popd + +# Do what the regular make install does + %{__make} install DESTDIR=%{buildroot} PREFIX=%{_prefix} mandir=%{_mandir} + %{__make} -C man install DESTDIR=%{buildroot} PREFIX=%{_prefix} mandir=%{_mandir} +%else + %{__make} install DESTDIR=%{buildroot} PREFIX=%{buildroot}%{_prefix} mandir=%{_mandir} + %{__make} -C man install DESTDIR=%{buildroot} PREFIX=%{buildroot}%{_prefix} mandir=%{_mandir} +%endif + +%if %{DEL_WRAP} +%{__install} -m 2755 deliver-wrapper %{buildroot}%{_cyrexecdir}/ +%endif +%{__install} -m 755 imtest/imtest %{buildroot}%{_cyrexecdir}/ +%{__install} -m 755 perl/imap/cyradm %{buildroot}%{_cyrexecdir}/ + +# Install tools +for tool in tools/* ; do + test -f ${tool} && %{__install} -m 755 ${tool} %{buildroot}%{_cyrexecdir}/ +done + +# Create directories +%{__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}%{_datadir}/%{name}/rpm \ + %{_contribdir} + +# Install additional files +%{__install} -m 755 %{SOURCE13} %{buildroot}%{_cyrexecdir}/cvt_cyrusdb_all +%if %{GROUPCACHE} +%{__install} -m 755 %{SOURCE32} %{buildroot}%{_cyrexecdir}/upd_groupcache +%endif +%{__install} -m 755 %{SOURCE28} %{buildroot}%{_cyrexecdir}/rpm_set_permissions +%{__install} -m 644 %{SOURCE14} %{buildroot}%{_datadir}/%{name}/rpm/magic +%{__install} -m 644 %{SOURCE10} %{buildroot}%{_datadir}/%{name}/rpm/db.cfg +%{__install} -m 644 %{SOURCE15} %{_contribdir}/imapcreate +%{__install} -m 644 %{SOURCE16} %{_contribdir}/cyrus_ldap_quota +%{__install} -m 644 %{SOURCE17} %{_contribdir}/batchreconstruct +%{__install} -m 644 %{SOURCE18} %{_contribdir}/bsd2cyrus +%{__install} -m 644 %{SOURCE19} %{_contribdir}/cpmsg +%{__install} -m 644 %{SOURCE20} %{_contribdir}/folderxfer +%{__install} -m 644 %{SOURCE21} %{_contribdir}/inboxfer +%{__install} -m 644 %{SOURCE22} %{_contribdir}/ +%{__install} -m 644 %{SOURCE30} %{_contribdir}/README + +# Install config files +%{__install} -m 644 %{_cyrusconf} %{buildroot}%{_sysconfdir}/cyrus.conf +%{__install} -m 644 %{SOURCE6} %{buildroot}%{_sysconfdir}/imapd.conf +%{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/pop +%{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/imap +%{__install} -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/pam.d/sieve +%{__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 %{SOURCE12} %{buildroot}%{_sysconfdir}/sysconfig/%{name} +%{__install} -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/logrotate.d/%{name} +%{__install} -m 755 %{SOURCE25} %{buildroot}%{_sysconfdir}/cron.daily/%{name} +%{__install} -m 755 %{SOURCE11} %{buildroot}%{_sysconfdir}/rc.d/init.d/%{name} + +# Install templates +%{__install} -m 755 -d doc/conf +%{__install} -m 644 %{_confdir}/*.conf doc/conf/ + +# Rename 'master' binary and manpage to avoid crash with postfix +%{__mv} -f %{buildroot}%{_cyrexecdir}/master %{buildroot}%{_cyrexecdir}/cyrus-master +%{__mv} -f %{buildroot}%{_mandir}/man8/master.8 %{buildroot}%{_mandir}/man8/cyrus-master.8 +%{__mv} -f doc/man/master.8.html doc/man/cyrus-master.8.html +%{__perl} -pi -e 's/master/cyrus-master/g' %{buildroot}%{_mandir}/man8/cyrus-master.8 +%{__perl} -pi -e 's/Master/Cyrus-master/g' %{buildroot}%{_mandir}/man8/cyrus-master.8 +%{__perl} -pi -e 's/MASTER/CYRUS-MASTER/g' %{buildroot}%{_mandir}/man8/cyrus-master.8 +%{__perl} -pi -e 's/master/cyrus-master/g' doc/man/cyrus-master.8.html +%{__perl} -pi -e 's/Master/Cyrus-master/g' doc/man/cyrus-master.8.html +%{__perl} -pi -e 's/MASTER/CYRUS-MASTER/g' doc/man/cyrus-master.8.html + +# Rename 'fetchnews' binary and manpage to avoid crash with leafnode +%{__mv} -f %{buildroot}%{_cyrexecdir}/fetchnews %{buildroot}%{_cyrexecdir}/cyrfetchnews +%{__mv} -f %{buildroot}%{_mandir}/man8/fetchnews.8 %{buildroot}%{_mandir}/man8/cyrfetchnews.8 +%{__mv} -f doc/man/fetchnews.8.html doc/man/cyrfetchnews.8.html +%{__perl} -pi -e 's/fetchnews/cyrfetchnews/g' %{buildroot}%{_mandir}/man8/cyrfetchnews.8 +%{__perl} -pi -e 's/Fetchnews/Cyrfetchnews/g' %{buildroot}%{_mandir}/man8/cyrfetchnews.8 +%{__perl} -pi -e 's/FETCHNEWS/CYRFETCHNEWS/g' %{buildroot}%{_mandir}/man8/cyrfetchnews.8 +%{__perl} -pi -e 's/fetchnews/cyrfetchnews/g' doc/man/cyrfetchnews.8.html +%{__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 | + %{__sed} "s@^%{buildroot}@@g" | + %{__grep} -v perllocal.pod | + %{__grep} -v "\.packlist" > perl-Cyrus-%{version}-filelist +find %{buildroot}%{_perl_man3dir} -type f -name "Cyrus*" -print | + %{__sed} "s@^%{buildroot}@@g" >> perl-Cyrus-%{version}-filelist +if [ "$(%{__cat} perl-Cyrus-%{version}-filelist)X" = "X" ] ; then + echo "ERROR: EMPTY FILE LIST" + exit -1 +fi + +# Strip binaries +%{__strip} --strip-unneeded %{buildroot}%{_cyrexecdir}/* ||: + +# Remove installed but not packaged files +%{__rm} -f %{buildroot}%{_cyrexecdir}/not-mkdep +%{__rm} -f %{buildroot}%{_cyrexecdir}/config2header +%{__rm} -f %{buildroot}%{_cyrexecdir}/config2man +%{__rm} -f %{buildroot}%{_cyrexecdir}/pop3proxyd +find %{buildroot} -name "perllocal.pod" -exec %{__rm} -f {} \; +find %{buildroot} -name ".packlist" -exec %{__rm} -f {} \; +%if !%{IDLED} +%{__rm} -f %{buildroot}%{_mandir}/man8/idled.8* +%{__rm} -f doc/man/idled.8.html +%endif + +# On RedHat 7.3, this file is created here +%{__rm} -f /perllocal.pod + +%clean +[ "%{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 || : + touch /var/lock/subsys/cyrus-imapd +fi + +%post +/sbin/chkconfig --add %{name} + +# Create SSL certificates +exec > /dev/null 2> /dev/null +if [ ! -f %{_datadir}/ssl/certs/%{name}.pem ]; then +pushd %{_datadir}/ssl/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 +popd +fi + +# Force synchronous updates, usually only on ext2 filesystems +for i in %{_vardata}/{user,quota} %{_spooldata} +do +%if %{FORCESYNCEXT3} + if [ $(find $i -maxdepth 0 -printf %%F) = "ext2" -o $(find $i -maxdepth 0 -printf %%F) = "ext3" ]; then +%else + if [ $(find $i -maxdepth 0 -printf %%F) = "ext2" ]; then +%endif + chattr -R +S $i 2>/dev/null + fi +done + +# "ctl_deliver -E" is deprecated, now is "cyr_expire -E" +if grep -q "ctl_deliver *-E" %{_sysconfdir}/cyrus.conf ; then + %{__perl} -pi -e "s/ctl_deliver *-E/cyr_expire -E/" %{_sysconfdir}/cyrus.conf +fi + +# prevent idled related errors to show up +%if %{IDLED} + if grep -q "^# idled" %{_sysconfdir}/cyrus.conf ; then + %{__perl} -pi -e "s/^# idled/ idled/" %{_sysconfdir}/cyrus.conf + fi +%else + if grep -q "^ idled" %{_sysconfdir}/cyrus.conf ; then + %{__perl} -pi -e "s/^ idled/# idled/" %{_sysconfdir}/cyrus.conf + fi +%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 +fi + +%postun +if [ $1 = 0 ]; then + /usr/sbin/userdel %{_cyrususer} 2> /dev/null || : +%if %{SASLGROUP} + if [ "$(%{__grep} ^%{_saslgroup}: %{_sysconfdir}/group | cut -d: -f4-)" = "" ]; then + /usr/sbin/groupdel %{_saslgroup} 2> /dev/null || : + fi +%endif +else + /sbin/service %{name} condrestart >/dev/null 2>&1 || : +fi + +%files +%defattr(0644,root,root,0755) +%config(noreplace) %{_sysconfdir}/cyrus.conf +%config(noreplace) %{_sysconfdir}/imapd.conf +%attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} +%config %{_sysconfdir}/logrotate.d/%{name} +%config(noreplace) %{_sysconfdir}/sysconfig/%{name} +%config(noreplace) %{_sysconfdir}/pam.d/pop +%config(noreplace) %{_sysconfdir}/pam.d/imap +%config(noreplace) %{_sysconfdir}/pam.d/sieve +%config(noreplace) %{_sysconfdir}/pam.d/lmtp +%attr(0755,root,root) %config %{_sysconfdir}/cron.daily/%{name} +%dir %{_cyrexecdir} +%attr(0755,root,root) %{_cyrexecdir}/arbitron +%attr(0755,root,root) %{_cyrexecdir}/arbitronsort.pl +%attr(0755,root,root) %{_cyrexecdir}/chk_cyrus +%attr(0755,root,root) %{_cyrexecdir}/convert-sieve.pl +%attr(0755,root,root) %{_cyrexecdir}/ctl_cyrusdb +%attr(0755,root,root) %{_cyrexecdir}/ctl_deliver +%attr(0755,root,root) %{_cyrexecdir}/ctl_mboxlist +%attr(0755,root,root) %{_cyrexecdir}/cvt_cyrusdb +%attr(0755,root,root) %{_cyrexecdir}/cyr_expire +%attr(0755,root,root) %{_cyrexecdir}/cyrdump +%attr(0755,root,root) %{_cyrexecdir}/cyrus-master +%attr(0755,root,root) %{_cyrexecdir}/deliver +%attr(0755,root,root) %{_cyrexecdir}/dohash +%attr(0755,root,root) %{_cyrexecdir}/fud +%attr(0755,root,root) %{_cyrexecdir}/imapd +%attr(0755,root,root) %{_cyrexecdir}/ipurge +%attr(0755,root,root) %{_cyrexecdir}/lmtpd +%attr(0755,root,root) %{_cyrexecdir}/masssievec +%attr(0755,root,root) %{_cyrexecdir}/mbexamine +%attr(0755,root,root) %{_cyrexecdir}/mbpath +%attr(0755,root,root) %{_cyrexecdir}/mkimap +%attr(0755,root,root) %{_cyrexecdir}/mknewsgroups +%attr(0755,root,root) %{_cyrexecdir}/notifyd +%attr(0755,root,root) %{_cyrexecdir}/pop3d +%attr(0755,root,root) %{_cyrexecdir}/quota +%attr(0755,root,root) %{_cyrexecdir}/reconstruct +%attr(0755,root,root) %{_cyrexecdir}/rehash +%attr(0755,root,root) %{_cyrexecdir}/sievec +%attr(0755,root,root) %{_cyrexecdir}/smmapd +%attr(0755,root,root) %{_cyrexecdir}/squatter +%attr(0755,root,root) %{_cyrexecdir}/timsieved +%attr(0755,root,root) %{_cyrexecdir}/tls_prune +%attr(0755,root,root) %{_cyrexecdir}/translatesieve +%attr(0755,root,root) %{_cyrexecdir}/undohash +%attr(0755,root,root) %{_cyrexecdir}/upgradesieve +%attr(0755,root,root) %{_cyrexecdir}/cvt_cyrusdb_all +%if %{GROUPCACHE} +%attr(0755,root,root) %{_cyrexecdir}/upd_groupcache +%endif +%attr(0755,root,root) %{_cyrexecdir}/rpm_set_permissions +%if %{IDLED} +%attr(0755,root,root) %{_cyrexecdir}/idled +%endif +%if %{AUTOCREATE} +%attr(0755,root,root) %{_cyrexecdir}/compile_sieve +%endif +%if %{DEL_WRAP} +%attr(2755,%{_cyrususer},%{_cyrusgroup}) %{_cyrexecdir}/deliver-wrapper +%endif +%attr(0750,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata} +%attr(0750,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/socket +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/user +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/quota +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/proc +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/log +%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}/rpm +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_vardata}/backup +%attr(0700,%{_cyrususer},%{_cyrusgroup}) %dir %{_spooldata} +%dir %{_datadir}/%{name} +%dir %{_datadir}/%{name}/rpm +%{_datadir}/%{name}/rpm/* +%{_mandir}/man5/* +%{_mandir}/man8/* +%doc COPYRIGHT README +%doc doc/* + +%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 +%{_libdir}/lib*.a +%{_mandir}/man3/imclient.3* + +%files -n perl-Cyrus -f perl-Cyrus-%{version}-filelist +%defattr(-,root,root) +%doc perl/imap/README +%doc perl/imap/Changes +%doc perl/imap/examples + +%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 +* Fri Apr 15 2005 John Dennis - 2.2.12-1.2.fc4 +- fix debug_package macro, it was still being expanded, + comments don't hide macro expansion +- fix changelog chronological order +- fix bug 118832, cyrus-imapd is modifying /etc/services + +* 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 + +* Fri Mar 4 2005 John Dennis - 2.2.10-11.4.fc4 +- fix gcc4 build problems + +* Thu Mar 3 2005 John Dennis 2.2.10-11.3.fc4 +- bump rev for build + +* Mon Feb 14 2005 Simon Matter +- updated to 2.2.12 +- updated autocreate and autosievefolder patches + +* Fri Feb 11 2005 John Dennis - 2.2.10-11.2.fc4 +- make _contribdir identical to Simon's, + I had been getting burned by rpm's bizarre handling of macros in comments + +* Thu Feb 10 2005 John Dennis - 2.2.10-11.1.fc4 +- bring up to date with Simon Matter's 2.2.10-11 rpm + +* Sat Feb 05 2005 Simon Matter +- updated autosievefolder patch + +* Tue Feb 01 2005 Simon Matter +- remove special ownership and permissions from deliver +- enable deliver-wrapper per default +- enable OutlookExpress seenstate patch per default + +* Wed Jan 19 2005 Simon Matter +- updated autocreate patch + +* Fri Jan 14 2005 Simon Matter +- spec file cleanup + +* Tue Jan 11 2005 Simon Matter +- updated autocreate patch + +* Fri Jan 07 2005 Simon Matter +- moved contrib dir into doc, made scripts not executable + +* Thu Jan 06 2005 Simon Matter +- added more fixes to the autocreate patch +- don't use %_libdir for %_cyrexecdir, it's a mess on x86_64 +- don't use %_libdir for symlinks +- remove %_libdir pachtes +- change pam configs to work on x86_64 +- changed default build option for IDLED to on +- changed rpm_set_permissions to honor partitions in /etc/imapd.conf + +* Tue Jan 04 2005 Simon Matter +- updated autocreate patch + +* Mon Dec 20 2004 Simon Matter +- remove idled docs when disabled, fixes RedHat's bug #142345 + +* Fri Dec 17 2004 Simon Matter +- removed allnumeric patch, not needed anymore +- made groupcache a compile time option +- rename nntp's pam service, fixes RedHat's bug #142672 + +* Thu Dec 16 2004 Simon Matter +- updated groupcache patch +- updated cvt_cyrusdb_all to use runuser instead of su if available +- added upd_groupcache tool + +* Wed Dec 15 2004 Simon Matter +- added groupfile patch to help those using nss_ldap + +* Thu Dec 02 2004 Simon Matter +- modified config directives and removed verify options + +* Thu Dec 2 2004 John Dennis 2.2.10-3.devel +- fix bug #141673, dup of bug #141470 + Also make cyrus.conf noreplace in addition to imapd.conf + Remove the verify overrides on the noreplace config files, + we do want config file changes visible when verifying + +* Wed Dec 1 2004 John Dennis 2.2.10-2.devel +- fix bug #141470, make imapd.conf a noreplace config file + +* Wed Dec 1 2004 John Dennis 2.2.10-1.devel +- update to Simon Matter's 2.2.10 RPM, + fixes bug #139382, + security advisories: CAN-2004-1011 CAN-2004-1012 CAN-2004-1013 CAN-2004-1015 + +* Tue Nov 24 2004 Simon Matter +- updated to 2.2.10 + +* Tue Nov 23 2004 Simon Matter +- updated to 2.2.9 + +* Fri Nov 19 2004 Simon Matter +- changed scripts to use runuser instead of su if available + +* Thu Nov 18 2004 Simon Matter +- changed requirement for file >= 3.35-1 from BuildPrereq to + Requires, fixes RedHat's bug #124991 +- added acceptinvalidfrom patch to fix RedHat's bug #137705 + +* Mon Oct 4 2004 Dan Walsh 2.2.6-2.FC3.6 +- Change cyrus init scripts and cron job to use runuser instead of su + +* Fri Aug 6 2004 John Dennis 2.2.6-2.FC3.5 +- remove obsoletes tag, fixes bugs #127448, #129274 + +* Wed Aug 4 2004 John Dennis +- replace commas in release field with dots, bump build number + +* Tue Aug 03 2004 Simon Matter +- fixed symlinks for x86_64, now uses the _libdir macro + reported by John Dennis, fixes RedHat's bug #128964 +- removed obsoletes tag, fixes RedHat's bugs #127448, #129274 + +* Mon Aug 2 2004 John Dennis 2.2.6-2,FC3,3 +- fix bug #128964, lib symlinks wrong on x86_64 + +* Thu Jul 29 2004 Simon Matter +- updated to 2.2.8 + +* Thu Jul 29 2004 Simon Matter +- updated autocreate and autosieve patches +- made authorization a compile time option +- added sieve-bc_eval patch + +* Tue Jul 27 2004 Simon Matter +- updated to 2.2.7 +- modified autocreate patch or 2.2.7 +- removed snmpargs patch which was needed for RedHat 6.2 + +* Tue Jul 13 2004 Simon Matter +- added mboxlist / mboxname patches from CVS + +* Tue Jul 06 2004 Simon Matter +- updated rmquota+deletemailbox patch + +* Sat Jul 3 2004 John Dennis - 2.2.6-2,FC3,1 +- bring up to date with Simon Matter's latest upstream rpm 2.2.6-2 +- comment out illegal tags Packager, Vendor, Distribution + build for FC3 + +* Wed Jun 30 2004 Simon Matter +- added quota patches from CVS + +* Fri Jun 25 2004 Simon Matter +- updated autocreate patch + +* Fri Jun 18 2004 Simon Matter +- updated to 2.2.6 + +* Fri Jun 11 2004 Simon Matter +- updated autocreate and autosieve patches + +* Tue Jun 01 2004 Simon Matter +- updated autocreate, autosieve and rmquota patches +- fixed rmquota patch to build on gcc v3.3.x +- added lmtp_sieve patch + +* Sat May 29 2004 Simon Matter +- updated to 2.2.5 + +* Fri May 28 2004 Simon Matter +- updated to 2.2.5 pre-release + +* Mon May 24 2004 Simon Matter +- added hash patch to fix a sig11 problem +- added noncritical typo patch + +* Fri May 21 2004 Simon Matter +- include OutlookExpress seenstate patch +- fixed allnumeric patch + +* Thu May 20 2004 Simon Matter +- don't enable cyrus-imapd per default +- rename fetchnews to cyrfetchnews to avoid namespace conflicts with leafnode +- replace fetchnews with cyrfetchnews in man pages +- replace master with cyrus-master in man pages + +* Tue May 18 2004 Simon Matter +- updated to 2.2.4 + +* Fri Apr 30 2004 Simon Matter +- Don't provides: imap + +* Wed Mar 17 2004 Simon Matter +- fix init script + +* Thu Mar 04 2004 Simon Matter +- strip binaries + +* Tue Mar 02 2004 Simon Matter +- add more SELinux fixes + +* Wed Feb 25 2004 Simon Matter +- add makedepend to path, thank you Andreas Piesk for reporting it + +* Mon Feb 23 2004 Dan Walsh +- change su within init script to get input from /dev/null + this prevents hang when running in SELinux +- don't use -fpie as default, it breaks different distributions + +* Thu Feb 19 2004 Simon Matter +- merged in most changes from Karsten Hopp's RedHat package +- fixed permissions of files in contrib, thank you + Edward Rudd for reporting it. +- modified snmp patch to make it build on RedHat 6.2 again + +* Tue Feb 03 2004 Karsten Hopp +- switch to Simon Matter's cyrus-imapd package, which has + some major improvements over the old Red Hat package. + - configdirectory moved from /var/imap to /var/lib/imap + - sasl_pwcheck_method changed to saslauthd +- needed to delete package/vendor tags for buildsystem. +- added USEPIE variable for linking with -fpie flag +- removed rpath from linker arguments +- removed email header from README.HOWTO-recover-mailboxes +- added lib64 patch +- use CFLAGS from specfile in imtest subdir +- disable -pie on ppc for now + +* Tue Feb 03 2004 Simon Matter +- added tls_ca_file: to imapd.conf +- updated autocreate patch which fixes a small sig11 problem + +* Thu Jan 29 2004 Simon Matter +- convert sieve scripts to UTF-8 only if sievec failed before +- add note to the readme about limiting loggin on busy servers +- added build time option to chose the syslog facility + +* Wed Jan 28 2004 Simon Matter +- sieve scripts are now converted to UTF-8 with cvt_cyrusdb_all + +* Tue Jan 27 2004 Simon Matter +- fixed problems with masssievec +- lots of small fixes in the init scripts + +* Fri Jan 23 2004 Simon Matter +- updated auto db converting functionality +- added auto masssievec functionality + +* Thu Jan 22 2004 Simon Matter +- updated autocreate/autosievefolder patches + +* Fri Jan 16 2004 Simon Matter +- updated to 2.2.3 + +* Wed Jan 14 2004 Simon Matter +- number of mailbox list dumps can now be configured + +* Fri Jan 01 2004 Simon Matter +- updated autosievefolder patch + +* Thu Dec 18 2003 Simon Matter +- updated autocreate/autosievefolder/rmquota patches + +* Tue Oct 28 2003 Simon Matter +- updated to 2.2.2-BETA + +* Tue Aug 05 2003 Simon Matter +- add sendmail m4 macro, some people were looking for it +- just one source for pam default configuration (they were all the same) +- added /etc/pam.d/lmtp +- added build support for RedHat Beta severn + +* Wed Jul 30 2003 Simon Matter +- updated autocreate patch to 0.8.1 +- removed creation of spool/config dirs, not needed anymore +- added cyrus_sharedbackup to contrib + +* Fri Jul 18 2003 Simon Matter +- modified for 2.2.1-BETA + +* Wed Jul 09 2003 Simon Matter +- modified rpm_set_permissions script + +* Mon Jul 07 2003 Simon Matter +- changed permissions on config and spool dirs +- modified init script + +* Thu Jul 03 2003 Simon Matter +- upgraded to 2.1.14 +- removed now obsolete forcedowncase patch +- use --with-extraident to add extra version information +- updated munge8bit patch + +* Wed Jun 04 2003 Simon Matter +- added RedHat 2.1ES support to the perlhack detection + +* Tue May 20 2003 Simon Matter +- upgraded autocreate patch + +* Fri May 09 2003 Simon Matter +- upgraded autocreate patch +- modified init script + +* Mon May 05 2003 Simon Matter +- upgraded to 2.1.13 +- replaced commands with macros, cleaned up spec file + +* Fri May 02 2003 Simon Matter +- added murder subpackage +- changed exec path to /usr/lib/cyrus-imapd + +* Thu May 01 2003 Simon Matter +- included modified munge8bit patch again + +* Tue Apr 29 2003 Simon Matter +- added new 8bit header patch +- upgraded IPv6 patch +- upgraded autocreate patch to 0.7 + +* Mon Apr 28 2003 Simon Matter +- added new autocreate patch + +* Mon Mar 31 2003 H-E Sandstrom +- added munge8bit patch + +* Mon Mar 24 2003 Simon Matter +- added createonpost fix patch + +* Thu Mar 20 2003 Simon Matter +- added functionality to patch the IPv6 patch on the fly if + autoconf > 2.13, we can now use newer autoconf again. + +* Tue Mar 18 2003 Paul Bender +- fixed spec file so that autoconf 2.13 will always be used, + since the IPv6 patch requires autoconf <= 2.13 + +* Fri Mar 14 2003 Simon Matter +- fixed problems with new file package + +* Thu Mar 13 2003 Simon Matter +- added kerberos include for RedHat Beta phoebe 2 +- added Henrique's forcedowncase patch + +* Mon Mar 03 2003 Simon Matter +- corrected imapd.conf + +* Sat Mar 01 2003 Simon Matter +- added note about lmtp socket in sendmail +- added flock patches + +* Fri Feb 07 2003 Simon Matter +- added build time option for fulldirhash + +* Wed Feb 05 2003 Simon Matter +- added IPV6 patch to source rpm +- fixed build on RedHat 6.2 + +* Tue Feb 04 2003 Simon Matter +- update to 2.1.12 +- added logrotate entry for /var/log/auth.log +- modified init script to use builtin daemon mode + +* Fri Jan 10 2003 Simon Matter +- small change in mboxlist backup script + +* Fri Jan 10 2003 Simon Matter +- fixed a cosmetic bug in cvt_cyrusdb_all +- added cron.daily job to backup mailboxes.db + +* Mon Jan 06 2003 Simon Matter +- add more entries to /etc/services + +* Wed Jan 01 2003 Simon Matter +- include snmpargs patch for build on RedHat 6.2 +- added build support for RedHat 6.2 + +* Mon Dec 30 2002 Simon Matter +- removed autoconf hack, not needed anymore +- enabled build on RedHat Beta Phoebe +- added services entry for lmtp +- cleanup spec file + +* Thu Dec 26 2002 Simon Matter +- removed BuildPrereq for e2fsprogs-devel + +* Thu Dec 12 2002 Simon Matter +- modified RedHat release detection +- added BuildPrereq for file + +* Thu Dec 05 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.11 +- upgrade IPV6 patch to 20021205 + +* Thu Nov 28 2002 Simon Matter +- Fixed some default attributes + +* Thu Nov 28 2002 Troels Arvin +- Explicitly changed files-section to + - use defattr for simple (root-owned 0644) files + - explictly set root as user/group owner where + the user/group ownership was previously indicated + as "-"; this allows building valid packages without + having to being root when building + +* Mon Nov 25 2002 Simon Matter +- changed default build option for IDLED to off +- included some useful info in README.* + +* Thu Nov 21 2002 Simon Matter +- added build time option for IDLED, thank you Roland Pope + +* Tue Nov 19 2002 Simon Matter +- fixed spec to really use fdatasync patch +- added createonpost patch + +* Thu Nov 14 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.10 +- build without IPv6 support by default + +* Tue Nov 12 2002 Simon Matter +- fixed db detection in .spec + +* Mon Oct 21 2002 Simon Matter +- updated cvt_cyrusdb_all script + +* Fri Oct 18 2002 Simon Matter +- added fdatasync patch + +* Thu Oct 03 2002 Simon Matter +- add RPM version 4.1 compatibility, which means remove installed + but not packaged files + +* Wed Sep 18 2002 Simon Matter +- added auto db converting functionality +- changed default for MBOXLIST_DB and SEEN_DB to skiplist + +* Mon Sep 16 2002 Simon Matter +- remove creation of cyrus user at build time +- added scripts from ftp://kalamazoolinux.org/pub/projects/awilliam/cyrus/ + +* Mon Sep 02 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.9 + +* Fri Aug 30 2002 Simon Matter +- included extra ident string + +* Thu Aug 29 2002 Simon Matter +- modified path in deliver-wrapper, thank you Richard L. Phipps +- added RedHat 2.1AS support to the perlhack detection +- added build time option to force syncronous updates on ext3 + +* Wed Aug 28 2002 Simon Matter +- added updated IPv6 patch from Hajimu UMEMOTO + +* Wed Aug 28 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.8 + +* Thu Aug 22 2002 Simon Matter +- included IPv6 patch from Hajimu UMEMOTO + +* Wed Aug 21 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.7 because of wrong version info + +* Wed Aug 21 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.6 + +* Mon Aug 19 2002 Simon Matter +- change db version detection, thank you Chris for reporting + +* Tue Aug 13 2002 Simon Matter +- fixed autoconf detection + +* Mon Aug 12 2002 Simon Matter +- included support for different autoconf versions +- modified the perl build and install process +- made some .spec changes to build on RedHat 7.x and limbo + +* Fri Aug 09 2002 Simon Matter +- included sieve matching patch + +* Thu Jun 27 2002 Simon Matter +- fixed %post script where %F was expanded to file.file + +* Wed Jun 26 2002 Simon Matter +- fixed missing man page + +* Tue Jun 25 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.5 + +* Mon Jun 24 2002 Simon Matter +- added compile time parameters to configure the package based on + the idea from Luca Olivetti +- make deliver-wrapper a compile time option + +* Fri May 02 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.4 + +* Mon Apr 22 2002 Simon Matter +- small initscript fix + +* Fri Mar 08 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.3 +- removed some stuff that was cleaned up in the sources +- added compile time options for db backends + +* Wed Mar 06 2002 Simon Matter +- removed requires perl-File-Temp for utils package, it's in the RedHat + perl RPM now + +* Fri Feb 22 2002 Simon Matter +- removed deliverdb/db + +* Wed Feb 20 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.2 + +* Mon Feb 11 2002 Simon Matter +- changed sasl_mech_list: PLAIN in /etc/imapd.conf +- added sieve to /etc/pam.d + +* Fri Feb 08 2002 Simon Matter +- added requires perl-File-Temp for utils package + +* Wed Feb 06 2002 Simon Matter +- added some %dir flags +- removed /usr/lib/sasl/Cyrus.conf +- added conf templates +- build time option for usage of saslauth group + +* Tue Feb 05 2002 Simon Matter +- upgraded to cyrus-imapd 2.1.1 +- dependency of cyrus-sasl >= 2.1.0-1 + +* Sun Feb 03 2002 Simon Matter +- saslauth group is only deleted on uninstall if there is no other + member in this group + +* Sat Feb 02 2002 Simon Matter +- changed start/stop level in init file + +* Tue Jan 29 2002 Simon Matter +- dependency of cyrus-sasl >= 1.5.24-22 +- dotstuffing patch for sendmail calls made by sieve for outgoing + mails +- patch for ability to force ipurge to traverse personal folders + +* Mon Jan 28 2002 Simon Matter +- minor spec file changes + +* Sat Jan 19 2002 Simon Matter +- changed default auth to pam +- remove several %dir from %files sections +- change from /usr/lib/cyrus -> /usr/libexec/cyrus +- rename source files to something like cyrus... +- added rehash tool +- changed to hashed spool + +* Fri Jan 18 2002 Simon Matter +- fixed init script +- fixed %post section in spec + +* Thu Jan 17 2002 Simon Matter +- ready for first build + +* Wed Jan 09 2002 Simon Matter +- initial package, with help from other packages out there diff --git a/cyrus-imapd.sysconfig b/cyrus-imapd.sysconfig new file mode 100644 index 0000000..ad8bec5 --- /dev/null +++ b/cyrus-imapd.sysconfig @@ -0,0 +1,5 @@ +# Options to cyrus-master +CYRUSOPTIONS="" + +# Mailbox list dumps are rotated n times via cron.daily +#ROTATE=6 diff --git a/cyrus-imapd.upd_groupcache b/cyrus-imapd.upd_groupcache new file mode 100644 index 0000000..bf50c35 --- /dev/null +++ b/cyrus-imapd.upd_groupcache @@ -0,0 +1,66 @@ +#!/bin/sh + +# 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 of the License, 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 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# This script updates a cache of the unix group database. It's purpose is to +# speedup group authorization when using large groups with slow nss backends. +# For more info consult the README.groupcache file. +# +# This script can safely be run as root, it will reexec itself as user +# cyrus if needed. +# +# author: Simon Matter, Invoca Systems + +# changelog +# v1.0.0, Dec 15 2004 Simon Matter +# - initial release + +if [ ! -f /etc/imapd.conf ]; then + echo "ERROR: configuration file not found." + exit 1 +fi + +# fallback to su if runuser not available +if [ -x /sbin/runuser ]; then + RUNUSER=runuser +else + RUNUSER=su +fi + +# force cyrus user for security reasons +if [ ! $(whoami) = "cyrus" ]; then + exec $RUNUSER - cyrus -c "cd $PWD < /dev/null ; $0" +fi + +# files get mode 0600 +umask 166 + +# 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 +imap_prefix=$(get_config configdirectory /var/lib/imap) +group_cache=${imap_prefix}/group.cache + +TMPCACHE=$(mktemp ${group_cache}.XXXXXX) || exit 1 +getent group >> $TMPCACHE +mv -f $TMPCACHE $group_cache diff --git a/cyrus-procmailrc b/cyrus-procmailrc new file mode 100644 index 0000000..66c6127 --- /dev/null +++ b/cyrus-procmailrc @@ -0,0 +1,129 @@ +################################################# +# procmailrc +# This is the main procmail file with common SPAM recipes +# Based on the article at +# http://www.ncworldmag.com/ncw-05-1998/ncw-05-imap.html +# +# +# First we define some basics + +PATH=/usr/bin:/bin +SHELL=/bin/sh + +# We define DELIVERTO just to prevent a lot of extra +# typing later on. We define SPAMIT to prevent even more +# repetitive typing, as it's the same action for every user. +# This assumes we set up a SPAM folder right off the INBOX +# for every user on the system. If we neglect to do that, we'll +# get in a bit of trouble. + +DELIVERTO=/usr/cyrus/bin/deliver-wrapper +SPAMIT="$DELIVERTO user.$LOGNAME.SPAM" + +# This file includes the appropriate procmail.$LOGNAME +# file so that each user has his or her own recipe techniques +# for subscribed lists, e-mail alerts, etc. + +# Before we begin any recipes, let's make a backup +# copy of any incoming mail. +# +# Remember to comment out the next recipe once +# you know everything is working fine, otherwise +# you'll fill up the backup directory very quickly. +# Some procmail tutorials demonstrate how you can +# set a quota on the backup directory so that you can +# leave it in force at all times. + +:0 ic +| $DELIVERTO user.$LOGNAME.Backup + +############################### +# If there used to be an existing system-wide procmailrc, you can +# include it here +#INCLUDERC=/etc/procmailrc + +# We shouldn't be running as a privileged user, but just in case, +# make sure we drop any privileges we have +DROPPRIVS=1 + +############################### +# If users want to be able to define their own private recipes +# and put them in their home .procmailrc files, comment out +# the next definition. +# +# These recipes will be processed BEFORE the user-specific +# recipes that are kept in the /home/cyrus directory +# +# setup some variables, before we start +ALERTSBOX=user.$LOGNAME.Folders.Alerts +LISTSBOX=user.$LOGNAME.Folders.Lists +# +INCLUDERC=$HOME/.procmailrc + +# If you want to define user-specific recipes that +# you manage centrally (perhaps because you don't want +# to allow your users to "roll their own," then +# uncomment the following line. In this case, you have +# to create a file for each user in the form: +# procmail.username -- for example, procmail.Joe +# +# INCLUDERC=/usr/cyrus/etc/procmail.$LOGNAME + +############################# +# Now we begin our recipes + +############################# +# Email-specific SPAM recipes +# Here's one example + +#### NOTE: surely cyrus 'deliver' does its own locking? There should +#### thus be no need for :0:$LOGNAME.lock + +:0 +* ^To:.*anyplace@juno.com +| $SPAMIT + +############################# +# General SPAM Recipes +# Here are a few examples +# +# The "To:" line doesn't exist + +#:0 +#* !^To: +#| $SPAMIT + +# The "To:" line is empty + +#:0 +#* ^To: $ +#| $SPAMIT + +# The "From:" line is empty + +#:0 +#* ^From: $ +#| $SPAMIT + +############################# +# All the mail that falls +# through the above recipes +# will be put into the user's +# inbox. This is always the LAST +# recipe to appear in the file. + +:0W +| $DELIVERTO user.$LOGNAME + +# If that fails - maybe because the user is out of quota, or the mailbox +# hasn't been created - then force a bounce (otherwise the message would +# get silently appended to /var/spool/mail/$LOGNAME). + +# This is EX_CANTCREAT (Can't create output) +EXITCODE=73 +:0 +/dev/null + +# +# End of procmailrc file +############################## diff --git a/cyrus-user-procmailrc.template b/cyrus-user-procmailrc.template new file mode 100644 index 0000000..8a018a1 --- /dev/null +++ b/cyrus-user-procmailrc.template @@ -0,0 +1,58 @@ +############################## +# Begin procmailrc.joe file +# +# This is Joe's specific set of procmail +# recipes. It assumes that Joe has a +# number of specific folders created +# to which these recipes refer. Otherwise +# the mail cannot be sorted properly. +# +# First, let's define some high-level +# folder macros to save typing later on. +# The ALERTSBOX points to the +# folder where we'll sort out various +# incoming news alerts. +# The LISTSBOX will point to a +# folder where we'll sort out various +# list services to which we're subscribed. +# +# Both ALERTSBOX and LISTSBOX +# are subfolders of a generic folder called, +# duh, Folders, which is right off the +# user's INBOX. +# +# So if a Linux-kernel message comes in +# it gets deposited in the folder +# Folders/Lists/Linux_Kernel which is +# represented in Cyrus IMAP terms as +# user.Joe.Folders.Lists.Linux_kernel +# + +############################ +# Put anchordesk alerts in news alerts folder + +:0:$LOGNAME.lock +* ^From:.*anchordesk +| $DELIVERTO $ALERTSBOX.News-Alerts + +# Put NC World alerts in their own folder + +:0:$LOGNAME.lock +* ^From:.*NCWorld@FDDS.com +| $DELIVERTO $ALERTSBOX.NCWorld-Alerts + +############################# +# List processing & Misc Alerts + +:0:$LOGNAME.lock +* (^Cc:|^CC:|^To:|^Sender:).*linux-kernel@vger.rutgers.edu +| $DELIVERTO $LISTSBOX.Linux_Kernel + +:0:$LOGNAME.lock +* (^Cc:|^CC:|^To:|^Sender:).*linux-net@vger.rutgers.edu +| $DELIVERTO $LISTSBOX.Linux_Net + +# +# End of procmailrc.joe file +############################## + diff --git a/cyrus_ldap_quota.pl b/cyrus_ldap_quota.pl new file mode 100644 index 0000000..2fcf052 --- /dev/null +++ b/cyrus_ldap_quota.pl @@ -0,0 +1,127 @@ +#!/usr/bin/perl +use Cyrus::IMAP::Admin; + +# This script was created by Kevin J. Menard, Jr. . +# It requires root privileges to write to a file in /etc. Best use is +# to set this up as cron job. Works for me. Hope it does for you. +# Any questions/complaints/praise/whatever, send 'em to the address +# above. -- 08/16/2001 + + +# These are the variables you might want to tweak. +my $quota_attr = "mailQuota"; +my $mail_attr = "mailRoutingAddress"; +my $user = "cyrus"; +my $passwd = "blah"; + +# These are the ones that you shouldn't have to. +my @entries = (); +my $index = 0; +my $counter = 0; +my $old_timestamp = 0; +my $timestamp = "199412161032Z"; + +# Open the /etc/cyrus_ldap_quota_time file; it's a long name, but +# shouldn't interfere with existing files :) This file contains 1 line, +# the generalized time format of the last time the script ran. This is +# used for the search, so we only update quotas that have been modified +# since then. + +{ + if (-e "/etc/cyrus_ldap_quota_time") + { + open(TIME_FILE, "/etc/cyrus_ldap_quota_time") or die "could not + open the time file: $!\n"; + + while() { $old_timestamp = $_; } + + close(TIME_FILE); + } + + # Now we deal with the case where the file doesn't exist, that is to + # say the first time the script was run. + + unless ($old_timestamp == 0) { $timestamp = $old_timestamp; } + + + # Now that we have that information, we can overwrite the file with + # the new timestamp. Maybe this overkill, but this is only a + # temporary solution anyway. + + open(TIME_FILE, ">/etc/cyrus_ldap_quota_time") or die "could not + create file: $!\n"; + + my @time = (localtime)[0..5]; + + printf TIME_FILE $time[5] + 1900; + printf TIME_FILE "%02d", $time[4] + 1; + for (my $i = 3; $i >= 0; $i--) { printf TIME_FILE "%02d", $time[$i];} + print TIME_FILE 'Z'; + + close(TIME_FILE); +} + + +# This is where we do the search and then parse the results into a +# useable form. In this case, an arry of hash entries. +{ + # Okay, this very ugly line sets up the LDAP search, and the strips + # away the meaningless stuff. This could be prettier, but I didn't + # want to add a dependency for an LDAP module, and everyone should + # have LDAP search. The greps are just to make things simpler. + + (my $query = "ldapsearch -x '(&(modifyTimestamp>=$timestamp)($quota_attr=*))' $quota_attr $mail_attr + | grep -v ^# | grep -v ^dn | grep -v ^version | grep -v ^search | grep -v ^result | grep -v ^\$") =~ s!\n!!; + + # Now actually do the commands in the above line. + my $result = `$query`; + + + # Split the output into an array, one entry per line. + my @output = split(/\n/, $result); + + # Now go through each line . . . + foreach (@output) + { + # Split on the attribute:value boundary. + (my $key, my $value) = split(/: /); + + # Handle mailRoutingAddress; strip away everything after '@'. + if ($value =~ m!@!) + { + ($value, undef) = split (/@/, $value); + } + + # Add each doctored up attribute:value pair to the entries array. + $entries[$index]{$key} = $value; + + # A crude hack to make sure each of the two attributes makes it + # into one of the entries array element. + if ($counter % 2) + { + $index++; + } + + $counter++; + } +} + +# Now here's the actual interaction with Cyrus IMAPd. It's all pretty +# self-explanatory. +{ + my $imap = Cyrus::IMAP::Admin->new('localhost') or die "imap: + cannot connect to server: $!\n"; + + $imap->send(undef, undef, "LOGIN %s %s", $user, $passwd) or die + "could not send user:pass to the server: $!\n"; + + for (my $i = 0; $i <= $#entries; $i++) + { + $imap->setquota("user." . $entries[$i]{$mail_attr}, "STORAGE", + $entries[$i]{$quota_attr}) + or die "imap: could not set quota for + user.$entries[$i]{$mail_attr}: $!\n"; + } + + $imap=undef; +} diff --git a/folderxfer b/folderxfer new file mode 100644 index 0000000..095fadc --- /dev/null +++ b/folderxfer @@ -0,0 +1,46 @@ +#!/usr/bin/perl +# +# Usage: folderxfer inputfile +# +# Purpose: Converts contents of Berkeley-format mail folders +# to Cyrus mailboxes +# +# Input: Output of 'bsd2cyrus' +# (username:Cyrus-folder-name:Berkeley-folder-path) +# +# Warnings: The root mailbox and empty Cyrus folder must +# exist before conversion takes place, and source folders +# should be checked for RFC 822 content before being processed +# +#$Id: folderxfer,v 1.1 2004/02/04 12:59:42 karsten Exp $ + +$pwd = "/usr/lib/cyrus-imapd"; +$mailstore = "/var/spool/imap"; # Cyrus mailstore +$cat = "/bin/cat"; +$cmd = "/usr/bin/formail -n 20 -s $pwd/cpmsg"; + +$folders = "$ARGV[0]"; +if (!$folders) { die "Usage: $0 filename"; } + +open (MB,"$folders") || die "can't open $folders"; + +while () { + + chop; + + # Be careful with this split - the last token might have + # whitespace we want to preserve + + ($user,$cyrusfolder,$folder) = split(/:/,$_,3); + @fields = split(/\./,$cyrusfolder); + $cyrfol = $fields[$#fields]; + + $fcat = "$cat \"$folder\""; + print $fcat; + $prefix = substr($user,0,1); + system ("$fcat | $cmd '$mailstore/$prefix/user/$user/$cyrfol'"); + #print "'$mailstore/$prefix/user/$user/$cyrfol"; +} +close MB; + + diff --git a/imapcreate.pl b/imapcreate.pl new file mode 100644 index 0000000..b26af24 --- /dev/null +++ b/imapcreate.pl @@ -0,0 +1,159 @@ +#!/usr/bin/perl -w +# +# imapcreate: create IMAP mailboxes with quotas +# Reads user names from standard input. +# launch without argument for a short help. +# +# originally found on http://cyrus-utils.sourceforge.net +# (could not find any copyright info, thought) +# +# enhanced by Cl�ment "nodens" Hermann +# +# I'd like to consider this as GPL'd (cf www.gnu.org), but won't add any copyright without the original author's consent. +# + +use Getopt::Long; +use Cyrus::IMAP::Admin; +use strict; + + +my $debug; +my $user; +my $pass; +my $quota; +my @part; +my $useunixhierarchy; +my @mailboxes; +my $delete; +my $cyrus; + +sub usage { + print <]] + [-q quota] [-t partition:list] [-s] [-v] + +Options: + -t : the partition to use. Default to the \"default\" partition + -q ; the quota, if a quota is needed. It is normally in KiloBytes, but you can use m,M,g or G suffix to use MB or GB instead, e.g 10k, 2048M or 100g + -m : a comma-separated mailbox list + -u : your cyrus admin user (usually cyrus or cyradm) + -p : your cyrus admin password (if not provided, it will be asked for) + -s : use the unix hierarchy separator (see imapd.conf(1)) + -d : delete mailboxes instead of creating them + -v : run in debug mode, and print information on stdout + +If no password is submitted with -p, we'll prompt for one. +if no mailbox name is specified with -m, read user names from standard input + + examples: + imapcreate -u cyradm -m foo,bar,joe -q 50000 -t p1:p2 mail.testing.umanitoba.ca + cat list.txt | imapcreate -u cyradm -p 'cyruspass' -q 50M mail.testing.umanitoba.ca +EOU + exit 1; +} + +# Create a mailbox... usage : &CreateMailBox(user,partition[,quota]). +# You have to be authentified already. We use "$cyrus" as the connection name. +# partition can be 'default' +sub CreateMailBox { + my $mbuser = $_[0]; + my $mbpart = $_[1]; + my $mbquota = $_[2]; + + print "Creating $mbuser on $mbpart\n" if $debug; + if ($mbpart eq 'default') { + $cyrus->createmailbox($mbuser); + } + else { + $cyrus->createmailbox($mbuser, $mbpart); + } + warn $cyrus->error if $cyrus->error; + + # Set the quota + if ($mbquota) { + print "Setting quota for $mbuser to $mbquota\n" if $debug; + $cyrus->setquota($mbuser, 'STORAGE', $mbquota); + warn $cyrus->error if $cyrus->error; + } +} + +# Delete a mailbox. Usage: $DeleteMailBox($user) +# Assuming we use $user as the admin. +sub DeleteMailBox { + my $mbuser = $_[0]; + my $delacl = "c"; + + print "Deleting $mbuser\n" if $debug; + $cyrus->setaclmailbox($mbuser, $user, $delacl); + $cyrus->deletemailbox($mbuser); + warn $cyrus->error if $cyrus->error; +} + +GetOptions("d|delete" => \$delete, "u|user=s" => \$user, "p|pass=s" => \$pass, "m|mailboxes=s" => \@mailboxes, "q|quota=s" => \$quota, + "t|part=s" => \@part, "s|UnixHierarchy" => \$useunixhierarchy, "v|verbose" => \$debug ); +@part = split(/:/, join(':', @part)); +push @part, 'default' unless @part; +my $pn = 0; +@mailboxes = split(/,/, join(',', @mailboxes)); + +my $server = shift(@ARGV) if (@ARGV); +usage unless $server; + +# quotas formatting: +if ($quota) { + if ($quota =~ /^(\d+)([mk]?)$/i) { + my $numb = $1; + my $letter = $2; + if ($letter =~ /^m$/i) { + $quota = $numb * 1024; + print "debug: quota=$quota\n" if $debug; + } elsif ($letter =~ /^k$/i) { + $quota = $numb; + print "debug: quota=$quota\n" if $debug; + } else { + die "malformed quota: $quota (must be at least one digit eventually followed by m, M, k or K\n"; +# $quota = $numb; +# print "debug: quota=$quota\n" if $debug; + } + } else { + die "malformed quota: $quota (must be at least one digit eventually followed by m, M, k or K\n"; + } +} + +# Authenticate +$cyrus = Cyrus::IMAP::Admin->new($server); +$cyrus->authenticate(-mechanism => 'login', -user => $user, + -password => $pass); +die $cyrus->error if $cyrus->error; + +# if there isn't any mailbox defined yet, get them from standard input +if (! (defined $mailboxes[0])) { + # For all users + while (<>) { + chomp; + my $mbox = $_; + push @mailboxes, $mbox; + } +} + +# create/delete mailboxes for each user +foreach my $mailbox (@mailboxes) { + if ($useunixhierarchy) { + $mailbox = 'user/' . $mailbox; + } else { + $mailbox = 'user.' . $mailbox; + } + + if ($delete) { + &DeleteMailBox($mailbox) + } else { + # Select the partition + my $pt = $part[$pn]; + $pn += 1; + $pn = 0 unless $pn < @part; + &CreateMailBox($mailbox,$pt,$quota) + } +} + diff --git a/inboxfer b/inboxfer new file mode 100644 index 0000000..473aa98 --- /dev/null +++ b/inboxfer @@ -0,0 +1,36 @@ +#!/usr/bin/perl +# +# Usage: inboxfer inputfile +# +# Purpose: Transfer messages from Berkeley-format inbox to Cyrus inbox +# +# Input: Text file containing one username per line +# +# Warning: Do not use this script to transfer messages into a Cyrus +# mailbox that already contain messages. Existing messages +# will be overwritten. +# +#$Id: inboxfer,v 1.1 2004/02/04 12:59:42 karsten Exp $ + +$mailstore = "/var/spool/imap"; # Cyrus mailstore +$oldspool = "/var/spool/mail"; # Old mail spool +$cat = "/bin/cat"; # /usr/bin/cat on Solaris +$formail = "/usr/bin/formail"; +$pwd = "/usr/lib/cyrus-imapd"; +$cpmsg = "cpmsg"; + +$cmd = "$formail -n 20 -s $pwd/$cpmsg"; + +$users = "$ARGV[0]"; +if (!$users) { die "Usage: $0 $users\n"; } + +open(USERS,"$users") || die "can't open $users"; + +while () { + chop; + $inbox = "$oldspool/$_"; + $prefix = substr($_,0,1); + system("$cat $inbox | $cmd $mailstore/$prefix/user/$_"); +} + + diff --git a/sources b/sources index e69de29..ee8ff12 100644 --- a/sources +++ b/sources @@ -0,0 +1,3 @@ +70b3bba526a8d36d3bb23a87d37e9188 cyrus-imapd-2.2.12.tar.gz +f3d52a0eb84ec6c8a127cd4c1bc6af7b cyrus-imapd-README.HOWTO-recover-mailboxes.db +8f7a26b0556369827bb5c8084a3e3ea1 cyrus_sharedbackup-0.1.tar.gz