1 /* $Id: mboxClient.c,v 1.17 2004/03/28 00:28:58 bluehal Exp $ */
2 /* Author: Yong-iL Joh <tolkien@mizi.com>
3 Modified: Jorge GarcĂa <Jorge.Garcia@uv.es>
4 Rob Funk <rfunk@funknet.net>
5 Neil Spring <nspring@cs.washington.edu>
9 * Last Updated : $Date: 2004/03/28 00:28:58 $
25 #define PCM (pc->u).mbox
26 #define FROM_STR "From "
27 #define STATUS_STR "Status: "
29 FILE *openMailbox(Pop3 pc
, const char *mbox_filename
)
33 if ((mailbox
= fopen(mbox_filename
, "r")) == NULL
) {
34 DM(pc
, DEBUG_ERROR
, "Error opening mailbox '%s': %s\n",
35 mbox_filename
, strerror(errno
));
42 /* count the messages in a mailbox */
43 static void countMessages(Pop3 pc
, const char *mbox_filename
)
48 int next_from_is_start_of_header
= 1;
49 int count_from
= 0, count_status
= 0;
50 int len_from
= strlen(FROM_STR
), len_status
= strlen(STATUS_STR
);
53 F
= openMailbox(pc
, mbox_filename
);
58 while (fgets(buf
, BUF_SIZE
, F
)) {
59 // The first message usually is automatically created by POP3/IMAP
60 // clients for internal record keeping and is ignored
61 // (not displayed) by most email clients.
62 if (is_header
&& !strncmp(buf
, "X-IMAP: ", 8))
67 /* a newline by itself terminates the header */
71 next_from_is_start_of_header
= 1;
72 } else if (!strncmp(buf
, FROM_STR
, len_from
)) {
73 /* A line starting with "From" is the beginning of a new header.
74 "From" in the text of the mail should get escaped by the MDA.
75 If your MDA doesn't do that, it is broken.
77 if (next_from_is_start_of_header
)
82 next_from_is_start_of_header
= 0;
83 if (is_header
&& !strncmp(buf
, STATUS_STR
, len_status
)
84 && strrchr(buf
, 'R')) {
90 if (count_from
&& pseudo_mail
) {
96 DM(pc
, DEBUG_INFO
, "from: %d status: %d\n", count_from
, count_status
);
97 pc
->TotalMsgs
= count_from
;
98 pc
->UnreadMsgs
= count_from
- count_status
;
102 /* check file status; hold on to file information used
103 to restore access time */
105 fileHasChanged(const char *mbox_filename
, time_t * atime
,
106 time_t * mtime
, off_t
* size
)
111 if (stat(mbox_filename
, &st
)) {
112 DMA(DEBUG_ERROR
, "Can't stat '%s': %s\n",
113 mbox_filename
, strerror(errno
));
114 } else if (st
.st_mtime
!= *mtime
|| st
.st_size
!= *size
) {
115 /* file was changed OR initially read */
116 DMA(DEBUG_INFO
, " %s was changed,"
117 " mTIME: %lu -> %lu; SIZE: %lu -> %lu\n",
118 mbox_filename
, *mtime
, st
.st_mtime
,
119 (unsigned long) *size
, (unsigned long) st
.st_size
);
121 *atime
= st
.st_atime
;
122 *mtime
= st
.st_mtime
;
129 int mboxCheckHistory(Pop3 pc
)
131 char *mbox_filename
= backtickExpand(pc
, pc
->path
);
134 DM(pc
, DEBUG_INFO
, ">Mailbox: '%s'\n", mbox_filename
);
136 if (fileHasChanged(mbox_filename
, &ut
.actime
, &PCM
.mtime
, &PCM
.size
)
137 || pc
->OldMsgs
< 0) {
139 countMessages(pc
, mbox_filename
);
141 /* Reset atime for (at least) MUTT to work */
142 /* ut.actime is set above */
143 ut
.modtime
= PCM
.mtime
;
144 utime(mbox_filename
, &ut
);
150 int mboxCreate(Pop3 pc
, const char *str
)
152 /* MBOX format: mbox:fullpathname */
157 pc
->OldUnreadMsgs
= -1;
158 pc
->checkMail
= mboxCheckHistory
;
160 /* default boxes are mbox... cut mbox: if it exists */
161 if (!strncasecmp(pc
->path
, "mbox:", 5)) {
162 if (strlen(str
+ 5) + 1 > BUF_BIG
) {
163 DM(pc
, DEBUG_ERROR
, "mbox '%s' is too long.\n", str
+ 5);
164 memset(pc
->path
, 0, BUF_BIG
);
166 strncpy(pc
->path
, str
+ 5, BUF_BIG
- 1); /* cut off ``mbox:'' */
170 DM(pc
, DEBUG_INFO
, "mbox: str = '%s'\n", str
);
171 DM(pc
, DEBUG_INFO
, "mbox: path= '%s'\n", pc
->path
);