diff options
Diffstat (limited to 'imap/src')
-rw-r--r-- | imap/src/c-client/imap4r1.c | 2 | ||||
-rw-r--r-- | imap/src/c-client/mail.c | 35 | ||||
-rw-r--r-- | imap/src/c-client/mail.h | 9 | ||||
-rw-r--r-- | imap/src/c-client/nntp.c | 5 | ||||
-rw-r--r-- | imap/src/c-client/pop3.c | 3 | ||||
-rw-r--r-- | imap/src/osdep/unix/Makefile | 8 | ||||
-rw-r--r-- | imap/src/osdep/unix/dummy.c | 48 | ||||
-rw-r--r-- | imap/src/osdep/unix/maildir.c | 2638 | ||||
-rw-r--r-- | imap/src/osdep/unix/maildir.h | 226 | ||||
-rw-r--r-- | imap/src/osdep/unix/os_cyg.h | 1 |
10 files changed, 16 insertions, 2959 deletions
diff --git a/imap/src/c-client/imap4r1.c b/imap/src/c-client/imap4r1.c index 96d1fa19..1409b37d 100644 --- a/imap/src/c-client/imap4r1.c +++ b/imap/src/c-client/imap4r1.c @@ -1156,7 +1156,6 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) } /* no error if protocol-initiated cancel */ lsterr = cpystr (reply->text); - delete_password(mb, usr); } } while (LOCAL->netstream && !LOCAL->byeseen && trial && @@ -1208,7 +1207,6 @@ long imap_login (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) if (imap_OK (stream,reply = imap_send (stream,"LOGIN",args))) ret = LONGT; /* success */ else { - delete_password(mb, usr); mm_log (reply->text,WARN); if (!LOCAL->referral && (trial == imap_maxlogintrials)) mm_log ("Too many login failures",ERROR); diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c index 8fd55265..d80a01f6 100644 --- a/imap/src/c-client/mail.c +++ b/imap/src/c-client/mail.c @@ -52,8 +52,6 @@ static mailcache_t mailcache = mm_cache; static rfc822out_t mail822out = NIL; /* RFC-822 output generator (new style) */ static rfc822outfull_t mail822outfull = NIL; - /* Erase password (client side) */ -static deletepwd_t erase_password = NIL; /* SMTP verbose callback */ static smtpverbose_t mailsmtpverbose = mm_dlog; /* proxy copy routine */ @@ -546,11 +544,6 @@ void *mail_parameters (MAILSTREAM *stream,long function,void *value) case GET_SENDCOMMAND: ret = (void *) mailsendcommand; break; - case SET_ERASEPASSWORD: - erase_password = (deletepwd_t) value; - case GET_ERASEPASSWORD: - ret = (void *) erase_password; - break; case SET_SERVICENAME: servicename = (char *) value; @@ -998,7 +991,7 @@ long mail_create (MAILSTREAM *stream,char *mailbox) MAILSTREAM *ts; char *s,*t,tmp[MAILTMPLEN]; size_t i; - DRIVER *d, *md; + DRIVER *d; /* never allow names with newlines */ if (s = strpbrk (mailbox,"\015\012")) { MM_LOG ("Can't create mailbox with such a name",ERROR); @@ -1022,8 +1015,6 @@ long mail_create (MAILSTREAM *stream,char *mailbox) return NIL; } - /* Hack, we should do this better, but it works */ - for (md = maildrivers; md && strcmp (md->name, "md"); md = md->next); /* see if special driver hack */ if ((mailbox[0] == '#') && ((mailbox[1] == 'd') || (mailbox[1] == 'D')) && ((mailbox[2] == 'r') || (mailbox[2] == 'R')) && @@ -1054,13 +1045,6 @@ long mail_create (MAILSTREAM *stream,char *mailbox) (((*mailbox == '{') || (*mailbox == '#')) && (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT)))) d = stream->dtb; - else if(mailbox[0] == '#' - && (mailbox[1] == 'm' || mailbox[1] == 'M') - && (mailbox[2] == 'd' || mailbox[2] == 'D' - || mailbox[2] == 'c' || mailbox[2] == 'C') - && mailbox[3] == '/' - && mailbox[4] != '\0') - return (*md->create)(stream, mailbox); else if ((*mailbox != '{') && (ts = default_proto (NIL))) d = ts->dtb; else { /* failed utterly */ sprintf (tmp,"Can't create mailbox %.80s: indeterminate format",mailbox); @@ -3368,13 +3352,13 @@ unsigned long mail_filter (char *text,unsigned long len,STRINGLIST *lines, long flags) { STRINGLIST *hdrs; - int notfound, fix = text[len - 1] == '\0'; + int notfound; unsigned long i; char c,*s,*e,*t,tmp[MAILTMPLEN]; char *src = text; char *dst = src; char *end = text + len; - text[fix ? len - 1 : len] = '\012'; /* guard against running off buffer */ + text[len] = '\012'; /* guard against running off buffer */ while (src < end) { /* process header */ /* slurp header line name */ for (s = src,e = s + MAILTMPLEN - 1,e = (e < end ? e : end),t = tmp; @@ -3413,10 +3397,6 @@ unsigned long mail_filter (char *text,unsigned long len,STRINGLIST *lines, } } *dst = '\0'; /* tie off destination */ - if(fix){ - text[len] = '\012'; - text[len-1] = '\0'; - } return dst - text; } @@ -6141,15 +6121,6 @@ unsigned int mail_lookup_auth_name (char *mechanism,long flags) return i; return 0; } -/* Client side callback warning to delete wrong password - * - */ -void delete_password(NETMBX *mb, char *user) -{ - deletepwd_t ep = mail_parameters(NULL, GET_ERASEPASSWORD, NULL); - if (ep) (ep)(mb, user); -} - /* Standard TCP/IP network driver */ diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index 0af362e6..174993e1 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -177,8 +177,6 @@ #define SET_EXTERNALAUTHID (long) 230 #define GET_SSLCAPATH (long) 231 #define SET_SSLCAPATH (long) 232 -#define GET_ERASEPASSWORD (long) 233 -#define SET_ERASEPASSWORD (long) 234 /* 3xx: TCP/IP */ #define GET_OPENTIMEOUT (long) 300 @@ -355,10 +353,6 @@ #define SET_SCANCONTENTS (long) 573 #define GET_MHALLOWINBOX (long) 574 #define SET_MHALLOWINBOX (long) 575 -#define GET_COURIERSTYLE (long) 576 -#define SET_COURIERSTYLE (long) 577 -#define SET_MDINBOXPATH (long) 578 -#define GET_MDINBOXPATH (long) 579 /* Driver flags */ @@ -1332,7 +1326,6 @@ typedef ADDRESS *(*parsephrase_t) (char *phrase,char *end,char *host); typedef void *(*blocknotify_t) (int reason,void *data); typedef long (*kinit_t) (char *host,char *reason); typedef void (*sendcommand_t) (MAILSTREAM *stream,char *cmd,long flags); -typedef void (*deletepwd_t) (NETMBX *mb,char *user); typedef char *(*newsrcquery_t) (MAILSTREAM *stream,char *mulname,char *name); typedef void (*getacl_t) (MAILSTREAM *stream,char *mailbox,ACLLIST *acl); typedef void (*listrights_t) (MAILSTREAM *stream,char *mailbox,char *id, @@ -1612,8 +1605,6 @@ long mm_diskerror (MAILSTREAM *stream,long errcode,long serious); void mm_fatal (char *string); void *mm_cache (MAILSTREAM *stream,unsigned long msgno,long op); -void delete_password (NETMBX *mb, char *user); - extern STRINGDRIVER mail_string; void mail_versioncheck (char *version); void mail_link (DRIVER *driver); diff --git a/imap/src/c-client/nntp.c b/imap/src/c-client/nntp.c index 8fbcb9b7..fe90edba 100644 --- a/imap/src/c-client/nntp.c +++ b/imap/src/c-client/nntp.c @@ -2031,7 +2031,6 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) sprintf (tmp,"Retrying using %s authentication after %.80s", at->name,lsterr); mm_log (tmp,NIL); - delete_password(mb, mb ? mb->user : NULL); fs_give ((void **) &lsterr); } trial = 0; /* initial trial count */ @@ -2040,7 +2039,6 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) if (lsterr) { sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr); mm_log (tmp,WARN); - delete_password(mb, mb ? mb->user : NULL); fs_give ((void **) &lsterr); } stream->saslcancel = NIL; @@ -2066,7 +2064,6 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) sprintf (tmp,"Can not authenticate to NNTP server: %.80s",lsterr); mm_log (tmp,ERROR); } - delete_password(mb, mb ? mb->user : NULL); fs_give ((void **) &lsterr); } else if (mb->secflag) /* no SASL, can't do /secure */ @@ -2095,8 +2092,6 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags) stream->sensitive = T; /* hide this command */ if (nntp_send_work (stream,"AUTHINFO PASS",pwd) == NNTPAUTHED) ret = LONGT; /* password OK */ - else - delete_password(mb, mb ? mb->user : NULL); stream->sensitive = NIL; /* unhide */ if (ret) break; /* OK if successful */ default: /* authentication failed */ diff --git a/imap/src/c-client/pop3.c b/imap/src/c-client/pop3.c index 1b411546..58a9ceb6 100644 --- a/imap/src/c-client/pop3.c +++ b/imap/src/c-client/pop3.c @@ -615,7 +615,6 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) sprintf (pwd,"Retrying using %.80s authentication after %.80s", at->name,t); mm_log (pwd,NIL); - delete_password(mb, usr); fs_give ((void **) &t); } trial = 0; /* initial trial count */ @@ -623,7 +622,6 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) if (t) { sprintf (pwd,"Retrying %s authentication after %.80s",at->name,t); mm_log (pwd,WARN); - delete_password(mb, usr); fs_give ((void **) &t); } LOCAL->saslcancel = NIL; @@ -669,7 +667,6 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr) LOCAL->sensitive=NIL; /* unhide */ } if (!ret) { /* failure */ - delete_password(mb, usr); mm_log (LOCAL->reply,WARN); if (trial == pop3_maxlogintrials) mm_log ("Too many login failures",ERROR); diff --git a/imap/src/osdep/unix/Makefile b/imap/src/osdep/unix/Makefile index ae7b5b9e..78913acc 100644 --- a/imap/src/osdep/unix/Makefile +++ b/imap/src/osdep/unix/Makefile @@ -144,7 +144,7 @@ DEFAULTAUTHENTICATORS=ext md5 pla log # However, mh needs to be before any sysinbox formats (such as mmdf or unix) # since otherwise INBOX won't work correctly when mh_allow_inbox is set. # -DEFAULTDRIVERS=maildir courier imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile +DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile CHUNKSIZE=65536 # Normally no need to change any of these @@ -153,7 +153,7 @@ ARCHIVE=c-client.a BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \ - unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o maildir.o + unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o CFLAGS=-g CAT=cat @@ -290,7 +290,7 @@ cvx: # Convex cyg: # Cygwin - note that most local file drivers don't work!! $(BUILD) `$(CAT) SPECIALS` OS=$@ \ - DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \ + DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \ SPOOLDIR=/var \ ACTIVEFILE=/usr/local/news/lib/active \ @@ -900,7 +900,7 @@ tenex.o: mail.h misc.h osdep.h dummy.h unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h utf8.o: mail.h misc.h osdep.h utf8.h tmap.c widths.c utf8aux.o: mail.h misc.h osdep.h utf8.h -maildir.o: mail.h misc.h osdep.h maildir.h dummy.h + # OS-dependent diff --git a/imap/src/osdep/unix/dummy.c b/imap/src/osdep/unix/dummy.c index 92a2c463..b003a0ba 100644 --- a/imap/src/osdep/unix/dummy.c +++ b/imap/src/osdep/unix/dummy.c @@ -106,19 +106,13 @@ MAILSTREAM dummyproto = {&dummydriver}; * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */ -char * maildir_remove_root(char *); + DRIVER *dummy_valid (char *name) { - char *s,tmp[MAILTMPLEN], *rname; + char *s,tmp[MAILTMPLEN]; struct stat sbuf; - - if(strlen(name) > MAILTMPLEN) - name[MAILTMPLEN] = '\0'; - - strcpy(tmp, name); - rname = maildir_remove_root(tmp); /* must be valid local mailbox */ - if (rname && *rname && (*rname != '{') && (s = mailboxfile (tmp,rname))) { + if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { /* indeterminate clearbox INBOX */ if (!*s) return &dummydriver; else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { @@ -127,9 +121,8 @@ DRIVER *dummy_valid (char *name) return &dummydriver; } /* blackbox INBOX does not exist yet */ - else if (!compare_cstring (rname,"INBOX")) return &dummydriver; + else if (!compare_cstring (name,"INBOX")) return &dummydriver; } - if(rname) fs_give((void **)&rname); return NIL; } @@ -461,8 +454,6 @@ long dummy_create (MAILSTREAM *stream,char *mailbox) { char *s,tmp[MAILTMPLEN]; long ret = NIL; - if(!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4)) - return maildir_create(stream, mailbox); /* validate name */ if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) { sprintf (tmp,"Can't create %.80s: invalid name",mailbox); @@ -528,14 +519,6 @@ long dummy_delete (MAILSTREAM *stream,char *mailbox) { struct stat sbuf; char *s,tmp[MAILTMPLEN]; - if (!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4) - || is_valid_maildir(&mailbox)){ - char tmp[MAILTMPLEN] = {'\0'}; - strcpy(tmp, mailbox); - if(tmp[strlen(tmp) - 1] != '/') - tmp[strlen(tmp)] = '/'; - return maildir_delete(stream, tmp); - } if (!(s = dummy_file (tmp,mailbox))) { sprintf (tmp,"Can't delete - invalid name: %.80s",s); MM_LOG (tmp,ERROR); @@ -561,23 +544,12 @@ long dummy_delete (MAILSTREAM *stream,char *mailbox) long dummy_rename (MAILSTREAM *stream,char *old,char *newname) { struct stat sbuf; - char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN], *rold, *rnewname; - - if(strlen(old) > MAILTMPLEN) - old[MAILTMPLEN] = '\0'; - - if(strlen(newname) > MAILTMPLEN) - newname[MAILTMPLEN] = '\0'; - - strcpy(tmp, old); - rold = maildir_remove_root(tmp); - strcpy(tmp, newname); - rnewname = maildir_remove_root(tmp); + char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; /* no trailing / allowed */ - if (!dummy_file (oldname,rold) || !(s = dummy_file (mbx,rnewname)) || + if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] && ((sbuf.st_mode & S_IFMT) != S_IFDIR))) { - sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",rold,rnewname); + sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname); MM_LOG (mbx,ERROR); return NIL; } @@ -593,16 +565,14 @@ long dummy_rename (MAILSTREAM *stream,char *old,char *newname) } } /* rename of non-ex INBOX creates dest */ - if (!compare_cstring (rold,"INBOX") && stat (oldname,&sbuf)) + if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf)) return dummy_create (NIL,mbx); if (rename (oldname,mbx)) { - sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",rold,rnewname, + sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname, strerror (errno)); MM_LOG (tmp,ERROR); return NIL; } - if(rold) fs_give((void **)&rold); - if(rnewname) fs_give((void **)&rnewname); return T; /* return success */ } diff --git a/imap/src/osdep/unix/maildir.c b/imap/src/osdep/unix/maildir.c deleted file mode 100644 index b15adc87..00000000 --- a/imap/src/osdep/unix/maildir.c +++ /dev/null @@ -1,2638 +0,0 @@ -/* - * Maildir driver for Alpine 2.11 - * - * Written by Eduardo Chappa <chappa@gmx.com> - * Last Update: May 29, 2011. - * - */ - -#include <stdio.h> -#include <ctype.h> -#include <errno.h> -extern int errno; /* just in case */ -#include "mail.h" -#include <pwd.h> -#include <sys/stat.h> -#include <sys/time.h> -#include "osdep.h" -#include "rfc822.h" -#include "fdstring.h" -#include "misc.h" -#include "dummy.h" -#include "maildir.h" - -/* Driver dispatch used by MAIL */ -DRIVER maildirdriver = { - "md", /* driver name, yes it's md, not maildir */ - DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT, /* driver flags */ - (DRIVER *) NIL, /* next driver */ - maildir_valid, /* mailbox is valid for us */ - maildir_parameters, /* manipulate parameters */ - NIL, /* scan mailboxes */ - maildir_list, /* find mailboxes */ - maildir_lsub, /* find subscribed mailboxes */ - maildir_sub, /* subscribe to mailbox */ - maildir_unsub, /* unsubscribe from mailbox */ - maildir_create, /* create mailbox */ - maildir_delete, /* delete mailbox */ - maildir_rename, /* rename mailbox */ - mail_status_default, /* status of mailbox */ - maildir_open, /* open mailbox */ - maildir_close, /* close mailbox */ - maildir_fast, /* fetch message "fast" attributes */ - NIL, /* fetch message flags */ - NIL, /* fetch overview */ - NIL, /* fetch message structure */ - maildir_header, /* fetch message header */ - maildir_text, /* fetch message body */ - NIL, /* fetch partial message text */ - NIL, /* unique identifier */ - NIL, /* message number */ - NIL, /* modify flags */ - maildir_flagmsg, /* per-message modify flags */ - NIL, /* search for message based on criteria */ - NIL, /* sort messages */ - NIL, /* thread messages */ - maildir_ping, /* ping mailbox to see if still alive */ - maildir_check, /* check for new messages */ - maildir_expunge, /* expunge deleted messages */ - maildir_copy, /* copy messages to another mailbox */ - maildir_append, /* append string message to mailbox */ - NIL /* garbage collect stream */ -}; - - -DRIVER courierdriver = { - "mc", /* Why a separate driver? So that createproto will work */ - DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_DIRFMT, /* driver flags */ - (DRIVER *) NIL, /* next driver */ - maildir_valid, /* mailbox is valid for us */ - maildir_parameters, /* manipulate parameters */ - NIL, /* scan mailboxes */ - courier_list, /* find mailboxes */ - maildir_lsub, /* find subscribed mailboxes */ - maildir_sub, /* subscribe to mailbox */ - maildir_unsub, /* unsubscribe from mailbox */ - maildir_create, /* create mailbox */ - maildir_delete, /* delete mailbox */ - maildir_rename, /* rename mailbox */ - mail_status_default, /* status of mailbox */ - maildir_open, /* open mailbox */ - maildir_close, /* close mailbox */ - maildir_fast, /* fetch message "fast" attributes */ - NIL, /* fetch message flags */ - NIL, /* fetch overview */ - NIL, /* fetch message structure */ - maildir_header, /* fetch message header */ - maildir_text, /* fetch message body */ - NIL, /* fetch partial message text */ - NIL, /* unique identifier */ - NIL, /* message number */ - NIL, /* modify flags */ - maildir_flagmsg, /* per-message modify flags */ - NIL, /* search for message based on criteria */ - NIL, /* sort messages */ - NIL, /* thread messages */ - maildir_ping, /* ping mailbox to see if still alive */ - maildir_check, /* check for new messages */ - maildir_expunge, /* expunge deleted messages */ - maildir_copy, /* copy messages to another mailbox */ - maildir_append, /* append string message to mailbox */ - NIL /* garbage collect stream */ -}; - -MAILSTREAM maildirproto = {&maildirdriver}; /* prototype stream */ -MAILSTREAM courierproto = {&courierdriver}; /* prototype stream */ - -long maildir_dirfmttest (char *name) -{ - int i; - for (i = 0; mdstruct[i] && strcmp(name, mdstruct[i]); i++); - return (i < EndDir) || !strcmp(name, MDDIR) - || !strncmp(name, MDUIDLAST, strlen(MDUIDLAST)) - || !strncmp(name, MDUIDTEMP, strlen(MDUIDTEMP)) ? LONGT : NIL; -} - -void -md_domain_name(void) -{ - int i, j; - - strcpy(mdlocaldomain, mylocalhost ()); - for (i = 0; mdlocaldomain[i] != '\0' ;) - if(mdlocaldomain[i] == '/' || mdlocaldomain[i] == ':'){ - for(j = strlen(mdlocaldomain); j >= i; j--) - mdlocaldomain[j+4] = mdlocaldomain[j]; - mdlocaldomain[i++] = '\\'; - mdlocaldomain[i++] = '0'; - if(mdlocaldomain[i] == '/'){ - mdlocaldomain[i++] = '5'; - mdlocaldomain[i++] = '7'; - } else { - mdlocaldomain[i++] = '7'; - mdlocaldomain[i++] = '2'; - } - } - else - i++; -} - -char * -myrootdir(char *name) -{ -return myhomedir(); -} - -char * -mdirpath(void) -{ - char *path = maildir_parameters(GET_MDINBOXPATH, NIL); - return path ? (path[0] ? path : ".") : "Maildir"; -} - -/* remove the "#md/" or "#mc/" part from a folder name - * memory freed by caller - */ -char * -maildir_remove_root (char *name) -{ - int courier = IS_COURIER(name), offset; - char realname[MAILTMPLEN]; - - offset = maildir_valid_name(name) ? (name[3] == '/' ? 4 : 3) : 0; - if(courier) - courier_realname(name+offset, realname); - else - strcpy(realname, name+offset); - return cpystr(realname); -} - - -/* Check validity of the name, we accept: - * a) #md/directory/folder - * b) #md/inbox - * A few considerations: We can only accept as valid - * a) names that start with #md/ and the directory exists or - * b) names that do not start with #md/ but are maildir directories (have - * the /cur, /tmp and /new structure) - */ -int maildir_valid_name (char *name) -{ - char tmpname[MAILTMPLEN] = {'\0'}; - - if (mdfpath) - fs_give((void **)&mdfpath); - if (name && (name[0] != '#')) - snprintf(tmpname, sizeof(tmpname), "%s%s",MDPREFIX(CCLIENT), name); - mdfpath = cpystr(tmpname[0] ? tmpname : name); - - return IS_CCLIENT(name) || IS_COURIER(name); -} - -/* Check if the directory whose path is given by name is a valid maildir - * directory (contains /cur, /tmp and /new) - */ -int maildir_valid_dir (char *name) -{ - int len; - DirNamesType i; - struct stat sbuf; - char tmp[MAILTMPLEN]; - - if(name[strlen(name) - 1] == '/') - name[strlen(name) - 1] = '\0'; - len = strlen(name); - for (i = Cur; i != EndDir; i++){ - MDFLD(tmp, name, i); - if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)) - break; - } - name[len] = '\0'; - return (i == EndDir) ? T : NIL; -} - -void courier_realname(char *name, char *realname) -{ - int i,j; - - if(!name) - return; - - for (i = 0, j = 0; i < MAILTMPLEN && j < strlen(name); j++, i++){ - realname[i] = name[j]; - if(name[j] == '/' && name[j+1] != '.' && name[j+1] != '%' - && name[j+1] != '*') - realname[++i] = '.'; - } - if(realname[i-1] == '.') - i--; - realname[i] = '\0'; -} - - -/* given a maildir folder, return its path. Memory freed by caller. Directory - * does not contain the trailing slash "/". On error NULL is returned. - */ -int maildir_file_path (char *name, char *tmp, size_t sizeoftmp) -{ - char *maildirpath = mdirpath(), *rname; - int courier = IS_COURIER(name); - - /* There are several ways in which the path can come, so we will handle - them here. First we deal with #mc/ or #md/ prefix by removing the - prefix, if any */ - - if(strlen(name) >= MAILTMPLEN) - name[MAILTMPLEN] = '\0'; - strcpy(tmp, name); - rname = maildir_remove_root(tmp); - tmp[0] = '\0'; /* just in case something fails */ - - if (strlen(myrootdir(rname)) + - max(strlen(rname), strlen(maildirpath)) > sizeoftmp){ - errno = ENAMETOOLONG; - snprintf(tmp, sizeoftmp, "Error opening \"%s\": %s", rname, strerror (errno)); - mm_log(tmp,ERROR); - if(rname) fs_give((void **)&rname); - return NIL; - } - - /* There are two ways in which the name can come here, either as a - full path or not. If it is not a full path it can come in two ways, - either as a file system path (Maildir/.Drafts) or as a maildir path - (INBOX.Drafts) - */ - - if(*rname == '/'){ /* full path */ - strncpy(tmp, rname, sizeoftmp); /* do nothing */ - tmp[sizeoftmp-1] = '\0'; - } - else - snprintf (tmp, sizeoftmp, "%s/%s%s%s", myrootdir (rname), - strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) - ? rname : maildirpath, - strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) - ? "" : (courier ? "/" : ""), - strncmp (ucase (strcpy (tmp, rname)), "INBOX", 5) - ? "" : (*(rname+5) == MDSEPARATOR(courier) ? rname+5 : "")); - if(rname) fs_give((void **)&rname); - return tmp[0] ? T : NIL; -} - -/* This function is given a full path for a mailbox and returns - * if it is a valid maildir transformed to canonical notation - */ -int -is_valid_maildir (char **name) -{ - if (!strncmp(*name, myrootdir (*name), strlen(myrootdir(*name)))){ - (*name) += strlen(myrootdir(*name)); - if (**name == '/') (*name)++; - } - return maildir_valid(*name) ? T : NIL; -} - -/* Check validity of mailbox. This routine does not send errors to log, other - * routines calling this one may do so, though - */ - -DRIVER *maildir_valid (char *name) -{ - char tmpname[MAILTMPLEN]; - - maildir_file_path(name, tmpname, sizeof(tmpname)); - - return maildir_valid_dir(tmpname) - ? (IS_COURIER(name) ? &courierdriver : &maildirdriver) : NIL; -} - -void maildir_fast (MAILSTREAM *stream,char *sequence,long flags) -{ - unsigned long i; - MESSAGECACHE *elt; - /* get sequence */ - if (stream && LOCAL && ((flags & FT_UID) ? - mail_uid_sequence (stream,sequence) : - mail_sequence (stream,sequence))) - for (i = 1L; i <= stream->nmsgs; i++) { - if ((elt = mail_elt (stream,i))->sequence && (elt->valid = T) && - !(elt->day && elt->rfc822_size)) { - ENVELOPE **env = NIL; - ENVELOPE *e = NIL; - if (!stream->scache) env = &elt->private.msg.env; - else if (stream->msgno == i) env = &stream->env; - else env = &e; - if (!*env || !elt->rfc822_size) { - STRING bs; - unsigned long hs; - char *ht = (*stream->dtb->header) (stream,i,&hs,NIL); - - if (!*env) rfc822_parse_msg (env,NIL,ht,hs,NIL,BADHOST, - stream->dtb->flags); - if (!elt->rfc822_size) { - (*stream->dtb->text) (stream,i,&bs,FT_PEEK); - elt->rfc822_size = hs + SIZE (&bs) - GETPOS (&bs); - } - } - - if (!elt->day && *env && (*env)->date) - mail_parse_date (elt,(*env)->date); - - if (!elt->day) elt->day = elt->month = 1; - mail_free_envelope (&e); - } - } -} - -int -maildir_eliminate_duplicate (char *name, struct direct ***flist, unsigned long *nfiles) -{ - int i, j, k, error = 0, scanr; - char new[MAILTMPLEN], old[MAILTMPLEN], tmp[MAILTMPLEN], *str; - struct direct **names = NIL; - - if((scanr = maildir_doscandir(name, &names, CCLIENT)) < 0) - return -1; - - if(nfiles) *nfiles = scanr; - for(i = 0, j = 1, k = 0; j < scanr; i++, j++){ - if(k) - names[i] = names[i+k]; - if(same_maildir_file(names[i]->d_name, names[j]->d_name)){ - int d, f, r, s; - maildir_getflag(names[i]->d_name, &d, &f, &r, &s, NIL); - snprintf(old, sizeof(old), "%s/%s", name, names[i]->d_name); - snprintf(new, sizeof(new), "%s/.%s", name, names[i]->d_name); - if(rename(old, new) < 0 && errno != EEXIST) - error++; - if(!error){ - for(; j < scanr - && same_maildir_file(names[i]->d_name, names[j]->d_name) - ; j++, k++){ - maildir_getflag(names[j]->d_name, (d ? NIL : &d), - (f ? NIL : &f), (r ? NIL : &r), (s ? NIL : &s), NIL); - snprintf(tmp, sizeof(tmp), "%s/%s", name, names[j]->d_name); - if(unlink(tmp) < 0){ /* Hmmm... a problem, let's see */ - struct stat sbuf; - if (stat(tmp, &sbuf) == 0 && (sbuf.st_mode & S_IFMT) == S_IFREG) - error++; - } - } - if((str = strrchr(names[i]->d_name,FLAGSEP)) != NULL) *str = '\0'; - snprintf (old, sizeof(old), "%s/%s%s%s%s%s%s", name, names[i]->d_name, MDSEP(2), - MDFLAG(Draft, d), MDFLAG(Flagged, f), MDFLAG(Replied, r), - MDFLAG(Seen, s)); - if(rename(new, old) < 0) - error++; - } - } - - } - if(k > 0) - fs_give((void **)&names); - else - *flist = names; - return error ? -1 : k; -} - -int -maildir_doscandir(char *name, struct direct ***flist, int flag) -{ -return scandir(name, flist, - flag == CCLIENT ? maildir_select : courier_dir_select, - flag == CCLIENT ? maildir_namesort : courier_dir_sort); -} - -/* - * return all files in a given directory. This is a separate call - * so that if there are warnings during compilation this only appears once. - */ -unsigned long -maildir_scandir (char *name, struct direct ***flist, - unsigned long *nfiles, int *scand, int flag) -{ - struct stat sbuf; - int rv = -2; /* impossible value */ - - if (scand) - *scand = -1; /* assume error for safety */ - *nfiles = 0; - if((stat(name,&sbuf) < 0) - || (flag == CCLIENT - && ((rv = maildir_eliminate_duplicate(name, flist, nfiles)) < 0))) - return 0L; - - if (scand && (rv > 0 || rv == -2)) - *nfiles = maildir_doscandir(name, flist, flag); - - if(scand) *scand = *nfiles; - - return (unsigned long) sbuf.st_ctime; -} - -/* Does a message with given name exists (or was it removed)? - * Returns: 1 - yes, such message exist, - * 0 - No, that message does not exist anymore - * - * Parameters: stream, name of mailbox, new name if his message does not - * exist. - */ - -int maildir_message_exists(MAILSTREAM *stream, char *name, char *newfile) -{ - char tmp[MAILTMPLEN]; - int gotit = NIL; - DIR *dir; - struct direct *d; - struct stat sbuf; - - /* First check directly if it exists, if not there, look for it */ - snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->path[Cur], name); - if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG)) - return T; - - if (!(dir = opendir (LOCAL->path[Cur]))) - return NIL; - - while ((d = readdir(dir)) && gotit == NIL){ - if (d->d_name[0] == '.') - continue; - if (same_maildir_file(d->d_name, name)){ - gotit = T; - strcpy(newfile, d->d_name); - } - } - closedir(dir); - return gotit; -} - -/* Maildir open */ - -MAILSTREAM *maildir_open (MAILSTREAM *stream) -{ - char tmp[MAILTMPLEN]; - struct stat sbuf; - - if (!stream) return &maildirproto; - if (stream->local) fatal ("maildir recycle stream"); - md_domain_name(); /* get domain name for maildir files in mdlocaldomain */ - if(mypid == (pid_t) 0) - mypid = getpid(); - if (!stream->rdonly){ - stream->perm_seen = stream->perm_deleted = stream->perm_flagged = - stream->perm_answered = stream->perm_draft = T; - } - stream->local = (MAILDIRLOCAL *) fs_get (sizeof (MAILDIRLOCAL)); - memset(LOCAL, 0, sizeof(MAILDIRLOCAL)); - LOCAL->fd = -1; - - LOCAL->courier = IS_COURIER(stream->mailbox); - strcpy(tmp, stream->mailbox); - if (maildir_file_path (stream->mailbox, tmp, sizeof(tmp))) - LOCAL->dir = cpystr (tmp); - LOCAL->candouid = maildir_can_assign_uid(stream); - maildir_read_uid(stream, &stream->uid_last, &stream->uid_validity); - if (LOCAL->dir){ - LOCAL->path = (char **) fs_get(EndDir*sizeof(char *)); - MDFLD(tmp, LOCAL->dir, Cur); LOCAL->path[Cur] = cpystr (tmp); - MDFLD(tmp, LOCAL->dir, New); LOCAL->path[New] = cpystr (tmp); - MDFLD(tmp, LOCAL->dir, Tmp); LOCAL->path[Tmp] = cpystr (tmp); - if (stat (LOCAL->path[Cur],&sbuf) < 0) { - snprintf (tmp, sizeof(tmp), "Can't open folder %s: %s", - stream->mailbox,strerror (errno)); - mm_log (tmp,ERROR); - maildir_close(stream, 0); - return NIL; - } - } - - if(maildir_file_path (stream->mailbox, tmp, sizeof(tmp))){ - fs_give ((void **) &stream->mailbox); - stream->mailbox = cpystr(tmp); - } - - LOCAL->buf = (char *) fs_get (CHUNKSIZE); - LOCAL->buflen = CHUNKSIZE - 1; - stream->sequence++; - stream->nmsgs = stream->recent = 0L; - - maildir_parse_folder(stream, 1); - - return stream; -} - -/* Maildir initial parsing of the folder */ -void -maildir_parse_folder (MAILSTREAM *stream, int full) -{ - char tmp[MAILTMPLEN]; - struct direct **namescur = NIL, **namesnew = NIL; - unsigned long i, nfilescur = 0L, nfilesnew = 0L, oldpos, newpos, total; - int scan_err, rescan, loop = 0; - - if (!stream) /* what??? */ - return; - - MM_CRITICAL(stream); - - maildir_scandir (LOCAL->path[New], &namesnew, &nfilesnew, &scan_err, CCLIENT); - if (scan_err < 0) - maildir_abort(stream); - - /* Scan old messages first, escoba! */ - if(stream->rdonly || - (LOCAL && ((maildir_initial_check(stream, Cur) == 0) - || nfilesnew > 0L))){ - LOCAL->scantime = maildir_scandir (LOCAL->path[Cur], &namescur, &nfilescur, - &scan_err, CCLIENT); - if (scan_err < 0){ - if(namesnew){ - for(i = 0L; i < nfilesnew; i++) - fs_give((void **)&namesnew[i]); - fs_give((void **) &namesnew); - } - maildir_abort(stream); - } - } - if(LOCAL && (maildir_initial_check(stream, New) == 0) - && (nfilescur > 0L)){ - while(LOCAL && loop < 10){ - if(nfilesnew == 0L) - maildir_scandir (LOCAL->path[New], &namesnew, &nfilesnew, &scan_err, CCLIENT); - if (scan_err < 0){ - if(namesnew){ - for(i = 0L; i < nfilesnew; i++) - fs_give((void **)&namesnew[i]); - fs_give((void **) &namesnew); - } - maildir_abort(stream); - break; - } - for(i = 0L, rescan = 0, newpos = oldpos = 0L; - newpos < nfilescur && i < nfilesnew; i++){ - if(maildir_message_in_list(namesnew[i]->d_name, namescur, oldpos, - nfilescur - 1L, &newpos)){ - oldpos = newpos; - snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->path[New], namesnew[i]->d_name); - if(unlink(tmp) < 0) - scan_err = -1; - rescan++; - } - else - newpos = oldpos; - } - if(scan_err < 0) - maildir_abort(stream); - if(rescan == 0) - break; - else{ /* restart */ - if(namesnew){ - for(i = 0L; i < nfilesnew; i++) - fs_give((void **)&namesnew[i]); - fs_give((void **) &namesnew); - } - nfilesnew = 0L; - loop++; - } - } - } - if(loop == 10) - maildir_abort(stream); - if(LOCAL){ - if(stream->rdonly) - stream->recent = 0L; - total = namescur || stream->rdonly - ? maildir_parse_dir(stream, 0L, Cur, namescur, - nfilescur, full) : stream->nmsgs; - stream->nmsgs = maildir_parse_dir(stream, total, New, namesnew, - nfilesnew, full); - } - if(namesnew){ - for(i = 0L; i < nfilesnew; i++) - fs_give((void **)&namesnew[i]); - fs_give((void **) &namesnew); - } - if(namescur){ - for(i = 0L; i < nfilescur; i++) - fs_give((void **)&namescur[i]); - fs_give((void **) &namescur); - } - MM_NOCRITICAL(stream); -} - -int -maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype) -{ - char *tmp; - struct stat sbuf; - - if (access (LOCAL->path[dirtype], R_OK|W_OK|X_OK) != 0){ - maildir_abort(stream); - return -1; - } - - if (dirtype != New && - (stat(LOCAL->path[Cur], &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime)) - return -1; - return 0; -} - - -/* Return the number of messages in the directory, while filling the - * elt structure. - */ - -unsigned long -maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, - DirNamesType dirtype, struct direct **names, - unsigned long nfiles, int full) -{ - char tmp[MAILTMPLEN], file[MAILTMPLEN], newfile[MAILTMPLEN], *mdstr; - struct stat sbuf; - unsigned long i, new = 0L, l, uid_last; - unsigned long recent = stream ? stream->recent : 0L; - int d = 0, f = 0, r = 0, s = 0, t = 0; - int we_compute, in_list; - int silent = stream ? stream->silent : NIL; - MESSAGECACHE *elt; - - if (dirtype == Cur && !stream->rdonly) - for (i = 1L; i <= stream->nmsgs;){ - elt = mail_elt(stream, i); - in_list = elt && elt->private.spare.ptr && nfiles > 0L - ? (MDPOS(elt) < nfiles - ? same_maildir_file(MDFILE(elt), names[MDPOS(elt)]->d_name) - : NIL) - || maildir_message_in_list(MDFILE(elt), names, 0L, - nfiles - 1L, &MDPOS(elt)) - : NIL; - if (!in_list){ - if (elt->private.spare.ptr) - maildir_free_file ((void **) &elt->private.spare.ptr); - - if (elt->recent) --recent; - mail_expunged(stream,i); - } - else i++; - } - - stream->silent = T; - uid_last = 0L; - for (we_compute = 0, i = l = 1L; l <= nfiles; l++){ - unsigned long pos, uid; - if (dirtype == New && !stream->rdonly){ /* move new messages to cur */ - pos = l - 1L; - snprintf (file, sizeof(file), "%s/%s", LOCAL->path[New], names[pos]->d_name); - if(lstat(file,&sbuf) == 0) - switch(sbuf.st_mode & S_IFMT){ - case S_IFREG: - strcpy(tmp, names[pos]->d_name); - if((mdstr = strstr(tmp,MDSEP(3))) - || (mdstr = strstr(tmp,MDSEP(2)))) - *(mdstr+1) = '2'; - else - strcat(tmp, MDSEP(2)); - snprintf(newfile, sizeof(newfile), "%s/%s", LOCAL->path[Cur], tmp); - if(rename (file, newfile) != 0){ - mm_log("Unable to read new mail!", WARN); - continue; - } - unlink (file); - new++; - break; - case S_IFLNK: /* clean up, clean up, everybody, everywhere */ - if(unlink(file) < 0){ - if(LOCAL->link == NIL){ - mm_log("Unable to remove symbolic link", WARN); - LOCAL->link = T; - } - } - continue; - break; - default: - if(LOCAL && LOCAL->link == NIL){ - mm_log("Unrecognized file or link in folder", WARN); - LOCAL->link = T; - } - continue; - break; - } - } - mail_exists(stream, i + nmsgs); - elt = mail_elt(stream, i + nmsgs); - pos = (elt && elt->private.spare.ptr) ? MDPOS(elt) : l - 1L; - if (dirtype == New) elt->recent = T; - maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t); - if (elt->private.spare.ptr) - maildir_free_file_only ((void **)&elt->private.spare.ptr); - else{ - maildir_get_file((MAILDIRFILE **)&elt->private.spare.ptr); - we_compute++; - } - MDFILE(elt) = cpystr(names[pos]->d_name); - MDPOS(elt) = pos; - MDLOC(elt) = dirtype; - if (dirtype == Cur){ /* deal with UIDs */ - if(elt->private.uid == 0L) - elt->private.uid = maildir_get_uid(MDFILE(elt)); - if(elt->private.uid <= uid_last){ - uid = (we_compute ? uid_last : stream->uid_last) + 1L; - if(LOCAL->candouid) - maildir_assign_uid(stream, i + nmsgs, uid); - else - elt->private.uid = uid; - } - else - uid = elt->private.uid; - uid_last = uid; - if(uid_last > stream->uid_last) - stream->uid_last = uid_last; - } - if(dirtype == New && !stream->rdonly){ - maildir_free_file_only((void **)&elt->private.spare.ptr); - MDFILE(elt) = cpystr(tmp); - MDSIZE(elt) = sbuf.st_size; - MDMTIME(elt) = sbuf.st_mtime; - MDLOC(elt) = Cur; - } - if (elt->draft != d || elt->flagged != f || - elt->answered != r || elt->seen != s || elt->deleted != t){ - elt->draft = d; elt->flagged = f; elt->answered = r; - elt->seen = s; elt->deleted = t; - if (!we_compute && !stream->rdonly) - MM_FLAGS(stream, i+nmsgs); - } - maildir_get_date(stream, i+nmsgs); - elt->valid = T; - i++; - } - stream->silent = silent; - if(LOCAL->candouid && dirtype == Cur) - maildir_read_uid(stream, NULL, &stream->uid_validity); - if (dirtype == New && stream->rdonly) - new = nfiles; - mail_exists(stream, nmsgs + ((dirtype == New) ? new : nfiles)); - mail_recent(stream, recent + ((dirtype == New) ? new : 0L)); - - return (nmsgs + (dirtype == New ? new : nfiles)); -} - -long maildir_ping (MAILSTREAM *stream) -{ - maildir_parse_folder(stream, 0); - if(stream && LOCAL){ - if(LOCAL->candouid < 0) - LOCAL->candouid++; - else if(LOCAL->candouid) - maildir_uid_renew_tempfile(stream); - else /* try again to get uids */ - LOCAL->candouid = maildir_can_assign_uid(stream); - } - return stream && LOCAL ? LONGT : NIL; -} - -int maildir_select (const struct direct *name) -{ - return (name->d_name[0] != '.'); -} - -/* - * Unfortunately, there is no way to sort by arrival in this driver, this - * means that opening a folder in this driver using the scandir function - * will always make this driver slower than any driver that has a natural - * way of sorting by arrival (like a flat file format, "mbox", "mbx", etc). - */ -int maildir_namesort (const struct direct **d1, const struct direct **d2) -{ - const struct direct *e1 = *(const struct direct **) d1; - const struct direct *e2 = *(const struct direct **) d2; - - return comp_maildir_file((char *) e1->d_name, (char *) e2->d_name); -} - -/* Maildir close */ - -void maildir_close (MAILSTREAM *stream, long options) -{ - MESSAGECACHE *elt; - unsigned long i; - int silent = stream ? stream->silent : 0; - mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL); - - if (!stream) return; - - for (i = 1L; i <= stream->nmsgs; i++) - if((elt = (MESSAGECACHE *) (*mc)(stream,i,CH_ELT)) && elt->private.spare.ptr) - maildir_free_file ((void **) &elt->private.spare.ptr); - stream->silent = T; - if (options & CL_EXPUNGE) maildir_expunge (stream, NIL, NIL); - maildir_abort(stream); - if (mdfpath) fs_give((void **)&mdfpath); - if (mypid) mypid = (pid_t) 0; - stream->silent = silent; -} - -void maildir_check (MAILSTREAM *stream) -{ - if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL); -} - -long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags) -{ - char tmp[MAILTMPLEN]; - unsigned long i; - MESSAGECACHE *elt; - char *s; - /* UID call "impossible" */ - if (flags & FT_UID || !LOCAL) return NIL; - elt = mail_elt (stream, msgno); - - if (!(flags & FT_PEEK) && !elt->seen){ - elt->seen = T; - maildir_flagmsg (stream, elt); - MM_FLAGS(stream, elt->msgno); - } - - MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); - if (LOCAL->fd < 0) /* if file closed ? */ - LOCAL->fd = open(tmp,O_RDONLY,NIL); - - if (LOCAL->fd < 0 && (errno == EACCES || errno == ENOENT)){ - INIT (bs, mail_string, "", 0); - elt->rfc822_size = 0L; - return NIL; - } - - s = maildir_text_work(stream, elt, &i, flags); - INIT (bs, mail_string, s, i); - return LONGT; -} - -char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, - unsigned long *length,long flags) -{ - FDDATA d; - STRING bs; - char *s,tmp[CHUNK]; - unsigned long msgno = elt->msgno; - static int try = 0; - - if (length) - *length = 0L; - LOCAL->buf[0] = '\0'; - - MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); - if (LOCAL->fd < 0) /* if file closed ? */ - LOCAL->fd = open(tmp,O_RDONLY,NIL); - - if (LOCAL->fd < 0){ /* flag change? */ - if (try < 5){ - try++; - if (maildir_update_elt_maildirp(stream, msgno) > 0) - try = 0; - return maildir_text_work(stream, mail_elt(stream, msgno),length, flags); - } - try = 0; - return NULL; - } - - lseek (LOCAL->fd, elt->private.msg.text.offset,L_SET); - - if (flags & FT_INTERNAL) { /* initial data OK? */ - if (elt->private.msg.text.text.size > LOCAL->buflen) { - fs_give ((void **) &LOCAL->buf); - LOCAL->buf = (char *) fs_get ((LOCAL->buflen = - elt->private.msg.text.text.size) + 1); - } - read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size); - LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0'; - } - else { - if (elt->rfc822_size > LOCAL->buflen) { - fs_give ((void **) &LOCAL->buf); - LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->rfc822_size) + 1); - } - d.fd = LOCAL->fd; /* yes, set up file descriptor */ - d.pos = elt->private.msg.text.offset; - d.chunk = tmp; /* initial buffer chunk */ - d.chunksize = CHUNK; - INIT (&bs,fd_string,&d,elt->private.msg.text.text.size); - for (s = LOCAL->buf; SIZE (&bs);) switch (CHR (&bs)) { - case '\r': /* carriage return seen */ - *s++ = SNX (&bs); /* copy it and any succeeding LF */ - if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs); - break; - case '\n': - *s++ = '\r'; /* insert a CR */ - default: - *s++ = SNX (&bs); /* copy characters */ - } - *s = '\0'; /* tie off buffer */ - *length = s - (char *) LOCAL->buf; /* calculate length */ - } - close(LOCAL->fd); LOCAL->fd = -1; - return LOCAL->buf; -} - -/* maildir parse, fill the elt structure... well not all of it... */ -unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno, - DirNamesType dirtype) -{ - char *b, *s, *t, c; - char tmp[MAILTMPLEN]; - struct stat sbuf; - unsigned long i, len; - int d, f, r, se, dt; - MESSAGECACHE *elt; - - elt = mail_elt (stream,msgno); - MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype); - if(stat(tmp, &sbuf) == 0) - MDSIZE(elt) = sbuf.st_size; - - maildir_get_date(stream, msgno); - maildir_getflag(MDFILE(elt), &d, &f, &r ,&se, &dt); - elt->draft = d; elt->flagged = f; elt->answered = r; elt->seen = se; - elt->deleted = dt; elt->valid = T; - if (LOCAL->fd < 0) /* if file closed ? */ - LOCAL->fd = open(tmp,O_RDONLY,NIL); - - if (LOCAL->fd >= 0){ - s = (char *) fs_get (MDSIZE(elt) + 1); - read (LOCAL->fd,s,MDSIZE(elt)); - s[MDSIZE(elt)] = '\0'; - t = s + strlen(s); /* make t point to the end of s */ - for (i = 0L, b = s; b < t && !(i && (*b == '\n')); i = (*b++ == '\n')); - len = (*b ? ++b : b) - s; - elt->private.msg.header.text.size = - elt->private.msg.text.offset = len; - elt->private.msg.text.text.size = MDSIZE(elt) - len; - for (i = 0L, b = s, c = *b; b && - ((c < '\016' && ((c == '\012' && ++i) - ||(c == '\015' && *(b+1) == '\012' && ++b && (i +=2)))) - || b < t); i++, c= *++b); - elt->rfc822_size = i; - fs_give ((void **) &s); - close(LOCAL->fd); LOCAL->fd = -1; - } - return elt->rfc822_size; -} - -int -maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno) -{ - struct direct **names = NIL; - unsigned long i, nfiles, pos; - int d = 0, f = 0 , r = 0, s = 0, t = 0, in_list, scan_err; - MESSAGECACHE *elt; - - maildir_scandir (LOCAL->path[Cur], &names, &nfiles, &scan_err, CCLIENT); - - elt = mail_elt (stream,msgno); - - in_list = nfiles > 0L - ? maildir_message_in_list(MDFILE(elt), names, 0L, nfiles - 1L, &pos) - : NIL; - - if (in_list && pos >= 0L && pos < nfiles - && !strcmp(MDFILE(elt), names[pos]->d_name)){ - in_list = NIL; - maildir_abort(stream); - } - - if (in_list && pos >= 0L && pos < nfiles){ - maildir_free_file_only((void **)&elt->private.spare.ptr); - MDFILE(elt) = cpystr(names[pos]->d_name); - maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t); - if (elt->draft != d || elt->flagged != f || - elt->answered != r || elt->seen != s || elt->deleted != t){ - elt->draft = d; elt->flagged = f; elt->answered = r; - elt->seen = s; elt->deleted = t; - MM_FLAGS(stream, msgno); - } - } - for (i = 0L; i < nfiles; i++) - fs_give((void **) &names[i]); - if (names) - fs_give((void **) &names); - return in_list ? 1 : -1; -} - -/* Maildir fetch message header */ - -char *maildir_header (MAILSTREAM *stream,unsigned long msgno, - unsigned long *length, long flags) -{ - char tmp[MAILTMPLEN], *s; - MESSAGECACHE *elt; - static int try = 0; - - if (length) *length = 0; - if (flags & FT_UID || !LOCAL) return ""; /* UID call "impossible" */ - elt = mail_elt (stream,msgno); - if(elt->private.msg.header.text.size == 0) - maildir_parse_message(stream, msgno, MDLOC(elt)); - - MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt)); - if (LOCAL->fd < 0) - LOCAL->fd = open (tmp,O_RDONLY,NIL); - - if (LOCAL->fd < 0 && errno == EACCES){ - mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR); - return NULL; - } - - if (LOCAL->fd < 0){ /* flag change? */ - if (try < 5){ - try++; - if (maildir_update_elt_maildirp(stream, msgno) > 0) - try = 0; - return maildir_header(stream, msgno, length, flags); - } - try = 0; - return NULL; - } - - if (flags & FT_INTERNAL){ - if(elt->private.msg.header.text.size > LOCAL->buflen){ - fs_give ((void **) &LOCAL->buf); - LOCAL->buf = (char *) fs_get ((LOCAL->buflen = - elt->private.msg.header.text.size) + 1); - } - read (LOCAL->fd, (void *)LOCAL->buf, elt->private.msg.header.text.size); - LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0'; - } - else{ - s = (char *) fs_get(elt->private.msg.header.text.size+1); - read (LOCAL->fd, (void *)s, elt->private.msg.header.text.size); - s[elt->private.msg.header.text.size] = '\0'; - *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s, - elt->private.msg.header.text.size); - fs_give ((void **) &s); - } - elt->private.msg.text.offset = elt->private.msg.header.text.size; - elt->private.msg.text.text.size = MDSIZE(elt) - elt->private.msg.text.offset; - close(LOCAL->fd); LOCAL->fd = -1; - return LOCAL->buf; -} - -/* Maildir find list of subscribed mailboxes - * Accepts: mail stream - * pattern to search - */ - -void maildir_list (MAILSTREAM *stream,char *ref, char *pat) -{ - char *s,test[MAILTMPLEN],file[MAILTMPLEN]; - long i = 0L; - - if((!pat || !*pat) && maildir_canonicalize (test,ref,"*") - && maildir_valid_name(test)){ /* there is a #md/ leading here */ - for (i = 3L; test[i] && test[i] != '/'; i++); - if ((s = strchr (test+i+1,'/')) != NULL) *++s = '\0'; - else test[0] = '\0'; - mm_list (stream,'/',test, LATT_NOSELECT); - } - else if (maildir_canonicalize (test,ref,pat)) { - if (test[3] == '/') { /* looking down levels? */ - /* yes, found any wildcards? */ - if ((s = strpbrk (test,"%*")) != NULL){ - /* yes, copy name up to that point */ - strncpy (file,test+4,i = s - (test+4)); - file[i] = '\0'; /* tie off */ - } - else strcpy (file,test+4);/* use just that name then */ - /* find directory name */ - if ((s = strrchr (file, '/')) != NULL){ - *s = '\0'; /* found, tie off at that point */ - s = file; - } - /* do the work */ - if(IS_COURIER(test)) - courier_list_work (stream,s,test,0); - else - maildir_list_work (stream,s,test,0); - } - /* always an INBOX */ - if (!compare_cstring (test,"#MD/INBOX")) - mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS); - if (!compare_cstring (test,"#MC/INBOX")) - mm_list (stream,NIL,"#MC/INBOX",LATT_NOINFERIORS); - } -} - -void courier_list (MAILSTREAM *stream,char *ref, char *pat) -{ -/* I am too lazy to do anything. Do you care to ask maildir list, please? - The real reason why this is a dummy function is because we do not want to - see the same folder listed twice. -*/ -} - -/* For those that want to hide things, we give them a chance to do so */ -void *maildir_parameters (long function, void *value) -{ - void *ret = NIL; - switch ((int) function) { - case SET_MDINBOXPATH: - if(strlen((char *) value ) > 49) - strcpy(myMdInboxDir, "Maildir"); - else - strcpy(myMdInboxDir, (char *) value); - case GET_MDINBOXPATH: - if (myMdInboxDir[0] == '\0') strcpy(myMdInboxDir,"Maildir"); - ret = (void *) myMdInboxDir; - break; - case SET_COURIERSTYLE: - CourierStyle = (long) value; - case GET_COURIERSTYLE: - ret = (void *) CourierStyle; - break; - case GET_DIRFMTTEST: - ret = (void *) maildir_dirfmttest; - break; - default: - break; - } - return ret; -} - -int maildir_create_folder(char *mailbox) -{ - char tmp[MAILTMPLEN], err[MAILTMPLEN]; - DirNamesType i; - - for (i = Cur; i != EndDir; i++){ - MDFLD(tmp, mailbox, i); - if (mkdir(tmp, 0700) && errno != EEXIST){ /* try to make new dir */ - snprintf (err, sizeof(err), "Can't create %s: %s", tmp, strerror(errno)); - mm_log (err,ERROR); - return NIL; - } - } - return T; -} - -int maildir_create_work(char *mailbox, int loop) -{ - char *s, c, err[MAILTMPLEN], tmp[MAILTMPLEN], tmp2[MAILTMPLEN], mbx[MAILTMPLEN]; - int fnlen, create_dir = 0, courier, mv; - struct stat sbuf; - long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL); - - courier = IS_COURIER(mailbox); - strcpy(mbx, mailbox); - mv = maildir_valid(mbx) ? 1 : 0; - maildir_file_path(mailbox, tmp, sizeof(tmp)); - if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){ - create_dir++; - mailbox[strlen(mailbox) - 1] = '\0'; - } - - if(!loop && courier){ - if(mv){ - if(create_dir){ - if(style == CCLIENT) - strcpy (err,"Can not create directory: folder exists. Create subfolder"); - else - strcpy(err,"Folder and Directory already exist"); - } - else - strcpy (err, "Can't create mailbox: mailbox already exists"); - } - else{ - if(create_dir) - strcpy(err, "Can not create directory. Cread folder instead"); - else - err[0] = '\0'; - } - if(err[0]){ - mm_log (err,ERROR); - return NIL; - } - } - - fnlen = strlen(tmp); - if ((s = strrchr(mailbox,MDSEPARATOR(courier))) != NULL){ - c = *++s; - *s = '\0'; - if ((stat(tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && - !maildir_create_work (mailbox, ++loop)) - return NIL; - *s = c; - } - tmp[fnlen] = '\0'; - - if (mkdir(tmp,0700) && errno != EEXIST) - return NIL; - - if (create_dir) - mailbox[fnlen] = '/'; - - if (create_dir){ - if(style == CCLIENT){ - if(!courier){ - FILE *fp = NULL; - snprintf(tmp2, sizeof(tmp2), "%s%s", tmp, MDDIR); - if ((fp = fopen(tmp2,"w")) == NULL){ - snprintf (err, sizeof(err), "Problem creating %s: %s", tmp2, strerror(errno)); - mm_log (err,ERROR); - return NIL; - } - fclose(fp); - } - } - return T; - } - else - return maildir_create_folder(tmp); -} - -long maildir_create (MAILSTREAM *stream,char *mailbox) -{ - char tmp[MAILTMPLEN], err[MAILTMPLEN]; - int rv, create_dir; - - create_dir = mailbox ? - (mailbox[strlen(mailbox) - 1] == - MDSEPARATOR(IS_COURIER(mailbox))) : 0; - maildir_file_path(mailbox, tmp, sizeof(tmp)); - strcpy(tmp, mailbox); - rv = maildir_create_work(mailbox, 0); - strcpy(mailbox, tmp); - if (rv == 0){ - snprintf (err, sizeof(err), "Can't create %s %s", - (create_dir ? "directory" : "mailbox"), mailbox); - mm_log (err,ERROR); - } - return rv ? LONGT : NIL; -} - -#define MAXTRY 10000 -void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt) -{ - char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN]; - char *s; - int ren, try = 0; - - if (elt->valid){ - for (try = 1; try > 0 && try < MAXTRY; try++){ - /* build the new filename */ - snprintf (oldfile, sizeof(oldfile), "%s/%s",LOCAL->path[Cur], MDFILE(elt)); - fn[0] = '\0'; - if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){ - errno = ENOENT; - try = MAXTRY; - } - if (*fn) /* new oldfile! */ - snprintf (oldfile,sizeof(oldfile),"%s/%s", LOCAL->path[Cur], fn); - if ((s = strrchr (MDFILE(elt), FLAGSEP))) *s = '\0'; - snprintf (fn, sizeof(fn), "%s%s%s%s%s%s%s", MDFILE(elt), MDSEP(2), - MDFLAG(Draft, elt->draft), MDFLAG(Flagged, elt->flagged), - MDFLAG(Replied, elt->answered), MDFLAG(Seen, elt->seen), - MDFLAG(Trashed, elt->deleted)); - snprintf (newfile, sizeof(newfile), "%s/%s",LOCAL->path[Cur],fn); - if (ren != 0 && rename (oldfile,newfile) >= 0) - try = -1; - } - - if (try > 0){ - snprintf(oldfile, sizeof(oldfile), "Unable to write flags to disk: %s", - (errno == ENOENT) ? "message is gone!" : strerror (errno)); - mm_log(oldfile,ERROR); - return; - } -#ifdef __CYGWIN__ - utime(LOCAL->path[Cur], NIL); /* make sure next scan will catch the change */ -#endif - maildir_free_file_only ((void **) &elt->private.spare.ptr); - MDFILE(elt) = cpystr (fn); - } -} - -long maildir_expunge (MAILSTREAM *stream, char *sequence, long options) -{ - long ret; - MESSAGECACHE *elt; - unsigned long i, n = 0L; - unsigned long recent = stream->recent; - char tmp[MAILTMPLEN]; - - mm_critical (stream); /* go critical */ - ret = sequence ? ((options & EX_UID) ? - mail_uid_sequence (stream,sequence) : - mail_sequence (stream,sequence)) : LONGT; - if(ret == 0L) - return 0L; - for (i = 1L; i <= stream->nmsgs;){ - elt = mail_elt (stream,i); - if (elt->deleted && (sequence ? elt->sequence : T)){ - snprintf (tmp, sizeof(tmp), "%s/%s", LOCAL->path[Cur], MDFILE(elt)); - if (unlink (tmp) < 0) {/* try to delete the message */ - snprintf (tmp, sizeof(tmp), "Expunge of message %ld failed, aborted: %s",i, - strerror (errno)); - if (!stream->silent) - mm_log (tmp,WARN); - break; - } - if (elt->private.spare.ptr) - maildir_free_file ((void **) &elt->private.spare.ptr); - if (elt->recent) --recent;/* if recent, note one less recent message */ - mail_expunged (stream,i); /* notify upper levels */ - n++; /* count up one more expunged message */ - } - else i++; - } - if(n){ /* output the news if any expunged */ - snprintf (tmp, sizeof(tmp), "Expunged %ld messages", n); - if (!stream->silent) - mm_log (tmp,(long) NIL); - } - else - if (!stream->silent) - mm_log ("No messages deleted, so no update needed",(long) NIL); - mm_nocritical (stream); /* release critical */ - /* notify upper level of new mailbox size */ - mail_exists (stream, stream->nmsgs); - mail_recent (stream, recent); - return ret; -} - -long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) -{ - STRING st; - MESSAGECACHE *elt; - unsigned long len; - int fd; - unsigned long i; - struct stat sbuf; - char tmp[MAILTMPLEN], flags[MAILTMPLEN], path[MAILTMPLEN], *s; - /* copy the messages */ - if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : - mail_sequence (stream,sequence)) - for (i = 1L; i <= stream->nmsgs; i++) - if ((elt = mail_elt (stream,i))->sequence){ - MSGPATH(path, LOCAL->dir, MDFILE(elt), MDLOC(elt)); - if (((fd = open (path,O_RDONLY,NIL)) < 0) - ||((!elt->rfc822_size && - ((stat(path, &sbuf) < 0) || !S_ISREG (sbuf.st_mode))))) - return NIL; - if(!elt->rfc822_size) - MDSIZE(elt) = sbuf.st_size; - s = (char *) fs_get(MDSIZE(elt) + 1); - read (fd,s,MDSIZE(elt)); - s[MDSIZE(elt)] = '\0'; - close (fd); - len = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen, s, MDSIZE(elt)); - INIT (&st,mail_string, LOCAL->buf, len); - elt->rfc822_size = len; - fs_give ((void **)&s); - - flags[0] = flags[1] = '\0'; - if (elt->seen) strcat (flags," \\Seen"); - if (elt->draft) strcat (flags," \\Draft"); - if (elt->deleted) strcat (flags," \\Deleted"); - if (elt->flagged) strcat (flags," \\Flagged"); - if (elt->answered) strcat (flags," \\Answered"); - flags[0] = '('; /* open list */ - strcat (flags,")"); /* close list */ - mail_date (tmp,elt); /* generate internal date */ - if (!mail_append_full (NIL, mailbox, flags, tmp, &st)) - return NIL; - if (options & CP_MOVE) elt->deleted = T; - } - return LONGT; /* return success */ -} - -long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) -{ - int fd, k; - STRING *message; - char c,*s, *flags, *date; - char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN]; - MESSAGECACHE elt; - long i, size = 0L, ret = LONGT, f; - unsigned long uf, ti; - static unsigned int transact = 0; - - if (!maildir_valid(mailbox)) { - snprintf (tmp, sizeof(tmp), "Not a valid Maildir mailbox: %s", mailbox); - mm_log (tmp,ERROR); - return NIL; - } - - if (!*mdlocaldomain) - md_domain_name(); /* get domain name for maildir files in mdlocaldomain now! */ - - if (mypid == (pid_t) 0) - mypid = getpid(); - - if (!stream){ - stream = &maildirproto; - - for (k = 0; k < NUSERFLAGS && stream->user_flags[k]; ++k) - fs_give ((void **) &stream->user_flags[k]); - } - - if (!(*af)(stream, data, &flags, &date, &message)) return NIL; - - mm_critical (stream); /* go critical */ - /* call time(0) only once, use transact to distinguish instead */ - ti = time(0); - do { - if (!SIZE (message)) { /* guard against zero-length */ - mm_log ("Append of zero-length message",ERROR); - ret = NIL; - break; - } - if (date && !mail_parse_date(&elt,date)){ - snprintf (tmp, sizeof(tmp), "Bad date in append: %.80s",date); - mm_log (tmp,ERROR); - ret = NIL; - break; - } - f = mail_parse_flags (stream,flags,&uf); - /* build file name we will use */ - snprintf (file, sizeof(file), "%lu.%d_%09u.%s%s%s%s%s%s", - ti, mypid, transact++, mdlocaldomain, (f ? MDSEP(2) : ""), - MDFLAG(Draft, f&fDRAFT), MDFLAG(Flagged, f&fFLAGGED), - MDFLAG(Replied, f&fANSWERED), MDFLAG(Seen, f&fSEEN)); - /* build tmp file name */ - if (maildir_file_path(mailbox, tmp, sizeof(tmp))) - MSGPATH(path1, tmp, file, Tmp); - - if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) { - snprintf (tmp, sizeof(tmp), "Can't open append mailbox: %s", strerror (errno)); - mm_log (tmp, ERROR); - return NIL; - } - for (size = 0,i = SIZE (message),s = (char *) fs_get (i + 1); i; --i) - if ((c = SNX (message)) != '\015') s[size++] = c; - if ((write (fd, s, size) < 0) || fsync (fd)) { - unlink (path1); /* delete message */ - snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno)); - mm_log (tmp, ERROR); - ret = NIL; - } - fs_give ((void **) &s); /* flush the buffer */ - close (fd); /* close the file */ - /* build final filename to use */ - if (maildir_file_path(mailbox, tmp, sizeof(tmp))) - MSGPATH(path2, tmp, file, New); - if (rename (path1,path2) < 0) { - snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno)); - mm_log (tmp, ERROR); - ret = NIL; - } - unlink (path1); - - if (ret) - if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL; - - } while (ret && message); /* write the data */ - mm_nocritical (stream); /* release critical */ - return ret; -} - -long maildir_delete (MAILSTREAM *stream,char *mailbox) -{ - DIR *dirp; - struct direct *d; - int i, remove_dir = 0, mddir = 0, rv, error = 0; - char tmp[MAILTMPLEN],tmp2[MAILTMPLEN], realname[MAILTMPLEN]; - struct stat sbuf; - int courier = IS_COURIER(mailbox); - - if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){ - remove_dir++; - mailbox[strlen(mailbox) -1] = '\0'; - } - - if (!maildir_valid(mailbox)){ - maildir_file_path(mailbox, tmp, sizeof(tmp)); - if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)){ - snprintf(tmp, sizeof(tmp), "Can not remove %s", mailbox); - error++; - } - } - - if (!error && remove_dir && !maildir_dir_is_empty(mailbox)){ - snprintf(tmp, sizeof(tmp), "Can not remove directory %s/: directory not empty", mailbox); - error++; - } - - if(error){ - mm_log (tmp,ERROR); - return NIL; - } - - maildir_close(stream,0); /* even if stream was NULL */ - - maildir_file_path(mailbox, realname, sizeof(realname)); - - if (remove_dir){ - snprintf(tmp, sizeof(tmp), "%s/%s", realname, MDDIR); - if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode)) - rv = unlink(tmp); - else if (errno == ENOENT) - rv = 0; - if (rv != 0){ - snprintf(tmp, sizeof(tmp), "Can not remove %s/%s: %s", tmp2, MDDIR, strerror(errno)); - mm_log (tmp,ERROR); - return NIL; - } - if (!maildir_valid(realname) && rmdir(realname) != 0){ - snprintf(tmp, sizeof(tmp), "Can not remove %s/: %s", mailbox, strerror(errno)); - mm_log (tmp, ERROR); - return NIL; - } - return LONGT; - } - /* else remove just the folder. Remove all hidden files, except MDDIR */ - for (i = Cur; i != EndDir; i++){ - MDFLD(tmp, realname, i); - - if (!(dirp = opendir (tmp))){ - snprintf(tmp, sizeof(tmp), "Can not read %s/: %s", mailbox, strerror(errno)); - mm_log (tmp, ERROR); - return NIL; - } - - while ((d = readdir(dirp)) != NULL){ - if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){ - snprintf(tmp2, sizeof(tmp2), "%s/%s", tmp, d->d_name); - if (unlink(tmp2) != 0){ - snprintf(tmp2, sizeof(tmp2), "Can not remove %s: %s", mailbox, strerror(errno)); - mm_log (tmp2, ERROR); - return NIL; - } - } - } - closedir(dirp); - if (rmdir(tmp) != 0){ - snprintf(tmp, sizeof(tmp), "Can not remove %s: %s", mailbox, strerror(errno)); - mm_log (tmp, ERROR); - return NIL; - } - } - /* - * ok we have removed all subdirectories of the folder mailbox, Remove the - * hidden files. - */ - - if(!(dirp = opendir (realname))){ - snprintf(tmp, sizeof(tmp), "Can not read %s/: %s", realname, strerror(errno)); - mm_log (tmp, ERROR); - return NIL; - } - - while ((d = readdir(dirp)) != NULL){ - if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") - && (!strcmp(d->d_name, MDDIR) - || !strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST)) - || !strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)))){ - if(strcmp(d->d_name, MDDIR) == 0) - mddir++; - snprintf(tmp, sizeof(tmp), "%s/%s", realname, d->d_name); - if (unlink(tmp) != 0) - error++; - } - } - closedir(dirp); - if (error || - (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(realname) < 0)){ - snprintf(tmp, sizeof(tmp), "Can not remove folder %s: %s", mailbox, strerror(errno)); - mm_log (tmp, ERROR); - return NIL; - } - return LONGT; -} - -long maildir_rename (MAILSTREAM *stream, char *old, char *new) -{ - char tmp[MAILTMPLEN], tmpnew[MAILTMPLEN], realold[MAILTMPLEN]; - char realnew[MAILTMPLEN]; - int courier = IS_COURIER(old) && IS_COURIER(new); - int i; - long rv = LONGT; - COURIER_S *cdir; - - if((IS_COURIER(old) || IS_COURIER(new)) && !courier){ - snprintf (tmp, sizeof(tmp), "Can't rename mailbox %s to %s", old, new); - mm_log (tmp, ERROR); - return NIL; - } - - if (!maildir_valid(old)){ - snprintf (tmp, sizeof(tmp), "Can't rename mailbox %s: folder not in maildir format",old); - mm_log (tmp, ERROR); - return NIL; - } - maildir_file_path(old, realold, sizeof(realold)); - if (!maildir_valid_name(new) && new[0] == '#'){ - snprintf (tmp, sizeof(tmp), "Cannot rename mailbox %s: folder not in maildir format", new); - mm_log (tmp, ERROR); - return NIL; - } - maildir_file_path(new, realnew, sizeof(realnew)); - if (access(tmpnew,F_OK) == 0){ /* new mailbox name must not exist */ - snprintf (tmp, sizeof(tmp), "Cannot rename to mailbox %s: destination already exists", new); - mm_log (tmp, ERROR); - return NIL; - } - - if(!courier){ - if (rename(realold, realnew)){ /* try to rename the directory */ - snprintf(tmp, sizeof(tmp), "Can't rename mailbox %s to %s: %s", old, new, - strerror(errno)); - mm_log(tmp,ERROR); - return NIL; - } - return LONGT; /* return success */ - } - - cdir = courier_list_dir(old); - for (i = 0; cdir && i < cdir->total; i++){ - if(strstr(cdir->data[i]->name, old)){ - snprintf(tmp, sizeof(tmp), "%s%s", new, cdir->data[i]->name+strlen(old)); - maildir_file_path(cdir->data[i]->name, realold, sizeof(realold)); - maildir_file_path(tmp, realnew, sizeof(realnew)); - if (rename(realold, realnew)){ - snprintf (tmp, sizeof(tmp), "Can't rename mailbox %s to %s: %s", old, new, - strerror(errno)); - mm_log(tmp,ERROR); - rv = NIL; - } - } - } - courier_free_cdir(&cdir); - return rv; -} - -long maildir_sub(MAILSTREAM *stream,char *mailbox) -{ - return sm_subscribe(mailbox); -} - -long maildir_unsub(MAILSTREAM *stream,char *mailbox) -{ - return sm_unsubscribe(mailbox); -} - -void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat) -{ - void *sdb = NIL; - char *s, test[MAILTMPLEN]; - /* get canonical form of name */ - if (maildir_canonicalize (test, ref, pat) && (s = sm_read (&sdb))) { - do if (pmatch_full (s, test, '/')) mm_lsub (stream, '/', s, NIL); - while ((s = sm_read (&sdb)) != NULL); /* until no more subscriptions */ - } -} - -long maildir_canonicalize (char *pattern,char *ref,char *pat) -{ - if (ref && *ref) { /* have a reference */ - strcpy (pattern,ref); /* copy reference to pattern */ - /* # overrides mailbox field in reference */ - if (*pat == '#') strcpy (pattern,pat); - /* pattern starts, reference ends, with / */ - else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/')) - strcat (pattern,pat + 1); /* append, omitting one of the period */ - - else strcat (pattern,pat); /* anything else is just appended */ - } - else strcpy (pattern,pat); /* just have basic name */ - return maildir_valid_name(pattern) ? LONGT : NIL; -} - -void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level) -{ - DIR *dp; - struct direct *d; - struct stat sbuf; - char curdir[MAILTMPLEN],name[MAILTMPLEN], tmp[MAILTMPLEN]; - char realpat[MAILTMPLEN]; - long i; - char *maildirpath = mdirpath(); - - snprintf(curdir, sizeof(curdir), "%s/%s/", myrootdir(pat), dir ? dir : maildirpath); - if ((dp = opendir (curdir)) != NULL){ - if (dir) snprintf (name, sizeof(name), "%s%s/",MDPREFIX(CCLIENT),dir); - else strcpy (name, pat); - - if (level == 0 && !strpbrk(pat,"%*")){ - if(maildir_valid(pat)){ - i = maildir_contains_folder(pat, NULL) - ? LATT_HASCHILDREN - : (maildir_is_dir(pat, NULL) - ? LATT_HASNOCHILDREN : LATT_NOINFERIORS); - maildir_file_path(pat, realpat, sizeof(realpat)); - i += maildir_any_new_msgs(realpat) - ? LATT_MARKED : LATT_UNMARKED; - mm_list (stream,'/', pat, i); - } - else - if(pat[strlen(pat) - 1] == '/') - mm_list (stream,'/', pat, LATT_NOSELECT); - } - - while ((d = readdir (dp)) != NULL) - if(strcmp(d->d_name, ".") && strcmp(d->d_name,"..") - && strcmp(d->d_name, MDNAME(Cur)) - && strcmp(d->d_name, MDNAME(Tmp)) - && strcmp(d->d_name, MDNAME(New))){ - - if (dir) snprintf (tmp, sizeof(tmp), "%s%s", name,d->d_name); - else strcpy(tmp, d->d_name); - - if(pmatch_full (tmp, pat,'/')){ - snprintf(tmp, sizeof(tmp), "%s/%s/%s", myrootdir(d->d_name), - (dir ? dir : maildirpath), d->d_name); - if(stat (tmp,&sbuf) == 0 - && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){ - if (dir) snprintf (tmp, sizeof(tmp), "%s%s", name,d->d_name); - else strcpy(tmp, d->d_name); - i = maildir_valid(tmp) - ? (maildir_contains_folder(dir, d->d_name) - ? LATT_HASCHILDREN - : (maildir_is_dir(dir, d->d_name) - ? LATT_HASNOCHILDREN : LATT_NOINFERIORS)) - : LATT_NOSELECT; - i += maildir_any_new_msgs(tmp) - ? LATT_MARKED : LATT_UNMARKED; - mm_list (stream,'/',tmp, i); - strcat (tmp, "/"); - if(dmatch (tmp, pat,'/') && - (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))){ - snprintf(tmp, sizeof(tmp), "%s/%s",dir,d->d_name); - maildir_list_work (stream,tmp,pat,level+1); - } - } - } - } - closedir (dp); - } -} - -void courier_list_work (MAILSTREAM *stream, char *dir, char *pat, long level) -{ - char c, curdir[MAILTMPLEN], tmp[MAILTMPLEN]; - char realname[MAILTMPLEN], realpat[MAILTMPLEN] = {'\0'}; - int i, found; - long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL), j; - char *maildirpath = mdirpath(); - COURIER_S *cdir; - - if(!strpbrk(pat,"%*")){ /* a mailbox */ - maildir_file_path(pat, curdir, sizeof(curdir)); - i = strlen(curdir) - 1; - if(curdir[i] == '/') - curdir[i] = '\0'; - cdir = courier_list_dir(curdir); - if(cdir){ - found = 0; j = 0L; - if(maildir_valid_name(pat)){ - for(i = 0; !found && i < cdir->total; i++) - if(strstr(curdir, cdir->data[i]->name)){ - if(strlen(curdir) < strlen(cdir->data[i]->name)) - found += 2; - else if(strlen(curdir) == strlen(cdir->data[i]->name)) - found -= 1; - } - if(found > 0) - j = LATT_HASCHILDREN; - else if(found == 0) - j = (style == COURIER) ? LATT_HASNOCHILDREN : LATT_NOINFERIORS; - } - else - j = LATT_NOSELECT; - j += maildir_any_new_msgs(curdir) ? LATT_MARKED : LATT_UNMARKED; - if (found) - mm_list (stream, '.', pat, j); - courier_free_cdir(&cdir); - } - return; - } - - strcpy(tmp,pat + 4); /* a directory */ - j = strlen(pat) - 1; - maildir_file_path(pat, realpat, sizeof(realpat)); - c = pat[j]; - pat[j] = '\0'; - realname[0] = '\0'; - if(dir) - maildir_file_path(dir, realname, sizeof(realname)); - snprintf(curdir, sizeof(curdir), "%s%s%s/%s", (dir ? "" : myrootdir(pat)), (dir ? "" : "/"), - (dir ? realname : maildirpath), (dir ? "" : ".")); - snprintf(tmp, sizeof(tmp), "%s%s/.", MDPREFIX(COURIER), dir ? dir : maildirpath); - if (level == 0 && tmp && pmatch_full (tmp, realpat, '.')) - mm_list (stream,'.', tmp, LATT_NOSELECT); - - cdir = courier_list_dir(pat); - pat[j] = c; - for (i = 0; cdir && i < cdir->total; i++) - if(pmatch_full (cdir->data[i]->name, pat, '.')){ - snprintf(tmp, sizeof(tmp), "%s.", cdir->data[i]->name); - courier_list_info(&cdir, tmp, i); - mm_list (stream,'.',cdir->data[i]->name, cdir->data[i]->attribute); - } - courier_free_cdir(&cdir); -} - -int -same_maildir_file(char *name1, char *name2) -{ - char tmp1[MAILTMPLEN], tmp2[MAILTMPLEN]; - char *s; - - strcpy(tmp1, name1 ? name1 : ""); - strcpy(tmp2, name2 ? name2 : ""); - if ((s = strrchr(tmp1, FLAGSEP)) != NULL) - *s = '\0'; - if (((s = strrchr(tmp1, SIZESEP)) != NULL) && (strchr(s,'.') == NULL)) - *s = '\0'; - if ((s = strrchr(tmp2, FLAGSEP)) != NULL) - *s = '\0'; - if (((s = strrchr(tmp2, SIZESEP)) != NULL) && (strchr(s,'.') == NULL)) - *s = '\0'; - - return !strcmp(tmp1, tmp2); -} - -unsigned long antoul(char *seed) -{ - int i, error = 0; - unsigned long val = 0L, rv1 = 0L, t; - char c, *p; - if(!seed) - return 0L; - t = strtoul(seed, &p, 10); - if(p && (*p == '.' || *p == '_')) - return t; - /* else */ - if((p = strchr(seed,'.')) != NULL) - *p = '\0'; - error = (strlen(seed) > 6); /* too long */ - for(i= strlen(seed)-1; error == 0 && i >= 0; i--){ - c = seed[i]; - if (c >= 'A' && c <= 'Z') val = c - 'A'; - else if (c >= 'a' && c <= 'z') val = c - 'a' + 26; - else if (c >= '0' && c <= '9') val = c - '0' + 26 + 26; - else if (c == '-') val = c - '-' + 26 + 26 + 10; - else if (c == '_') val = c - '_' + 26 + 26 + 10 + 1; - else error++; - rv1 = val + (rv1 << 6); - } - if(p) - *p = '.'; - return error ? 0L : rv1; -} - -unsigned long mdfntoul (char *name) -{ - unsigned long t; - char *r, last; - - if((*name == '_') && ((r = strpbrk(name,".,%+")) != NULL)){ /* Grrr!!! */ - last = *r; - *r = '\0'; - t = antoul(r+1); - *r = last; - } - else - t = antoul(name); - return t; -} - -int comp_maildir_file(char *name1, char *name2) -{ - int uset1 = 1, uset2 = 1, i, j, cmp; - unsigned long t1, t2; - char *s1, *s2; - - if (!(name1 && *name1)) - return (name2 && *name2) ? (*name2 == FLAGSEP ? 0 : -1) : 0; - - if (!(name2 && *name2)) - return (name1 && *name1) ? (*name1 == FLAGSEP ? 0 : 1) : 0; - - if((cmp = strcmp(name1,name2)) == 0) - return 0; - - t1 = strtoul(name1, &s1, 10); - t2 = strtoul(name2, &s2, 10); - - if(!s1 || *s1 != '.') - uset1 = 0; - - if(!s2 || *s2 != '.') - uset2 = 0; - - if(uset1 && uset2) /* normal sort order */ - return (t1 < t2) ? -1 : (t1 > t2 ? 1 : (cmp < 0 ? -1 : 1)); - - /* If we make it here we say Grrrr.... first, then we try to figure out - * how to sort this mess. - * These are the rules. - * If there is a number at the beginning it is bigger than anything else. - * If there are digits, then the number of digits decides which one is bigger. - */ - - for(i = 0; isdigit(name1[i]); i++); - for(j = 0; isdigit(name2[j]); j++); - - return(uset1 ? 1 - : (uset2 ? -1 - : (i < j ? -1 : (i > j ? 1 : (cmp < 0 ? -1 : 1))))); -} - -void -maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t) -{ - char tmp[MAILTMPLEN], *b; - int offset = 0; - int tmpd, tmpf, tmpr, tmps, tmpt; - - if(d) *d = 0; - if(f) *f = 0; - if(r) *r = 0; - if(s) *s = 0; - if(t) *t = 0; - - tmpd = tmpf = tmpr = tmps = tmpt = NIL; /* no flags set by default */ - strcpy(tmp,name); - while ((b = strrchr(tmp+offset, FLAGSEP)) != NULL){ - char flag,last; - int k; - if (!++b) break; - switch (*b){ - case '1': - case '2': - case '3': flag = *b; b += 2; - for (k = 0; b[k] && b[k] != FLAGSEP && b[k] != ','; k++); - last = b[k]; - b[k] = '\0'; - if (flag == '2' || flag == '3'){ - tmpd = strchr (b, MDFLAGC(Draft)) ? T : NIL; - tmpf = strchr (b, MDFLAGC(Flagged)) ? T : NIL; - tmpr = strchr (b, MDFLAGC(Replied)) ? T : NIL; - tmps = strchr (b, MDFLAGC(Seen)) ? T : NIL; - tmpt = strchr (b, MDFLAGC(Trashed)) ? T : NIL; - } - b[k] = last; - b += k; - for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++); - offset++; - break; - default: break; /* Should we crash?... Nahhh */ - } - } - if(d) *d = tmpd; - if(f) *f = tmpf; - if(r) *r = tmpr; - if(s) *s = tmps; - if(t) *t = tmpt; -} - -int -maildir_message_in_list(char *msgname, struct direct **names, - unsigned long bottom, unsigned long top, unsigned long *pos) -{ - unsigned long middle = (bottom + top)/2; - int test; - - if (!msgname) - return NIL; - - if (pos) *pos = middle; - - if (same_maildir_file(msgname, names[middle]->d_name)) - return T; - - if (middle == bottom){ /* 0 <= 0 < 1 */ - int rv = NIL; - if (same_maildir_file(msgname, names[middle]->d_name)){ - rv = T; - if (pos) *pos = middle; - } - else - if (same_maildir_file(msgname, names[top]->d_name)){ - rv = T; - if (pos) *pos = top; - } - return rv; - } - - test = comp_maildir_file(msgname, names[middle]->d_name); - - if (top <= bottom) - return test ? NIL : T; - - if (test < 0 ) /* bottom < msgname < middle */ - return maildir_message_in_list(msgname, names, bottom, middle, pos); - else if (test > 0) /* middle < msgname < top */ - return maildir_message_in_list(msgname, names, middle, top, pos); - else return T; -} - -void -maildir_abort(MAILSTREAM *stream) -{ - if (LOCAL){ - DirNamesType i; - - if(LOCAL->candouid) - maildir_read_uid(stream, NULL, &stream->uid_validity); - if (LOCAL->dir) fs_give ((void **) &LOCAL->dir); - for (i = Cur; i < EndDir; i++) - if(LOCAL->path[i]) fs_give ((void **) &LOCAL->path[i]); - fs_give ((void **) &LOCAL->path); - if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); - if(LOCAL->uidtempfile){ - unlink(LOCAL->uidtempfile); - fs_give ((void **) &LOCAL->uidtempfile); - } - fs_give ((void **) &stream->local); - } - if (mdfpath) fs_give((void **)&mdfpath); - stream->dtb = NIL; -} - -int -maildir_contains_folder(char *dirname, char *name) -{ - char tmp[MAILTMPLEN], tmp2[MAILTMPLEN]; - int rv = 0; - DIR *dir; - struct direct *d; - - maildir_file_path(dirname, tmp2, sizeof(tmp2)); - if(name){ - strcat(tmp2,"/"); - strcat(tmp2, name); - } - - if (!(dir = opendir (tmp2))) - return NIL; - - while ((d = readdir(dir)) != NULL){ - if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") - && strcmp(d->d_name, MDNAME(Cur)) - && strcmp(d->d_name, MDNAME(Tmp)) - && strcmp(d->d_name, MDNAME(New))){ - - snprintf(tmp, sizeof(tmp), "%s/%s", tmp2, d->d_name); - if(maildir_valid(tmp)){ - rv++; - break; - } - } - } - closedir(dir); - return rv; -} - -int -maildir_is_dir(char *dirname, char *name) -{ - char tmp[MAILTMPLEN]; - struct stat sbuf; - - maildir_file_path(dirname, tmp, sizeof(tmp)); - if(name){ - strcat(tmp, "/"); - strcat(tmp, name); - } - strcat(tmp, "/"); - strcat(tmp, MDDIR); - - return ((stat(tmp, &sbuf) == 0) && S_ISREG (sbuf.st_mode)) ? 1 : 0; -} - -int -maildir_dir_is_empty(char *mailbox) -{ - char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], tmp3[MAILTMPLEN],*s; - int rv = 1, courier = IS_COURIER(mailbox); - DIR *dir; - struct direct *d; - struct stat sbuf; - - maildir_file_path(mailbox, tmp2, sizeof(tmp2)); - - if(courier){ - strcpy(tmp3, tmp2); - if(s = strrchr(tmp2, '/')) - *s = '\0'; - } - - if (!(dir = opendir (tmp2))) - return rv; - - if(courier){ - while((d = readdir(dir)) != NULL){ - snprintf(tmp, sizeof(tmp), "%s/%s", tmp2, d->d_name); - if(!strncmp(tmp, tmp3, strlen(tmp3)) - && tmp[strlen(tmp3)] == '.'){ - rv = 0; - break; - } - } - } - else - while ((d = readdir(dir)) != NULL){ - snprintf(tmp, sizeof(tmp), "%s/%s", tmp2, d->d_name); - if (strcmp(d->d_name, ".") - && strcmp(d->d_name,"..") - && strcmp(d->d_name, MDNAME(Cur)) - && strcmp(d->d_name, MDNAME(Tmp)) - && strcmp(d->d_name, MDNAME(New)) - && strcmp(d->d_name, MDDIR) - && strcmp(d->d_name, MDUIDVALIDITY) - && !(d->d_name[0] == '.' - && stat (tmp,&sbuf) == 0 - && S_ISREG(sbuf.st_mode))){ - rv = 0; - break; - } - } - closedir(dir); - return rv; -} - -void -maildir_get_file (MAILDIRFILE **mdfile) -{ - MAILDIRFILE *md; - - md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE)); - memset(md, 0, sizeof(MAILDIRFILE)); - *mdfile = md; -} - -void -maildir_free_file (void **mdfile) -{ - MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; - - if (md){ - if (md->name) fs_give((void **)&md->name); - fs_give((void **)&md); - } -} - -void -maildir_free_file_only (void **mdfile) -{ - MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; - - if (md && md->name) - fs_give((void **)&md->name); -} - -int -maildir_any_new_msgs(char *mailbox) -{ - char tmp[MAILTMPLEN]; - int rv = NIL; - DIR *dir; - struct direct *d; - - MDFLD(tmp, mailbox, New); - - if (!(dir = opendir (tmp))) - return rv; - - while ((d = readdir(dir)) != NULL){ - if (d->d_name[0] == '.') - continue; - rv = T; - break; - } - closedir(dir); - return rv; -} - - -void -maildir_get_date(MAILSTREAM *stream, unsigned long msgno) -{ - MESSAGECACHE *elt; - struct tm *t; - time_t ti; - int i,k; - - elt = mail_elt (stream,msgno); - if(elt && elt->year != 0) - return; - if ((ti = mdfntoul(MDFILE(elt))) > 0L && (t = gmtime(&ti))){ - i = t->tm_hour * 60 + t->tm_min; - k = t->tm_yday; - t = localtime(&ti); - i = t->tm_hour * 60 + t->tm_min - i; - if((k = t->tm_yday - k) != 0) - i += ((k < 0) == (abs (k) == 1)) ? -24*60 : 24*60; - k = abs (i); - elt->hours = t->tm_hour; - elt->minutes = t->tm_min; - elt->seconds = t->tm_sec; - elt->day = t->tm_mday; elt->month = t->tm_mon + 1; - elt->year = t->tm_year - (BASEYEAR - 1900); - elt->zoccident = (k == i) ? 0 : 1; - elt->zhours = k/60; - elt->zminutes = k % 60; - } -} - -/* Support for Courier Style directories - When this code is complete there will be two types of support, which - will be configurable. The problem is the following: In Courier style - folder structure, a "folder" may have a subfolder called - "folder.subfolder", which is not natural in the file system in the - sense that I can not stat for "folder.subfolder" wihtout knowing what - "subfolder" is. It needs to be guessed. Because of this I need to look - in the list of folders if there is a folder with a name - "folder.subfolder", before I can say if the folder is dual or not. One - can avoid this annoyance if one ignores the problem by declaring that - every folder is dual. I will however code as the default the more - complicated idea of scaning the containing directory each time it is - modified and search for subfolders, and list the entries it found. - */ - -int courier_dir_select (const struct direct *name) -{ - return name->d_name[0] == '.' && (strlen(name->d_name) > 2 - || (strlen(name->d_name) == 2 && name->d_name[1] != '.')); -} - -int courier_dir_sort (const struct direct **d1, const struct direct **d2) -{ - const struct direct *e1 = *(const struct direct **) d1; - const struct direct *e2 = *(const struct direct **) d2; - - return strcmp((char *) e1->d_name, (char *) e2->d_name); -} - -void courier_free_cdir (COURIER_S **cdir) -{ - int i; - - if (!*cdir) - return; - - if ((*cdir)->path) fs_give((void **)&((*cdir)->path)); - for (i = 0; i < (*cdir)->total; i++) - if((*cdir)->data[i]->name) fs_give((void **)&((*cdir)->data[i]->name)); - fs_give((void **)&((*cdir)->data)); - fs_give((void **)&(*cdir)); -} - -COURIER_S *courier_get_cdir (int total) -{ - COURIER_S *cdir; - - cdir = (COURIER_S *)fs_get(sizeof(COURIER_S)); - memset(cdir, 0, sizeof(COURIER_S)); - cdir->data = (COURIERLOCAL **) fs_get(total*sizeof(COURIERLOCAL *)); - memset(cdir->data, 0, sizeof(COURIERLOCAL *)); - cdir->total = total; - return cdir; -} - -int courier_search_list(COURIERLOCAL **data, char *name, int first, int last) -{ - int try = (first + last)/2; - - if(!strstr(data[try]->name, name)){ - if(first == try) /* first == last || first + 1 == last */ - return strstr(data[last]->name, name) ? 1 : 0; - if(strcmp(data[try]->name, name) < 0) /*data[try] < name < data[end] */ - return courier_search_list(data, name, try, last); - else /* data[begin] < name < data[try] */ - return courier_search_list(data, name, first, try); - } - return 1; -} - -/* Lists all directories that are subdirectories of a given directory */ - -COURIER_S *courier_list_dir(char *curdir) -{ - struct direct **names = NIL; - struct stat sbuf; - unsigned long ndir; - COURIER_S *cdir = NULL; - char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], pathname[MAILTMPLEN], - realname[MAILTMPLEN]; - int i, j, scand, td; - - /* There are two cases, either curdir is - #mc/INBOX. #mc/INBOX.foo - or - #mc/Maildir/. #mc/Maildir/.foo - */ - strcpy(tmp,curdir + 4); - if(!strncmp(ucase(tmp), "INBOX", 5)) - strcpy(tmp, "#mc/INBOX."); - else{ - strcpy(tmp, curdir); - for (i = strlen(tmp) - 1; tmp[i] && tmp[i] != '/'; i--); - tmp[i+2] = '\0'; /* keep the last "." intact */ - } - maildir_file_path(tmp, realname, sizeof(realname)); - maildir_scandir (realname, &names, &ndir, &scand, COURIER); - - if (scand > 0){ - cdir = courier_get_cdir(ndir); - cdir->path = cpystr(realname); - for(i = 0, j = 0; i < ndir; i++){ - td = realname[strlen(realname) - 1] == '.' - && *names[i]->d_name == '.'; - snprintf(tmp2, sizeof(tmp2), "%s%s", tmp, names[i]->d_name+1); - snprintf(pathname, sizeof(pathname), "%s%s", realname, names[i]->d_name + td); - if(stat(pathname, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)){ - cdir->data[j] = (COURIERLOCAL *) fs_get(sizeof(COURIERLOCAL)); - cdir->data[j++]->name = cpystr(tmp2); - } - fs_give((void **)&names[i]); - } - cdir->total = j; - if(cdir->total == 0) - courier_free_cdir(&cdir); - } - if(names) - fs_give((void **) &names); - return cdir; -} - -void -courier_list_info(COURIER_S **cdirp, char *data, int i) -{ - long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL); - COURIER_S *cdir = *cdirp; - - if(maildir_valid(cdir->data[i]->name)){ - if(courier_search_list(cdir->data, data, 0, cdir->total - 1)) - cdir->data[i]->attribute = LATT_HASCHILDREN; - else - cdir->data[i]->attribute = (style == COURIER) - ? LATT_HASNOCHILDREN : LATT_NOINFERIORS; - } - else - cdir->data[i]->attribute = LATT_NOSELECT; - cdir->data[i]->attribute += maildir_any_new_msgs(cdir->data[i]->name) - ? LATT_MARKED : LATT_UNMARKED; -} - -/* UID Support */ -/* Yes, I know I procastinated a lot about this, but here it is finally */ - -/* return code: - bigger than zero: this session can assign uids - zero: this session will not assign uid - smaller than zero: this session temporarily suspends assigning uids - */ -int -maildir_can_assign_uid (MAILSTREAM *stream) -{ - unsigned int rv = 0; - int ownuid, existuid; - unsigned long t; - char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], *p, *s; - DIR *dir; - struct direct *d; - - if(!stream || stream->rdonly - || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir))) - return 0; - - if(mypid == (pid_t) 0) - mypid = getpid(); - - snprintf(tmp, sizeof(tmp), "%s.%d", MDUIDTEMP, mypid); - - ownuid = existuid = 0; - s = NULL; - while ((d = readdir(dir)) != NULL){ - if(strncmp(d->d_name, tmp, strlen(tmp)) == 0){ - existuid++; ownuid++; - if(ownuid > 1){ - snprintf(tmp2, sizeof(tmp), "%s/%s", LOCAL->dir, d->d_name); - unlink(tmp2); - if(s){ - snprintf(tmp2, sizeof(tmp2), "%s/%s", LOCAL->dir, s); - unlink(tmp2); - fs_give((void **)&s); - } - } - else - s = cpystr(d->d_name); - } - else if(strncmp(d->d_name, MDUIDTEMP, strlen(MDUIDTEMP)) == 0) - existuid++; - } - - closedir(dir); - if(s) - fs_give((void **)&s); - - if(ownuid == 1 && existuid == 1) - rv = 1; - - if(ownuid == 0 && existuid == 0){ /* nobody owns the uid? */ - FILE *fp; - snprintf(tmp, sizeof(tmp), "%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0)); - if(fp = fopen(tmp, "w")){ - fclose(fp); - if(LOCAL->uidtempfile) - fs_give((void **)&LOCAL->uidtempfile); - LOCAL->uidtempfile = cpystr(tmp); - } - rv = 1; - } - - if(ownuid == 0 && existuid > 0) /* someone else owns uid assignment */ - return 0; - - /* if we own the uid, check that we do not own it more than once - * or that we share ownership. If any of these situations happens, - * give up the ownership until we can recover it - */ - - if(ownuid > 0){ - if(ownuid > 1) /* impossible, two lock files for the same session */ - return (-1)*ownuid; - - if(ownuid != existuid){ /* lock files for different sessions */ - if(LOCAL->uidtempfile){ - unlink(LOCAL->uidtempfile); - fs_give((void **)&LOCAL->uidtempfile); - } - return (-1)*ownuid; - } - } - - return rv; -} - -void -maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last, - unsigned long *uid_validity) -{ - int createuid, deleteuid = 0; - char tmp[MAILTMPLEN], *s = NULL; - DIR *dir; - struct direct *d; - - if(uid_last) *uid_last = 0L; - if(uid_last && uid_validity) *uid_validity = time(0); - if(!stream || !LOCAL || !LOCAL->dir || !(dir = opendir(LOCAL->dir))) - return; - - while ((d = readdir(dir)) != NULL){ - if(!strncmp(d->d_name, MDUIDLAST, strlen(MDUIDLAST))) - break; - } - createuid = d == NULL ? 1 : 0; - if(uid_last == NULL) - deleteuid++; - if(d){ - if(uid_last){ - s = d->d_name + strlen(MDUIDLAST) + 1; - *uid_last = strtoul(s, &s, 10); - if(!s || *s != '.'){ - deleteuid++; - createuid++; - *uid_last = 0L; - } - } - if(s && *s == '.'){ - if(uid_validity){ - s++; - *uid_validity = strtoul(s, &s, 10); - if(s && *s != '\0'){ - *uid_validity = time(0); - deleteuid++; - createuid++; - } - } - } - else{ - deleteuid++; - createuid++; - } - } - if(deleteuid){ - snprintf(tmp, sizeof(tmp), "%s/%s", LOCAL->dir, d->d_name); - unlink(tmp); - } - if(createuid) - maildir_write_uid(stream, (uid_last ? *uid_last : stream->uid_last), - uid_validity ? *uid_validity : time(0)); - closedir(dir); -} - -void -maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last, - unsigned long uid_validity) -{ - char tmp[MAILTMPLEN]; - FILE *fp; - - if(!stream || stream->rdonly || !LOCAL || !LOCAL->dir) - return; - - snprintf(tmp, sizeof(tmp), "%s/%s.%010lu.%010lu", LOCAL->dir, MDUIDLAST, - uid_last, uid_validity); - if(fp = fopen(tmp, "w")) - fclose(fp); -} - -unsigned long -maildir_get_uid(char *name) -{ - char *s; - unsigned long rv = 0L; - - if(!name || (s = strstr(name,MDUIDSEP)) == NULL) - return rv; - - s += strlen(MDUIDSEP); - rv = strtoul(s, NULL, 10); - return rv; -} - - -void -maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno) -{ - char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t; - MESSAGECACHE *elt; - - elt = mail_elt(stream, msgno); - if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir) - return; - - snprintf(old, sizeof(old), "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt)); - t = MDFILE(elt); - if(s = strstr(MDFILE(elt), MDUIDSEP)){ - *s = '\0'; - s += strlen(MDUIDSEP); - strtoul(s, &s, 10); - snprintf(new, sizeof(new), "%s/%s/%s%s", LOCAL->dir, MDNAME(Cur), t, s); - if(rename(old, new) == 0){ - maildir_free_file_only ((void **)&elt->private.spare.ptr); - s = strrchr(new, '/'); - MDFILE(elt) = cpystr(s+1); - } - elt->private.uid = 0L; - } -} - -void -maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid) -{ - int createuid, deleteuid = 0; - char old[MAILTMPLEN], new[MAILTMPLEN], *s, *t; - MESSAGECACHE *elt; - - elt = mail_elt(stream, msgno); - if(!stream || !elt || !elt->private.spare.ptr || !LOCAL || !LOCAL->dir) - return; - - maildir_delete_uid(stream, msgno); - snprintf(old, sizeof(old), "%s/%s/%s", LOCAL->dir, MDNAME(Cur), MDFILE(elt)); - t = MDFILE(elt); - if((s = strrchr(MDFILE(elt),FLAGSEP)) != NULL){ - *s++ = '\0'; - snprintf(new, sizeof(new), "%s/%s/%s%s%lu%c%s", - LOCAL->dir, MDNAME(Cur), t, MDUIDSEP, uid, FLAGSEP, s); - if(rename(old, new) == 0){ - maildir_free_file_only ((void **)&elt->private.spare.ptr); - s = strrchr(new, '/'); - MDFILE(elt) = cpystr(s+1); - stream->uid_validity = time(0); - } - elt->private.uid = uid; - } -} - -void -maildir_uid_renew_tempfile(MAILSTREAM *stream) -{ - char tmp[MAILTMPLEN]; - - if(!stream || stream->rdonly - || !LOCAL || !LOCAL->candouid || !LOCAL->dir || !LOCAL->uidtempfile) - return; - - if(mypid == (pid_t) 0) - mypid = getpid(); - - snprintf(tmp, sizeof(tmp), "%s/%s.%d.%lu", LOCAL->dir, MDUIDTEMP, mypid, time(0)); - if(rename(LOCAL->uidtempfile, tmp) == 0){ - fs_give((void **)&LOCAL->uidtempfile); - LOCAL->uidtempfile = cpystr(tmp); - } -} diff --git a/imap/src/osdep/unix/maildir.h b/imap/src/osdep/unix/maildir.h deleted file mode 100644 index c1eef9e4..00000000 --- a/imap/src/osdep/unix/maildir.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * A few definitions that try to make this module portable to other - * platforms (e.g. Cygwin). This module is based on the information from - * http://cr.yp.to/proto/maildir.html - */ - -/* First we deal with the separator character */ -#ifndef FLAGSEP -#define FLAGSEP ':' -#endif -#define SIZESEP ',' - -const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/ -const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */ -const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */ - -const char *sep[] = { sep1, sep2, sep3, NULL}; - -#define MDSEP(i) sep[((i) - 1)] - -/* Now we deal with flags. Woohoo! */ -typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed, - EmptyFlag, EndFlags} MdFlagNamesType; -const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags}; -const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags}; - -/* this array lists the codes for mdflgnms (maildir flag names) above */ -const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL}; -/* and as characters too */ -const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'}; - -/* MDFLAG(Seen, elt->seen) */ -#define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag] -/* MDFLAGC(Seen) */ -#define MDFLAGC(i) cmdflags[(i)] - -/* Now we deal with the directory structure */ -typedef enum {Cur, Tmp, New, EndDir} DirNamesType; -char *mdstruct[] = {"cur", "tmp", "new", NULL}; -#define MDNAME(i) mdstruct[(i)] -#define MDFLD(tmp, dir, i) sprintf((tmp),"%s/%s", (dir), mdstruct[(i)]) -#define MSGPATH(tmp, dir, msg,i) sprintf((tmp),"%s/%s/%s", (dir), mdstruct[(i)],(msg)) - -/* Files associated to a maildir directory */ - -#define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */ -#define MDDIR ".mdir" /* this folder is a directory */ -#define MDUIDLAST ".uidlast" /* last assigned uid */ -#define MDUIDTEMP ".uidtemp" /* We assign uid's no one else */ - - - -/* Support of Courier Structure */ -#define CCLIENT 0 -#define COURIER 1 -#define IS_CCLIENT(t) \ - (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\ - && ((t)[2] == 'd' || (t)[2] == 'D')\ - && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0) - -#define IS_COURIER(t) \ - (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\ - && ((t)[2] == 'c' || (t)[2] == 'C')\ - && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0) -#define MDPREFIX(s) ((s) ? "#mc/" : "#md/") -#define MDSEPARATOR(s) ((s) ? '.' : '/') - -/* UID Support */ - -#define MAXTEMPUID (unsigned long) 180L -const char mduid[] = {',','u','=','\0'}; -#define MDUIDSEP mduid - - -/* Now we deal with messages filenames */ -char mdlocaldomain[MAILTMPLEN+1] = {'\0'}; -pid_t mypid = (pid_t) 0; -static char *mdfpath = NULL; -static char myMdInboxDir[50] = { '\0' };/* Location of the Maildir INBOX */ -static long CourierStyle = CCLIENT; - -#define CHUNK 16384 /* from unix.h */ - -typedef struct courier_local { - char *name; /* name of directory/folder */ - int attribute; /* attributes (children/marked/etc) */ -} COURIERLOCAL; - -typedef struct courier { - char *path; /* Path to collection */ - time_t scantime; /* time at which information was generated */ - int total; /* total number of elements in data */ - COURIERLOCAL **data; -} COURIER_S; - -/* In gdb this is the *(struct maildir_local *)stream->local structure */ -typedef struct maildir_local { - unsigned int dirty : 1; /* diskcopy needs updating */ - unsigned int courier : 1; /* It is Courier style file system */ - unsigned int link : 1; /* There is a symbolic link */ - int candouid; /* we can assign uids and no one else */ - char *uidtempfile; /* path to uid temp file */ - int fd; /* fd of open message */ - char *dir; /* mail directory name */ - char **path; /* path to directories cur, new and tmp */ - unsigned char *buf; /* temporary buffer */ - unsigned long buflen; /* current size of temporary buffer */ - time_t scantime; /* last time directory scanned */ -} MAILDIRLOCAL; - -/* Convenient access to local data */ -#define LOCAL ((MAILDIRLOCAL *) stream->local) - -typedef struct maildir_file_info { - char *name; /* name of the file */ - DirNamesType loc; /* location of this file */ - unsigned long pos; /* place in list where this file is listed */ - off_t size; /* size in bytes, on disk */ - time_t atime; /* last access time */ - time_t mtime; /* last modified time */ - time_t ctime; /* last changed time */ -} MAILDIRFILE; - -#define MDFILE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->name) -#define MDLOC(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->loc) -#define MDPOS(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->pos) -#define MDSIZE(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->size) -#define MDATIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->atime) -#define MDMTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->mtime) -#define MDCTIME(F) (((MAILDIRFILE *)((F)->private.spare.ptr))->ctime) - -/* Function prototypes */ - -DRIVER *maildir_valid (char *name); -MAILSTREAM *maildir_open (MAILSTREAM *stream); -void maildir_close (MAILSTREAM *stream, long options); -long maildir_ping (MAILSTREAM *stream); -void maildir_check (MAILSTREAM *stream); -long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags); -char *maildir_header (MAILSTREAM *stream,unsigned long msgno, - unsigned long *length, long flags); -void maildir_list (MAILSTREAM *stream,char *ref,char *pat); -void *maildir_parameters (long function,void *value); -int maildir_create_folder (char *mailbox); -long maildir_create (MAILSTREAM *stream,char *mailbox); -void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */ -long maildir_expunge (MAILSTREAM *stream, char *sequence, long options); -long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options); -long maildir_append (MAILSTREAM *stream,char *mailbox, append_t af, void *data); -long maildir_delete (MAILSTREAM *stream,char *mailbox); -long maildir_rename (MAILSTREAM *stream,char *old,char *new); -long maildir_sub (MAILSTREAM *stream,char *mailbox); -long maildir_unsub (MAILSTREAM *stream,char *mailbox); -void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat); -void courier_list (MAILSTREAM *stream,char *ref, char *pat); - -/* utility functions */ -void courier_realname (char *name, char *realname); -long maildir_dirfmttest (char *name); -char *maildir_file (char *dst,char *name); -int maildir_select (const struct direct *name); -int maildir_namesort (const struct direct **d1, const struct direct **d2); -unsigned long antoul (char *seed); -unsigned long mdfntoul (char *name); -int courier_dir_select (const struct direct *name); -int courier_dir_sort (const struct direct **d1, const struct direct **d2); -long maildir_canonicalize (char *pattern,char *ref,char *pat); -void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); -void courier_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); -int maildir_file_path(char *name, char *tmp, size_t sizeoftmp); -int maildir_valid_name (char *name); -int maildir_valid_dir (char *name); -int is_valid_maildir (char **name); -int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp); -char *maildir_remove_root(char *name); -char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags); -unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno, - DirNamesType dirtype); -int maildir_eliminate_duplicate (char *name, struct direct ***flist, - unsigned long *nfiles); -int maildir_doscandir (char *name, struct direct ***flist, int flag); -unsigned long maildir_scandir (char *name, struct direct ***flist, - unsigned long *nfiles, int *scand, int flag); -void maildir_parse_folder (MAILSTREAM *stream, int full); -void md_domain_name (void); -char *myrootdir (char *name); -char *mdirpath (void); -int maildir_initial_check (MAILSTREAM *stream, DirNamesType dirtype); -unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, - DirNamesType dirtype, struct direct **names, unsigned long nfiles, int full); -int same_maildir_file(char *name1, char *name2); -int comp_maildir_file(char *name1, char *name2); -int maildir_message_in_list(char *msgname, struct direct **names, - unsigned long bottom, unsigned long top, unsigned long *pos); -void maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t); -int maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno); -void maildir_abort (MAILSTREAM *stream); -int maildir_contains_folder(char *dirname, char *name); -int maildir_is_dir(char *dirname, char *name); -int maildir_dir_is_empty(char *mailbox); -int maildir_create_work (char *mailbox, int loop); -void maildir_get_file (MAILDIRFILE **mdfile); -void maildir_free_file (void **mdfile); -void maildir_free_file_only (void **mdfile); -int maildir_any_new_msgs(char *mailbox); -void maildir_get_date(MAILSTREAM *stream, unsigned long msgno); -void maildir_fast (MAILSTREAM *stream,char *sequence,long flags); - -/* Courier server support */ -void courier_free_cdir (COURIER_S **cdir); -COURIER_S *courier_get_cdir (int total); -int courier_search_list(COURIERLOCAL **data, char *name, int first, int last); -COURIER_S *courier_list_dir(char *curdir); -void courier_list_info(COURIER_S **cdirp, char *data, int i); - -/* UID Support */ -int maildir_can_assign_uid (MAILSTREAM *stream); -void maildir_read_uid(MAILSTREAM *stream, unsigned long *uid_last, - unsigned long *uid_validity); -void maildir_write_uid(MAILSTREAM *stream, unsigned long uid_last, - unsigned long uid_validity); -unsigned long maildir_get_uid(char *name); -void maildir_delete_uid(MAILSTREAM *stream, unsigned long msgno); -void maildir_assign_uid(MAILSTREAM *stream, unsigned long msgno, unsigned long uid); -void maildir_uid_renew_tempfile(MAILSTREAM *stream); - diff --git a/imap/src/osdep/unix/os_cyg.h b/imap/src/osdep/unix/os_cyg.h index 81397225..061db332 100644 --- a/imap/src/osdep/unix/os_cyg.h +++ b/imap/src/osdep/unix/os_cyg.h @@ -47,7 +47,6 @@ #define setpgrp setpgid #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */ -#define FLAGSEP ';' #define geteuid Geteuid uid_t Geteuid (void); |