aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/local/camel-mbox-summary.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/local/camel-mbox-summary.c')
-rw-r--r--camel/providers/local/camel-mbox-summary.c1105
1 files changed, 0 insertions, 1105 deletions
diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c
deleted file mode 100644
index 41ebe28fa6..0000000000
--- a/camel/providers/local/camel-mbox-summary.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*-
- *
- * Copyright (C) 2000 Ximian Inc.
- *
- * Authors: Michael Zucchi <notzed@ximian.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "camel-mbox-summary.h"
-#include "camel/camel-mime-message.h"
-#include "camel/camel-operation.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "camel-mbox-summary.h"
-#include "camel/camel-file-utils.h"
-#include "camel/camel-mime-message.h"
-#include "camel/camel-operation.h"
-
-#define io(x)
-#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
-
-#define CAMEL_MBOX_SUMMARY_VERSION (0x1000)
-
-struct _CamelMboxSummaryPrivate {
-};
-
-#define _PRIVATE(o) (((CamelMboxSummary *)(o))->priv)
-
-static int summary_header_load (CamelFolderSummary *, FILE *);
-static int summary_header_save (CamelFolderSummary *, FILE *);
-
-static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _header_raw *);
-static CamelMessageInfo * message_info_new_from_parser (CamelFolderSummary *, CamelMimeParser *);
-static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *);
-static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *);
-/*static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);*/
-
-static int mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex);
-static int mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex);
-#ifdef STATUS_PINE
-static CamelMessageInfo *mbox_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex);
-#endif
-
-static int mbox_summary_sync_quick(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex);
-static int mbox_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex);
-
-static void camel_mbox_summary_class_init (CamelMboxSummaryClass *klass);
-static void camel_mbox_summary_init (CamelMboxSummary *obj);
-static void camel_mbox_summary_finalise (CamelObject *obj);
-
-#ifdef STATUS_PINE
-/* Which status flags are stored in each separate header */
-#define STATUS_XSTATUS (CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_ANSWERED|CAMEL_MESSAGE_DELETED)
-#define STATUS_STATUS (CAMEL_MESSAGE_SEEN)
-
-static void encode_status(guint32 flags, char status[8]);
-static guint32 decode_status(const char *status);
-#endif
-
-static CamelLocalSummaryClass *camel_mbox_summary_parent;
-
-CamelType
-camel_mbox_summary_get_type(void)
-{
- static CamelType type = CAMEL_INVALID_TYPE;
-
- if (type == CAMEL_INVALID_TYPE) {
- type = camel_type_register(camel_local_summary_get_type(), "CamelMboxSummary",
- sizeof (CamelMboxSummary),
- sizeof (CamelMboxSummaryClass),
- (CamelObjectClassInitFunc) camel_mbox_summary_class_init,
- NULL,
- (CamelObjectInitFunc) camel_mbox_summary_init,
- (CamelObjectFinalizeFunc) camel_mbox_summary_finalise);
- }
-
- return type;
-}
-
-static void
-camel_mbox_summary_class_init(CamelMboxSummaryClass *klass)
-{
- CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *)klass;
- CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass;
-
- camel_mbox_summary_parent = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type());
-
- sklass->summary_header_load = summary_header_load;
- sklass->summary_header_save = summary_header_save;
-
- sklass->message_info_new = message_info_new;
- sklass->message_info_new_from_parser = message_info_new_from_parser;
- sklass->message_info_load = message_info_load;
- sklass->message_info_save = message_info_save;
- /*sklass->message_info_free = message_info_free;*/
-
- lklass->check = mbox_summary_check;
- lklass->sync = mbox_summary_sync;
-#ifdef STATUS_PINE
- lklass->add = mbox_summary_add;
-#endif
-
- klass->sync_quick = mbox_summary_sync_quick;
- klass->sync_full = mbox_summary_sync_full;
-}
-
-static void
-camel_mbox_summary_init(CamelMboxSummary *obj)
-{
- struct _CamelMboxSummaryPrivate *p;
- struct _CamelFolderSummary *s = (CamelFolderSummary *)obj;
-
- p = _PRIVATE(obj) = g_malloc0(sizeof(*p));
-
- /* subclasses need to set the right instance data sizes */
- s->message_info_size = sizeof(CamelMboxMessageInfo);
- s->content_info_size = sizeof(CamelMboxMessageContentInfo);
-
- /* and a unique file version */
- s->version += CAMEL_MBOX_SUMMARY_VERSION;
-}
-
-static void
-camel_mbox_summary_finalise(CamelObject *obj)
-{
- /*CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(obj);*/
-}
-
-/**
- * camel_mbox_summary_new:
- *
- * Create a new CamelMboxSummary object.
- *
- * Return value: A new CamelMboxSummary widget.
- **/
-CamelMboxSummary *
-camel_mbox_summary_new(const char *filename, const char *mbox_name, CamelIndex *index)
-{
- CamelMboxSummary *new = (CamelMboxSummary *)camel_object_new(camel_mbox_summary_get_type());
-
- camel_local_summary_construct((CamelLocalSummary *)new, filename, mbox_name, index);
- return new;
-}
-
-void camel_mbox_summary_xstatus(CamelMboxSummary *mbs, int state)
-{
- mbs->xstatus = state;
-}
-
-static int
-summary_header_load(CamelFolderSummary *s, FILE *in)
-{
- CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
-
- if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_load(s, in) == -1)
- return -1;
-
- return camel_file_util_decode_uint32(in, &mbs->folder_size);
-}
-
-static int
-summary_header_save(CamelFolderSummary *s, FILE *out)
-{
- CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s);
-
- if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_save(s, out) == -1)
- return -1;
-
- return camel_file_util_encode_uint32(out, mbs->folder_size);
-}
-
-static CamelMessageInfo *
-message_info_new(CamelFolderSummary *s, struct _header_raw *h)
-{
- CamelMessageInfo *mi;
- CamelMboxSummary *mbs = (CamelMboxSummary *)s;
-
- mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new(s, h);
- if (mi) {
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
- const char *xev, *uid;
- CamelMessageInfo *info = NULL;
- int add = 0; /* bitmask of things to add, 1 assign uid, 2, just add as new, 4 = recent */
-#ifdef STATUS_PINE
- const char *status = NULL, *xstatus = NULL;
- guint32 flags = 0;
-
- if (mbs->xstatus) {
- /* check for existance of status & x-status headers */
- status = header_raw_find(&h, "Status", NULL);
- if (status)
- flags = decode_status(status);
- xstatus = header_raw_find(&h, "X-Status", NULL);
- if (xstatus)
- flags |= decode_status(xstatus);
- }
-#endif
- /* if we have an xev header, use it, else assign a new one */
- xev = header_raw_find(&h, "X-Evolution", NULL);
- if (xev != NULL
- && camel_local_summary_decode_x_evolution((CamelLocalSummary *)s, xev, mi) == 0) {
- uid = camel_message_info_uid(mi);
- d(printf("found valid x-evolution: %s\n", uid));
- info = camel_folder_summary_uid(s, uid);
- if (info) {
- if ((info->flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) {
- info->flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN;
- camel_folder_summary_info_free(s, mi);
- mbi = (CamelMboxMessageInfo *)mi = info;
- } else {
- add = 7;
- d(printf("seen '%s' before, adding anew\n", uid));
- camel_folder_summary_info_free(s, info);
- }
- } else {
- add = 2;
- d(printf("but isn't present in summary\n"));
- }
- } else {
- d(printf("didn't find x-evolution\n"));
- add = 7;
- }
-
- if (add&1) {
- mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
- camel_message_info_set_uid(mi, camel_folder_summary_next_uid_string(s));
- } else {
- camel_folder_summary_set_uid(s, strtoul(camel_message_info_uid(mi), NULL, 10));
- }
-#ifdef STATUS_PINE
- if (mbs->xstatus && add&2) {
- /* use the status as the flags when we read it the first time */
- if (status)
- mi->flags = (mi->flags & ~(STATUS_STATUS)) | (flags & STATUS_STATUS);
- if (xstatus)
- mi->flags = (mi->flags & ~(STATUS_XSTATUS)) | (flags & STATUS_XSTATUS);
- }
-#endif
- if (mbs->changes) {
- if (add&2)
- camel_folder_change_info_add_uid(mbs->changes, camel_message_info_uid(mi));
- if ((add&4) && status == NULL)
- camel_folder_change_info_recent_uid(mbs->changes, camel_message_info_uid(mi));
- }
-
- mbi->frompos = -1;
- }
-
- return mi;
-}
-
-static CamelMessageInfo *
-message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
-{
- CamelMessageInfo *mi;
-
- mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new_from_parser(s, mp);
- if (mi) {
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
-
- mbi->frompos = camel_mime_parser_tell_start_from(mp);
- }
-
- return mi;
-}
-
-static CamelMessageInfo *
-message_info_load(CamelFolderSummary *s, FILE *in)
-{
- CamelMessageInfo *mi;
-
- io(printf("loading mbox message info\n"));
-
- mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_load(s, in);
- if (mi) {
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
-
- if (camel_file_util_decode_off_t(in, &mbi->frompos) == -1)
- goto error;
- }
-
- return mi;
-error:
- camel_folder_summary_info_free(s, mi);
- return NULL;
-}
-
-static int
-message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi)
-{
- CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
-
- io(printf("saving mbox message info\n"));
-
- if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_save(s, out, mi) == -1
- || camel_file_util_encode_off_t(out, mbi->frompos) == -1)
- return -1;
-
- return 0;
-}
-
-/* like summary_rebuild, but also do changeinfo stuff (if supplied) */
-static int
-summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *changeinfo, CamelException *ex)
-{
- int i, count;
- CamelFolderSummary *s = (CamelFolderSummary *)cls;
- CamelMboxSummary *mbs = (CamelMboxSummary *)cls;
- CamelMimeParser *mp;
- CamelMessageInfo *mi;
- int fd;
- int ok = 0;
- struct stat st;
- off_t size = 0;
-
- d(printf("Calling summary update, from pos %d\n", (int)offset));
-
- cls->index_force = FALSE;
-
- camel_operation_start(NULL, _("Storing folder"));
-
- fd = open(cls->folder_path, O_RDONLY);
- if (fd == -1) {
- d(printf("%s failed to open: %s\n", cls->folder_path, strerror (errno)));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not open folder: %s: %s"),
- cls->folder_path, g_strerror (errno));
- camel_operation_end(NULL);
- return -1;
- }
-
- if (fstat(fd, &st) == 0)
- size = st.st_size;
-
- mp = camel_mime_parser_new();
- camel_mime_parser_init_with_fd(mp, fd);
- camel_mime_parser_scan_from(mp, TRUE);
- camel_mime_parser_seek(mp, offset, SEEK_SET);
-
- if (offset > 0) {
- if (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM
- && camel_mime_parser_tell_start_from(mp) == offset) {
- camel_mime_parser_unstep(mp);
- } else {
- g_warning("The next message didn't start where I expected, building summary from start");
- camel_mime_parser_drop_step(mp);
- offset = 0;
- camel_mime_parser_seek(mp, offset, SEEK_SET);
- }
- }
-
- /* we mark messages as to whether we've seen them or not.
- If we're not starting from the start, we must be starting
- from the old end, so everything must be treated as new */
- count = camel_folder_summary_count(s);
- for (i=0;i<count;i++) {
- mi = camel_folder_summary_index(s, i);
- if (offset == 0)
- mi->flags |= CAMEL_MESSAGE_FOLDER_NOTSEEN;
- else
- mi->flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN;
- camel_folder_summary_info_free(s, mi);
- }
- mbs->changes = changeinfo;
-
- while (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM) {
- CamelMessageInfo *info;
- off_t pc = camel_mime_parser_tell_start_from (mp) + 1;
-
- camel_operation_progress (NULL, (int) (((float) pc / size) * 100));
-
- info = camel_folder_summary_add_from_parser(s, mp);
- if (info == NULL) {
- camel_exception_setv(ex, 1, _("Fatal mail parser error near position %ld in folder %s"),
- camel_mime_parser_tell(mp), cls->folder_path);
- ok = -1;
- break;
- }
-
- g_assert(camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM_END);
- }
-
- camel_object_unref(CAMEL_OBJECT (mp));
-
- count = camel_folder_summary_count(s);
- for (i=0;i<count;i++) {
- mi = camel_folder_summary_index(s, i);
- /* must've dissapeared from the file? */
- if (mi->flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) {
- d(printf("uid '%s' vanished, removing", camel_message_info_uid(mi)));
- if (changeinfo)
- camel_folder_change_info_remove_uid(changeinfo, camel_message_info_uid(mi));
- camel_folder_summary_remove(s, mi);
- count--;
- i--;
- }
- camel_folder_summary_info_free(s, mi);
- }
- mbs->changes = NULL;
-
- /* update the file size/mtime in the summary */
- if (ok != -1) {
- if (stat(cls->folder_path, &st) == 0) {
- camel_folder_summary_touch(s);
- mbs->folder_size = st.st_size;
- s->time = st.st_mtime;
- }
- }
-
- camel_operation_end(NULL);
-
- return ok;
-}
-
-static int
-mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex)
-{
- CamelMboxSummary *mbs = (CamelMboxSummary *)cls;
- CamelFolderSummary *s = (CamelFolderSummary *)cls;
- struct stat st;
- int ret = 0;
- int i, count;
-
- d(printf("Checking summary\n"));
-
- /* check if the summary is up-to-date */
- if (stat(cls->folder_path, &st) == -1) {
- camel_folder_summary_clear(s);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot check folder: %s: %s"),
- cls->folder_path, g_strerror (errno));
- return -1;
- }
-
- if (cls->check_force)
- mbs->folder_size = 0;
- cls->check_force = 0;
-
- if (st.st_size == 0) {
- /* empty? No need to scan at all */
- d(printf("Empty mbox, clearing summary\n"));
- count= camel_folder_summary_count(s);
- for (i=0;i<count;i++) {
- CamelMessageInfo *info = camel_folder_summary_index(s, i);
-
- if (info) {
- camel_folder_change_info_remove_uid(changes, camel_message_info_uid(info));
- camel_folder_summary_info_free(s, info);
- }
- }
- camel_folder_summary_clear(s);
- ret = 0;
- } else {
- /* is the summary uptodate? */
- if (st.st_size != mbs->folder_size || st.st_mtime != s->time) {
- if (mbs->folder_size < st.st_size) {
- /* this will automatically rescan from 0 if there is a problem */
- d(printf("folder grew, attempting to rebuild from %d\n", mbs->folder_size));
- ret = summary_update(cls, mbs->folder_size, changes, ex);
- } else {
- d(printf("folder shrank! rebuilding from start\n"));
- ret = summary_update(cls, 0, changes, ex);
- }
- } else {
- d(printf("Folder unchanged, do nothing\n"));
- }
- }
-
- /* FIXME: move upstream? */
-
- if (ret != -1) {
- if (mbs->folder_size != st.st_size || s->time != st.st_mtime) {
- mbs->folder_size = st.st_size;
- s->time = st.st_mtime;
- camel_folder_summary_touch(s);
- }
- }
-
- return ret;
-}
-
-static char *tz_months[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-static char *tz_days[] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-/* tries to build a From line, based on message headers */
-char *
-camel_mbox_summary_build_from(struct _header_raw *header)
-{
- GString *out = g_string_new("From ");
- char *ret;
- const char *tmp;
- time_t thetime;
- int offset;
- struct tm tm;
-
- tmp = header_raw_find(&header, "Sender", NULL);
- if (tmp == NULL)
- tmp = header_raw_find(&header, "From", NULL);
- if (tmp != NULL) {
- struct _header_address *addr = header_address_decode(tmp);
-
- tmp = NULL;
- if (addr) {
- if (addr->type == HEADER_ADDRESS_NAME) {
- g_string_append(out, addr->v.addr);
- tmp = "";
- }
- header_address_unref(addr);
- }
- }
- if (tmp == NULL) {
- g_string_append(out, "unknown@nodomain.now.au");
- }
-
- /* try use the received header to get the date */
- tmp = header_raw_find(&header, "Received", NULL);
- if (tmp) {
- tmp = strrchr(tmp, ';');
- if (tmp)
- tmp++;
- }
-
- /* if there isn't one, try the Date field */
- if (tmp == NULL)
- tmp = header_raw_find(&header, "Date", NULL);
-
- thetime = header_decode_date(tmp, &offset);
-
- thetime += ((offset / 100) * (60 * 60)) + (offset % 100) * 60;
-
- /* a pseudo, but still bogus attempt at thread safing the function */
- /*memcpy(&tm, gmtime(&thetime), sizeof(tm));*/
- gmtime_r (&thetime, &tm);
-
- g_string_append_printf (out, " %s %s %2d %02d:%02d:%02d %4d\n",
- tz_days[tm.tm_wday], tz_months[tm.tm_mon],
- tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
- tm.tm_year + 1900);
-
- ret = out->str;
- g_string_free (out, FALSE);
-
- return ret;
-}
-
-/* perform a full sync */
-static int
-mbox_summary_sync_full(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex)
-{
- CamelLocalSummary *cls = (CamelLocalSummary *)mbs;
- int fd = -1, fdout = -1;
- char *tmpname = NULL;
- guint32 flags = (expunge?1:0);
-
- d(printf("performing full summary/sync\n"));
-
- camel_operation_start(NULL, _("Storing folder"));
-
- fd = open(cls->folder_path, O_RDONLY);
- if (fd == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not open file: %s: %s"),
- cls->folder_path, g_strerror (errno));
- camel_operation_end(NULL);
- return -1;
- }
-
- tmpname = g_alloca (strlen (cls->folder_path) + 5);
- sprintf (tmpname, "%s.tmp", cls->folder_path);
- d(printf("Writing tmp file to %s\n", tmpname));
- fdout = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0600);
- if (fdout == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot open temporary mailbox: %s"),
- g_strerror (errno));
- goto error;
- }
-
- if (camel_mbox_summary_sync_mbox((CamelMboxSummary *)cls, flags, changeinfo, fd, fdout, ex) == -1)
- goto error;
-
- d(printf("Closing folders\n"));
-
- if (close(fd) == -1) {
- g_warning("Cannot close source folder: %s", strerror (errno));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not close source folder %s: %s"),
- cls->folder_path, g_strerror (errno));
- fd = -1;
- goto error;
- }
-
- if (close(fdout) == -1) {
- g_warning("Cannot close tmp folder: %s", strerror (errno));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not close temp folder: %s"),
- g_strerror (errno));
- fdout = -1;
- goto error;
- }
-
- /* this should probably either use unlink/link/unlink, or recopy over
- the original mailbox, for various locking reasons/etc */
- if (rename(tmpname, cls->folder_path) == -1) {
- g_warning("Cannot rename folder: %s", strerror (errno));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not rename folder: %s"),
- g_strerror (errno));
- goto error;
- }
- tmpname = NULL;
-
- camel_operation_end(NULL);
-
- return 0;
- error:
- if (fd != -1)
- close(fd);
-
- if (fdout != -1)
- close(fdout);
-
- if (tmpname)
- unlink(tmpname);
-
- camel_operation_end(NULL);
-
- return -1;
-}
-
-/* perform a quick sync - only system flags have changed */
-static int
-mbox_summary_sync_quick(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex)
-{
- CamelLocalSummary *cls = (CamelLocalSummary *)mbs;
- CamelFolderSummary *s = (CamelFolderSummary *)mbs;
- CamelMimeParser *mp = NULL;
- int i, count;
- CamelMboxMessageInfo *info = NULL;
- int fd = -1;
- char *xevnew, *xevtmp;
- const char *xev;
- int len;
- off_t lastpos;
-
- d(printf("Performing quick summary sync\n"));
-
- camel_operation_start(NULL, _("Storing folder"));
-
- fd = open(cls->folder_path, O_RDWR);
- if (fd == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not open file: %s: %s"),
- cls->folder_path, g_strerror (errno));
-
- camel_operation_end(NULL);
- return -1;
- }
-
- mp = camel_mime_parser_new();
- camel_mime_parser_scan_from(mp, TRUE);
- camel_mime_parser_scan_pre_from(mp, TRUE);
- camel_mime_parser_init_with_fd(mp, fd);
-
- count = camel_folder_summary_count(s);
- for (i = 0; i < count; i++) {
- int xevoffset;
- int pc = (i+1)*100/count;
-
- camel_operation_progress(NULL, pc);
-
- info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i);
-
- g_assert(info);
-
- d(printf("Checking message %s %08x\n", camel_message_info_uid(info), info->info.flags));
-
- if ((info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) {
- camel_folder_summary_info_free(s, (CamelMessageInfo *)info);
- info = NULL;
- continue;
- }
-
- d(printf("Updating message %s\n", camel_message_info_uid(info)));
-
- camel_mime_parser_seek(mp, info->frompos, SEEK_SET);
-
- if (camel_mime_parser_step(mp, 0, 0) != HSCAN_FROM) {
- g_warning("Expected a From line here, didn't get it");
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
- _("Summary and folder mismatch, even after a sync"));
- goto error;
- }
-
- if (camel_mime_parser_tell_start_from(mp) != info->frompos) {
- g_warning("Didn't get the next message where I expected (%d) got %d instead",
- (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp));
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
- _("Summary and folder mismatch, even after a sync"));
- goto error;
- }
-
- if (camel_mime_parser_step(mp, 0, 0) == HSCAN_FROM_END) {
- g_warning("camel_mime_parser_step failed (2)");
- goto error;
- }
-
- xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset);
- if (xev == NULL || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1) {
- g_warning("We're supposed to have a valid x-ev header, but we dont");
- goto error;
- }
- xevnew = camel_local_summary_encode_x_evolution(cls, (CamelMessageInfo *)info);
- /* SIGH: encode_param_list is about the only function which folds headers by itself.
- This should be fixed somehow differently (either parser doesn't fold headers,
- or param_list doesn't, or something */
- xevtmp = header_unfold(xevnew);
- /* the raw header contains a leading ' ', so (dis)count that too */
- if (strlen(xev)-1 != strlen(xevtmp)) {
- g_free(xevnew);
- g_free(xevtmp);
- g_warning("Hmm, the xev headers shouldn't have changed size, but they did");
- goto error;
- }
- g_free(xevtmp);
-
- /* we write out the xevnew string, assuming its been folded identically to the original too! */
-
- lastpos = lseek(fd, 0, SEEK_CUR);
- lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET);
- do {
- len = write(fd, xevnew, strlen(xevnew));
- } while (len == -1 && errno == EINTR);
- lseek(fd, lastpos, SEEK_SET);
- g_free(xevnew);
-
- camel_mime_parser_drop_step(mp);
- camel_mime_parser_drop_step(mp);
-
- info->info.flags &= 0xffff;
- camel_folder_summary_info_free(s, (CamelMessageInfo *)info);
- }
-
- d(printf("Closing folders\n"));
-
- if (close(fd) == -1) {
- g_warning ("Cannot close source folder: %s", strerror (errno));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not close source folder %s: %s"),
- cls->folder_path, g_strerror (errno));
- fd = -1;
- goto error;
- }
-
- camel_object_unref((CamelObject *)mp);
-
- camel_operation_end(NULL);
-
- return 0;
- error:
- if (fd != -1)
- close(fd);
- if (mp)
- camel_object_unref((CamelObject *)mp);
- if (info)
- camel_folder_summary_info_free(s, (CamelMessageInfo *)info);
-
- camel_operation_end(NULL);
-
- return -1;
-}
-
-static int
-mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex)
-{
- struct stat st;
- CamelMboxSummary *mbs = (CamelMboxSummary *)cls;
- CamelFolderSummary *s = (CamelFolderSummary *)cls;
- int i, count;
- int quick = TRUE, work=FALSE;
- int ret;
-
- /* first, sync ourselves up, just to make sure */
- if (camel_local_summary_check(cls, changeinfo, ex) == -1)
- return -1;
-
- count = camel_folder_summary_count(s);
- if (count == 0)
- return 0;
-
- /* check what work we have to do, if any */
- for (i=0;quick && i<count; i++) {
- CamelMessageInfo *info = camel_folder_summary_index(s, i);
- g_assert(info);
- if ((expunge && (info->flags & CAMEL_MESSAGE_DELETED)) ||
- (info->flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_XEVCHANGE)))
- quick = FALSE;
- else
- work |= (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
- camel_folder_summary_info_free(s, info);
- }
-
- /* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */
- ret = -1;
- if (quick) {
- if (work) {
- ret = ((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_quick(mbs, expunge, changeinfo, ex);
- if (ret == -1) {
- g_warning("failed a quick-sync, trying a full sync");
- camel_exception_clear(ex);
- }
- } else {
- ret = 0;
- }
- }
-
- if (ret == -1)
- ret = ((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_full(mbs, expunge, changeinfo, ex);
- if (ret == -1)
- return -1;
-
- if (stat(cls->folder_path, &st) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Unknown error: %s"), g_strerror (errno));
- return -1;
- }
-
- if (mbs->folder_size != st.st_size || s->time != st.st_mtime) {
- s->time = st.st_mtime;
- mbs->folder_size = st.st_size;
- camel_folder_summary_touch(s);
- }
-
- return ((CamelLocalSummaryClass *)camel_mbox_summary_parent)->sync(cls, expunge, changeinfo, ex);
-}
-
-int
-camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderChangeInfo *changeinfo, int fd, int fdout, CamelException *ex)
-{
- CamelMboxSummary *mbs = (CamelMboxSummary *)cls;
- CamelFolderSummary *s = (CamelFolderSummary *)mbs;
- CamelMimeParser *mp = NULL;
- int i, count;
- CamelMboxMessageInfo *info = NULL;
- char *buffer, *xevnew = NULL;
- int len;
- const char *fromline;
- int lastdel = FALSE;
-#ifdef STATUS_PINE
- char statnew[8], xstatnew[8];
-#endif
-
- d(printf("performing full summary/sync\n"));
-
- /* need to dup this because the mime-parser owns the fd after we give it to it */
- fd = dup(fd);
- if (fd == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not store folder: %s"),
- g_strerror (errno));
- return -1;
- }
-
- mp = camel_mime_parser_new();
- camel_mime_parser_scan_from(mp, TRUE);
- camel_mime_parser_scan_pre_from(mp, TRUE);
- camel_mime_parser_init_with_fd(mp, fd);
-
- count = camel_folder_summary_count(s);
- for (i = 0; i < count; i++) {
- int pc = (i + 1) * 100 / count;
-
- camel_operation_progress(NULL, pc);
-
- info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i);
-
- g_assert(info);
-
- d(printf("Looking at message %s\n", camel_message_info_uid(info)));
-
- /* only need to seek past deleted messages, otherwise we should be at the right spot/state already */
- if (lastdel) {
- d(printf("seeking to %d\n", (int)info->frompos));
- camel_mime_parser_seek(mp, info->frompos, SEEK_SET);
- }
-
- if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM) {
- g_warning("Expected a From line here, didn't get it");
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
- _("Summary and folder mismatch, even after a sync"));
- goto error;
- }
-
- if (camel_mime_parser_tell_start_from(mp) != info->frompos) {
- g_warning("Didn't get the next message where I expected (%d) got %d instead",
- (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp));
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
- _("Summary and folder mismatch, even after a sync"));
- goto error;
- }
-
- lastdel = FALSE;
- if ((flags&1) && info->info.flags & CAMEL_MESSAGE_DELETED) {
- const char *uid = camel_message_info_uid(info);
-
- d(printf("Deleting %s\n", uid));
-
- if (((CamelLocalSummary *)cls)->index)
- camel_index_delete_name(((CamelLocalSummary *)cls)->index, uid);
-
- /* remove it from the change list */
- camel_folder_change_info_remove_uid(changeinfo, uid);
- camel_folder_summary_remove(s, (CamelMessageInfo *)info);
- camel_folder_summary_info_free(s, (CamelMessageInfo *)info);
- count--;
- i--;
- info = NULL;
- lastdel = TRUE;
- } else {
- /* otherwise, the message is staying, copy its From_ line across */
-#if 0
- if (i>0)
- write(fdout, "\n", 1);
-#endif
- info->frompos = lseek(fdout, 0, SEEK_CUR);
- fromline = camel_mime_parser_from_line(mp);
- write(fdout, fromline, strlen(fromline));
- }
-
- if (info && info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) {
- d(printf("Updating header for %s flags = %08x\n", camel_message_info_uid(info), info->info.flags));
-
- if (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_FROM_END) {
- g_warning("camel_mime_parser_step failed (2)");
- goto error;
- }
-
- xevnew = camel_local_summary_encode_x_evolution((CamelLocalSummary *)cls, (CamelMessageInfo *)info);
-#ifdef STATUS_PINE
- if (mbs->xstatus) {
- encode_status(((CamelMessageInfo *)info)->flags & STATUS_STATUS, statnew);
- encode_status(((CamelMessageInfo *)info)->flags & STATUS_XSTATUS, xstatnew);
- len = camel_local_summary_write_headers(fdout, camel_mime_parser_headers_raw(mp), xevnew, statnew, xstatnew);
- } else {
-#endif
- len = camel_local_summary_write_headers(fdout, camel_mime_parser_headers_raw(mp), xevnew, NULL, NULL);
-#ifdef STATUS_PINE
- }
-#endif
- if (len == -1) {
- d(printf("Error writing to tmp mailbox\n"));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Error writing to temp mailbox: %s"),
- g_strerror (errno));
- goto error;
- }
- info->info.flags &= 0xffff;
- g_free(xevnew);
- xevnew = NULL;
- camel_mime_parser_drop_step(mp);
- }
-
- camel_mime_parser_drop_step(mp);
- if (info) {
- d(printf("looking for message content to copy across from %d\n", (int)camel_mime_parser_tell(mp)));
- while (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_PRE_FROM) {
- /*d(printf("copying mbox contents to tmp: '%.*s'\n", len, buffer));*/
- if (write(fdout, buffer, len) != len) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Writing to tmp mailbox failed: %s: %s"),
- ((CamelLocalSummary *)cls)->folder_path,
- g_strerror (errno));
- goto error;
- }
- }
-
- if (write(fdout, "\n", 1) != 1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Error writing to temp mailbox: %s"),
- g_strerror (errno));
- goto error;
- }
-
- d(printf("we are now at %d, from = %d\n", (int)camel_mime_parser_tell(mp),
- (int)camel_mime_parser_tell_start_from(mp)));
- camel_mime_parser_unstep(mp);
- camel_folder_summary_info_free(s, (CamelMessageInfo *)info);
- info = NULL;
- }
- }
-
-#if 0
- /* if last was deleted, append the \n we removed */
- if (lastdel && count > 0)
- write(fdout, "\n", 1);
-#endif
-
- camel_object_unref((CamelObject *)mp);
-
- return 0;
- error:
- g_free(xevnew);
-
- if (mp)
- camel_object_unref((CamelObject *)mp);
- if (info)
- camel_folder_summary_info_free(s, (CamelMessageInfo *)info);
-
- return -1;
-}
-
-#ifdef STATUS_PINE
-static CamelMessageInfo *
-mbox_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex)
-{
- CamelMessageInfo *mi;
-
- mi = ((CamelLocalSummaryClass *)camel_mbox_summary_parent)->add(cls, msg, info, ci, ex);
- if (mi && ((CamelMboxSummary *)cls)->xstatus) {
- char status[8];
-
- /* we snoop and add status/x-status headers to suit */
- encode_status(mi->flags & STATUS_STATUS, status);
- camel_medium_set_header((CamelMedium *)msg, "Status", status);
- encode_status(mi->flags & STATUS_XSTATUS, status);
- camel_medium_set_header((CamelMedium *)msg, "X-Status", status);
- }
-
- return mi;
-}
-
-static struct {
- char tag;
- guint32 flag;
-} status_flags[] = {
- { 'F', CAMEL_MESSAGE_FLAGGED },
- { 'A', CAMEL_MESSAGE_ANSWERED },
- { 'D', CAMEL_MESSAGE_DELETED },
- { 'R', CAMEL_MESSAGE_SEEN },
-};
-
-static void
-encode_status(guint32 flags, char status[8])
-{
- char *p;
- int i;
-
- p = status;
- for (i=0;i<sizeof(status_flags)/sizeof(status_flags[0]);i++)
- if (status_flags[i].flag & flags)
- *p++ = status_flags[i].tag;
- *p++ = 'O';
- *p=0;
-}
-
-static guint32
-decode_status(const char *status)
-{
- const char *p;
- char c;
- guint32 flags = 0;
- int i;
-
- p = status;
- while ((c = *p++)) {
- for (i=0;i<sizeof(status_flags)/sizeof(status_flags[0]);i++)
- if (status_flags[i].tag == *p)
- flags |= status_flags[i].flag;
- }
-
- return flags;
-}
-
-#endif /* STATUS_PINE */