Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 28877 | Differences between
and this patch

Collapse All | Expand All

(-)pine4.50/README.maildir (+93 lines)
Line 0 Link Here
1
Pine 4.0x Maildir c-client module
2
---------------------------------
3
4
Written by Mattias Larsson <ml@techno.org> <mta@freeit.com>
5
6
This is the second release of my Maildir driver for Pine 4. It is based
7
on Eric Greens IMAP2bis Maildir driver.
8
9
PLEASE NOTE that this driver has only been tested in the IMAP4rev1 daemon
10
before. It was just put into Pine 4.00, and it looks like it works, but it
11
has not been extensively tested. It has been running for 8 months in
12
production in our IMAP4 daemon though.
13
14
PLEASE NOTE:
15
16
This driver needs to store the UID's of the message in the file somehow. In
17
the earlier versions of this driver this was done by adding a new maildir
18
flag (the ,3 flag), however, this solution was not very good since most
19
other clients could not handle it. Thus I had to find another solution. In
20
this driver I use a pretty radical method. Any file in the maildir with the
21
execute bit set has its UID set in the mtime of the file. So you should not
22
edit the files in here, or in any otherway update the mtime, because then
23
the UID gets changed. Most clients should not do this, so I think this
24
solution is compatible with most other clients (if you find one that isn't,
25
let me know). If you for some reason have to edit a file in the Maildir,
26
delete the ".uidvalidity" file in the root of the Maildir (ie, the dir where
27
you find cur/ new/ and tmp/). Alternatively, edit maildir.c and define the
28
NO_UID_VALIDITY option, which will cause the Maildir to get set new UID's on
29
every start up. Note that if you are running IMAP and Netscape as a client,
30
you can't change the UID's, because Netscape do not support the UID validity
31
flag in the IMAP protocol. So use this with care. 
32
33
Please edit the maildir.c file in any case. There are 3 options you can
34
set yourself. The default configuration is not suitable for ISPs. If you are
35
an ISP, or system with many users, you might want to consider setting some
36
of the options different.
37
38
Ohh, if there are problems compiling it, let me know, and please let me know
39
what you did to fix it. This thing was developed on Solaris (using both GCC
40
and SunCC, should work with both), but I haven't tried it on any other
41
platform. It is also known to compile cleanly on Linux RH5.1
42
43
CONFIGURATION
44
-------------
45
46
There are a few configurable options. You find these at the top of the
47
maildir.c file (and it can be found in imap/src/osdep/unix if I'm not all
48
mistaken). Right now, two options are configurable. By default it is
49
configured for ISP use, something that you might want to change if you use
50
it at home.
51
52
HOW TO USE
53
----------
54
55
Use it as any other c-client driver. There is some option you want to change
56
if you want all folders to be created as Maildirs (and I can't remember what
57
the option is from the top of my head). Read the pine documentation.
58
59
CHANGES
60
-------
61
62
Rel 4.  Coredump problem fixed. In release 3 I decided to user the sparep
63
	in the message cache so no patching of mail.h would be necessary,
64
	however, PINE uses this pointer internally for other things, causing
65
	coredumps when used with the Rel 3. patch.
66
67
Rel 3.	New way of storing UID's (compatible with ,2 clients).
68
	Multiple inbox patches applied
69
70
Rel 2.  Pine 4 changes.
71
72
Rel 1.  Imap4rev 1 driver
73
74
FINAL NOTES
75
-----------
76
77
I'll try to maintain and release new versions as soon as I have time over,
78
which unfortunately does not happen very often in this business ;)
79
80
You can (might) find newer versions of this driver at:
81
82
http://www.freeit.com/mta/
83
84
85
Regards,
86
Daniel Mattias Larsson
87
88
e-mail: ml@techno.org
89
ph: +46-707-268785
90
snail-mail:
91
Industrivagen 4
92
SE-194 77 Upplands Vasby
93
SWEDEN
(-)pine4.53/imap/src/c-client/mail.h (+1 lines)
Lines 755-760 Link Here
755
  unsigned int spare7 : 1;	/* seventh spare bit */
755
  unsigned int spare7 : 1;	/* seventh spare bit */
756
  unsigned int spare8 : 1;	/* eighth spare bit */
756
  unsigned int spare8 : 1;	/* eighth spare bit */
757
  void *sparep;			/* spare pointer */
757
  void *sparep;			/* spare pointer */
758
  void *maildirp;		/* for the Maildir driver */
758
  unsigned long user_flags;	/* user-assignable flags */
759
  unsigned long user_flags;	/* user-assignable flags */
759
} MESSAGECACHE;
760
} MESSAGECACHE;
760
761
(-)pine4.53/imap/src/osdep/unix/Makefile (-4 / +4 lines)
Lines 21-27 Link Here
21
# Command line build parameters
21
# Command line build parameters
22
22
23
EXTRAAUTHENTICATORS=
23
EXTRAAUTHENTICATORS=
24
EXTRADRIVERS=mbox
24
EXTRADRIVERS=maildir mbox
25
PASSWDTYPE=std
25
PASSWDTYPE=std
26
SSLTYPE=nopwd
26
SSLTYPE=nopwd
27
27
Lines 106-112 Link Here
106
# Standard distribution build parameters
106
# Standard distribution build parameters
107
107
108
DEFAULTAUTHENTICATORS=md5 pla log
108
DEFAULTAUTHENTICATORS=md5 pla log
109
DEFAULTDRIVERS=imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile
109
DEFAULTDRIVERS=maildir imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile
110
110
111
111
112
# Normally no need to change any of these
112
# Normally no need to change any of these
Lines 115-121 Link Here
115
BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \
115
BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \
116
 dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
116
 dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
117
 rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
117
 rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
118
 unix.o mbox.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o
118
 unix.o mbox.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o maildir.o
119
CFLAGS=-g
119
CFLAGS=-g
120
120
121
CAT=cat
121
CAT=cat
Lines 809-815 Link Here
809
tenex.o: mail.h misc.h osdep.h tenex.h dummy.h
809
tenex.o: mail.h misc.h osdep.h tenex.h dummy.h
810
unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
810
unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
811
utf8.o: mail.h misc.h osdep.h utf8.h
811
utf8.o: mail.h misc.h osdep.h utf8.h
812
812
maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
813
813
814
# OS-dependent
814
# OS-dependent
815
815
(-)pine4.53/imap/src/osdep/unix/dummy.c (-2 / +6 lines)
Lines 345-357 Link Here
345
  char tmp[MAILTMPLEN];
345
  char tmp[MAILTMPLEN];
346
				/* don't \NoSelect dir if it has a driver */
346
				/* don't \NoSelect dir if it has a driver */
347
  if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
347
  if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
348
      (d != &dummydriver)) attributes &= ~LATT_NOSELECT;
348
      (d != &dummydriver)) {
349
    attributes &= ~LATT_NOSELECT; 
350
    attributes |= LATT_NOINFERIORS;
351
  }      
