dockapps/wmbiff/wmbiff/mboxClient.c
2014-10-05 19:18:49 +01:00

184 lines
4.3 KiB
C

/* $Id: mboxClient.c,v 1.17 2004/03/28 00:28:58 bluehal Exp $ */
/* Author: Yong-iL Joh <tolkien@mizi.com>
Modified: Jorge García <Jorge.Garcia@uv.es>
Rob Funk <rfunk@funknet.net>
Neil Spring <nspring@cs.washington.edu>
*
* MBOX checker.
*
* Last Updated : $Date: 2004/03/28 00:28:58 $
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Client.h"
#include <sys/stat.h>
#include <errno.h>
#include <utime.h>
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
#define PCM (pc->u).mbox
#define FROM_STR "From "
#define STATUS_STR "Status: "
FILE *openMailbox(Pop3 pc, const char *mbox_filename)
{
FILE *mailbox;
if ((mailbox = fopen(mbox_filename, "r")) == NULL) {
DM(pc, DEBUG_ERROR, "Error opening mailbox '%s': %s\n",
mbox_filename, strerror(errno));
pc->TotalMsgs = -1;
pc->UnreadMsgs = -1;
}
return (mailbox);
}
/* count the messages in a mailbox */
static void countMessages(Pop3 pc, const char *mbox_filename)
{
FILE *F;
char buf[BUF_SIZE];
int is_header = 0;
int next_from_is_start_of_header = 1;
int count_from = 0, count_status = 0;
int len_from = strlen(FROM_STR), len_status = strlen(STATUS_STR);
int pseudo_mail = 0;
F = openMailbox(pc, mbox_filename);
if (F == NULL)
return;
/* count message */
while (fgets(buf, BUF_SIZE, F)) {
// The first message usually is automatically created by POP3/IMAP
// clients for internal record keeping and is ignored
// (not displayed) by most email clients.
if (is_header && !strncmp(buf, "X-IMAP: ", 8))
{
pseudo_mail = 1;
}
if (buf[0] == '\n') {
/* a newline by itself terminates the header */
if (is_header)
is_header = 0;
else
next_from_is_start_of_header = 1;
} else if (!strncmp(buf, FROM_STR, len_from)) {
/* A line starting with "From" is the beginning of a new header.
"From" in the text of the mail should get escaped by the MDA.
If your MDA doesn't do that, it is broken.
*/
if (next_from_is_start_of_header)
is_header = 1;
if (is_header)
count_from++;
} else {
next_from_is_start_of_header = 0;
if (is_header && !strncmp(buf, STATUS_STR, len_status)
&& strrchr(buf, 'R')) {
count_status++;
}
}
}
if (count_from && pseudo_mail) {
count_from--;
if (count_status)
count_status--;
}
DM(pc, DEBUG_INFO, "from: %d status: %d\n", count_from, count_status);
pc->TotalMsgs = count_from;
pc->UnreadMsgs = count_from - count_status;
fclose(F);
}
/* check file status; hold on to file information used
to restore access time */
int
fileHasChanged(const char *mbox_filename, time_t * atime,
time_t * mtime, off_t * size)
{
struct stat st;
/* mbox file */
if (stat(mbox_filename, &st)) {
DMA(DEBUG_ERROR, "Can't stat '%s': %s\n",
mbox_filename, strerror(errno));
} else if (st.st_mtime != *mtime || st.st_size != *size) {
/* file was changed OR initially read */
DMA(DEBUG_INFO, " %s was changed,"
" mTIME: %lu -> %lu; SIZE: %lu -> %lu\n",
mbox_filename, *mtime, st.st_mtime,
(unsigned long) *size, (unsigned long) st.st_size);
*atime = st.st_atime;
*mtime = st.st_mtime;
*size = st.st_size;
return 1;
}
return 0;
}
int mboxCheckHistory(Pop3 pc)
{
char *mbox_filename = backtickExpand(pc, pc->path);
struct utimbuf ut;
DM(pc, DEBUG_INFO, ">Mailbox: '%s'\n", mbox_filename);
if (fileHasChanged(mbox_filename, &ut.actime, &PCM.mtime, &PCM.size)
|| pc->OldMsgs < 0) {
countMessages(pc, mbox_filename);
/* Reset atime for (at least) MUTT to work */
/* ut.actime is set above */
ut.modtime = PCM.mtime;
utime(mbox_filename, &ut);
}
free(mbox_filename);
return 0;
}
int mboxCreate(Pop3 pc, const char *str)
{
/* MBOX format: mbox:fullpathname */
pc->TotalMsgs = 0;
pc->UnreadMsgs = 0;
pc->OldMsgs = -1;
pc->OldUnreadMsgs = -1;
pc->checkMail = mboxCheckHistory;
/* default boxes are mbox... cut mbox: if it exists */
if (!strncasecmp(pc->path, "mbox:", 5)) {
if (strlen(str + 5) + 1 > BUF_BIG) {
DM(pc, DEBUG_ERROR, "mbox '%s' is too long.\n", str + 5);
memset(pc->path, 0, BUF_BIG);
} else {
strncpy(pc->path, str + 5, BUF_BIG - 1); /* cut off ``mbox:'' */
}
}
DM(pc, DEBUG_INFO, "mbox: str = '%s'\n", str);
DM(pc, DEBUG_INFO, "mbox: path= '%s'\n", pc->path);
return 0;
}
/* vim:set ts=4: */
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/