Blob Blame History Raw
diff -rc alpine-2.26/alpine/alpine.c alpine-2.26.maildir/alpine/alpine.c
*** alpine-2.26/alpine/alpine.c	2022-06-02 18:14:00.463274817 -0600
--- alpine-2.26.maildir/alpine/alpine.c	2022-06-02 18:14:52.219147911 -0600
***************
*** 593,598 ****
--- 593,603 ----
      if(F_ON(F_MAILDROPS_PRESERVE_STATE, ps_global))
        mail_parameters(NULL, SET_SNARFPRESERVE, (void *) TRUE);
  
+ #ifndef _WINDOWS
+     rv = F_ON(F_COURIER_FOLDER_LIST, ps_global) ? 1 : 0;
+     mail_parameters(NULL,SET_COURIERSTYLE, (void *) &rv);
+ #endif
+ 
      rvl = 0L;
      if(pine_state->VAR_NNTPRANGE){
  	if(!SVAR_NNTPRANGE(pine_state, rvl, tmp_20k_buf, SIZEOF_20KBUF))
diff -rc alpine-2.26/alpine/confscroll.c alpine-2.26.maildir/alpine/confscroll.c
*** alpine-2.26/alpine/confscroll.c	2022-06-02 18:14:00.463274817 -0600
--- alpine-2.26.maildir/alpine/confscroll.c	2022-06-02 18:14:52.223147900 -0600
***************
*** 5565,5570 ****
--- 5565,5576 ----
  			  (void *)var->current_val.p);
      }
  #endif
+ #ifndef _WINDOWS
+     else if(var == &ps->vars[V_MAILDIR_LOCATION]){
+       if(var->current_val.p && var->current_val.p[0])
+ 	mail_parameters(NULL, SET_MDINBOXPATH, (void *)var->current_val.p);
+     }
+ #endif
      else if(revert && standard_radio_var(ps, var)){
  
  	cur_rule_value(var, TRUE, FALSE);
diff -rc alpine-2.26/imap/src/c-client/mail.c alpine-2.26.maildir/imap/src/c-client/mail.c
*** alpine-2.26/imap/src/c-client/mail.c	2022-06-02 18:14:00.471274797 -0600
--- alpine-2.26.maildir/imap/src/c-client/mail.c	2022-06-02 18:14:52.223147900 -0600
***************
*** 1071,1077 ****
    MAILSTREAM *ts;
    char *s,*t,tmp[MAILTMPLEN];
    size_t i;
!   DRIVER *d;
  				/* never allow names with newlines */
    if ((s = strpbrk (mailbox,"\015\012")) != NULL) {
      MM_LOG ("Can't create mailbox with such a name",ERROR);
--- 1071,1077 ----
    MAILSTREAM *ts;
    char *s,*t,tmp[MAILTMPLEN];
    size_t i;
!   DRIVER *d, *md;
  				/* never allow names with newlines */
    if ((s = strpbrk (mailbox,"\015\012")) != NULL) {
      MM_LOG ("Can't create mailbox with such a name",ERROR);
***************
*** 1095,1100 ****
--- 1095,1102 ----
      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')) &&
***************
*** 1125,1130 ****
--- 1127,1139 ----
  	   (((*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);
diff -rc alpine-2.26/imap/src/c-client/mail.h alpine-2.26.maildir/imap/src/c-client/mail.h
*** alpine-2.26/imap/src/c-client/mail.h	2022-06-02 18:14:00.471274797 -0600
--- alpine-2.26.maildir/imap/src/c-client/mail.h	2022-06-02 18:14:52.239147861 -0600
***************
*** 389,394 ****
--- 389,398 ----
  #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 */
  
diff -rc alpine-2.26/imap/src/osdep/unix/dummy.c alpine-2.26.maildir/imap/src/osdep/unix/dummy.c
*** alpine-2.26/imap/src/osdep/unix/dummy.c	2022-06-02 18:14:00.475274788 -0600
--- alpine-2.26.maildir/imap/src/osdep/unix/dummy.c	2022-06-02 18:14:52.243147852 -0600
***************
*** 33,38 ****
--- 33,39 ----
  #include <pwd.h>
  #include <sys/stat.h>
  #include "dummy.h"
+ #include "maildir.h"
  #include "misc.h"
  
  /* Function prototypes */
***************
*** 104,116 ****
   * Accepts: mailbox name
   * Returns: our driver if name is valid, NIL otherwise
   */
! 
  DRIVER *dummy_valid (char *name)
  {
!   char *s,tmp[MAILTMPLEN];
    struct stat sbuf;
  				/* must be valid local mailbox */
!   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) {
--- 105,123 ----
   * 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;
    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))) {
  				/* indeterminate clearbox INBOX */
      if (!*s) return &dummydriver;
      else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) {
***************
*** 119,126 ****
        return &dummydriver;
      }
  				/* blackbox INBOX does not exist yet */
!     else if (!compare_cstring (name,"INBOX")) return &dummydriver;
    }
    return NIL;
  }
  
--- 126,134 ----
        return &dummydriver;
      }
  				/* blackbox INBOX does not exist yet */
!     else if (!compare_cstring (rname,"INBOX")) return &dummydriver;
    }
+   if(rname) fs_give((void **)&rname);
    return NIL;
  }
  
***************
*** 453,458 ****
--- 461,468 ----
  {
    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);
***************
*** 518,523 ****
--- 528,541 ----
  {
    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",mailbox);
      MM_LOG (tmp,ERROR);
***************
*** 543,554 ****
  long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
  {
    struct stat sbuf;
!   char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
  				/* no trailing / allowed */
!   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",old,newname);
      MM_LOG (mbx,ERROR);
      return NIL;
    }
--- 561,583 ----
  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);
  				/* no trailing / allowed */
!   if (!dummy_file (oldname,rold) || !(s = dummy_file (mbx,rnewname)) ||
        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);
      MM_LOG (mbx,ERROR);
      return NIL;
    }
***************
*** 564,577 ****
      }
    }
  				/* rename of non-ex INBOX creates dest */
!   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",old,newname,
  	     strerror (errno));
      MM_LOG (tmp,ERROR);
      return NIL;
    }
    return T;			/* return success */
  }
  
--- 593,608 ----
      }
    }
  				/* rename of non-ex INBOX creates dest */
!   if (!compare_cstring (rold,"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,
  	     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 -rc alpine-2.26/imap/src/osdep/unix/maildir.c alpine-2.26.maildir/imap/src/osdep/unix/maildir.c
*** alpine-2.26/imap/src/osdep/unix/maildir.c	2022-06-02 18:14:52.323147655 -0600
--- alpine-2.26.maildir/imap/src/osdep/unix/maildir.c	2022-06-02 18:14:52.251147832 -0600
***************
*** 0 ****
--- 1,2865 ----
+ /*
+  * Maildir driver for Alpine 2.25
+  * 
+  * Written by Eduardo Chappa <alpine.chappa@yandex.com>
+  * Last Update: October 16, 2021.
+  *
+  */
+ 
+ #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"
+ 
+ /* 
+  * 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! */
+ 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 */
+ char *mdstruct[] = {"cur", "tmp", "new", NULL};
+ #define MDNAME(i) mdstruct[(i)]
+ #define MDFLD(X, Y, i) do { snprintf((X), sizeof((X)), "%.*s/%.*s",	\
+ 				    (int) (sizeof((X)) - 6), (Y),	\
+ 				    3, mdstruct[(i)]);			\
+ 				(X)[sizeof((X)) - 1] = '\0';		\
+ 		       } while(0)
+ 				
+ #define MSGPATH(X, Y, Z,i) do { snprintf((X), sizeof((X)), "%.*s/%.*s/%.*s",		\
+ 				     (int) strlen((Y)), (Y),				\
+ 					3, mdstruct[(i)],				\
+ 				      (int)(sizeof((X)) - strlen((Y)) - 3 - 3), (Z));	\
+ 				(X)[sizeof((X)) - 1] = '\0';				\
+ 			   } while(0)
+ 
+ /* 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 */
+ 
+ /* 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)
+ 
+ #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)
+ 
+ /* 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){
+       if(namesnew){
+ 	for(i = 0L; i < nfilesnew; i++)
+ 	   fs_give((void **)&namesnew[i]);
+ 	fs_give((void **) &namesnew);
+       }
+       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(namescur){
+ 	  for(i = 0L; i < nfilescur; i++)
+ 	    fs_give((void **)&namescur[i]);
+ 	  fs_give((void **) &namescur);
+ 	}
+ 	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, len;
+    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;
+    len = LOCAL->path[Cur] ? (int) strlen(LOCAL->path[Cur]) : 0;
+    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", 
+ 		   len, LOCAL->path[Cur] ? LOCAL->path[Cur] : "",
+ 		   (int) sizeof(newfile) - len, tmp);
+ 		newfile[sizeof(newfile)-1] = '\0';
+ 		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;
+ 
+   if (length)
+      *length = 0L;
+   LOCAL->buf[0] = '\0';
+ 
+   MSGPATH(tmp, LOCAL->dir, MDFILE(elt), MDLOC(elt));
+   if (LOCAL->fd < 0 && ((LOCAL->fd = open (tmp,O_RDONLY,NIL)) < 0))
+      return maildir_update_elt_maildirp(stream, msgno) > 0
+ 	    ? maildir_text_work(stream, mail_elt(stream, msgno),length, flags)
+ 	    : 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);
+ 
+    if(scan_err < 0) return -1;
+ 
+    elt = mail_elt (stream,msgno);
+ 
+    in_list = nfiles > 0L
+ 	    ? maildir_message_in_list(MDFILE(elt), names, 0L, nfiles - 1L, &pos)
+ 	    : 0;
+ 
+    if (in_list && pos >= 0L && pos < nfiles
+ 	&& strcmp(MDFILE(elt), names[pos]->d_name)){
+ 	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);
+ 	}
+    }
+    else in_list = 0;	/* we did not update the file name */
+ 
+    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 = NULL;
+   MESSAGECACHE *elt;
+ 
+   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)) < 0)){
+      if(errno == EACCES)
+         mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR);
+      return maildir_update_elt_maildirp(stream, msgno) > 0
+ 	    ? maildir_header(stream, msgno, length, flags)
+ 	    : 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;	/* fix by Chris Caputo */
+   case GET_COURIERSTYLE:
+     ret = (void *) &CourierStyle;	/* fix by Chris Caputo */
+     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++){
+ 	int len;
+ 	MDFLD(tmp, mailbox, i);
+ 	len = (int) strlen(tmp);
+ 	if (mkdir(tmp, 0700) && errno != EEXIST){ /* try to make new dir */
+ 	    snprintf (err, sizeof(err), "Can't create %.*s: %.*s", len, tmp, (int)(sizeof(err) - len - 16), strerror(errno));
+ 	    err[sizeof(err) - 1] = '\0';
+ 	    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;
+ 	   int len = (int) (sizeof(tmp2) - strlen(MDDIR)) - 1;
+ 	   snprintf(tmp2, sizeof(tmp2), "%.*s%.*s", len, tmp, (int) strlen(MDDIR), MDDIR);
+ 	   tmp2[sizeof(tmp2) - 1] = '\0';
+ 	   if ((fp = fopen(tmp2,"w")) == NULL){
+ 	      snprintf (err, sizeof(err), "Problem creating %.*s: %.*s", 
+ 			len, tmp2, 
+ 			(int) sizeof(err) - len - 19, strerror(errno));
+ 	      err[sizeof(err) - 1] = '\0';
+               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", 
+ 			(int) strlen(LOCAL->path[Cur]), LOCAL->path[Cur],
+ 			(int) (sizeof(oldfile) - strlen(LOCAL->path[Cur])),fn);
+ 	   oldfile[sizeof(oldfile) - 1] = '\0';
+ 	}
+         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",
+ 			(int) strlen(LOCAL->path[Cur]), LOCAL->path[Cur],
+ 			(int) (sizeof(newfile) - strlen(LOCAL->path[Cur]) - 4), fn);
+ 	newfile[sizeof(newfile) - 1] = '\0';
+         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, done, fail;
+   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;
+   struct stat sbuf;
+ 
+   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 */
+   do {
+     fail = done = 0;			/* we have not determined name of message file yet */
+     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;
+     }
+ 
+     if(date){
+       struct tm tm;
+ 
+       tm.tm_sec  = elt.seconds;
+       tm.tm_min  = elt.minutes;
+       tm.tm_hour = elt.hours;
+       tm.tm_mday = elt.day;
+       tm.tm_mon  = elt.month - 1;
+       tm.tm_year = BASEYEAR + elt.year - 1900;
+ 
+       ti = mktime(&tm);
+     } else ti = time(0);
+ 
+     f = mail_parse_flags (stream,flags,&uf);
+     do {
+ 			/* build file name we will use, fix by Chris Caputo */
+ 	snprintf (file, sizeof(file), "%lu.%d_%09u.%.*s%.*s%.*s%.*s%.*s%.*s",
+ 		ti, mypid, transact++,
+ 		(int)(sizeof(file) - 50), mdlocaldomain, (int) strlen(MDSEP(2)), (f ? MDSEP(2) : ""),
+ 		1, MDFLAG(Draft, f&fDRAFT), 1, MDFLAG(Flagged, f&fFLAGGED),
+ 		1, MDFLAG(Replied, f&fANSWERED), 1, MDFLAG(Seen, f&fSEEN));
+ 				/* build tmp file name */
+ 	if (maildir_file_path(mailbox, tmp, sizeof(tmp)))	/* copy in TMP */
+ 	   MSGPATH(path1, tmp, file, Tmp);
+ 				/* build final filename to use */
+         if (maildir_file_path(mailbox, tmp, sizeof(tmp)))
+ 	   MSGPATH(path2, tmp, file, New);			/* copy in NEW */
+         if(stat(path1, &sbuf) < 0 && errno == ENOENT 
+ 	   &&  stat(path2, &sbuf) < 0 && errno == ENOENT)
+ 	  done++;
+ 	else
+ 	  fail++;
+ 	if(fail == 1000){
+ 	   snprintf (tmp, sizeof(tmp), "Failure to create append message name");
+ 	   mm_log (tmp, ERROR);
+ 	   return NIL;
+ 	}
+     } while (done == 0);
+ 
+     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 */
+ 
+     if (rename (path1,path2) < 0) {
+        snprintf (tmp, sizeof(tmp), "Message append failed: %s", strerror (errno));
+        mm_log (tmp, ERROR);
+        ret = NIL;
+     }
+     unlink (path1);
+     if(date){
+ 	time_t tp[2];
+         tp[0] = tp[1] = ti;
+         utime (path2,tp);
+     }
+ 
+     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, len;
+   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", (int) (sizeof(tmp) - strlen(MDDIR) - 2), realname, (int) strlen(MDDIR), MDDIR);
+      tmp[sizeof(tmp) - 1] = '\0';
+      if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode))
+ 	rv = unlink(tmp);
+      else if (errno == ENOENT)
+ 	rv = 0;
+      if (rv != 0){
+ 	len = (int) strlen(tmp2);
+ 	snprintf(tmp, sizeof(tmp), "Can not remove %.*s/%.*s: %.*s", 
+ 		len, tmp2, 
+ 		(int) strlen(MDDIR), MDDIR, 
+ 		(int) (sizeof(tmp) - strlen(MDDIR)) - len - 19, strerror(errno));
+ 	tmp[sizeof(tmp) - 1] = '\0';
+ 	mm_log (tmp,ERROR);
+ 	return NIL;
+      }
+      if (!maildir_valid(realname) && rmdir(realname) != 0){
+ 	len = (int) strlen(mailbox);
+ 	snprintf(tmp, sizeof(tmp), "Can not remove %.*s/: %.*s", 
+ 		len, mailbox, 
+ 		(int)(sizeof(tmp) - len - 19), strerror(errno));
+ 	tmp[sizeof(tmp)-1] = '\0';
+ 	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))){
+ 	  len = (int) strlen(mailbox);
+ 	  snprintf(tmp, sizeof(tmp), "Can not read %.*s/: %.*s",
+ 		len, mailbox, 
+ 		(int)(sizeof(tmp) - len - 19), strerror(errno));
+ 	  tmp[sizeof(tmp)-1] = '\0';
+ 	  mm_log (tmp, ERROR);
+ 	  return NIL;
+       }
+ 
+       while ((d = readdir(dirp)) != NULL){
+ 	 len = (int) strlen(tmp);
+ 	 if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){
+ 	    snprintf(tmp2, sizeof(tmp2), "%.*s/%.*s", 
+ 		len, tmp, 
+ 		(int) (sizeof(tmp) - len) -1, d->d_name);
+ 	    tmp2[sizeof(tmp2) - 1] = '\0';
+ 	    if (unlink(tmp2) != 0){
+ 	       len = (int) strlen(mailbox);
+ 	       snprintf(tmp2, sizeof(tmp2), "Can not remove %.*s: %.*s",
+ 			len, mailbox, 
+ 			(int)(sizeof(tmp2) - len - 18), strerror(errno));
+ 	       tmp2[sizeof(tmp2)-1] = '\0';
+ 	       mm_log (tmp2, ERROR);
+ 	       return NIL;
+ 	    }
+ 	 }
+       }
+       closedir(dirp);
+       if (rmdir(tmp) != 0){
+ 	 len = (int) strlen(mailbox);
+ 	 snprintf(tmp, sizeof(tmp), "Can not remove %.*s: %.*s",
+ 			len, mailbox, 
+ 			(int)(sizeof(tmp) - len - 18), strerror(errno));
+ 	 tmp[sizeof(tmp)-1] = '\0';
+ 	 mm_log (tmp, ERROR);
+ 	 return NIL;
+       }
+   }
+   /* 
+    * ok we have removed all subdirectories of the folder mailbox, Remove the
+    * hidden files.
+    */
+ 
+   if(!(dirp = opendir (realname))){
+     len = (int) strlen(realname);
+     snprintf(tmp, sizeof(tmp), "Can not read %.*s/: %.*s",
+ 			len, realname,
+ 			(int)(sizeof(tmp) - len - 16), strerror(errno));
+     tmp[sizeof(tmp)-1] = '\0';
+     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++;
+ 	   len = (int) strlen(realname);
+ 	   snprintf(tmp, sizeof(tmp), "%.*s/%.*s",
+ 			len, realname,
+ 			(int)(sizeof(tmp) - len - 2), strerror(errno));
+ 	   tmp[sizeof(tmp)-1] = '\0';
+ 	   if (unlink(tmp) != 0)
+ 	      error++;
+ 	}
+   }
+   closedir(dirp);
+   if (error || 
+ 	 (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(realname) < 0)){
+ 	len = (int) strlen(mailbox);
+         snprintf(tmp, sizeof(tmp), "Can not remove folder %.*s: %.*s",
+ 			len, mailbox,
+ 			(int)(sizeof(tmp) - len - 16), strerror(errno));
+ 	tmp[sizeof(tmp)-1] = '\0';
+         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, len;
+   long rv = LONGT;
+   COURIER_S *cdir;
+ 
+   if((IS_COURIER(old) || IS_COURIER(new)) && !courier){
+     len = (int) strlen(old);
+     snprintf (tmp, sizeof(tmp), "Can't rename mailbox %.*s to %.*s", 
+ 	len, old, 
+ 	(int) sizeof(tmp) - len - 26, new);
+     tmp[sizeof(tmp) - 1] = '\0';
+     mm_log (tmp, ERROR);
+     return NIL;
+   }
+ 
+   if (!maildir_valid(old)){
+     snprintf (tmp, sizeof(tmp), "Can't rename mailbox %.*s: folder not in maildir format",
+ 	(int) sizeof(tmp) - 52, old);
+     tmp[sizeof(tmp) - 1] = '\0';
+     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",
+ 		(int) sizeof(tmp) - 53, new);
+     tmp[sizeof(tmp) - 1] = '\0';
+     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",
+ 		(int)(sizeof(tmp) - 54), new);
+     tmp[sizeof(tmp) - 1]  = '\0';
+     mm_log (tmp, ERROR);
+     return NIL;
+   }
+ 
+   if(!courier){
+     if (rename(realold, realnew)){	/* try to rename the directory */
+ 	int len2 = (int) strlen(new);
+ 	len = (int) strlen(old);
+        snprintf(tmp, sizeof(tmp), "Can't rename mailbox %.*s to %.*s: %.*s", 
+ 		len, old, 
+ 	        len2, new,
+ 		(int) sizeof(tmp) - len - len2 - 28, strerror(errno));
+        tmp[sizeof(tmp) - 1] = '\0';
+        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)){
+ 	len = (int) strlen(new);
+ 	snprintf(tmp, sizeof(tmp), "%.*s%.*s", 
+ 			len, new, 
+ 			(int) sizeof(tmp) - len - 1, cdir->data[i]->name+strlen(old));
+ 	tmp[sizeof(tmp) - 1] = '\0';
+ 	maildir_file_path(cdir->data[i]->name, realold, sizeof(realold));
+ 	maildir_file_path(tmp, realnew, sizeof(realnew));
+ 	if (rename(realold, realnew)){
+ 	   int len2 = (int) strlen(new);
+ 	   len = (int) strlen(old);
+ 	   snprintf (tmp, sizeof(tmp), "Can't rename mailbox %.*s to %.*s: %.*s",
+ 			len, old,
+ 			len2, new,
+ 			(int) sizeof(tmp) - len - len2 - 28, strerror(errno));
+ 	   tmp[sizeof(tmp) - 1] = '\0';
+ 	   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], tmp[MAILTMPLEN];
+                                 /* get canonical form of name */
+   if (maildir_canonicalize (test, ref, pat) && (s = sm_read (tmp, &sdb))) {
+     do if (pmatch_full (s, test, '/')) mm_lsub (stream, '/', s, NIL);
+     while ((s = sm_read (tmp, &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;
+   int len;
+   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);
+      }
+ 
+      len = (int) strlen(name);
+      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", len, name,(int) sizeof(tmp) - len - 1, d->d_name);
+ 	  else strcpy(tmp, d->d_name);
+ 	  tmp[sizeof(tmp) - 1] = '\0';
+ 
+ 	  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", len, name, (int) sizeof(tmp) - len - 1, d->d_name);
+ 	       else strcpy(tmp, d->d_name);
+ 	       tmp[sizeof(tmp) - 1] = '\0';
+                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;
+   int done = 0; 	/* fix by Chris Caputo */
+ 
+   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 (!done && (b = strrchr(tmp+offset, FLAGSEP)) != NULL){ 	/* fix by Chris Caputo */
+     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;
+ 		break;
+ 	default: done++; 	/* fix by Chris Caputo */
+ 		break;
+     }
+     offset++;
+     for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++);
+   }
+   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, len;
+   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;
+ 
+   len = (int) strlen(tmp2);
+ 
+   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", len, tmp2, (int) sizeof(tmp) - len - 2, d->d_name);
+        tmp[sizeof(tmp) - 1] = '\0';
+        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), len;
+   DIR *dir;
+   struct direct *d;
+   struct stat sbuf;
+ 
+   maildir_file_path(mailbox, tmp2, sizeof(tmp2));
+ 
+   if(courier){
+      strcpy(tmp3, tmp2);
+      if((s = strrchr(tmp2, '/')) != NULL)
+ 	*s = '\0';
+   }
+ 
+   if (!(dir = opendir (tmp2)))
+      return rv;
+ 
+   len = (int) strlen(tmp2);
+ 
+   if(courier){
+      while((d = readdir(dir)) != NULL){
+         snprintf(tmp, sizeof(tmp), "%.*s/%.*s", len, tmp2, (int)(sizeof(tmp) - len - 2),d->d_name);
+ 	tmp[sizeof(tmp) - 1] = '\0';
+ 	if(!strncmp(tmp, tmp3, strlen(tmp3)) 
+ 	   && tmp[strlen(tmp3)] == '.'){
+ 	   rv = 0;
+ 	   break;
+ 	}
+      }
+   }
+   else
+     while ((d = readdir(dir)) != NULL){
+       snprintf(tmp, sizeof(tmp), "%.*s/%.*s", len, tmp2, (int)(sizeof(tmp) - len - 2), d->d_name);
+       tmp[sizeof(tmp) - 1] = '\0';
+       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)
+ 	&& strncmp(d->d_name, MDUIDTEMP, 8)
+ 	&& strcmp(d->d_name, ".mbsyncstate")
+ 	&& strcmp(d->d_name, ".mbsyncstate")
+ 	&& strcmp(d->d_name, ".mbsyncstate.new")
+ 	&& strcmp(d->d_name, ".mbsyncstate.journal")
+ 	&& strcmp(d->d_name, ".mbsyncstate.lock")
+ 	&& !(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")) != NULL){
+       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")) != NULL)
+      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)) != NULL){
+      *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 -rc alpine-2.26/imap/src/osdep/unix/maildir.h alpine-2.26.maildir/imap/src/osdep/unix/maildir.h
*** alpine-2.26/imap/src/osdep/unix/maildir.h	2022-06-02 18:14:52.323147655 -0600
--- alpine-2.26.maildir/imap/src/osdep/unix/maildir.h	2022-06-02 18:14:52.251147832 -0600
***************
*** 0 ****
--- 1,122 ----
+ typedef enum  {Draft, Flagged, Passed, Replied, Seen, Trashed, 
+ 	       EmptyFlag, EndFlags} MdFlagNamesType;
+ 
+ typedef enum {Cur, Tmp, New, EndDir} DirNamesType;
+ 
+ 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;
+ 
+ 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;
+ 
+ /* 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 -rc alpine-2.26/imap/src/osdep/unix/Makefile alpine-2.26.maildir/imap/src/osdep/unix/Makefile
*** alpine-2.26/imap/src/osdep/unix/Makefile	2022-06-02 18:14:00.475274788 -0600
--- alpine-2.26.maildir/imap/src/osdep/unix/Makefile	2022-06-02 18:14:52.255147822 -0600
***************
*** 146,152 ****
  # 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=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
  CHUNKSIZE=65536
  
  # Normally no need to change any of these
--- 146,152 ----
  # 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
  CHUNKSIZE=65536
  
  # Normally no need to change any of these
***************
*** 155,161 ****
  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 http.o json.o pop3.o \
!  unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o sha.o
  CFLAGS=-g
  
  CAT=cat
--- 155,163 ----
  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 http.o json.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 sha.o
! 
  CFLAGS=-g
  
  CAT=cat
***************
*** 292,298 ****
  
  cyg:	# Cygwin - note that most local file drivers don't work!!
  	$(BUILD) `$(CAT) SPECIALS` OS=$@ \
! 	DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \
  	SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
  	SPOOLDIR=/var \
  	ACTIVEFILE=/usr/local/news/lib/active \
--- 294,300 ----
  
  cyg:	# Cygwin - note that most local file drivers don't work!!
  	$(BUILD) `$(CAT) SPECIALS` OS=$@ \
! 	DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \
  	SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
  	SPOOLDIR=/var \
  	ACTIVEFILE=/usr/local/news/lib/active \
***************
*** 922,927 ****
--- 924,930 ----
  json.o: mail.h misc.h osdep.h utf8.h json.h
  http.o: mail.h misc.h osdep.h utf8.h http.h json.h
  sha.o: mail.h misc.h osdep.h sha.h sha-private.h hash.h hmac.c sha1.c sha224-256.c sha384-512.c usha.c
+ maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
  
  # OS-dependent
  
diff -rc alpine-2.26/imap/src/osdep/unix/os_cyg.h alpine-2.26.maildir/imap/src/osdep/unix/os_cyg.h
*** alpine-2.26/imap/src/osdep/unix/os_cyg.h	2022-06-02 18:14:00.475274788 -0600
--- alpine-2.26.maildir/imap/src/osdep/unix/os_cyg.h	2022-06-02 18:14:52.255147822 -0600
***************
*** 47,52 ****
--- 47,53 ----
  #define setpgrp setpgid
  
  #define SYSTEMUID 18		/* Cygwin returns this for SYSTEM */
+ #define FLAGSEP ';'
  #define geteuid Geteuid
  uid_t Geteuid (void);
  
diff -rc alpine-2.26/pith/conf.c alpine-2.26.maildir/pith/conf.c
*** alpine-2.26/pith/conf.c	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/conf.c	2022-06-02 18:14:52.259147813 -0600
***************
*** 451,456 ****
--- 451,459 ----
  
  CONF_TXT_T cf_text_newsrc_path[] =		"Full path and name of NEWSRC file";
  
+ #ifndef _WINDOWS
+ CONF_TXT_T cf_text_maildir_location[] = "Location relative to your HOME directory of the directory where your INBOX\n# for the maildir format is located. Default value is \"Maildir\". If your\n# inbox is located at \"~/Maildir\" you do not need to change this value.\n# A common value is also \".maildir\"";
+ #endif
  
  /*----------------------------------------------------------------------
  These are the variables that control a number of pine functions.  They
***************
*** 655,660 ****
--- 658,667 ----
  	NULL,			cf_text_news_active},
  {"news-spool-directory",		0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
  	NULL,			cf_text_news_spooldir},
+ #ifndef _WINDOWS
+ {"maildir-location",			0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ 	"Maildir Location",			cf_text_maildir_location},
+ #endif
  {"upload-command",			0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
  	NULL,			cf_text_upload_cmd},
  {"upload-command-prefix",		0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
***************
*** 2396,2401 ****
--- 2403,2414 ----
        mail_parameters(NULL, SET_NEWSSPOOL,
  		      (void *)VAR_NEWS_SPOOL_DIR);
  
+ #ifndef _WINDOWS
+     set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE);
+     if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0])
+       mail_parameters(NULL, SET_MDINBOXPATH, (void *)VAR_MAILDIR_LOCATION);
+ #endif
+ 
      /* guarantee a save default */
      set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
      if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
***************
*** 3037,3042 ****
--- 3050,3059 ----
  	 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
  	{"vertical-folder-list", "Use Vertical Folder List",
  	 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
+ #ifndef _WINDOWS
+ 	{"use-courier-folder-list", "Courier Style Folder List",
+ 	 F_COURIER_FOLDER_LIST, h_config_courier_list, PREF_FLDR, 0},
+ #endif
  
  /* Addr book */
  	{"combined-addrbook-display", "Combined Address Book Display",
***************
*** 7217,7223 ****
  	       int just_flip_value, EditWhich ew)
  {
      char      **vp, *p, **lval, ***alval;
!     int		og, on_before, was_set;
      char       *err;
      long	l;
  
--- 7234,7240 ----
  	       int just_flip_value, EditWhich ew)
  {
      char      **vp, *p, **lval, ***alval;
!     int		og, on_before, was_set, i;
      char       *err;
      long	l;
  
***************
*** 7270,7275 ****
--- 7287,7299 ----
  
  	break;
  
+ #ifndef _WINDOWS
+       case F_COURIER_FOLDER_LIST:
+       i = F_ON(f->id ,ps) ? 1 : 0;
+       mail_parameters(NULL,SET_COURIERSTYLE, (void *) &i);
+       break; /* COURIER == 1, CCLIENT == 0, see maildir.h */
+ #endif
+ 
        case F_COLOR_LINE_IMPORTANT :
        case F_DATES_TO_LOCAL :
  	clear_index_cache(ps->mail_stream, 0);
***************
*** 8074,8079 ****
--- 8098,8107 ----
  	return(h_config_newmailwidth);
        case V_NEWSRC_PATH :
  	return(h_config_newsrc_path);
+ #ifndef _WINDOWS
+       case V_MAILDIR_LOCATION :
+ 	return(h_config_maildir_location);
+ #endif
        case V_BROWSER :
  	return(h_config_browser);
        case V_HISTORY :
diff -rc alpine-2.26/pith/conf.h alpine-2.26.maildir/pith/conf.h
*** alpine-2.26/pith/conf.h	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/conf.h	2022-06-02 18:14:52.263147802 -0600
***************
*** 265,270 ****
--- 265,274 ----
  #define GLO_NEWS_ACTIVE_PATH	     vars[V_NEWS_ACTIVE_PATH].global_val.p
  #define VAR_NEWS_SPOOL_DIR	     vars[V_NEWS_SPOOL_DIR].current_val.p
  #define GLO_NEWS_SPOOL_DIR	     vars[V_NEWS_SPOOL_DIR].global_val.p
+ #ifndef _WINDOWS
+ #define VAR_MAILDIR_LOCATION	     vars[V_MAILDIR_LOCATION].current_val.p
+ #define GLO_MAILDIR_LOCATION	     vars[V_MAILDIR_LOCATION].global_val.p
+ #endif
  #define VAR_DISABLE_DRIVERS	     vars[V_DISABLE_DRIVERS].current_val.l
  #define VAR_DISABLE_AUTHS	     vars[V_DISABLE_AUTHS].current_val.l
  #define VAR_REMOTE_ABOOK_METADATA    vars[V_REMOTE_ABOOK_METADATA].current_val.p
diff -rc alpine-2.26/pith/conftype.h alpine-2.26.maildir/pith/conftype.h
*** alpine-2.26/pith/conftype.h	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/conftype.h	2022-06-02 18:14:52.275147774 -0600
***************
*** 118,123 ****
--- 118,126 ----
  		, V_NEWSRC_PATH
  		, V_NEWS_ACTIVE_PATH
  		, V_NEWS_SPOOL_DIR
+ #ifndef _WINDOWS
+ 		, V_MAILDIR_LOCATION
+ #endif
  		, V_UPLOAD_CMD
  		, V_UPLOAD_CMD_PREFIX
  		, V_DOWNLOAD_CMD
***************
*** 410,415 ****
--- 413,421 ----
  	F_PASS_C1_CONTROL_CHARS,
  	F_SINGLE_FOLDER_LIST,
  	F_VERTICAL_FOLDER_LIST,
+ #ifndef _WINDOWS
+ 	F_COURIER_FOLDER_LIST,
+ #endif
  	F_TAB_CHK_RECENT,
  	F_AUTO_REPLY_TO,
  	F_VERBOSE_POST,
diff -rc alpine-2.26/pith/headers.h alpine-2.26.maildir/pith/headers.h
*** alpine-2.26/pith/headers.h	2022-06-02 18:14:00.495274738 -0600
--- alpine-2.26.maildir/pith/headers.h	2022-06-02 18:14:52.275147774 -0600
***************
*** 32,37 ****
--- 32,38 ----
  #include "../c-client/utf8.h"	/* for CHARSET and such*/
  #include "../c-client/imap4r1.h"
  #include "../c-client/http.h"	/* for http support */
+ #include "../c-client/maildir.h"
  
  /* include osdep protos and def'ns */
  #include "osdep/bldpath.h"
diff -rc alpine-2.26/pith/init.c alpine-2.26.maildir/pith/init.c
*** alpine-2.26/pith/init.c	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/init.c	2022-06-02 18:14:52.283147754 -0600
***************
*** 404,409 ****
--- 404,412 ----
             && stricmp(filename, folder_base)){
  #else
          if(strncmp(filename, folder_base, folder_base_len) == 0
+ #ifndef _WINDOWS
+ 	   && filename[folder_base_len] != list_cntxt->dir->delim
+ #endif
             && strcmp(filename, folder_base)){
  #endif
  #endif
diff -rc alpine-2.26/pith/pattern.c alpine-2.26.maildir/pith/pattern.c
*** alpine-2.26/pith/pattern.c	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/pattern.c	2022-06-02 18:14:52.291147734 -0600
***************
*** 46,52 ****
  #include "../pith/icache.h"
  #include "../pith/ablookup.h"
  #include "../pith/keyword.h"
! 
  
  /*
   * Internal prototypes
--- 46,54 ----
  #include "../pith/icache.h"
  #include "../pith/ablookup.h"
  #include "../pith/keyword.h"
! #ifndef _WINDOWS
! int maildir_file_path(char *name, char *tmp, size_t sizeoftmp);
! #endif /* _WINDOWS */
  
  /*
   * Internal prototypes
***************
*** 5485,5490 ****
--- 5487,5501 ----
  		break;
  	      
  	      case '#':
+ #ifndef _WINDOWS
+ 		if(!struncmp(patfolder, "#md/", 4)
+ 		       || !struncmp(patfolder, "#mc/", 4)){
+ 		  maildir_file_path(patfolder, tmp1, sizeof(tmp1));
+ 		  if(!strcmp(tmp1, stream->mailbox))
+ 		     match++;
+ 		  break;
+ 		}
+ #endif
  	        if(!strcmp(patfolder, stream->mailbox))
  		  match++;
  
***************
*** 7905,7911 ****
      int           we_cancel = 0, width;
      CONTEXT_S	 *save_context = NULL;
      char	  buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1];
!     char         *save_ref = NULL;
  #define	FILTMSG_MAX	30
  
      if(!stream)
--- 7916,7922 ----
      int           we_cancel = 0, width;
      CONTEXT_S	 *save_context = NULL;
      char	  buf[MAX_SCREEN_COLS+1], sbuf[MAX_SCREEN_COLS+1];
!     char         *save_ref = NULL, *save_dstfldr = NULL, *save_dstfldr2 = NULL;
  #define	FILTMSG_MAX	30
  
      if(!stream)
***************
*** 7939,7944 ****
--- 7950,7965 ----
      if(F_OFF(F_QUELL_FILTER_MSGS, ps_global))
        we_cancel = busy_cue(buf, NULL, 0);
  
+ #ifndef _WINDOWS
+     if(!struncmp(dstfldr, "#md/", 4) || !struncmp(dstfldr, "#mc/", 4)){  
+ 	char tmp1[MAILTMPLEN];
+ 	maildir_file_path(dstfldr, tmp1, sizeof(tmp1));
+ 	save_dstfldr2 = dstfldr;
+ 	save_dstfldr = cpystr(tmp1);
+ 	dstfldr = save_dstfldr;
+    }
+ #endif
+ 
      if(!is_absolute_path(dstfldr)
         && !(save_context = default_save_context(ps_global->context_list)))
        save_context = ps_global->context_list;
***************
*** 8002,8007 ****
--- 8023,8033 ----
      if(we_cancel)
        cancel_busy_cue(buf[0] ? 0 : -1);
  
+     if(save_dstfldr){
+ 	fs_give((void **)&save_dstfldr);
+ 	dstfldr = save_dstfldr2;
+     }
+ 
      return(buf[0] != '\0');
  }
  
diff -rc alpine-2.26/pith/pine.hlp alpine-2.26.maildir/pith/pine.hlp
*** alpine-2.26/pith/pine.hlp	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/pine.hlp	2022-06-02 18:14:52.299147715 -0600
***************
*** 23793,23798 ****
--- 23793,23894 ----
  &lt;End of help on this topic&gt;
  </BODY>
  </HTML>
+ ====== h_config_maildir_location ======
+ <HTML>
+ <HEAD>
+ <TITLE>OPTION: <!--#echo var="VAR_maildir-location"--></TITLE>
+ </HEAD>
+ <BODY>
+ <H1>OPTION: <!--#echo var="VAR_maildir-location"--></H1>
+ 
+ <P>
+ This option should be used only if you have a Maildir folder which you
+ want to use as your INBOX. If this is not your case (or don't know what
+ this is), you can safely ignore this option.
+ 
+ <P>
+ This option overrides the default directory Pine uses to find the location of
+ your INBOX, in case this is in Maildir format. The default value of this
+ option is "Maildir", but in some systems, this directory could have been
+ renamed (e.g. to ".maildir"). If this is your case use this option to change
+ the default.
+ 
+ <P>
+ The value of this option is prefixed with the "~/" string to determine the
+ full path to your INBOX.
+ 
+ <P>
+ You should probably <A HREF="h_config_maildir">read</A> a few tips that 
+ teach you how to configure your maildir for optimal performance. This
+ version also has <A HREF="h_config_courier_list">support</A> for the 
+ Courier style file system when a maildir collection is accessed locally.
+ 
+ <P><UL>
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+ </UL>
+ <P>
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+ ====== h_config_maildir =====
+ <HTML>
+ <HEAD>
+ <TITLE>Maildir Support</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>Maildir Support</H1>
+ 
+ This version of Alpine has been enhanced with Maildir support. This text is 
+ intended to be a reference on its support.
+ <P>
+ 
+ A Maildir folder is a directory that contains three directories called 
+ cur, tmp and new. A program that delivers mail (e.g. postfix) will put new 
+ mail in the new directory. A program that reads mail will look for for old 
+ messages in the cur directory, while it will look for new mail in the new 
+ directory.
+ <P>
+ 
+ In order to use maildir support it is better to set your inbox-path to the 
+ value &quot;#md/inbox&quot; (without quotes). This assumes that your mail 
+ delivery agent is delivering new mail to ~/Maildir/new. If the directory 
+ where new mail is being delivered is not called "Maildir", you can set the 
+ name of the subdirectory of home where it is being delivered in the <A 
+ HREF="h_config_maildir_location"><!--#echo var="VAR_maildir-location"--></A> configuration 
+ variable. Most of the time you will not have to worry about the 
+ <!--#echo var="VAR_maildirlocation"--> variable, because it will probably be set by your 
+ administrator in the pine.conf configuration file.
+ <P>
+ 
+ One of the advantages of the Maildir support of this version of Alpine is 
+ that you do not have to stop using folders in another styles (mbox, mbx, 
+ etc.). This is desirable since the usage of a specific mail storage system 
+ is a personal decision. Folders in the maildir format that are part of the 
+ Mail collection will be recognized without any extra configuration of your 
+ part. If your mail/ collection is located under the mail/ directory, then 
+ creating a new maildir folder in this collection is done by pressing "A" 
+ and entering the string "#driver.md/mail/newfolder". Observe that adding a 
+ new folder as "newfolder" may not create such folder in maildir format.
+ 
+ <P>
+ If you would like to have all folders created in the maildir format by 
+ default, you do so by adding a Maildir Collection. In order to convert 
+ your current mail/ collection into a maildir collection, edit the 
+ collection and change the path variable from &quot;mail/&quot; to 
+ &quot;#md/mail&quot;. In a maildir collection folders of any other format 
+ are ignored.
+ 
+ <P> Finally, This version also has 
+ <A HREF="h_config_courier_list">support</A> for the Courier style file system 
+ when a maildir collection is accessed locally.
+ 
+ <P>
+ <UL>   
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+ </UL><P>
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
  ====== h_config_literal_sig =====
  <HTML>
  <HEAD>
***************
*** 31999,32004 ****
--- 32095,32143 ----
  <P>
  &lt;End of help on this topic&gt;
  </BODY>
+ </HTML>
+ ====== h_config_courier_list =====
+ <HTML>
+ <HEAD>
+ <TITLE>FEATURE: <!--#echo var="FEAT_courier-folder-list"--></TITLE>
+ </HEAD>
+ <BODY>
+ <H1>FEATURE: <!--#echo var="FEAT_courier-folder-list"--></H1>
+ 
+ In a maildir collection, a folder could be used as a directory to store 
+ folders. In the Courier server if you create a folder, then a directory 
+ with the same name is created. If you use this patch to access a 
+ collection created by the Courier server, then the display of such 
+ collection will look confusing. The best way to access a maildir 
+ collection created by the Courier server is by using the &quot;#mc/&quot; 
+ prefix instead of the &quot;#md/&quot; prefix. If you use this alternate 
+ prefix, then this feature applies to you, otherwise you can safely ignore 
+ the text that follows.
+ <P>
+ Depending on if you have enabled the option 
+ <a href="h_config_separate_fold_dir_view"><!--#echo var="FEAT_separate-folder-and-directory-entries"--></a> 
+ a folder may be listed as &quot;folder[.]&quot;, or as two entries in the 
+ list by &quot;folder&quot; and &quot;folder.&quot;.
+ <P>
+ If this option is disabled, Pine will list local folders that are in Courier
+ style format, as &quot;folder&quot;, and those that are also directories as
+ &quot;folder[.]&quot;. This makes the default display cleaner.
+ <P>
+ If this feature is enabled then creating folders in a maildir collection
+ will create a directory with the same name. If this feature is disabled, then 
+ a folder is considered a directory only if it contains subfolders, so you can
+ not create a directory with the same name as an exisiting folder unless 
+ you create a subfolder of that folder first (e.g. if you have a folder
+ called &quot;foo&quot; simply add &quot;foo.bar&quot; directly. This will
+ create the directory &quot;foo&quot; and the subfolder &quot;bar&quot; of it).
+ <P>
+ Observe that this feature works only for maildir collections that are accessed
+ locally. If a collection is accessed remotely then this feature has no value,
+ as the report is created in a server, and Pine only reports what received
+ from the server in this case.
+ <P>
+ &lt;End of help on this topic&gt;
+ </BODY>
  </HTML>
  ====== h_config_verbose_post =====
  <HTML>
diff -rc alpine-2.26/pith/send.c alpine-2.26.maildir/pith/send.c
*** alpine-2.26/pith/send.c	2022-06-02 18:14:00.491274749 -0600
--- alpine-2.26.maildir/pith/send.c	2022-06-02 18:14:52.303147704 -0600
***************
*** 43,48 ****
--- 43,51 ----
  
  #include "../c-client/smtp.h"
  #include "../c-client/nntp.h"
+ #ifndef _WINDOWS
+ int maildir_file_path(char *name, char *tmp, size_t sizeoftmp);
+ #endif /* _WINDOWS */
  
  
  /* this is used in pine_send and pine_simple_send */
***************
*** 246,251 ****
--- 249,261 ----
  
      if(exists & FEX_ISFILE){
  	context_apply(tmp, p_cntxt, mbox, sizeof(tmp));
+ #ifndef _WINDOWS
+         if (!struncmp(tmp, "#md/",4) || !struncmp(tmp, "#mc/", 4)){
+ 	    char tmp2[MAILTMPLEN];
+ 	    maildir_file_path(tmp, tmp2, sizeof(tmp2));
+ 	    strcpy(tmp, tmp2);
+ 	}
+ #endif
  	if(!(IS_REMOTE(tmp) || is_absolute_path(tmp))){
  	    /*
  	     * The mbox is relative to the home directory.
diff -rc alpine-2.26/README.maildir alpine-2.26.maildir/README.maildir
*** alpine-2.26/README.maildir	2022-06-02 18:14:52.327147646 -0600
--- alpine-2.26.maildir/README.maildir	2022-06-02 18:14:52.303147704 -0600
***************
*** 0 ****
--- 1,149 ----
+ ---------------------------------------
+ 
+ Maildir Driver for Alpine 2.0
+ By Eduardo Chappa 
+ <alpine.chappa@gmx.com>
+ 
+ ---------------------------------------
+ 1. General Information About This Patch
+ ---------------------------------------
+ 
+ This patch adds support for the maildir format to Alpine. We take the 
+ approach that this patch is one more driver among the number of formats 
+ supported by Alpine (more generally c-client). This approach differs from 
+ older versions of similar patches, in that once a maildir patch was 
+ applied, it was assumed that all your folders would be created in the 
+ maildir format. 
+ 
+ This patch does not assume that maildir is a preferred format, instead 
+ puts maildir in equal footing with other formats (mbox, mbx, mix, etc), 
+ and so a maildir folder in the mail/ collection is treated in the same way 
+ as any other folder in any other format. In other words, just by reading 
+ the name of a folder, or opening it, or doing any operation with it, you 
+ can not know in which format the folder is.
+ 
+ This implies that if you want to add a folder in the maildir format to the 
+ mail/ collection, then you must add by pressing "A" in the folder list 
+ collection and enter "#driver.md/mail/name_maildir_folder".
+ 
+ If you only want to use maildir, however, you can do so too. In this case, 
+ you must create a maildir collection. In that collection, only maildir 
+ folders will be listed. If there is any folder in any other format, that 
+ folder will be ignored. In another words, any folder listed there is in 
+ maildir format and can be accessed through that collection, conversely, 
+ any folder not listed there is not in maildir format and there is no way 
+ to access it using this collection.
+ 
+ In order to create a maildir collection, you could press M S L, and "A" to 
+ add a collection. Fill in the required fields as follows:
+ 
+ Nickname  : Anything
+ Server    :
+ Path      : #md/relative/path/to/maildir/collection/
+ View      :
+ 
+ For example, if "path" is set to "#md/mail/", then Alpine will look for your 
+ maildir folders that are in ~/mail/.
+ 
+ The code in this patch is mostly based in code for the unix driver plus 
+ some combinations of the mh, mbx and nntp drivers for the c-client 
+ library. Those drivers were designed by Mark Crispin, and bugs in this 
+ code are not his bugs, but my own.
+ 
+   I got all the specification for this patch from 
+ http://cr.yp.to/proto/maildir.html. If you know of a place with a better 
+ specification for maildir format please let me know. The method this patch 
+ uses to create a unique filename for a message is one of the "old 
+ fashioned" methods. I realize that this is old fashioned, but it is 
+ portable, and portability is the main reason why I decided to use an old 
+ fashioned method (most methods are not portable. See the word 
+ "Unfortunately" in that document).
+ 
+ --------------
+ 2. Other Goals
+ --------------
+ 
+   It is intended that this code will work well with any application 
+ written using the c-client library. Of paramount importance is to make the 
+ associated imap server work well when the server accesses a folder in 
+ Maildir format. The program mailutil should also work flawlessly with this 
+ implemetation of the driver.
+ 
+   It is intended that this driver be fast and stable. We intend not to 
+ patch Alpine to make this driver do its work, unless such patching is for 
+ fixing bugs in Alpine or to pass parameters to the driver.
+ 
+ ------------------------------------------------------------------------ 
+ 3. What are the known bugs of this implementation of the Maildir driver? 
+ ------------------------------------------------------------------------
+ 
+   I don't know any at this time. There have been bugs before, though, but 
+ I try to fix bugs as soon as they are reported. 
+ 
+ ----------
+ 4. On UIDs
+ ----------
+ 
+  This patch keeps uids in the name of the file that contains the message, 
+ by adding a ",u=" string to the file name to save the uid of a message. A 
+ file is kept between sessions to save information on the last uid assigned 
+ and its time of validity. Only one session with writing access can write 
+ uids, all others must wait for the other session to assign them. The 
+ session assigning uids creates a ".uidtemp" file which other sessions must 
+ not disturb.
+ 
+   Uid support appeared in Alpine 1.00 (snapshot 925), and is experimental,
+ please report any problems.
+ 
+ ----------------------------------------------
+ 5. Configuring Alpine and Setting up a Maildir 
+ ----------------------------------------------
+ 
+ Once this approach was chosen, it implied the following:
+ 
+     * This patch assumes that your INBOX is located at "$HOME/Maildir".  
+       This is a directory which should have three subdirectories "cur", 
+       "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I 
+       have added a configuration option "maildir-location" which can be 
+       used to tell Alpine where your Maildir inbox is, in case your system 
+       does not use the above directory (e.g. your system may use 
+       "~/.maildir"). In this case define that variable to be the name of 
+       the directory where your e-mail is being delivered (e.g.  
+       ".maildir").
+ 
+     * If you want to use the above configuration as your inbox, you must 
+       define your inbox-path as "#md/inbox" (no quotes).  You can define 
+       the inbox-path like above even if you have changed the 
+       maildir-location variable. That's the whole point of that variable.
+ 
+ -------------------------------------------
+ 6. What about Courier/Dovecot file systems?
+ -------------------------------------------
+ 
+ In a courier file system all folders are subfolders of a root folder 
+ called INBOX. Normally INBOX is located at ~/Maildir and subfolders are 
+ "dot" directories in ~/Maildir. For example ~/Maildir/.Trash is a 
+ subfolder of INBOX and is accessed with the nickname "INBOX.Trash".
+ 
+ You can not access folders in this way unless you preceed them with the 
+ string "#mc/". The purpose of the string "#mc/" is to warn Alpine that a 
+ collection in the Courier format is going to be accessed. Therefore, you 
+ can SELECT a folder like "#mc/INBOX.Trash", but not "INBOX.Trash"
+ 
+ You can access a collection through a server, but if you want to access a 
+ collection of folders created using the Courier server, you MUST edit your
+ ".pinerc" file and enter the definition of the collection as follows:
+ 
+ folder-collections="Anything you want" #mc/INBOX.[]
+ 
+ You can replace the string "#mc/INBOX." by something different, for example
+ "#mc/Courier/." will make Alpine search for your collection in ~/Courier.
+ 
+ You can not add this setting directly into Alpine because Alpine fails to 
+ accept this value from its input, but it takes it correctly when it is 
+ added through the ".pinerc" file.
+ 
+ You can access your inbox as "#mc/INBOX" or "#md/INBOX". Both definitions 
+ point to the same place.
+ 
+ Last Updated May 28, 2011