349
  if (!contents ||		/* notify main program */
352
  if (!contents ||		/* notify main program */
350
      (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
353
      (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
351
       !stat (dummy_file (tmp,name),&sbuf) && (csiz <= sbuf.st_size) &&
354
       !stat (dummy_file (tmp,name),&sbuf) && (csiz <= sbuf.st_size) &&
352
       SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size)))
355
       SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size)))
353
    mm_list (stream,delimiter,name,attributes);
356
    mm_list (stream,delimiter,name,attributes);
354
  return T;
357
  if (attributes & LATT_NOINFERIORS) return NIL;
358
  else return T;
355
}
359
}
356
360
357
/* Dummy create mailbox
361
/* Dummy create mailbox
(-)pine4.53/imap/src/osdep/unix/maildir.c (+1143 lines)
Line 0 Link Here
1
/*
2
 * Maildir Module for PINE 4.0x - fourth release, use with CARE! 
3
 *
4
 * Author:      Mattias Larsson <ml@techno.org>
5
 *
6
 * Version:     21.07.98
7
 *
8
 * Please read the README.maildir file before using this module!
9
 *
10
 * If you have any questions, please e-mail ml@techno.org 
11
 *
12
 * Multiple inboxes patch by Dean Gaudet <dgaudet@arctic.org>
13
 *
14
 * =================================================
15
 *
16
 * Based on the IMAP2 maildir routines by:
17
 *
18
 * Author:      Eric Green
19
 *              Bloodhounds International Inc.
20
 *              thrytis@imaxx.net
21
 *
22
 * Additional contributions from:
23
 *              Aidas Kasparas (kaspar@soften.ktu.lt)
24
 *
25
 * Date:        27 April 1997
26
 * Last Edited: 13 June 1997
27
 *
28
 * Based (heavily) on mh.c and other c-client library files by Mark Crispin:
29
 *
30
 *              Mark Crispin
31
 *              Networks and Distributed Computing
32
 *              Computing & Communications
33
 *              University of Washington
34
 *              Administration Building, AG-44
35
 *              Seattle, WA  98195
36
 *              Internet: MRC@CAC.Washington.EDU
37
 *
38
 * Copyright 1995 by the University of Washington
39
 *
40
 *  Permission to use, copy, modify, and distribute this software and its
41
 * documentation for any purpose and without fee is hereby granted, provided
42
 * that the above copyright notice appears in all copies and that both the
43
 * above copyright notice and this permission notice appear in supporting
44
 * documentation, and that the name of the University of Washington not be
45
 * used in advertising or publicity pertaining to distribution of the software
46
 * without specific, written prior permission.  This software is made
47
 * available "as is", and
48
 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
49
 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
50
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
51
 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
52
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
53
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
54
 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
55
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
56
 *
57
 */
58
59
/* CONFIGURABLE OPTIONS - PLEASE CHECK THESE OUT */
60
61
#define NO_MAILDIR_FIDDLE	/* disallow Maildir with Maildir in the
62
				name. This is useful in an ISP setup
63
				using the IMAP daemon. #undef it if you
64
				are running a normal pine and know what
65
				you are doing */
66
67
#define NO_ABSOLUTE_PATHS	/* if you define this, all paths
68
				use your HOMEDIR is the root instead
69
				of the actual root of the machine. This
70
				is also useful in an ISP setup with
71
				IMAP */
72
73
#undef NO_UID_VALIDITIY		/* define this if you want the UID's not
74
				to be persistent over sessions. Use this
75
				if you use another client to read the
76
				maildir that screws up the special way
77
				in which we store UIDs. Do not enable
78
				unless you are sure you need it. */
79
	
80
/* END CONFIGURATION */
81
82
#define MTA_DEBUG	/* debugging sent to stdout */
83
#undef MTA_DEBUG
84
85
#include <stdio.h>
86
#include <ctype.h>
87
#include <errno.h>
88
extern int errno;		/* just in case */
89
#include "mail.h"
90
#include "osdep.h"
91
#include <pwd.h>
92
#include <sys/stat.h>
93
#include <sys/time.h>
94
#include <sys/types.h>
95
#include <utime.h>
96
#include "maildir.h"
97
#include "misc.h"
98
#include "dummy.h"
99
100
/* Driver dispatch used by MAIL */
101
102
DRIVER maildirdriver = {
103
  "maildir",			/* driver name */
104
				/* driver flags */
105
  DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE,
106
  (DRIVER *) NIL,		/* next driver */
107
  maildir_valid,			/* mailbox is valid for us */
108
  maildir_parameters,		/* manipulate parameters */
109
  NIL,			/* scan mailboxes */
110
  maildir_list,			/* find mailboxes */
111
  maildir_lsub,			/* find subscribed mailboxes */
112
  maildir_sub,			/* subscribe to mailbox */
113
  maildir_unsub,		/* unsubscribe from mailbox */
114
  maildir_create,			/* create mailbox */
115
  maildir_delete,			/* delete mailbox */
116
  maildir_rename,			/* rename mailbox */
117
  NIL,				/* status of mailbox */
118
  maildir_open,			/* open mailbox */
119
  maildir_close,		/* close mailbox */
120
  maildir_fast,			/* fetch message "fast" attributes */
121
  NIL,				/* fetch message flags */
122
  NIL,				/* fetch overview */
123
  NIL,				/* fetch message envelopes */
124
  maildir_fetchheader,		/* fetch message header */
125
  maildir_fetchtext,		/* fetch message body */
126
  NIL,				/* fetch partial message text */
127
  NIL,				/* unique identifier */
128
  NIL,				/* message number */
129
  NIL,				/* modify flags */
130
  maildir_flagmsg,		/* per-message modify flags */
131
  NIL,				/* search for message based on criteria */
132
  NIL,				/* sort messages */
133
  NIL,				/* thread messages */
134
  maildir_ping,			/* ping mailbox to see if still alive */
135
  maildir_check,		/* check for new messages */
136
  maildir_expunge,			/* expunge deleted messages */
137
  maildir_copy,			/* copy messages to another mailbox */
138
  maildir_append,			/* append string message to mailbox */
139
  maildir_gc				/* garbage collect stream */
140
};
141
142
				/* prototype stream */
143
MAILSTREAM maildirproto = {&maildirdriver};
144
145
/* Check validity of mailbox
146
 */
147
 
