From 2c2c957d5b8a09b6bbe1046d802eabf1fc621f59 Mon Sep 17 00:00:00 2001 From: kolla Date: Tue, 2 Aug 2005 15:11:20 +0000 Subject: Pine - A tool for reading, sending and managing electronic messages. With chappa-patches, transparent and more. LDAP- and SSL-support. --- packages/pine/.mtn2git_empty | 0 packages/pine/pine-4.63/.mtn2git_empty | 0 packages/pine/pine-4.63/imap-2000-time.patch | 56 + packages/pine/pine-4.63/pine-4.30-ldap.patch | 11 + packages/pine/pine-4.63/pine-4.31-segfix.patch | 17 + .../pine/pine-4.63/pine-4.40-lockfile-perm.patch | 22 + packages/pine/pine-4.63/pine-4.56-passfile.patch | 12 + .../pine/pine-4.63/pine-4.61-largeterminal.patch | 14 + .../pine/pine-4.63/pine-4.61-subjectlength.patch | 59 + .../pine-4.63/pine-4.62-spooldir-permissions.patch | 12 + .../pine/pine-4.63/pine-4.63-r2-chappa-all.patch | 21900 +++++++++++++++++++ packages/pine/pine-4.63/pine-ldap3.patch | 11 + packages/pine/pine-4.63/transparency.patch | 14 + packages/pine/pine_4.63.bb | 82 + 14 files changed, 22210 insertions(+) create mode 100644 packages/pine/.mtn2git_empty create mode 100644 packages/pine/pine-4.63/.mtn2git_empty create mode 100644 packages/pine/pine-4.63/imap-2000-time.patch create mode 100644 packages/pine/pine-4.63/pine-4.30-ldap.patch create mode 100644 packages/pine/pine-4.63/pine-4.31-segfix.patch create mode 100644 packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch create mode 100644 packages/pine/pine-4.63/pine-4.56-passfile.patch create mode 100644 packages/pine/pine-4.63/pine-4.61-largeterminal.patch create mode 100644 packages/pine/pine-4.63/pine-4.61-subjectlength.patch create mode 100644 packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch create mode 100644 packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch create mode 100644 packages/pine/pine-4.63/pine-ldap3.patch create mode 100644 packages/pine/pine-4.63/transparency.patch create mode 100644 packages/pine/pine_4.63.bb diff --git a/packages/pine/.mtn2git_empty b/packages/pine/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/pine/pine-4.63/.mtn2git_empty b/packages/pine/pine-4.63/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/pine/pine-4.63/imap-2000-time.patch b/packages/pine/pine-4.63/imap-2000-time.patch new file mode 100644 index 0000000000..751d1ff506 --- /dev/null +++ b/packages/pine/pine-4.63/imap-2000-time.patch @@ -0,0 +1,56 @@ +--- pine4.33/imap/src/osdep/unix/os_lnx.c.time Wed Feb 14 12:25:06 2001 ++++ pine4.33/imap/src/osdep/unix/os_lnx.c Wed Feb 14 12:25:16 2001 +@@ -23,6 +23,7 @@ + #include "osdep.h" + #include + #include ++#include + #include + #include + #include +--- pine4.33/imap/src/osdep/unix/news.c.time Thu Jan 18 21:28:33 2001 ++++ pine4.33/imap/src/osdep/unix/news.c Wed Feb 14 12:24:34 2001 +@@ -21,7 +21,7 @@ + #include + #include + #include +-extern int errno; /* just in case */ ++#include + #include "mail.h" + #include "osdep.h" + #include +--- pine4.33/imap/src/osdep/unix/phile.c.time Thu Jan 18 21:31:20 2001 ++++ pine4.33/imap/src/osdep/unix/phile.c Wed Feb 14 12:24:34 2001 +@@ -21,8 +21,8 @@ + #include + #include + #include +-extern int errno; /* just in case */ + #include ++#include + #include "mail.h" + #include "osdep.h" + #include +--- pine4.33/imap/src/osdep/unix/mh.c.time Thu Jan 18 21:27:37 2001 ++++ pine4.33/imap/src/osdep/unix/mh.c Wed Feb 14 12:24:34 2001 +@@ -21,7 +21,8 @@ + #include + #include + #include +-extern int errno; /* just in case */ ++#include ++ + #include "mail.h" + #include "osdep.h" + #include +--- pine4.33/imap/src/osdep/unix/mx.c.time Thu Jan 18 21:28:09 2001 ++++ pine4.33/imap/src/osdep/unix/mx.c Wed Feb 14 12:24:34 2001 +@@ -21,7 +21,7 @@ + #include + #include + #include +-extern int errno; /* just in case */ ++#include + #include "mail.h" + #include "osdep.h" + #include diff --git a/packages/pine/pine-4.63/pine-4.30-ldap.patch b/packages/pine/pine-4.63/pine-4.30-ldap.patch new file mode 100644 index 0000000000..6b920ade51 --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.30-ldap.patch @@ -0,0 +1,11 @@ +--- pine4.30/build.ldap Fri Oct 27 12:48:05 2000 ++++ pine4.30/build Fri Oct 27 12:49:00 2000 +@@ -249,7 +249,7 @@ + case "$?" in + 1) if [ "$LLIBS" != "1" ] + then +- L1="'LDAPLIBS=../ldap/libraries/libldap.a ../ldap/libraries/liblber.a'" ++ L1="'LDAPLIBS=../ldap/libraries/libldap.so ../ldap/libraries/liblber.so ../ldap/libraries/libresolv.so'" + fi + if [ "$LFLAGS" != "1" ] + then diff --git a/packages/pine/pine-4.63/pine-4.31-segfix.patch b/packages/pine/pine-4.63/pine-4.31-segfix.patch new file mode 100644 index 0000000000..f65aa60294 --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.31-segfix.patch @@ -0,0 +1,17 @@ +diff -urN pine4.31.orig/pine/osdep/lstcmpnt pine4.31/pine/osdep/lstcmpnt +--- pine4.31.orig/pine/osdep/lstcmpnt Mon Oct 30 17:45:08 2000 ++++ pine4.31/pine/osdep/lstcmpnt Tue Dec 12 06:33:53 2000 +@@ -9,10 +9,10 @@ + last_cmpnt(filename) + char *filename; + { +- register char *p = NULL, *q = filename; ++ char *p = NULL, *q = filename; + +- if(!q) +- return(q); ++ if(filename == 0) ++ return 0; + + while(q = strchr(q, '/')) + if(*++q) diff --git a/packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch b/packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch new file mode 100644 index 0000000000..f2cb434de2 --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch @@ -0,0 +1,22 @@ +--- pine4.40/imap/src/osdep/unix/env_unix.h.lock_protection_fix Thu Oct 4 05:26:33 2001 ++++ pine4.40/imap/src/osdep/unix/env_unix.h Thu Oct 4 05:30:33 2001 +@@ -46,12 +46,15 @@ + + + /* +- * Attention: all sorcerer's apprentices who think that 0666 is a mistake. +- * You are wrong. Read the FAQ. Do not meddle in the affairs of wizards, +- * for they are subtle and quick to anger. ++ * Attention: all people who do not care about OS security, and think that ++ * mode 0666 is a correct. You are wrong. In modern multiuser systems, ++ * both remote and local security is critically important. Allowing 0666 ++ * lockfiles, allows all sorts of security problems to occur. Feel free to ++ * meddle with it however, if you do not care about local security. + */ + +-#define MANDATORYLOCKPROT 0666 /* don't change this */ ++/* Change this only if you do not want a secure multiuser system */ ++#define MANDATORYLOCKPROT 0600 + + /* Function prototypes */ + diff --git a/packages/pine/pine-4.63/pine-4.56-passfile.patch b/packages/pine/pine-4.63/pine-4.56-passfile.patch new file mode 100644 index 0000000000..bb9813f7c6 --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.56-passfile.patch @@ -0,0 +1,12 @@ +--- pine4.56/pine/osdep/os-lnx.h.orig 2003-07-23 07:23:26.000000000 -0700 ++++ pine4.56/pine/osdep/os-lnx.h 2003-07-23 07:23:30.000000000 -0700 +@@ -295,5 +295,9 @@ + #define MAX_ADDR_EXPN (1000) /* Longest expanded addr */ + #define MAX_ADDR_FIELD (10000) /* Longest fully-expanded addr field */ + ++/*---------------------------------------------------------------------- ++ Allow for caching of passwords between connections. ++ ----*/ ++#define PASSFILE ".pinepw" + + #endif /* _OS_INCLUDED */ diff --git a/packages/pine/pine-4.63/pine-4.61-largeterminal.patch b/packages/pine/pine-4.63/pine-4.61-largeterminal.patch new file mode 100644 index 0000000000..c046546dba --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.61-largeterminal.patch @@ -0,0 +1,14 @@ +diff -Nur pine4.61.orig/pine/osdep/os-lnx.h pine4.61/pine/osdep/os-lnx.h +--- pine4.61.orig/pine/osdep/os-lnx.h 2004-12-18 00:33:46.162401405 +0100 ++++ pine4.61/pine/osdep/os-lnx.h 2004-12-18 00:34:14.473012057 +0100 +@@ -247,8 +247,8 @@ + + + /*-- Max screen pine will display on. Used to define some array sizes --*/ +-#define MAX_SCREEN_COLS (170) +-#define MAX_SCREEN_ROWS (200) ++#define MAX_SCREEN_COLS (340) ++#define MAX_SCREEN_ROWS (400) + + + /*---------------------------------------------------------------------- diff --git a/packages/pine/pine-4.63/pine-4.61-subjectlength.patch b/packages/pine/pine-4.63/pine-4.61-subjectlength.patch new file mode 100644 index 0000000000..b7a9cdf7b7 --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.61-subjectlength.patch @@ -0,0 +1,59 @@ +--- pine4.61/pine/strings.c_orig 2004-03-12 10:48:17.783992528 +0100 ++++ pine4.61/pine/strings.c 2004-03-12 11:01:37.929351944 +0100 +@@ -2912,7 +2912,7 @@ int rfc1522_token PROTO((char *, + char **)); + int rfc1522_valtok PROTO((int)); + int rfc1522_valenc PROTO((int)); +-int rfc1522_valid PROTO((char *, char **, char **, char **, ++int rfc1522_valid PROTO((char *, int, char **, char **, char **, + char **)); + char *rfc1522_8bit PROTO((void *, int)); + char *rfc1522_binary PROTO((void *, int)); +@@ -2949,7 +2949,7 @@ rfc1522_decode(d, len, s, charset) + + while(s && (sw = strstr(s, RFC1522_INIT))){ + /* validate the rest of the encoded-word */ +- if(rfc1522_valid(sw, &cset, &enc, &txt, &ew)){ ++ if(rfc1522_valid(sw, 1, &cset, &enc, &txt, &ew)){ + if(!rv) + rv = d; /* remember start of dest */ + +@@ -3222,10 +3222,15 @@ rfc1522_valenc(c) + + /* + * rfc1522_valid - validate the given string as to it's rfc1522-ness ++ * if relaxchk is true, double the maximum length of an encoded word. ++ * this is necessary to decode overlong encoded words generated by ++ * numerous incompliant implementations of RFC 2047 (1522). ++ + */ + int +-rfc1522_valid(s, charset, enc, txt, endp) ++rfc1522_valid(s, relaxchk, charset, enc, txt, endp) + char *s; ++ int relaxchk; + char **charset; + char **enc; + char **txt; +@@ -3237,7 +3242,11 @@ rfc1522_valid(s, charset, enc, txt, endp + rv = rfc1522_token(c = s+RFC1522_INIT_L, rfc1522_valtok, RFC1522_DLIM, &e) + && rfc1522_token(++e, rfc1522_valtok, RFC1522_DLIM, &t) + && rfc1522_token(++t, rfc1522_valenc, RFC1522_TERM, &p) +- && p - s <= RFC1522_MAXW; ++ && p - s <= RFC1522_MAXW * (relaxchk ? 2 : 1); ++ /* ++ * relax the length condition by doubling the max length of an ++ * encoded word. It's is needed for some longer encoded words. ++ */ + + if(charset) + *charset = c; +@@ -3288,7 +3297,7 @@ rfc1522_encode(d, len, s, charset) + } + else if(*p == RFC1522_INIT[0] + && !strncmp((char *) p, RFC1522_INIT, RFC1522_INIT_L)){ +- if(rfc1522_valid((char *) p, NULL, NULL, NULL, (char **) &q)) ++ if(rfc1522_valid((char *) p, 0, NULL, NULL, NULL, (char **) &q)) + p = q + RFC1522_TERM_L - 1; /* advance past encoded gunk */ + } + else if(*p == ESCAPE && match_escapes((char *)(p+1))){ diff --git a/packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch b/packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch new file mode 100644 index 0000000000..eb8c2f3eee --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch @@ -0,0 +1,12 @@ +diff -bur pine4.62/imap/src/osdep/unix/env_unix.c pine4.62-gentoo/imap/src/osdep/unix/env_unix.c +--- pine4.62/imap/src/osdep/unix/env_unix.c 2004-09-13 23:32:11.000000000 +0200 ++++ pine4.62-gentoo/imap/src/osdep/unix/env_unix.c 2005-03-24 23:38:13.000000000 +0100 +@@ -106,7 +106,7 @@ + * on the mail spool, or install mlock. + */ + /* disable warning if can't make .lock file */ +-static short disableLockWarning = NIL; ++static short disableLockWarning = 1; + + /* UNIX namespaces */ + diff --git a/packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch b/packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch new file mode 100644 index 0000000000..313d4544ef --- /dev/null +++ b/packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch @@ -0,0 +1,21900 @@ +diff -rc pine4.63/README.maildir pine4.63.I.USE/README.maildir +*** pine4.63/README.maildir Thu May 19 19:59:15 2005 +--- pine4.63.I.USE/README.maildir Thu May 19 19:57:24 2005 +*************** +*** 0 **** +--- 1,244 ---- ++ ------------------------------------------------------------------------------- ++ ++ Maildir Driver for Pine4.63 ++ By Eduardo Chappa ++ http://www.math.washington.edu/~chappa/pine/ ++ ++ ------------------------------------------------------------------------------- ++ 1. General Information About This Patch ++ --------------------------------------- ++ ++ This patch adds support for the maildir format to Pine. We take the ++ approach that this patch is one more driver among the number of formats ++ supported by Pine (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, 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 another 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 Pine 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 Pine to make this driver do its work, unless such patching is for ++ fixing bugs in Pine or to pass parameters to the driver. ++ ++ ---------------------------------------- ++ 3. One sided comparison to other patches ++ ---------------------------------------- ++ ++ There are two other maildir patches that could be easily adapted for ++ version 4.63. ++ ++ The first one is the patch distributed by SuSe which can be downloaded ++ from http://hico.fphil.uniba.sk/pine-patches.html. This patch was last ++ updated for version 4.58. Several hunks fail to be applied when you try to ++ apply it to Pine 4.63. Even if you apply those hunks manually there will ++ still be the following bugs: ++ ++ * You can not save between any two storage systems. The old patch did ++ not do this well, because it had to modify the mailcmd.c file in order ++ to save messages to a unix style mailbox, and this is undesirable, ++ because the mailutil application associated to this patch would fail ++ to save messages. ++ * It corrupts messages when it saves them to a mbx format folder. ++ * It could not save messages to the INBOX folder. ++ * It crashes when two different clients are accessing the same mailbox: ++ For example, if a message is marked deleted in one session, then it ++ should be marked deleted in any other session too, but instead it ++ crashes the second session. ++ * Pine crashes when saving several messages to a maildir (not even the ++ prototype of the function is correctly defined). ++ * Pine crashes when checking for the STATUS of a maildir mailbox. ++ * Pine could not delete a maildir folder. ++ * Pine could not rename a maildir folder. ++ ++ The other patch is available from Glue Logic (GL), was last updated for ++ version 4.61 and fails to apply a hunk in version 4.63, which must be ++ manually applied. There are, however, several problems and bugs. The patch ++ can be found at http://www.gluelogic.com/code/PINE-maildir/ ++ ++ * [Bug] It changes the default sort by arrival into sort by Date in ++ every folder. This makes Pine sort incorrectly any folder (no matter ++ in which format such folder is). ++ ++ * [Missing Important Feature] Lacks support for dual folder use. You can ++ not create a directory with the same name than a given folder and use ++ it! ++ ++ * [Bug] It confuses Unseen and Recent messages. Unseen messages are ++ reported as Recent. An Unseen message is a message that had not been ++ read the last time the folder was closed (or had been read but marked ++ Unseen in an earlier session). A Recent message is one which was not ++ in the folder the last time it was closed. Recent messages are your ++ real new messages, but Unseen are not. In GL patch, every Unseen ++ message is treated as Recent!. ++ ++ * [Problem] Large folders take long time to be opened for the first ++ time. ++ ++ * [Bug] Reported sizes are the number of bytes in the message and not ++ the "on the wire" size. If you were to manually edit a message and ++ either add or remove information from it, the size reported by Pine ++ would not be affected by this change. ++ ++ * [Bug] Crashes when two sessions access the same mailbox and one ++ deletes and expunges a message while the other tries to read that ++ message. (explicitly, if session A uses the GL patch, and session B ++ uses my patch, then the following procedure crashes session A: ++ ++ - In session B delete and expunge a message. ++ - Open that message in session A. Session A will notice it is gone ++ and will not crash. ++ - In session A delete and expunge a message. ++ - Open that message in session B. Session B will print a message ++ about no such message, then it will go back to the index screen ++ telling you that the message your were viewing was gone. ++ - Now in session B delete and expunge a message. ++ - Open that message in session A, Pine will crash). ++ ++ * [Bug] The patch changes the name of a message-file by adding a place ++ for the size in the name of the message-file. By doing so it breaks ++ the maildir specification which only allows you to change the name by ++ changing flags. If there is another client reading that mailbox, there ++ is a chance that the other client will fail finding messages due to ++ changes made by the GL patch. ++ ++ * [Bug] Any patch for Maildir support is NOT a patch for Pine (despite ++ the fact that you have read many times that the patch is for Pine), ++ but a patch for the C-Client library. As such it should work well with ++ any application that can be built with such library, like the UW-IMAP ++ server. The GL patch has a self proclaimed message stating not to use ++ the associated IMAP server to read Maildirs. This restriction does not ++ apply to my patch. I encourage you to use the server built with my ++ patch to access Maildirs. ++ ++ ------------------------------------------------------------------------ ++ 4. 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. All bugs of the other ++ patches have been reported but not fixed, either because there was no one ++ maintaining the patch, or the maintainer has not fixed them yet (all these ++ reports were made as late as November 2004). A very complete list of ++ updates for this patch, which includes bug fixes, improvements and ++ addition of new features can be found at ++ ++ http://www.math.washington.edu/~chappa/pine/updates/maildir.html ++ ++ ---------- ++ 5. On UIDs ++ ---------- ++ ++ 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. ++ ++ -------------------------------------------- ++ 6. Configuring Pine 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 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. ++ ++ ----------------------------------- ++ 7. What about Courier 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 Pine that a ++ collection in the Courier format is going to be accessed, so 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 Pine search for your collection in ~/Courier. ++ ++ You can not add this directly into Pine because Pine 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 April 29, 2005 +diff -rc pine4.63/imap/src/c-client/imap4r1.c pine4.63.I.USE/imap/src/c-client/imap4r1.c +*** pine4.63/imap/src/c-client/imap4r1.c Fri Apr 8 16:44:01 2005 +--- pine4.63.I.USE/imap/src/c-client/imap4r1.c Thu May 19 19:57:33 2005 +*************** +*** 4396,4401 **** +--- 4396,4402 ---- + if (*env) { /* need to merge this header into envelope? */ + if (!(*env)->newsgroups) { /* need Newsgroups? */ + (*env)->newsgroups = nenv->newsgroups; ++ (*env)->ngpathexists = nenv->ngpathexists; + nenv->newsgroups = NIL; + } + if (!(*env)->followup_to) { /* need Followup-To? */ +*************** +*** 4450,4455 **** +--- 4451,4457 ---- + if (oenv) { /* need to merge old envelope? */ + (*env)->newsgroups = oenv->newsgroups; + oenv->newsgroups = NIL; ++ (*env)->ngpathexists = oenv->ngpathexists; + (*env)->followup_to = oenv->followup_to; + oenv->followup_to = NIL; + (*env)->references = oenv->references; +diff -rc pine4.63/imap/src/c-client/mail.c pine4.63.I.USE/imap/src/c-client/mail.c +*** pine4.63/imap/src/c-client/mail.c Wed Mar 16 16:12:17 2005 +--- pine4.63.I.USE/imap/src/c-client/mail.c Thu May 19 19:57:24 2005 +*************** +*** 977,982 **** +--- 977,983 ---- + (((*mailbox == '{') || (*mailbox == '#')) && + (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT)))) + d = stream->dtb; ++ else if (maildir_valid_name(mailbox)) return maildir_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 pine4.63/imap/src/c-client/mail.h pine4.63.I.USE/imap/src/c-client/mail.h +*** pine4.63/imap/src/c-client/mail.h Tue Feb 8 15:44:54 2005 +--- pine4.63.I.USE/imap/src/c-client/mail.h Thu May 19 19:57:33 2005 +*************** +*** 149,154 **** +--- 149,156 ---- + #define SET_LOGOUTHOOK (long) 226 + #define GET_LOGOUTDATA (long) 227 + #define SET_LOGOUTDATA (long) 228 ++ #define SET_PASSWORDFILE 229 ++ #define GET_PASSWORDFILE 230 + + /* 3xx: TCP/IP */ + #define GET_OPENTIMEOUT (long) 300 +*************** +*** 311,316 **** +--- 313,320 ---- + #define SET_SNARFPRESERVE (long) 567 + #define GET_INBOXPATH (long) 568 + #define SET_INBOXPATH (long) 569 ++ #define GET_COURIERSTYLE (long) 570 ++ #define SET_COURIERSTYLE (long) 571 + + /* Driver flags */ + +*************** +*** 622,627 **** +--- 626,632 ---- + /* Message envelope */ + + typedef struct mail_envelope { ++ unsigned int ngpathexists : 1; /* newsgroups may be bogus */ + unsigned int incomplete : 1; /* envelope may be incomplete */ + unsigned int imapenvonly : 1; /* envelope only has IMAP envelope */ + char *remail; /* remail header if any */ +*************** +*** 790,795 **** +--- 795,801 ---- + 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.63/imap/src/c-client/rfc822.c pine4.63.I.USE/imap/src/c-client/rfc822.c +*** pine4.63/imap/src/c-client/rfc822.c Tue Jan 18 12:41:09 2005 +--- pine4.63.I.USE/imap/src/c-client/rfc822.c Thu May 19 19:57:33 2005 +*************** +*** 354,359 **** +--- 354,360 ---- + ENVELOPE *env = (*en = mail_newenvelope ()); + BODY *body = bdy ? (*bdy = mail_newbody ()) : NIL; + long MIMEp = -1; /* flag that MIME semantics are in effect */ ++ long PathP = NIL; /* flag that a Path: was seen */ + parseline_t pl = (parseline_t) mail_parameters (NIL,GET_PARSELINE,NIL); + if (!host) host = BADHOST; /* make sure that host is non-null */ + while (i && *s != '\n') { /* until end of header */ +*************** +*** 443,448 **** +--- 444,452 ---- + *t++ = '\0'; + } + break; ++ case 'P': /* possible Path: */ ++ if (!strcmp (tmp+1,"ATH")) env->ngpathexists = T; ++ break; + case 'R': /* possible Reply-To: */ + if (!strcmp (tmp+1,"EPLY-TO")) + rfc822_parse_adrlist (&env->reply_to,d,host); +diff -rc pine4.63/imap/src/mailutil/mailutil.c pine4.63.I.USE/imap/src/mailutil/mailutil.c +*** pine4.63/imap/src/mailutil/mailutil.c Tue Feb 8 15:50:49 2005 +--- pine4.63.I.USE/imap/src/mailutil/mailutil.c Thu May 19 19:57:33 2005 +*************** +*** 29,34 **** +--- 29,35 ---- + + /* Globals */ + ++ int passfile = NIL; /* password file supplied ? */ + int debugp = NIL; /* flag saying debug */ + int verbosep = NIL; /* flag saying verbose */ + int rwcopyp = NIL; /* flag saying readwrite copy (for POP) */ +*************** +*** 159,164 **** +--- 160,166 ---- + for (nargs = argc ? argc - 1 : 0,args = argv + 1; nargs; args++,nargs--) { + if (*(s = *args) == '-') { /* parse switches */ + if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T; ++ else if (!strcmp (s,"-passfile")) passfile = T; + else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T; + else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T; + else if ((nargs > 1) && (!strcmp (s,"-merge") || !strcmp (s,"-m"))) { +*************** +*** 179,184 **** +--- 181,190 ---- + exit (ret); + } + } ++ else if (passfile) { ++ env_parameters(SET_PASSWORDFILE, (void *)s); ++ passfile = NIL; ++ } + else if (!cmd) cmd = s; /* first non-switch is command */ + else if (!src) src = s; /* second non-switch is source */ + else if (!dst) dst = s; /* third non-switch is destination */ +*************** +*** 665,671 **** + username[NETMAXUSER-1] = '\0'; + if (s = strchr (username,'\n')) *s = '\0'; + } +! strcpy (password,getpass ("password: ")); + } + + +--- 671,679 ---- + username[NETMAXUSER-1] = '\0'; + if (s = strchr (username,'\n')) *s = '\0'; + } +! mm_userpwd(mb, &username, &password); +! if (!password || !*password) +! strcpy (password,getpass ("password: ")); + } + + +diff -rc pine4.63/imap/src/osdep/unix/Makefile pine4.63.I.USE/imap/src/osdep/unix/Makefile +*** pine4.63/imap/src/osdep/unix/Makefile Wed Apr 20 17:49:08 2005 +--- pine4.63.I.USE/imap/src/osdep/unix/Makefile Thu May 19 19:57:24 2005 +*************** +*** 119,125 **** + # 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 +--- 119,125 ---- + # Standard distribution build parameters + + DEFAULTAUTHENTICATORS=md5 pla log +! DEFAULTDRIVERS=maildir courier imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile + + + # Normally no need to change any of these +*************** +*** 128,134 **** + 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 +--- 128,134 ---- + 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 +*************** +*** 257,263 **** + + 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 \ +--- 257,263 ---- + + 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 \ +*************** +*** 846,852 **** + 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 + +--- 846,852 ---- + 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.63/imap/src/osdep/unix/dummy.c pine4.63.I.USE/imap/src/osdep/unix/dummy.c +*** pine4.63/imap/src/osdep/unix/dummy.c Wed Nov 10 16:16:23 2004 +--- pine4.63.I.USE/imap/src/osdep/unix/dummy.c Thu May 19 19:57:24 2005 +*************** +*** 104,109 **** +--- 104,110 ---- + { + 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 */ +*************** +*** 364,370 **** + 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 = mailboxfile (tmp,name)) && +--- 365,374 ---- + 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 = mailboxfile (tmp,name)) && +*************** +*** 385,390 **** +--- 389,396 ---- + { + 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); +*************** +*** 450,455 **** +--- 456,469 ---- + { + struct stat sbuf; + char *s,tmp[MAILTMPLEN]; ++ if (!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4) ++ || is_valid_maildir(&mailbox)){ ++ char tmp[MAILTMPLEN] = {'\0'}; ++ strcpy(tmp, mailbox); ++ if(tmp[strlen(tmp) - 1] != '/') ++ tmp[strlen(tmp)] = '/'; ++ return maildir_delete(stream, tmp); ++ } + if (!(s = dummy_file (tmp,mailbox))) { + sprintf (tmp,"Can't delete - invalid name: %.80s",s); + MM_LOG (tmp,ERROR); +*************** +*** 476,481 **** +--- 490,498 ---- + { + 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.63/imap/src/osdep/unix/env_unix.c pine4.63.I.USE/imap/src/osdep/unix/env_unix.c +*** pine4.63/imap/src/osdep/unix/env_unix.c Mon Sep 13 14:31:19 2004 +--- pine4.63.I.USE/imap/src/osdep/unix/env_unix.c Thu May 19 19:57:33 2005 +*************** +*** 24,29 **** +--- 24,30 ---- + + /* c-client environment parameters */ + ++ static char *pwdfile = NIL; /* password file */ + static char *myUserName = NIL; /* user name */ + static char *myHomeDir = NIL; /* home directory name */ + static char *myMailboxDir = NIL;/* mailbox directory name */ +*************** +*** 41,46 **** +--- 42,48 ---- + static char *blackBoxDir = NIL; /* black box directory name */ + /* black box default home directory */ + static char *blackBoxDefaultHome = NIL; ++ static int xlate_key; /* for password file support */ + static short anonymous = NIL; /* is anonymous */ + static short blackBox = NIL; /* is a black box */ + static short closedBox = NIL; /* is a closed box */ +*************** +*** 215,220 **** +--- 217,229 ---- + case GET_SHAREDHOME: + ret = (void *) sharedHome; + break; ++ case SET_PASSWORDFILE: ++ if (pwdfile) fs_give ((void **) &pwdfile); ++ pwdfile = cpystr ((char *) value); ++ break; ++ case GET_PASSWORDFILE: ++ ret = (void *) pwdfile; ++ break; + case SET_SYSINBOX: + if (sysInbox) fs_give ((void **) &sysInbox); + sysInbox = cpystr ((char *) value); +*************** +*** 1638,1640 **** +--- 1647,1723 ---- + } + return ret; + } ++ ++ /* ++ * ++ * Module to add support for password file to a c-client application ++ * ++ * Written by Eduardo Chappa, based on password file support for Pine ++ * ++ */ ++ #ifndef PWDFILE ++ #define PWDFILE 1 ++ #endif ++ ++ #define FIRSTCH 0x20 ++ #define LASTCH 0x7e ++ #define TABSZ (LASTCH - FIRSTCH + 1) ++ ++ char mm_xlate_out (char c); ++ void mm_userpwd (NETMBX *mb, char **username, char **password); ++ ++ /* function that decodes passwords */ ++ ++ char mm_xlate_out (char c) ++ { ++ register int dti; ++ register int xch; ++ ++ if((c >= FIRSTCH) && (c <= LASTCH)){ ++ xch = c - (dti = xlate_key); ++ xch += (xch < FIRSTCH-TABSZ) ? 2*TABSZ : (xch < FIRSTCH) ? TABSZ : 0; ++ dti = (xch - FIRSTCH) + dti; ++ dti -= (dti >= 2*TABSZ) ? 2*TABSZ : (dti >= TABSZ) ? TABSZ : 0; ++ xlate_key = dti; ++ return(xch); ++ } ++ else ++ return(c); ++ } ++ ++ void mm_userpwd (NETMBX *mb, char **username, char **password) ++ { ++ char *s; ++ char tmp[MAILTMPLEN], *ui[5]; ++ FILE *fp; ++ int i, j, n; ++ ++ if (!(pwdfile = env_parameters(GET_PASSWORDFILE, NULL))) ++ return; ++ ++ if (fp = fopen(pwdfile, "r")){ ++ for(n = 0; fgets(tmp, sizeof(tmp), fp); n++){ ++ xlate_key = n; ++ for(i = 0; tmp[i]; i++) ++ tmp[i] = mm_xlate_out(tmp[i]); ++ ++ if(i && tmp[i-1] == '\n') ++ tmp[i-1] = '\0'; ++ ++ ui[0] = ui[1] = ui[2] = ui[3] = ui[4] = NULL; ++ for(i = 0, j = 0; tmp[i] && j < 5; j++){ ++ for(ui[j] = &tmp[i]; tmp[i] && tmp[i] != '\t'; i++); ++ ++ if(tmp[i]) ++ tmp[i++] = '\0'; ++ } ++ if (*username && ui[1] && !strcmp(*username, ui[1]) && mb->host ++ && ((ui[2] && !strcmp(mb->host, ui[2])) ++ || (ui[4] && !strcmp(mb->host,ui[4])) ++ || (ui[2] && !strcmp(mb->orighost, ui[2])) ++ || (ui[4] && !strcmp(mb->orighost,ui[4])))) ++ strcpy (*password,ui[0]); ++ } ++ fclose(fp); ++ } ++ } +diff -rc pine4.63/imap/src/osdep/unix/maildir.c pine4.63.I.USE/imap/src/osdep/unix/maildir.c +*** pine4.63/imap/src/osdep/unix/maildir.c Thu May 19 19:59:15 2005 +--- pine4.63.I.USE/imap/src/osdep/unix/maildir.c Thu May 19 19:57:24 2005 +*************** +*** 0 **** +--- 1,2031 ---- ++ /* ++ * Maildir driver for Pine4.63 ++ * ++ * Written by Eduardo Chappa ++ * Last Update: May 04, 2005 ++ * ++ * 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 "rfc822.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_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 */ ++ 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 */ ++ /* driver flags */ ++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_NOSTICKY, ++ (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 */ ++ ++ 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/" or "#mc/" part from a folder name */ ++ void maildir_remove_root (char **name) ++ { ++ int courier = IS_COURIER(*name); ++ char realname[MAILTMPLEN], *p; ++ ++ if (maildir_valid_name(*name)){ ++ (*name) += 3; ++ if (**name == '/') ++ (*name)++; ++ } ++ if(courier) ++ courier_realname(*name, realname); ++ else ++ strcpy(realname, *name); ++ *name = 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] != '#')) ++ sprintf(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) ++ { ++ char *maildirpath = maildir_parameters(GET_INBOXPATH,NIL); ++ char realname[MAILTMPLEN]; ++ 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 */ ++ ++ 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); ++ 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(*name == '/') /* full path */ ++ strcpy(tmp, name); /* do nothing */ ++ else{ ++ sprintf (tmp,"%s/%s%s%s", myhomedir (), ++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5) ++ ? name : (maildirpath ? maildirpath : "Maildir"), ++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5) ++ ? "" : (courier ? "/" : ""), ++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5) ++ ? "" : *(name+5) == MDSEPARATOR(courier) ? name+5 : ""); ++ } ++ ++ 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, myhomedir (), strlen(myhomedir()))){ ++ (*name) += strlen(myhomedir()); ++ 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); ++ ++ return maildir_valid_dir(tmpname) ++ ? (IS_COURIER(name) ? &courierdriver : &maildirdriver) : NIL; ++ } ++ /*maildir fast */ ++ 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 = 1; 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); ++ } ++ } ++ } ++ ++ ++ /* ++ * 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; ++ ++ if (scand) ++ *scand = -1; /* assume error for safety */ ++ stat(name,&sbuf); /* stat the containing directory */ ++ if (scand) ++ *scand = scandir(name, flist, ++ flag == CCLIENT ? maildir_select : courier_dir_select, ++ flag == CCLIENT ? maildir_namesort : courier_dir_sort); ++ *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]; ++ 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]; ++ 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; ++ ++ LOCAL->courier = IS_COURIER(stream->mailbox); ++ 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; ++ } ++ } ++ ++ if(maildir_file_path (stream->mailbox, tmp)){ ++ 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], tmp2[MAILTMPLEN], file[MAILTMPLEN], ++ newfile[MAILTMPLEN], *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, CCLIENT); ++ 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; ++ ++ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t); ++ if (elt->maildirp) ++ maildir_free_file_only ((void **)&elt->maildirp); ++ else{ ++ maildir_get_file((MAILDIRFILE **)&elt->maildirp); ++ we_compute++; ++ } ++ MDFILE(elt) = cpystr(names[pos]->d_name); ++ MDPOS(elt) = pos; ++ ++ 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, dirtype); ++ elt->valid = T; ++ 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); ++ if (mdfpath) fs_give((void **)&mdfpath); ++ 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); ++ 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 (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.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 dirtyp