Not necessarily Evolution-specific, but I've had reason to 'fix' my
mailboxes a number of times in the past year and so I've written this
little tool.
gcc -o mboxtool mboxtool.c `pkg-config --cflags --libs gmime-2.0`
Enjoy.
Jeff
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors: Jeffrey Stedfast [EMAIL PROTECTED]
*
* Copyright 2008 Novell, Inc. (www.novell.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.
*
*/
#ifdef HAVE_CONFIG_H
#include config.h
#endif
#include stdio.h
#include stdlib.h
#include string.h
#include sys/types.h
#include sys/stat.h
#include unistd.h
#include fcntl.h
#include errno.h
#include gmime/gmime.h
enum {
RESORT = (1 0),
REMDUP = (1 1),
REUID = (1 2),
REPLACE = (1 3),
};
typedef struct {
char *msg_id;
off_t msg_start;
off_t msg_uid;
time_t msg_date;
char *msg_key;
int msg_dup;
} MsgInfo;
static int
datecmp (const void *a, const void *b)
{
MsgInfo *mia = (MsgInfo *) *((void **) a);
MsgInfo *mib = (MsgInfo *) *((void **) b);
return mia-msg_date - mib-msg_date;
}
static void
xev_cb (GMimeParser *parser, const char *header, const char *value, off_t offset, off_t *save)
{
*save = offset;
}
static int
sort_mbox (GMimeStream *istream, GMimeStream *ostream, GMimeStream *dstream, guint32 flags)
{
GHashTable *msgid_hash = NULL;
GMimeMessage *message;
GMimeStream *stream;
GMimeParser *parser;
GPtrArray *summary;
MsgInfo *info;
int tz_offset;
off_t offset;
char *from;
int rv = 0;
guint32 i;
if (flags REMDUP)
msgid_hash = g_hash_table_new (g_str_hash, g_str_equal);
summary = g_ptr_array_new ();
parser = g_mime_parser_new ();
g_mime_parser_init_with_stream (parser, istream);
g_mime_parser_set_header_regex (parser, ^X-Evolution$, (GMimeParserHeaderRegexFunc) xev_cb, offset);
g_mime_parser_set_scan_from (parser, TRUE);
while (!g_mime_parser_eos (parser)) {
offset = -1;
if (!(message = g_mime_parser_construct_message (parser)))
continue;
info = g_new (MsgInfo, 1);
info-msg_id = g_strdup (g_mime_message_get_message_id (message));
info-msg_start = g_mime_parser_get_from_offset (parser);
info-msg_uid = offset info-msg_start ? (offset - info-msg_start) +
(summary-len 0 ? 1 : 0) : -1;
g_mime_message_get_date (message, info-msg_date, tz_offset);
info-msg_date -= tz_offset;
info-msg_key = g_strdup_printf (%s, info-msg_id);
info-msg_dup = (flags REMDUP) g_hash_table_lookup (msgid_hash, info-msg_key);
g_ptr_array_add (summary, info);
if ((flags REMDUP) !info-msg_dup)
g_hash_table_insert (msgid_hash, info-msg_key, info);
g_object_unref (message);
}
g_object_unref (parser);
if (msgid_hash != NULL)
g_hash_table_destroy (msgid_hash);
if (flags RESORT)
qsort (summary-pdata, summary-len, sizeof (void *), datecmp);
for (i = 0; i summary-len; i++) {
info = summary-pdata[i];
if ((rv = g_mime_stream_seek (istream, info-msg_start, GMIME_STREAM_SEEK_SET)) == -1)
break;
parser = g_mime_parser_new ();
g_mime_parser_init_with_stream (parser, istream);
g_mime_parser_set_scan_from (parser, TRUE);
message = g_mime_parser_construct_message (parser);
from = g_mime_parser_get_from (parser);
g_object_unref (parser);
if (info-msg_dup)
stream = dstream;
else
stream = ostream;
if (stream == NULL) {
g_free (from);
goto next;
}
offset = g_mime_stream_tell (stream);
if (offset 0 (rv = g_mime_stream_write (stream, \n, 1)) == -1) {
g_object_unref (message);
g_free (from);
break;
}
if ((rv = g_mime_stream_write_string (stream, from)) == -1) {
g_object_unref (message);
g_free (from);
break;
}
g_free (from);
if ((rv = g_mime_stream_write (stream, \n, 1)) == -1) {
g_object_unref (message);
break;
}
if ((rv = g_mime_object_write_to_stream ((GMimeObject *) message, stream)) == -1) {
g_object_unref (message);
break;
}
g_object_unref (message);
if ((flags REUID) offset != -1 info-msg_uid != -1) {
if ((rv = g_mime_stream_seek (stream, offset + info-msg_uid, GMIME_STREAM_SEEK_SET)) == -1)
break;
if ((rv = g_mime_stream_printf (stream, X-Evolution: %08x-, i + 1)) == -1)
break;
if ((rv = g_mime_stream_seek (stream, 0, GMIME_STREAM_SEEK_END))