Added code to expunge if called for (still need to finish coding this).

2000-06-16  Jeffrey Stedfast  <fejj@helixcode.com>

	* providers/imap/camel-imap-folder.c (imap_sync): Added code
	to expunge if called for (still need to finish coding this).
	(imap_get_uids): Implemented.
	(imap_get_summary): Found a way to get the date
	(imap_summary_get_by_uid): Same.
	(imap_free_summary): Implemented.

	* string-utils.c (strstrcase): Fixed a compile warning

	* providers/imap/camel-imap-summary.c: Removed - we don't
	need a CamelImapSummary structure.

svn path=/trunk/; revision=3606
This commit is contained in:
Jeffrey Stedfast
2000-06-17 05:29:55 +00:00
committed by Jeffrey Stedfast
parent 7070854816
commit 18dc66f594
7 changed files with 97 additions and 1000 deletions

View File

@ -1,3 +1,17 @@
2000-06-16 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-folder.c (imap_sync): Added code
to expunge if called for (still need to finish coding this).
(imap_get_uids): Implemented.
(imap_get_summary): Found a way to get the date
(imap_summary_get_by_uid): Same.
(imap_free_summary): Implemented.
* string-utils.c (strstrcase): Fixed a compile warning
* providers/imap/camel-imap-summary.c: Removed - we don't
need a CamelImapSummary structure.
2000-06-16 Dan Winship <danw@helixcode.com>
Move flag handling from CamelMimeMessage to CamelFolder. This
@ -69,12 +83,13 @@
2000-06-15 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-folder.c (imap_get_summary): Started to implement
(imap_summary_get_by_uid): Started to code, I've got to find a way to get the
date in time_t format and also get the flags
* providers/imap/camel-imap-folder.c (imap_get_summary): Started to
implement - may want to use ENVELOPE instead of BODY.PEEK[HEADER]
(imap_summary_get_by_uid): Started to code, I've got to find a way to
get the date in time_t format and also get the flags
* string-utils.c (strstrcase): Added this convenience function - I know about
strcasestr() but it's not portable.
* string-utils.c (strstrcase): Added this convenience function - I
know about strcasestr() but it's not portable.
2000-06-15 Dan Winship <danw@helixcode.com>
@ -121,22 +136,24 @@
2000-06-14 Jeffrey Stedfast <fejj@helixcode.com>
* camel-mime-filter-crlf.c (filter): Updated the encoder to allocate more
memory (since we are also now adding dots). Also updated the decoder as we
have found that it sometimes passes the end of the buffer.
* camel-mime-filter-crlf.c (filter): Updated the encoder to allocate
more memory (since we are also now adding dots). Also updated the
decoder as we have found that it sometimes passes the end of the
buffer.
* providers/pop3/camel-pop3-folder.c (get_message_by_uid): Took out the
filter code ( we already filter in camel_pop3_command_get_additional_data)
filter code (we already filter in
camel_pop3_command_get_additional_data)
* camel-folder.c (init): Updated: a separator is now a char* rather than
a single char because IMAP can have a string for a directory separator.
Also, since IMAP does not begin with a directory separator, there is a new
argument (path_begins_with_sep) which decides if a directory should begin
with a directory separator.
* camel-folder.c (init): Updated: a separator is now a char* rather
than a single char because IMAP can have a string for a directory
separator. Also, since IMAP does not begin with a directory separator,
there is a new argument (path_begins_with_sep) which decides if a
directory should begin with a directory separator.
* providers/imap/camel-imap-store.c (imap_create): Since, on connect,
Camel tries to create INBOX (which already exists on every IMAP provider)
we can return TRUE when the folder name is "INBOX".
Camel tries to create INBOX (which already exists on every IMAP
provider) we can return TRUE when the folder name is "INBOX".
* providers/vee/camel-vee-folder.c (vee_init): Updated.
@ -223,11 +240,11 @@
2000-06-09 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-stream.c (stream_read): Updated to reflect changes
made in camel-imap-store.c
* providers/imap/camel-imap-stream.c (stream_read): Updated to reflect
changes made in camel-imap-store.c
* providers/imap/camel-imap-store.c (imap_create): No longer checks to make
sure a folder doesn't already exists (as this is no longer needed)
* providers/imap/camel-imap-store.c (imap_create): No longer checks to
make sure a folder doesn't already exists (as this is no longer needed)
(camel_imap_command): Now takes a CamelFolder argument so it can detect
whether or not it needs to SELECT a folder or not
(camel_imap_command_extended): Same.
@ -238,10 +255,12 @@
2000-06-07 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-summary.c: Now builds (not that it's worth much yet).
* providers/imap/camel-imap-summary.c: Now builds (not that it's worth
much yet).
* providers/imap/camel-imap-folder.c (imap_get_uids): Now uses the correct
cast to a CamelImapMessageInfo structure (should get rid of compile warnings).
* providers/imap/camel-imap-folder.c (imap_get_uids): Now uses the
correct cast to a CamelImapMessageInfo structure (should get rid of
compile warnings).
* providers/imap/Makefile.am: Added rules to build
camel-imap-stream
@ -317,8 +336,8 @@
* camel-stream-buffer.c: same
* camel-imap-stream.[c,h]: Added this new stream, cache's previously read
data so each successive call will instead read from the cache
* camel-imap-stream.[c,h]: Added this new stream, cache's previously
read data so each successive call will instead read from the cache
2000-06-05 Dan Winship <danw@helixcode.com>
@ -336,8 +355,8 @@
2000-06-02 Jeffrey Stedfast <fejj@helixcode.com>
* camel-mime-filter-smtp.c (filter): Fixed the filter so that it wouldn't
insert garbage under certain conditions.
* camel-mime-filter-smtp.c (filter): Fixed the filter so that it
wouldn't insert garbage under certain conditions.
2000-06-02 Christopher James Lahey <clahey@helixcode.com>

View File

@ -25,18 +25,16 @@ libcamelimap_la_SOURCES = \
camel-imap-folder.c \
camel-imap-provider.c \
camel-imap-store.c \
camel-imap-stream.c \
camel-imap-summary.c
camel-imap-stream.c
libcamelimapinclude_HEADERS = \
camel-imap-folder.h \
camel-imap-store.h \
camel-imap-stream.h \
camel-imap-summary.h
camel-imap-stream.h
libcamelimap_la_LDFLAGS = -version-info 0:0:0
libcamelimap_la_LIBADD = $(top_builddir)/e-util/libeutil.la $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS)
libcamelimap_la_LIBADD = $(top_builddir)/e-util/libeutil.la $(UNICODE_LIBS)
#libcamelimap_la_LIBADD = $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS)
EXTRA_DIST = libcamelimap.urls

View File

@ -48,6 +48,7 @@
#include "camel-mime-filter-from.h"
#include "camel-mime-filter-crlf.h"
#include "camel-exception.h"
#include "camel-mime-utils.h"
#define d(x)
@ -216,7 +217,6 @@ imap_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_fo
CAMEL_MESSAGE_USER;
imap_folder->summary = NULL;
imap_folder->search = NULL;
/* SELECT the IMAP mail spool */
@ -237,6 +237,8 @@ static void
imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
{
/* TODO: actually code this method */
if (expunge)
imap_expunge (folder, ex);
}
static void
@ -445,17 +447,21 @@ static GPtrArray *
imap_get_uids (CamelFolder *folder, CamelException *ex)
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
CamelImapMessageInfo *info;
GPtrArray *array;
CamelMessageInfo *info;
GPtrArray *array, *infolist;
gint i, count;
count = camel_folder_summary_count(CAMEL_FOLDER_SUMMARY (imap_folder->summary));
infolist = imap_get_summary (folder, ex);
count = infolist->len;
array = g_ptr_array_new ();
g_ptr_array_set_size (array, count);
for (i = 0; i < count; i++) {
info = (CamelImapMessageInfo *) camel_folder_summary_index(CAMEL_FOLDER_SUMMARY (imap_folder->summary), i);
array->pdata[i] = g_strdup(info->info.uid);
info = (CamelMessageInfo *) g_ptr_array_index (infolist, i);
array->pdata[i] = g_strdup(info->uid);
}
imap_free_summary (folder, infolist);
return array;
}
@ -536,8 +542,8 @@ imap_delete_message_by_uid (CamelFolder *folder, const gchar *uid, CamelExceptio
gchar *result;
gint status;
status = camel_imap_command_extended(CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, "UID STORE %s +FLAGS.SILENT (\\Deleted)", uid);
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, "UID STORE %s +FLAGS.SILENT (\\Deleted)", uid);
if (status != CAMEL_IMAP_OK) {
CamelService *service = CAMEL_SERVICE (folder->parent_store);
@ -602,95 +608,6 @@ imap_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *
return msg;
}
#if 0
static CamelMimeMessage *
imap_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
{
/* NOTE: oh boy, this is gonna be complicated */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
CamelStreamMem *message_stream = NULL;
CamelMimeMessage *message = NULL;
CamelImapMessageInfo *info;
CamelMimeParser *parser = NULL;
gchar *buffer, *result;
gint len, status;
/* get the message summary info */
info = (CamelImapMessageInfo *)camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY (imap_folder->summary), uid);
if (info == NULL) {
errno = ENOENT;
goto fail;
}
/* if this has no content, its an error in the library */
g_assert(info->info.content);
g_assert(info->frompos != -1);
/* get our message buffer */
status = camel_imap_command_extended(CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, "UID FETCH %s (FLAGS BODY[])", uid);
if (status != CAMEL_IMAP_OK) {
CamelService *service = CAMEL_SERVICE (folder->parent_store);
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
"Could not mark message %s as 'Deleted' on IMAP server %s: %s",
uid, service->url->host,
status == CAMEL_IMAP_ERR ? result :
"Unknown error");
g_free (result);
goto fail;
}
/* where we read from */
message_stream = CAMEL_STREAM_MEM (camel_stream_mem_new_with_buffer (result, strlen(result)));
if (message_stream == NULL)
goto fail;
/* we use a parser to verify the message is correct, and in the correct position */
parser = camel_mime_parser_new();
camel_mime_parser_init_with_stream(parser, CAMEL_STREAM (message_stream));
gtk_object_unref(GTK_OBJECT (message_stream));
camel_mime_parser_scan_from(parser, TRUE);
camel_mime_parser_seek(parser, info->frompos, SEEK_SET);
if (camel_mime_parser_step(parser, &buffer, &len) != HSCAN_FROM) {
g_warning("File appears truncated");
goto fail;
}
if (camel_mime_parser_tell_start_from(parser) != info->frompos) {
g_warning("Summary doesn't match the folder contents! eek!"
" expecting offset %ld got %ld", (long int)info->frompos,
(long int)camel_mime_parser_tell_start_from(parser));
errno = EINVAL;
goto fail;
}
message = camel_mime_message_new();
if (camel_mime_part_construct_from_parser(CAMEL_MIME_PART (message), parser) == -1) {
g_warning("Construction failed");
goto fail;
}
gtk_object_unref(GTK_OBJECT (parser));
return message;
fail:
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
"Cannot get message: %s",
g_strerror(errno));
if (parser)
gtk_object_unref(GTK_OBJECT (parser));
if (message)
gtk_object_unref(GTK_OBJECT (message));
return NULL;
}
#endif
/* This probably shouldn't go here...but it will for now */
static gchar *
get_header_field (gchar *header, gchar *field)
@ -723,14 +640,13 @@ GPtrArray *
imap_get_summary (CamelFolder *folder, CamelException *ex)
{
/* TODO: code this - loop: "FETCH <i> BODY.PEEK[HEADER]" and parse */
/* TODO: Maybe use FETCH ENVELOPE instead */
GPtrArray *array = NULL;
CamelMessageInfo *info;
int i, num, status;
char *result;
char *result, *datestr;
num = imap_get_message_count (folder, ex);
array = g_ptr_array_new ();
for (i = 0; i < num; i++) {
@ -746,10 +662,15 @@ imap_get_summary (CamelFolder *folder, CamelException *ex)
info->subject = get_header_field (result, "\nSubject:");
info->to = get_header_field (result, "\nTo:");
info->from = get_header_field (result, "\nFrom:");
datestr = get_header_field (result, "\nDate:");
info->date_sent = header_decode_date (datestr, NULL);
g_free (datestr);
info->uid = NULL; /* FIXME: how can we get the UID? */
g_free (result);
/* still need to get flags and date_sent */
/* still need to get flags */
g_ptr_array_add (array, info);
}
@ -760,7 +681,20 @@ imap_get_summary (CamelFolder *folder, CamelException *ex)
void
imap_free_summary (CamelFolder *folder, GPtrArray *array)
{
/* no-op */
CamelMessageInfo *info;
gint i, max;
max = array->len;
for (i = 0; i < max; i++) {
info = g_ptr_array_index (array, i);
g_free (info->subject);
g_free (info->to);
g_free (info->from);
g_free (info->uid);
}
g_ptr_array_free (array, TRUE);
return;
}
@ -770,7 +704,7 @@ imap_summary_get_by_uid (CamelFolder *folder, const char *uid)
{
/* TODO: code this - do a "UID FETCH <uid> BODY.PEEK[HEADER]" and parse */
CamelMessageInfo *info = NULL;
char *result;
char *result, *datestr;
int status;
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
@ -785,10 +719,15 @@ imap_summary_get_by_uid (CamelFolder *folder, const char *uid)
info->subject = get_header_field (result, "\nSubject:");
info->to = get_header_field (result, "\nTo:");
info->from = get_header_field (result, "\nFrom:");
datestr = get_header_field (result, "\nDate:");
info->date_sent = header_decode_date (datestr, NULL);
g_free (datestr);
info->uid = g_strdup (uid);
g_free (result);
/* still need to get flags and date_sent */
/* still need to get flags */
return info;
}
@ -796,6 +735,8 @@ imap_summary_get_by_uid (CamelFolder *folder, const char *uid)
static GList *
imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
{
return NULL;
#if 0
/* TODO: find a good way of doing this */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
@ -811,9 +752,5 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
camel_folder_search_set_body_index(imap_folder->search, imap_folder->index);
return camel_folder_search_execute_expression(imap_folder->search, expression, ex);
#endif
}

View File

@ -35,9 +35,7 @@ extern "C" {
#include <gtk/gtk.h>
#include "camel-folder.h"
#include "camel-imap-summary.h"
#include <camel/camel-folder-search.h>
#include <libibex/ibex.h>
#define CAMEL_IMAP_FOLDER_TYPE (camel_imap_folder_get_type ())
#define CAMEL_IMAP_FOLDER(obj) (GTK_CHECK_CAST((obj), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolder))
@ -47,8 +45,6 @@ extern "C" {
typedef struct {
CamelFolder parent_object;
ibex *index; /* index for this folder */
CamelImapSummary *summary;
CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */
gint count;

View File

@ -1,771 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors: Jeffrey Stedfast <fejj@helixcode.com>
*
* Copyright 2000 Helix Code, Inc. (www.helixcode.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 Street #330, Boston, MA 02111-1307, USA.
*
*/
#include "camel-imap-summary.h"
#include <camel/camel-mime-message.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define io(x)
#define d(x)
#define CAMEL_IMAP_SUMMARY_VERSION (0x1000)
struct _CamelImapSummaryPrivate {
};
#define _PRIVATE(o) (((CamelImapSummary *)(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 void camel_imap_summary_class_init (CamelImapSummaryClass *klass);
static void camel_imap_summary_init (CamelImapSummary *obj);
static void camel_imap_summary_finalise (GtkObject *obj);
static CamelFolderSummaryClass *camel_imap_summary_parent;
enum SIGNALS {
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
guint
camel_imap_summary_get_type (void)
{
static guint type = 0;
if (!type) {
GtkTypeInfo type_info = {
"CamelImapSummary",
sizeof (CamelImapSummary),
sizeof (CamelImapSummaryClass),
(GtkClassInitFunc) camel_imap_summary_class_init,
(GtkObjectInitFunc) camel_imap_summary_init,
(GtkArgSetFunc) NULL,
(GtkArgGetFunc) NULL
};
type = gtk_type_unique (camel_folder_summary_get_type (), &type_info);
}
return type;
}
static void
camel_imap_summary_class_init (CamelImapSummaryClass *klass)
{
GtkObjectClass *object_class = (GtkObjectClass *) klass;
CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass;
camel_imap_summary_parent = gtk_type_class (camel_folder_summary_get_type ());
object_class->finalize = camel_imap_summary_finalise;
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;*/
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
}
static void
camel_imap_summary_init (CamelImapSummary *obj)
{
struct _CamelImapSummaryPrivate *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(CamelImapMessageInfo);
s->content_info_size = sizeof(CamelImapMessageContentInfo);
/* and a unique file version */
s->version += CAMEL_IMAP_SUMMARY_VERSION;
}
static void
camel_imap_summary_finalise (GtkObject *obj)
{
CamelImapSummary *mbs = (CamelImapSummary *)obj;
g_free(mbs->folder_path);
((GtkObjectClass *)(camel_imap_summary_parent))->finalize((GtkObject *)obj);
}
/**
* camel_imap_summary_new:
*
* Create a new CamelImapSummary object.
*
* Return value: A new CamelImapSummary widget.
**/
CamelImapSummary *
camel_imap_summary_new (const char *filename, const char *imap_name, ibex *index)
{
CamelImapSummary *new = CAMEL_IMAP_SUMMARY (gtk_type_new(camel_imap_summary_get_type ()));
if (new) {
/* ?? */
camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY (new), TRUE);
camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY (new), filename);
new->folder_path = g_strdup(imap_name);
new->index = index;
}
return new;
}
static int
summary_header_load (CamelFolderSummary *s, FILE *in)
{
CamelImapSummary *mbs = CAMEL_IMAP_SUMMARY (s);
if (((CamelFolderSummaryClass *)camel_imap_summary_parent)->summary_header_load(s, in) == -1)
return -1;
return camel_folder_summary_decode_uint32(in, &mbs->folder_size);
}
static int
summary_header_save(CamelFolderSummary *s, FILE *out)
{
CamelImapSummary *mbs = CAMEL_IMAP_SUMMARY (s);
if (((CamelFolderSummaryClass *)camel_imap_summary_parent)->summary_header_save(s, out) == -1)
return -1;
return camel_folder_summary_encode_uint32(out, mbs->folder_size);
}
static int
header_evolution_decode(const char *in, guint32 *uid, guint32 *flags)
{
char *header;
if (in && (header = header_token_decode(in))) {
if (strlen(header) == strlen("00000000-0000")
&& sscanf(header, "%08x-%04x", uid, flags) == 2) {
g_free(header);
return *uid;
}
g_free(header);
}
return -1;
}
static char *
header_evolution_encode (guint32 uid, guint32 flags)
{
return g_strdup_printf("%08x-%04x", uid, flags & 0xffff);
}
static CamelMessageInfo *
message_info_new (CamelFolderSummary *s, struct _header_raw *h)
{
CamelMessageInfo *mi;
mi = CAMEL_FOLDER_SUMMARY_CLASS (camel_imap_summary_parent)->message_info_new(s, h);
if (mi) {
const char *xev;
guint32 uid, flags;
CamelImapMessageInfo *mbi = (CamelImapMessageInfo *) mi;
xev = header_raw_find(&h, "X-Evolution", NULL);
if (xev && header_evolution_decode(xev, &uid, &flags) != -1) {
g_free(mi->uid);
mi->uid = g_strdup_printf("%u", uid);
mi->flags = flags;
} else {
/* to indicate it has no xev header? */
mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV;
mi->uid = g_strdup_printf("%u", camel_folder_summary_next_uid(s));
}
mbi->frompos = -1;
}
return mi;
}
static CamelMessageInfo *
message_info_new_from_parser (CamelFolderSummary *s, CamelMimeParser *mp)
{
CamelMessageInfo *mi;
CamelImapSummary *mbs = CAMEL_IMAP_SUMMARY (s);
mi = ((CamelFolderSummaryClass *)camel_imap_summary_parent)->message_info_new_from_parser(s, mp);
if (mi) {
CamelImapMessageInfo *mbi = (CamelImapMessageInfo *) mi;
mbi->frompos = camel_mime_parser_tell_start_from(mp);
/* do we want to index this message as we add it, as well? */
if (mbs->index_force
|| (mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0
|| !ibex_contains_name(mbs->index, mi->uid)) {
camel_folder_summary_set_index(s, mbs->index);
} else {
camel_folder_summary_set_index(s, NULL);
}
}
return mi;
}
static CamelMessageInfo *
message_info_load (CamelFolderSummary *s, FILE *in)
{
CamelMessageInfo *mi;
io(printf("loading imap message info\n"));
mi = ((CamelFolderSummaryClass *) camel_imap_summary_parent)->message_info_load(s, in);
if (mi) {
CamelImapMessageInfo *mbi = (CamelImapMessageInfo *) mi;
camel_folder_summary_decode_uint32(in, (guint32) &mbi->frompos);
}
return mi;
}
static int
message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi)
{
CamelImapMessageInfo *mbi = (CamelImapMessageInfo *) mi;
io(printf("saving imap message info\n"));
((CamelFolderSummaryClass *) camel_imap_summary_parent)->message_info_save(s, out, mi);
return camel_folder_summary_encode_uint32(out, mbi->frompos);
}
static int
summary_rebuild (CamelImapSummary *mbs, off_t offset)
{
CamelMimeParser *mp;
int fd;
int ok = 0;
printf("(re)Building summary from %d (%s)\n", (int)offset, mbs->folder_path);
fd = open(mbs->folder_path, O_RDONLY);
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) {
if (camel_mime_parser_tell_start_from(mp) != offset) {
g_warning("The next message didn't start where I expected\nbuilding summary from start");
camel_mime_parser_drop_step(mp);
offset = 0;
camel_mime_parser_seek(mp, offset, SEEK_SET);
camel_folder_summary_clear(CAMEL_FOLDER_SUMMARY (mbs));
} else {
camel_mime_parser_unstep(mp);
}
} else {
gtk_object_unref(GTK_OBJECT (mp));
/* end of file - no content? */
printf("We radn out of file?\n");
return -1;
}
}
while (camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM) {
CamelMessageInfo *info;
info = camel_folder_summary_add_from_parser(CAMEL_FOLDER_SUMMARY (mbs), mp);
if (info == NULL) {
printf("Could not build info from file?\n");
ok = -1;
break;
}
g_assert(camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM_END);
}
/* update the file size in the summary */
if (ok != -1)
mbs->folder_size = camel_mime_parser_seek(mp, 0, SEEK_CUR);
printf("updating folder size = %d\n", mbs->folder_size);
gtk_object_unref(GTK_OBJECT (mp));
return ok;
}
int
camel_imap_summary_update (CamelImapSummary *mbs, off_t offset)
{
int ret;
mbs->index_force = FALSE;
ret = summary_rebuild(mbs, offset);
#if 0
#warning "Saving full summary and index after every summarisation is slow ..."
if (ret != -1) {
if (camel_folder_summary_save(CAMEL_FOLDER_SUMMARY (mbs)) == -1)
g_warning("Could not save summary: %s", strerror(errno));
printf("summary saved\n");
if (mbs->index)
ibex_save(mbs->index);
printf("ibex saved\n");
}
#endif
return ret;
}
int
camel_imap_summary_load (CamelImapSummary *mbs, int forceindex)
{
CamelFolderSummary *s = CAMEL_FOLDER_SUMMARY (mbs);
struct stat st;
int ret = 0;
off_t minstart;
mbs->index_force = forceindex;
/* is the summary out of date? */
if (stat(mbs->folder_path, &st) == -1) {
camel_folder_summary_clear(s);
printf("Cannot summarise folder: '%s': %s\n", mbs->folder_path, strerror(errno));
return -1;
}
if (forceindex || camel_folder_summary_load(s) == -1) {
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
} else {
minstart = st.st_size;
#if 0
/* find out the first unindexed message ... */
/* TODO: For this to work, it has to check that the message is
indexable, and contains content ... maybe it cannot be done
properly? */
for (i=0;i<camel_folder_summary_count(s);i++) {
CamelMessageInfo *mi = camel_folder_summary_index(s, i);
if (!ibex_contains_name(mbs->index, mi->uid)) {
minstart = ((CamelImapMessageInfo *) mi)->frompos;
printf("Found unindexed message: %s\n", mi->uid);
break;
}
}
#endif
/* is the summary uptodate? */
if (st.st_size == mbs->folder_size && st.st_mtime == s->time) {
printf("Summary time and date match imap\n");
if (minstart < st.st_size) {
/* FIXME: Only clear the messages and reindex from this point forward */
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
}
} else {
if (mbs->folder_size < st.st_size) {
printf("Index is for a smaller imap\n");
if (minstart < mbs->folder_size) {
/* FIXME: only make it rebuild as necessary */
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
} else {
ret = summary_rebuild(mbs, mbs->folder_size);
}
} else {
printf("index is for a bigger imap\n");
camel_folder_summary_clear(s);
ret = summary_rebuild(mbs, 0);
}
}
}
if (ret != -1) {
mbs->folder_size = st.st_size;
s->time = st.st_mtime;
printf("saving summary\n");
if (camel_folder_summary_save(s) == -1)
g_warning("Could not save summary: %s", strerror(errno));
printf("summary saved\n");
if (mbs->index)
ibex_save(mbs->index);
printf("ibex saved\n");
}
return ret;
}
static int
header_write (int fd, struct _header_raw *header, char *xevline)
{
struct iovec iv[4];
int outlen = 0, len;
iv[1].iov_base = ":";
iv[1].iov_len = 1;
iv[3].iov_base = "\n";
iv[3].iov_len = 1;
while (header) {
if (strcasecmp(header->name, "X-Evolution")) {
iv[0].iov_base = header->name;
iv[0].iov_len = strlen(header->name);
iv[2].iov_base = header->value;
iv[2].iov_len = strlen(header->value);
do {
len = writev(fd, iv, 4);
} while (len == -1 && errno == EINTR);
if (len == -1)
return -1;
outlen += len;
}
header = header->next;
}
iv[0].iov_base = "X-Evolution: ";
iv[0].iov_len = strlen(iv[0].iov_base);
iv[1].iov_base = xevline;
iv[1].iov_len = strlen(xevline);
iv[2].iov_base = "\n\n";
iv[2].iov_len = 2;
do {
len = writev(fd, iv, 3);
} while (len == -1 && errno == EINTR);
if (len == -1)
return -1;
outlen += 1;
d(printf("Wrote %d bytes of headers\n", outlen));
return outlen;
}
static int
copy_block (int fromfd, int tofd, off_t start, size_t bytes)
{
char buffer[4096];
int written = 0;
d(printf("writing %d bytes ... ", bytes));
if (lseek(fromfd, start, SEEK_SET) != start)
return -1;
while (bytes > 0) {
int toread, towrite;
toread = bytes;
if (bytes>4096)
toread = 4096;
else
toread = bytes;
do {
towrite = read(fromfd, buffer, toread);
} while (towrite == -1 && errno == EINTR);
if (towrite == -1)
return -1;
/* check for 'end of file' */
if (towrite == 0) {
d(printf("end of file?\n"));
break;
}
do {
toread = write(tofd, buffer, towrite);
} while (toread == -1 && errno == EINTR);
if (toread == -1)
return -1;
written += toread;
bytes -= toread;
}
d(printf("written %d bytes\n", written));
return written;
}
int
camel_imap_summary_expunge (CamelImapSummary *mbs)
{
CamelMimeParser *mp = NULL;
int i, count;
CamelImapMessageInfo *info;
CamelFolderSummary *s = (CamelFolderSummary *) mbs;
int fd = -1, fdout= -1;
off_t offset = 0;
char *tmpname = 0;
char *buffer, *xevnew = NULL;
const char *xev;
int len;
guint32 uid, flags;
int quick = TRUE, work = FALSE;
/* make sure we're in sync */
count = camel_folder_summary_count(s);
if (count>0) {
CamelMessageInfo *mi = camel_folder_summary_index(s, count-1);
camel_imap_summary_update(mbs, mi->content->endpos);
} else {
camel_imap_summary_update(mbs, 0);
}
/* check if we have any work to do */
d(printf("Performing expunge, %d messages in inbox\n", count));
for (i=0;quick && i<count;i++) {
info = (CamelImapMessageInfo *)camel_folder_summary_index(s, i);
if (info->info.flags & (CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_FOLDER_NOXEV))
quick = FALSE;
else
work |= (info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0;
}
d(printf("Options: %s %s\n", quick?"quick":"", work?"Work":""));
if (quick && !work)
return 0;
fd = open(mbs->folder_path, O_RDWR);
if (fd == -1)
return -1;
mp = camel_mime_parser_new();
camel_mime_parser_scan_from(mp, TRUE);
camel_mime_parser_init_with_fd(mp, fd);
if (!quick) {
tmpname = alloca(strlen(mbs->folder_path)+5);
sprintf(tmpname, "%s.tmp", mbs->folder_path);
d(printf("Writing tmp file to %s\n", tmpname));
retry_out:
fdout = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, 0600);
if (fdout == -1) {
if (errno == EEXIST)
if (unlink(tmpname) != -1)
goto retry_out;
tmpname = 0;
goto error;
}
}
for (i = 0; i < count; i++) {
off_t frompos, bodypos;
off_t xevoffset;
info = (CamelImapMessageInfo *) camel_folder_summary_index(s, i);
g_assert(info);
d(printf("Looking at message %s\n", info->info.uid));
if (info->info.flags & CAMEL_MESSAGE_DELETED) {
d(printf("Deleting %s\n", info->info.uid));
g_assert(!quick);
offset -= (info->info.content->endpos - info->frompos);
if (mbs->index)
ibex_unindex(mbs->index, info->info.uid);
camel_folder_summary_remove(s, (CamelMessageInfo *)info);
count--;
i--;
info = NULL;
} else if (info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) {
int xevok = FALSE;
d(printf("Updating header for %s flags = %08x\n", info->info.uid, info->info.flags));
/* find the next message, header parts */
camel_mime_parser_seek(mp, info->frompos, SEEK_SET);
if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM)
goto error;
if (camel_mime_parser_tell_start_from(mp) != info->frompos) {
g_error("Summary/imap mismatch, aborting expunge");
goto error;
}
if (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_FROM_END)
goto error;
xev = camel_mime_parser_header(mp, "X-Evolution", (int *)&xevoffset);
if (xev && header_evolution_decode(xev, &uid, &flags) != -1) {
char name[64];
sprintf(name, "%u", uid);
if (strcmp(name, info->info.uid)) {
d(printf("Summary mismatch, aborting leaving mailbox intact\n"));
goto error;
}
xevok = TRUE;
}
xevnew = header_evolution_encode(strtoul(info->info.uid, NULL, 10), info->info.flags & 0xffff);
if (quick) {
if (!xevok) {
g_error("The summary told me I had an X-Evolution header, but i dont!");
goto error;
}
buffer = g_strdup_printf("X-Evolution: %s", xevnew);
do {
len = write(fd, buffer, strlen(buffer));
} while (len == -1 && errno == EINTR);
g_free(buffer);
if (len == -1) {
goto error;
}
} else {
frompos = lseek(fdout, 0, SEEK_CUR);
write(fdout, "From -\n", strlen("From -\n"));
if (header_write(fdout, camel_mime_parser_headers_raw(mp), xevnew) == -1) {
d(printf("Error writing to tmp mailbox\n"));
goto error;
}
bodypos = lseek(fdout, 0, SEEK_CUR);
d(printf("pos = %d, endpos = %d, bodypos = %d\n",
info->info.content->pos,
info->info.content->endpos,
info->info.content->bodypos));
if (copy_block(fd, fdout, info->info.content->bodypos,
info->info.content->endpos - info->info.content->bodypos) == -1) {
g_warning("Cannot copy data to output fd");
goto error;
}
info->frompos = frompos;
offset = bodypos - info->info.content->bodypos;
}
info->info.flags &= 0xffff;
g_free(xevnew); xevnew = NULL;
camel_mime_parser_drop_step(mp);
camel_mime_parser_drop_step(mp);
} else {
if (!quick) {
if (copy_block(fd, fdout, info->frompos,
info->info.content->endpos - info->frompos) == -1) {
g_warning("Cannot copy data to output fd");
goto error;
}
/* update from pos here? */
info->frompos += offset;
} else {
d(printf("Nothing to do for this message\n"));
}
}
if (!quick && info!=NULL && offset!=0) {
d(printf("offsetting content: %d\n", offset));
camel_folder_summary_offset_content(info->info.content, offset);
d(printf("pos = %d, endpos = %d, bodypos = %d\n",
info->info.content->pos,
info->info.content->endpos,
info->info.content->bodypos));
}
}
d(printf("Closing folders\n"));
if (close(fd) == -1) {
g_warning("Cannot close source folder: %s", strerror(errno));
goto error;
}
if (!quick) {
struct stat st;
if (close(fdout) == -1) {
g_warning("Cannot close tmp folder: %s", strerror(errno));
goto error;
}
if (rename(tmpname, mbs->folder_path) == -1) {
g_warning("Cannot rename folder: %s", strerror(errno));
goto error;
}
tmpname = 0;
if (stat(mbs->folder_path, &st) == -1)
goto error;
camel_folder_summary_touch(s);
s->time = st.st_mtime;
mbs->folder_size = st.st_size;
camel_folder_summary_save(s);
if (mbs->index)
ibex_save(mbs->index);
}
gtk_object_unref((GtkObject *)mp);
return 0;
error:
d(printf("Error occured: %s\n", strerror(errno)));
count = errno;
close(fd);
close(fdout);
g_free(xevnew);
if (tmpname)
unlink(tmpname);
if (mp)
gtk_object_unref((GtkObject *)mp);
errno = count;
return -1;
}

View File

@ -1,82 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2000 Helix Code Inc.
*
* Authors: Jeffrey Stedfast <fejj@helixcode.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* 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
*/
#ifndef _CAMEL_IMAP_SUMMARY_H
#define _CAMEL_IMAP_SUMMARY_H
#include <gtk/gtk.h>
#include <camel/camel-folder-summary.h>
#include <libibex/ibex.h>
#define CAMEL_IMAP_SUMMARY(obj) GTK_CHECK_CAST (obj, camel_imap_summary_get_type (), CamelImapSummary)
#define CAMEL_IMAP_SUMMARY_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, camel_imap_summary_get_type (), CamelImapSummaryClass)
#define IS_CAMEL_IMAP_SUMMARY(obj) GTK_CHECK_TYPE (obj, camel_imap_summary_get_type ())
typedef struct _CamelImapSummary CamelImapSummary;
typedef struct _CamelImapSummaryClass CamelImapSummaryClass;
/* extra summary flags */
enum {
CAMEL_MESSAGE_FOLDER_NOXEV = 1<<16,
/* CAMEL_MESSAGE_FOLDER_FLAGGED = 1<<17,*/
};
typedef struct _CamelImapMessageContentInfo {
CamelMessageContentInfo info;
} CamelImapMessageContentInfo;
typedef struct _CamelImapMessageInfo {
CamelMessageInfo info;
off_t frompos;
} CamelImapMessageInfo;
struct _CamelImapSummary {
CamelFolderSummary parent;
struct _CamelImapSummaryPrivate *priv;
char *folder_path; /* name of matching folder */
size_t folder_size; /* size of the imap file, last sync */
ibex *index;
int index_force; /* do we force index during creation? */
};
struct _CamelImapSummaryClass {
CamelFolderSummaryClass parent_class;
};
guint camel_imap_summary_get_type (void);
CamelImapSummary *camel_imap_summary_new (const char *filename, const char *imap_name, ibex *index);
/* load/check the summary */
int camel_imap_summary_load (CamelImapSummary *mbs, int forceindex);
/* incremental update */
int camel_imap_summary_update (CamelImapSummary *mbs, off_t offset);
/* perform a folder expunge */
int camel_imap_summary_expunge (CamelImapSummary *mbs);
#endif /* ! _CAMEL_IMAP_SUMMARY_H */

View File

@ -189,7 +189,7 @@ strstrcase (const gchar *haystack, const gchar *needle)
if (len > strlen(haystack))
return NULL;
for (ptr = haystack; *(ptr + len - 1) != '\0'; ptr++)
for (ptr = (char *)haystack; *(ptr + len - 1) != '\0'; ptr++)
if (!g_strncasecmp(ptr, needle, len))
return ptr;