From owner-freebsd-ports-bugs@FreeBSD.ORG Wed Jan 12 12:00:46 2005 Return-Path: Delivered-To: freebsd-ports-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C026D16A4D3 for ; Wed, 12 Jan 2005 12:00:46 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2D29743D48 for ; Wed, 12 Jan 2005 12:00:46 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.1/8.13.1) with ESMTP id j0CC0jJQ033020 for ; Wed, 12 Jan 2005 12:00:45 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.1/8.13.1/Submit) id j0CC0jfZ032996; Wed, 12 Jan 2005 12:00:45 GMT (envelope-from gnats) Resent-Date: Wed, 12 Jan 2005 12:00:45 GMT Resent-Message-Id: <200501121200.j0CC0jfZ032996@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-ports-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Lewis Thompson Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9609516A4CE for ; Wed, 12 Jan 2005 11:51:01 +0000 (GMT) Received: from blaster.systems.pipex.net (blaster.systems.pipex.net [62.241.163.7]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3D82A43D49 for ; Wed, 12 Jan 2005 11:51:00 +0000 (GMT) (envelope-from lewiz@black.fajita.org) Received: from infidel.fajita.org (81-178-123-209.dsl.pipex.com [81.178.123.209]) by blaster.systems.pipex.net (Postfix) with ESMTP id A1D1BE000110; Wed, 12 Jan 2005 11:50:46 +0000 (GMT) Received: from black.fajita.org ([192.168.0.20]) by infidel.fajita.org (8.13.1/8.13.1) with ESMTP id j0CBokZC028508; Wed, 12 Jan 2005 11:50:46 GMT (envelope-from lewiz@black.fajita.org) Received: from black.fajita.org (localhost [127.0.0.1]) by black.fajita.org (8.13.1/8.13.1) with ESMTP id j0CBobfB037113; Wed, 12 Jan 2005 11:50:37 GMT (envelope-from lewiz@black.fajita.org) Received: (from lewiz@localhost) by black.fajita.org (8.13.1/8.13.1/Submit) id j0CBoWHV037108; Wed, 12 Jan 2005 11:50:32 GMT (envelope-from lewiz) Message-Id: <200501121150.j0CBoWHV037108@black.fajita.org> Date: Wed, 12 Jan 2005 11:50:32 GMT From: Lewis Thompson To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 cc: Doug Barton Subject: ports/76137: UPDATE PORT mail/pine4: add WITH_MAILDIR flag X-BeenThere: freebsd-ports-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Lewis Thompson List-Id: Ports bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Jan 2005 12:00:46 -0000 >Number: 76137 >Category: ports >Synopsis: UPDATE PORT mail/pine4: add WITH_MAILDIR flag >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Jan 12 12:00:44 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Lewis Thompson >Release: FreeBSD 5.3-RELEASE-p4 i386 >Organization: >Environment: System: FreeBSD black.fajita.org 5.3-RELEASE-p4 FreeBSD 5.3-RELEASE-p4 #0: Sun Jan 9 17:55:30 GMT 2005 lewiz@black.fajita.org:/usr/src/sys/i386/compile/BLACK i386 >Description: This adds a WITH_MAILDIR option to allow compilation of pine4 with Maildir support. Maildir patch from http://www.math.washington.edu/~chappa/pine/info/maildir.html Port maintainer is CC:d. >How-To-Repeat: >Fix: diff -ruN pine4.orig/Makefile pine4/Makefile --- pine4.orig/Makefile Mon Aug 9 09:52:13 2004 +++ pine4/Makefile Wed Jan 12 11:24:06 2005 @@ -75,6 +75,11 @@ ${LN} -sf ${LDAP_PREFIX}/lib ${WRKSRC}/ldap/libraries .endif +pre-build: +.if defined(WITH_MAILDIR) + @${PATCH} ${PATCH_ARGS} -F 3 -p1 < ${PATCHDIR}/extra-patch-maildir +.endif + do-build: @(cd ${WRKSRC}; ${SETENV} ${MAKE_ENV} ./build bsf ${EXTRA_OPTS}) diff -ruN pine4.orig/files/extra-patch-maildir pine4/files/extra-patch-maildir --- pine4.orig/files/extra-patch-maildir Thu Jan 1 01:00:00 1970 +++ pine4/files/extra-patch-maildir Wed Jan 12 11:24:06 2005 @@ -0,0 +1,2462 @@ +diff -rc pine4.61/README.maildir pine4.61.maildir/README.maildir +*** pine4.61/README.maildir Sat Dec 11 15:12:09 2004 +--- pine4.61.maildir/README.maildir Thu Dec 2 08:13:02 2004 +*************** +*** 0 **** +--- 1,152 ---- ++ Maildir Driver for Pine4.61 ++ --------------------------- ++ ++ This is a maildir driver for the c-client library and Pine. This code ++ started from code in old maildir patches but it was completely rewritten, ++ so the old way to configure it does not apply anymore. ++ ++ This patch takes the approach that you should not patch Pine to make the ++ maildir driver do its work correctly, by this I mean things like appending ++ messages to a folder, or so. You could of course patch Pine if you want to ++ pass parameters to the driver, but not to fix the driver. This patch ++ modifies Pine so that it will be possible to pass a parameter to the ++ driver (e.g. the location of the INBOX). Although this patch was based in ++ an old version of a maildir patch it has been almost completely rewritten ++ and it can be considered independent work (look at the flow of functions, ++ checks, etc). The patch is based on the code for the unix driver plus some ++ combinations of the mh driver and the mbx driver for the c-client library. ++ Those drivers were designed by Mark Crispin, and bugs in this code are not ++ his bugs, but my own. ++ ++ One of my goals with this patch is that the associated imap server must ++ work well with this patch and any client!. Trying to do this I've cleaned ++ a lot of bugs in older work and restructured the flow. I am sure that ++ doing this is a never ending job, since improvements to the code can ++ always be made, and I am looking forward to doing them sometime in the ++ future. ++ ++ This patch does not keep UIDs between sessions, but hopefully it does ++ keep consistent UIDs during one session. This is not a bug of the driver, ++ instead it is a shortcoming of the maildir specification. The main point ++ of the maildir configuration is that you should never (read my lips) ever ++ edit the message, but edit the filename associated to the message. Well, I ++ could not find any single place in the web where it was told how to save ++ the UID of a message, if there is one please let me know and I will add ++ UID support for this driver. ++ ++ 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). ++ ++ I am interested in improving speed in the driver, please send me reports ++ of slowness or any other comments you can think are appropriate. ++ ++ 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 Pine where your Maildir inbox is, in case your system ++ do 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. ++ ++ * You can create a collection of folders which are in maildir format. ++ In order to do that press M S L and add the following data: ++ ++ Nickname: Anything ++ Server : ++ Path : #md/relative/path/to/home ++ View : ++ ++ Written by Eduardo Chappa ++ ++ Last Updated June 04, 2004 ++ Maildir Driver for Pine4.61 ++ --------------------------- ++ ++ This is a maildir driver for the c-client library and Pine. This code ++ started from code in old maildir patches but it was completely rewritten, ++ so the old way to configure it does not apply anymore. ++ ++ This patch takes the approach that you should not patch Pine to make the ++ maildir driver do its work correctly, by this I mean things like appending ++ messages to a folder, or so. You could of course patch Pine if you want to ++ pass parameters to the driver, but not to fix the driver. This patch ++ modifies Pine so that it will be possible to pass a parameter to the ++ driver (e.g. the location of the INBOX). Although this patch was based in ++ an old version of a maildir patch it has been almost completely rewritten ++ and it can be considered independent work (look at the flow of functions, ++ checks, etc). The patch is based on the code for the unix driver plus some ++ combinations of the mh driver and the mbx driver for the c-client library. ++ Those drivers were designed by Mark Crispin, and bugs in this code are not ++ his bugs, but my own. ++ ++ One of my goals with this patch is that the associated imap server must ++ work well with this patch and any client!. Trying to do this I've cleaned ++ a lot of bugs in older work and restructured the flow. I am sure that ++ doing this is a never ending job, since improvements to the code can ++ always be made, and I am looking forward to doing them sometime in the ++ future. ++ ++ This patch does not keep UIDs between sessions, but hopefully it does ++ keep consistent UIDs during one session. This is not a bug of the driver, ++ instead it is a shortcoming of the maildir specification. The main point ++ of the maildir configuration is that you should never (read my lips) ever ++ edit the message, but edit the filename associated to the message. Well, I ++ could not find any single place in the web where it was told how to save ++ the UID of a message, if there is one please let me know and I will add ++ UID support for this driver. ++ ++ 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). ++ ++ I am interested in improving speed in the driver, please send me reports ++ of slowness or any other comments you can think are appropriate. ++ ++ 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 Pine where your Maildir inbox is, in case your system ++ do 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. ++ ++ * You can create a collection of folders which are in maildir format. ++ In order to do that press M S L and add the following data: ++ ++ Nickname: Anything ++ Server : ++ Path : #md/relative/path/to/home ++ View : ++ ++ Written by Eduardo Chappa ++ ++ Last Updated June 04, 2004 +diff -rc pine4.61/imap/src/c-client/mail.h pine4.61.maildir/imap/src/c-client/mail.h +*** pine4.61/imap/src/c-client/mail.h Mon Jun 21 18:06:58 2004 +--- pine4.61.maildir/imap/src/c-client/mail.h Thu Dec 2 08:13:10 2004 +*************** +*** 307,312 **** +--- 307,314 ---- + #define SET_SNARFINTERVAL (long) 565 + #define GET_SNARFPRESERVE (long) 566 + #define SET_SNARFPRESERVE (long) 567 ++ #define GET_MDINBOX (long) 568 ++ #define SET_MDINBOX (long) 569 + + /* Driver flags */ + +*************** +*** 785,790 **** +--- 787,793 ---- + unsigned int spare7 : 1; /* seventh spare bit */ + unsigned int spare8 : 1; /* eighth spare bit */ + void *sparep; /* spare pointer */ ++ void *maildirp; /* for the Maildir driver, can't use sparep */ + unsigned long user_flags; /* user-assignable flags */ + } MESSAGECACHE; + +diff -rc pine4.61/imap/src/osdep/unix/Makefile pine4.61.maildir/imap/src/osdep/unix/Makefile +*** pine4.61/imap/src/osdep/unix/Makefile Tue Jun 22 13:56:05 2004 +--- pine4.61.maildir/imap/src/osdep/unix/Makefile Wed Nov 24 15:15:18 2004 +*************** +*** 107,113 **** + # Standard distribution build parameters + + DEFAULTAUTHENTICATORS=md5 pla log +! DEFAULTDRIVERS=imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile + + + # Normally no need to change any of these +--- 107,113 ---- + # Standard distribution build parameters + + DEFAULTAUTHENTICATORS=md5 pla log +! DEFAULTDRIVERS=maildir imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile + + + # Normally no need to change any of these +*************** +*** 116,122 **** + BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \ + dummy.o pseudo.o netmsg.o flstring.o fdstring.o \ + rfc822.o nntp.o smtp.o imap4r1.o pop3.o \ +! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o + CFLAGS=-g + + CAT=cat +--- 116,122 ---- + BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \ + dummy.o pseudo.o netmsg.o flstring.o fdstring.o \ + rfc822.o nntp.o smtp.o imap4r1.o pop3.o \ +! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o maildir.o + CFLAGS=-g + + CAT=cat +*************** +*** 245,251 **** + + 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 \ +--- 245,251 ---- + + 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 \ +*************** +*** 834,840 **** + tenex.o: mail.h misc.h osdep.h dummy.h + unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h + utf8.o: mail.h misc.h osdep.h utf8.h +! + + # OS-dependent + +--- 834,840 ---- + tenex.o: mail.h misc.h osdep.h dummy.h + unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h + utf8.o: mail.h misc.h osdep.h utf8.h +! maildir.o: mail.h misc.h osdep.h maildir.h dummy.h + + # OS-dependent + +diff -rc pine4.61/imap/src/osdep/unix/dummy.c pine4.61.maildir/imap/src/osdep/unix/dummy.c +*** pine4.61/imap/src/osdep/unix/dummy.c Mon Feb 2 16:50:32 2004 +--- pine4.61.maildir/imap/src/osdep/unix/dummy.c Wed Nov 24 15:15:18 2004 +*************** +*** 104,109 **** +--- 104,111 ---- + { + char *s,tmp[MAILTMPLEN]; + struct stat sbuf; ++ ++ maildir_remove_root(&name); + /* must be valid local mailbox */ + if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { + /* indeterminate clearbox INBOX */ +*************** +*** 362,368 **** + char *s,tmp[MAILTMPLEN]; + /* don't \NoSelect dir if it has a driver */ + if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) && +! (d != &dummydriver)) attributes &= ~LATT_NOSELECT; + if (!contents || /* notify main program */ + (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) && + (s = dummy_file (tmp,name)) && !stat (s,&sbuf) && +--- 364,373 ---- + char *s,tmp[MAILTMPLEN]; + /* don't \NoSelect dir if it has a driver */ + if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) && +! (d != &dummydriver)){ +! attributes &= ~LATT_NOSELECT; +! attributes |= LATT_NOINFERIORS; +! } + if (!contents || /* notify main program */ + (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) && + (s = dummy_file (tmp,name)) && !stat (s,&sbuf) && +*************** +*** 382,387 **** +--- 387,394 ---- + { + char *s,tmp[MAILTMPLEN]; + long ret = NIL; ++ if(!strncmp(mailbox,"#md/",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); +*************** +*** 447,452 **** +--- 454,461 ---- + { + struct stat sbuf; + char *s,tmp[MAILTMPLEN]; ++ if (!strncmp(mailbox,"#md/",4)) ++ return maildir_delete(stream, mailbox); + if (!(s = dummy_file (tmp,mailbox))) { + sprintf (tmp,"Can't delete - invalid name: %.80s",s); + MM_LOG (tmp,ERROR); +*************** +*** 473,478 **** +--- 482,490 ---- + { + struct stat sbuf; + char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; ++ ++ maildir_remove_root(&old); ++ maildir_remove_root(&newname); + /* no trailing / allowed */ + if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || + ((s = strrchr (s,'/')) && !s[1])) { +diff -rc pine4.61/imap/src/osdep/unix/env_unix.c pine4.61.maildir/imap/src/osdep/unix/env_unix.c +*** pine4.61/imap/src/osdep/unix/env_unix.c Thu Jul 8 15:02:04 2004 +--- pine4.61.maildir/imap/src/osdep/unix/env_unix.c Wed Nov 24 15:15:18 2004 +*************** +*** 33,38 **** +--- 33,39 ---- + static char *sysInbox = NIL; /* system inbox name */ + static char *newsActive = NIL; /* news active file */ + static char *newsSpool = NIL; /* news spool */ ++ static char *myMdInboxDir = NIL;/* Location of the Maildir INBOX */ + /* anonymous home directory */ + static char *anonymousHome = NIL; + static char *ftpHome = NIL; /* ftp export home directory */ +*************** +*** 177,182 **** +--- 178,189 ---- + case GET_NEWSRC: + ret = (void *) myNewsrc; + break; ++ case SET_MDINBOX: ++ if (myMdInboxDir) fs_give ((void **) &myMdInboxDir); ++ myMdInboxDir = cpystr ((char *) value); ++ case GET_MDINBOX: ++ ret = (void *) myMdInboxDir; ++ break; + case SET_NEWSACTIVE: + if (newsActive) fs_give ((void **) &newsActive); + newsActive = cpystr ((char *) value); +*************** +*** 733,738 **** +--- 740,746 ---- + } + if (!myLocalHost) mylocalhost (); + if (!myNewsrc) myNewsrc = cpystr(strcat (strcpy (tmp,myHomeDir),"/.newsrc")); ++ if (!myMdInboxDir) myMdInboxDir = cpystr("Maildir"); + if (!newsActive) newsActive = cpystr (ACTIVEFILE); + if (!newsSpool) newsSpool = cpystr (NEWSSPOOL); + /* force default prototype to be set */ +diff -rc pine4.61/imap/src/osdep/unix/maildir.c pine4.61.maildir/imap/src/osdep/unix/maildir.c +*** pine4.61/imap/src/osdep/unix/maildir.c Sat Dec 11 15:12:09 2004 +--- pine4.61.maildir/imap/src/osdep/unix/maildir.c Mon Dec 6 08:44:51 2004 +*************** +*** 0 **** +--- 1,1659 ---- ++ /* ++ * Maildir driver for Pine4.61 ++ * ++ * Written by Eduardo Chappa ++ * Last Update: December 06, 2004. ++ * ++ * The IMAP toolkit provided in this Distribution is ++ * Copyright 2004 University of Washington. ++ * The full text of our legal notices is contained in the file called ++ * CPYRIGHT, included with this Distribution. ++ */ ++ ++ #include ++ #include ++ #include ++ extern int errno; /* just in case */ ++ #include "mail.h" ++ #include "osdep.h" ++ #include ++ #include ++ #include ++ #include "maildir.h" ++ #include "fdstring.h" ++ #include "misc.h" ++ #include "dummy.h" ++ ++ /* Driver dispatch used by MAIL */ ++ ++ DRIVER maildirdriver = { ++ "md", /* driver name, yes it's md, not maildir */ ++ /* driver flags */ ++ DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE|DR_NOSTICKY, ++ (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 */ ++ NIL, /* 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 */ ++ ++ void ++ md_domain_name(void) ++ { ++ int i; ++ ++ strcpy(mdlocaldomain,mylocalhost ()); ++ for (i = 0; mdlocaldomain[i] ; i++) ++ if(mdlocaldomain[i] == '/') ++ mdlocaldomain[i] = '\057'; ++ else if (mdlocaldomain[i] == ':') ++ mdlocaldomain[i] = '\072'; ++ } ++ ++ /* remove the "#md/" part from a folder name */ ++ void maildir_remove_root (char **name) ++ { ++ if (maildir_valid_name(*name)){ ++ (*name) += 3; ++ if (**name == '/') ++ (*name)++; ++ } ++ } ++ ++ ++ /* 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) ++ { ++ int ret = NIL; ++ char tmpname[MAILTMPLEN+1] = {'\0'}; ++ ++ if (mdfpath) ++ fs_give((void **)&mdfpath); ++ if (name && name[0] != '#') ++ sprintf(tmpname,"#md/%s",name); ++ mdfpath = cpystr(tmpname[0] ? tmpname : name); ++ ++ if (name && (name[0] == '#') ++ && ((name[1] == 'm') || (name[1] == 'M')) ++ && ((name[2] == 'd') || (name[2] == 'D')) ++ && ((name[3] == '/') && name[4])) ret = T; ++ ++ return ret; ++ } ++ ++ /* 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+1]; ++ ++ 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; ++ } ++ ++ /* 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) ++ { ++ char *maildirpath = mail_parameters(NIL,GET_MDINBOX,NIL); ++ ++ maildir_remove_root(&name); ++ tmp[0] = '\0'; /* just in case something fails */ ++ if (strlen(myhomedir()) + ++ max(strlen(name), strlen(maildirpath ++ ? maildirpath : "Maildir")) > MAILTMPLEN){ ++ errno = ENAMETOOLONG; ++ sprintf(tmp,"Error opening \"%s\": %s", name, strerror (errno)); ++ mm_log(tmp,ERROR); ++ } ++ else ++ sprintf (tmp,"%s/%s%s",myhomedir (), ++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5) ++ ? name : (maildirpath ? maildirpath : "Maildir") , ++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5) ++ ? "" : *(name+5) == '/' ? name+5 : ""); ++ ++ return tmp[0] ? 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+1]; ++ struct stat sbuf; ++ int rv, mdv, mdvd; ++ ++ maildir_file_path(name, tmpname); ++ mdv = maildir_valid_name(name); ++ mdvd = maildir_valid_dir(tmpname); ++ rv = stat(tmpname, &sbuf); ++ ++ return (mdv == 1 && rv == 0 && S_ISDIR(sbuf.st_mode) && mdvd == 1) ++ || (mdv == 1 && rv < 0 && errno == ENOENT) ++ || (mdv == 0 && mdvd == 1) ? &maildirdriver : NIL; ++ } ++ ++ int maildir_base_name(char *name, char *tmp) ++ { ++ int i; ++ ++ if (tmp) ++ *tmp = '\0'; ++ ++ if (!name || name[0] == '.') ++ return NIL; ++ ++ for (i = 0; name[i] && name[i] != FLAGSEP && (tmp[i] = name[i]); i++); ++ tmp[i] = '\0'; /* tie me off, thank you */ ++ ++ return T; ++ } ++ ++ /* ++ * return all files in a given directory. This is a separate call ++ * so that if there are warnings during compilation this only appears once ++ * It is also important to touch the uidvalidity file to tell us when we did ++ * this last. ++ */ ++ unsigned long ++ maildir_scandir (char *name, struct direct ***flist, ++ unsigned long *nfiles, int *scand) ++ { ++ struct stat sbuf; ++ ++ if (scand) ++ *scand = -1; /* assume error for safety */ ++ stat(name,&sbuf); /* stat the containing directory */ ++ if (scand) ++ *scand = scandir(name, flist, maildir_select, maildir_namesort); ++ *nfiles = (scand && (*scand > 0)) ? (unsigned long) *scand : 0L; ++ ++ return 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+1]; ++ int gotit = NIL; ++ DIR *dir; ++ struct direct *d; ++ struct stat sbuf; ++ ++ /* First check directly if it exists, if not there, look for it */ ++ sprintf(tmp,"%s/%s", LOCAL->curdir, name); ++ if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG)) ++ return T; ++ ++ if (!(dir = opendir (LOCAL->curdir))) ++ 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+1], tmp2[MAILTMPLEN+1]; ++ 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 */ ++ stream->uid_last = stream->uid_validity = 0; ++ if (!stream->rdonly){ ++ stream->perm_seen = stream->perm_deleted = stream->perm_flagged = ++ stream->perm_answered = stream->perm_draft = T; ++ } ++ stream->uid_validity = time(0); ++ stream->local = (MAILDIRLOCAL *)fs_get (sizeof (MAILDIRLOCAL)); ++ memset(LOCAL, 0, sizeof(MAILDIRLOCAL)); ++ LOCAL->fd = -1; ++ ++ strcpy(tmp2, stream->mailbox); /* tmp2 = what the user entered */ ++ if (maildir_file_path("#md/INBOX", tmp)) /* tmp = real path to #md/inbox */ ++ LOCAL->inbox = !strcmp(ucase(tmp2),"#MD/INBOX") || !strcmp(tmp2,tmp); ++ ++ strcpy(tmp, stream->mailbox); ++ if (maildir_file_path (stream->mailbox, tmp)) ++ LOCAL->dir = cpystr (tmp); ++ if (LOCAL->dir){ ++ MDFLD(tmp, LOCAL->dir, Cur); ++ LOCAL->curdir = cpystr (tmp); ++ if (stat (LOCAL->curdir,&sbuf) < 0) { ++ sprintf (tmp,"Can't open folder %s: %s", ++ stream->mailbox,strerror (errno)); ++ mm_log (tmp,ERROR); ++ maildir_close(stream, 0); ++ return NIL; ++ } ++ } ++ sprintf(tmp,"%s/%s", *stream->mailbox == '/' ? "" : myhomedir(), ++ stream->mailbox); ++ fs_give ((void **) &stream->mailbox); ++ stream->mailbox = cpystr(tmp); ++ ++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = MAXMESSAGESIZE) + 1); ++ stream->sequence++; ++ stream->nmsgs = stream->recent = 0; ++ ++ maildir_parse_folder(stream, 1); ++ ++ return stream; ++ } ++ ++ /* Maildir initial parsing of the folder */ ++ void ++ maildir_parse_folder (MAILSTREAM *stream, int full) ++ { ++ unsigned long total; ++ ++ if (!stream) /* what??? */ ++ return; ++ ++ MM_CRITICAL(stream); ++ ++ /* Scan old messages first, escoba! */ ++ total = LOCAL ? maildir_parse_dir(stream, 0L, Cur, full) ++ : stream->nmsgs; ++ stream->nmsgs = LOCAL ? maildir_parse_dir(stream, total, New, full) ++ : stream->nmsgs; ++ ++ MM_NOCRITICAL(stream); ++ } ++ ++ /* 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, int full) ++ { ++ char tmp[MAILTMPLEN+1], tmp2[MAILTMPLEN+1], file[MAILTMPLEN+1], ++ newfile[MAILTMPLEN+1], *mdstr; ++ struct direct **names = NIL; ++ struct stat sbuf; ++ unsigned long i, j = 0L, nfiles, last_scan; ++ unsigned long recent = stream ? stream->recent : 0L; ++ int d = 0, f = 0, r = 0, s = 0, t = 0; ++ int k, we_compute, in_list, scan_err; ++ int silent = stream ? stream->silent : NIL; ++ MESSAGECACHE *elt; ++ ++ MDFLD(tmp, LOCAL->dir, dirtype); ++ if (access (tmp, R_OK|W_OK|X_OK) != 0){ ++ maildir_abort(stream); ++ return stream->nmsgs; ++ } ++ ++ MDFLD(tmp, LOCAL->dir, Cur); ++ if (dirtype != New && ++ (stat(tmp, &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime)) ++ return stream->nmsgs; ++ ++ MDFLD(tmp, LOCAL->dir, dirtype); ++ last_scan = maildir_scandir (tmp, &names, &nfiles, &scan_err); ++ if (dirtype == Cur) ++ LOCAL->scantime = last_scan; ++ ++ if (scan_err < 0){ ++ maildir_abort(stream); ++ return nmsgs; ++ } ++ ++ if (dirtype == Cur) ++ for (i = 1L; i <= stream->nmsgs;){ ++ elt = mail_elt(stream, i); ++ in_list = elt && elt->maildirp && 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->maildirp) ++ maildir_free_file ((void **) &elt->maildirp); ++ ++ if (elt->recent) --recent; ++ mail_expunged(stream,i); ++ } ++ else i++; ++ } ++ ++ stream->silent = T; ++ for (we_compute = 0, i = 1L; i <= nfiles; i++){ ++ unsigned long pos, n; ++ mail_exists(stream, i + nmsgs); ++ elt = mail_elt(stream, i + nmsgs); ++ if (elt && elt->maildirp) ++ pos = MDPOS(elt); /* use data we found above */ ++ else{ ++ if (full) ++ pos = i - 1; /* first time, use sequence number */ ++ else{ ++ for (n = 0L ; (n < nfiles) && !names[n] ; n++); ++ pos = n; /* nfiles > stream->nmsgs!!, assign one */ ++ } ++ } ++ if (dirtype == New) elt->recent = T; ++ if (!elt->private.uid){ ++ elt->private.uid = stream->uid_last + 1; ++ stream->uid_validity = time(0); ++ } ++ if (stream->uid_last < elt->private.uid) ++ stream->uid_last = elt->private.uid; ++ if (elt->maildirp || stream->rdonly){ ++ we_compute++; /* get old flags */ ++ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t); ++ maildir_free_file_only ((void **)&elt->maildirp); ++ } ++ if (!elt->maildirp) ++ maildir_get_file(&elt->maildirp); ++ MDFILE(elt) = cpystr(names[pos]->d_name); ++ MDPOS(elt) = pos; ++ if (full && !stream->rdonly) ++ maildir_parse_message(stream, i+nmsgs, dirtype); ++ ++ if (we_compute && (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 (!stream->rdonly) ++ MM_FLAGS(stream, i+nmsgs); ++ } ++ if (dirtype == New && !stream->rdonly){ /* move new messages to cur */ ++ sprintf (file,"%s/%s", tmp, names[pos]->d_name); ++ if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)){ ++ strcpy(tmp2,names[pos]->d_name); ++ if ((mdstr = strstr (names[pos]->d_name,MDSEP(3))) ++ || (mdstr = strstr (names[pos]->d_name,MDSEP(2)))){ /* Grrr */ ++ *(mdstr+1) = '2'; ++ sprintf (newfile,"%s/%s",LOCAL->curdir,names[pos]->d_name); ++ } ++ else{ ++ sprintf (newfile,"%s/%s%s",LOCAL->curdir,names[pos]->d_name,MDSEP(2)); ++ strcat(tmp2, MDSEP(2)); ++ } ++ if (link (file,newfile) < 0){ ++ mm_log("Unable to read new mail!",WARN); ++ } ++ else{ ++ unlink (file); ++ j++; /* success!, count it! */ ++ } ++ maildir_free_file_only((void **)&elt->maildirp); ++ MDFILE(elt) = cpystr(tmp2); ++ MDSIZE(elt) = sbuf.st_size; ++ MDMTIME(elt) = sbuf.st_mtime; ++ maildir_get_date(stream, i + nmsgs, New); ++ } ++ } ++ fs_give((void **)&names[pos]); ++ } ++ if(names) ++ fs_give((void **) &names); ++ stream->silent = silent; ++ if (dirtype == New && stream->rdonly) ++ j = nfiles; ++ mail_exists(stream, nmsgs + (dirtype == New ? j : nfiles)); ++ mail_recent(stream, recent + (dirtype == New ? j : 0)); ++ ++ return (nmsgs + (dirtype == New ? j : nfiles)); ++ } ++ ++ long maildir_ping (MAILSTREAM *stream) ++ { ++ maildir_parse_folder(stream, 0); ++ return stream && LOCAL ? T : NIL; ++ } ++ ++ int maildir_select (struct direct *name) ++ { ++ int rv = NIL, val; ++ val = name->d_name[0] - '0'; ++ switch(val){ ++ case 1: case 2: case 3: case 4: case 5: ++ case 6: case 7: case 8: case 9: ++ rv = T; ++ default: break; ++ } ++ return rv; ++ } ++ ++ /* ++ * 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 void *d1,const void *d2) ++ { ++ const struct direct **e1, **e2; ++ ++ e1 = (const struct direct **)d1; ++ 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 = 1; i <= stream->nmsgs; i++) ++ if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp) ++ maildir_free_file ((void **) &(elt->maildirp)); ++ stream->silent = T; ++ if (options & CL_EXPUNGE) maildir_expunge (stream); ++ maildir_abort(stream); ++ 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+1]; ++ unsigned long i; ++ MESSAGECACHE *elt; ++ char *s; ++ /* UID call "impossible" */ ++ if (flags & FT_UID || !LOCAL) return NIL; ++ elt = mail_elt (stream,msgno); ++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(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; ++ } ++ ++ if (!(flags & FT_PEEK) && !elt->seen) { /* mark as seen */ ++ elt->seen = T; ++ maildir_flagmsg (stream,elt); /* Change flags physically */ ++ if (LOCAL->dirty == 0) ++ MM_FLAGS(stream, elt->msgno); ++ } ++ s = maildir_text_work(stream, elt, &i, flags); ++ INIT (bs, mail_string, s, i); ++ return T; ++ } ++ ++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, ++ unsigned long *length,long flags) ++ { ++ FDDATA d; ++ STRING bs; ++ char *s,*t,*tl,tmp[CHUNK]; ++ unsigned long msgno = elt->msgno; ++ static int try = 0; ++ ++ if (length) ++ *length = 0L; ++ LOCAL->buf[0] = '\0'; ++ ++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt)); ++ if (LOCAL->fd < 0) /* if file closed ? */ ++ LOCAL->fd = open(tmp,O_RDONLY,NIL); ++ ++ if (LOCAL->fd < 0){ /* flag change? */ ++ if (try < 5){ ++ try++; ++ if (maildir_update_elt_maildirp(stream, msgno) > 0) ++ try = 0; ++ return maildir_text_work(stream, mail_elt(stream, msgno),length, flags); ++ } ++ try = 0; ++ return NULL; ++ } ++ ++ lseek (LOCAL->fd,elt->private.special.offset + ++ 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.special.offset + 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, c; ++ char tmp[MAILTMPLEN+1]; ++ unsigned long i, len; ++ int offset = 0, d, f, r, se, dt; ++ MESSAGECACHE *elt; ++ ++ elt = mail_elt (stream,msgno); ++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype); ++ if (LOCAL->fd < 0) /* if file closed ? */ ++ LOCAL->fd = open(tmp,O_RDONLY,NIL); ++ ++ if (LOCAL->fd >= 0){ ++ if (elt->day == 0) ++ maildir_get_date(stream, msgno, dirtype); ++ if (LOCAL->fd >= 0){ ++ s = (char *) fs_get (MDSIZE(elt) + 1); ++ read (LOCAL->fd,s,MDSIZE(elt)); ++ s[MDSIZE(elt)] = '\0'; ++ for (i = 0, b = s; *b && !(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 = 0, b = s, c = *b; b && c && ++ ((c < '\016') && (((c == '\012') && ++i) || ++ ((c == '\015') && (*++b == '\012') && (i +=2))) ++ || c); i++, c= *++b); ++ elt->rfc822_size = i; ++ fs_give ((void **) &s); ++ close(LOCAL->fd); LOCAL->fd = -1; ++ } ++ } ++ 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; ++ return elt->rfc822_size; ++ } ++ ++ int ++ maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno) ++ { ++ char tmp[MAILTMPLEN+1]; ++ 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; ++ ++ MDFLD(tmp, LOCAL->dir, Cur); ++ ++ maildir_scandir (tmp, &names, &nfiles, &scan_err); ++ ++ elt = mail_elt (stream,msgno); ++ ++ in_list = nfiles > 0L ++ ? maildir_message_in_list(MDFILE(elt), names, 0L, ++ nfiles - 1L, &pos) ++ : NIL; ++ ++ if (in_list && pos >= 0L && pos < nfiles ++ && !strcmp(MDFILE(elt), names[pos]->d_name)){ ++ in_list = NIL; ++ maildir_abort(stream); ++ } ++ ++ if (in_list && pos >= 0L && pos < nfiles){ ++ maildir_free_file_only((void **)&elt->maildirp); ++ MDFILE(elt) = cpystr(names[pos]->d_name); ++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t); ++ if (elt->draft != d || elt->flagged != f || ++ elt->answered != r || elt->seen != s || elt->deleted != t){ ++ elt->draft = d; elt->flagged = f; elt->answered = r; ++ elt->seen = s; elt->deleted = t; ++ MM_FLAGS(stream, msgno); ++ } ++ } ++ for (i = 0L; i < nfiles; i++) ++ fs_give((void **) &names[i]); ++ if (names) ++ fs_give((void **) &names); ++ return in_list ? 1 : -1; ++ } ++ ++ /* Maildir fetch message header */ ++ ++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno, ++ unsigned long *length, long flags) ++ { ++ char tmp[MAILTMPLEN+1], *s; ++ MESSAGECACHE *elt; ++ static int try = 0; ++ unsigned long hdrlen; ++ ++ 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, Cur); ++ ++ ++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt)); ++ if (LOCAL->fd < 0) ++ LOCAL->fd = open (tmp,O_RDONLY,NIL); ++ ++ if (LOCAL->fd < 0 && errno == EACCES){ ++ mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR); ++ return NULL; ++ } ++ ++ if (LOCAL->fd < 0){ /* flag change? */ ++ if (try < 5){ ++ try++; ++ if (maildir_update_elt_maildirp(stream, msgno) > 0) ++ try = 0; ++ return maildir_header(stream, msgno, length, flags); ++ } ++ try = 0; ++ return NULL; ++ } ++ ++ if ((flags & FT_INTERNAL) && ++ (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); ++ } ++ else ++ s = (char *) fs_get(elt->private.msg.header.text.size+1); ++ if (LOCAL->fd >= 0){ ++ read (LOCAL->fd, flags & FT_INTERNAL ? (void *)LOCAL->buf : (void *)s, ++ elt->private.msg.header.text.size); ++ if (flags & FT_INTERNAL) ++ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0'; ++ else{ ++ s[*length = 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; ++ if(s) ++ fs_give((void **)&s); ++ close(LOCAL->fd); LOCAL->fd = -1; ++ return LOCAL->buf; ++ ++ ++ ++ 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+1],file[MAILTMPLEN+1]; ++ long i = 0; ++ ++ if (!pat || !*pat) { ++ if (maildir_canonicalize (test,ref,"*")) { ++ if (maildir_valid_name(test)){ /* there is a #md/ leading here */ ++ for (i = 3; test[i] && test[i] != '/'; i++); ++ if (s = strchr (test+i+1,'/')) *++s = '\0'; ++ else test[0] = '\0'; ++ mm_list (stream,'/',test, LATT_NOSELECT); ++ } ++ } ++ } ++ /* get canonical form of name */ ++ else if (maildir_canonicalize (test,ref,pat)) { ++ if (test[3] == '/') { /* looking down levels? */ ++ /* yes, found any wildcards? */ ++ if (s = strpbrk (test,"%*")) { ++ /* 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,'/')) { ++ *s = '\0'; /* found, tie off at that point */ ++ s = file; ++ } ++ /* do the work */ ++ maildir_list_work (stream,s,test,0); ++ } ++ /* always an INBOX */ ++ if (!compare_cstring (test,"#MD/INBOX")) ++ mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS); ++ } ++ } ++ ++ /* For those that want to hide things, we give them a chance to do so */ ++ void *maildir_parameters (long function,void *value) ++ { ++ switch ((int) function) { ++ case GET_MDINBOX: ++ value = env_parameters (function,NIL); ++ break; ++ default: ++ value = NIL; ++ break; ++ } ++ return value; ++ } ++ ++ long maildir_create_work(char *mailbox) ++ { ++ char *s, c, err[MAILTMPLEN+1], tmp[MAILTMPLEN+1]; ++ int fnlen, i, create_dir = 0; ++ struct stat sbuf; ++ ++ if (mailbox[strlen(mailbox) - 1] == '/'){ ++ create_dir++; ++ mailbox[strlen(mailbox) - 1] = '\0'; ++ } ++ ++ fnlen = strlen(mailbox); ++ ++ if (s = strrchr(mailbox,'/')){ ++ c = *++s; ++ *s = '\0'; ++ ++ if ((stat(mailbox,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && ++ !maildir_create_work (mailbox)) ++ return NIL; ++ *s = c; ++ } ++ mailbox[fnlen] = '\0'; ++ ++ if (mkdir (mailbox,0700) && errno != EEXIST) ++ return NIL; ++ ++ if (create_dir) ++ mailbox[fnlen] = '/'; ++ ++ if (!create_dir){ ++ for (i = Cur; i != EndDir; i++){ ++ MDFLD(tmp, mailbox, i); ++ ++ if (mkdir(tmp, 0700)){ /* try to make new dir */ ++ sprintf (err, "Can't create %s: %s", tmp, strerror(errno)); ++ mm_log (err,ERROR); ++ return NIL; ++ } ++ } ++ } ++ else{ ++ FILE *fp = NULL; ++ sprintf(tmp,"%s%s", mailbox, MDDIR); ++ if ((fp = fopen(tmp,"w")) == NULL){ ++ sprintf (err,"Problem creating %s: %s", tmp, strerror(errno)); ++ mm_log (err,ERROR); ++ return NIL; ++ } ++ fclose(fp); ++ } ++ return T; /* return success */ ++ } ++ ++ long maildir_create (MAILSTREAM *stream,char *mailbox) ++ { ++ char tmp[MAILTMPLEN+1], err[MAILTMPLEN+1]; ++ long rv; ++ int create_dir; ++ ++ create_dir = mailbox ? (mailbox[strlen(mailbox) - 1] == '/') : 0; ++ maildir_file_path(mailbox, tmp); ++ rv = maildir_create_work(tmp); ++ if (rv == 0L){ ++ sprintf (err,"Can't create %s %s: %s %s", ++ create_dir ? "directory" : "mailbox", ++ mailbox, tmp, strerror (errno)); ++ mm_log (err,ERROR); ++ } ++ return rv; ++ } ++ ++ #define MAXTRY 10000 ++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt) ++ { ++ char oldfile[MAILTMPLEN+1],newfile[MAILTMPLEN+1],fn[MAILTMPLEN+1]; ++ char tmp[MAILTMPLEN+1]; ++ char *s; ++ int ren, try = 0; ++ ++ LOCAL->dirty = 0; ++ if (elt->valid){ ++ for (try = 1; try > 0 && try < MAXTRY; try++){ ++ /* build the new filename */ ++ sprintf (oldfile,"%s/%s",LOCAL->curdir, MDFILE(elt)); ++ fn[0] = '\0'; ++ if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){ ++ errno = ENOENT; ++ try = MAXTRY; ++ } ++ if (*fn) /* new oldfile! */ ++ sprintf (oldfile,"%s/%s",LOCAL->curdir,fn); ++ if ((s = strchr (MDFILE(elt), FLAGSEP))) *s = '\0'; ++ sprintf (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)); ++ sprintf (newfile,"%s/%s",LOCAL->curdir,fn); ++ if (ren != 0 && rename (oldfile,newfile) >= 0){ ++ char tmp[MAILTMPLEN+1]; ++ try = -1; ++ } ++ } ++ ++ if (try > 0){ ++ sprintf(oldfile,"Unable to write flags to disk: %s",strerror (errno)); ++ mm_log(oldfile,ERROR); ++ LOCAL->dirty = 1; ++ return; ++ } ++ maildir_free_file_only ((void **) &elt->maildirp); ++ MDFILE(elt) = cpystr (fn); ++ } ++ } ++ ++ void maildir_expunge (MAILSTREAM *stream) ++ { ++ MESSAGECACHE *elt; ++ unsigned long i; ++ unsigned long n = 0; ++ unsigned long nmsgs = stream->nmsgs; ++ unsigned long recent = stream->recent; ++ char tmp[MAILTMPLEN+1]; ++ ++ mm_critical (stream); /* go critical */ ++ for (i = 1; i <= stream->nmsgs;) ++ if ((elt = mail_elt (stream,i))->deleted){ ++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt)); ++ if (unlink (tmp)) {/* try to delete the message */ ++ sprintf (tmp,"Expunge of message %ld failed, aborted: %s",i, ++ strerror (errno)); ++ if (!stream->silent) ++ mm_log (tmp,WARN); ++ break; ++ } ++ /* free the cached filename */ ++ if (elt->maildirp) ++ maildir_free_file ((void **) &elt->maildirp); ++ ++ 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 */ ++ sprintf (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); ++ } ++ ++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) ++ { ++ STRING st; ++ MESSAGECACHE *elt; ++ unsigned long len; ++ int fd; ++ long i, length; ++ char tmp[MAILTMPLEN+1], flags[MAILTMPLEN+1], path[MAILTMPLEN+1], *s, *b; ++ /* copy the messages */ ++ if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : ++ mail_sequence (stream,sequence)) ++ for (i = 1; i <= stream->nmsgs; i++) ++ if ((elt = mail_elt (stream,i))->sequence){ ++ sprintf (path,"%s/%s",LOCAL->curdir, MDFILE(elt)); ++ if ((fd = open (path,O_RDONLY,NIL)) < 0) return NIL; ++ 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); ++ 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 T; /* return success */ ++ } ++ ++ long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) ++ { ++ int fd; ++ STRING *message; ++ char c,*s, *flags, *date; ++ char tmp[MAILTMPLEN+1],file[MAILTMPLEN+1],path1[MAILTMPLEN+1],path2[MAILTMPLEN+1]; ++ MESSAGECACHE elt; ++ long i; ++ long size = 0; ++ long ret = LONGT; ++ unsigned long uf; ++ long f; ++ static unsigned int transact = 0; ++ ++ if (!maildir_valid(mailbox)) { ++ sprintf (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 (!(*af) (stream,data,&flags,&date,&message)) return NIL; ++ ++ mm_critical (stream); /* go critical */ ++ do { ++ if (!SIZE (message)) { /* guard against zero-length */ ++ mm_log ("Append of zero-length message",ERROR); ++ ret = NIL; ++ break; ++ } ++ if (date) { /* want to preserve date? */ ++ /* yes, parse date into an elt */ ++ if (!mail_parse_date (&elt,date)) { ++ sprintf (tmp,"Bad date in append: %.80s",date); ++ mm_log (tmp,ERROR); ++ ret = NIL; ++ break; ++ } ++ } ++ f = mail_parse_flags (stream,flags,&uf); ++ /* build file name we will use */ ++ sprintf (file,"%u.%d_%09u.%s%s%s%s%s%s", ++ time (0),getpid (),transact++,mdlocaldomain, f ? MDSEP(2) : "", ++ MDFLAG(Draft, f&fDRAFT), MDFLAG(Flagged, f&fFLAGGED), ++ MDFLAG(Replied, f&fANSWERED), MDFLAG(Seen, f&fSEEN)); ++ /* build tmp file name */ ++ if (maildir_file_path(mailbox, tmp)) ++ MSGPATH(path1, tmp, file, Tmp); ++ ++ if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) { ++ sprintf (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 */ ++ sprintf (tmp,"Message append failed: %s",strerror (errno)); ++ mm_log (tmp,ERROR); ++ ret = NIL; ++ } ++ fs_give ((void **) &s); /* flush the buffer */ ++ close (fd); /* close the file */ ++ /* build final filename to use */ ++ if (maildir_file_path(mailbox, tmp)) ++ MSGPATH(path2, tmp, file, New); ++ if (link (path1,path2) < 0) { ++ sprintf (tmp,"Message append failed: %s",strerror (errno)); ++ mm_log (tmp,ERROR); ++ ret = NIL; ++ } ++ unlink (path1); ++ ++ if (ret) ++ if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL; ++ ++ } while (ret && message); /* write the data */ ++ ++ mm_nocritical (stream); /* release critical */ ++ return ret; ++ } ++ ++ long maildir_delete (MAILSTREAM *stream,char *mailbox) ++ { ++ DIR *dirp; ++ struct direct *d; ++ int i, remove_dir = 0, mddir = 0, rv; ++ char tmp[MAILTMPLEN+1],tmp2[MAILTMPLEN+1]; ++ struct stat sbuf; ++ char *mdpath = mail_parameters(NIL,GET_MDINBOX,NIL); ++ ++ if (mailbox[strlen(mailbox) - 1] == '/'){ ++ remove_dir++; ++ mailbox[strlen(mailbox) -1] = '\0'; ++ } ++ ++ if (!maildir_valid(mailbox)){ ++ sprintf(tmp,"%s/%s/", myhomedir(), *(mdfpath+4) ? mdfpath+4 ++ : (mdpath ? mdpath : "Maildir")); ++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)) ++ return NIL; ++ } ++ ++ maildir_close(stream,0); /* even if stream was NULL */ ++ ++ if (remove_dir && !maildir_dir_is_empty(mailbox)){ ++ sprintf(tmp,"Can not remove directory %s/: directory not empty", mailbox); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ maildir_file_path(mailbox, tmp2); ++ ++ if (remove_dir){ ++ sprintf(tmp,"%s/%s", tmp2, MDDIR); ++ if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode)) ++ rv = unlink(tmp); ++ else if (errno == ENOENT) ++ rv = 0; ++ if (rv != 0){ ++ sprintf(tmp,"Can not remove %s/%s: %s", tmp2, MDDIR, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ if (!maildir_valid(mailbox) && rmdir(tmp2) != 0){ ++ sprintf(tmp,"Can not remove %s/: %s", tmp2, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ return T; ++ } ++ /* else remove just the folder. Remove all hidden files, except MDDIR */ ++ for (i = Cur; i != EndDir; i++){ ++ maildir_file_path(mailbox, tmp); ++ MDFLD(tmp2, tmp, i); ++ ++ if (!(dirp = opendir (tmp2))){ ++ sprintf(tmp,"Can not read %s/: %s", tmp2, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ ++ while (d = readdir(dirp)){ ++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){ ++ sprintf(tmp,"%s/%s", tmp2, d->d_name); ++ if (unlink(tmp) != 0){ ++ sprintf(tmp,"Can not remove %s: %s", tmp2, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ } ++ } ++ closedir(dirp); ++ if (rmdir(tmp2) != 0){ ++ sprintf(tmp,"Can not remove %s: %s", tmp2, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ } ++ /* ++ * ok we have removed all subdirectories of the folder mailbox, Remove the ++ * hidden files. ++ */ ++ ++ maildir_file_path(mailbox, tmp2); ++ if (!(dirp = opendir (tmp2))){ ++ sprintf(tmp,"Can not read %s/: %s", tmp2, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ ++ while (d = readdir(dirp)){ ++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..") ++ && strcmp(d->d_name, MDDIR)){ ++ sprintf(tmp,"%s/%s", tmp2, d->d_name); ++ if (unlink(tmp) != 0){ ++ sprintf(tmp,"Can not remove %s: %s", tmp2, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ } ++ else if (!strcmp(d->d_name, MDDIR)) mddir++; ++ } ++ closedir(dirp); ++ if (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(tmp2) < 0){ ++ sprintf(tmp,"Can not remove folder %s: %s", mailbox, strerror(errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ return T; ++ } ++ ++ long maildir_rename (MAILSTREAM *stream,char *old,char *new) ++ { ++ char tmp[MAILTMPLEN+1],tmpnew[MAILTMPLEN+1]; ++ char *maildirpath = mail_parameters(NIL, GET_MDINBOX, NIL); ++ ++ if (!maildir_valid(old)){ ++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",old); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ sprintf(tmp,"%s/%s/", myhomedir(), *(mdfpath+4) ? mdfpath+4 : ++ maildirpath ? maildirpath : "Maildir"); ++ ++ if (!maildir_valid_name(new) && new[0] == '#'){ ++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",new); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ sprintf(tmpnew,"%s/%s/", myhomedir(), *(mdfpath+4) ? mdfpath+4 : ++ maildirpath ? maildirpath : "Maildir"); ++ ++ /* new mailbox name must not exist */ ++ if (access(tmpnew,F_OK) == 0) { ++ sprintf (tmp,"Can't rename to mailbox %s: destination already exists",new); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ /* try to rename the directory */ ++ if (rename (tmp,tmpnew)) { ++ sprintf (tmp,"Can't rename mailbox %s to %s: %s",old,new,strerror (errno)); ++ mm_log (tmp,ERROR); ++ return NIL; ++ } ++ return T; /* return success */ ++ } ++ ++ 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+1]; ++ /* get canonical form of name */ ++ if (maildir_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) { ++ do if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL); ++ while (s = sm_read (&sdb)); /* 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)); ++ } ++ ++ void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level) ++ { ++ DIR *dp; ++ struct direct *d; ++ struct stat sbuf; ++ char *cp,*np, curdir[MAILTMPLEN+1],name[MAILTMPLEN+1], tmp[MAILTMPLEN+1]; ++ int i; ++ char *maildirpath = mail_parameters(NIL, GET_MDINBOX, NIL); ++ ++ sprintf(curdir,"%s/%s/", myhomedir(), dir ? dir : ++ (maildirpath ? maildirpath : "Maildir")); ++ if (dp = opendir (curdir)){ ++ if (dir) sprintf (name,"#md/%s/",dir); ++ else strcpy (name,"#md/"); ++ ++ if (level == 0 && name && pmatch_full (name, pat, '/')) ++ mm_list (stream,'/', name, LATT_NOSELECT); ++ ++ while (d = readdir (dp)) ++ 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) sprintf (tmp,"%s%s", name,d->d_name); ++ else strcpy(tmp, d->d_name); ++ ++ if (pmatch_full (tmp,pat,'/')){ ++ sprintf(tmp,"%s/%s/%s", myhomedir(), dir ? dir : ++ (maildirpath ? maildirpath : "Maildir"), d->d_name); ++ if (stat (tmp,&sbuf) == 0 ++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){ ++ if (dir) sprintf (tmp,"%s%s", name,d->d_name); ++ else strcpy(tmp, d->d_name); ++ i = maildir_valid(tmp) ? LATT_NOINFERIORS : LATT_NOSELECT; ++ if (i == LATT_NOINFERIORS && ++ maildir_contains_folder(dir, d->d_name)) ++ i = LATT_HASCHILDREN; ++ 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))){ ++ sprintf(tmp,"%s/%s",dir,d->d_name); ++ maildir_list_work (stream,tmp,pat,level+1); ++ } ++ } ++ } ++ } ++ } ++ closedir (dp); ++ } ++ ++ int ++ same_maildir_file(char *name1, char *name2) ++ { ++ char tmp1[MAILTMPLEN+1], tmp2[MAILTMPLEN+1]; ++ char *s; ++ ++ strcpy(tmp1, name1 ? name1 : ""); ++ strcpy(tmp2, name2 ? name2 : ""); ++ if (s = strchr(tmp1, FLAGSEP)) ++ *s = '\0'; ++ if (s = strchr(tmp1, SIZESEP)) ++ *s = '\0'; ++ if (s = strchr(tmp2, FLAGSEP)) ++ *s = '\0'; ++ if (s = strchr(tmp2, SIZESEP)) ++ *s = '\0'; ++ ++ return !strcmp(tmp1, tmp2); ++ } ++ ++ ++ int comp_maildir_file(char *name1, char *name2) ++ { ++ unsigned long t1, t2; ++ int i; ++ ++ if (!(name1 && *name1)) ++ return name2 && *name2 ? (*name2 == FLAGSEP ? 0 : -1) : 0; ++ ++ if (!(name2 && *name2)) ++ return name1 && *name1 ? (*name1 == FLAGSEP ? 0 : 1) : 0; ++ ++ if(!strcmp(name1,name2)) ++ return 0; ++ ++ t1 = strtoul(name1, NULL, 10); ++ t2 = strtoul(name2, NULL, 10); ++ ++ if (t1 < t2) ++ return -1; ++ ++ if (t1 > t2) ++ return 1; ++ ++ i = strchr(name1,'.') - name1 + 1; ++ return (strcmp (name1 + i, name2 + i)); ++ } ++ ++ void ++ maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t) ++ { ++ char tmp[MAILTMPLEN+1], *b; ++ int offset = 0; ++ ++ if(d && f && r && s && t) ++ *d = *f = *r = *s = *t = 0; ++ else ++ return; /* can not call this function with null arguments */ ++ ++ strcpy(tmp,name); ++ while (b = strchr(tmp+offset, FLAGSEP)){ ++ char flag,last; ++ int i,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'){ ++ *d = strchr (b, MDFLAGC(Draft)) ? T : NIL; ++ *f = strchr (b, MDFLAGC(Flagged)) ? T : NIL; ++ *r = strchr (b, MDFLAGC(Replied)) ? T : NIL; ++ *s = strchr (b, MDFLAGC(Seen)) ? T : NIL; ++ *t = strchr (b, MDFLAGC(Trashed)) ? T : NIL; ++ } ++ b[k] = last; ++ b += k; ++ for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++); ++ offset++; ++ break; ++ default: break; /* Should we crash?... Nahhh */ ++ } ++ } ++ } ++ ++ 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){ ++ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir); ++ if (LOCAL->curdir) fs_give ((void **) &LOCAL->curdir); ++ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf); ++ 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+1], tmp2[MAILTMPLEN+1]; ++ int rv = 0; ++ DIR *dir; ++ struct direct *d; ++ struct stat sbuf; ++ char *maildirpath = mail_parameters(NIL, GET_MDINBOX, NIL); ++ ++ sprintf(tmp2,"%s/%s/%s", myhomedir(), dirname ? dirname ++ : (maildirpath ? maildirpath : "Maildir"), name); ++ ++ if (!(dir = opendir (tmp2))) ++ return NIL; ++ ++ while (d = readdir(dir)){ ++ 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))){ ++ ++ sprintf(tmp,"%s/%s", tmp2, d->d_name); ++ if (stat (tmp,&sbuf) == 0 ++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR || ++ (S_ISREG(sbuf.st_mode) && !strcmp(d->d_name, MDDIR)))){ ++ rv++; ++ break; ++ } ++ } ++ } ++ closedir(dir); ++ return rv; ++ } ++ ++ int ++ maildir_dir_is_empty(char *mailbox) ++ { ++ char tmp[MAILTMPLEN+1], tmp2[MAILTMPLEN+1]; ++ int rv = 1; ++ DIR *dir; ++ struct direct *d; ++ struct stat sbuf; ++ ++ maildir_file_path(mailbox, tmp2); ++ ++ if (!(dir = opendir (tmp2))) ++ return rv; ++ ++ while (d = readdir(dir)){ ++ sprintf(tmp,"%s/%s", tmp2, d->d_name); ++ if (strcmp(d->d_name, ".") ++ && strcmp(d->d_name,"..") ++ && strcmp(d->d_name, MDNAME(Cur)) ++ && strcmp(d->d_name, MDNAME(Tmp)) ++ && strcmp(d->d_name, MDNAME(New)) ++ && strcmp(d->d_name, MDDIR) ++ && strcmp(d->d_name, MDUIDVALIDITY) ++ && !(d->d_name[0] == '.' ++ && stat (tmp,&sbuf) == 0 ++ && S_ISREG(sbuf.st_mode))){ ++ rv = 0; ++ break; ++ } ++ } ++ closedir(dir); ++ return rv; ++ } ++ ++ void ++ maildir_get_file (MAILDIRFILE **mdfile) ++ { ++ MAILDIRFILE *md; ++ ++ md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE)); ++ memset(md, 0, sizeof(MAILDIRFILE)); ++ *mdfile = md; ++ } ++ ++ void ++ maildir_free_file (void **mdfile) ++ { ++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; ++ ++ if (md){ ++ if (md->name) fs_give((void **)&md->name); ++ fs_give((void **)&md); ++ } ++ } ++ ++ void ++ maildir_free_file_only (void **mdfile) ++ { ++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL; ++ ++ if (md && md->name) ++ fs_give((void **)&md->name); ++ } ++ ++ int ++ maildir_any_new_msgs(char *mailbox) ++ { ++ char tmp[MAILTMPLEN+1]; ++ int rv = NIL; ++ DIR *dir; ++ struct direct *d; ++ struct stat sbuf; ++ ++ MDFLD(tmp, mailbox, New); ++ ++ if (!(dir = opendir (tmp))) ++ return rv; ++ ++ while (d = readdir(dir)){ ++ if (d->d_name[0] == '.') ++ continue; ++ rv = T; ++ break; ++ } ++ closedir(dir); ++ return rv; ++ } ++ ++ ++ void ++ maildir_get_date(MAILSTREAM *stream, unsigned long msgno, DirNamesType dirtype) ++ { ++ MESSAGECACHE *elt; ++ char tmp[MAILTMPLEN+1]; ++ struct tm *tm; ++ struct stat sbuf; ++ ++ elt = mail_elt (stream,msgno); ++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype); ++ ++ if(MDSIZE(elt) == (off_t) 0 && stat(tmp, &sbuf) == 0){ ++ MDSIZE(elt) = sbuf.st_size; ++ MDMTIME(elt) = sbuf.st_mtime; ++ } ++ ++ ++ if (MDMTIME(elt) > 0){ ++ tm = gmtime (&MDMTIME(elt)); ++ elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1; ++ elt->year = tm->tm_year + 1900 - BASEYEAR; ++ elt->hours = tm->tm_hour; elt->minutes = tm->tm_min; ++ elt->seconds = tm->tm_sec; ++ elt->zhours = 0; elt->zminutes = 0; ++ } ++ } +diff -rc pine4.61/imap/src/osdep/unix/maildir.h pine4.61.maildir/imap/src/osdep/unix/maildir.h +*** pine4.61/imap/src/osdep/unix/maildir.h Sat Dec 11 15:12:09 2004 +--- pine4.61.maildir/imap/src/osdep/unix/maildir.h Sun Dec 5 20:51:17 2004 +*************** +*** 0 **** +--- 1,145 ---- ++ /* ++ * 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 ',' ++ ++ #define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */ ++ #define MDDIR ".mdir" /* this folder is a directory */ ++ ++ const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/ ++ const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */ ++ const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */ ++ ++ const char *sep[] = { sep1, sep2, sep3, NULL}; ++ ++ #define MDSEP(i) sep[((i) - 1)] ++ ++ /* Now we deal with flags. Woohoo! */ ++ typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed, ++ EmptyFlag, EndFlags} MdFlagNamesType; ++ const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags}; ++ const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags}; ++ ++ /* this array lists the codes for mdflgnms (maildir flag names) above */ ++ const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL}; ++ /* and as characters too */ ++ const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'}; ++ ++ /* MDFLAG(Seen, elt->seen) */ ++ #define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag] ++ /* MDFLAGC(Seen) */ ++ #define MDFLAGC(i) cmdflags[(i)] ++ ++ /* Now we deal with the directory structure */ ++ typedef enum {Cur, Tmp, New, EndDir} DirNamesType; ++ char *mdstruct[] = {"cur", "tmp", "new", NULL}; ++ #define MDNAME(i) mdstruct[(i)] ++ #define MDFLD(tmp, dir, i) sprintf((tmp),"%s/%s", (dir), mdstruct[(i)]) ++ #define MSGPATH(tmp, dir, msg,i) sprintf((tmp),"%s/%s/%s", (dir), mdstruct[(i)],(msg)) ++ ++ /* Now we deal with messages filenames */ ++ char mdlocaldomain[MAILTMPLEN+1] = {'\0'}; ++ static char *mdfpath = NULL; ++ #define CHUNK 16384 /* from unix.h */ ++ /* In gdb this is the *(struct maildir_local *)stream->local structure */ ++ ++ typedef struct maildir_local { ++ unsigned int inbox : 1; /* if it is an INBOX or not */ ++ unsigned int dirty : 1; /* diskcopy needs updating */ ++ int fd; /* fd of open message */ ++ char *dir; /* mail directory name */ ++ char *curdir; /* mail directory name/cur */ ++ unsigned char *buf; /* temporary buffer */ ++ char *hdr; /* current header */ ++ unsigned long buflen; /* current size of temporary buffer */ ++ time_t scantime; /* last time directory scanned */ ++ } MAILDIRLOCAL; ++ ++ /* Convenient access to local data */ ++ #define LOCAL ((MAILDIRLOCAL *) stream->local) ++ ++ typedef struct maildir_file_info { ++ char *name; /* name of the file */ ++ unsigned long pos; /* place in list where this file is listed */ ++ off_t size; /* size in bytes, on disk */ ++ time_t atime; /* last access time */ ++ time_t mtime; /* last modified time */ ++ time_t ctime; /* last changed time */ ++ } MAILDIRFILE; ++ ++ #define MDFILE(F) (((MAILDIRFILE *)((F)->maildirp))->name) ++ #define MDPOS(F) (((MAILDIRFILE *)((F)->maildirp))->pos) ++ #define MDSIZE(F) (((MAILDIRFILE *)((F)->maildirp))->size) ++ #define MDATIME(F) (((MAILDIRFILE *)((F)->maildirp))->atime) ++ #define MDMTIME(F) (((MAILDIRFILE *)((F)->maildirp))->mtime) ++ #define MDCTIME(F) (((MAILDIRFILE *)((F)->maildirp))->ctime) ++ ++ /* Function prototypes */ ++ ++ DRIVER *maildir_valid (char *name); ++ MAILSTREAM *maildir_open (MAILSTREAM *stream); ++ void maildir_gc (MAILSTREAM *stream,long gcflags); ++ void maildir_close (MAILSTREAM *stream, long options); ++ long maildir_ping (MAILSTREAM *stream); ++ long maildir_ping_core (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); ++ long maildir_create (MAILSTREAM *stream,char *mailbox); ++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */ ++ void maildir_expunge (MAILSTREAM *stream); ++ 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); ++ ++ /* utility functions */ ++ char *maildir_file (char *dst,char *name); ++ int maildir_select (struct direct *name); ++ int maildir_namesort (const void *d1, const void *d2); ++ void maildir_listwork(char *name, MAILSTREAM *stream, char *s2, char *subdir, int flag); ++ long maildir_canonicalize (char *pattern,char *ref,char *pat); ++ void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level); ++ int maildir_file_path(char *name, char *tmp); ++ int maildir_valid_name (char *name); ++ int maildir_valid_dir (char *name); ++ int maildir_base_name (char *name, char *tmp); ++ int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp); ++ void 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); ++ unsigned long maildir_scandir (char *name, struct direct ***flist, ++ unsigned long *nfiles, int *scand); ++ void maildir_parse_folder (MAILSTREAM *stream, int full); ++ void md_domain_name (void); ++ unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs, ++ DirNamesType dirtype, 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_dir_is_empty(char *mailbox); ++ long maildir_create_work (char *mailbox); ++ 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, DirNamesType dirtype); +diff -rc pine4.61/imap/src/osdep/unix/os_cyg.h pine4.61.maildir/imap/src/osdep/unix/os_cyg.h +*** pine4.61/imap/src/osdep/unix/os_cyg.h Mon Apr 19 08:23:48 2004 +--- pine4.61.maildir/imap/src/osdep/unix/os_cyg.h Wed Nov 24 15:15:18 2004 +*************** +*** 39,44 **** +--- 39,45 ---- + #define setpgrp setpgid + + #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */ ++ #define FLAGSEP ';' + #define geteuid Geteuid + uid_t Geteuid (void); + +diff -rc pine4.61/pine/folder.c pine4.61.maildir/pine/folder.c +*** pine4.61/pine/folder.c Mon Jul 12 19:26:16 2004 +--- pine4.61.maildir/pine/folder.c Wed Nov 24 15:15:18 2004 +*************** +*** 5752,5759 **** + } + else{ + sprintf(ques_buf, "DELETE \"%.100s\"%s", folder, +! close_opened ? " (the currently open folder)" +! : fp->isdir ? " (a directory)" : ""); + + if((ret = want_to(ques_buf, 'n', 'x', NO_HELP, WT_NORM)) != 'y'){ + q_status_message(SM_ORDER,0,3, (ret == 'x') ? "Delete cancelled" +--- 5752,5760 ---- + } + else{ + sprintf(ques_buf, "DELETE \"%.100s\"%s", folder, +! (!fp->isfolder || (fp->isdir && !close_opened)) +! ? " (a directory)" +! : close_opened ? " (the currently open folder)" : ""); + + if((ret = want_to(ques_buf, 'n', 'x', NO_HELP, WT_NORM)) != 'y'){ + q_status_message(SM_ORDER,0,3, (ret == 'x') ? "Delete cancelled" +*************** +*** 5787,5793 **** + && context_same_stream(context, fp->name, *possible_streamp)) + del_stream = *possible_streamp; + +! if(!fp->isfolder) + sprintf(fnamep = fname, "%.*s%c", sizeof(fname)-3, fp->name, + context->dir->delim); + else +--- 5788,5794 ---- + && context_same_stream(context, fp->name, *possible_streamp)) + del_stream = *possible_streamp; + +! if(!fp->isfolder || (fp->isdir && !close_opened)) + sprintf(fnamep = fname, "%.*s%c", sizeof(fname)-3, fp->name, + context->dir->delim); + else +*************** +*** 5803,5810 **** + } + + q_status_message2(SM_ORDER, 0, 3, "%.200s \"%.200s\" deleted.", +! blast_folder ? "Folder" : "Nickname", folder); +! + + if(context->use & CNTXT_INCMNG){ + char **new_list, **lp, ***alval; +--- 5804,5813 ---- + } + + q_status_message2(SM_ORDER, 0, 3, "%.200s \"%.200s\" deleted.", +! blast_folder +! ? (!fp->isfolder || (fp->isdir && !close_opened)) +! ? "Directory" : "Folder" +! : "Nickname", folder); + + if(context->use & CNTXT_INCMNG){ + char **new_list, **lp, ***alval; +diff -rc pine4.61/pine/init.c pine4.61.maildir/pine/init.c +*** pine4.61/pine/init.c Thu Jul 15 10:37:24 2004 +--- pine4.61.maildir/pine/init.c Wed Nov 24 15:15:18 2004 +*************** +*** 408,413 **** +--- 408,416 ---- + + CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file"; + ++ 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\""; ++ ++ + /* these are used to report folder directory creation problems */ + CONF_TXT_T init_md_exists[] = "The \"%s\" subdirectory already exists, but it is not writable by Pine so Pine cannot run. Please correct the permissions and restart Pine."; + +*************** +*** 591,596 **** +--- 594,601 ---- + cf_text_news_active}, + {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, + cf_text_news_spooldir}, ++ {"maildir-location", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, ++ cf_text_maildir_location}, + {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, + cf_text_upload_cmd}, + {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, +*************** +*** 2065,2070 **** +--- 2070,2079 ---- + mail_parameters(NULL, SET_NEWSSPOOL, + (void *)VAR_NEWS_SPOOL_DIR); + ++ set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE); ++ if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0]) ++ mail_parameters(NULL, SET_MDINBOX, (void *)VAR_MAILDIR_LOCATION); ++ + /* guarantee a save default */ + set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE); + if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0]) +diff -rc pine4.61/pine/other.c pine4.61.maildir/pine/other.c +*** pine4.61/pine/other.c Fri Jul 2 14:38:16 2004 +--- pine4.61.maildir/pine/other.c Wed Nov 24 15:15:18 2004 +*************** +*** 7464,7469 **** +--- 7464,7471 ---- + return(h_config_mimetype_path); + case V_NEWSRC_PATH : + return(h_config_newsrc_path); ++ case V_MAILDIR_LOCATION : ++ return(h_config_maildir_location); + case V_BROWSER : + return(h_config_browser); + #if defined(DOS) || defined(OS2) +*************** +*** 12720,12725 **** +--- 12722,12732 ---- + (void *)var->current_val.p); + } + #endif ++ else if(var == &ps->vars[V_MAILDIR_LOCATION]){ ++ if(var->current_val.p && var->current_val.p[0]) ++ mail_parameters(NULL, SET_MDINBOX, ++ (void *)var->current_val.p); ++ } + else if(revert && standard_radio_var(ps, var)){ + + cur_rule_value(var, TRUE, FALSE); +diff -rc pine4.61/pine/pine.c pine4.61.maildir/pine/pine.c +*** pine4.61/pine/pine.c Wed Jul 14 11:17:13 2004 +--- pine4.61.maildir/pine/pine.c Wed Nov 24 15:15:18 2004 +*************** +*** 552,558 **** + rv = 0; + if(pine_state->VAR_TCPWRITEWARNTIMEO){ + if(!SVAR_TCP_WRITEWARN(pine_state, rv, tmp_20k_buf)) +! if(rv == 0 || rv > 4) /* making sure */ + mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long)rv); + } + +--- 552,558 ---- + rv = 0; + if(pine_state->VAR_TCPWRITEWARNTIMEO){ + if(!SVAR_TCP_WRITEWARN(pine_state, rv, tmp_20k_buf)) +! if(rv == 0 || rv > 4) /* making sure */ + mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long)rv); + } + +diff -rc pine4.61/pine/pine.h pine4.61.maildir/pine/pine.h +*** pine4.61/pine/pine.h Wed Jul 14 17:25:12 2004 +--- pine4.61.maildir/pine/pine.h Wed Nov 24 15:15:19 2004 +*************** +*** 661,666 **** +--- 661,667 ---- + , V_NEWSRC_PATH + , V_NEWS_ACTIVE_PATH + , V_NEWS_SPOOL_DIR ++ , V_MAILDIR_LOCATION + , V_UPLOAD_CMD + , V_UPLOAD_CMD_PREFIX + , V_DOWNLOAD_CMD +*************** +*** 951,956 **** +--- 952,959 ---- + #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 ++ #define VAR_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].current_val.p ++ #define GLO_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].global_val.p + #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 pine4.61/pine/pine.hlp pine4.61.maildir/pine/pine.hlp +*** pine4.61/pine/pine.hlp Thu Jul 15 10:37:22 2004 +--- pine4.61.maildir/pine/pine.hlp Wed Nov 24 15:15:19 2004 +*************** +*** 18750,18755 **** +--- 18750,18845 ---- + <End of help on this topic> + + ++ ====== h_config_maildir_location ====== ++ ++ ++ OPTION: maildir-location ++ ++ ++

OPTION: maildir-location

++ ++

++ 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. ++ ++

++ 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. ++ ++

++ The value of this option is prefixed with the "~/" string to determine the ++ full path to your INBOX. ++ ++

++ You should probably read a few tips that ++ teach you how to configure your maildir for optimal performance. ++ ++

++

++ <End of help on this topic> ++ ++ ++ ====== h_config_maildir ===== ++ ++ ++ Maildir Support ++ ++ ++

Maildir Support

++ ++ This version of Pine has been enhanced with Maildir support. This text is ++ intended to be a reference on its support. ++

++ ++ 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. ++

++ ++ In order to use maildir support it is better to set your inbox-path to the ++ value "#md/inbox" (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 maildir-location configuration ++ variable. Most of the time you will not have to worry about the ++ maildir-location variable, because it will probably be set by your ++ administrator in the pine.conf configuration file. ++

++ ++ One of the advantages of the Maildir support of this version of Pine 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. ++

++ ++ 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 pah variable from "mail/" to ++ "#md/mail". In a maildir collection folders of any other format ++ are ignored. ++ ++

++

++ <End of help on this topic> ++ ++ + ====== h_config_literal_sig ===== + + >Release-Note: >Audit-Trail: >Unformatted: