Index: src/tracker-indexer/tracker-main.c
===================================================================
--- src/tracker-indexer/tracker-main.c	(revision 2761)
+++ src/tracker-indexer/tracker-main.c	(working copy)
@@ -44,7 +44,10 @@
 
 #include <libtracker-data/tracker-data-update.h>
 #include <libtracker-data/tracker-turtle.h>
+#include <libtracker-data/tracker-data-manager.h>
 
+#include <tracker-evolution-plugin/tracker-evolution-indexer.h>
+
 #include "tracker-dbus.h"
 #include "tracker-indexer.h"
 
@@ -254,11 +257,14 @@
 main (gint argc, gchar *argv[])
 {
 	TrackerConfig *config;
+	TrackerLanguage *language;
 	TrackerIndexer *indexer;
 	TrackerDBManagerFlags flags = 0;
 	GOptionContext *context;
 	GError *error = NULL;
 	gchar *filename;
+	TrackerDBIndex *file_index;
+	TrackerDBIndex *email_index;
 
 	g_type_init ();
 
@@ -296,6 +302,7 @@
 
 	/* Initialize logging */
 	config = tracker_config_new ();
+	language = tracker_language_new (config);
 
 	if (verbosity > -1) {
 		tracker_config_set_verbosity (config, verbosity);
@@ -371,6 +378,13 @@
                 tracker_indexer_process_modules (indexer, modules);
         }
 
+	file_index = tracker_db_index_manager_get_index (TRACKER_DB_INDEX_FILE);
+	email_index = tracker_db_index_manager_get_index (TRACKER_DB_INDEX_EMAIL);
+
+	tracker_data_manager_init (config, language, file_index, email_index);
+
+	tracker_evolution_idx_init (config);
+
 	tracker_turtle_init ();
 
 	g_message ("Starting...");
@@ -383,6 +397,10 @@
 
 	tracker_turtle_shutdown ();
 
+	tracker_evolution_idx_shutdown ();
+	tracker_data_manager_shutdown ();
+	g_object_unref (language);
+
 	if (quit_timeout_id) {
 		g_source_remove (quit_timeout_id);
 	}
Index: src/tracker-indexer/Makefile.am
===================================================================
--- src/tracker-indexer/Makefile.am	(revision 2761)
+++ src/tracker-indexer/Makefile.am	(working copy)
@@ -55,6 +55,7 @@
 	$(top_builddir)/src/libtracker-db/libtracker-db.la 		\
 	$(top_builddir)/src/libtracker-common/libtracker-common.la 	\
 	$(top_builddir)/src/libstemmer/libstemmer.la	 		\
+	$(top_builddir)/src/tracker-evolution-plugin/libtracker-evolution-indexer.la \
 	$(trackerd_win_libs)						\
 	$(DBUS_LIBS)							\
 	$(GMODULE_LIBS)							\
Index: src/trackerd/tracker-main.c
===================================================================
--- src/trackerd/tracker-main.c	(revision 2761)
+++ src/trackerd/tracker-main.c	(working copy)
@@ -53,8 +53,11 @@
 #include <libtracker-db/tracker-db-index.h>
 #include <libtracker-db/tracker-db-index-manager.h>
 
+#include <libtracker-data/tracker-data-manager.h>
 #include <libtracker-data/tracker-turtle.h>
 
+#include <tracker-evolution-plugin/tracker-evolution.h>
+
 #include "tracker-crawler.h"
 #include "tracker-dbus.h"
 #include "tracker-indexer-client.h"
@@ -1026,11 +1029,11 @@
 		return EXIT_FAILURE;
 	}
 
+	tracker_module_config_init ();
+
 	tracker_turtle_init ();
 	tracker_thumbnailer_init (config);
 
-	tracker_module_config_init ();
-
 	flags |= TRACKER_DB_MANAGER_REMOVE_CACHE;
 	index_flags |= TRACKER_DB_INDEX_MANAGER_READONLY;
 
@@ -1128,6 +1131,8 @@
 		return EXIT_FAILURE;
 	}
 
+	tracker_evolution_init (config);
+
 	g_message ("Waiting for DBus requests...");
 
 	/* Set our status as running, if this is FALSE, threads stop
@@ -1174,6 +1179,8 @@
 
 	g_timeout_add_full (G_PRIORITY_LOW, 5000, shutdown_timeout_cb, NULL, NULL);
 
+	tracker_evolution_shutdown ();
+
 	g_message ("Waiting for indexer to finish");
 	org_freedesktop_Tracker_Indexer_shutdown (tracker_dbus_indexer_get_proxy (), &error);
 
Index: src/trackerd/Makefile.am
===================================================================
--- src/trackerd/Makefile.am	(revision 2761)
+++ src/trackerd/Makefile.am	(working copy)
@@ -77,6 +77,7 @@
 	$(top_builddir)/src/libtracker-db/libtracker-db.la 		\
 	$(top_builddir)/src/libtracker-common/libtracker-common.la 	\
 	$(top_builddir)/src/libstemmer/libstemmer.la	 		\
+	$(top_builddir)/src/tracker-evolution-plugin/libtracker-evolution.la \
 	$(inotify_libs)							\
 	$(GMIME_LIBS)							\
 	$(FAM_LIBS)							\
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 2761)
+++ src/Makefile.am	(working copy)
@@ -28,6 +28,10 @@
 build_libtrackergtk = libtracker-gtk
 endif
 
+if HAVE_EVOPLUG
+build_evoplug = tracker-evolution-plugin
+endif
+
 SUBDIRS = 					\
 	libstemmer				\
 	$(build_qdbm)				\
@@ -37,6 +41,7 @@
 	libtracker-data				\
 	libtracker				\
 	$(build_sqlite_fts)			\
+	$(build_evoplug)			\
 	trackerd				\
 	tracker-utils				\
 	tracker-extract				\
@@ -62,4 +67,5 @@
 	libtracker-gtk				\
 	tracker-applet	 			\
 	tracker-search-tool			\
-	tracker-preferences
+	tracker-preferences			\
+	tracker-evolution-plugin
Index: src/tracker-evolution-plugin/tracker-evolution-plugin.h
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-plugin.h	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-plugin.h	(revision 0)
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#ifndef __TRACKER_EVOLUTION_PLUGIN_H__
+#define __TRACKER_EVOLUTION_PLUGIN_H__
+
+#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
+#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
+#endif
+
+#include <glib.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include <libtracker-common/tracker-common.h>
+
+#include "tracker-evolution-common.h"
+
+#define TRACKER_TYPE_EVOLUTION_PLUGIN          (tracker_evolution_plugin_get_type())
+#define TRACKER_EVOLUTION_PLUGIN(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPlugin))
+#define TRACKER_EVOLUTION_PLUGIN_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginClass))
+#define TRACKER_EVOLUTION_PLUGIN_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginClass))
+
+G_BEGIN_DECLS
+
+typedef struct TrackerEvolutionPlugin TrackerEvolutionPlugin;
+typedef struct TrackerEvolutionPluginClass TrackerEvolutionPluginClass;
+
+struct TrackerEvolutionPlugin {
+	GObject parent;
+};
+
+struct TrackerEvolutionPluginClass {
+	GObjectClass parent;
+};
+
+GType tracker_evolution_plugin_get_type (void);
+
+void tracker_evolution_plugin_register  (TrackerEvolutionPlugin *object, 
+					 gchar *registrar_path,
+					 guint last_checkout, 
+					 DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __TRACKER_EVOLUTION_PLUGIN_H__ */
Index: src/tracker-evolution-plugin/tracker-evolution-indexer.h
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-indexer.h	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-indexer.h	(revision 0)
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#ifndef __LIBTRACKER_EVOLUTION_H__
+#define __LIBTRACKER_EVOLUTION_H__
+
+#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
+#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
+#endif
+
+#include <glib.h>
+
+#include <libtracker-common/tracker-common.h>
+
+G_BEGIN_DECLS
+
+#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
+#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
+#endif
+
+#include <glib.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include "tracker-evolution-common.h"
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_EVOLUTION_INDEXER          (tracker_evolution_indexer_get_type())
+#define TRACKER_EVOLUTION_INDEXER(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexer))
+#define TRACKER_EVOLUTION_INDEXER_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexerClass))
+#define TRACKER_EVOLUTION_INDEXER_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexerClass))
+
+G_BEGIN_DECLS
+
+typedef struct TrackerEvolutionIndexer TrackerEvolutionIndexer;
+typedef struct TrackerEvolutionIndexerClass TrackerEvolutionIndexerClass;
+
+struct TrackerEvolutionIndexer {
+	GObject parent;
+};
+
+struct TrackerEvolutionIndexerClass {
+	GObjectClass parent;
+};
+
+GType  tracker_evolution_indexer_get_type   (void);
+
+void  tracker_evolution_indexer_set         (TrackerEvolutionIndexer *object, 
+					     const gchar *subject, 
+					     const GStrv predicates,
+					     const GStrv values,
+					     DBusGMethodInvocation *context);
+void  tracker_evolution_indexer_set_many    (TrackerEvolutionIndexer *object, 
+					     const GStrv subjects, 
+					     const GPtrArray *predicates,
+					     const GPtrArray *values,
+					     DBusGMethodInvocation *context);
+void  tracker_evolution_indexer_unset_many  (TrackerEvolutionIndexer *object, 
+					     const GStrv subjects, 
+					     DBusGMethodInvocation *context);
+void  tracker_evolution_indexer_unset       (TrackerEvolutionIndexer *object, 
+					     const gchar *subject, 
+					     DBusGMethodInvocation *context);
+void  tracker_evolution_indexer_cleanup     (TrackerEvolutionIndexer *object, 
+					     DBusGMethodInvocation *context);
+
+void  tracker_evolution_idx_init            (TrackerConfig *config);
+void  tracker_evolution_idx_shutdown        (void);
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_EVOLUTION_H__ */
Index: src/tracker-evolution-plugin/tracker-evolution.h
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution.h	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution.h	(revision 0)
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#ifndef __LIBTRACKER_EVOLUTION_H__
+#define __LIBTRACKER_EVOLUTION_H__
+
+#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
+#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
+#endif
+
+#include <glib.h>
+
+#include <libtracker-common/tracker-common.h>
+
+G_BEGIN_DECLS
+
+void  tracker_evolution_init     (TrackerConfig *config);
+void  tracker_evolution_shutdown (void);
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_EVOLUTION_H__ */
Index: src/tracker-evolution-plugin/tracker-evolution-registrar.h
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-registrar.h	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-registrar.h	(revision 0)
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#ifndef __LIBTRACKER_EVOLUTION_REGISTRAR_H__
+#define __LIBTRACKER_EVOLUTION_REGISTRAR_H__
+
+#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
+#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
+#endif
+
+#include <glib.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include "tracker-evolution-common.h"
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_EVOLUTION_REGISTRAR          (tracker_evolution_registrar_get_type())
+#define TRACKER_EVOLUTION_REGISTRAR(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrar))
+#define TRACKER_EVOLUTION_REGISTRAR_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarClass))
+#define TRACKER_EVOLUTION_REGISTRAR_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarClass))
+
+G_BEGIN_DECLS
+
+extern const DBusGObjectInfo dbus_glib_tracker_evolution_registrar_object_info;
+
+typedef struct TrackerEvolutionRegistrar TrackerEvolutionRegistrar;
+typedef struct TrackerEvolutionRegistrarClass TrackerEvolutionRegistrarClass;
+
+struct TrackerEvolutionRegistrar {
+	GObject parent;
+};
+
+struct TrackerEvolutionRegistrarClass {
+	GObjectClass parent;
+};
+
+GType  tracker_evolution_registrar_get_type   (void);
+
+void  tracker_evolution_registrar_set         (TrackerEvolutionRegistrar *object, 
+					       const gchar *subject, 
+					       const GStrv predicates,
+					       const GStrv values,
+					       DBusGMethodInvocation *context);
+void  tracker_evolution_registrar_set_many    (TrackerEvolutionRegistrar *object, 
+					       const GStrv subjects, 
+					       const GPtrArray *predicates,
+					       const GPtrArray *values,
+					       DBusGMethodInvocation *context);
+void  tracker_evolution_registrar_unset_many  (TrackerEvolutionRegistrar *object, 
+					       const GStrv subjects, 
+					       DBusGMethodInvocation *context);
+void  tracker_evolution_registrar_unset       (TrackerEvolutionRegistrar *object, 
+					       const gchar *subject, 
+					       DBusGMethodInvocation *context);
+void  tracker_evolution_registrar_cleanup     (TrackerEvolutionRegistrar *object, 
+					       DBusGMethodInvocation *context);
+
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_EVOLUTION_REGISTRAR_H__ */
Index: src/tracker-evolution-plugin/tracker-evolution-plugin.xml
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-plugin.xml	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-plugin.xml	(revision 0)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+  <interface name="org.gnome.evolution.metadata.Manager">  
+    <method name="Register">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="o" name="registrar_path" direction="in" />
+      <arg type="u" name="last_checkout" direction="in" />
+    </method>
+  </interface>
+</node>
+
Index: src/tracker-evolution-plugin/liborg-freedesktop-Tracker-evolution-plugin.eplug.xml
===================================================================
--- src/tracker-evolution-plugin/liborg-freedesktop-Tracker-evolution-plugin.eplug.xml	(revision 0)
+++ src/tracker-evolution-plugin/liborg-freedesktop-Tracker-evolution-plugin.eplug.xml	(revision 0)
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+	<e-plugin id="org.freedesktop.Tracker.evolution_plugin" 
+		type="shlib"
+		location="+PLUGIN_INSTALL_DIR+/liborg-freedesktop-Tracker-evolution-plugin.so"
+		domain="+GETTEXT_PACKAGE+"
+		localedir="+LOCALEDIR+"
+		_name="TrackerEvolutionPlugin"
+		load-on-startup="true">
+
+		<_description>Support for Tracker.</_description>
+
+		<author name="Philip Van Hoof" email="philip@codeminded.be"/>
+	</e-plugin>
+</e-plugin-list>
Index: src/tracker-evolution-plugin/tracker-evolution-common.h
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-common.h	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-common.h	(revision 0)
@@ -0,0 +1,80 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#ifndef __TRACKER_EVOLUTION_COMMON_H__
+#define __TRACKER_EVOLUTION_COMMON_H__
+
+#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
+#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
+#endif
+
+#define TRACKER_EVOLUTION_INDEXER_PATH		"/org/freedesktop/Tracker/Indexer/Evolution/Registrar"
+
+#define TRACKER_EVOLUTION_REGISTRAR_SERVICE	"org.freedesktop.Tracker"
+#define TRACKER_EVOLUTION_REGISTRAR_PATH	"/org/freedesktop/Tracker/Evolution/Registrar"
+#define TRACKER_EVOLUTION_REGISTRAR_INTERFACE	"org.gnome.evolution.metadata.Registrar"
+
+#define TRACKER_EVOLUTION_MANAGER_SERVICE	"org.gnome.evolution"
+#define TRACKER_EVOLUTION_MANAGER_PATH		"/org/gnome/evolution/metadata/Manager"
+#define TRACKER_EVOLUTION_MANAGER_INTERFACE	"org.gnome.evolution.metadata.Manager"
+
+#define DBUS_ERROR_DOMAIN			"TrackerEvolution"
+#define DBUS_ERROR				g_quark_from_static_string (DBUS_ERROR_DOMAIN)
+
+#define TRACKER_EVOLUTION_PREDICATE_SUBJECT	"Evolution:MessageSubject"
+#define TRACKER_EVOLUTION_PREDICATE_SENT	"Evolution:MessageSent"
+#define TRACKER_EVOLUTION_PREDICATE_FROM	"Evolution:MessageFrom"
+#define TRACKER_EVOLUTION_PREDICATE_TO		"Evolution:MessageTo"
+#define TRACKER_EVOLUTION_PREDICATE_FILE	"Evolution:MessageFile"
+#define TRACKER_EVOLUTION_PREDICATE_CC		"Evolution:MessageCc"
+#define TRACKER_EVOLUTION_PREDICATE_UID		"Evolution:MessageUid"
+#define TRACKER_EVOLUTION_PREDICATE_SEEN	"Evolution:MessageSeen"
+#define TRACKER_EVOLUTION_PREDICATE_JUNK	"Evolution:MessageJunk"
+#define TRACKER_EVOLUTION_PREDICATE_ANSWERED	"Evolution:MessageAnswered"
+#define TRACKER_EVOLUTION_PREDICATE_FLAGGED	"Evolution:MessageFlagged"
+#define TRACKER_EVOLUTION_PREDICATE_TAG		"Evolution:MessageTag"
+#define TRACKER_EVOLUTION_PREDICATE_FORWARDED	"Evolution:MessageForwarded"
+#define TRACKER_EVOLUTION_PREDICATE_DELETED	"Evolution:MessageDeleted"
+#define TRACKER_EVOLUTION_PREDICATE_SIZE	"Evolution:MessageSize"
+
+#define TRACKER_TYPE_G_STRV_ARRAY   (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRV))
+
+#define dbus_async_return_if_fail(expr,context)				\
+	G_STMT_START {							\
+		if G_LIKELY(expr) { } else {				\
+			GError *error = NULL;				\
+									\
+			g_set_error (&error,				\
+				     DBUS_ERROR,			\
+				     0,					\
+				     "Assertion `%s' failed",		\
+				     #expr);				\
+									\
+			dbus_g_method_return_error (context, error);	\
+			g_error_free (error);				\
+									\
+			return;						\
+		};							\
+	} G_STMT_END
+
+#endif /* __TRACKER_EVOLUTION_COMMON_H__ */
Index: src/tracker-evolution-plugin/Makefile.am
===================================================================
--- src/tracker-evolution-plugin/Makefile.am	(revision 0)
+++ src/tracker-evolution-plugin/Makefile.am	(revision 0)
@@ -0,0 +1,102 @@
+INCLUDES =						\
+	-I$(top_srcdir)/src				\
+	-DGETTEXT_PACKAGE="\"$(GETTEXT_PACKAGE)\""	\
+	-DLOCALEDIR="\"$(LOCALEDIR)\""			\
+	-DTRACKER_COMPILATION				\
+	$(DBUS_CFLAGS)					\
+	$(GMIME_CFLAGS)					\
+	$(EVOPLUG_CFLAGS)
+
+%.eplug.in: %.eplug.xml
+	LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@
+
+%.eplug: %.eplug.in
+	sed -e "s%+PLUGIN_INSTALL_DIR+%$(EVOPLUG_INSTALL_DIR)%" \
+	-e "s%+GETTEXT_PACKAGE+%$(GETTEXT_PACKAGE)%" \
+	-e "s%+LOCALEDIR+%$(LOCALEDIR)%" \
+	$< > $@
+
+eplugindir = $(EVOPLUG_INSTALL_DIR)
+
+eplugin_DATA = liborg-freedesktop-Tracker-evolution-plugin.eplug
+
+eplugin_LTLIBRARIES = liborg-freedesktop-Tracker-evolution-plugin.la
+
+noinst_LTLIBRARIES = libtracker-evolution.la libtracker-evolution-indexer.la
+
+libtracker_evolution_indexer_la_SOURCES =				\
+	tracker-evolution-indexer.c					\
+	tracker-evolution-indexer.h					\
+	tracker-evolution-registrar-glue.h				\
+	tracker-evolution-common.h
+
+libtracker_evolution_la_SOURCES =	 				\
+	tracker-evolution.c						\
+	tracker-evolution.h						\
+	tracker-evolution-registrar.c					\
+	tracker-evolution-registrar.h					\
+	tracker-evolution-common.h					\
+	tracker-evolution-registrar-glue.h
+
+libtracker_evolution_la_LIBADD = 					\
+	$(top_builddir)/src/libtracker-data/libtracker-data.la          \
+	$(top_builddir)/src/libtracker-db/libtracker-db.la              \
+	$(top_builddir)/src/libtracker-common/libtracker-common.la      \
+	$(DBUS_LIBS)                                                    \
+	$(GTHREAD_LIBS)                                                 \
+	$(GIO_LIBS)                                                     \
+	$(GLIB2_LIBS)                                                   \
+	$(RAPTOR_LIBS)
+
+libtracker_evolution_indexer_la_LIBADD = 				\
+	$(top_builddir)/src/libtracker-data/libtracker-data.la          \
+	$(top_builddir)/src/libtracker-db/libtracker-db.la              \
+	$(top_builddir)/src/libtracker-common/libtracker-common.la      \
+	$(DBUS_LIBS)                                                    \
+	$(GTHREAD_LIBS)                                                 \
+	$(GIO_LIBS)                                                     \
+	$(GLIB2_LIBS)                                                   \
+	$(RAPTOR_LIBS)							\
+	$(GMIME_LIBS)
+
+liborg_freedesktop_Tracker_evolution_plugin_la_SOURCES = 		\
+	tracker-evolution-plugin.c 			 		\
+	tracker-evolution-plugin.h					\
+	tracker-evolution-common.h					\
+	$(marshal_sources)						\
+	tracker-evolution-plugin-glue.h
+
+liborg_freedesktop_Tracker_evolution_plugin_la_LDFLAGS = -module -avoid-version
+liborg_freedesktop_Tracker_evolution_plugin_la_LDLIBS = 		\
+	$(EVOPLUG_LIBS)							\
+	$(DBUS_LIBS)
+
+dbus_sources = 								\
+	tracker-evolution-plugin-glue.h					\
+	tracker-evolution-registrar-glue.h
+
+%-glue.h: %.xml
+	$(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+
+tracker-evolution-marshal.h: tracker-evolution-marshal.list
+	$(GLIB_GENMARSHAL) $< --prefix=tracker_evolution_marshal --header > $@ 
+
+tracker-evolution-marshal.c: tracker-evolution-marshal.list
+	$(GLIB_GENMARSHAL) $< --prefix=tracker_evolution_marshal --body > $@
+
+marshal_sources =							\
+	tracker-evolution-marshal.h					\
+	tracker-evolution-marshal.c
+
+BUILT_SOURCES = 							\
+	$(dbus_sources)							\
+	$(marshal_sources)						\
+	$(eplugin_DATA)
+
+CLEANFILES = $(BUILT_SOURCES) \
+	liborg-freedesktop-Tracker-evolution-plugin.eplug
+
+EXTRA_DIST = 								\
+	$(BUILT_SOURCES)						\
+	tracker-evolution-marshal.list					\
+	org-freedesktop-Tracker-evolution-plugin.eplug.xml
Index: src/tracker-evolution-plugin/tracker-evolution-plugin.c
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-plugin.c	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-plugin.c	(revision 0)
@@ -0,0 +1,1584 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+#include <signal.h>
+#include <time.h>
+#include <inttypes.h>
+
+#include <sqlite3.h>
+
+#include <camel/camel-mime-message.h>
+#include <camel/camel-i18n.h>
+#include <camel/camel-store.h>
+#include <camel/camel-folder.h>
+#include <camel/camel-db.h>
+#include <camel/camel-offline-store.h>
+
+#include <mail/mail-config.h>
+#include <camel/camel-session.h>
+#include <mail/mail-session.h>
+#include <mail/em-utils.h>
+#include <mail/mail-ops.h>
+
+#include <e-util/e-config.h>
+
+#include <libedataserver/e-account.h>
+#include <libedataserver/e-account-list.h>
+
+#include <gtk/gtk.h>
+
+#include <gconf/gconf-client.h>
+
+#include "tracker-evolution-plugin.h"
+#include "tracker-evolution-plugin-glue.h"
+
+
+#define MAX_BEFORE_SEND		100
+#define DIRKEY "/apps/evolution/mail/Tracker"
+#define DIRKEY_LENGTH (G_N_ELEMENTS (DIRKEY) - 1)
+
+G_DEFINE_TYPE (TrackerEvolutionPlugin, tracker_evolution_plugin, G_TYPE_OBJECT)
+
+#define TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginPrivate))
+
+/* This runs in-process of evolution (in the mailer, as a EPlugin). It has 
+ * access to the CamelSession using the external variable 'session'. The header
+ * mail/mail-session.h makes this variable public */
+
+#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func)
+
+#define EXTRACT_FIRST_STRING(val) len=strtoul (part, &part, 10); if (*part) part++; val=g_strndup (part, len); part+=len;
+#define EXTRACT_STRING(val) if (*part) part++; len=strtoul (part, &part, 10); if (*part) part++; val=g_strndup (part, len); part+=len;
+#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
+#define EXTRACT_DIGIT(val) if (*part && *part == ' ') part++; val=strtoul (part, &part, 10);
+
+typedef struct {
+	guint64 last_checkout;
+	DBusGProxy *registrar;
+} ClientRegistry;
+
+typedef struct {
+	TrackerEvolutionPlugin *self;
+	gchar *account_uri;
+	guint hook_id;
+} OnSummaryChangedInfo;
+
+typedef struct {
+	OnSummaryChangedInfo *hook_info;
+	CamelFolder *folder;
+} FolderRegistry;
+
+typedef struct {
+	EAccount *account;
+	TrackerEvolutionPlugin *self;
+	guint hook_id;
+	CamelStore *store;
+} StoreRegistry;
+
+typedef struct {
+	TrackerEvolutionPlugin *self;
+	gchar *account_uri;
+	ClientRegistry *info;
+} IntroductionInfo;
+
+typedef struct {
+	TrackerEvolutionPlugin *self;
+	gchar *uri;
+	gboolean old_state;
+	EAccount *account;
+} RegisterInfo;
+
+typedef struct {
+	DBusGConnection *connection;
+	GHashTable *registrars;
+	GStaticRecMutex *mutex;
+	GHashTable *registered_folders;
+	GHashTable *cached_folders;
+	GHashTable *registered_stores;
+	GList *registered_clients;
+	EAccountList *accounts;
+} TrackerEvolutionPluginPrivate;
+
+static DBusGProxy *dbus_proxy = NULL;
+static TrackerEvolutionPlugin *manager = NULL;
+static GStaticRecMutex glock = G_STATIC_REC_MUTEX_INIT;
+
+enum {
+	PROP_0,
+	PROP_CONNECTION
+};
+
+
+static void register_account (TrackerEvolutionPlugin *self, EAccount *account);
+static void unregister_account (TrackerEvolutionPlugin *self, EAccount *account);
+int e_plugin_lib_enable (EPluginLib *ep, int enable);
+static void metadata_set_many (TrackerEvolutionPlugin *self, GStrv subjects, GPtrArray *predicates, GPtrArray *values);
+static void metadata_unset_many (TrackerEvolutionPlugin *self, GStrv subjects);
+
+/* Not in the public headers of DBus? */
+gchar* dbus_g_method_get_sender (DBusGMethodInvocation *context);
+
+
+static GList *
+get_recipient_list (const gchar *str)
+{
+	GList *list = NULL;
+	gchar **arr;
+	gint i;
+
+	if (!str) {
+		return NULL;
+	}
+
+	arr = g_strsplit (str, ",", -1);
+
+	for (i = 0; arr[i]; i++) {
+		g_strstrip (arr[i]);
+		list = g_list_prepend (list, g_strdup (arr[i]));
+	}
+
+	g_strfreev (arr);
+
+	return g_list_reverse (list);
+}
+
+/*static void
+on_plugin_dying (OnSummaryChangedInfo *hook_info)
+{
+	hook_info->self = NULL;
+}*/
+
+static void
+folder_registry_free (FolderRegistry *registry)
+{
+	camel_object_remove_event (registry->folder, registry->hook_info->hook_id);
+	camel_object_unref (registry->folder);
+	/*g_object_weak_unref (G_OBJECT (registry->hook_info->self), 
+			     (GWeakNotify) on_plugin_dying, 
+			     registry->hook_info);*/
+	g_free (registry->hook_info->account_uri);
+	g_slice_free (OnSummaryChangedInfo, registry->hook_info);
+	g_slice_free (FolderRegistry, registry);
+}
+
+static FolderRegistry*
+folder_registry_new (const gchar *account_uri, CamelFolder *folder, TrackerEvolutionPlugin *self)
+{
+	FolderRegistry *registry = g_slice_new (FolderRegistry);
+	registry->hook_info = g_slice_new (OnSummaryChangedInfo);
+	registry->hook_info->account_uri = g_strdup (account_uri);
+	/*g_object_weak_ref (G_OBJECT (self), 
+			   (GWeakNotify) on_plugin_dying, 
+			   registry->hook_info);*/
+	registry->hook_info->self = self; /* weak */
+	registry->hook_info->hook_id = 0;
+	camel_object_ref (folder);
+	registry->folder = folder;
+	return registry;
+}
+
+static void
+process_fields (GPtrArray *predicates_temp, GPtrArray *values_temp, gchar *uid, guint flags, gchar *sent, gchar *subject, gchar *from, gchar *to, gchar *cc, gchar *size, CamelFolder *folder)
+{
+	GList *list, *l;
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_UID));
+	g_ptr_array_add (values_temp, g_strdup (uid));
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SEEN));
+	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_SEEN)?"True":"False"));
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_JUNK));
+	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_JUNK)?"True":"False"));
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_DELETED));
+	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_DELETED)?"True":"False"));
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_ANSWERED));
+	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_ANSWERED)?"True":"False"));
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FLAGGED));
+	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_FLAGGED)?"True":"False"));
+
+	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FORWARDED));
+	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_FORWARDED)?"True":"False"));
+
+
+	if (subject && g_utf8_validate (subject, -1, NULL)) {
+		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SUBJECT));
+		g_ptr_array_add (values_temp, g_strdup (subject));
+	}
+
+	list = get_recipient_list (to);
+	for (l = list; l; l = l->next) {
+		if (l->data && g_utf8_validate (l->data, -1, NULL)) {
+			g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TO));
+			g_ptr_array_add (values_temp, l->data);
+		} else
+			g_free (l->data);
+	}
+	g_list_free (list);
+
+	if (from && g_utf8_validate (from, -1, NULL)) {
+		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FROM));
+		g_ptr_array_add (values_temp, g_strdup (from));
+	}
+
+	if (size && g_utf8_validate (size, -1, NULL)) {
+		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SIZE));
+		g_ptr_array_add (values_temp, g_strdup (size));
+	}
+
+	list = get_recipient_list (cc);
+	for (l = list; l; l = l->next) {
+		if (l->data && g_utf8_validate (l->data, -1, NULL)) {
+			g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_CC));
+			g_ptr_array_add (values_temp, l->data);
+		} else
+			g_free (l->data);
+	}
+	g_list_free (list);
+
+	if (sent && g_utf8_validate (sent, -1, NULL)) {
+		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SENT));
+		g_ptr_array_add (values_temp, g_strdup (sent));
+	}
+
+	if (folder) {
+		gchar *filen = camel_folder_get_filename (folder, uid, NULL);
+		if (filen) {
+			g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FILE));
+			g_ptr_array_add (values_temp, filen);
+		}
+	}
+
+}
+
+/* If new messages arrive to- or get deleted from the summary */
+
+static void
+on_folder_summary_changed (CamelFolder *folder, CamelFolderChangeInfo *changes, gpointer user_data)
+{
+	OnSummaryChangedInfo *info = user_data;
+	TrackerEvolutionPlugin *self  = info->self;
+	CamelFolderSummary *summary;
+	gchar *account_uri = info->account_uri;
+	GPtrArray *merged;
+	guint i;
+	gchar *em_uri;
+
+	if (!folder)
+		return;
+
+	summary = folder->summary;
+	em_uri = em_uri_from_camel (account_uri);
+
+	merged = g_ptr_array_new ();
+
+	if (changes->uid_added && changes->uid_added->len > 0) {
+		for (i = 0; i < changes->uid_added->len; i++)
+			g_ptr_array_add (merged, changes->uid_added->pdata[i]);
+	}
+
+	if (changes->uid_changed && changes->uid_changed->len > 0) {
+		gboolean found = FALSE;
+		guint y;
+
+		for (i = 0; i < changes->uid_changed->len; i++) {
+			for (y = 0; y < merged->len; y++) {
+				if (strcmp (merged->pdata[y], changes->uid_changed->pdata[i]) == 0) {
+					found = TRUE;
+					break;
+				}
+			}
+
+			if (!found)
+				g_ptr_array_add (merged, changes->uid_changed->pdata[i]);
+		}
+	}
+
+	if (merged->len > 0) {
+		GPtrArray *predicates_array = g_ptr_array_new ();
+		GPtrArray *values_array = g_ptr_array_new ();
+		gchar **subjects = (gchar **) g_malloc0 (sizeof (gchar *) * merged->len + 1);
+		guint y;
+
+		/* the uid_added member contains the added-to-the-summary items */
+
+		y = 0;
+
+		for (i = 0; i< merged->len; i++) {
+			gchar *subject, *to, *from, *cc, *uid = NULL, *sent, *size;
+			guint flags;
+			gchar **values, **predicates;
+			CamelMessageInfo *linfo;
+			GPtrArray *values_temp = g_ptr_array_new ();
+			GPtrArray *predicates_temp = g_ptr_array_new ();
+			const CamelTag *ctags;
+			const CamelFlag *cflags;
+
+			linfo = camel_folder_summary_uid (summary, merged->pdata[i]);
+
+			if (linfo)
+				uid = (gchar *) camel_message_info_uid (linfo);
+
+			if (linfo && uid) {
+				guint j, max;
+
+				subject = (gchar *) camel_message_info_subject (linfo);
+				to =      (gchar *) camel_message_info_to (linfo);
+				from =    (gchar *) camel_message_info_from (linfo);
+				cc =      (gchar *) camel_message_info_cc (linfo);
+				flags =   (guint)   camel_message_info_flags (linfo);
+
+				sent = g_strdup_printf ("%"PRIu64, (long long) camel_message_info_date_sent (linfo));
+				size = g_strdup_printf ("%d", camel_message_info_size (linfo));
+
+				process_fields (predicates_temp, values_temp, uid,
+						flags, sent, subject, from, to, cc, 
+						size, folder);
+
+				cflags = camel_message_info_user_flags (linfo);
+				while (cflags) {
+					g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
+					g_ptr_array_add (values_temp, g_strdup (cflags->name));
+					cflags = cflags->next;
+				}
+
+				ctags = camel_message_info_user_tags (linfo);
+				while (ctags) {
+					g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
+					g_ptr_array_add (values_temp, g_strdup_printf ("%s=%s", ctags->name, ctags->value));
+					ctags = ctags->next;
+				}
+
+				if (values_temp->len != predicates_temp->len)
+					g_critical ("values_temp->len != predicates_temp->len");
+
+				max = MIN (values_temp->len, predicates_temp->len);
+
+				values = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
+				predicates = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
+
+				for (j = 0; j < max; j++) {
+					predicates[j] = predicates_temp->pdata[j];
+					values[j] = values_temp->pdata[j];
+				}
+
+				predicates[j] = NULL;
+				values[j] = NULL;
+
+				g_ptr_array_add (values_array, values);
+				g_ptr_array_add (predicates_array, predicates);
+
+				subjects[y] = g_strdup_printf ("%s%s/%s", 
+							       em_uri, 
+							       camel_folder_get_full_name (folder),
+							       uid);
+
+				g_ptr_array_free (predicates_temp, TRUE);
+				g_ptr_array_free (values_temp, TRUE);
+
+				y++;
+			}
+
+			if (linfo)
+				camel_message_info_free (linfo);
+		}
+
+		subjects[y] = NULL;
+
+		/* This goes to all currently registered registrars */
+
+		metadata_set_many (self, subjects, predicates_array, values_array);
+
+		g_strfreev (subjects);
+		for (i = 0; i < values_array->len; i++)
+			g_strfreev (values_array->pdata[i]);
+		g_ptr_array_free (values_array, TRUE);
+		for (i = 0; i < predicates_array->len; i++)
+			g_strfreev (predicates_array->pdata[i]);
+		g_ptr_array_free (predicates_array, TRUE);
+	}
+
+	g_ptr_array_free (merged, TRUE);
+
+	/* the uid_removed member contains the removed-from-the-summary items */
+
+	if (changes->uid_removed && changes->uid_removed->len > 0) {
+		gchar **subjects = (gchar **) g_malloc0 (sizeof (gchar *) * changes->uid_removed->len + 1);
+
+		for (i = 0; i< changes->uid_removed->len; i++) {
+			subjects[i] = g_strdup_printf ("%s%s/%s", em_uri, 
+						       camel_folder_get_full_name (folder),
+						       (char*) changes->uid_removed->pdata[i]);
+		}
+
+		subjects[i] = NULL;
+
+		/* This goes to all currently registered registrars */
+
+		metadata_unset_many (self, subjects);
+
+		g_strfreev (subjects);
+	}
+	g_free (em_uri);
+}
+
+
+
+/* Initial upload of more recent than last_checkout items */
+
+static void
+introduce_walk_folders_in_folder (TrackerEvolutionPlugin *self, CamelFolderInfo *iter, CamelStore *store, gchar *account_uri, ClientRegistry *info)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	gchar *em_uri = em_uri_from_camel (account_uri);
+
+	while (iter) {
+		guint i, ret = SQLITE_OK;
+		CamelDB *cdb_r = store->cdb_r;
+		gchar *query;
+		sqlite3_stmt *stmt = NULL;
+		gboolean more = TRUE;
+
+		query = sqlite3_mprintf ("SELECT uid , flags, read , deleted , "
+					        "replied , important , junk , attachment ,"
+					        " size , dsent , dreceived , subject ,"
+					        " mail_from , mail_to , mail_cc , mlist,"
+					        " labels, usertags"
+					 " FROM %Q WHERE modified > %"PRIu64, 
+					 iter->full_name, info->last_checkout);
+
+		g_mutex_lock (cdb_r->lock);
+
+		ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL);
+
+		while (more) {
+			GPtrArray *subjects_a = g_ptr_array_new ();
+			GPtrArray *predicates_array = g_ptr_array_new ();
+			GPtrArray *values_array = g_ptr_array_new ();
+			guint count = 0;
+
+			more = FALSE;
+
+			while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) {
+				gchar **values, **predicates;
+				gchar *subject, *to, *from, *cc, *sent, *uid, *size;
+				gchar *part, *label, *p;
+				guint flags;
+
+				ret = sqlite3_step (stmt);
+
+				if (ret == SQLITE_BUSY) {
+					usleep (10);
+					continue;
+				}
+
+				if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) {
+					more = FALSE;
+					break;
+				}
+
+				uid = (gchar *) sqlite3_column_text (stmt, 0);
+
+				if (uid) {
+					GPtrArray *predicates_temp = g_ptr_array_new ();
+					GPtrArray *values_temp = g_ptr_array_new ();
+					CamelFolder *folder;
+					guint max = 0, j;
+
+					flags =   (guint  ) sqlite3_column_int  (stmt, 1);
+					size =    (gchar *) sqlite3_column_text (stmt, 8);
+					sent =    (gchar *) sqlite3_column_text (stmt, 9);
+					subject = (gchar *) sqlite3_column_text (stmt, 11);
+					from =    (gchar *) sqlite3_column_text (stmt, 12);
+					to =      (gchar *) sqlite3_column_text (stmt, 13);
+					cc =      (gchar *) sqlite3_column_text (stmt, 14);
+
+					folder = g_hash_table_lookup (priv->cached_folders, iter->full_name);
+
+					process_fields (predicates_temp, values_temp, uid, flags, sent, 
+							subject, from, to, cc, size, folder);
+
+					/* Extract User flags/labels */
+					p = part = g_strdup ((const gchar *) sqlite3_column_text (stmt, 16));
+					if (part) {
+						label = part;
+						for (j=0; part[j]; j++) {
+
+							if (part[j] == ' ') {
+								part[j] = 0;
+								g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
+								g_ptr_array_add (values_temp, g_strdup (label));
+								label = &(part[j+1]);
+							}
+						}
+						g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
+						g_ptr_array_add (values_temp, g_strdup (label));
+					}
+					g_free (p);
+
+					p = part = g_strdup ((const gchar *) sqlite3_column_text (stmt, 17));
+					EXTRACT_FIRST_DIGIT (max)
+					for (j = 0; j < max; j++) {
+						int len;
+						char *name, *value;
+						EXTRACT_STRING (name)
+						EXTRACT_STRING (value)
+						if (name && g_utf8_validate (name, -1, NULL) &&
+						    value && g_utf8_validate (value, -1, NULL)) {
+							g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
+							g_ptr_array_add (values_temp, g_strdup_printf ("%s=%s", name, value));
+						}
+						g_free(name);
+						g_free(value);
+					}
+					g_free (p);
+
+					if (values_temp->len != predicates_temp->len)
+						g_critical ("values_temp->len != predicates_temp->len");
+
+					max = MIN (values_temp->len, predicates_temp->len);
+
+					values = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
+					predicates = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
+
+					for (j = 0; j < max; j++) {
+						predicates[j] = predicates_temp->pdata[j];
+						values[j] = values_temp->pdata[j];
+					}
+
+					predicates[j] = NULL;
+					values[j] = NULL;
+
+					g_ptr_array_add (subjects_a, g_strdup_printf ("%s%s/%s", em_uri, 
+										      iter->full_name, uid));
+					g_ptr_array_add (predicates_array, predicates);
+					g_ptr_array_add (values_array, values);
+
+					g_ptr_array_free (predicates_temp, TRUE);
+					g_ptr_array_free (values_temp, TRUE);
+
+					count++;
+				}
+
+				if (count > MAX_BEFORE_SEND) {
+					more = TRUE;
+					break;
+				}
+
+				more = FALSE;
+			}
+
+
+			if (count > 0) {
+				gchar **subjects;
+
+				subjects = (gchar **) g_malloc0 (sizeof (gchar *) * subjects_a->len + 1);
+				for (i = 0; i < subjects_a->len; i++)
+					subjects[i] = g_ptr_array_index (subjects_a, i);
+				subjects[i] = NULL;
+
+				dbus_g_proxy_call_no_reply (info->registrar,
+							    "SetMany",
+							    G_TYPE_STRV, subjects,
+							    TRACKER_TYPE_G_STRV_ARRAY, predicates_array,
+							    TRACKER_TYPE_G_STRV_ARRAY, values_array,
+							    G_TYPE_INVALID, 
+							    G_TYPE_INVALID);
+
+				g_strfreev (subjects);
+			}
+
+			g_ptr_array_free (subjects_a, TRUE);
+
+			for (i = 0; i < values_array->len; i++)
+				g_strfreev (values_array->pdata[i]); 
+			g_ptr_array_free (values_array, TRUE);
+
+			for (i = 0; i < predicates_array->len; i++)
+				g_strfreev (predicates_array->pdata[i]); 
+			g_ptr_array_free (predicates_array, TRUE);
+		}
+
+		sqlite3_finalize (stmt);
+		sqlite3_free (query);
+
+		g_mutex_unlock (cdb_r->lock);
+
+		if (iter->child) {
+			introduce_walk_folders_in_folder (self, iter->child, store, account_uri, info);
+		}
+
+		iter = iter->next;
+	}
+
+	g_free (em_uri);
+}
+
+/* Initial notify of deletes that are more recent than last_checkout */
+
+static void
+introduce_store_deal_with_deleted (TrackerEvolutionPlugin *self, CamelStore *store, char *account_uri, gpointer user_data)
+{
+	ClientRegistry *info = user_data;
+	gboolean more = TRUE;
+	gchar *query;
+	sqlite3_stmt *stmt = NULL;
+	CamelDB *cdb_r;
+	guint i, ret;
+	gchar *em_uri = em_uri_from_camel (account_uri);
+
+	query = sqlite3_mprintf ("SELECT uid , mailbox FROM Deletes WHERE modified > %" PRIu64, 
+				 info->last_checkout);
+
+	cdb_r = store->cdb_r;
+
+	g_mutex_lock (cdb_r->lock);
+
+	sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL);
+
+	ret = SQLITE_OK;
+
+	while (more) {
+		GPtrArray *subjects_a = g_ptr_array_new ();
+		guint count = 0;
+
+		more = FALSE;
+
+		while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) {
+			const gchar *uid;
+			const gchar *mailbox;
+
+			ret = sqlite3_step (stmt);
+
+			if (ret == SQLITE_BUSY) {
+				usleep (10);
+				continue;
+			}
+
+			if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) {
+				more = FALSE;
+				break;
+			}
+
+			uid = (const gchar *) sqlite3_column_text (stmt, 0);
+			mailbox = (const gchar *) sqlite3_column_text (stmt, 1);
+
+
+			g_ptr_array_add (subjects_a, g_strdup_printf ("%s%s/%s", em_uri, 
+								      mailbox, uid));
+
+			if (count > MAX_BEFORE_SEND) {
+
+				/* Yield per MAX_BEFORE_SEND */
+				g_main_context_iteration (NULL, TRUE);
+
+				more = TRUE;
+				break;
+			}
+
+			count++;
+
+			more = FALSE;
+		}
+
+		if (count > 0) {
+			gchar **subjects;
+
+			subjects = (gchar **) g_malloc0 (sizeof (gchar *) * subjects_a->len + 1);
+			for (i = 0; i < subjects_a->len; i++)
+				subjects[i] = g_ptr_array_index (subjects_a, i);
+			subjects[i] = NULL;
+
+			dbus_g_proxy_call_no_reply (info->registrar,
+						    "UnsetMany",
+						    G_TYPE_STRV, subjects,
+						    G_TYPE_INVALID,
+						    G_TYPE_INVALID);
+
+			g_strfreev (subjects);
+		}
+
+		g_ptr_array_free (subjects_a, TRUE);
+
+	}
+	sqlite3_finalize (stmt);
+	sqlite3_free (query);
+	g_mutex_unlock (cdb_r->lock);
+
+	g_free (em_uri);
+}
+
+static guint64
+get_last_deleted_time (TrackerEvolutionPlugin *self)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	guint64 smallest = (guint64) time (NULL);
+
+	if (priv->accounts) {
+		EIterator *it;
+
+		for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it)) {
+			EAccount *account = (EAccount *) e_iterator_get (it);
+			CamelProvider *provider;
+			CamelStore *store;
+			CamelException ex;
+			char *uri;
+			CamelDB *cdb_r;
+			sqlite3_stmt *stmt = NULL;
+			gchar *query;
+			guint ret = SQLITE_OK;
+			guint latest = smallest;
+
+			camel_exception_init (&ex);
+
+			if (!account->enabled ||!(uri = account->source->url))
+				continue;
+
+			if (!(provider = camel_provider_get(uri, NULL))) {
+				camel_exception_clear (&ex);
+				continue;
+			}
+
+			if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
+				continue;
+
+			if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
+				camel_exception_clear (&ex);
+				continue;
+			}
+
+			cdb_r = store->cdb_r;
+
+			query = sqlite3_mprintf ("SELECT time FROM Deletes ORDER BY time LIMIT 1");
+
+			g_mutex_lock (cdb_r->lock);
+
+			ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL);
+
+			ret = sqlite3_step (stmt);
+			if (ret == SQLITE_OK || ret == SQLITE_ROW)
+				latest = sqlite3_column_int64 (stmt, 0);
+
+			if (latest < smallest)
+				smallest = latest;
+
+			sqlite3_finalize (stmt);
+			sqlite3_free (query);
+			g_mutex_unlock (cdb_r->lock);
+
+		}
+
+		g_object_unref (it);
+	}
+
+	return smallest;
+}
+
+
+static void
+register_walk_folders_in_folder (TrackerEvolutionPlugin *self, CamelFolderInfo *iter, CamelStore *store, gchar *account_uri)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+
+	while (iter) {
+		CamelFolder *folder;
+
+		folder = camel_store_get_folder (store, iter->full_name, 0, NULL);
+
+		if (folder) {
+			guint hook_id;
+			FolderRegistry *registry;
+
+			registry = folder_registry_new (account_uri, folder, self);
+
+			if (!priv->registered_folders) {
+				priv->registered_folders = g_hash_table_new_full (g_int_hash, g_int_equal,
+										  (GDestroyNotify) NULL,
+										  (GDestroyNotify) folder_registry_free);
+				priv->cached_folders = g_hash_table_new_full (g_str_hash, g_str_equal,
+										  (GDestroyNotify) g_free,
+										  (GDestroyNotify) NULL);
+			}
+
+			hook_id = camel_object_hook_event (folder, "folder_changed", 
+							   CAMEL_CALLBACK (on_folder_summary_changed), 
+							   registry->hook_info);
+			registry->hook_info->hook_id = hook_id;
+
+			g_hash_table_replace (priv->registered_folders, &hook_id, 
+					      registry);
+			g_hash_table_replace (priv->cached_folders, g_strdup (iter->full_name), 
+					      folder);
+
+			camel_object_unref (folder);
+		}
+
+		if (iter->child) {
+			register_walk_folders_in_folder (self, iter->child, store, 
+						      account_uri);
+		}
+
+		iter = iter->next;
+	}
+}
+
+
+static void
+unregister_walk_folders_in_folder (TrackerEvolutionPlugin *self, CamelFolderInfo *titer, CamelStore *store, gchar *account_uri)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+
+	while (titer) {
+		CamelFolder *folder;
+		GHashTableIter iter;
+		gpointer key, value;
+
+		/* Yield per folder */
+		g_main_context_iteration (NULL, TRUE);
+
+		folder = camel_store_get_folder (store, titer->full_name, 0, NULL);
+
+		g_hash_table_iter_init (&iter, priv->registered_folders);
+
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			FolderRegistry *registry = value;
+
+			if (value == registry->folder) {
+				g_hash_table_remove (priv->cached_folders, titer->full_name);
+				g_hash_table_iter_remove (&iter);
+				break;
+			}
+		}
+
+		if (titer->child) {
+			unregister_walk_folders_in_folder (self, titer->child, store, 
+							 account_uri);
+		}
+
+		titer = titer->next;
+	}
+}
+
+static void
+client_registry_info_free (ClientRegistry *info)
+{
+	g_object_unref (info->registrar);
+	g_slice_free (ClientRegistry, info);
+}
+
+static ClientRegistry*
+client_registry_info_copy (ClientRegistry *info)
+{
+	ClientRegistry *ninfo = g_slice_new0 (ClientRegistry);
+	ninfo->last_checkout = info->last_checkout;
+	ninfo->registrar = g_object_ref (info->registrar);
+	return ninfo;
+}
+
+static gboolean
+on_got_folderinfo_introduce (CamelStore *store, CamelFolderInfo *iter, void *data)
+{
+	IntroductionInfo *intro_info = data;
+
+	introduce_walk_folders_in_folder (intro_info->self, iter, store, 
+					  intro_info->account_uri, 
+					  intro_info->info);
+
+	client_registry_info_free (intro_info->info);
+	g_free (intro_info->account_uri);
+	g_object_unref (intro_info->self);
+	g_free (intro_info);
+
+	return TRUE;
+}
+
+static void
+introduce_account_to (TrackerEvolutionPlugin *self, EAccount *account, ClientRegistry *info)
+{
+	CamelProvider *provider;
+	CamelStore *store;
+	CamelException ex;
+	char *uri, *account_uri, *ptr;
+	IntroductionInfo *intro_info;
+
+	if (!account->enabled ||!(uri = account->source->url))
+		return;
+
+	camel_exception_init (&ex);
+	if (!(provider = camel_provider_get(uri, &ex))) {
+		camel_exception_clear (&ex);
+		return;
+	}
+
+	if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
+		return;
+
+	if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
+		camel_exception_clear (&ex);
+		return;
+	}
+
+	account_uri = g_strdup (uri);
+
+	ptr = strchr (account_uri, ';');
+
+	if (ptr)
+		*ptr = '\0';
+
+	introduce_store_deal_with_deleted (self, store, account_uri, info);
+
+	intro_info = g_new0 (IntroductionInfo, 1);
+
+	intro_info->self = g_object_ref (self);
+	intro_info->info = client_registry_info_copy (info);
+	intro_info->account_uri = account_uri; /* is freed on done */
+
+	mail_get_folderinfo (store, NULL, on_got_folderinfo_introduce, intro_info);
+
+	camel_object_unref (store);
+
+}
+
+
+static void
+introduce_account_to_all (TrackerEvolutionPlugin *self, EAccount *account)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	GList *copy = priv->registered_clients;
+
+	while (copy) {
+		ClientRegistry *info = copy->data;
+		introduce_account_to (self, account, info);
+		copy = g_list_next (copy);
+	}
+
+}
+
+static void
+introduce_accounts_to (TrackerEvolutionPlugin *self, ClientRegistry *info)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	EIterator *it;
+
+	for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it))
+		introduce_account_to (self, (EAccount *) e_iterator_get (it), info);
+
+	g_object_unref (it);
+}
+
+
+static void
+register_client (TrackerEvolutionPlugin *self, guint64 last_checkout, DBusGProxy *registrar)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	guint64 too_old = get_last_deleted_time (self);
+	ClientRegistry *info = g_slice_new (ClientRegistry);
+
+	g_print ("too-old=%"PRIu64" < last=%"PRIu64" (time=%"PRIu64")\n", 
+		 too_old, last_checkout, (guint64) time (NULL));
+
+	info->registrar = g_object_ref (registrar);
+
+	if (last_checkout < too_old) {
+		dbus_g_proxy_call_no_reply (registrar,
+					    "Cleanup",
+					    G_TYPE_INVALID,
+					    G_TYPE_INVALID);
+		info->last_checkout = 0;
+	} else
+		info->last_checkout = last_checkout;
+
+	introduce_accounts_to (self, info);
+
+	priv->registered_clients = g_list_prepend (priv->registered_clients, info);
+}
+
+
+static void
+metadata_set_many (TrackerEvolutionPlugin *self, GStrv subjects, GPtrArray *predicates, GPtrArray *values)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_static_rec_mutex_lock (priv->mutex);
+
+	g_hash_table_iter_init (&iter, priv->registrars);
+
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		DBusGProxy *registrar = value;
+
+		dbus_g_proxy_call_no_reply (registrar,
+					    "SetMany",
+					    G_TYPE_STRV, subjects,
+					    TRACKER_TYPE_G_STRV_ARRAY, predicates,
+					    TRACKER_TYPE_G_STRV_ARRAY, values,
+					    G_TYPE_INVALID, 
+					    G_TYPE_INVALID);
+	}
+
+	g_static_rec_mutex_unlock (priv->mutex);
+}
+
+
+static void
+metadata_unset_many (TrackerEvolutionPlugin *self, GStrv subjects)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_static_rec_mutex_lock (priv->mutex);
+
+	g_hash_table_iter_init (&iter, priv->registrars);
+
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		DBusGProxy *registrar = value;
+
+		dbus_g_proxy_call_no_reply (registrar,
+					    "UnsetMany",
+					    G_TYPE_STRV, subjects,
+					    G_TYPE_INVALID, 
+					    G_TYPE_INVALID);
+	}
+
+	g_static_rec_mutex_unlock (priv->mutex);
+
+}
+
+
+
+static void
+on_folder_created (CamelStore *store, void *event_data, StoreRegistry *registry)
+{
+	unregister_account (registry->self, registry->account);
+	register_account (registry->self, registry->account);
+	introduce_account_to_all (registry->self, registry->account);
+}
+
+static void
+on_folder_deleted (CamelStore *store, void *event_data, StoreRegistry *registry)
+{
+	unregister_account (registry->self, registry->account);
+	register_account (registry->self, registry->account);
+	introduce_account_to_all (registry->self, registry->account);
+}
+
+static void
+on_folder_renamed (CamelStore *store, CamelRenameInfo *info, StoreRegistry *registry)
+{
+	unregister_account (registry->self, registry->account);
+	register_account (registry->self, registry->account);
+	introduce_account_to_all (registry->self, registry->account);
+}
+
+static StoreRegistry*
+store_registry_new (gpointer co, EAccount *account, TrackerEvolutionPlugin *self)
+{
+	StoreRegistry *registry = g_slice_new (StoreRegistry);
+	registry->store = co;
+	registry->account = account; /* weak */
+	registry->self = self; /* weak */
+	camel_object_ref (co);
+	return registry;
+}
+
+static void
+store_registry_free (StoreRegistry *registry) 
+{
+	camel_object_remove_event (registry->store, registry->hook_id);
+	camel_object_unref (registry->store);
+	g_slice_free (StoreRegistry, registry);
+}
+
+
+static gboolean
+on_got_folderinfo_register (CamelStore *store, CamelFolderInfo *iter, void *data)
+{
+	RegisterInfo *reg_info = data;
+	TrackerEvolutionPlugin *self = reg_info->self;
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+	EAccount *account = reg_info->account;
+	StoreRegistry *registry;
+	char *uri = reg_info->uri;
+	guint hook_id;
+
+	register_walk_folders_in_folder (self, iter, store, uri);
+
+	if (!priv->registered_stores)
+		priv->registered_stores = g_hash_table_new_full (g_int_hash, g_int_equal,
+								 (GDestroyNotify) NULL,
+								 (GDestroyNotify) store_registry_free);
+
+	registry = store_registry_new (store, account, self);
+	hook_id = camel_object_hook_event (store, "folder_created", 
+					   CAMEL_CALLBACK (on_folder_created), 
+					   registry);
+	registry->hook_id = hook_id;
+	g_hash_table_replace (priv->registered_stores, &hook_id, registry);
+
+	registry = store_registry_new (store, account, self);
+	hook_id = camel_object_hook_event (store, "folder_renamed", 
+					   CAMEL_CALLBACK (on_folder_renamed), 
+					   registry);
+	registry->hook_id = hook_id;
+	g_hash_table_replace (priv->registered_stores, &hook_id, registry);
+
+	registry = store_registry_new (store, account, self);
+	hook_id = camel_object_hook_event (store, "folder_deleted", 
+					   CAMEL_CALLBACK (on_folder_deleted), 
+					   registry);
+	registry->hook_id = hook_id;
+	g_hash_table_replace (priv->registered_stores, &hook_id, registry);
+
+	g_object_unref (reg_info->account);
+	g_object_unref (reg_info->self);
+	g_free (reg_info->uri);
+	g_free (reg_info);
+
+	return TRUE;
+}
+
+static void
+register_account (TrackerEvolutionPlugin *self, EAccount *account)
+{
+	CamelProvider *provider;
+	CamelStore *store;
+	CamelException ex;
+	char *uri;
+	RegisterInfo *reg_info;
+
+	if (!account->enabled ||!(uri = account->source->url))
+		return;
+
+	camel_exception_init (&ex);
+	if (!(provider = camel_provider_get(uri, &ex))) {
+		camel_exception_clear (&ex);
+		return;
+	}
+
+	if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
+		return;
+
+	if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
+		camel_exception_clear (&ex);
+		return;
+	}
+
+	reg_info = g_new0 (RegisterInfo, 1);
+
+	reg_info->self = g_object_ref (self);
+	reg_info->uri = g_strdup (uri);
+	reg_info->account = g_object_ref (account);
+
+	mail_get_folderinfo (store, NULL, on_got_folderinfo_register, reg_info);
+
+	camel_object_unref (store);
+}
+
+static void
+unregister_account (TrackerEvolutionPlugin *self, EAccount *account)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+
+	CamelProvider *provider;
+	CamelStore *store;
+	CamelFolderInfo *titer = NULL;
+	CamelException ex;
+	char *uri;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	camel_exception_init (&ex);
+	if (!(provider = camel_provider_get(uri, &ex))) {
+		camel_exception_clear (&ex);
+		return;
+	}
+
+	if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
+		return;
+
+	if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
+		camel_exception_clear (&ex);
+		return;
+	}
+
+	titer = camel_store_get_folder_info (store, "", CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL |
+		CAMEL_STORE_FOLDER_INFO_RECURSIVE, &ex);
+
+	unregister_walk_folders_in_folder (self, titer, store, uri);
+
+	camel_folder_info_free (titer);
+
+	if (priv->registered_stores) {
+		g_hash_table_iter_init (&iter, priv->registered_stores);
+
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			if (value == store) 
+				g_hash_table_iter_remove (&iter);
+		}
+	}
+
+	camel_object_unref (store);
+}
+
+static void
+on_account_added (EAccountList *list, EAccount *account, TrackerEvolutionPlugin *self)
+{
+	register_account (self, account);
+	introduce_account_to_all (self, account);
+}
+
+static void
+on_account_removed (EAccountList *list, EAccount *account, TrackerEvolutionPlugin *self)
+{
+	unregister_account (self, account);
+}
+
+static void
+on_account_changed (EAccountList *list, EAccount *account, TrackerEvolutionPlugin *self)
+{
+	unregister_account (self, account);
+	register_account (self, account);
+	introduce_account_to_all (self, account);
+}
+
+
+static void
+disable_plugin (void) 
+{
+	GError *error = NULL;
+	guint result;
+
+	org_freedesktop_DBus_release_name (dbus_proxy, TRACKER_EVOLUTION_MANAGER_SERVICE, 
+					   &result, &error);
+
+	if (!error) {
+		if (manager) {
+			g_object_unref (manager);
+			manager = NULL;
+		}
+
+		if (dbus_proxy) {
+			g_object_unref (dbus_proxy);
+			dbus_proxy = NULL;
+		}
+	} else
+		g_error_free (error);
+
+}
+
+static void
+enable_plugin (void)
+{
+	DBusGConnection *connection;
+	GError *error = NULL;
+	guint result;
+
+	if (dbus_proxy && manager)
+		return;
+
+	if ((dbus_proxy && !manager) || (!dbus_proxy && manager))
+		disable_plugin ();
+
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+	if (error)
+		goto error_handler;
+
+	dbus_proxy = dbus_g_proxy_new_for_name (connection, 
+						DBUS_SERVICE_DBUS,
+						DBUS_PATH_DBUS,
+						DBUS_INTERFACE_DBUS);
+
+	if (!org_freedesktop_DBus_request_name (dbus_proxy, TRACKER_EVOLUTION_MANAGER_SERVICE,
+						DBUS_NAME_FLAG_DO_NOT_QUEUE,
+						&result, &error)) {
+		goto error_handler;
+	}
+
+	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+		goto error_handler;
+	}
+
+	if (error)
+		goto error_handler;
+
+	manager = g_object_new (TRACKER_TYPE_EVOLUTION_PLUGIN, 
+				"connection", connection, NULL);
+
+	dbus_g_object_type_install_info (G_OBJECT_TYPE (manager), 
+					 &dbus_glib_tracker_evolution_plugin_object_info);
+
+	dbus_g_connection_register_g_object (connection, 
+					     TRACKER_EVOLUTION_MANAGER_PATH, 
+					     G_OBJECT (manager));
+
+	error_handler:
+
+	if (error) {
+		g_critical ("Could not setup DBus, %s\n", error->message);
+		disable_plugin();
+		g_error_free (error);
+	}
+}
+
+
+static gboolean 
+do_remove_or_not (gpointer key, gpointer value, gpointer user_data)
+{
+	if (user_data == value)
+		return TRUE;
+
+	return FALSE;
+}
+
+static void
+service_gone (DBusGProxy *lproxy, TrackerEvolutionPlugin *plugin)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+	GList *copy = priv->registered_clients;
+	GList *to_delete = NULL;
+
+	g_static_rec_mutex_lock (priv->mutex);
+
+	g_hash_table_foreach_remove (priv->registrars, 
+				     do_remove_or_not,
+				     lproxy);
+
+	while (copy) {
+		ClientRegistry *creg = copy->data;
+		if (creg->registrar == lproxy)
+			to_delete = g_list_prepend (to_delete, copy);
+		copy = g_list_next (copy);
+	}
+
+	copy = to_delete;
+	while (copy) {
+		GList *node = copy->data;
+		ClientRegistry *creg = node->data;
+		priv->registered_clients = g_list_delete_link (priv->registered_clients, node);
+		client_registry_info_free (creg);
+		copy = g_list_next (copy);
+	}
+
+	g_list_free (to_delete);
+
+	g_static_rec_mutex_unlock (priv->mutex);
+}
+
+void 
+tracker_evolution_plugin_register  (TrackerEvolutionPlugin *plugin, 
+				    gchar *registrar_path,
+				    guint last_checkout, 
+				    DBusGMethodInvocation *context)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+	gchar *sender;
+	DBusGProxy *registrar;
+
+	g_static_rec_mutex_lock (priv->mutex);
+
+	sender = dbus_g_method_get_sender (context);
+
+	registrar = dbus_g_proxy_new_for_name (priv->connection, sender, 
+					       registrar_path,
+					       TRACKER_EVOLUTION_REGISTRAR_INTERFACE);
+
+	g_hash_table_replace (priv->registrars, g_strdup (sender), 
+			      registrar);
+
+	g_signal_connect (registrar, "destroy",
+			  G_CALLBACK (service_gone),
+			  plugin);
+
+	g_static_rec_mutex_unlock (priv->mutex);
+
+	/* Passing uint64 over DBus ain't working :-\ */
+	register_client (plugin, (guint64) last_checkout, registrar);
+
+	dbus_g_method_return (context);
+}
+
+
+int
+e_plugin_lib_enable (EPluginLib *ep, int enabled)
+{
+	g_static_rec_mutex_lock (&glock);
+	if (enabled)
+		enable_plugin ();
+	else
+		disable_plugin ();
+	g_static_rec_mutex_unlock (&glock);
+
+	return 0;
+}
+
+
+static void
+tracker_evolution_plugin_finalize (GObject *plugin)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+	GList *copy;
+
+	g_static_rec_mutex_lock (priv->mutex);
+
+	copy = priv->registered_clients;
+	while (copy) {
+		ClientRegistry *creg = copy->data;
+		client_registry_info_free (creg);
+		copy = g_list_next (copy);
+	}
+	g_list_free (priv->registered_clients);
+
+	if (priv->registered_folders) {
+		g_hash_table_destroy (priv->registered_folders);
+		g_hash_table_destroy (priv->cached_folders);
+		priv->cached_folders = NULL;
+		priv->registered_folders = NULL;
+	}
+
+	if (priv->registered_stores) {
+		g_hash_table_destroy (priv->registered_stores);
+		priv->registered_stores = NULL;
+	}
+
+	g_object_unref (priv->accounts);
+
+	g_hash_table_destroy (priv->registrars);
+
+	g_static_rec_mutex_unlock (priv->mutex);
+
+	g_slice_free (GStaticRecMutex, priv->mutex);
+
+	G_OBJECT_CLASS (tracker_evolution_plugin_parent_class)->finalize (plugin);
+}
+
+static void 
+tracker_evolution_plugin_set_connection (TrackerEvolutionPlugin *plugin, DBusGConnection *connection)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+	priv->connection = connection;
+}
+
+
+static void
+tracker_evolution_plugin_set_property (GObject     *plugin,
+				      guint         prop_id,
+				      const GValue *value,
+				      GParamSpec   *pspec)
+{
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		tracker_evolution_plugin_set_connection (TRACKER_EVOLUTION_PLUGIN (plugin),
+							 g_value_get_pointer (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (plugin, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_plugin_get_property (GObject   *plugin,
+				      guint       prop_id,
+				      GValue     *value,
+				      GParamSpec *pspec)
+{
+	TrackerEvolutionPluginPrivate *priv;
+
+	priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		g_value_set_pointer (value, priv->connection);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (plugin, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_plugin_class_init (TrackerEvolutionPluginClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = tracker_evolution_plugin_finalize;
+	object_class->set_property = tracker_evolution_plugin_set_property;
+	object_class->get_property = tracker_evolution_plugin_get_property;
+
+	g_object_class_install_property (object_class,
+					 PROP_CONNECTION,
+					 g_param_spec_pointer ("connection",
+							       "DBus connection",
+							       "DBus connection",
+							      G_PARAM_READWRITE |
+							      G_PARAM_CONSTRUCT));
+
+	g_type_class_add_private (object_class, sizeof (TrackerEvolutionPluginPrivate));
+}
+
+static void
+tracker_evolution_plugin_init (TrackerEvolutionPlugin *plugin)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+	EIterator *it;
+
+	priv->mutex = g_slice_new0 (GStaticRecMutex);
+	g_static_rec_mutex_init (priv->mutex);
+	priv->registrars = g_hash_table_new_full (g_str_hash, g_str_equal,
+						  (GDestroyNotify) g_free, 
+						  (GDestroyNotify) g_object_unref);
+
+	priv->cached_folders = NULL;
+	priv->registered_folders = NULL;
+	priv->registered_stores = NULL;
+	priv->registered_clients = NULL;
+
+	priv->accounts = g_object_ref (mail_config_get_accounts ());
+
+	for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it))
+		register_account (plugin, (EAccount *) e_iterator_get (it));
+
+	g_object_unref (it);
+
+	g_signal_connect (priv->accounts, "account-added", 
+			  G_CALLBACK (on_account_added), plugin);
+	g_signal_connect (priv->accounts, "account-removed", 
+			  G_CALLBACK (on_account_removed), plugin);
+	g_signal_connect (priv->accounts, "account-changed", 
+			  G_CALLBACK (on_account_changed), plugin);
+
+}
Index: src/tracker-evolution-plugin/tracker-evolution-indexer.c
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-indexer.c	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-indexer.c	(revision 0)
@@ -0,0 +1,519 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gmime/gmime.h>
+
+#include <libtracker-data/tracker-data-update.h>
+
+/* This is okay, we run in-process of the indexer, so we can access its symbols */
+#include <tracker-indexer/tracker-module.h>
+
+/* No idea why this ain't in the .h files */
+GHashTable * tracker_module_metadata_get_hash_table (TrackerModuleMetadata *metadata);
+
+#include "tracker-evolution-indexer.h"
+
+#define tracker_evolution_registrar_set tracker_evolution_indexer_set
+#define tracker_evolution_registrar_set_many tracker_evolution_indexer_set_many
+#define tracker_evolution_registrar_unset_many tracker_evolution_indexer_unset_many
+#define tracker_evolution_registrar_unset tracker_evolution_indexer_unset
+#define tracker_evolution_registrar_cleanup tracker_evolution_indexer_cleanup
+#define dbus_glib_tracker_evolution_indexer_object_info dbus_glib_tracker_evolution_registrar_object_info
+
+#include "tracker-evolution-registrar-glue.h"
+
+
+/* From evolution-common.h */
+
+#define METADATA_FILE_PATH	     "File:Path"
+#define METADATA_FILE_NAME	     "File:Name"
+#define METADATA_EMAIL_RECIPIENT     "Email:Recipient"
+#define METADATA_EMAIL_DATE	     "Email:Date"
+#define METADATA_EMAIL_SENDER	     "Email:Sender"
+#define METADATA_EMAIL_SUBJECT	     "Email:Subject"
+#define METADATA_EMAIL_SENT_TO	     "Email:SentTo"
+#define METADATA_EMAIL_CC	     "Email:CC"
+#define METADATA_EMAIL_TEXT	     "Email:Text"
+
+#define TRACKER_EVOLUTION_INDEXER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexerPrivate))
+
+G_DEFINE_TYPE (TrackerEvolutionIndexer, tracker_evolution_indexer, G_TYPE_OBJECT)
+
+/* This runs in-process of tracker-indexer */
+
+static GObject *idx_indexer = NULL;
+
+typedef struct {
+	GMutex *mutex;
+} TrackerEvolutionIndexerPrivate;
+
+enum {
+	PROP_0
+};
+
+static GList *
+get_recipient_list (const gchar *str)
+{
+	GList *list = NULL;
+	gchar **arr;
+	gint i;
+
+	if (!str) {
+		return NULL;
+	}
+
+	arr = g_strsplit (str, ",", -1);
+
+	for (i = 0; arr[i]; i++) {
+		g_strstrip (arr[i]);
+		list = g_list_prepend (list, g_strdup (arr[i]));
+	}
+
+	g_strfreev (arr);
+
+	return g_list_reverse (list);
+}
+
+static void
+tracker_evolution_indexer_finalize (GObject *object)
+{
+	TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
+
+	g_mutex_free (priv->mutex);
+
+	G_OBJECT_CLASS (tracker_evolution_indexer_parent_class)->finalize (object);
+}
+
+
+static void
+tracker_evolution_indexer_set_property (GObject      *object,
+					guint         prop_id,
+					const GValue *value,
+					GParamSpec   *pspec)
+{
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_indexer_get_property (GObject    *object,
+					guint       prop_id,
+					GValue     *value,
+					GParamSpec *pspec)
+{
+	TrackerEvolutionIndexerPrivate *priv;
+
+	priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_indexer_class_init (TrackerEvolutionIndexerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = tracker_evolution_indexer_finalize;
+	object_class->set_property = tracker_evolution_indexer_set_property;
+	object_class->get_property = tracker_evolution_indexer_get_property;
+
+	g_type_class_add_private (object_class, sizeof (TrackerEvolutionIndexerPrivate));
+}
+
+static void
+tracker_evolution_indexer_init (TrackerEvolutionIndexer *object)
+{
+	TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
+
+	priv->mutex = g_mutex_new ();
+}
+
+
+static void
+extract_mime_parts (GMimeObject *object,
+		    gpointer     user_data)
+{
+	//TrackerModuleMetadata *metadata = user_data;
+	const gchar *disposition, *filename;
+	GMimePart *part;
+
+	if (GMIME_IS_MESSAGE_PART (object)) {
+		GMimeMessage *message;
+
+		message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (object));
+
+		if (message) {
+			g_mime_message_foreach_part (message, extract_mime_parts, user_data);
+			g_object_unref (message);
+		}
+
+		return;
+	} else if (GMIME_IS_MULTIPART (object)) {
+		g_mime_multipart_foreach (GMIME_MULTIPART (object), extract_mime_parts, user_data);
+		return;
+	}
+
+	part = GMIME_PART (object);
+	disposition = g_mime_part_get_content_disposition (part);
+
+	if (!disposition ||
+	    (g_strcmp0 (disposition, GMIME_DISPOSITION_ATTACHMENT) != 0 &&
+	     g_strcmp0 (disposition, GMIME_DISPOSITION_INLINE) != 0)) {
+		return;
+	}
+
+	filename = g_mime_part_get_filename (GMIME_PART (object));
+
+	if (!filename ||
+	    g_strcmp0 (filename, "signature.asc") == 0 ||
+	    g_strcmp0 (filename, "signature.pgp") == 0) {
+		return;
+	}
+
+	// todo: why is this being done?
+}
+
+
+static gchar *
+get_object_encoding (GMimeObject *object)
+{
+	const gchar *start_encoding, *end_encoding;
+	const gchar *content_type = NULL;
+
+	if (GMIME_IS_MESSAGE (object)) {
+		content_type = g_mime_message_get_header (GMIME_MESSAGE (object), "Content-Type");
+	} else if (GMIME_IS_PART (object)) {
+		content_type = g_mime_part_get_content_header (GMIME_PART (object), "Content-Type");
+	}
+
+	if (!content_type) {
+		return NULL;
+	}
+
+	start_encoding = strstr (content_type, "charset=");
+
+	if (!start_encoding) {
+		return NULL;
+	}
+
+	start_encoding += strlen ("charset=");
+
+	if (start_encoding[0] == '"') {
+		/* encoding is quoted */
+		start_encoding++;
+		end_encoding = strstr (start_encoding, "\"");
+	} else {
+		end_encoding = strstr (start_encoding, ";");
+	}
+
+	if (end_encoding) {
+		return g_strndup (start_encoding, end_encoding - start_encoding);
+	} else {
+		return g_strdup (start_encoding);
+	}
+}
+
+static void
+perform_set (TrackerEvolutionIndexer *object, const gchar *subject, const GStrv predicates, const GStrv values)
+{
+	guint i = 0;
+	TrackerModuleMetadata *metadata;
+	GHashTable *data;
+	GList *l, *list;
+
+	metadata = tracker_module_metadata_new ();
+	while (predicates [i] != NULL && values[i] != NULL) {
+
+		/* TODO: TRACKER_EVOLUTION_PREDICATE_UID */
+
+		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_FILE) == 0) {
+			GMimeStream *stream;
+			GMimeMessage *message;
+			GMimeParser *parser;
+			gint fd;
+			gchar *text, *orig_text, *ptr, *encoding;
+			gchar *path = g_strdup (values[i]);
+			off_t offset = 0;
+			gboolean is_html;
+
+			ptr = strstr (path, "/!");
+			if (ptr) {
+				offset = (off_t) atol (ptr+2);
+				*ptr = '\0';
+			}
+
+#if defined(__linux__)
+			fd = g_open (path, O_RDONLY /*| O_NOATIME*/, S_IRUSR | S_IWUSR);
+#else
+			fd = g_open (path, O_RDONLY , S_IRUSR | S_IWUSR);
+#endif
+
+			g_free (path);
+
+			if (fd == -1)
+				continue;
+
+			stream = g_mime_stream_fs_new_with_bounds (fd, offset, -1);
+
+			if (!stream) {
+				close (fd);
+				continue;
+			}
+
+			parser = g_mime_parser_new_with_stream (stream);
+
+			if (!parser) {
+				g_object_unref (stream);
+				continue;
+			}
+
+			g_mime_parser_set_scan_from (parser, TRUE);
+
+			message = g_mime_parser_construct_message (parser);
+
+			if (!message) {
+				g_object_unref (stream);
+				g_object_unref (parser);
+				continue;
+			}
+
+			g_mime_message_foreach_part (message,
+						     extract_mime_parts,
+						     metadata);
+
+			orig_text = g_mime_message_get_body (message, TRUE, &is_html);
+
+			if (orig_text) {
+
+				encoding = get_object_encoding (GMIME_OBJECT (message));
+
+				if (encoding) {
+					text = g_convert (text, -1, "utf8", encoding, NULL, NULL, NULL);
+					g_free (orig_text);
+				} else
+					text = orig_text;
+
+				tracker_module_metadata_add_string (metadata, 
+								    METADATA_EMAIL_TEXT, 
+								    text);
+
+				g_free (text);
+				g_free (encoding);
+			}
+
+			g_object_unref (message);
+			g_object_unref (parser);
+			g_object_unref (stream);
+		}
+
+		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_SUBJECT) == 0) {
+			tracker_module_metadata_add_string (metadata, 
+							    METADATA_EMAIL_SUBJECT, 
+							    values[i]);
+		}
+
+		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_SENT) == 0) {
+			tracker_module_metadata_add_string (metadata, 
+							    METADATA_EMAIL_DATE, 
+							    values[i]);
+		}
+
+		if (g_strcmp0 (predicates[i], METADATA_EMAIL_SENDER) == 0) {
+			tracker_module_metadata_add_string (metadata, 
+							    METADATA_EMAIL_SENDER, 
+							    values[i]);
+		}
+
+		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_TO) == 0) {
+			list = get_recipient_list (values[i]);
+			for (l = list; l; l = l->next) {
+				tracker_module_metadata_add_string (metadata, 
+								    METADATA_EMAIL_SENT_TO, 
+								    l->data);
+				g_free (l->data);
+			}
+			g_list_free (list);
+		}
+
+		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_CC) == 0) {
+			list = get_recipient_list (values[i]);
+			for (l = list; l; l = l->next) {
+				tracker_module_metadata_add_string (metadata, 
+								    METADATA_EMAIL_CC, 
+								    l->data);
+				g_free (l->data);
+			}
+			g_list_free (list);
+		}
+
+		i++;
+	}
+
+	data = tracker_module_metadata_get_hash_table (metadata);
+
+	/* TODO: the rdf:type here must be correct */
+	tracker_data_update_replace_service (subject, "EvolutionEmails", data);
+
+	g_hash_table_destroy (data);
+	g_object_unref (metadata);
+}
+
+static void 
+perform_unset (TrackerEvolutionIndexer *object, const gchar *subject)
+{
+	/* TODO: the rdf:type here must be correct */
+	tracker_data_update_delete_service_by_path (subject, "EvolutionEmails"); 
+}
+
+static void
+perform_cleanup (TrackerEvolutionIndexer *object)
+{
+	/* TODO: the rdf:type here must be correct, and test if passing '%' here
+	 * is how we want to do this */
+	tracker_data_update_delete_service_by_path ("%", "EvolutionEmails");
+}
+
+void
+tracker_evolution_indexer_set (TrackerEvolutionIndexer *object, 
+			       const gchar *subject, 
+			       const GStrv predicates,
+			       const GStrv values,
+			       DBusGMethodInvocation *context)
+{
+	dbus_async_return_if_fail (subject != NULL, context);
+
+	perform_set (object, subject, predicates, values);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_indexer_set_many (TrackerEvolutionIndexer *object, 
+				    const GStrv subjects, 
+				    const GPtrArray *predicates,
+				    const GPtrArray *values,
+				    DBusGMethodInvocation *context)
+{
+	guint len = g_strv_length (subjects);
+	guint i = 0;
+
+	dbus_async_return_if_fail (len == predicates->len, context);
+	dbus_async_return_if_fail (len == values->len, context);
+
+	while (subjects[i] != NULL) {
+		GStrv preds = g_ptr_array_index (predicates, i);
+		GStrv vals = g_ptr_array_index (values, i);
+
+		perform_set (object, subjects[i], preds, vals);
+
+		i++;
+	}
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_indexer_unset_many (TrackerEvolutionIndexer *object, 
+				      const GStrv subjects, 
+				      DBusGMethodInvocation *context)
+{
+	guint i = 0;
+
+	while (subjects[i] != NULL) {
+
+		perform_unset (object, subjects[i]);
+
+		i++;
+	}
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_indexer_unset (TrackerEvolutionIndexer *object, 
+				 const gchar *subject, 
+				 DBusGMethodInvocation *context)
+{
+	dbus_async_return_if_fail (subject != NULL, context);
+
+	perform_unset (object, subject);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_indexer_cleanup (TrackerEvolutionIndexer *object, 
+				   DBusGMethodInvocation *context)
+{
+	perform_cleanup (object);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_idx_init (TrackerConfig *config)
+{
+	GError *error = NULL;
+	DBusGConnection *connection;
+
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+	if (!error) {
+		idx_indexer = g_object_new (TRACKER_TYPE_EVOLUTION_INDEXER, NULL);
+		dbus_g_object_type_install_info (G_OBJECT_TYPE (idx_indexer), 
+						 &dbus_glib_tracker_evolution_indexer_object_info);
+
+		dbus_g_connection_register_g_object (connection, 
+						     TRACKER_EVOLUTION_INDEXER_PATH, 
+						     idx_indexer);
+	}
+
+	if (error) {
+		g_critical ("Can't init DBus for Evolution support: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+void
+tracker_evolution_idx_shutdown (void)
+{
+	if (idx_indexer)
+		g_object_unref (idx_indexer);
+}
Index: src/tracker-evolution-plugin/tracker-evolution-marshal.list
===================================================================
Index: src/tracker-evolution-plugin/tracker-evolution-registrar.xml
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-registrar.xml	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-registrar.xml	(revision 0)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+  <interface name="org.gnome.evolution.metadata.Registrar">
+
+  <method name="Set">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="s" name="subject" direction="in" />
+      <arg type="as" name="predicates" direction="in" />
+      <arg type="as" name="values" direction="in" />
+    </method>
+
+    <method name="SetMany">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="as" name="subjects" direction="in" />
+      <arg type="aas" name="predicates" direction="in" />
+      <arg type="aas" name="values" direction="in" />
+    </method>
+
+    <method name="Unset">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="s" name="subject" direction="in" />
+    </method>
+
+    <method name="UnsetMany">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+      <arg type="as" name="subjects" direction="in" />
+    </method>
+
+    <method name="Cleanup">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+    </method>
+
+  </interface>
+</node>
Index: src/tracker-evolution-plugin/tracker-evolution.c
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution.c	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution.c	(revision 0)
@@ -0,0 +1,361 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <time.h>
+
+#include <libtracker-data/tracker-data-manager.h>
+
+#include "tracker-evolution.h"
+#include "tracker-evolution-registrar.h"
+
+typedef struct {
+	TrackerConfig *config;
+	DBusGConnection *connection;
+	gboolean is_enabled;
+	DBusGProxy *dbus_proxy;
+	DBusGProxy *manager_proxy;
+	GObject *object;
+	gboolean deactivating;
+} EvolutionSupportPrivate;
+
+static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
+
+
+static guint
+get_stored_last_checkout (void)
+{
+	return (guint) tracker_data_manager_get_db_option_int ("EvolutionLastCheckout");
+}
+
+static void
+set_stored_last_checkout (guint last_checkout)
+{
+	tracker_data_manager_set_db_option_int ("EvolutionLastCheckout", (gint) last_checkout);
+}
+
+static void
+deactivate_registrar (void)
+{
+	EvolutionSupportPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	set_stored_last_checkout (time(NULL));
+
+	if (private->object)
+		g_object_unref (private->object);
+	private->object = NULL;
+
+	if (private->manager_proxy && !private->deactivating)
+		g_object_unref (private->manager_proxy);
+	private->manager_proxy = NULL;
+}
+
+static void
+deactivate_dbus_client (void)
+{
+	EvolutionSupportPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	deactivate_registrar ();
+
+	if (private->dbus_proxy)
+		g_object_unref (private->dbus_proxy);
+	private->dbus_proxy = NULL;
+}
+
+static void
+on_manager_destroy (DBusGProxy *proxy, gpointer user_data)
+{
+	EvolutionSupportPrivate *private;
+	gboolean old_setting;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	old_setting = private->deactivating;
+
+	private->deactivating = TRUE;
+	deactivate_registrar ();
+	private->deactivating = old_setting;
+}
+
+
+static void
+activate_registrar (void)
+{
+	EvolutionSupportPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	if (private->object)
+		return;
+
+	private->manager_proxy = 
+		dbus_g_proxy_new_for_name (private->connection,
+					   TRACKER_EVOLUTION_MANAGER_SERVICE,
+					   TRACKER_EVOLUTION_MANAGER_PATH,
+					   TRACKER_EVOLUTION_MANAGER_INTERFACE);
+
+	/* If while we had a proxy for the manager the manager shut itself down,
+	 * then we'll get rid of our registrar too, in on_manager_destroy */
+
+	g_signal_connect (private->manager_proxy, "destroy",
+			  G_CALLBACK (on_manager_destroy), NULL);
+
+	if (private->manager_proxy) {
+		GError *error = NULL;
+		guint result;
+
+		/* Creation of the registrar */
+		if (!org_freedesktop_DBus_request_name (private->dbus_proxy, 
+							   TRACKER_EVOLUTION_REGISTRAR_SERVICE,
+							   DBUS_NAME_FLAG_DO_NOT_QUEUE,
+							   &result, &error)) {
+			g_critical ("Could not setup DBus, %s in use\n", TRACKER_EVOLUTION_REGISTRAR_SERVICE);
+			goto error_handler;
+		}
+
+		if (error)
+			goto error_handler;
+
+		private->object = g_object_new (TRACKER_TYPE_EVOLUTION_REGISTRAR, 
+						"connection", private->connection, 
+						NULL);
+
+		dbus_g_object_type_install_info (G_OBJECT_TYPE (private->object), 
+						 &dbus_glib_tracker_evolution_registrar_object_info);
+		dbus_g_connection_register_g_object (private->connection, 
+						     TRACKER_EVOLUTION_REGISTRAR_PATH, 
+						     private->object);
+
+		/* Registration of the registrar to the manager */
+		dbus_g_proxy_call_no_reply (private->manager_proxy, "Register",
+					    G_TYPE_OBJECT, private->object, /* TRACKER_EVOLUTION_REGISTRAR_PATH, */
+					    G_TYPE_UINT, get_stored_last_checkout (),
+					    G_TYPE_INVALID,
+					    G_TYPE_INVALID);
+
+		error_handler:
+
+		if (error) {
+			g_critical ("Could not setup DBus, %s\n", error->message);
+			g_error_free (error);
+		}
+	}
+}
+
+static void
+name_owner_changed_cb (DBusGProxy *proxy, 
+		       gchar *name, 
+		       gchar *old_owner, 
+		       gchar *new_owner, 
+		       gpointer user_data)
+{
+
+	/* If we receive a NameOwnerChanged about the manager's service */
+
+	if (g_strcmp0 (name, TRACKER_EVOLUTION_MANAGER_SERVICE) == 0) {
+		if ((!new_owner || strlen (new_owner) == 0) && (old_owner && strlen (old_owner) > 0))
+			deactivate_registrar ();
+		if ((!old_owner || strlen (old_owner) == 0) && (new_owner && strlen (new_owner) > 0))
+			activate_registrar ();
+	}
+}
+
+
+static void
+list_names_reply_cb (DBusGProxy     *proxy,
+		     DBusGProxyCall *call,
+		     gpointer        user_data)
+{
+	GError *error = NULL;
+	GStrv names = NULL;
+	guint i = 0;
+
+	dbus_g_proxy_end_call (proxy, call, &error,
+			       G_TYPE_STRV, &names,
+			       G_TYPE_INVALID);
+
+	if (error) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		if (names)
+			g_strfreev (names); 
+		return;
+	}
+
+	while (names[i] != NULL) {
+		/* If the manager's service is found, start the registrar */
+		if (g_strcmp0 (names[i], TRACKER_EVOLUTION_MANAGER_SERVICE) == 0) {
+			activate_registrar ();
+			break;
+		}
+		i++;
+	}
+
+	g_strfreev (names); 
+}
+
+static void
+activate_dbus_client (void)
+{
+	EvolutionSupportPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	private->dbus_proxy = dbus_g_proxy_new_for_name (private->connection, 
+							 DBUS_SERVICE_DBUS,
+							 DBUS_PATH_DBUS,
+							 DBUS_INTERFACE_DBUS);
+
+	/* We listen for NameOwnerChanged to know when the manager's service 
+	 * comes up and to know when it goes down */
+
+	dbus_g_proxy_add_signal (private->dbus_proxy, "NameOwnerChanged",
+				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+				 G_TYPE_INVALID);
+
+	dbus_g_proxy_connect_signal (private->dbus_proxy, "NameOwnerChanged",
+				     G_CALLBACK (name_owner_changed_cb),
+				     NULL, NULL);
+
+	/* If the manager service is up and running, then list_names_reply_cb
+	 * will execute activate_registrar, as it'll appear in the results of
+	 * the ListNames DBus function. If not then we will just wait for the
+	 * NameOwnerChanged to emit that the manager's service has came up. */
+
+	dbus_g_proxy_begin_call (private->dbus_proxy, "ListNames",
+				 list_names_reply_cb, NULL, NULL,
+				 G_TYPE_INVALID,
+				 G_TYPE_INVALID);
+}
+
+static gboolean 
+is_enabled (TrackerConfig *config)
+{
+	gboolean enabled = TRUE;
+	GSList *disabled = tracker_config_get_disabled_modules (config);
+
+	/* If none of the disabled modules include the Evolution module,
+	 * we assume we are enabled in the configuration. */
+
+	while (disabled && enabled) {
+		if (g_strcmp0 (disabled->data, "Evolution") == 0)
+			enabled = FALSE;
+		disabled = g_slist_next (disabled);
+	}
+
+	return enabled;
+}
+
+static void 
+disabled_notify (GObject    *pspec,
+		 GParamSpec *gobject,
+		 gpointer    user_data)
+{
+	EvolutionSupportPrivate *private;
+	gboolean new_value;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	new_value = is_enabled (private->config);
+
+	if (private->is_enabled != new_value) {
+		if (private->is_enabled) {
+			/* If we were enabled, disable */
+			deactivate_dbus_client ();
+		} else {
+			/* If we were disabled, enable */
+			activate_dbus_client ();
+		}
+		private->is_enabled = new_value;
+	}
+
+	g_message ("Evolutiopn support service %s", 
+		   private->is_enabled ? "enabled" : "disabled");
+}
+
+void
+tracker_evolution_init (TrackerConfig *config)
+{
+	EvolutionSupportPrivate *private;
+	GError *error = NULL;
+
+	private = g_new0 (EvolutionSupportPrivate, 1);
+
+	private->deactivating = FALSE;
+	private->config = g_object_ref (config);
+	private->is_enabled = is_enabled (config);
+	private->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+	if (error)
+		goto error_handler;
+
+	g_static_private_set (&private_key,
+			      private,
+			      (GDestroyNotify) g_free);
+
+	/* Hook configuration changes */
+	g_signal_connect (private->config, "notify::disabled-modules",
+			  G_CALLBACK (disabled_notify), 
+			  NULL);
+
+	/* If in configuration we are enabled now */
+	if (private->is_enabled)
+		activate_dbus_client ();
+
+	error_handler:
+
+	if (error) {
+		g_object_unref (private->config);
+		g_free (private);
+		g_critical ("Could not setup DBus, %s\n", error->message);
+		g_error_free (error);
+	}
+}
+
+void
+tracker_evolution_shutdown ()
+{
+	EvolutionSupportPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	if (private->is_enabled)
+		deactivate_dbus_client ();
+
+	g_object_unref (private->config);
+
+	g_static_private_set (&private_key, NULL, NULL);
+}
Index: src/tracker-evolution-plugin/tracker-evolution-registrar.c
===================================================================
--- src/tracker-evolution-plugin/tracker-evolution-registrar.c	(revision 0)
+++ src/tracker-evolution-plugin/tracker-evolution-registrar.c	(revision 0)
@@ -0,0 +1,223 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip@codeminded.be>
+ */
+
+#include "config.h"
+
+#include <libtracker-data/tracker-data-update.h>
+
+#include "tracker-evolution-registrar.h"
+#include "tracker-evolution-registrar-glue.h"
+
+#define TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarPrivate))
+
+G_DEFINE_TYPE (TrackerEvolutionRegistrar, tracker_evolution_registrar, G_TYPE_OBJECT)
+
+/* This runs in-process of trackerd. It simply proxies everything to the indexer
+ * who wont always be running. Which is why this is needed (trackerd is always
+ * running, so it's more suitable to respond to Evolution's reqeusts). */
+
+typedef struct {
+	DBusGProxy *idx_proxy;
+	DBusGConnection *connection;
+} TrackerEvolutionRegistrarPrivate;
+
+enum {
+	PROP_0,
+	PROP_CONNECTION
+};
+
+static void
+tracker_evolution_registrar_finalize (GObject *object)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	if (priv->idx_proxy)
+		g_object_unref (priv->idx_proxy);
+
+	G_OBJECT_CLASS (tracker_evolution_registrar_parent_class)->finalize (object);
+}
+
+static void 
+tracker_evolution_registrar_set_connection (TrackerEvolutionRegistrar *object, DBusGConnection *connection)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	priv->connection = connection; /* weak */
+
+	priv->idx_proxy = dbus_g_proxy_new_for_name (priv->connection, 
+						     "org.freedesktop.Tracker.Indexer",
+						     TRACKER_EVOLUTION_INDEXER_PATH,
+						     TRACKER_EVOLUTION_REGISTRAR_INTERFACE);
+}
+
+static void
+tracker_evolution_registrar_set_property (GObject      *object,
+					  guint         prop_id,
+					  const GValue *value,
+					  GParamSpec   *pspec)
+{
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		tracker_evolution_registrar_set_connection (TRACKER_EVOLUTION_REGISTRAR (object),
+							    g_value_get_pointer (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_registrar_get_property (GObject    *object,
+					  guint       prop_id,
+					  GValue     *value,
+					  GParamSpec *pspec)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		g_value_set_pointer (value, priv->connection);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_registrar_class_init (TrackerEvolutionRegistrarClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = tracker_evolution_registrar_finalize;
+	object_class->set_property = tracker_evolution_registrar_set_property;
+	object_class->get_property = tracker_evolution_registrar_get_property;
+
+	g_object_class_install_property (object_class,
+					 PROP_CONNECTION,
+					 g_param_spec_pointer ("connection",
+							       "DBus connection",
+							       "DBus connection",
+							      G_PARAM_READWRITE |
+							      G_PARAM_CONSTRUCT));
+
+	g_type_class_add_private (object_class, sizeof (TrackerEvolutionRegistrarPrivate));
+}
+
+static void
+tracker_evolution_registrar_init (TrackerEvolutionRegistrar *object)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	priv->idx_proxy = NULL;
+
+}
+
+void
+tracker_evolution_registrar_set (TrackerEvolutionRegistrar *object, 
+				 const gchar *subject, 
+				 const GStrv predicates,
+				 const GStrv values,
+				 DBusGMethodInvocation *context)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	dbus_async_return_if_fail (subject != NULL, context);
+
+	dbus_g_proxy_call_no_reply (priv->idx_proxy,
+				    "Set",
+				    G_TYPE_STRING, subject,
+				    G_TYPE_STRV, predicates,
+				    G_TYPE_STRV, values,
+				    G_TYPE_INVALID, 
+				    G_TYPE_INVALID);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_registrar_set_many (TrackerEvolutionRegistrar *object, 
+				      const GStrv subjects, 
+				      const GPtrArray *predicates,
+				      const GPtrArray *values,
+				      DBusGMethodInvocation *context)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	dbus_g_proxy_call_no_reply (priv->idx_proxy,
+				    "SetMany",
+				    G_TYPE_STRV, subjects,
+				    TRACKER_TYPE_G_STRV_ARRAY, predicates,
+				    TRACKER_TYPE_G_STRV_ARRAY, values,
+				    G_TYPE_INVALID, 
+				    G_TYPE_INVALID);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_registrar_unset_many (TrackerEvolutionRegistrar *object, 
+					const GStrv subjects, 
+					DBusGMethodInvocation *context)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	dbus_g_proxy_call_no_reply (priv->idx_proxy,
+				    "UnsetMany",
+				    G_TYPE_STRV, subjects,
+				    G_TYPE_INVALID, 
+				    G_TYPE_INVALID);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_registrar_unset (TrackerEvolutionRegistrar *object, 
+				   const gchar *subject, 
+				   DBusGMethodInvocation *context)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	dbus_async_return_if_fail (subject != NULL, context);
+
+	dbus_g_proxy_call_no_reply (priv->idx_proxy,
+				    "Unset",
+				    G_TYPE_STRING, subject,
+				    G_TYPE_INVALID, 
+				    G_TYPE_INVALID);
+
+	dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_registrar_cleanup (TrackerEvolutionRegistrar *object, 
+				     DBusGMethodInvocation *context)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	dbus_g_proxy_call_no_reply (priv->idx_proxy,
+				    "Cleanup",
+				    G_TYPE_INVALID, 
+				    G_TYPE_INVALID);
+
+	dbus_g_method_return (context);
+}
Index: configure.ac
===================================================================
--- configure.ac	(revision 2761)
+++ configure.ac	(working copy)
@@ -120,6 +120,8 @@
 LIBGSF_REQUIRED=1.13
 EXEMPI_REQUIRED=1.99.2
 HILDON_THUMBNAIL_REQUIRED=3.0.10
+EVO_REQUIRED=2.25.3
+EDS_REQUIRED=2.25.3
 
 # Library Checks
 PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= $GLIB_REQUIRED])
@@ -181,6 +183,24 @@
   AC_DEFINE(HAVE_RAPTOR, 1, [Raptor RDF parsers])
 fi
 
+# Check for Evolution's plugin system
+PKG_CHECK_MODULES(EVOPLUG, [
+	evolution-plugin >= $EVO_REQUIRED
+	evolution-data-server-1.2 >= $EDS_REQUIRED], 
+	have_evoplug=yes, have_evoplug=no)
+AC_SUBST(EVOPLUG_CFLAGS)
+AC_SUBST(EVOPLUG_LIBS)
+
+if test x$have_evoplug == "xyes"; then
+EVOPLUG_INSTALL_DIR=`$PKG_CONFIG evolution-plugin --variable=plugindir`
+else
+EVOPLUG_INSTALL_DIR=/dev/null
+fi
+
+AC_SUBST(EVOPLUG_INSTALL_DIR)
+
+AM_CONDITIONAL(HAVE_EVOPLUG, test "$have_evoplug" = "yes")
+
 # Check we have the DBUS binding tool we need
 AC_PATH_PROG(DBUSBINDINGTOOL, dbus-binding-tool)
 if test -z $DBUSBINDINGTOOL; then
@@ -1199,6 +1219,7 @@
 	src/tracker-search-tool/Makefile
 	src/tracker-search-tool/tracker-search-tool.desktop.in
 	src/tracker-utils/Makefile
+	src/tracker-evolution-plugin/Makefile
 	tests/common/Makefile
 	tests/libtracker-common/Makefile
 	tests/libtracker-db/Makefile
Index: data/services/email.metadata
===================================================================
--- data/services/email.metadata	(revision 2761)
+++ data/services/email.metadata	(working copy)
@@ -58,7 +58,9 @@
 DataType=Indexable
 Weight=5
 
+[Email:Text]
+DisplayName=Text
+Description=The body of the E-mail
+DataType=Indexable
+Weight=1
 
-
-
-
Index: data/db/sqlite-tracker.sql
===================================================================
--- data/db/sqlite-tracker.sql	(revision 2761)
+++ data/db/sqlite-tracker.sql	(working copy)
@@ -8,6 +8,7 @@
 insert Into Options (OptionKey, OptionValue) values ('Sequence', '1');
 insert Into Options (OptionKey, OptionValue) values ('EventSequence', '1');
 insert Into Options (OptionKey, OptionValue) values ('UpdateCount', '0');
+insert Into Options (OptionKey, OptionValue) values ('EvolutionLastCheckout', '0');
 
 
 /* store volume and HAL info here for files */