148
DRIVER *maildir_valid (char *name)
149
{
150
  return maildir_isvalid(name,T) ? &maildirdriver : NIL;
151
}
152
153
int maildir_isvalid (char *name,long justname)
154
{
155
  char tmp[MAILTMPLEN];
156
  struct stat sbuf;
157
  
158
  if (!name || (!*name) || 
159
      ((*name == '#') && 
160
       (*(name+1) == 0 ||
161
	(*(name+1) != 'm' && *(name+1) != 'M') ||
162
	(*(name+2) != 'd' && *(name+1) != 'D') ||
163
	*(name+3) != '/')) || (*name == '.'))
164
    return NIL;
165
  
166
  /* okay, anything containing the name Maildir will be ignored
167
     this is to prevent anyone from fiddling with their incoming Maildir
168
     directly, it should be accessed via the INBOX alias */
169
170
  #ifdef NO_MAILDIR_FIDDLE
171
  if (strstr(name, ".maildir")) {
172
	return NIL; 
173
	}
174
  #endif
175
 				/* If we are requested only to check 
176
  				   if the name is appropriate then we
177
  				   have done! */
178
  if (justname && *name == '#') return T;
179
  
180
181
				/* must be valid local mailbox */
182
  if ((*name != '*') && (*name != '{') &&
183
      maildir_file (tmp,name) &&
184
				/* assume its maildir if its a dir */
185
      stat (tmp,&sbuf) == 0 && S_ISDIR (sbuf.st_mode))
186
    return T;
187
188
				/* INBOX is for default Maildir */
189
  if (!strcmp (ucase (strcpy (tmp,name)), "INBOX") &&
190
      (stat (maildir_file (tmp,name),&sbuf) == 0) &&
191
      S_ISDIR (sbuf.st_mode))
192
    return T;
193
194
  return NIL;
195
}
196
197
/* Maildir mail generate file string
198
 */
199
200
char *maildir_file (char *dst,char *name)
201
{
202
  char tmp[MAILTMPLEN];
203
  
204
  if (strlen (name) > 3 &&	/* safe do other comparisons */
205
      (*name == '#') &&
206
      (name[1] == 'm' || name[1] == 'M') &&
207
      (name[2] == 'd' || name[2] == 'D') &&
208
      (name[3] == '/'))
209
    name += 4;
210
211
#ifdef NO_ABSOLUTE_PATHS  
212
  if (*name == '/') {	
213
  /* we do not want to accept / absolute paths, so lets strip the first
214
     / ... */
215
    sprintf(dst,"%s/%s/cur", myhomedir(), name+1);
216
217
/*    strncpy (dst, name, MAILTMPLEN - 2);
218
    strncat (dst, "/cur", MAILTMPLEN - 2);
219
    dst[MAILTMPLEN - 1] = '\0'; */
220
  }
221
  else
222
    sprintf (dst,"%s/%s/cur",myhomedir (),
223
	    strcmp (ucase (strcpy (tmp, name)), "INBOX") ? name : MAILDIRPATH);
224
#else
225
  if (*name == '/') {	
226
    strncpy (dst, name, MAILTMPLEN - 2);
227
    strncat (dst, "/cur", MAILTMPLEN - 2);
228
    dst[MAILTMPLEN - 1] = '\0';
229
  }
230
  else
231
    sprintf (dst,"%s/%s/cur",myhomedir (),
232
	    strcmp (ucase (strcpy (tmp, name)), "INBOX") ? name : MAILDIRPATH);
233
234
#endif 
235
  
236
  #ifdef MTA_DEBUG
237
  printf("maildir_file '%s'\n", dst);
238
  #endif
239
  return dst;
240
}
241
242
/* Maildir open
243
 */
244
 
245
MAILSTREAM *maildir_open (MAILSTREAM *stream)
246
{
247
 char tmp[MAILTMPLEN],tmp2[MAILTMPLEN];
248
249
 if (!stream) return &maildirproto;
250
 if (LOCAL) {		/* recycle stream */
251
	maildir_close (stream, 0);
252
	stream->dtb = &maildirdriver;
253
	mail_free_cache (stream);
254
	stream->uid_last = 0;       /* default UID validity */
255
	stream->uid_validity = time (0);
256
	}
257
258
	stream->uid_validity = 0; /* was time(0) */
259
260
  if (stream->uid_last < time(0))
261
  	stream->uid_last = time (0);  
262
  
263
    stream->local = fs_get (sizeof (MAILDIRLOCAL));
264
  LOCAL->inbox = !strcmp (ucase (strcpy (tmp,stream->mailbox)),"INBOX") ||
265
      !strcmp (stream->mailbox,maildir_file (tmp2,"INBOX"));
266
  LOCAL->dir = cpystr (maildir_file (tmp,stream->mailbox)); /* copy dir name */
267
                                /* make temporary buffer */
268
  LOCAL->buf = (char *) fs_get ((LOCAL->buflen = MAXMESSAGESIZE) + 1);
269
  LOCAL->scantime = 0;          /* not scanned yet */
270
  stream->sequence++;
271
  stream->nmsgs = stream->recent = 0;
272
273
  maildir_ping_core (stream);
274
  maildir_ping (stream);
275
/*  if (maildir_ping (stream) && !(stream->nmsgs || stream->silent))
276
    printf("Mailbox is empty\n");
277
*/
278
  return stream;
279
280
}
281
282
/* Maildir ping mailbox
283
 */
284
285
long maildir_ping_core (MAILSTREAM *stream)
286
{
287
  char tmp[MAILTMPLEN];
288
  MESSAGECACHE *elt;
289
  struct stat sbuf, sbuf2;
290
  DIR *dir;
291
  struct direct *d;
292
  int reloadall = NIL;
293
  int uidinvalid = NIL;
294
  unsigned long old;
295
  long i;
296
  long nmsgs = stream->nmsgs;
297
  long recent = stream->recent;
298
  long nfiles = stream->nmsgs;
299
  int silent = stream->silent;
300
  char *s, *s2;
301
  mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
302
303
/*  maildir_copynew (LOCAL->dir);
304
 */
305
  
306
  if (stat (LOCAL->dir,&sbuf) < 0) {
307
    sprintf (tmp,"Unable to open maildir: %s",strerror (errno));
308
    mm_log (tmp,ERROR);
309
    return NIL;
310
  }
311
312
  /* okay, lets try to figure out the Maildir UID validity. This is done
313
     by checking the last modification time of the file .uidvalidity
314
     in the rootdir of the Maildir. Any program reordering the files
315
     in the directory have to touch this file */
316
317
  sprintf(tmp, "%s/../.uidvalidity", LOCAL->dir);
318
  
319
  if (stat (tmp,&sbuf2) < 0) {
320
	/* no uid validity file found, if uid_validity == 0, we have
321
	   to set it to something other than 0, and then create the
322
	   .uidvalidity file for future accesses */
323
324
	if (stream->uid_validity == 0) {
325
		FILE *fl;
326
		struct utimbuf tbuf;
327
		
328
		stream->uid_validity = time(0);
329
		tbuf.actime = stream->uid_validity;
330
		tbuf.modtime = stream->uid_validity;
331
332
		if ((fl = fopen(tmp, "w"))) {
333
			fclose(fl);
334
			chmod (tmp, S_IRUSR|S_IWUSR);
335
			utime(tmp, &tbuf);
336
			}
337
		}
338
		uidinvalid = T; /* UID's are invalid, update them */
339
	} else {
340
	/* valid file, lets set UID if uid_validity = 0 */
341
	if (stream->uid_validity == 0) {
342
	stream->uid_validity = sbuf2.st_mtime;
343
		}
344
	}
345
346
  #ifdef NO_UID_VALIDITY
347
  uidinvalid = T; /* force the UIDs to be invalid and reset every time,
348
  		     useful in an environment without imap servers and
349
  		     clients that screw up the UIDs.. i'd leave it to
350
  		     OFF until I really need it though... */
351
  #endif
352
353
  stream->silent = T;  
354
  if (sbuf.st_ctime != LOCAL->scantime) {
355
    /* update the message list */
356
    struct direct **names = NIL;
357
    nfiles = scandir (LOCAL->dir,&names,maildir_select,maildir_namesort);
358
359
    for (i = 0; i < nfiles; i++) {
360
361
	/* check if file has executable bit set */
362
	sprintf(tmp, "%s/%s", LOCAL->dir, names[i]->d_name);
363
  	stat (tmp,&sbuf2);
364
	if (sbuf2.st_mode & S_IXUSR) {
365
		/* executable bit set, modtime is uid */
366
		if (sbuf2.st_mtime > stream->uid_last)
367
			stream->uid_last = sbuf2.st_mtime+1;
368
		}
369
	/* this is kept for backwards compatibility */
370
        if ((s = strstr (names[i]->d_name,":3,")))
371
		s += 3;
372
        if (s && (s2 = strstr (s, ",U"))) {
373
      		s2 += 2;
374
		sscanf(s2, "%d", &old);
375
		if (old > stream->uid_last) {
376
			stream->uid_last = old+1;
377
			}
378
		}	
379
	
380
    }
381
382
    mm_critical (stream);	/* go critical */
383
    old = stream->uid_last;
384
    LOCAL->scantime = sbuf.st_ctime;
385
386
				/* check if old files same */
387
    for (i = 0; i < stream->nmsgs; i++) {
388
389
      if (strcmp ((char *) mail_elt (stream, i + 1)->maildirp,
390
		  names[i]->d_name)) {
391
	reloadall = T;
392
	break;
393
      }
394
    }
395
396
    if (reloadall) { /* files are out of order, rebuild cache */
397
398
      i = 1;
399
      while (i <= stream->nmsgs)
400
				/* clean out cache */
401
	if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT))) {
402
	  fs_give ((void **) &elt->maildirp);
403
	  mail_expunged (stream,i);
404
	}
405
	else
406
	  i++;
407
      
408
      mm_log ("Warning: Mailbox has changed in an unexpected way.  Reloading.",
409
	      WARN);
410
      stream->nmsgs = 0;
411
    }
412
    nmsgs = stream->nmsgs;
413
    
414
    stream->nmsgs = nfiles; /* hm? */    
415
416
    for (i = nmsgs; i < nfiles; i++) {
417
418
      mail_exists(stream, i+1);
419
				/* if newly seen, add to list */
420
      (elt = mail_elt (stream, i + 1))->maildirp = (long) cpystr (names[i]->d_name);
421
       elt->valid = T;
422
423
      /* grab the flags */
424
      if ((s = strstr (names[i]->d_name,":3,"))) {
425
	s += 3;
426
	if (strchr (s,'F'))
427
	  elt->flagged = T;
428
	if (strchr (s,'R'))
429
	  elt->answered = T;
430
	if (strchr (s,'S'))
431
	  elt->seen = T;
432
	if (strchr (s,'T'))
433
	  elt->deleted = T;
434
      } else if ((s = strstr (names[i]->d_name,":2,"))) {
435
	/* this is the :2, id where all files go nowadays */
436
	s += 3;
437
	if (strchr (s,'F'))
438
	  elt->flagged = T;
439
	if (strchr (s,'R'))
440
	  elt->answered = T;
441
	if (strchr (s,'S'))
442
	  elt->seen = T;
443
	if (strchr (s,'T'))
444
	  elt->deleted = T;
445
	sprintf(tmp, "%s/%s", LOCAL->dir, names[i]->d_name);
446
  	stat (tmp,&sbuf2);
447
	if (sbuf2.st_mode & S_IXUSR) {
448
		/* executable bit set, modtime is uid */
449
		elt->private.uid = sbuf2.st_mtime;
450
		}
451
	/* and if we could not retrieve UID from modtime, or if
452
	   UIDs are invalid, go here */
453
	if (elt->private.uid == 0 || uidinvalid) {
454
        	stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
455
		maildir_flagmsg(stream, elt);
456
		}	
457
	s = 0; /* make sure next if statement does not trigger */      
458
      	}
459
460
      if (s)
461
      if ((s2 = strstr (s, ",U"))) {
462
      	s2 += 2;
463
	sscanf(s2, "%d", &elt->private.uid);
464
	if (elt->private.uid == 0 || uidinvalid) {
465
        	stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
466
		maildir_flagmsg(stream, elt);
467
		}	
468
	
469
      	} else { /* assign new UID */
470
        stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
471
	elt->recent = T;
472
	recent++;
473
	maildir_flagmsg(stream, elt); /* store the UID that we assigned to it */
474
	}	
475
476
477
478
    }
479
480
    mm_nocritical (stream);	/* release critical */
481
				/* free the names stuff */
482
    for (i = 0; i < nfiles; i++)
483
      fs_give ((void **) &names[i]);
484
    if (names)
485
      fs_give ((void **) &names);
486
  }
487
  stream->silent = silent;
488
  mail_exists(stream,nfiles);
489
/*  if (!reloadall)  */
490
  	mail_recent (stream,recent);
491
492
  return T;			/* return that we are alive */
493
}
494
495
long maildir_ping (MAILSTREAM *stream)
496
{
497
  maildir_copynew (LOCAL->dir);
498
  return maildir_ping_core (stream);
499
}
500
501
void maildir_copynew (const char *mailbox)
502
{
503
  char tmp[MAILTMPLEN],file[MAILTMPLEN],newfile[MAILTMPLEN];
504
  DIR *dir;
505
  struct dirent *d;
506
  struct stat sbuf;
507
  
508
  sprintf (tmp,"%s/../new",mailbox);
509
  if (!(dir = opendir (tmp)))
510
    return;
511
512
  while (d = readdir (dir)) {
513
    if (d->d_name[0] == '.')
514
      continue;			/* skip .files */
515
516
    sprintf (file,"%s/%s",tmp,d->d_name);
517
				/* make sure this is a normal file */
518
    if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)) {
519
      
520
      if (strstr (d->d_name,":3,")) /* this message already has flags */
521
	sprintf (newfile,"%s/%s",mailbox,d->d_name);
522
      else
523
	sprintf (newfile,"%s/%s:3,",mailbox,d->d_name);
524
      
525
				/* move the new mail to the cur dir */
526
      if (link (file,newfile) == -1)
527
	mm_log("Unable to read new mail!",WARN);
528
      else
529
	unlink (file);	
530
    }
531
  }
532
  closedir (dir);
533
}
534
535
int maildir_select (struct direct *name)
536
{
537
  if (name->d_name[0] != '.')
538
    return T;
539
540
  return NIL;
541
}
542
543
int maildir_namesort (struct direct **d1,struct direct **d2)
544
{
545
/* this maildir module is kind of lame and expects files it just moved
546
 * from new/ to cur/ to show up at the end of the sorting... this mostly
547
 * works fine when the timestamp is less than 1000000000 -- you can just
548
 * strcmp.  but when the timestamp went past that point we need to do
549
 * this convoluted sort.
550
 */
551
  unsigned long t1, t2;
552
553
  t1 = strtoul((*d1)->d_name, NULL, 10);
554
  t2 = strtoul((*d2)->d_name, NULL, 10);
555
  if (t1 == t2) {
556
    return strcmp ((*d1)->d_name,(*d2)->d_name);
557
  }
558
  else if (t1 > t2) {
559
    return 1;
560
  }
561
  return -1;
562
}
563
564
565
/* Maildir garbage collect stream
566
 */
