Enable classic mode.
[dockapps.git] / wmbiff / wmbiff / mboxClient.c
blobe5e85f3ec1e9ebebede29c3df6ac4f1c6aa070c6
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>
6 *
7 * MBOX checker.
9 * Last Updated : $Date: 2004/03/28 00:28:58 $
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
17 #include "Client.h"
18 #include <sys/stat.h>
19 #include <errno.h>
20 #include <utime.h>
21 #ifdef USE_DMALLOC
22 #include <dmalloc.h>
23 #endif
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)
31 FILE *mailbox;
33 if ((mailbox = fopen(mbox_filename, "r")) == NULL) {
34 DM(pc, DEBUG_ERROR, "Error opening mailbox '%s': %s\n",
35 mbox_filename, strerror(errno));
36 pc->TotalMsgs = -1;
37 pc->UnreadMsgs = -1;
39 return (mailbox);
42 /* count the messages in a mailbox */
43 static void countMessages(Pop3 pc, const char *mbox_filename)
45 FILE *F;
46 char buf[BUF_SIZE];
47 int is_header = 0;
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);
51 int pseudo_mail = 0;
53 F = openMailbox(pc, mbox_filename);
54 if (F == NULL)
55 return;
57 /* count message */
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))
64 pseudo_mail = 1;
66 if (buf[0] == '\n') {
67 /* a newline by itself terminates the header */
68 if (is_header)
69 is_header = 0;
70 else
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)
78 is_header = 1;
79 if (is_header)
80 count_from++;
81 } else {
82 next_from_is_start_of_header = 0;
83 if (is_header && !strncmp(buf, STATUS_STR, len_status)
84 && strrchr(buf, 'R')) {
85 count_status++;
90 if (count_from && pseudo_mail) {
91 count_from--;
92 if (count_status)
93 count_status--;
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;
99 fclose(F);
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)
108 struct stat st;
110 /* mbox file */
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;
123 *size = st.st_size;
124 return 1;
126 return 0;
129 int mboxCheckHistory(Pop3 pc)
131 char *mbox_filename = backtickExpand(pc, pc->path);
132 struct utimbuf ut;
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);
146 free(mbox_filename);
147 return 0;
150 int mboxCreate(Pop3 pc, const char *str)
152 /* MBOX format: mbox:fullpathname */
154 pc->TotalMsgs = 0;
155 pc->UnreadMsgs = 0;
156 pc->OldMsgs = -1;
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);
165 } else {
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);
173 return 0;
176 /* vim:set ts=4: */
178 * Local Variables:
179 * tab-width: 4
180 * c-indent-level: 4
181 * c-basic-offset: 4
182 * End: