summaryrefslogtreecommitdiff
path: root/imap/src/osdep
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2013-05-31 17:16:44 -0600
committerEduardo Chappa <chappa@washington.edu>2013-05-31 17:16:44 -0600
commita46157ba61f2c65f88b42abb31db60c4a714f87b (patch)
treee37bc41ad2f57b3fd2bad310576cc155a58ca6b7 /imap/src/osdep
parent81e994d7907f850506ddc248f84761a54995e58c (diff)
downloadalpine-a46157ba61f2c65f88b42abb31db60c4a714f87b.tar.xz
* somehow all.patch got here. Reversing.
Diffstat (limited to 'imap/src/osdep')
-rw-r--r--imap/src/osdep/unix/Makefile8
-rw-r--r--imap/src/osdep/unix/dummy.c48
-rw-r--r--imap/src/osdep/unix/maildir.c2638
-rw-r--r--imap/src/osdep/unix/maildir.h226
-rw-r--r--imap/src/osdep/unix/os_cyg.h1
5 files changed, 13 insertions, 2908 deletions
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);