567
568
void maildir_gc (MAILSTREAM *stream,long gcflags)
569
{
570
  unsigned long i;
571
  
572
  if (gcflags & GC_TEXTS) {	/* garbage collect texts? */
573
				/* flush texts from cache */
574
/*    if (LOCAL->hdr) fs_give ((void **) &LOCAL->hdr);
575
//    if (stream->text) fs_give ((void **) &stream->text);
576
//    stream->msgno = 0;		invalidate stream text
577
*/
578
  }
579
}
580
581
/* Maildir close
582
 */
583
584
void maildir_close (MAILSTREAM *stream, long options)
585
{
586
  MESSAGECACHE *elt;
587
  int i;
588
  mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
589
 
590
/*  CL_EXPUNGE OPTION SUPPORT HERE SOMEWHERE! */
591
				/* clean out the cached paths */
592
  for (i = 1; i <= stream->nmsgs; i++)
593
    if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp) {
594
      fs_give ((void **) &elt->maildirp);
595
      elt->maildirp = 0; /* otherwise pine coredumps */  
596
	}  
597
  
598
  if (LOCAL) {			/* only if a stream is open */
599
    if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
600
    maildir_gc (stream,GC_TEXTS); /* free local cache */
601
				/* free local scratch buffer */
602
    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
603
				/* nuke the local data */
604
    fs_give ((void **) &stream->local);
605
    stream->dtb = NIL;		/* log out the DTB */
606
  }
607
}
608
609
void maildir_check (MAILSTREAM *stream)
610
{
611
  /* Perhaps in the future this will preserve flags */
612
  if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);   
613
}
614
615
long maildir_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
616
{
617
  unsigned long i;
618
  MESSAGECACHE *elt;
619
                                /* UID call "impossible" */
620
  if (flags & FT_UID) return NIL;
621
  elt = mail_elt (stream,msgno);/* get elt */
622
                                /* snarf message if don't have it yet */
623
  if (!elt->private.msg.text.text.data) {
624
    maildir_fetchheader (stream,msgno,&i,flags);
625
    if (!elt->private.msg.text.text.data) return NIL;
626
  }
627
  if (!(flags & FT_PEEK)) {     /* mark as seen */
628
    mail_elt (stream,msgno)->seen = T;
629
    maildir_flagmsg (stream, mail_elt(stream,msgno));
630
    mm_flags (stream,msgno);
631
  }
632
  if (!elt->private.msg.text.text.data) return NIL;
633
  INIT (bs,mail_string,elt->private.msg.text.text.data,
634
        elt->private.msg.text.text.size);
635
  return T;
636
}
637
638
639
/* Maildir fetch message header
640
 */
641
642
char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
643
		unsigned long *length, long flags)
644
{
645
  unsigned long i,hdrsize;
646
  int fd;
647
  char *t;
648
  char tmp[MAILTMPLEN];
649
  char *s,*b;
650
  struct stat sbuf;
651
  struct tm *tm;
652
  MESSAGECACHE *elt;
653
  *length = 0;                  /* default to empty */
654
  if (flags & FT_UID) return "";/* UID call "impossible" */
655
  elt = mail_elt (stream,msgno);/* get elt */
656
  if (!elt->private.msg.header.text.data) {
657
658
/*    maildir_gc (stream,GC_TEXTS);  invalidate current cache */
659
				/* build message file name */
660
    sprintf (tmp,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
661
    if ((fd = open (tmp,O_RDONLY,NIL)) >= 0) {
662
      fstat (fd,&sbuf);		/* get size of message */
663
				/* make plausible IMAPish date string */
664
      tm = gmtime (&sbuf.st_mtime);
665
      elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
666
      elt->year = tm->tm_year + 1900 - BASEYEAR;
667
      elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
668
      elt->seconds = tm->tm_sec;
669
      elt->zhours = 0; elt->zminutes = 0;
670
				/* slurp message */
671
      read (fd,s = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);
672
      s[sbuf.st_size] = '\0';	/* tie off file */
673
      close (fd);		/* close file */
674
675
      for (i = 0,b = s; *b && !(i && (*b == '\n')); i = (*b++ == '\n'));
676
      hdrsize = (*b ? ++b:b)-s;	/* number of header bytes */
677
678
      elt->rfc822_size =          /* size of entire message in CRLF form */
679
       (elt->private.msg.header.text.size =
680
        strcrlfcpy ((char **) &elt->private.msg.header.text.data,&i,s,
681
                    hdrsize)) +
682
          (elt->private.msg.text.text.size =
683
           strcrlfcpy ((char **) &elt->private.msg.text.text.data,&i,b,
684
                       sbuf.st_size - hdrsize));
685
      fs_give ((void **) &s);
686
    } else return "";
687
688
  }
689
690
  *length = elt->private.msg.header.text.size;
691
  return (char *) elt->private.msg.header.text.data;
692
}
693
694
void maildir_fast (MAILSTREAM *stream,char *sequence,long flags)
695
{
696
  unsigned long i,j;
697
				/* ugly and slow */
698
  if (stream && LOCAL && ((flags & FT_UID) ?
699
			  mail_uid_sequence (stream,sequence) :
700
			  mail_sequence (stream,sequence)))
701
    for (i = 1; i <= stream->nmsgs; i++)
702
      if (mail_elt (stream,i)->sequence) maildir_fetchheader (stream,i,&j,NIL);
703
}
704
705
/* Maildir find list of subscribed mailboxes
706
 * Accepts: mail stream
707
 *	    pattern to search
708
 */
709
710
void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
711
{
712
  return;
713
}
714
715
void *maildir_parameters (long function,void *value)
716
{
717
  return NIL;
718
}
719
720
long maildir_create (MAILSTREAM *stream,char *mailbox)
721
{
722
  char tmp[MAILTMPLEN];
723
  char err[MAILTMPLEN];
724
  char *s, *s2;
725
  int fnlen, i;
726
  char *subdir_names[] = {"/cur","/new","/tmp",NULL};
727
728
				/* must not already exist */
729
  if (access (maildir_file (tmp,mailbox),F_OK) == 0) {
730
    sprintf (err,"Can't create mailbox %s: mailbox already exists",mailbox);
731
    mm_log (err,ERROR);
732
    return NIL;
733
  }
734
  
735
  maildir_file (tmp,mailbox);	/* get file name */
736
  fnlen = strlen (tmp);
737
  /*syslog(LOG_INFO, "fname: '%s'", tmp);*/
738
  tmp[fnlen - 4] = '\0';	/* making main directory's name */
739
  fnlen -= 4;
740
741
  /* okay, try to add support for adding hiearchys of directories, this
742
     is done by scanning for /'s.... */
743
     
744
  /*syslog(LOG_INFO, "tmp '%s'", tmp);*/
745
  s = tmp;
746
747
  while ((s = strstr(s, "/")) != 0) {
748
	/*syslog(LOG_INFO, "Before make: '%s'", s);*/
749
  	*s = '\0';
750
  	/*syslog(LOG_INFO, "Trying to make: '%s'", tmp);*/
751
	if (mkdir (tmp,0700) && *s != '\0') /* trying to make the dir */
752
	  if (errno != EEXIST) {
753
	    sprintf (err,"Can't create mailbox %s: %s %s",
754
		     mailbox,tmp,strerror (errno));
755
    	     mm_log (err,ERROR);
756
             return NIL;
757
	  }
758
  	*s = '/';
759
	s++;
760
  	} 
761
762
  if (mkdir (tmp,0700)) {	/* try to make new dir */
763
    sprintf (err,"Can't create mailbox %s: %s %s",
764
	     mailbox,tmp,strerror (errno));
765
    mm_log (err,ERROR);
766
    return NIL;
767
  }
768
769
  /*syslog(LOG_INFO, "create maildir");*/
770
  for (i = 0; subdir_names[i]; i++) {
771
    strcpy (tmp + fnlen,subdir_names[i]);
772
773
    if (mkdir (tmp,0700)) {	/* try to make new dir */
774
      sprintf (err,"Can't create mailbox %s: %s %s",
775
	       mailbox,tmp,strerror (errno));
776
      mm_log (err,ERROR);
777
      return NIL;
778
    }
779
  }
780
781
  return T;			/* return success */
782
}
783
784
void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
785
{
786
  char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN];
787
  struct utimbuf tbuf;
788
  char *s;
789
790
                                /* build the new filename */
791
  sprintf (oldfile,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
792
  if ((s = strchr ((char *) elt->maildirp,':'))) *s = '\0';
793
  sprintf (fn,"%s:2,%s%s%s%s",(char *) elt->maildirp,elt->flagged ? "F" : "",
794
           elt->answered ? "R" : "",elt->seen ? "S" : "",
795
           elt->deleted ? "T" : "");
796
  sprintf (newfile,"%s/%s",LOCAL->dir,fn);
797
                                /* rename the file with new flags */
798
  if (rename (oldfile,newfile) < 0) {
799
    sprintf(oldfile,"Unable to write flags to disk: %s",strerror (errno));
800
    mm_log(oldfile,ERROR);
801
    return;
802
  }
803
                                /* update the file name in cache */
804
  fs_give ((void **) &elt->maildirp);
805
  elt->maildirp = (long) cpystr (fn);
806
807
  /* fix the UID on the file */
808
  tbuf.actime = elt->private.uid;
809
  tbuf.modtime = elt->private.uid;
810
  chmod (newfile, S_IRUSR|S_IWUSR|S_IXUSR);
811
  utime (newfile, &tbuf);
812
813
}
814
815
void maildir_expunge (MAILSTREAM *stream)
816
{
817
  MESSAGECACHE *elt;
818
  unsigned long i = 1;
819
  unsigned long n = 0;
820
  unsigned long recent = stream->recent;
821
  
822
  maildir_gc (stream,GC_TEXTS);	/* invalidate texts */
823
  mm_critical (stream);		/* go critical */
824
  while (i <= stream->nmsgs) {	/* for each message */
825
				/* if deleted, need to trash it */
826
    if ((elt = mail_elt (stream,i))->deleted) {
827
      sprintf (LOCAL->buf,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
828
      if (unlink (LOCAL->buf)) {/* try to delete the message */
829
	sprintf (LOCAL->buf,"Expunge of message %ld failed, aborted: %s",i,
830
		 strerror (errno));
831
	mm_log (LOCAL->buf,WARN);
832
	break;
833
      }
834
				/* free the cached filename */
835
      if (elt->maildirp) {
836
	      fs_give ((void **) &elt->maildirp);
837
	      elt->maildirp = 0; /* otherwise pine coredumps */
838
		}
839
      if (elt->recent) --recent;/* if recent, note one less recent message */
840
      mail_expunged (stream,i);	/* notify upper levels */
841
      n++;			/* count up one more expunged message */
842
    }
843
    else i++;			/* otherwise try next message */
844
  }
845
  if (n) {			/* output the news if any expunged */
846
    sprintf (LOCAL->buf,"Expunged %ld messages",n);
847
    mm_log (LOCAL->buf,(long) NIL);
848
  }
849
  else mm_log ("No messages deleted, so no update needed",(long) NIL);
850
  mm_nocritical (stream);	/* release critical */
851
				/* notify upper level of new mailbox size */
852
  mail_exists (stream,stream->nmsgs);
853
  mail_recent (stream,recent);
854
}
855
856
/* dont forget to process options in here */
857
long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
858
{
859
  STRING st;
860
  MESSAGECACHE *elt;
861
  struct stat sbuf;
862
  int fd;
863
  long i;
864
  char *s,tmp[MAILTMPLEN];
865
				/* copy the messages */
866
  if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : 
867
  	mail_sequence (stream,sequence)) 
868
  for (i = 1; i <= stream->nmsgs; i++)
869
    if ((elt = mail_elt (stream,i))->sequence) {
870
      sprintf (LOCAL->buf,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
871
      if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
872
      fstat (fd,&sbuf);		/* get size of message */
873
				/* slurp message */
874
      read (fd,s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size);
875
      s[sbuf.st_size] = '\0';	/* tie off file */
876
      close (fd);		/* flush message file */
877
      INIT (&st,mail_string,(void *) s,sbuf.st_size);
878
      sprintf (LOCAL->buf,"%s%s%s%s%s)",
879
	       elt->seen ? " \\Seen" : "",
880
	       elt->deleted ? " \\Deleted" : "",
881
	       elt->flagged ? " \\Flagged" : "",
882
	       elt->answered ? " \\Answered" : "",
883
	       (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
884
	       "" : " ");
885
      LOCAL->buf[0] = '(';	/* open list */
886
      mail_date (tmp,elt);	/* generate internal date */
887
      if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
888
	fs_give ((void **) &s);	/* give back temporary space */
889
	return NIL;
890
      }
891
      fs_give ((void **) &s);	/* give back temporary space */
892
    }
893
  return T;			/* return success */
894
}
895
896
long maildir_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
897
		   STRING *message)
898
{
899
  int fd;
900
  char c,*s;
901
  char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
902
  MESSAGECACHE elt;
903
  long i;
904
  long size = 0;
905
  long ret = LONGT;
906
  short uf = 0;
907
  
908
  /*  
909
     This is intentionaly made static.  Users can ask to save a LOT of messages
910
     at once and this program can do that within one second. Dan's assumption
911
     that time+pid+hostname always will be unique stops being true in this
912
     case. So we will add yet another number to host part of message file's
913
     name. Hostname is used only to make filename unique and Dan  explicitly
914
     says that "<...>  Other than this [skipping filenames starting at dot] ,
915
     readers should not attempt to parse filenames. <...>". Therefore this 
916
     addition should be no problem. Am I right, Dan?   --AK
917
  */ 
918
  
919
  static unsigned int transact = 0;
920
921
  if (flags) 			/* get flags if given */
922
    uf = maildir_getflags (user_flags (&maildirproto),flags);
923
924
/*  if (date) {			want to preserve date?
925
    //syslog(LOG_INFO, "date: '%s'", date);
926
				// yes, parse date into an elt
927
    if (!mail_parse_date (&elt,date)) {
928
      sprintf (tmp,"Bad date in append: %s",date);
929
      mm_log (tmp,ERROR);
930
      return NIL;
931
    }
932
  } */
933
				/* N.B.: can't use LOCAL->buf for tmp */
934
				/* make sure valid mailbox */
935
  if (!maildir_isvalid (mailbox, NIL)) {
936
    sprintf (tmp,"Not a valid Maildir mailbox: %s",mailbox);
937
    mm_log (tmp,ERROR);
938
    return NIL;
939
  }
940
				/* build file name we will use */
941
  sprintf (file,"%u.%d.%09u.%s:3,%s%s%s%s",
942
	   time (0),getpid (),transact++,mylocalhost (),
943
	   uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
944
	   uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
945
				/* build tmp file name */
946
  sprintf (path1,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
947
  
948
  if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
949
    sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));
950
    mm_log (tmp,ERROR);
951
    return NIL;
952
  }
953
  i = SIZE (message);		/* get size of message */
954
  s = (char *) fs_get (i + 1);	/* get space for the data */
955
				/* copy the data w/o CR's */
956
  while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
957
  mm_critical (stream);		/* go critical */
958
				/* write the data */
959
  if ((write (fd,s,size) < 0) || fsync (fd)) {
960
    unlink (path1);		/* delete message */
961
    sprintf (tmp,"Message append failed: %s",strerror (errno));
962
    mm_log (tmp,ERROR);
963
    ret = NIL;
964
  }
965
				/* build final filename to use */
966
  sprintf (path2,"%s/../new/%s",maildir_file (tmp,mailbox),file);
967
  if (link (path1,path2) < 0) {
968
    sprintf (tmp,"Message append failed: %s",strerror (errno));
969
    mm_log (tmp,ERROR);
970
    ret = NIL;
971
  }
972
  unlink (path1);
973
  
974
  close (fd);			/* close the file */
975
  mm_nocritical (stream);	/* release critical */
976
  fs_give ((void **) &s);	/* flush the buffer */
977
  return ret;
978
}
979
980
short bezerk_getflags (MAILSTREAM *stream,char *flag)
981
{
982
  char *t,tmp[MAILTMPLEN],err[MAILTMPLEN];
983
  short f = 0;
984
  short i,j;
985
  if (flag && *flag) {		/* no-op if no flag string */
986
				/* check if a list and make sure valid */
987
    if ((i = (*flag == '(')) ^ (flag[strlen (flag)-1] == ')')) {
988
      mm_log ("Bad flag list",ERROR);
989
      return NIL;
990
    }
991
				/* copy the flag string w/o list construct */
992
    strncpy (tmp,flag+i,(j = strlen (flag) - (2*i)));
993
    tmp[j] = '\0';
994
    t = ucase (tmp);		/* uppercase only from now on */
995
996
    while (t && *t) {		/* parse the flags */
997
      if (*t == '\\') {		/* system flag? */
998
	switch (*++t) {		/* dispatch based on first character */
999
	case 'S':		/* possible \Seen flag */
1000
	  if (t[1] == 'E' && t[2] == 'E' && t[3] == 'N') i = fSEEN;
1001
	  t += 4;		/* skip past flag name */
1002
	  break;
1003
	case 'D':		/* possible \Deleted flag */
1004
	  if (t[1] == 'E' && t[2] == 'L' && t[3] == 'E' && t[4] == 'T' &&
1005
	      t[5] == 'E' && t[6] == 'D') i = fDELETED;
1006
	  t += 7;		/* skip past flag name */
1007
	  break;
1008
	case 'F':		/* possible \Flagged flag */
1009
	  if (t[1] == 'L' && t[2] == 'A' && t[3] == 'G' && t[4] == 'G' &&
1010
	      t[5] == 'E' && t[6] == 'D') i = fFLAGGED;
1011
	  t += 7;		/* skip past flag name */
1012
	  break;
1013
	case 'A':		/* possible \Answered flag */
1014
	  if (t[1] == 'N' && t[2] == 'S' && t[3] == 'W' && t[4] == 'E' &&
1015
	      t[5] == 'R' && t[6] == 'E' && t[7] == 'D') i = fANSWERED;
1016
	  t += 8;		/* skip past flag name */
1017
	  break;
1018
	default:		/* unknown */
1019
	  i = 0;
1020
	  break;
1021
	}
1022
				/* add flag to flags list */
1023
	if (i && ((*t == '\0') || (*t++ == ' '))) f |= i;
1024
      }
1025
      else {			/* no user flags yet */
1026
	t = strtok (t," ");	/* isolate flag name */
1027
	sprintf (err,"Unknown flag: %.80s",t);
1028
	t = strtok (NIL," ");	/* get next flag */
1029
	mm_log (err,ERROR);
1030
      }
1031
    }
1032
  }
1033
  return f;
1034
}
1035
1036
short maildir_getflags (MAILSTREAM *stream,char *flag)
1037
{
1038
  return bezerk_getflags (stream,flag); /* nothing exciting, reuse old code */
1039
}
1040
1041
long maildir_delete (MAILSTREAM *stream,char *mailbox)
1042
{
1043
  DIR *dirp;
1044
  struct direct *d;
1045
  int i,j;
1046
  char tmp[MAILTMPLEN],err[MAILTMPLEN];
1047
  char *subdir_names[] = {"cur/","new/","tmp/",NULL};
1048
1049
				/* check if mailbox even exists */
1050
  if (!maildir_isvalid (mailbox,NIL)) {
1051
/*    sprintf (tmp,"Can't delete mailbox %s: no such mailbox",mailbox);
1052
    mm_log (tmp,ERROR);
1053
    return NIL; */
1054
    /*syslog(LOG_INFO, "Invalid maildir in delete()"); */
1055
    return T; /* well.. a stupid hack to get by a problem in netscape ..
1056
    		it remembers folders locally, and if a folder is deleted on
1057
    		another machine, you have no way removing it on any other
1058
    		netscapes... */
1059
  }
1060
1061
				/* get name of directory */
1062
  i = strlen (maildir_file (tmp,mailbox)) + 1;
1063
  for (j = 0; subdir_names[j]; j++) {
1064
    strcpy (tmp + i - 4,subdir_names[j]);
1065
    if (dirp = opendir (tmp)) {	/* open directory */
1066
      while (d = readdir (dirp))	/* empty the directory */
1067
	if (strcmp (d->d_name,".") && strcmp (d->d_name,"..")) {
1068
	  strcpy (tmp + i,d->d_name);
1069
	  /*syslog(LOG_INFO, "unlink1: '%s'");*/
1070
	  unlink (tmp);
1071
	}
1072
      closedir (dirp);		/* flush directory */
1073
    }
1074
				/* remove the subdir */
1075
    tmp[i + 3] = '\0';
1076
    /*syslog(LOG_INFO, "tmp: '%s'", tmp);*/
1077
    if (rmdir (tmp)) {
1078
    /*  sprintf (err,"Can't delete directory %s: %s",tmp,strerror (errno));
1079
      mm_log (err,ERROR);*/
1080
    }
1081
  }
1082
1083
				/* try to remove the directory */
1084
  *(tmp + i - 5) = '\0';
1085
  /*syslog(LOG_INFO, "tmp2: '%s'", tmp);*/
1086
  if (rmdir (tmp)) {
1087
/*    sprintf (err,"Can't delete mailbox %s: %s",mailbox,strerror (errno));
1088
    mm_log (err,ERROR);
1089
    return NIL; */
1090
  }
1091
  return T;			/* return success */
1092
}
1093
1094
long maildir_rename (MAILSTREAM *stream,char *old,char *new)
1095
{
1096
  char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN];
