Index: src/tracker-indexer/Makefile.am
===================================================================
--- src/tracker-indexer/Makefile.am	(revision 2736)
+++ src/tracker-indexer/Makefile.am	(working copy)
@@ -54,6 +54,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 \
 	$(trackerd_win_libs)						\
 	$(DBUS_LIBS)							\
 	$(GMODULE_LIBS)							\
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 2736)
+++ 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)				\
@@ -44,7 +48,8 @@
 	$(build_libtrackergtk)			\
 	$(build_tracker_applet)			\
 	$(build_tracker_search_tool)		\
-	$(build_tracker_preferences)
+	$(build_tracker_preferences)		\
+	$(build_evoplug)
 
 DIST_SUBDIRS = 					\
 	libstemmer				\
@@ -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,
+					 int last_checkout, 
+					 DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __TRACKER_EVOLUTION_PLUGIN_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,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 __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, TrackerEvolutionPlugin))
+#define TRACKER_EVOLUTION_REGISTRAR_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionPluginClass))
+#define TRACKER_EVOLUTION_REGISTRAR_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarClass))
+
+G_BEGIN_DECLS
+
+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="i" 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,14 @@
+<?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">
+
+		<_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,68 @@
+/* -*- 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_REGISTRAR_SERVICE	"org.gnome.evolution"
+#define TRACKER_EVOLUTION_REGISTRAR_PATH	"/org/gnome/evolution/metadata/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 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,84 @@
+INCLUDES =						\
+	-I$(top_srcdir)/src				\
+	-DGETTEXT_PACKAGE="\"$(GETTEXT_PACKAGE)\""	\
+	-DLOCALEDIR="\"$(LOCALEDIR)\""			\
+	-DTRACKER_COMPILATION				\
+	$(DBUS_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_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)
+
+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,1110 @@
+/* -*- 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 <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 <mail/mail-session.h>
+#include <mail/em-utils.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		3000
+#define DIRKEY "/apps/evolution/mail/Tracker"
+#define DIRKEY_LENGTH (G_N_ELEMENTS (DIRKEY) - 1)
+
+#define TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginPrivate))
+
+G_DEFINE_TYPE (TrackerEvolutionPlugin, tracker_evolution_plugin, G_TYPE_OBJECT)
+
+/* 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 TRACKER_TYPE_G_STRV_ARRAY   (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRV))
+
+#ifndef dbus_g_method_get_sender
+gchar* dbus_g_method_get_sender (DBusGMethodInvocation *context);
+#endif
+
+
+static gboolean enabled = TRUE;
+static DBusGProxy *proxy = NULL;
+static GObject *object = NULL;
+static GHashTable *folders = NULL;
+
+typedef struct {
+	guint64 last_checkout;
+	DBusGProxy *registrar;
+} ClientRegistry;
+
+typedef struct {
+	DBusGConnection *connection;
+	GHashTable *registrars;
+	GStaticRecMutex *mutex;
+	GHashTable *folders;
+} TrackerEvolutionPluginPrivate;
+
+enum {
+	PROP_0,
+	PROP_CONNECTION
+};
+
+static void metadata_set (const gchar *subject, GStrv predicates, GStrv values);
+static void metadata_set_many (GStrv subjects, GPtrArray *predicates, GPtrArray *values);
+static void metadata_unset (const gchar *subject);
+static void metadata_unset_many (GStrv subjects);
+static void metadata_cleanup (void);
+
+
+/* If new messages arrive to- or get deleted from the summary */
+
+static void
+on_folder_summary_changed (CamelFolder *folder, CamelFolderChangeInfo *changes, gpointer user_data)
+{
+	guint i;
+	CamelFolderSummary *summary = folder->summary;
+	gchar *account_uri = user_data;
+	g_warning (__FUNCTION__);
+	gchar *auri = g_strdup (account_uri), *ptr;
+
+	ptr = strchr (auri, ';');
+	if (ptr)
+		*ptr = '\0';
+
+	if (changes->uid_added && changes->uid_added->len > 0) {
+		const gchar *predicates[8] = { TRACKER_EVOLUTION_PREDICATE_SUBJECT, 
+					       TRACKER_EVOLUTION_PREDICATE_TO,
+					       TRACKER_EVOLUTION_PREDICATE_FROM,
+					       TRACKER_EVOLUTION_PREDICATE_CC, 
+					       TRACKER_EVOLUTION_PREDICATE_SENT,
+					       TRACKER_EVOLUTION_PREDICATE_FILE,
+					       TRACKER_EVOLUTION_PREDICATE_UID,
+					       NULL };
+		GPtrArray *predicates_array = g_ptr_array_new ();
+		GPtrArray *values_array = g_ptr_array_new ();
+		gchar **subjects = (gchar **) g_malloc0 (sizeof (gchar *) * changes->uid_added->len + 1);
+		gchar *camel_uri;
+
+		/* the uid_added member contains the added-to-the-summary items */
+
+		for (i = 0; i< changes->uid_added->len; i++) {
+			gchar **values = (gchar **) g_malloc0 (sizeof (gchar*) * 8);
+			CamelMessageInfo *info = camel_folder_summary_uid (summary, 
+									   changes->uid_added->pdata[i]);
+
+			camel_uri = g_strdup_printf ("%s/%s/%s", 
+						     auri, 
+						     camel_folder_get_full_name (folder),
+						     camel_message_info_uid (info));
+
+			subjects[i] = /*em_uri_from_camel*/ (camel_uri);
+
+			/*g_free (camel_uri);*/
+
+			values[0] = (gchar *) camel_message_info_subject (info);
+			values[1] = (gchar *) camel_message_info_to (info);
+			values[2] = (gchar *) camel_message_info_from (info);
+			values[3] = (gchar *) camel_message_info_cc (info);
+			values[4] = g_strdup_printf ("%d", camel_message_info_date_sent (info)); /* freeme */
+
+			/* TODO: determine file. It's likely that at this time the
+			 * file doesn't yet exist. It's just a summary update, this
+			 * is not the same as "the user clicked on a message" */
+
+			values[5] = g_strdup (""); /* freeme */
+			values[6] = (gchar *) camel_message_info_uid (info);
+			values[7] = NULL;
+
+			g_ptr_array_add (values_array, values);
+			g_ptr_array_add (predicates_array, predicates);
+		}
+
+		/* This goes to all currently registered registrars */
+
+		metadata_set_many (subjects, predicates_array, values_array);
+
+		for (i = 0; i < values_array->len; i++) {
+			gchar **values = values_array->pdata[i];
+			g_free (values[4]); /* freeme */
+			g_free (values[5]); /* freeme */
+			/* g_strfreev (values_array->pdata[i]); */
+			g_free (values);
+		}
+		g_strfreev (subjects);
+		g_ptr_array_free (predicates_array, TRUE);
+		g_ptr_array_free (values_array, 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++) {
+			gchar *camel_uri;
+
+			camel_uri = g_strdup_printf ("%s/%s/%s", auri, 
+						     camel_folder_get_full_name (folder),
+						     changes->uid_removed->pdata[i]);
+
+			subjects[i] = /*em_uri_from_camel*/(camel_uri);
+
+			/*g_free (camel_uri);*/
+		}
+
+		subjects[i] = NULL;
+
+		/* This goes to all currently registered registrars */
+
+		metadata_unset_many (subjects);
+
+		g_strfreev (subjects);
+	}
+	g_free (auri);
+}
+
+/* Initial upload of more recent than last_checkout items */
+
+static void
+init_walk_folders_in_folder (CamelFolderInfo *iter, CamelStore *store, gchar *account_uri, gpointer user_data)
+{
+	ClientRegistry *info = user_data;
+	const gchar *predicates[8] = { TRACKER_EVOLUTION_PREDICATE_SUBJECT, 
+				       TRACKER_EVOLUTION_PREDICATE_TO,
+				       TRACKER_EVOLUTION_PREDICATE_FROM,
+				       TRACKER_EVOLUTION_PREDICATE_CC, 
+				       TRACKER_EVOLUTION_PREDICATE_SENT,
+				       TRACKER_EVOLUTION_PREDICATE_FILE,
+				       TRACKER_EVOLUTION_PREDICATE_UID,
+				       NULL };
+	gchar *auri = g_strdup (account_uri), *ptr;
+
+	ptr = strchr (auri, ';');
+	if (ptr)
+		*ptr = '\0';
+
+	g_warning (__FUNCTION__);
+
+	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 FROM %Q WHERE modified > %d", 
+					 iter->full_name, info->last_checkout);
+
+		g_warning (query);
+
+		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;
+
+			while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) {
+				const gchar *uid;
+				gchar *camel_uri;
+				gchar **values;
+
+				ret = sqlite3_step (stmt);
+
+				if (ret == SQLITE_BUSY) {
+					usleep (10);
+					continue;
+				}
+
+				if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) {
+					more = FALSE;
+					break;
+				}
+
+				values = (gchar **) g_malloc0 (sizeof (gchar*) * 8);
+
+				uid = sqlite3_column_text (stmt, 0);
+
+				values[0] = (gchar *) sqlite3_column_text (stmt, 11);
+				values[1] = (gchar *) sqlite3_column_text (stmt, 13);
+				values[2] = (gchar *) sqlite3_column_text (stmt, 12);
+				values[3] = (gchar *) sqlite3_column_text (stmt, 14);
+				values[4] = (gchar *) sqlite3_column_text (stmt, 9);
+
+				// TODO determine filename
+				values[5] = g_strdup ("unknown.eml"); /* freeme */
+				values[6] = (gchar *) uid;
+
+				values[7] = NULL;
+
+				camel_uri = g_strdup_printf ("%s/%s/%s", 
+							     auri, 
+							     iter->full_name, 
+							     uid);
+
+				g_ptr_array_add (subjects_a, /*em_uri_from_camel*/ (camel_uri));
+				//g_free (camel_uri);
+
+				g_ptr_array_add (predicates_array, predicates);
+				g_ptr_array_add (values_array, values);
+
+				if (count > MAX_BEFORE_SEND) {
+
+					/* Yield per MAX_BEFORE_SEND */
+					g_main_context_iteration (NULL, FALSE);
+
+					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,
+							    "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++) {
+				gchar **values = values_array->pdata[i];
+				g_free (values[5]); // freeme 
+				 //g_strfreev (values_array->pdata[i]); 
+				g_free (values);
+			}
+			g_ptr_array_free (predicates_array, TRUE);
+			g_ptr_array_free (values_array, TRUE);
+		}
+
+		sqlite3_finalize (stmt);
+		sqlite3_free (query);
+
+		if (iter->child) {
+			init_walk_folders_in_folder (iter->child, store, account_uri, user_data);
+		}
+
+		/* Yield per folder */
+		g_main_context_iteration (NULL, FALSE);
+
+		iter = iter->next;
+	}
+	g_free (auri);
+}
+
+/* Initial notify of deletes that are more recent than last_checkout */
+
+static void
+init_store_deal_with_deleted (CamelStore *store, char *uri, gpointer user_data)
+{
+	ClientRegistry *info = user_data;
+	gboolean more = TRUE;
+	gchar *query;
+	sqlite3_stmt *stmt = NULL;
+	CamelDB *cdb_r;
+	guint i, ret;
+	g_warning (__FUNCTION__);
+
+	gchar *auri = g_strdup (uri), *ptr;
+
+	ptr = strchr (auri, ';');
+	if (ptr)
+		*ptr = '\0';
+
+	/* TODO: don't use %d but something for uint64 here */
+	/* TODO: check this query */
+
+	query = sqlite3_mprintf ("SELECT uid , mailbox FROM Deleted WHERE modified > %d", 
+				 info->last_checkout);
+
+	g_warning (query);
+
+	cdb_r = store->cdb_r;
+
+	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;
+
+		while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) {
+			const gchar *uid;
+			const gchar *mailbox;
+			gchar *camel_uri;
+
+			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 = sqlite3_column_text (stmt, 0);
+			mailbox = sqlite3_column_text (stmt, 0);
+
+			camel_uri = g_strdup_printf ("%s/%s/%s", 
+						     auri, 
+						     mailbox, 
+						     uid);
+
+			g_ptr_array_add (subjects_a, /*em_uri_from_camel*/ (camel_uri));
+
+			/*g_free (camel_uri);*/
+
+			if (count > MAX_BEFORE_SEND) {
+
+				/* Yield per MAX_BEFORE_SEND */
+				g_main_context_iteration (NULL, FALSE);
+
+				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_free (auri);
+}
+
+static guint64
+get_last_deleted_time (void)
+{
+	EAccountList *accounts;
+	GConfClient *gconf;
+	guint64 smallest = (guint64) -1;
+	g_warning (__FUNCTION__);
+
+	gconf = gconf_client_get_default ();
+	accounts = e_account_list_new (gconf);
+
+	if (accounts) {
+		gboolean changed = FALSE;
+		EIterator *it;
+
+		for (it = e_list_get_iterator (E_LIST (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;
+			guint64 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;
+
+			/* TODO: check this query */
+
+			query = sqlite3_mprintf ("SELECT time FROM Deletes ORDER BY time LIMIT 1");
+			g_warning (query);
+
+			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_int (stmt, 0);
+
+			if (latest < smallest)
+				smallest = latest;
+
+			sqlite3_finalize (stmt);
+			sqlite3_free (query);
+
+		}
+
+		g_object_unref (it);
+		g_object_unref (accounts);
+	}
+
+	g_object_unref (gconf);
+
+	return smallest;
+}
+
+
+
+static void
+setup_walk_folders_in_folder (CamelFolderInfo *iter, CamelStore *store, gchar *account_uri, gpointer user_data)
+{
+	g_warning (__FUNCTION__);
+
+	while (iter) {
+		CamelFolder *folder;
+
+		folder = camel_store_get_folder (store, iter->full_name, 0, NULL);
+
+		if (folder) {
+			guint hook_id;
+
+			if (!folders)
+				folders = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+			/* TODO: the small memleak for strdup of account_uri */
+
+			hook_id = camel_object_hook_event (folder, 
+					  "folder_changed", 
+					   (CamelObjectEventHookFunc) on_folder_summary_changed, 
+					   g_strdup (account_uri));
+
+			g_hash_table_replace (folders, folder, (gpointer) hook_id);
+		}
+
+		if (iter->child) {
+			setup_walk_folders_in_folder (iter->child, store, 
+						      account_uri, user_data);
+		}
+
+		/* Yield per folder */
+		g_main_context_iteration (NULL, FALSE);
+
+		iter = iter->next;
+	}
+}
+
+
+static void
+setup_each_account (gpointer user_data)
+{
+	EAccountList *accounts;
+	GConfClient *gconf;
+	g_warning (__FUNCTION__);
+
+	gconf = gconf_client_get_default ();
+	accounts = e_account_list_new (gconf);
+
+	if (accounts) {
+		gboolean changed = FALSE;
+		EIterator *it;
+
+		for (it = e_list_get_iterator (E_LIST (accounts)); e_iterator_is_valid (it); e_iterator_next (it)) {
+			EAccount *account = (EAccount *) e_iterator_get (it);
+			CamelProvider *provider;
+			CamelStore *store;
+			CamelFolderInfo *iter = NULL;
+			CamelException ex;
+			char *uri;
+
+			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;
+			}
+
+			iter = camel_store_get_folder_info (store, "", CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL |
+				CAMEL_STORE_FOLDER_INFO_RECURSIVE, &ex);
+
+			setup_walk_folders_in_folder (iter, store, uri, user_data);
+
+			camel_folder_info_free (iter);
+
+			camel_object_unref (store);
+
+		}
+		g_object_unref (it);
+		g_object_unref (accounts);
+	}
+
+	g_object_unref (gconf);
+}
+
+
+static void
+init_each_account (gpointer user_data)
+{
+	EAccountList *accounts;
+	GConfClient *gconf;
+	ClientRegistry *info = user_data;
+	g_warning (__FUNCTION__);
+
+	gconf = gconf_client_get_default ();
+	accounts = e_account_list_new (gconf);
+
+	if (accounts) {
+		gboolean changed = FALSE;
+		EIterator *it;
+
+		for (it = e_list_get_iterator (E_LIST (accounts)); e_iterator_is_valid (it); e_iterator_next (it)) {
+			EAccount *account = (EAccount *) e_iterator_get (it);
+			CamelProvider *provider;
+			CamelStore *store;
+			CamelFolderInfo *iter = NULL;
+			CamelException ex;
+			char *uri;
+
+			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;
+			}
+
+			init_store_deal_with_deleted (store, uri, user_data);
+
+			iter = camel_store_get_folder_info (store, "", CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL |
+				CAMEL_STORE_FOLDER_INFO_RECURSIVE, &ex);
+
+			init_walk_folders_in_folder (iter, store, uri, user_data);
+
+			camel_folder_info_free (iter);
+
+			camel_object_unref (store);
+		}
+
+		g_object_unref (it);
+		g_object_unref (accounts);
+	}
+
+	g_object_unref (gconf);
+
+}
+
+static void
+register_client (guint64 last_checkout, DBusGProxy *registrar)
+{
+	/* TODO: verify this too-old check, not sure */
+	guint64 too_old = get_last_deleted_time ();
+	ClientRegistry *info = g_slice_new (ClientRegistry);
+	g_warning (__FUNCTION__);
+
+	info->registrar = 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;
+
+
+	init_each_account ((gpointer) info);
+
+	g_slice_free (ClientRegistry, info);
+}
+
+
+
+static void
+metadata_set (const gchar *subject, GStrv predicates, GStrv values)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	GHashTableIter iter;
+	gpointer key, value;
+	g_warning (__FUNCTION__);
+
+	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,
+					    "Set",
+					    G_TYPE_STRING, subject,
+					    G_TYPE_STRV, predicates,
+					    G_TYPE_STRV, values,
+					    G_TYPE_INVALID, 
+					    G_TYPE_INVALID);
+	}
+
+	g_static_rec_mutex_unlock (priv->mutex);
+
+}
+
+
+static void
+metadata_set_many (GStrv subjects, GPtrArray *predicates, GPtrArray *values)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	GHashTableIter iter;
+	gpointer key, value;
+	g_warning (__FUNCTION__);
+
+	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 (const gchar *subject)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	GHashTableIter iter;
+	gpointer key, value;
+	g_warning (__FUNCTION__);
+
+	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,
+					    "Unset",
+					    G_TYPE_STRING, subject,
+					    G_TYPE_INVALID, 
+					    G_TYPE_INVALID);
+	}
+
+	g_static_rec_mutex_unlock (priv->mutex);
+
+}
+
+
+static void
+metadata_unset_many (GStrv subjects)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	GHashTableIter iter;
+	gpointer key, value;
+	g_warning (__FUNCTION__);
+
+	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
+unload_setup (void)
+{
+	g_warning (__FUNCTION__);
+
+	if (folders) {
+		GHashTableIter iter;
+		gpointer value, key;
+
+		g_hash_table_iter_init (&iter, folders);
+
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			CamelFolder *folder = key;
+			guint hook_id = (guint) value;
+
+			camel_object_remove_event (folder, hook_id);
+			camel_object_unref (folder);
+		}
+
+		g_hash_table_destroy (folders);
+		folders = NULL;
+	}
+}
+
+static void
+load_setup (void) {
+	g_warning (__FUNCTION__);
+	setup_each_account (NULL);
+}
+
+static void
+disable_plugin (void) 
+{
+	g_warning (__FUNCTION__);
+
+	unload_setup ();
+
+	if (proxy) {
+		g_object_unref (proxy);
+		proxy = NULL;
+	}
+
+	if (object) {
+		g_object_unref (object);
+		object = NULL;
+	}
+}
+
+static void
+enable_plugin (void)
+{
+	DBusGConnection *connection;
+	GError *error = NULL;
+	guint result;
+	g_warning (__FUNCTION__);
+
+	g_warning ("create tracker plugin1\n");
+	if (proxy && object)
+		return;
+
+	if ((proxy && !object) || (!proxy && object))
+		disable_plugin ();
+
+	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+	if (error)
+		goto error_handler;
+
+	g_warning ("create tracker plugin2\n");
+	
+	proxy = dbus_g_proxy_new_for_name (connection, 
+					   DBUS_SERVICE_DBUS,
+					   DBUS_PATH_DBUS,
+					   DBUS_INTERFACE_DBUS);
+
+	org_freedesktop_DBus_request_name (proxy, TRACKER_EVOLUTION_MANAGER_SERVICE,
+					   DBUS_NAME_FLAG_DO_NOT_QUEUE,
+					   &result, &error);
+
+	if (error)
+		goto error_handler;
+
+	g_warning ("create tracker plugin3\n");
+	
+	object = g_object_new (TRACKER_TYPE_EVOLUTION_PLUGIN, 
+			       "connection", connection,
+			       NULL);
+
+	dbus_g_object_type_install_info (G_OBJECT_TYPE (object), 
+					 &dbus_glib_tracker_evolution_plugin_object_info);
+
+	dbus_g_connection_register_g_object (connection, 
+					     TRACKER_EVOLUTION_MANAGER_PATH, 
+					     object);
+
+	error_handler:
+
+	if (error) {
+		g_critical ("Could not setup DBus, %s\n", error->message);
+		disable_plugin();
+		g_error_free (error);
+	}
+	else
+		load_setup ();
+
+	g_warning ("create tracker plugin4\n");
+}
+
+
+static gboolean 
+do_remove_or_not (gpointer key, gpointer value, gpointer user_data)
+{
+	g_warning (__FUNCTION__);
+
+	if (user_data == value)
+		return TRUE;
+	return FALSE;
+}
+
+static void
+service_gone (DBusGProxy *proxy, TrackerEvolutionPlugin *object)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	g_warning (__FUNCTION__);
+
+	g_static_rec_mutex_lock (priv->mutex);
+
+	g_hash_table_foreach_remove (priv->registrars, 
+				     do_remove_or_not,
+				     proxy);
+
+	g_static_rec_mutex_unlock (priv->mutex);
+}
+
+void 
+tracker_evolution_plugin_register  (TrackerEvolutionPlugin *object, 
+				    gchar *registrar_path,
+				    int last_checkout, 
+				    DBusGMethodInvocation *context)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	gchar *sender;
+	DBusGProxy *registrar;
+	guint len;
+	guint i;
+
+	g_warning (__FUNCTION__);
+
+	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),
+			  object);
+
+	g_static_rec_mutex_unlock (priv->mutex);
+
+	register_client (last_checkout, registrar);
+
+	dbus_g_method_return (context);
+
+}
+
+
+int
+e_plugin_lib_enable (EPluginLib *ep, int enable)
+{
+	g_warning (__FUNCTION__);
+	enabled = TRUE;
+	if (enabled)
+		enable_plugin ();
+	else
+		disable_plugin ();
+	return 0;
+}
+
+
+static void
+tracker_evolution_plugin_finalize (GObject *object)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+
+	g_warning (__FUNCTION__);
+
+	g_hash_table_destroy (priv->registrars);
+	g_slice_free (GStaticRecMutex, priv->mutex);
+
+	G_OBJECT_CLASS (tracker_evolution_plugin_parent_class)->finalize (object);
+}
+
+static void 
+tracker_evolution_plugin_set_connection (TrackerEvolutionPlugin *object, DBusGConnection *connection)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+	priv->connection = connection;
+	g_warning (__FUNCTION__);
+
+}
+
+
+static void
+tracker_evolution_plugin_set_property (GObject      *object,
+		      guint         prop_id,
+		      const GValue *value,
+		      GParamSpec   *pspec)
+{
+	switch (prop_id) {
+	case PROP_CONNECTION:
+		tracker_evolution_plugin_set_connection (TRACKER_EVOLUTION_PLUGIN (object),
+						 g_value_get_pointer (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	}
+}
+
+static void
+tracker_evolution_plugin_get_property (GObject    *object,
+			      guint       prop_id,
+			      GValue     *value,
+			      GParamSpec *pspec)
+{
+	TrackerEvolutionPluginPrivate *priv;
+
+	priv = TRACKER_EVOLUTION_PLUGIN_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_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 *object)
+{
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (object);
+
+	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);
+}
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,37 @@
+/* -*- 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 "tracker-evolution.h"
+#include "tracker-evolution-registrar.h"
+
+void
+tracker_evolution_init (TrackerConfig *config)
+{
+}
+
+void
+tracker_evolution_shutdown ()
+{
+}
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,304 @@
+/* -*- 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 <gtk/gtk.h>
+
+#include <gconf/gconf-client.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-registrar.h"
+#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 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 tracker-indexer */
+
+typedef struct {
+	GMutex *mutex;
+} TrackerEvolutionRegistrarPrivate;
+
+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_registrar_finalize (GObject *object)
+{
+	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	g_mutex_free (priv->mutex);
+
+	G_OBJECT_CLASS (tracker_evolution_registrar_parent_class)->finalize (object);
+}
+
+
+static void
+tracker_evolution_registrar_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_registrar_get_property (GObject    *object,
+			      guint       prop_id,
+			      GValue     *value,
+			      GParamSpec *pspec)
+{
+	TrackerEvolutionRegistrarPrivate *priv;
+
+	priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	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_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->mutex = g_mutex_new ();
+}
+
+static void
+perform_set (TrackerEvolutionRegistrar *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 */
+		/* TODO: TRACKER_EVOLUTION_PREDICATE_FILE */
+
+		if (strcmp (predicates[i], TRACKER_EVOLUTION_PREDICATE_SUBJECT) == 0) {
+			tracker_module_metadata_add_string (metadata, 
+							    METADATA_EMAIL_SUBJECT, 
+							    values[i]);
+		}
+
+		if (strcmp (predicates[i], TRACKER_EVOLUTION_PREDICATE_SENT) == 0) {
+			tracker_module_metadata_add_string (metadata, 
+							    METADATA_EMAIL_DATE, 
+							    values[i]);
+		}
+
+		if (strcmp (predicates[i], METADATA_EMAIL_SENDER) == 0) {
+			tracker_module_metadata_add_string (metadata, 
+							    METADATA_EMAIL_SENDER, 
+							    values[i]);
+		}
+
+		if (strcmp (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 (strcmp (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 (TrackerEvolutionRegistrar *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 (TrackerEvolutionRegistrar *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_registrar_set (TrackerEvolutionRegistrar *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_registrar_set_many (TrackerEvolutionRegistrar *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_registrar_unset_many (TrackerEvolutionRegistrar *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_registrar_unset (TrackerEvolutionRegistrar *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_registrar_cleanup (TrackerEvolutionRegistrar *object, 
+				     DBusGMethodInvocation *context)
+{
+	perform_cleanup (object);
+
+	dbus_g_method_return (context);
+}
Index: configure.ac
===================================================================
--- configure.ac	(revision 2736)
+++ 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
@@ -1223,6 +1243,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
