#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <sys/time.h>
#include <dirent.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
#include "gbuffy.h"
#include "rfc2047.h"
int parse_mime_header (BOX_INFO *mbox, GList *headers, FILE *fp,
int override_new)
{
static char *buffer = NULL;
static size_t buflen = STRING;
char from[STRING] = "";
char subject[STRING] = "";
char xface[STRING] = "";
int status = FALSE;
int is_new = FALSE;
if (buffer == NULL)
buffer = (char *) malloc (buflen);
while (*(buffer = read_rfc822_line (fp, buffer, &buflen)) != 0)
{
if (!strncmp (buffer, "Status:", 7))
{
status = TRUE;
if (!strchr (buffer, 'R') && !strchr (buffer, 'O'))
{
is_new = TRUE;
}
}
else if (headers)
{
if (!strncasecmp (buffer, "From:", 5))
{
rfc2047_decode (from, buffer, sizeof (from));
}
else if (!strncasecmp (buffer, "Subject:", 8))
{
rfc2047_decode (subject, buffer, sizeof (subject));
}
else if (!strncasecmp (buffer, "X-Face:", 7))
{
char *s;
s = buffer + 7;
while (*s && ISSPACE (*s)) s++;
strfcpy (xface, s, sizeof (xface));
if (strlen (s) > sizeof (xface))
g_print ("-E- xface header is larger than buffer\n");
}
}
}
if (status == FALSE)
{
is_new = TRUE;
}
else
status = FALSE;
if (headers && (is_new || override_new))
{
MESSAGE_INFO *m;
m = (MESSAGE_INFO *) calloc (1, sizeof (MESSAGE_INFO));
m->from = safe_strdup (from);
m->subject = safe_strdup (subject);
m->face = safe_strdup (xface);
headers = g_list_append (headers, m);
}
return is_new;
}
/*
* Return 0 on no change/failure, 1 on change
*/
int mbox_folder_count (BOX_INFO *mbox, int force, GList *headers)
{
FILE *fp;
char buffer[STRING];
char garbage[STRING];
char path[_POSIX_PATH_MAX];
struct stat s;
struct timeval t[2];
if (mbox->path == NULL)
return 0;
strfcpy (path, mbox->path, sizeof (path));
gbuffy_expand_path (path, sizeof (path));
/* g_print ("-I- Trying mbox %s\n", path); */
if (stat (path, &s) != 0)
{
mbox->file_size = 0;
mbox->file_mtime = 0;
if (mbox->num_messages)
{
mbox->num_messages = 0;
mbox->new_messages = 0;
return 1;
}
return 0;
}
if (!force && (s.st_size == mbox->file_size) && (s.st_mtime == mbox->file_mtime))
return 0;
if ((s.st_size == 0) || (!S_ISREG(s.st_mode)))
{
mbox->file_size = 0;
mbox->file_mtime = 0;
mbox->num_messages = 0;
mbox->new_messages = 0;
return 1;
}
if ((fp = fopen (path, "r")) == NULL)
return 0;
/* Check if a folder by checking for From as first thing in file */
fgets(buffer, sizeof (buffer), fp);
if (!is_from(buffer, garbage, sizeof (garbage)))
return 0;
mbox->num_messages = 1;
mbox->new_messages = 0;
mbox->file_mtime = s.st_mtime;
mbox->file_size = s.st_size;
if (parse_mime_header (mbox, headers, fp, 0))
{
mbox->new_messages++;
}
while (fgets (buffer, sizeof (buffer), fp) != 0)
{
if (is_from (buffer, garbage, sizeof (garbage)))
{
mbox->num_messages++;
if (parse_mime_header (mbox, headers, fp, 0))
{
mbox->new_messages++;
}
}
}
fclose (fp);
/* Restore the access time of the mailbox for other checking programs */
t[0].tv_sec = s.st_atime;
t[0].tv_usec = 0;
t[1].tv_sec = s.st_mtime;
t[1].tv_usec = 0;
utimes (path, t);
return 1;
}
static void count_mh_sequences(BOX_INFO *mbox, GList *headers, FILE *fp)
{
char *buff = NULL;
char *t;
char *p;
size_t sz = 0;
int first, last;
char file[_POSIX_PATH_MAX];
FILE *msg_fp;
while ((buff = read_rfc822_line (fp, buff, &sz)))
{
if (!(t = strtok (buff, " \t:")))
continue;
if (strcmp (t, "unseen"))
continue;
while ((t = strtok (NULL, " \t:")))
{
if ((p = strchr(t, '-')))
{
*p++ = '\0';
first = atoi(t);
last = atoi(p);
}
else
{
first = last = atoi (t);
}
for (; first <= last; first++)
{
mbox->new_messages++;
if (headers)
{
snprintf (file, sizeof (file), "%s/%d", mbox->path, first);
msg_fp = fopen (file, "r");
if (msg_fp != NULL)
{
parse_mime_header (mbox, headers, msg_fp, 1);
fclose(msg_fp);
}
}
}
}
}
if (buff != NULL)
free(&buff);
}
int dir_folder_count (BOX_INFO *mbox, int force, GList *headers)
{
DIR *dp = 0;
FILE *fp = 0;
char path[_POSIX_PATH_MAX];
char file[_POSIX_PATH_MAX];
int mailfile = TRUE;
struct dirent *de;
struct stat s;
struct stat ms;
struct timeval t[2];
time_t sylpheed_t = 0;
if (mbox->path == NULL)
return 0;
if (mbox->type == GB_MAILDIR)
{
snprintf (path, sizeof (path), "%s/new", mbox->path);
}
else
{
strfcpy (path, mbox->path, sizeof (path));
}
gbuffy_expand_path (path, sizeof (path));
if (stat (path, &s) != 0)
{
mbox->file_size = 0;
mbox->file_mtime = 0;
if (mbox->num_messages)
{
mbox->num_messages = 0;
mbox->new_messages = 0;
return 1;
}
return 0;
}
if (!force && (s.st_size == mbox->file_size) && (s.st_mtime == mbox->file_mtime))
return 0;
if (mbox->type == GB_MH)
{
snprintf(file, sizeof(file), "%s/.sylpheed_mark", mbox->path);
if (stat(file, &ms) == 0)
{
sylpheed_t = ms.st_mtime;
}
}
mbox->num_messages = 0;
mbox->new_messages = 0;
dp = opendir (path);
if (dp == NULL)
return 0;
while ((de = readdir (dp)) != NULL)
{
mailfile = TRUE;
if (mbox->type == GB_MH)
{
char *p = NULL;
strtol(de->d_name, &p, 10);
if (p && *p != '\0')
mailfile = FALSE;
}
else if (mbox->type == GB_MAILDIR)
{
if (*de->d_name == '.')
mailfile = FALSE;
}
if (mailfile)
{
mbox->num_messages++;
if (mbox->type == GB_MH)
{
/* If this is a sylpheed_t mh folder, then anything newer than
* the .sylpheed_mark file is new... */
if (sylpheed_t)
{
snprintf (file, sizeof (file), "%s/%s", path, de->d_name);
if (stat(file, &ms) == 0)
{
if (ms.st_mtime > sylpheed_t)
mbox->new_messages++;
}
}
}
else if (mbox->type == GB_MAILDIR)
{
/* For maildir, if we aren't getting headers, we just count
* everything in this directory as new */
mbox->new_messages++;
if (headers != NULL)
{
/* Ok, we need to get the From: and Subject: lines */
snprintf (file, sizeof (file), "%s/%s", path, de->d_name);
fp = fopen (file, "r");
if (fp != NULL)
{
parse_mime_header (mbox, headers, fp, 1);
fclose(fp);
}
}
}
}
}
closedir(dp);
if (mbox->type == GB_MH && !sylpheed_t)
{
snprintf(file, sizeof (file), "%s/.mh_sequences", mbox->path);
fp = fopen(file, "r");
if (fp != NULL)
{
count_mh_sequences(mbox, headers, fp);
fclose(fp);
}
}
/* Restore the access time of the mailbox for other checking programs */
t[0].tv_sec = s.st_atime;
t[0].tv_usec = 0;
t[1].tv_sec = s.st_mtime;
t[1].tv_usec = 0;
utimes (path, t);
return 1;
}
int external_folder_count (BOX_INFO *mbox, int force, GList *headers)
{
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1