rev |
line source |
yuuji@1
|
1 /*
|
yuuji@1
|
2 * Maildir Module for PINE 4.0x - fourth release, use with CARE!
|
yuuji@1
|
3 *
|
yuuji@1
|
4 * Author: Mattias Larsson <ml@techno.org>
|
yuuji@1
|
5 *
|
yuuji@1
|
6 * Version: 21.07.98
|
yuuji@1
|
7 *
|
yuuji@1
|
8 * Please read the README.maildir file before using this module!
|
yuuji@1
|
9 *
|
yuuji@1
|
10 * If you have any questions, please e-mail ml@techno.org
|
yuuji@1
|
11 *
|
yuuji@1
|
12 * Multiple inboxes patch by Dean Gaudet <dgaudet@arctic.org>
|
yuuji@1
|
13 *
|
yuuji@1
|
14 * =================================================
|
yuuji@1
|
15 *
|
yuuji@1
|
16 * Based on the IMAP2 maildir routines by:
|
yuuji@1
|
17 *
|
yuuji@1
|
18 * Author: Eric Green
|
yuuji@1
|
19 * Bloodhounds International Inc.
|
yuuji@1
|
20 * thrytis@imaxx.net
|
yuuji@1
|
21 *
|
yuuji@1
|
22 * Additional contributions from:
|
yuuji@1
|
23 * Aidas Kasparas (kaspar@soften.ktu.lt)
|
yuuji@1
|
24 *
|
yuuji@1
|
25 * Date: 27 April 1997
|
yuuji@1
|
26 * Last Edited: 13 June 1997
|
yuuji@1
|
27 *
|
yuuji@1
|
28 * Based (heavily) on mh.c and other c-client library files by Mark Crispin:
|
yuuji@1
|
29 *
|
yuuji@1
|
30 * Mark Crispin
|
yuuji@1
|
31 * Networks and Distributed Computing
|
yuuji@1
|
32 * Computing & Communications
|
yuuji@1
|
33 * University of Washington
|
yuuji@1
|
34 * Administration Building, AG-44
|
yuuji@1
|
35 * Seattle, WA 98195
|
yuuji@1
|
36 * Internet: MRC@CAC.Washington.EDU
|
yuuji@1
|
37 *
|
yuuji@1
|
38 * Copyright 1995 by the University of Washington
|
yuuji@1
|
39 *
|
yuuji@1
|
40 * Permission to use, copy, modify, and distribute this software and its
|
yuuji@1
|
41 * documentation for any purpose and without fee is hereby granted, provided
|
yuuji@1
|
42 * that the above copyright notice appears in all copies and that both the
|
yuuji@1
|
43 * above copyright notice and this permission notice appear in supporting
|
yuuji@1
|
44 * documentation, and that the name of the University of Washington not be
|
yuuji@1
|
45 * used in advertising or publicity pertaining to distribution of the software
|
yuuji@1
|
46 * without specific, written prior permission. This software is made
|
yuuji@1
|
47 * available "as is", and
|
yuuji@1
|
48 * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
|
yuuji@1
|
49 * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
|
yuuji@1
|
50 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
|
yuuji@1
|
51 * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
|
yuuji@1
|
52 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
yuuji@1
|
53 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
|
yuuji@1
|
54 * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
|
yuuji@1
|
55 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
yuuji@1
|
56 *
|
yuuji@1
|
57 */
|
yuuji@1
|
58
|
yuuji@1
|
59 /* CONFIGURABLE OPTIONS - PLEASE CHECK THESE OUT */
|
yuuji@1
|
60
|
yuuji@1
|
61 #define NO_MAILDIR_FIDDLE /* disallow Maildir with Maildir in the
|
yuuji@1
|
62 name. This is useful in an ISP setup
|
yuuji@1
|
63 using the IMAP daemon. #undef it if you
|
yuuji@1
|
64 are running a normal pine and know what
|
yuuji@1
|
65 you are doing */
|
yuuji@1
|
66
|
yuuji@1
|
67 /* #define NO_ABSOLUTE_PATHS /* if you define this, all paths
|
yuuji@1
|
68 use your HOMEDIR is the root instead
|
yuuji@1
|
69 of the actual root of the machine. This
|
yuuji@1
|
70 is also useful in an ISP setup with
|
yuuji@1
|
71 IMAP */
|
yuuji@1
|
72
|
yuuji@1
|
73 #undef NO_UID_VALIDITIY /* define this if you want the UID's not
|
yuuji@1
|
74 to be persistent over sessions. Use this
|
yuuji@1
|
75 if you use another client to read the
|
yuuji@1
|
76 maildir that screws up the special way
|
yuuji@1
|
77 in which we store UIDs. Do not enable
|
yuuji@1
|
78 unless you are sure you need it. */
|
yuuji@1
|
79
|
yuuji@1
|
80 /* END CONFIGURATION */
|
yuuji@1
|
81
|
yuuji@1
|
82 #define MTA_DEBUG /* debugging sent to stdout */
|
yuuji@1
|
83 #undef MTA_DEBUG
|
yuuji@1
|
84
|
yuuji@1
|
85 #include <stdio.h>
|
yuuji@1
|
86 #include <ctype.h>
|
yuuji@1
|
87 #include <errno.h>
|
yuuji@1
|
88 extern int errno; /* just in case */
|
yuuji@1
|
89 #include "mail.h"
|
yuuji@1
|
90 #include "osdep.h"
|
yuuji@1
|
91 #include <pwd.h>
|
yuuji@1
|
92 #include <sys/stat.h>
|
yuuji@1
|
93 #include <sys/time.h>
|
yuuji@1
|
94 #include <sys/types.h>
|
yuuji@1
|
95 #include <dirent.h>
|
yuuji@1
|
96 #include <utime.h>
|
yuuji@1
|
97 #include "maildir.h"
|
yuuji@1
|
98 #include "misc.h"
|
yuuji@1
|
99 #include "dummy.h"
|
yuuji@1
|
100
|
yuuji@1
|
101 /* Driver dispatch used by MAIL */
|
yuuji@1
|
102
|
yuuji@1
|
103 DRIVER maildirdriver = {
|
yuuji@1
|
104 "maildir", /* driver name */
|
yuuji@1
|
105 /* driver flags */
|
yuuji@1
|
106 DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE,
|
yuuji@1
|
107 (DRIVER *) NIL, /* next driver */
|
yuuji@1
|
108 maildir_valid, /* mailbox is valid for us */
|
yuuji@1
|
109 maildir_parameters, /* manipulate parameters */
|
yuuji@1
|
110 NIL, /* scan mailboxes */
|
yuuji@1
|
111 maildir_list, /* find mailboxes */
|
yuuji@1
|
112 maildir_lsub, /* find subscribed mailboxes */
|
yuuji@1
|
113 maildir_sub, /* subscribe to mailbox */
|
yuuji@1
|
114 maildir_unsub, /* unsubscribe from mailbox */
|
yuuji@1
|
115 maildir_create, /* create mailbox */
|
yuuji@1
|
116 maildir_delete, /* delete mailbox */
|
yuuji@1
|
117 maildir_rename, /* rename mailbox */
|
yuuji@1
|
118 NIL, /* status of mailbox */
|
yuuji@1
|
119 maildir_open, /* open mailbox */
|
yuuji@1
|
120 maildir_close, /* close mailbox */
|
yuuji@1
|
121 maildir_fast, /* fetch message "fast" attributes */
|
yuuji@1
|
122 NIL, /* fetch message flags */
|
yuuji@1
|
123 NIL, /* fetch overview */
|
yuuji@1
|
124 NIL, /* fetch message envelopes */
|
yuuji@1
|
125 maildir_fetchheader, /* fetch message header */
|
yuuji@1
|
126 maildir_fetchtext, /* fetch message body */
|
yuuji@1
|
127 NIL, /* fetch partial message text */
|
yuuji@1
|
128 NIL, /* unique identifier */
|
yuuji@1
|
129 NIL, /* message number */
|
yuuji@1
|
130 NIL, /* modify flags */
|
yuuji@1
|
131 maildir_flagmsg, /* per-message modify flags */
|
yuuji@1
|
132 NIL, /* search for message based on criteria */
|
yuuji@1
|
133 NIL, /* sort messages */
|
yuuji@1
|
134 NIL, /* thread messages */
|
yuuji@1
|
135 maildir_ping, /* ping mailbox to see if still alive */
|
yuuji@1
|
136 maildir_check, /* check for new messages */
|
yuuji@1
|
137 maildir_expunge, /* expunge deleted messages */
|
yuuji@1
|
138 maildir_copy, /* copy messages to another mailbox */
|
yuuji@1
|
139 maildir_append, /* append string message to mailbox */
|
yuuji@1
|
140 maildir_gc /* garbage collect stream */
|
yuuji@1
|
141 };
|
yuuji@1
|
142
|
yuuji@1
|
143 /* prototype stream */
|
yuuji@1
|
144 MAILSTREAM maildirproto = {&maildirdriver};
|
yuuji@1
|
145
|
yuuji@1
|
146 /* Check validity of mailbox
|
yuuji@1
|
147 */
|
yuuji@1
|
148
|
yuuji@1
|
149 DRIVER *maildir_valid (char *name)
|
yuuji@1
|
150 {
|
yuuji@1
|
151 return maildir_isvalid(name,T) ? &maildirdriver : NIL;
|
yuuji@1
|
152 }
|
yuuji@1
|
153
|
yuuji@1
|
154 int maildir_isvalid (char *name,long justname)
|
yuuji@1
|
155 {
|
yuuji@1
|
156 char tmp[MAILTMPLEN];
|
yuuji@1
|
157 struct stat sbuf;
|
yuuji@1
|
158
|
yuuji@1
|
159 if (!name || (!*name) ||
|
yuuji@1
|
160 ((*name == '#') &&
|
yuuji@1
|
161 (*(name+1) == 0 ||
|
yuuji@1
|
162 (*(name+1) != 'm' && *(name+1) != 'M') ||
|
yuuji@1
|
163 (*(name+2) != 'd' && *(name+1) != 'D') ||
|
yuuji@1
|
164 *(name+3) != '/')) || (*name == '.'))
|
yuuji@1
|
165 return NIL;
|
yuuji@1
|
166
|
yuuji@1
|
167 /* okay, anything containing the name Maildir will be ignored
|
yuuji@1
|
168 this is to prevent anyone from fiddling with their incoming Maildir
|
yuuji@1
|
169 directly, it should be accessed via the INBOX alias */
|
yuuji@1
|
170
|
yuuji@1
|
171 #ifdef NO_MAILDIR_FIDDLE
|
yuuji@1
|
172 if (strstr(name, "Maildir")) {
|
yuuji@1
|
173 return NIL;
|
yuuji@1
|
174 }
|
yuuji@1
|
175 #endif
|
yuuji@1
|
176 /* If we are requested only to check
|
yuuji@1
|
177 if the name is appropriate then we
|
yuuji@1
|
178 have done! */
|
yuuji@1
|
179 if (justname && *name == '#') return T;
|
yuuji@1
|
180
|
yuuji@1
|
181
|
yuuji@1
|
182 /* must be valid local mailbox */
|
yuuji@1
|
183 if ((*name != '*') && (*name != '{') &&
|
yuuji@1
|
184 maildir_file (tmp,name) &&
|
yuuji@1
|
185 /* assume its maildir if its a dir */
|
yuuji@1
|
186 stat (tmp,&sbuf) == 0 && S_ISDIR (sbuf.st_mode))
|
yuuji@1
|
187 return T;
|
yuuji@1
|
188
|
yuuji@1
|
189 /* INBOX is for default Maildir */
|
yuuji@1
|
190 if (!strcmp (ucase (strncpy (tmp,name,MAILTMPLEN)), "INBOX") &&
|
yuuji@1
|
191 (stat (maildir_file (tmp,name),&sbuf) == 0) &&
|
yuuji@1
|
192 S_ISDIR (sbuf.st_mode))
|
yuuji@1
|
193 return T;
|
yuuji@1
|
194
|
yuuji@1
|
195 return NIL;
|
yuuji@1
|
196 }
|
yuuji@1
|
197 #ifdef QMAIL
|
yuuji@1
|
198 #ifndef QMAILCONTROL
|
yuuji@1
|
199 # define QMAILCONTROL "/var/qmail/control"
|
yuuji@1
|
200 #endif
|
yuuji@1
|
201 #ifndef DOTQMAIL
|
yuuji@1
|
202 # ifdef POSTFIX
|
yuuji@1
|
203 # define DOTQMAIL ".forward"
|
yuuji@1
|
204 # else
|
yuuji@1
|
205 # define DOTQMAIL ".qmail"
|
yuuji@1
|
206 # endif
|
yuuji@1
|
207 #endif
|
yuuji@1
|
208 #ifndef XADDR_DELIM
|
yuuji@1
|
209 # ifdef POSTFIX
|
yuuji@1
|
210 # define XADDR_DELIM "+"
|
yuuji@1
|
211 # else
|
yuuji@1
|
212 # define XADDR_DELIM "-"
|
yuuji@1
|
213 # endif
|
yuuji@1
|
214 #endif
|
yuuji@1
|
215
|
yuuji@1
|
216 /* Convert virtual domain user
|
yuuji@1
|
217 */
|
yuuji@1
|
218 char* conv_virtualdomain(char *account) {
|
yuuji@1
|
219 char *dom = strchr(account, '@'), *p;
|
yuuji@1
|
220 char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
|
yuuji@1
|
221 FILE *vdfd;
|
yuuji@1
|
222 int match=0;
|
yuuji@1
|
223 snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
|
yuuji@1
|
224 if (NIL == dom) return account;
|
yuuji@1
|
225 dom++; /* set position of domain part beginning */
|
yuuji@1
|
226 if (dom && NIL != (vdfd = fopen (vd, "r"))) {
|
yuuji@1
|
227 char buf[MAILTMPLEN+1], *s;
|
yuuji@1
|
228 int l = strlen(dom);
|
yuuji@1
|
229 int L = strlen(account);
|
yuuji@1
|
230 while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
|
yuuji@1
|
231 if (p=strchr(s, '#'))
|
yuuji@1
|
232 *p = '\0'; /* zap comments */
|
yuuji@1
|
233 if (!strchr(buf, ':'))
|
yuuji@1
|
234 continue;
|
yuuji@1
|
235 while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
|
yuuji@1
|
236 s[strlen(s)-1] = '\0';
|
yuuji@1
|
237 if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
|
yuuji@1
|
238 match = 3;
|
yuuji@1
|
239 snprintf(rewrite, MAILTMPLEN, "%s%s%s", s+L+1, XADDR_DELIM, account);
|
yuuji@1
|
240 break;
|
yuuji@1
|
241 }
|
yuuji@1
|
242 if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
|
yuuji@1
|
243 match = 2;
|
yuuji@1
|
244 snprintf(rewrite, MAILTMPLEN, "%s%s%s", s+l+1, XADDR_DELIM, account);
|
yuuji@1
|
245 continue;
|
yuuji@1
|
246 }
|
yuuji@1
|
247 if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
|
yuuji@1
|
248 if (p=strchr(s, ':')) {
|
yuuji@1
|
249 *p = '\0';
|
yuuji@1
|
250 if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
|
yuuji@1
|
251 if (match == 0
|
yuuji@1
|
252 || strlen(previous) < strlen(s)) {
|
yuuji@1
|
253 match = 1;
|
yuuji@1
|
254 strncpy(previous, s, MAILTMPLEN);
|
yuuji@1
|
255 snprintf(rewrite, MAILTMPLEN, "%s%s%s", p+1, XADDR_DELIM, account);
|
yuuji@1
|
256 }
|
yuuji@1
|
257 }
|
yuuji@1
|
258 }
|
yuuji@1
|
259 }
|
yuuji@1
|
260 }
|
yuuji@1
|
261 fclose(vdfd);
|
yuuji@1
|
262 if (match) {
|
yuuji@1
|
263 p = strchr(rewrite, '@');
|
yuuji@1
|
264 /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
|
yuuji@1
|
265 if (p) {
|
yuuji@1
|
266 *p = '\0';
|
yuuji@1
|
267 }
|
yuuji@1
|
268 /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
|
yuuji@1
|
269 s = cpystr(rewrite);
|
yuuji@1
|
270 memset(vd, 0, sizeof(vd));
|
yuuji@1
|
271 memset(rewrite, 0, sizeof(rewrite));
|
yuuji@1
|
272 memset(previous, 0, sizeof(previous));
|
yuuji@1
|
273 return s;
|
yuuji@1
|
274 }
|
yuuji@1
|
275 }
|
yuuji@1
|
276 return account; /* return itself */
|
yuuji@1
|
277 }
|
yuuji@1
|
278 /* -------------------------------------------------
|
yuuji@1
|
279 Qmail virtual domain hack ends
|
yuuji@1
|
280 ------------------------------------------------- */
|
yuuji@1
|
281 #endif
|
yuuji@1
|
282
|
yuuji@1
|
283 char *maildir_getmaildir() {
|
yuuji@1
|
284 static char dir[MAILTMPLEN];
|
yuuji@1
|
285 extern char *mymailsuffix();
|
yuuji@1
|
286 static char qfile[MAILTMPLEN];
|
yuuji@1
|
287 FILE *qmail;
|
yuuji@1
|
288 dir[0] = '\0';
|
yuuji@1
|
289 snprintf(qfile, MAILTMPLEN, "%s/%s", myhomedir(), DOTQMAIL);
|
yuuji@1
|
290 strncat(qfile, mymailsuffix(), MAILTMPLEN);
|
yuuji@1
|
291 qmail = fopen(qfile, "r");
|
yuuji@1
|
292 if (NULL != qmail) { /* if ~/.qmail file exists */
|
yuuji@1
|
293 char buf[MAILTMPLEN], *s;
|
yuuji@1
|
294 while ((s=fgets(buf, MAILTMPLEN, qmail))) {
|
yuuji@1
|
295 /* Skip preceding spaces and trailing newlines */
|
yuuji@1
|
296 while (*s && (*s == ' ' || *s == '\t')) {s++;}
|
yuuji@1
|
297 while (*s && (s[strlen(s)-1] == '\r' || s[strlen(s)-1] == '\n')) {
|
yuuji@1
|
298 s[strlen(s)-1] = '\0';
|
yuuji@1
|
299 }
|
yuuji@1
|
300 if (*s == '#') continue;
|
yuuji@1
|
301 if (s[strlen(s)-1] != '/') continue; /* Skip non maildir format */
|
yuuji@1
|
302 if (*s == '~' && *(s+1) == '/')
|
yuuji@1
|
303 *s = '.'; /* Convert `~/' to `./' (for Postfix) */
|
yuuji@1
|
304 strncpy(dir, s, MAILTMPLEN);
|
yuuji@1
|
305 break;
|
yuuji@1
|
306 }
|
yuuji@1
|
307 fclose(qmail);
|
yuuji@1
|
308 }
|
yuuji@1
|
309 #ifdef DEFAULTMAILDIR
|
yuuji@1
|
310 else {
|
yuuji@1
|
311 strncpy(dir, DEFAULTMAILDIR, MAILTMPLEN);
|
yuuji@1
|
312 }
|
yuuji@1
|
313 #endif
|
yuuji@1
|
314 if (dir[0]) {
|
yuuji@1
|
315 return dir;
|
yuuji@1
|
316 } else {
|
yuuji@1
|
317 #ifdef DEFAULTMAILDIR
|
yuuji@1
|
318 snprintf(dir, MAILTMPLEN, "%s/%s/", myhomedir(), DEFAULTMAILDIR);
|
yuuji@1
|
319 #else
|
yuuji@1
|
320 snprintf(dir, MAILTMPLEN, "%s/%s/", myhomedir(), MAILDIRPATH);
|
yuuji@1
|
321 #endif
|
yuuji@1
|
322 return dir;
|
yuuji@1
|
323 }
|
yuuji@1
|
324 }
|
yuuji@1
|
325
|
yuuji@1
|
326 /* Maildir mail generate file string
|
yuuji@1
|
327 */
|
yuuji@1
|
328
|
yuuji@1
|
329 char *maildir_file (char *dst,char *name)
|
yuuji@1
|
330 {
|
yuuji@1
|
331 char tmp[MAILTMPLEN];
|
yuuji@1
|
332
|
yuuji@1
|
333 if (strlen (name) > 3 && /* safe do other comparisons */
|
yuuji@1
|
334 (*name == '#') &&
|
yuuji@1
|
335 (name[1] == 'm' || name[1] == 'M') &&
|
yuuji@1
|
336 (name[2] == 'd' || name[2] == 'D') &&
|
yuuji@1
|
337 (name[3] == '/'))
|
yuuji@1
|
338 name += 4;
|
yuuji@1
|
339
|
yuuji@1
|
340 #ifdef NO_ABSOLUTE_PATHS
|
yuuji@1
|
341 if (*name == '/') {
|
yuuji@1
|
342 /* we do not want to accept / absolute paths, so lets strip the first
|
yuuji@1
|
343 / ... */
|
yuuji@1
|
344 snprintf(dst, MAILTMPLEN, "%s/%s/cur", myhomedir(), name+1);
|
yuuji@1
|
345
|
yuuji@1
|
346 /* strncpy (dst, name, MAILTMPLEN - 2);
|
yuuji@1
|
347 strncat (dst, "/cur", MAILTMPLEN - 2);
|
yuuji@1
|
348 dst[MAILTMPLEN - 1] = '\0'; */
|
yuuji@1
|
349 }
|
yuuji@1
|
350 else
|
yuuji@1
|
351 snprintf (dst, MAILTMPLEN, "%s/%s/cur",myhomedir (),
|
yuuji@1
|
352 strcmp (ucase (strcnpy (tmp, name, MAILTMPLEN)), "INBOX") ? name : maildir_getmaildir());
|
yuuji@1
|
353 #else
|
yuuji@1
|
354 if (*name == '/') {
|
yuuji@1
|
355 strncpy (dst, name, MAILTMPLEN - 2);
|
yuuji@1
|
356 strncat (dst, "/cur", MAILTMPLEN - 2);
|
yuuji@1
|
357 dst[MAILTMPLEN - 1] = '\0';
|
yuuji@1
|
358 }
|
yuuji@1
|
359 else {
|
yuuji@1
|
360 char *maildir = maildir_getmaildir();
|
yuuji@1
|
361 if (*maildir == '/') {
|
yuuji@1
|
362 snprintf (dst,MAILTMPLEN,"%scur",maildir);
|
yuuji@1
|
363 } else {
|
yuuji@1
|
364 snprintf (dst,MAILTMPLEN,"%s/%s/cur",myhomedir (),
|
yuuji@1
|
365 strcmp (ucase (strncpy (tmp, name, MAILTMPLEN)), "INBOX") ? name : maildir);
|
yuuji@1
|
366 }
|
yuuji@1
|
367 }
|
yuuji@1
|
368
|
yuuji@1
|
369 #endif
|
yuuji@1
|
370
|
yuuji@1
|
371 #ifdef MTA_DEBUG
|
yuuji@1
|
372 printf("maildir_file '%s'\n", dst);
|
yuuji@1
|
373 #endif
|
yuuji@1
|
374 return dst;
|
yuuji@1
|
375 }
|
yuuji@1
|
376
|
yuuji@1
|
377 /* Maildir open
|
yuuji@1
|
378 */
|
yuuji@1
|
379
|
yuuji@1
|
380 MAILSTREAM *maildir_open (MAILSTREAM *stream)
|
yuuji@1
|
381 {
|
yuuji@1
|
382 char tmp[MAILTMPLEN],tmp2[MAILTMPLEN];
|
yuuji@1
|
383
|
yuuji@1
|
384 if (!stream) return &maildirproto;
|
yuuji@1
|
385 if (LOCAL) { /* recycle stream */
|
yuuji@1
|
386 maildir_close (stream, 0);
|
yuuji@1
|
387 stream->dtb = &maildirdriver;
|
yuuji@1
|
388 mail_free_cache (stream);
|
yuuji@1
|
389 stream->uid_last = 0; /* default UID validity */
|
yuuji@1
|
390 stream->uid_validity = time (0);
|
yuuji@1
|
391 }
|
yuuji@1
|
392
|
yuuji@1
|
393 stream->uid_validity = 0; /* was time(0) */
|
yuuji@1
|
394
|
yuuji@1
|
395 if (stream->uid_last < time(0))
|
yuuji@1
|
396 stream->uid_last = time (0);
|
yuuji@1
|
397
|
yuuji@1
|
398 stream->local = fs_get (sizeof (MAILDIRLOCAL));
|
yuuji@1
|
399 LOCAL->inbox = !strcmp (ucase (strncpy (tmp,stream->mailbox,MAILTMPLEN)),"INBOX") ||
|
yuuji@1
|
400 !strcmp (stream->mailbox,maildir_file (tmp2,"INBOX"));
|
yuuji@1
|
401 LOCAL->dir = cpystr (maildir_file (tmp,stream->mailbox)); /* copy dir name */
|
yuuji@1
|
402 /* make temporary buffer */
|
yuuji@1
|
403 LOCAL->buf = (char *) fs_get ((LOCAL->buflen = CHUNKSIZE-1) + 1);
|
yuuji@1
|
404 LOCAL->scantime = 0; /* not scanned yet */
|
yuuji@1
|
405 stream->sequence++;
|
yuuji@1
|
406 stream->nmsgs = stream->recent = 0;
|
yuuji@1
|
407
|
yuuji@1
|
408 maildir_ping_core (stream);
|
yuuji@1
|
409 maildir_ping (stream);
|
yuuji@1
|
410 /* if (maildir_ping (stream) && !(stream->nmsgs || stream->silent))
|
yuuji@1
|
411 printf("Mailbox is empty\n");
|
yuuji@1
|
412 */
|
yuuji@1
|
413 return stream;
|
yuuji@1
|
414
|
yuuji@1
|
415 }
|
yuuji@1
|
416
|
yuuji@1
|
417 /* Maildir ping mailbox
|
yuuji@1
|
418 */
|
yuuji@1
|
419
|
yuuji@1
|
420 long maildir_ping_core (MAILSTREAM *stream)
|
yuuji@1
|
421 {
|
yuuji@1
|
422 char tmp[MAILTMPLEN];
|
yuuji@1
|
423 MESSAGECACHE *elt;
|
yuuji@1
|
424 struct stat sbuf, sbuf2;
|
yuuji@1
|
425 DIR *dir;
|
yuuji@1
|
426 struct direct *d;
|
yuuji@1
|
427 int reloadall = NIL;
|
yuuji@1
|
428 int uidinvalid = NIL;
|
yuuji@1
|
429 unsigned long old;
|
yuuji@1
|
430 long i;
|
yuuji@1
|
431 long nmsgs = stream->nmsgs;
|
yuuji@1
|
432 long recent = stream->recent;
|
yuuji@1
|
433 long nfiles = stream->nmsgs;
|
yuuji@1
|
434 int silent = stream->silent;
|
yuuji@1
|
435 char *s, *s2;
|
yuuji@1
|
436 mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
|
yuuji@1
|
437
|
yuuji@1
|
438 /* maildir_copynew (LOCAL->dir);
|
yuuji@1
|
439 */
|
yuuji@1
|
440
|
yuuji@1
|
441 if (stat (LOCAL->dir,&sbuf) < 0) {
|
yuuji@1
|
442 snprintf (tmp,MAILTMPLEN,"Unable to open maildir: %s",strerror (errno));
|
yuuji@1
|
443 mm_log (tmp,ERROR);
|
yuuji@1
|
444 return NIL;
|
yuuji@1
|
445 }
|
yuuji@1
|
446
|
yuuji@1
|
447 /* okay, lets try to figure out the Maildir UID validity. This is done
|
yuuji@1
|
448 by checking the last modification time of the file .uidvalidity
|
yuuji@1
|
449 in the rootdir of the Maildir. Any program reordering the files
|
yuuji@1
|
450 in the directory have to touch this file */
|
yuuji@1
|
451
|
yuuji@1
|
452 snprintf(tmp, MAILTMPLEN, "%s/../.uidvalidity", LOCAL->dir);
|
yuuji@1
|
453
|
yuuji@1
|
454 if (stat (tmp,&sbuf2) < 0) {
|
yuuji@1
|
455 /* no uid validity file found, if uid_validity == 0, we have
|
yuuji@1
|
456 to set it to something other than 0, and then create the
|
yuuji@1
|
457 .uidvalidity file for future accesses */
|
yuuji@1
|
458
|
yuuji@1
|
459 if (stream->uid_validity == 0) {
|
yuuji@1
|
460 FILE *fl;
|
yuuji@1
|
461 struct utimbuf tbuf;
|
yuuji@1
|
462
|
yuuji@1
|
463 stream->uid_validity = time(0);
|
yuuji@1
|
464 tbuf.actime = stream->uid_validity;
|
yuuji@1
|
465 tbuf.modtime = stream->uid_validity;
|
yuuji@1
|
466
|
yuuji@1
|
467 if ((fl = fopen(tmp, "w"))) {
|
yuuji@1
|
468 fclose(fl);
|
yuuji@1
|
469 chmod (tmp, S_IRUSR|S_IWUSR);
|
yuuji@1
|
470 utime(tmp, &tbuf);
|
yuuji@1
|
471 }
|
yuuji@1
|
472 }
|
yuuji@1
|
473 uidinvalid = T; /* UID's are invalid, update them */
|
yuuji@1
|
474 } else {
|
yuuji@1
|
475 /* valid file, lets set UID if uid_validity = 0 */
|
yuuji@1
|
476 if (stream->uid_validity == 0) {
|
yuuji@1
|
477 stream->uid_validity = sbuf2.st_mtime;
|
yuuji@1
|
478 }
|
yuuji@1
|
479 }
|
yuuji@1
|
480
|
yuuji@1
|
481 #ifdef NO_UID_VALIDITY
|
yuuji@1
|
482 uidinvalid = T; /* force the UIDs to be invalid and reset every time,
|
yuuji@1
|
483 useful in an environment without imap servers and
|
yuuji@1
|
484 clients that screw up the UIDs.. i'd leave it to
|
yuuji@1
|
485 OFF until I really need it though... */
|
yuuji@1
|
486 #endif
|
yuuji@1
|
487
|
yuuji@1
|
488 stream->silent = T;
|
yuuji@1
|
489 if (sbuf.st_ctime != LOCAL->scantime) {
|
yuuji@1
|
490 /* update the message list */
|
yuuji@1
|
491 /* int maildir_namesort(const void *,const void *);
|
yuuji@1
|
492 int (*mn)(struct direct **, struct direct **) = maildir_namesort; */
|
yuuji@1
|
493 struct direct **names = NIL;
|
yuuji@1
|
494 nfiles = scandir (LOCAL->dir,&names,maildir_select,maildir_namesort);
|
yuuji@1
|
495
|
yuuji@1
|
496 for (i = 0; i < nfiles; i++) {
|
yuuji@1
|
497
|
yuuji@1
|
498 /* check if file has executable bit set */
|
yuuji@1
|
499 snprintf(tmp, MAILTMPLEN, "%s/%s", LOCAL->dir, names[i]->d_name);
|
yuuji@1
|
500 stat (tmp,&sbuf2);
|
yuuji@1
|
501 if (sbuf2.st_mode & S_IXUSR) {
|
yuuji@1
|
502 /* executable bit set, modtime is uid */
|
yuuji@1
|
503 if (sbuf2.st_mtime > stream->uid_last)
|
yuuji@1
|
504 stream->uid_last = sbuf2.st_mtime+1;
|
yuuji@1
|
505 }
|
yuuji@1
|
506 /* this is kept for backwards compatibility */
|
yuuji@1
|
507 if ((s = strstr (names[i]->d_name,":3,")))
|
yuuji@1
|
508 s += 3;
|
yuuji@1
|
509 if (s && (s2 = strstr (s, ",U"))) {
|
yuuji@1
|
510 s2 += 2;
|
yuuji@1
|
511 sscanf(s2, "%d", &old);
|
yuuji@1
|
512 if (old > stream->uid_last) {
|
yuuji@1
|
513 stream->uid_last = old+1;
|
yuuji@1
|
514 }
|
yuuji@1
|
515 }
|
yuuji@1
|
516
|
yuuji@1
|
517 }
|
yuuji@1
|
518
|
yuuji@1
|
519 mm_critical (stream); /* go critical */
|
yuuji@1
|
520 old = stream->uid_last;
|
yuuji@1
|
521 LOCAL->scantime = sbuf.st_ctime;
|
yuuji@1
|
522
|
yuuji@1
|
523 /* check if old files same */
|
yuuji@1
|
524 for (i = 0; i < stream->nmsgs; i++) {
|
yuuji@1
|
525
|
yuuji@1
|
526 if (strcmp ((char *) mail_elt (stream, i + 1)->maildirp,
|
yuuji@1
|
527 names[i]->d_name)) {
|
yuuji@1
|
528 reloadall = T;
|
yuuji@1
|
529 break;
|
yuuji@1
|
530 }
|
yuuji@1
|
531 }
|
yuuji@1
|
532
|
yuuji@1
|
533 if (reloadall) { /* files are out of order, rebuild cache */
|
yuuji@1
|
534
|
yuuji@1
|
535 i = 1;
|
yuuji@1
|
536 while (i <= stream->nmsgs)
|
yuuji@1
|
537 /* clean out cache */
|
yuuji@1
|
538 if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT))) {
|
yuuji@1
|
539 fs_give ((void **) &elt->maildirp);
|
yuuji@1
|
540 mail_expunged (stream,i);
|
yuuji@1
|
541 }
|
yuuji@1
|
542 else
|
yuuji@1
|
543 i++;
|
yuuji@1
|
544
|
yuuji@1
|
545 mm_log ("Warning: Mailbox has changed in an unexpected way. Reloading.",
|
yuuji@1
|
546 WARN);
|
yuuji@1
|
547 stream->nmsgs = 0;
|
yuuji@1
|
548 }
|
yuuji@1
|
549 nmsgs = stream->nmsgs;
|
yuuji@1
|
550
|
yuuji@1
|
551 stream->nmsgs = nfiles; /* hm? */
|
yuuji@1
|
552
|
yuuji@1
|
553 for (i = nmsgs; i < nfiles; i++) {
|
yuuji@1
|
554
|
yuuji@1
|
555 mail_exists(stream, i+1);
|
yuuji@1
|
556 /* if newly seen, add to list */
|
yuuji@1
|
557 (elt = mail_elt (stream, i + 1))->maildirp = (long) cpystr (names[i]->d_name);
|
yuuji@1
|
558 elt->valid = T;
|
yuuji@1
|
559
|
yuuji@1
|
560 /* grab the flags */
|
yuuji@1
|
561 if ((s = strstr (names[i]->d_name,":3,"))) {
|
yuuji@1
|
562 s += 3;
|
yuuji@1
|
563 if (strchr (s,'F'))
|
yuuji@1
|
564 elt->flagged = T;
|
yuuji@1
|
565 if (strchr (s,'R'))
|
yuuji@1
|
566 elt->answered = T;
|
yuuji@1
|
567 if (strchr (s,'S'))
|
yuuji@1
|
568 elt->seen = T;
|
yuuji@1
|
569 if (strchr (s,'T'))
|
yuuji@1
|
570 elt->deleted = T;
|
yuuji@1
|
571 } else if ((s = strstr (names[i]->d_name,":2,"))) {
|
yuuji@1
|
572 /* this is the :2, id where all files go nowadays */
|
yuuji@1
|
573 s += 3;
|
yuuji@1
|
574 if (strchr (s,'F'))
|
yuuji@1
|
575 elt->flagged = T;
|
yuuji@1
|
576 if (strchr (s,'R'))
|
yuuji@1
|
577 elt->answered = T;
|
yuuji@1
|
578 if (strchr (s,'S'))
|
yuuji@1
|
579 elt->seen = T;
|
yuuji@1
|
580 if (strchr (s,'T'))
|
yuuji@1
|
581 elt->deleted = T;
|
yuuji@1
|
582 snprintf(tmp, MAILTMPLEN, "%s/%s", LOCAL->dir, names[i]->d_name);
|
yuuji@1
|
583 stat (tmp,&sbuf2);
|
yuuji@1
|
584 if (sbuf2.st_mode & S_IXUSR) {
|
yuuji@1
|
585 /* executable bit set, modtime is uid */
|
yuuji@1
|
586 elt->private.uid = sbuf2.st_mtime;
|
yuuji@1
|
587 }
|
yuuji@1
|
588 /* and if we could not retrieve UID from modtime, or if
|
yuuji@1
|
589 UIDs are invalid, go here */
|
yuuji@1
|
590 if (elt->private.uid == 0 || uidinvalid) {
|
yuuji@1
|
591 stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
|
yuuji@1
|
592 maildir_flagmsg(stream, elt);
|
yuuji@1
|
593 }
|
yuuji@1
|
594 s = 0; /* make sure next if statement does not trigger */
|
yuuji@1
|
595 }
|
yuuji@1
|
596
|
yuuji@1
|
597 if (s)
|
yuuji@1
|
598 if ((s2 = strstr (s, ",U"))) {
|
yuuji@1
|
599 s2 += 2;
|
yuuji@1
|
600 sscanf(s2, "%d", &elt->private.uid);
|
yuuji@1
|
601 if (elt->private.uid == 0 || uidinvalid) {
|
yuuji@1
|
602 stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
|
yuuji@1
|
603 maildir_flagmsg(stream, elt);
|
yuuji@1
|
604 }
|
yuuji@1
|
605
|
yuuji@1
|
606 } else { /* assign new UID */
|
yuuji@1
|
607 stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
|
yuuji@1
|
608 elt->recent = T;
|
yuuji@1
|
609 recent++;
|
yuuji@1
|
610 maildir_flagmsg(stream, elt); /* store the UID that we assigned to it */
|
yuuji@1
|
611 }
|
yuuji@1
|
612
|
yuuji@1
|
613
|
yuuji@1
|
614
|
yuuji@1
|
615 }
|
yuuji@1
|
616
|
yuuji@1
|
617 mm_nocritical (stream); /* release critical */
|
yuuji@1
|
618 /* free the names stuff */
|
yuuji@1
|
619 for (i = 0; i < nfiles; i++)
|
yuuji@1
|
620 fs_give ((void **) &names[i]);
|
yuuji@1
|
621 if (names)
|
yuuji@1
|
622 fs_give ((void **) &names);
|
yuuji@1
|
623 }
|
yuuji@1
|
624 stream->silent = silent;
|
yuuji@1
|
625 mail_exists(stream,nfiles);
|
yuuji@1
|
626 /* if (!reloadall) */
|
yuuji@1
|
627 mail_recent (stream,recent);
|
yuuji@1
|
628
|
yuuji@1
|
629 return T; /* return that we are alive */
|
yuuji@1
|
630 }
|
yuuji@1
|
631
|
yuuji@1
|
632 long maildir_ping (MAILSTREAM *stream)
|
yuuji@1
|
633 {
|
yuuji@1
|
634 maildir_copynew (LOCAL->dir);
|
yuuji@1
|
635 return maildir_ping_core (stream);
|
yuuji@1
|
636 }
|
yuuji@1
|
637
|
yuuji@1
|
638 void maildir_copynew (const char *mailbox)
|
yuuji@1
|
639 {
|
yuuji@1
|
640 char tmp[MAILTMPLEN],file[MAILTMPLEN],newfile[MAILTMPLEN];
|
yuuji@1
|
641 DIR *dir;
|
yuuji@1
|
642 struct dirent *d;
|
yuuji@1
|
643 struct stat sbuf;
|
yuuji@1
|
644
|
yuuji@1
|
645 snprintf (tmp,MAILTMPLEN,"%s/../new",mailbox);
|
yuuji@1
|
646 if (!(dir = opendir (tmp)))
|
yuuji@1
|
647 return;
|
yuuji@1
|
648
|
yuuji@1
|
649 while (d = readdir (dir)) {
|
yuuji@1
|
650 if (d->d_name[0] == '.')
|
yuuji@1
|
651 continue; /* skip .files */
|
yuuji@1
|
652
|
yuuji@1
|
653 snprintf (file,MAILTMPLEN,"%s/%s",tmp,d->d_name);
|
yuuji@1
|
654 /* make sure this is a normal file */
|
yuuji@1
|
655 if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)) {
|
yuuji@1
|
656
|
yuuji@1
|
657 if (strstr (d->d_name,":3,")) /* this message already has flags */
|
yuuji@1
|
658 snprintf (newfile,MAILTMPLEN,"%s/%s",mailbox,d->d_name);
|
yuuji@1
|
659 else
|
yuuji@1
|
660 snprintf (newfile,MAILTMPLEN,"%s/%s:3,",mailbox,d->d_name);
|
yuuji@1
|
661
|
yuuji@1
|
662 /* move the new mail to the cur dir */
|
yuuji@1
|
663 if (link (file,newfile) == -1)
|
yuuji@1
|
664 mm_log("Unable to read new mail!",WARN);
|
yuuji@1
|
665 else
|
yuuji@1
|
666 unlink (file);
|
yuuji@1
|
667 }
|
yuuji@1
|
668 }
|
yuuji@1
|
669 closedir (dir);
|
yuuji@1
|
670 }
|
yuuji@1
|
671
|
yuuji@1
|
672 int maildir_select (struct direct *name)
|
yuuji@1
|
673 {
|
yuuji@1
|
674 if (name->d_name[0] != '.')
|
yuuji@1
|
675 return T;
|
yuuji@1
|
676
|
yuuji@1
|
677 return NIL;
|
yuuji@1
|
678 }
|
yuuji@1
|
679
|
yuuji@1
|
680 /* int maildir_namesort (struct direct **d1,struct direct **d2) */
|
yuuji@1
|
681 int maildir_namesort (const void *d1, const void *d2)
|
yuuji@1
|
682 {
|
yuuji@1
|
683 return strcmp ((*(struct direct **)d1)->d_name,
|
yuuji@1
|
684 (*(struct direct **)d2)->d_name);
|
yuuji@1
|
685 }
|
yuuji@1
|
686
|
yuuji@1
|
687
|
yuuji@1
|
688 /* Maildir garbage collect stream
|
yuuji@1
|
689 */
|
yuuji@1
|
690
|
yuuji@1
|
691 void maildir_gc (MAILSTREAM *stream,long gcflags)
|
yuuji@1
|
692 {
|
yuuji@1
|
693 unsigned long i;
|
yuuji@1
|
694
|
yuuji@1
|
695 if (gcflags & GC_TEXTS) { /* garbage collect texts? */
|
yuuji@1
|
696 /* flush texts from cache */
|
yuuji@1
|
697 /* if (LOCAL->hdr) fs_give ((void **) &LOCAL->hdr);
|
yuuji@1
|
698 // if (stream->text) fs_give ((void **) &stream->text);
|
yuuji@1
|
699 // stream->msgno = 0; invalidate stream text
|
yuuji@1
|
700 */
|
yuuji@1
|
701 }
|
yuuji@1
|
702 }
|
yuuji@1
|
703
|
yuuji@1
|
704 /* Maildir close
|
yuuji@1
|
705 */
|
yuuji@1
|
706
|
yuuji@1
|
707 void maildir_close (MAILSTREAM *stream, long options)
|
yuuji@1
|
708 {
|
yuuji@1
|
709 MESSAGECACHE *elt;
|
yuuji@1
|
710 int i;
|
yuuji@1
|
711 mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
|
yuuji@1
|
712
|
yuuji@1
|
713 /* CL_EXPUNGE OPTION SUPPORT HERE SOMEWHERE! */
|
yuuji@1
|
714 /* clean out the cached paths */
|
yuuji@1
|
715 for (i = 1; i <= stream->nmsgs; i++)
|
yuuji@1
|
716 if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp) {
|
yuuji@1
|
717 fs_give ((void **) &elt->maildirp);
|
yuuji@1
|
718 elt->maildirp = 0; /* otherwise pine coredumps */
|
yuuji@1
|
719 }
|
yuuji@1
|
720
|
yuuji@1
|
721 if (LOCAL) { /* only if a stream is open */
|
yuuji@1
|
722 if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
|
yuuji@1
|
723 maildir_gc (stream,GC_TEXTS); /* free local cache */
|
yuuji@1
|
724 /* free local scratch buffer */
|
yuuji@1
|
725 if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
|
yuuji@1
|
726 /* nuke the local data */
|
yuuji@1
|
727 fs_give ((void **) &stream->local);
|
yuuji@1
|
728 stream->dtb = NIL; /* log out the DTB */
|
yuuji@1
|
729 }
|
yuuji@1
|
730 }
|
yuuji@1
|
731
|
yuuji@1
|
732 void maildir_check (MAILSTREAM *stream)
|
yuuji@1
|
733 {
|
yuuji@1
|
734 /* Perhaps in the future this will preserve flags */
|
yuuji@1
|
735 if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);
|
yuuji@1
|
736 }
|
yuuji@1
|
737
|
yuuji@1
|
738 long maildir_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
|
yuuji@1
|
739 {
|
yuuji@1
|
740 unsigned long i;
|
yuuji@1
|
741 MESSAGECACHE *elt;
|
yuuji@1
|
742 /* UID call "impossible" */
|
yuuji@1
|
743 if (flags & FT_UID) return NIL;
|
yuuji@1
|
744 elt = mail_elt (stream,msgno);/* get elt */
|
yuuji@1
|
745 /* snarf message if don't have it yet */
|
yuuji@1
|
746 if (!elt->private.msg.text.text.data) {
|
yuuji@1
|
747 maildir_fetchheader (stream,msgno,&i,flags);
|
yuuji@1
|
748 if (!elt->private.msg.text.text.data) return NIL;
|
yuuji@1
|
749 }
|
yuuji@1
|
750 if (!(flags & FT_PEEK)) { /* mark as seen */
|
yuuji@1
|
751 mail_elt (stream,msgno)->seen = T;
|
yuuji@1
|
752 maildir_flagmsg (stream, mail_elt(stream,msgno));
|
yuuji@1
|
753 mm_flags (stream,msgno);
|
yuuji@1
|
754 }
|
yuuji@1
|
755 if (!elt->private.msg.text.text.data) return NIL;
|
yuuji@1
|
756 INIT (bs,mail_string,elt->private.msg.text.text.data,
|
yuuji@1
|
757 elt->private.msg.text.text.size);
|
yuuji@1
|
758 return T;
|
yuuji@1
|
759 }
|
yuuji@1
|
760
|
yuuji@1
|
761
|
yuuji@1
|
762 /* Maildir fetch message header
|
yuuji@1
|
763 */
|
yuuji@1
|
764
|
yuuji@1
|
765 char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
|
yuuji@1
|
766 unsigned long *length, long flags)
|
yuuji@1
|
767 {
|
yuuji@1
|
768 unsigned long i,hdrsize;
|
yuuji@1
|
769 int fd;
|
yuuji@1
|
770 char *t;
|
yuuji@1
|
771 char tmp[MAILTMPLEN];
|
yuuji@1
|
772 char *s,*b;
|
yuuji@1
|
773 struct stat sbuf;
|
yuuji@1
|
774 struct tm *tm;
|
yuuji@1
|
775 MESSAGECACHE *elt;
|
yuuji@1
|
776 *length = 0; /* default to empty */
|
yuuji@1
|
777 if (flags & FT_UID) return "";/* UID call "impossible" */
|
yuuji@1
|
778 elt = mail_elt (stream,msgno);/* get elt */
|
yuuji@1
|
779 if (!elt->private.msg.header.text.data) {
|
yuuji@1
|
780
|
yuuji@1
|
781 /* maildir_gc (stream,GC_TEXTS); invalidate current cache */
|
yuuji@1
|
782 /* build message file name */
|
yuuji@1
|
783 snprintf (tmp,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
|
yuuji@1
|
784 if ((fd = open (tmp,O_RDONLY,NIL)) >= 0) {
|
yuuji@1
|
785 fstat (fd,&sbuf); /* get size of message */
|
yuuji@1
|
786 /* make plausible IMAPish date string */
|
yuuji@1
|
787 tm = gmtime (&sbuf.st_mtime);
|
yuuji@1
|
788 elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
|
yuuji@1
|
789 elt->year = tm->tm_year + 1900 - BASEYEAR;
|
yuuji@1
|
790 elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
|
yuuji@1
|
791 elt->seconds = tm->tm_sec;
|
yuuji@1
|
792 elt->zhours = 0; elt->zminutes = 0;
|
yuuji@1
|
793 /* slurp message */
|
yuuji@1
|
794 read (fd,s = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);
|
yuuji@1
|
795 s[sbuf.st_size] = '\0'; /* tie off file */
|
yuuji@1
|
796 close (fd); /* close file */
|
yuuji@1
|
797
|
yuuji@1
|
798 for (i = 0,b = s; *b && !(i && (*b == '\n')); i = (*b++ == '\n'));
|
yuuji@1
|
799 hdrsize = (*b ? ++b:b)-s; /* number of header bytes */
|
yuuji@1
|
800
|
yuuji@1
|
801 elt->rfc822_size = /* size of entire message in CRLF form */
|
yuuji@1
|
802 (elt->private.msg.header.text.size =
|
yuuji@1
|
803 strcrlfcpy ((char **) &elt->private.msg.header.text.data,&i,s,
|
yuuji@1
|
804 hdrsize)) +
|
yuuji@1
|
805 (elt->private.msg.text.text.size =
|
yuuji@1
|
806 strcrlfcpy ((char **) &elt->private.msg.text.text.data,&i,b,
|
yuuji@1
|
807 sbuf.st_size - hdrsize));
|
yuuji@1
|
808 fs_give ((void **) &s);
|
yuuji@1
|
809 } else return "";
|
yuuji@1
|
810
|
yuuji@1
|
811 }
|
yuuji@1
|
812
|
yuuji@1
|
813 *length = elt->private.msg.header.text.size;
|
yuuji@1
|
814 return (char *) elt->private.msg.header.text.data;
|
yuuji@1
|
815 }
|
yuuji@1
|
816
|
yuuji@1
|
817 void maildir_fast (MAILSTREAM *stream,char *sequence,long flags)
|
yuuji@1
|
818 {
|
yuuji@1
|
819 unsigned long i,j;
|
yuuji@1
|
820 /* ugly and slow */
|
yuuji@1
|
821 if (stream && LOCAL && ((flags & FT_UID) ?
|
yuuji@1
|
822 mail_uid_sequence (stream,sequence) :
|
yuuji@1
|
823 mail_sequence (stream,sequence)))
|
yuuji@1
|
824 for (i = 1; i <= stream->nmsgs; i++)
|
yuuji@1
|
825 if (mail_elt (stream,i)->sequence) maildir_fetchheader (stream,i,&j,NIL);
|
yuuji@1
|
826 }
|
yuuji@1
|
827
|
yuuji@1
|
828 /* Maildir find list of subscribed mailboxes
|
yuuji@1
|
829 * Accepts: mail stream
|
yuuji@1
|
830 * pattern to search
|
yuuji@1
|
831 */
|
yuuji@1
|
832
|
yuuji@1
|
833 void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
|
yuuji@1
|
834 {
|
yuuji@1
|
835 DIR *dp;
|
yuuji@1
|
836 struct direct *d;
|
yuuji@1
|
837 struct stat sbuf;
|
yuuji@1
|
838 char *s,*s2,*cp,*np,curdir[MAILTMPLEN],name[MAILTMPLEN],subdir[MAILTMPLEN],rname[MAILTMPLEN];
|
yuuji@1
|
839
|
yuuji@1
|
840 strncpy(subdir, pat, MAILTMPLEN);
|
yuuji@1
|
841
|
yuuji@1
|
842 s = subdir;
|
yuuji@1
|
843 s2 = 0;
|
yuuji@1
|
844 while ((s = strstr(s, "/"))) {
|
yuuji@1
|
845 s2 = s;
|
yuuji@1
|
846 s++;
|
yuuji@1
|
847 }
|
yuuji@1
|
848
|
yuuji@1
|
849 if (s2) { /* pointer to last / */
|
yuuji@1
|
850 *s2 = '\0'; /* snip off string */
|
yuuji@1
|
851 s2++;
|
yuuji@1
|
852 /*syslog(LOG_INFO, "dir: '%s' pat: '%s'", subdir, s2);*/
|
yuuji@1
|
853 snprintf(name, MAILTMPLEN, "%s/%s", myhomedir(), subdir);
|
yuuji@1
|
854 } else {
|
yuuji@1
|
855 s2 = pat;
|
yuuji@1
|
856 snprintf(name, MAILTMPLEN, "%s", myhomedir());
|
yuuji@1
|
857 strcpy(subdir, "");
|
yuuji@1
|
858 }
|
yuuji@1
|
859
|
yuuji@1
|
860 maildir_listwork(name, stream, s2, subdir, 1);
|
yuuji@1
|
861
|
yuuji@1
|
862 if (pmatch ("INBOX", pat))
|
yuuji@1
|
863 mm_list (stream,NIL,"INBOX",LATT_NOINFERIORS);
|
yuuji@1
|
864
|
yuuji@1
|
865 }
|
yuuji@1
|
866
|
yuuji@1
|
867 void maildir_listwork(char *name1, MAILSTREAM *stream, char *s2, char *subdir, int flag)
|
yuuji@1
|
868 {
|
yuuji@1
|
869 DIR *dp;
|
yuuji@1
|
870 struct direct *d;
|
yuuji@1
|
871 struct stat sbuf;
|
yuuji@1
|
872 char *s,*cp,*np,curdir[MAILTMPLEN],rname[MAILTMPLEN],name[MAILTMPLEN];
|
yuuji@1
|
873 char tmpdir[MAILTMPLEN];
|
yuuji@1
|
874
|
yuuji@1
|
875 strncpy(name, name1, MAILTMPLEN);
|
yuuji@1
|
876
|
yuuji@1
|
877 /*syslog(LOG_INFO, "opendir: '%s'", name);
|
yuuji@1
|
878 //syslog(LOG_INFO, "subdir: '%s'", subdir);
|
yuuji@1
|
879 */
|
yuuji@1
|
880 if (dp = opendir (name)) { /* open directory */
|
yuuji@1
|
881 while (d = readdir (dp)) /* scan directory, ignore all . names */
|
yuuji@1
|
882 if (d->d_name[0] != '.' &&
|
yuuji@1
|
883 strcmp(d->d_name, "Maildir")) {/* build file name */
|
yuuji@1
|
884 /* we do not want to list Maildir to customers, because
|
yuuji@1
|
885 that might give them weird ideas :) */
|
yuuji@1
|
886
|
yuuji@1
|
887 if (subdir[0] != '\0' && subdir[0] != '%' && subdir[0] != '*')
|
yuuji@1
|
888 snprintf(name, MAILTMPLEN, "%s/%s", subdir, d->d_name);
|
yuuji@1
|
889 else
|
yuuji@1
|
890 snprintf(name, MAILTMPLEN, "%s", d->d_name);
|
yuuji@1
|
891 /*syslog(LOG_INFO, "ls: '%s'", name);*/
|
yuuji@1
|
892
|
yuuji@1
|
893 /* this matching might not be correctly implemented */
|
yuuji@1
|
894 if (maildir_file(curdir, name) &&
|
yuuji@1
|
895 stat (curdir,&sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
|
yuuji@1
|
896 /*syslog(LOG_INFO, "here for some stange reason");*/
|
yuuji@1
|
897 if (pmatch(d->d_name, s2)) {
|
yuuji@1
|
898 mm_list (stream,'/',name,NIL);
|
yuuji@1
|
899 /* call function recursive if last char % */
|
yuuji@1
|
900 /*syslog(LOG_INFO, "s2: '%s'",s2);*/
|
yuuji@1
|
901 if (s2[strlen(s2)-1] == '%'
|
yuuji@1
|
902 || s2[strlen(s2)-1] == '*') {
|
yuuji@1
|
903 snprintf(rname, MAILTMPLEN, "%s/%s", name1, name);
|
yuuji@1
|
904 /*syslog(LOG_INFO, "rname: '%s'", rname);*/
|
yuuji@1
|
905 maildir_listwork(rname, stream, "%", name, 1);
|
yuuji@1
|
906 }
|
yuuji@1
|
907 }
|
yuuji@1
|
908 } else
|
yuuji@1
|
909 if (strlen(curdir) > 4 && pmatch(d->d_name, s2)) {
|
yuuji@1
|
910 int fnlen = strlen (curdir);
|
yuuji@1
|
911 curdir[fnlen - 4] = '\0';
|
yuuji@1
|
912 /*syslog(LOG_INFO, "fname: '%s'", curdir);*/
|
yuuji@1
|
913 if (stat (curdir,&sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
|
yuuji@1
|
914 /* okay, do not list with NoSelect, since Netscape
|
yuuji@1
|
915 does not f*cking honor this flag.. stupid netscape */
|
yuuji@1
|
916 /*mm_list (stream,'/',name,LATT_NOSELECT);*/
|
yuuji@1
|
917
|
yuuji@1
|
918 /* call function recursive if last char % */
|
yuuji@1
|
919 /*syslog(LOG_INFO, "s2: '%s'",s2);*/
|
yuuji@1
|
920 if (s2[strlen(s2)-1] == '%'
|
yuuji@1
|
921 || s2[strlen(s2)-1] == '*') {
|
yuuji@1
|
922 snprintf(rname, MAILTMPLEN, "%s/%s", name1, name);
|
yuuji@1
|
923 /*syslog(LOG_INFO, "rname: '%s'", rname);*/
|
yuuji@1
|
924 maildir_listwork(rname, stream, "%", name, 1);
|
yuuji@1
|
925 }
|
yuuji@1
|
926
|
yuuji@1
|
927 }
|
yuuji@1
|
928 }
|
yuuji@1
|
929
|
yuuji@1
|
930 }
|
yuuji@1
|
931 closedir (dp); /* all done, flush directory */
|
yuuji@1
|
932 }
|
yuuji@1
|
933
|
yuuji@1
|
934 }
|
yuuji@1
|
935
|
yuuji@1
|
936
|
yuuji@1
|
937
|
yuuji@1
|
938
|
yuuji@1
|
939
|
yuuji@1
|
940 void *maildir_parameters (long function,void *value)
|
yuuji@1
|
941 {
|
yuuji@1
|
942 return NIL;
|
yuuji@1
|
943 }
|
yuuji@1
|
944
|
yuuji@1
|
945 long maildir_create (MAILSTREAM *stream,char *mailbox)
|
yuuji@1
|
946 {
|
yuuji@1
|
947 char tmp[MAILTMPLEN];
|
yuuji@1
|
948 char err[MAILTMPLEN];
|
yuuji@1
|
949 char *s, *s2;
|
yuuji@1
|
950 int fnlen, i;
|
yuuji@1
|
951 char *subdir_names[] = {"/cur","/new","/tmp",NULL};
|
yuuji@1
|
952
|
yuuji@1
|
953 /* must not already exist */
|
yuuji@1
|
954 if (access (maildir_file (tmp,mailbox),F_OK) == 0) {
|
yuuji@1
|
955 snprintf (err,MAILTMPLEN,"Can't create mailbox %s: mailbox already exists",mailbox);
|
yuuji@1
|
956 mm_log (err,ERROR);
|
yuuji@1
|
957 return NIL;
|
yuuji@1
|
958 }
|
yuuji@1
|
959
|
yuuji@1
|
960 maildir_file (tmp,mailbox); /* get file name */
|
yuuji@1
|
961 fnlen = strlen (tmp);
|
yuuji@1
|
962 /*syslog(LOG_INFO, "fname: '%s'", tmp);*/
|
yuuji@1
|
963 tmp[fnlen - 4] = '\0'; /* making main directory's name */
|
yuuji@1
|
964 fnlen -= 4;
|
yuuji@1
|
965
|
yuuji@1
|
966 /* okay, try to add support for adding hiearchys of directories, this
|
yuuji@1
|
967 is done by scanning for /'s.... */
|
yuuji@1
|
968
|
yuuji@1
|
969 /*syslog(LOG_INFO, "tmp '%s'", tmp);*/
|
yuuji@1
|
970 s = tmp;
|
yuuji@1
|
971
|
yuuji@1
|
972 while ((s = strstr(s, "/")) != 0) {
|
yuuji@1
|
973 /*syslog(LOG_INFO, "Before make: '%s'", s);*/
|
yuuji@1
|
974 *s = '\0';
|
yuuji@1
|
975 /*syslog(LOG_INFO, "Trying to make: '%s'", tmp);*/
|
yuuji@1
|
976 if (mkdir (tmp,0700) && *s != '\0') /* trying to make the dir */
|
yuuji@1
|
977 if (errno != EEXIST) {
|
yuuji@1
|
978 snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
|
yuuji@1
|
979 mailbox,tmp,strerror (errno));
|
yuuji@1
|
980 mm_log (err,ERROR);
|
yuuji@1
|
981 return NIL;
|
yuuji@1
|
982 }
|
yuuji@1
|
983 *s = '/';
|
yuuji@1
|
984 s++;
|
yuuji@1
|
985 }
|
yuuji@1
|
986
|
yuuji@1
|
987 if (mkdir (tmp,0700)) { /* try to make new dir */
|
yuuji@1
|
988 snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
|
yuuji@1
|
989 mailbox,tmp,strerror (errno));
|
yuuji@1
|
990 mm_log (err,ERROR);
|
yuuji@1
|
991 return NIL;
|
yuuji@1
|
992 }
|
yuuji@1
|
993
|
yuuji@1
|
994 /*syslog(LOG_INFO, "create maildir");*/
|
yuuji@1
|
995 for (i = 0; subdir_names[i]; i++) {
|
yuuji@1
|
996 strncpy (tmp + fnlen,subdir_names[i],MAILTMPLEN);
|
yuuji@1
|
997
|
yuuji@1
|
998 if (mkdir (tmp,0700)) { /* try to make new dir */
|
yuuji@1
|
999 snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
|
yuuji@1
|
1000 mailbox,tmp,strerror (errno));
|
yuuji@1
|
1001 mm_log (err,ERROR);
|
yuuji@1
|
1002 return NIL;
|
yuuji@1
|
1003 }
|
yuuji@1
|
1004 }
|
yuuji@1
|
1005
|
yuuji@1
|
1006 return T; /* return success */
|
yuuji@1
|
1007 }
|
yuuji@1
|
1008
|
yuuji@1
|
1009 void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
|
yuuji@1
|
1010 {
|
yuuji@1
|
1011 char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN];
|
yuuji@1
|
1012 struct utimbuf tbuf;
|
yuuji@1
|
1013 char *s;
|
yuuji@1
|
1014
|
yuuji@1
|
1015 /* build the new filename */
|
yuuji@1
|
1016 snprintf (oldfile,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
|
yuuji@1
|
1017 if ((s = strchr ((char *) elt->maildirp,':'))) *s = '\0';
|
yuuji@1
|
1018 snprintf (fn,MAILTMPLEN,"%s:2,%s%s%s%s",(char *) elt->maildirp,elt->flagged ? "F" : "",
|
yuuji@1
|
1019 elt->answered ? "R" : "",elt->seen ? "S" : "",
|
yuuji@1
|
1020 elt->deleted ? "T" : "");
|
yuuji@1
|
1021 snprintf (newfile,MAILTMPLEN,"%s/%s",LOCAL->dir,fn);
|
yuuji@1
|
1022 /* rename the file with new flags */
|
yuuji@1
|
1023 if (rename (oldfile,newfile) < 0) {
|
yuuji@1
|
1024 snprintf(oldfile,MAILTMPLEN,"Unable to write flags to disk: %s",strerror (errno));
|
yuuji@1
|
1025 mm_log(oldfile,ERROR);
|
yuuji@1
|
1026 return;
|
yuuji@1
|
1027 }
|
yuuji@1
|
1028 /* update the file name in cache */
|
yuuji@1
|
1029 fs_give ((void **) &elt->maildirp);
|
yuuji@1
|
1030 elt->maildirp = (long) cpystr (fn);
|
yuuji@1
|
1031
|
yuuji@1
|
1032 /* fix the UID on the file */
|
yuuji@1
|
1033 tbuf.actime = elt->private.uid;
|
yuuji@1
|
1034 tbuf.modtime = elt->private.uid;
|
yuuji@1
|
1035 chmod (newfile, S_IRUSR|S_IWUSR|S_IXUSR);
|
yuuji@1
|
1036 utime (newfile, &tbuf);
|
yuuji@1
|
1037
|
yuuji@1
|
1038 }
|
yuuji@1
|
1039
|
yuuji@1
|
1040 void maildir_expunge (MAILSTREAM *stream)
|
yuuji@1
|
1041 {
|
yuuji@1
|
1042 MESSAGECACHE *elt;
|
yuuji@1
|
1043 unsigned long i = 1;
|
yuuji@1
|
1044 unsigned long n = 0;
|
yuuji@1
|
1045 unsigned long recent = stream->recent;
|
yuuji@1
|
1046
|
yuuji@1
|
1047 maildir_gc (stream,GC_TEXTS); /* invalidate texts */
|
yuuji@1
|
1048 mm_critical (stream); /* go critical */
|
yuuji@1
|
1049 while (i <= stream->nmsgs) { /* for each message */
|
yuuji@1
|
1050 /* if deleted, need to trash it */
|
yuuji@1
|
1051 if ((elt = mail_elt (stream,i))->deleted) {
|
yuuji@1
|
1052 snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
|
yuuji@1
|
1053 if (unlink (LOCAL->buf)) {/* try to delete the message */
|
yuuji@1
|
1054 snprintf (LOCAL->buf,MAILTMPLEN,"Expunge of message %ld failed, aborted: %s",i,
|
yuuji@1
|
1055 strerror (errno));
|
yuuji@1
|
1056 mm_log (LOCAL->buf,WARN);
|
yuuji@1
|
1057 break;
|
yuuji@1
|
1058 }
|
yuuji@1
|
1059 /* free the cached filename */
|
yuuji@1
|
1060 if (elt->maildirp) {
|
yuuji@1
|
1061 fs_give ((void **) &elt->maildirp);
|
yuuji@1
|
1062 elt->maildirp = 0; /* otherwise pine coredumps */
|
yuuji@1
|
1063 }
|
yuuji@1
|
1064 if (elt->recent) --recent;/* if recent, note one less recent message */
|
yuuji@1
|
1065 mail_expunged (stream,i); /* notify upper levels */
|
yuuji@1
|
1066 n++; /* count up one more expunged message */
|
yuuji@1
|
1067 }
|
yuuji@1
|
1068 else i++; /* otherwise try next message */
|
yuuji@1
|
1069 }
|
yuuji@1
|
1070 if (n) { /* output the news if any expunged */
|
yuuji@1
|
1071 snprintf (LOCAL->buf,MAILTMPLEN,"Expunged %ld messages",n);
|
yuuji@1
|
1072 mm_log (LOCAL->buf,(long) NIL);
|
yuuji@1
|
1073 }
|
yuuji@1
|
1074 else mm_log ("No messages deleted, so no update needed",(long) NIL);
|
yuuji@1
|
1075 mm_nocritical (stream); /* release critical */
|
yuuji@1
|
1076 /* notify upper level of new mailbox size */
|
yuuji@1
|
1077 mail_exists (stream,stream->nmsgs);
|
yuuji@1
|
1078 mail_recent (stream,recent);
|
yuuji@1
|
1079 }
|
yuuji@1
|
1080
|
yuuji@1
|
1081 /* dont forget to process options in here */
|
yuuji@1
|
1082
|
yuuji@1
|
1083 /* modified by sakira@sundent.mine.nu (03.01.13) */
|
yuuji@1
|
1084 long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
|
yuuji@1
|
1085 {
|
yuuji@1
|
1086 STRING st;
|
yuuji@1
|
1087 MESSAGECACHE *elt;
|
yuuji@1
|
1088 struct stat sbuf;
|
yuuji@1
|
1089 int fd;
|
yuuji@1
|
1090 unsigned long i;
|
yuuji@1
|
1091 char flags[MAILTMPLEN], date[MAILTMPLEN];
|
yuuji@1
|
1092
|
yuuji@1
|
1093 /* copy the messages */
|
yuuji@1
|
1094 if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) :
|
yuuji@1
|
1095 mail_sequence (stream,sequence))
|
yuuji@1
|
1096 for (i = 1; i <= stream->nmsgs; i++)
|
yuuji@1
|
1097 if ((elt = mail_elt (stream,i))->sequence) {
|
yuuji@1
|
1098 sprintf (LOCAL->buf, "%s/%s", LOCAL->dir, (char *) elt->maildirp);
|
yuuji@1
|
1099 /* snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp); */
|
yuuji@1
|
1100 if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
|
yuuji@1
|
1101 fstat (fd,&sbuf); /* get size of message */
|
yuuji@1
|
1102
|
yuuji@1
|
1103 if (!elt->day) {
|
yuuji@1
|
1104 struct tm *tm = gmtime (&sbuf.st_mtime);
|
yuuji@1
|
1105 elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
|
yuuji@1
|
1106 elt->year = tm->tm_year + 1900 - BASEYEAR;
|
yuuji@1
|
1107 elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
|
yuuji@1
|
1108 elt->seconds = tm->tm_sec;
|
yuuji@1
|
1109 elt->zhours = 0; elt->zminutes = 0;
|
yuuji@1
|
1110 }
|
yuuji@1
|
1111
|
yuuji@1
|
1112 if (sbuf.st_size > LOCAL->buflen) {
|
yuuji@1
|
1113 fs_give((void **) &LOCAL->buf);
|
yuuji@1
|
1114 LOCAL->buf = (char *) fs_get ((LOCAL->buflen = sbuf.st_size) + 1);
|
yuuji@1
|
1115 }
|
yuuji@1
|
1116
|
yuuji@1
|
1117 /* slurp message */
|
yuuji@1
|
1118 read(fd, LOCAL->buf, sbuf.st_size);
|
yuuji@1
|
1119 LOCAL->buf[sbuf.st_size] = '\0';
|
yuuji@1
|
1120 close(fd);
|
yuuji@1
|
1121 /* read (fd, s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size);
|
yuuji@1
|
1122 s[sbuf.st_size] = '\0';
|
yuuji@1
|
1123 close (fd); */
|
yuuji@1
|
1124
|
yuuji@1
|
1125 INIT (&st,mail_string,(void *) LOCAL->buf,sbuf.st_size);
|
yuuji@1
|
1126 flags[0] = flags[1] = '\0';
|
yuuji@1
|
1127 if (elt->seen) strcat(flags, " \\Seen");
|
yuuji@1
|
1128 if (elt->deleted) strcat(flags, " \\Deleted");
|
yuuji@1
|
1129 if (elt->answered) strcat(flags, " \\Answered");
|
yuuji@1
|
1130 if (elt->draft) strcat(flags, " \\Draft");
|
yuuji@1
|
1131 flags[0] = '(';
|
yuuji@1
|
1132 strcat(flags, ")");
|
yuuji@1
|
1133 mail_date(date, elt);
|
yuuji@1
|
1134 /* snprintf (LOCAL->buf,MAILTMPLEN,"%s%s%s%s%s)",
|
yuuji@1
|
1135 elt->seen ? " \\Seen" : "",
|
yuuji@1
|
1136 elt->deleted ? " \\Deleted" : "",
|
yuuji@1
|
1137 elt->flagged ? " \\Flagged" : "",
|
yuuji@1
|
1138 elt->answered ? " \\Answered" : "",
|
yuuji@1
|
1139 (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
|
yuuji@1
|
1140 "" : " ");
|
yuuji@1
|
1141 LOCAL->buf[0] = '(';
|
yuuji@1
|
1142 mail_date (tmp,elt); */
|
yuuji@1
|
1143
|
yuuji@1
|
1144 if (!mail_append_full (NIL, mailbox, flags, date, &st)) return NIL;
|
yuuji@1
|
1145 if (options & CP_MOVE) elt->deleted = T;
|
yuuji@1
|
1146
|
yuuji@1
|
1147 /* if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
|
yuuji@1
|
1148 fs_give ((void **) &s);
|
yuuji@1
|
1149 return NIL;
|
yuuji@1
|
1150 } */
|
yuuji@1
|
1151 /* fs_give ((void **) &s); */ /* give back temporary space */
|
yuuji@1
|
1152 }
|
yuuji@1
|
1153 return T; /* return success */
|
yuuji@1
|
1154 }
|
yuuji@1
|
1155
|
yuuji@1
|
1156 #if 0
|
yuuji@1
|
1157 long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
|
yuuji@1
|
1158 {
|
yuuji@1
|
1159 STRING st;
|
yuuji@1
|
1160 MESSAGECACHE *elt;
|
yuuji@1
|
1161 struct stat sbuf;
|
yuuji@1
|
1162 int fd;
|
yuuji@1
|
1163 long i;
|
yuuji@1
|
1164 char *s,tmp[MAILTMPLEN];
|
yuuji@1
|
1165 /* copy the messages */
|
yuuji@1
|
1166 if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) :
|
yuuji@1
|
1167 mail_sequence (stream,sequence))
|
yuuji@1
|
1168 for (i = 1; i <= stream->nmsgs; i++)
|
yuuji@1
|
1169 if ((elt = mail_elt (stream,i))->sequence) {
|
yuuji@1
|
1170 snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
|
yuuji@1
|
1171 if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
|
yuuji@1
|
1172 fstat (fd,&sbuf); /* get size of message */
|
yuuji@1
|
1173 /* slurp message */
|
yuuji@1
|
1174 read (fd,s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size);
|
yuuji@1
|
1175 s[sbuf.st_size] = '\0'; /* tie off file */
|
yuuji@1
|
1176 close (fd); /* flush message file */
|
yuuji@1
|
1177 INIT (&st,mail_string,(void *) s,sbuf.st_size);
|
yuuji@1
|
1178 snprintf (LOCAL->buf,MAILTMPLEN,"%s%s%s%s%s)",
|
yuuji@1
|
1179 elt->seen ? " \\Seen" : "",
|
yuuji@1
|
1180 elt->deleted ? " \\Deleted" : "",
|
yuuji@1
|
1181 elt->flagged ? " \\Flagged" : "",
|
yuuji@1
|
1182 elt->answered ? " \\Answered" : "",
|
yuuji@1
|
1183 (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
|
yuuji@1
|
1184 "" : " ");
|
yuuji@1
|
1185 LOCAL->buf[0] = '('; /* open list */
|
yuuji@1
|
1186 mail_date (tmp,elt); /* generate internal date */
|
yuuji@1
|
1187 if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
|
yuuji@1
|
1188 fs_give ((void **) &s); /* give back temporary space */
|
yuuji@1
|
1189 return NIL;
|
yuuji@1
|
1190 }
|
yuuji@1
|
1191 fs_give ((void **) &s); /* give back temporary space */
|
yuuji@1
|
1192 }
|
yuuji@1
|
1193 return T; /* return success */
|
yuuji@1
|
1194 }
|
yuuji@1
|
1195 #endif
|
yuuji@1
|
1196
|
yuuji@1
|
1197 long maildir_append (MAILSTREAM *stream, char *mailbox, append_t af, void *data)
|
yuuji@1
|
1198 {
|
yuuji@1
|
1199 int fd;
|
yuuji@1
|
1200 char c, *s;
|
yuuji@1
|
1201 char *flags, *date;
|
yuuji@1
|
1202 char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
|
yuuji@1
|
1203 MESSAGECACHE elt;
|
yuuji@1
|
1204 STRING *message;
|
yuuji@1
|
1205 long i;
|
yuuji@1
|
1206 long size = 0;
|
yuuji@1
|
1207 long ret = LONGT;
|
yuuji@1
|
1208 short uf = 0;
|
yuuji@1
|
1209
|
yuuji@1
|
1210 /*
|
yuuji@1
|
1211 This is intentionaly made static. Users can ask to save a LOT of messages
|
yuuji@1
|
1212 at once and this program can do that within one second. Dan's assumption
|
yuuji@1
|
1213 that time+pid+hostname always will be unique stops being true in this
|
yuuji@1
|
1214 case. So we will add yet another number to host part of message file's
|
yuuji@1
|
1215 name. Hostname is used only to make filename unique and Dan explicitly
|
yuuji@1
|
1216 says that "<...> Other than this [skipping filenames starting at dot] ,
|
yuuji@1
|
1217 readers should not attempt to parse filenames. <...>". Therefore this
|
yuuji@1
|
1218 addition should be no problem. Am I right, Dan? --AK
|
yuuji@1
|
1219 */
|
yuuji@1
|
1220
|
yuuji@1
|
1221 static unsigned int transact = 0;
|
yuuji@1
|
1222
|
yuuji@1
|
1223 if (!stream) stream = &maildirproto;
|
yuuji@1
|
1224
|
yuuji@1
|
1225 if (flags) /* get flags if given */
|
yuuji@1
|
1226 uf = maildir_getflags (user_flags (&maildirproto),flags);
|
yuuji@1
|
1227
|
yuuji@1
|
1228 /* N.B.: can't use LOCAL->buf for tmp */
|
yuuji@1
|
1229 /* make sure valid mailbox */
|
yuuji@1
|
1230 if (!maildir_isvalid (mailbox, NIL)) {
|
yuuji@1
|
1231 snprintf (tmp,MAILTMPLEN,"Not a valid Maildir mailbox: %s",mailbox);
|
yuuji@1
|
1232 mm_log (tmp,ERROR);
|
yuuji@1
|
1233 return NIL;
|
yuuji@1
|
1234 }
|
yuuji@1
|
1235
|
yuuji@1
|
1236 if (!(*af)(stream, data, &flags, &date, &message)) return NIL;
|
yuuji@1
|
1237
|
yuuji@1
|
1238 mm_critical(stream); /* go critical */
|
yuuji@1
|
1239 do {
|
yuuji@1
|
1240 if (!SIZE(message)) { /* guard againt zero-length */
|
yuuji@1
|
1241 mm_log("Append of zero-length message", ERROR);
|
yuuji@1
|
1242 ret = NIL;
|
yuuji@1
|
1243 break;
|
yuuji@1
|
1244 }
|
yuuji@1
|
1245
|
yuuji@1
|
1246 /* build file name we will use */
|
yuuji@1
|
1247 snprintf (file,MAILTMPLEN,"%u.%d.%09u.%s:3,%s%s%s%s",
|
yuuji@1
|
1248 time (0),getpid (),transact++,mylocalhost (),
|
yuuji@1
|
1249 uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
|
yuuji@1
|
1250 uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
|
yuuji@1
|
1251 /* build tmp file name */
|
yuuji@1
|
1252 snprintf (path1,MAILTMPLEN,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
|
yuuji@1
|
1253
|
yuuji@1
|
1254 if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
|
yuuji@1
|
1255 snprintf (tmp,MAILTMPLEN,"Can't open append mailbox: %s",strerror (errno));
|
yuuji@1
|
1256 mm_log (tmp,ERROR);
|
yuuji@1
|
1257 return NIL;
|
yuuji@1
|
1258 }
|
yuuji@1
|
1259
|
yuuji@1
|
1260 i = SIZE (message); /* get size of message */
|
yuuji@1
|
1261 s = (char *) fs_get (i + 1); /* get space for the data */
|
yuuji@1
|
1262 /* copy the data w/o CR's */
|
yuuji@1
|
1263 while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
|
yuuji@1
|
1264 /* write the data */
|
yuuji@1
|
1265 if ((write (fd,s,size) < 0) || fsync (fd)) {
|
yuuji@1
|
1266 unlink (path1); /* delete message */
|
yuuji@1
|
1267 snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
|
yuuji@1
|
1268 mm_log (tmp,ERROR);
|
yuuji@1
|
1269 ret = NIL;
|
yuuji@1
|
1270 }
|
yuuji@1
|
1271 /* build final filename to use */
|
yuuji@1
|
1272 snprintf (path2,MAILTMPLEN,"%s/../new/%s",maildir_file (tmp,mailbox),file);
|
yuuji@1
|
1273 if (link (path1,path2) < 0) {
|
yuuji@1
|
1274 snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
|
yuuji@1
|
1275 mm_log (tmp,ERROR);
|
yuuji@1
|
1276 ret = NIL;
|
yuuji@1
|
1277 }
|
yuuji@1
|
1278 unlink (path1);
|
yuuji@1
|
1279 fs_give ((void **) &s); /* flush the buffer */
|
yuuji@1
|
1280 close (fd); /* close the file */
|
yuuji@1
|
1281
|
yuuji@1
|
1282 if (ret) {
|
yuuji@1
|
1283 if (!(*af)(stream, data, &flags, &date, &message)) ret = NIL;
|
yuuji@1
|
1284 }
|
yuuji@1
|
1285 } while(ret && message);
|
yuuji@1
|
1286
|
yuuji@1
|
1287 mm_nocritical (stream); /* release critical */
|
yuuji@1
|
1288 return ret;
|
yuuji@1
|
1289 }
|
yuuji@1
|
1290
|
yuuji@1
|
1291 #if 0
|
yuuji@1
|
1292 long maildir_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
|
yuuji@1
|
1293 STRING *message)
|
yuuji@1
|
1294 {
|
yuuji@1
|
1295 int fd;
|
yuuji@1
|
1296 char c,*s;
|
yuuji@1
|
1297 char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
|
yuuji@1
|
1298 MESSAGECACHE elt;
|
yuuji@1
|
1299 long i;
|
yuuji@1
|
1300 long size = 0;
|
yuuji@1
|
1301 long ret = LONGT;
|
yuuji@1
|
1302 short uf = 0;
|
yuuji@1
|
1303
|
yuuji@1
|
1304 /*
|
yuuji@1
|
1305 This is intentionaly made static. Users can ask to save a LOT of messages
|
yuuji@1
|
1306 at once and this program can do that within one second. Dan's assumption
|
yuuji@1
|
1307 that time+pid+hostname always will be unique stops being true in this
|
yuuji@1
|
1308 case. So we will add yet another number to host part of message file's
|
yuuji@1
|
1309 name. Hostname is used only to make filename unique and Dan explicitly
|
yuuji@1
|
1310 says that "<...> Other than this [skipping filenames starting at dot] ,
|
yuuji@1
|
1311 readers should not attempt to parse filenames. <...>". Therefore this
|
yuuji@1
|
1312 addition should be no problem. Am I right, Dan? --AK
|
yuuji@1
|
1313 */
|
yuuji@1
|
1314
|
yuuji@1
|
1315 static unsigned int transact = 0;
|
yuuji@1
|
1316
|
yuuji@1
|
1317 if (flags) /* get flags if given */
|
yuuji@1
|
1318 uf = maildir_getflags (user_flags (&maildirproto),flags);
|
yuuji@1
|
1319
|
yuuji@1
|
1320 /* if (date) { want to preserve date?
|
yuuji@1
|
1321 //syslog(LOG_INFO, "date: '%s'", date);
|
yuuji@1
|
1322 // yes, parse date into an elt
|
yuuji@1
|
1323 if (!mail_parse_date (&elt,date)) {
|
yuuji@1
|
1324 snprintf (tmp,MAILTMPLEN,"Bad date in append: %s",date);
|
yuuji@1
|
1325 mm_log (tmp,ERROR);
|
yuuji@1
|
1326 return NIL;
|
yuuji@1
|
1327 }
|
yuuji@1
|
1328 } */
|
yuuji@1
|
1329 /* N.B.: can't use LOCAL->buf for tmp */
|
yuuji@1
|
1330 /* make sure valid mailbox */
|
yuuji@1
|
1331 if (!maildir_isvalid (mailbox, NIL)) {
|
yuuji@1
|
1332 snprintf (tmp,MAILTMPLEN,"Not a valid Maildir mailbox: %s",mailbox);
|
yuuji@1
|
1333 mm_log (tmp,ERROR);
|
yuuji@1
|
1334 return NIL;
|
yuuji@1
|
1335 }
|
yuuji@1
|
1336 /* build file name we will use */
|
yuuji@1
|
1337 snprintf (file,MAILTMPLEN,"%u.%d.%09u.%s:3,%s%s%s%s",
|
yuuji@1
|
1338 time (0),getpid (),transact++,mylocalhost (),
|
yuuji@1
|
1339 uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
|
yuuji@1
|
1340 uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
|
yuuji@1
|
1341 /* build tmp file name */
|
yuuji@1
|
1342 snprintf (path1,MAILTMPLEN,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
|
yuuji@1
|
1343
|
yuuji@1
|
1344 if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
|
yuuji@1
|
1345 snprintf (tmp,MAILTMPLEN,"Can't open append mailbox: %s",strerror (errno));
|
yuuji@1
|
1346 mm_log (tmp,ERROR);
|
yuuji@1
|
1347 return NIL;
|
yuuji@1
|
1348 }
|
yuuji@1
|
1349 i = SIZE (message); /* get size of message */
|
yuuji@1
|
1350 s = (char *) fs_get (i + 1); /* get space for the data */
|
yuuji@1
|
1351 /* copy the data w/o CR's */
|
yuuji@1
|
1352 while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
|
yuuji@1
|
1353 mm_critical (stream); /* go critical */
|
yuuji@1
|
1354 /* write the data */
|
yuuji@1
|
1355 if ((write (fd,s,size) < 0) || fsync (fd)) {
|
yuuji@1
|
1356 unlink (path1); /* delete message */
|
yuuji@1
|
1357 snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
|
yuuji@1
|
1358 mm_log (tmp,ERROR);
|
yuuji@1
|
1359 ret = NIL;
|
yuuji@1
|
1360 }
|
yuuji@1
|
1361 /* build final filename to use */
|
yuuji@1
|
1362 snprintf (path2,MAILTMPLEN,"%s/../new/%s",maildir_file (tmp,mailbox),file);
|
yuuji@1
|
1363 if (link (path1,path2) < 0) {
|
yuuji@1
|
1364 snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
|
yuuji@1
|
1365 mm_log (tmp,ERROR);
|
yuuji@1
|
1366 ret = NIL;
|
yuuji@1
|
1367 }
|
yuuji@1
|
1368 unlink (path1);
|
yuuji@1
|
1369
|
yuuji@1
|
1370 close (fd); /* close the file */
|
yuuji@1
|
1371 mm_nocritical (stream); /* release critical */
|
yuuji@1
|
1372 fs_give ((void **) &s); /* flush the buffer */
|
yuuji@1
|
1373 return ret;
|
yuuji@1
|
1374 }
|
yuuji@1
|
1375 #endif
|
yuuji@1
|
1376
|
yuuji@1
|
1377 short bezerk_getflags (MAILSTREAM *stream,char *flag)
|
yuuji@1
|
1378 {
|
yuuji@1
|
1379 char *t,tmp[MAILTMPLEN],err[MAILTMPLEN];
|
yuuji@1
|
1380 short f = 0;
|
yuuji@1
|
1381 short i,j;
|
yuuji@1
|
1382 if (flag && *flag) { /* no-op if no flag string */
|
yuuji@1
|
1383 /* check if a list and make sure valid */
|
yuuji@1
|
1384 if ((i = (*flag == '(')) ^ (flag[strlen (flag)-1] == ')')) {
|
yuuji@1
|
1385 mm_log ("Bad flag list",ERROR);
|
yuuji@1
|
1386 return NIL;
|
yuuji@1
|
1387 }
|
yuuji@1
|
1388 /* copy the flag string w/o list construct */
|
yuuji@1
|
1389 strncpy (tmp,flag+i,(j = strlen (flag) - (2*i)));
|
yuuji@1
|
1390 tmp[j] = '\0';
|
yuuji@1
|
1391 t = ucase (tmp); /* uppercase only from now on */
|
yuuji@1
|
1392
|
yuuji@1
|
1393 while (t && *t) { /* parse the flags */
|
yuuji@1
|
1394 if (*t == '\\') { /* system flag? */
|
yuuji@1
|
1395 switch (*++t) { /* dispatch based on first character */
|
yuuji@1
|
1396 case 'S': /* possible \Seen flag */
|
yuuji@1
|
1397 if (t[1] == 'E' && t[2] == 'E' && t[3] == 'N') i = fSEEN;
|
yuuji@1
|
1398 t += 4; /* skip past flag name */
|
yuuji@1
|
1399 break;
|
yuuji@1
|
1400 case 'D': /* possible \Deleted flag */
|
yuuji@1
|
1401 if (t[1] == 'E' && t[2] == 'L' && t[3] == 'E' && t[4] == 'T' &&
|
yuuji@1
|
1402 t[5] == 'E' && t[6] == 'D') i = fDELETED;
|
yuuji@1
|
1403 t += 7; /* skip past flag name */
|
yuuji@1
|
1404 break;
|
yuuji@1
|
1405 case 'F': /* possible \Flagged flag */
|
yuuji@1
|
1406 if (t[1] == 'L' && t[2] == 'A' && t[3] == 'G' && t[4] == 'G' &&
|
yuuji@1
|
1407 t[5] == 'E' && t[6] == 'D') i = fFLAGGED;
|
yuuji@1
|
1408 t += 7; /* skip past flag name */
|
yuuji@1
|
1409 break;
|
yuuji@1
|
1410 case 'A': /* possible \Answered flag */
|
yuuji@1
|
1411 if (t[1] == 'N' && t[2] == 'S' && t[3] == 'W' && t[4] == 'E' &&
|
yuuji@1
|
1412 t[5] == 'R' && t[6] == 'E' && t[7] == 'D') i = fANSWERED;
|
yuuji@1
|
1413 t += 8; /* skip past flag name */
|
yuuji@1
|
1414 break;
|
yuuji@1
|
1415 default: /* unknown */
|
yuuji@1
|
1416 i = 0;
|
yuuji@1
|
1417 break;
|
yuuji@1
|
1418 }
|
yuuji@1
|
1419 /* add flag to flags list */
|
yuuji@1
|
1420 if (i && ((*t == '\0') || (*t++ == ' '))) f |= i;
|
yuuji@1
|
1421 }
|
yuuji@1
|
1422 else { /* no user flags yet */
|
yuuji@1
|
1423 return f;
|
yuuji@1
|
1424 t = strtok (t," "); /* isolate flag name */
|
yuuji@1
|
1425 /* snprintf (err,MAILTMPLEN,"Unknown flag: %.80s",t); */
|
yuuji@1
|
1426 t = strtok (NIL," "); /* get next flag */
|
yuuji@1
|
1427 /* mm_log (err,ERROR); */
|
yuuji@1
|
1428 }
|
yuuji@1
|
1429 }
|
yuuji@1
|
1430 }
|
yuuji@1
|
1431 return f;
|
yuuji@1
|
1432 }
|
yuuji@1
|
1433
|
yuuji@1
|
1434 short maildir_getflags (MAILSTREAM *stream,char *flag)
|
yuuji@1
|
1435 {
|
yuuji@1
|
1436 return bezerk_getflags (stream,flag); /* nothing exciting, reuse old code */
|
yuuji@1
|
1437 }
|
yuuji@1
|
1438
|
yuuji@1
|
1439 long maildir_delete (MAILSTREAM *stream,char *mailbox)
|
yuuji@1
|
1440 {
|
yuuji@1
|
1441 DIR *dirp;
|
yuuji@1
|
1442 struct direct *d;
|
yuuji@1
|
1443 int i,j;
|
yuuji@1
|
1444 char tmp[MAILTMPLEN],err[MAILTMPLEN];
|
yuuji@1
|
1445 char *subdir_names[] = {"cur/","new/","tmp/",NULL};
|
yuuji@1
|
1446
|
yuuji@1
|
1447 /* check if mailbox even exists */
|
yuuji@1
|
1448 if (!maildir_isvalid (mailbox,NIL)) {
|
yuuji@1
|
1449 /* sprintf (tmp,"Can't delete mailbox %s: no such mailbox",mailbox);
|
yuuji@1
|
1450 mm_log (tmp,ERROR);
|
yuuji@1
|
1451 return NIL; */
|
yuuji@1
|
1452 /*syslog(LOG_INFO, "Invalid maildir in delete()"); */
|
yuuji@1
|
1453 return T; /* well.. a stupid hack to get by a problem in netscape ..
|
yuuji@1
|
1454 it remembers folders locally, and if a folder is deleted on
|
yuuji@1
|
1455 another machine, you have no way removing it on any other
|
yuuji@1
|
1456 netscapes... */
|
yuuji@1
|
1457 }
|
yuuji@1
|
1458
|
yuuji@1
|
1459 /* get name of directory */
|
yuuji@1
|
1460 i = strlen (maildir_file (tmp,mailbox)) + 1;
|
yuuji@1
|
1461 for (j = 0; subdir_names[j]; j++) {
|
yuuji@1
|
1462 strncpy (tmp + i - 4,subdir_names[j], MAILTMPLEN);
|
yuuji@1
|
1463 if (dirp = opendir (tmp)) { /* open directory */
|
yuuji@1
|
1464 while (d = readdir (dirp)) /* empty the directory */
|
yuuji@1
|
1465 if (strcmp (d->d_name,".") && strcmp (d->d_name,"..")) {
|
yuuji@1
|
1466 strncpy (tmp + i,d->d_name, MAILTMPLEN);
|
yuuji@1
|
1467 /*syslog(LOG_INFO, "unlink1: '%s'");*/
|
yuuji@1
|
1468 unlink (tmp);
|
yuuji@1
|
1469 }
|
yuuji@1
|
1470 closedir (dirp); /* flush directory */
|
yuuji@1
|
1471 }
|
yuuji@1
|
1472 /* remove the subdir */
|
yuuji@1
|
1473 tmp[i + 3] = '\0';
|
yuuji@1
|
1474 /*syslog(LOG_INFO, "tmp: '%s'", tmp);*/
|
yuuji@1
|
1475 if (rmdir (tmp)) {
|
yuuji@1
|
1476 /* sprintf (err,"Can't delete directory %s: %s",tmp,strerror (errno));
|
yuuji@1
|
1477 mm_log (err,ERROR);*/
|
yuuji@1
|
1478 }
|
yuuji@1
|
1479 }
|
yuuji@1
|
1480
|
yuuji@1
|
1481 /* try to remove the directory */
|
yuuji@1
|
1482 *(tmp + i - 5) = '\0';
|
yuuji@1
|
1483 /*syslog(LOG_INFO, "tmp2: '%s'", tmp);*/
|
yuuji@1
|
1484 if (rmdir (tmp)) {
|
yuuji@1
|
1485 /* sprintf (err,"Can't delete mailbox %s: %s",mailbox,strerror (errno));
|
yuuji@1
|
1486 mm_log (err,ERROR);
|
yuuji@1
|
1487 return NIL; */
|
yuuji@1
|
1488 }
|
yuuji@1
|
1489 return T; /* return success */
|
yuuji@1
|
1490 }
|
yuuji@1
|
1491
|
yuuji@1
|
1492 long maildir_rename (MAILSTREAM *stream,char *old,char *new)
|
yuuji@1
|
1493 {
|
yuuji@1
|
1494 char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN];
|
yuuji@1
|
1495
|
yuuji@1
|
1496 /* old mailbox name must be valid */
|
yuuji@1
|
1497 if (!maildir_isvalid (old,NIL)) {
|
yuuji@1
|
1498 snprintf (tmp,MAILTMPLEN,"Can't rename mailbox %s: no such mailbox",old);
|
yuuji@1
|
1499 mm_log (tmp,ERROR);
|
yuuji@1
|
1500 return NIL;
|
yuuji@1
|
1501 }
|
yuuji@1
|
1502
|
yuuji@1
|
1503 /* new mailbox name must not exist */
|
yuuji@1
|
1504 if (access (maildir_file (tmp,new),F_OK) == 0) {
|
yuuji@1
|
1505 snprintf (tmp,MAILTMPLEN,"Can't rename to mailbox %s: destination already exists",new);
|
yuuji@1
|
1506 mm_log (tmp,ERROR);
|
yuuji@1
|
1507 return NIL;
|
yuuji@1
|
1508 }
|
yuuji@1
|
1509
|
yuuji@1
|
1510 /* try to rename the directory */
|
yuuji@1
|
1511 if (rename (maildir_file (tmp,old),maildir_file (tmpnew,new))) {
|
yuuji@1
|
1512 snprintf (tmp,MAILTMPLEN,"Can't rename mailbox %s to %s: %s",old,new,strerror (errno));
|
yuuji@1
|
1513 mm_log (tmp,ERROR);
|
yuuji@1
|
1514 return NIL;
|
yuuji@1
|
1515 }
|
yuuji@1
|
1516 return T; /* return success */
|
yuuji@1
|
1517 }
|
yuuji@1
|
1518
|
yuuji@1
|
1519 long maildir_sub (MAILSTREAM *stream,char *mailbox)
|
yuuji@1
|
1520 {
|
yuuji@1
|
1521 char tmp[MAILTMPLEN];
|
yuuji@1
|
1522 return sm_subscribe (mailbox);
|
yuuji@1
|
1523 }
|
yuuji@1
|
1524
|
yuuji@1
|
1525 long maildir_unsub (MAILSTREAM *stream,char *mailbox)
|
yuuji@1
|
1526 {
|
yuuji@1
|
1527 char tmp[MAILTMPLEN];
|
yuuji@1
|
1528 return sm_unsubscribe (mailbox);
|
yuuji@1
|
1529 }
|
yuuji@1
|
1530
|
yuuji@1
|
1531 void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
|
yuuji@1
|
1532 {
|
yuuji@1
|
1533 void *sdb = NIL;
|
yuuji@1
|
1534 char *s;
|
yuuji@1
|
1535 /* get canonical form of name */
|
yuuji@1
|
1536 if ((s = sm_read (&sdb))) {
|
yuuji@1
|
1537 do if (pmatch_full (s,pat,'/')) mm_lsub (stream,'/',s,NIL);
|
yuuji@1
|
1538 while (s = sm_read (&sdb)); /* until no more subscriptions */
|
yuuji@1
|
1539 }
|
yuuji@1
|
1540
|
yuuji@1
|
1541 }
|