1097
1098
				/* old mailbox name must be valid */
1099
  if (!maildir_isvalid (old,NIL)) {
1100
    sprintf (tmp,"Can't rename mailbox %s: no such mailbox",old);
1101
    mm_log (tmp,ERROR);
1102
    return NIL;
1103
  }
1104
1105
				/* new mailbox name must not exist */
1106
  if (access (maildir_file (tmp,new),F_OK) == 0) {
1107
    sprintf (tmp,"Can't rename to mailbox %s: destination already exists",new);
1108
    mm_log (tmp,ERROR);
1109
    return NIL;
1110
  }
1111
1112
				/* try to rename the directory */
1113
  if (rename (maildir_file (tmp,old),maildir_file (tmpnew,new))) {
1114
    sprintf (tmp,"Can't rename mailbox %s to %s: %s",old,new,strerror (errno));
1115
    mm_log (tmp,ERROR);
1116
    return NIL;
1117
  }
1118
  return T;			/* return success */
1119
}
1120
1121
long maildir_sub (MAILSTREAM *stream,char *mailbox)
1122
{
1123
  char tmp[MAILTMPLEN];
1124
  return sm_subscribe (mailbox);
1125
}
1126
1127
long maildir_unsub (MAILSTREAM *stream,char *mailbox)
1128
{
1129
  char tmp[MAILTMPLEN];
1130
  return sm_unsubscribe (mailbox);
1131
}
1132
1133
void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
1134
{
1135
 void *sdb = NIL;
1136
  char *s;
1137
                                /* get canonical form of name */
1138
  if ((s = sm_read (&sdb))) {
1139
    do if (pmatch_full (s,pat,'/')) mm_lsub (stream,'/',s,NIL);
1140
    while (s = sm_read (&sdb)); /* until no more subscriptions */
1141
  }
1142
1143
}
(-)pine4.50/imap/src/osdep/unix/maildir.h (+56 lines)
Line 0 Link Here
1
/*
2
 * Please read maildir.c for license and information
3
 *
4
 */
5
6
#define MAILDIRPATH ".maildir"
7
	
8
typedef struct maildir_local {
9
  unsigned int inbox : 1;	/* if it is an INBOX or not */
10
  unsigned int dirty : 1;	/* diskcopy needs updating */
11
  char *dir;			/* mail directory name */
12
  char *buf;			/* temporary buffer */
13
  char *hdr;			/* current header */
14
  unsigned long buflen;		/* current size of temporary buffer */
15
  time_t scantime;		/* last time directory scanned */
16
} MAILDIRLOCAL;
17
18
/* Convenient access to local data */
19
20
#define LOCAL ((MAILDIRLOCAL *) stream->local)
21
22
/* Function prototypes */
23
24
DRIVER *maildir_valid (char *name);
25
int maildir_isvalid (char *name,long justname);
26
MAILSTREAM *maildir_open (MAILSTREAM *stream);
27
void maildir_gc (MAILSTREAM *stream,long gcflags);
28
void maildir_close (MAILSTREAM *stream, long options);
29
long maildir_ping (MAILSTREAM *stream);
30
long maildir_ping_core (MAILSTREAM *stream);
31
void maildir_check (MAILSTREAM *stream);
32
long maildir_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
33
char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
34
		unsigned long *length, long flags);
35
void maildir_fast (MAILSTREAM *stream,char *sequence,long flags);
36
void maildir_list (MAILSTREAM *stream,char *ref,char *pat);
37
void *maildir_parameters (long function,void *value);
38
long maildir_create (MAILSTREAM *stream,char *mailbox);
39
void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);
40
void maildir_expunge (MAILSTREAM *stream);
41
long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
42
long maildir_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
43
                   STRING *message);
44
short maildir_getflags (MAILSTREAM *stream,char *flag);
45
long maildir_delete (MAILSTREAM *stream,char *mailbox);
46
long maildir_rename (MAILSTREAM *stream,char *old,char *new);
47
long maildir_sub (MAILSTREAM *stream,char *mailbox);
48
long maildir_unsub (MAILSTREAM *stream,char *mailbox);
49
void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat);
50
51
/* utility functions */
52
char *maildir_file (char *dst,char *name);
53
void maildir_copynew (const char *mailbox);
54
int maildir_select (struct direct *name);
55
int maildir_namesort (struct direct **d1,struct direct **d2);
56
void maildir_listwork(char *name, MAILSTREAM *stream, char *s2, char *subdir, int flag);
(-)pine4.53/pine/mailcmd.c (-2 / +1 lines)
Lines 3372-3379 Link Here
3372
	 * the destination folder will need...
3372
	 * the destination folder will need...
3373
	 */
3373
	 */
3374
	context_apply(tmp, context, save_folder, sizeof(tmp));
3374
	context_apply(tmp, context, save_folder, sizeof(tmp));
3375
        save_stream = (stream->dtb->flags & DR_LOCAL) && !IS_REMOTE(tmp) ?
3375
        save_stream = context_same_stream(context, save_folder, stream);
3376
	  stream : context_same_stream(context, save_folder, stream);
3377
    }
3376
    }
3378
3377
3379
    /* if needed, this'll get set in mm_notify */
3378
    /* if needed, this'll get set in mm_notify */
(-)pine4.53/pine/pine.h (-1 / +1 lines)
Lines 63-69 Link Here
63
#ifndef _PINE_INCLUDED
63
#ifndef _PINE_INCLUDED
64
#define _PINE_INCLUDED
64
#define _PINE_INCLUDED
65
65
66
#define PINE_VERSION		"4.58"
66
#define PINE_VERSION		"4.58L0"
67
#define	PHONE_HOME_VERSION	"-count"
67
#define	PHONE_HOME_VERSION	"-count"
68
#define	PHONE_HOME_HOST		"docserver.cac.washington.edu"
68
#define	PHONE_HOME_HOST		"docserver.cac.washington.edu"
69
69

Return to bug 28877