tracker r2794 - in trunk: . data/db src src/libtracker-data src/plugins src/plugins/evolution src/tracker-indexer src/tracker-indexer/modules src/trackerd
- From: pvanhoof svn gnome org
- To: svn-commits-list gnome org
- Subject: tracker r2794 - in trunk: . data/db src src/libtracker-data src/plugins src/plugins/evolution src/tracker-indexer src/tracker-indexer/modules src/trackerd
- Date: Thu, 15 Jan 2009 12:58:15 +0000 (UTC)
Author: pvanhoof
Date: Thu Jan 15 12:58:15 2009
New Revision: 2794
URL: http://svn.gnome.org/viewvc/tracker?rev=2794&view=rev
Log:
2009-01-15 Philip Van Hoof <philip codeminded be>
* src/tracker-indexer/modules/Makefile.am
* src/tracker-indexer/modules/evolution.c:
Selecting between the old and the new Evolution support, depending on
availability of the right version of EDS
* data/services/email.metadata:
* data/db/sqlite-tracker.sql:
* configure.ac
* src/tracker-indexer/Makefile.am
* src/trackerd/Makefile.am
* src/Makefile.am
* src/tracker-evolution-plugin/tracker-evolution-plugin.h
* src/tracker-evolution-plugin/tracker-evolution-indexer.h
* src/tracker-evolution-plugin/tracker-evolution.h
* src/tracker-evolution-plugin/tracker-evolution-registrar.h
* src/tracker-evolution-plugin/tracker-evolution-plugin.xml
* src/tracker-evolution-plugin/org-freedesktop-Tracker-evolution-plugin.eplug.xml
* src/tracker-evolution-plugin/tracker-evolution-common.h
* src/tracker-evolution-plugin/Makefile.am
* src/tracker-evolution-plugin/tracker-evolution-plugin.c
* src/tracker-evolution-plugin/tracker-evolution-indexer.c
* src/tracker-evolution-plugin/tracker-evolution-registrar.xml
* src/tracker-evolution-plugin/tracker-evolution.c
* src/tracker-evolution-plugin/tracker-evolution-registrar.c:
Implementation of the new Evolution support
* src/trackerd/tracker-main.c
Added:
trunk/src/plugins/
trunk/src/plugins/Makefile.am
trunk/src/plugins/evolution/
trunk/src/plugins/evolution/Makefile.am
trunk/src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml
trunk/src/plugins/evolution/tracker-evolution-common.h
trunk/src/plugins/evolution/tracker-evolution-indexer.c
trunk/src/plugins/evolution/tracker-evolution-indexer.h
trunk/src/plugins/evolution/tracker-evolution-plugin.c
trunk/src/plugins/evolution/tracker-evolution-plugin.h
trunk/src/plugins/evolution/tracker-evolution-plugin.xml
trunk/src/plugins/evolution/tracker-evolution-registrar.c
trunk/src/plugins/evolution/tracker-evolution-registrar.h
trunk/src/plugins/evolution/tracker-evolution-registrar.xml
trunk/src/plugins/evolution/tracker-evolution.c
trunk/src/plugins/evolution/tracker-evolution.h
Modified:
trunk/ChangeLog
trunk/configure.ac
trunk/data/db/sqlite-stored-procs.sql
trunk/data/db/sqlite-tracker.sql
trunk/src/Makefile.am
trunk/src/libtracker-data/tracker-data-update.c
trunk/src/libtracker-data/tracker-data-update.h
trunk/src/tracker-indexer/Makefile.am
trunk/src/tracker-indexer/modules/evolution.c
trunk/src/tracker-indexer/tracker-main.c
trunk/src/trackerd/Makefile.am
trunk/src/trackerd/tracker-main.c
Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Thu Jan 15 12:58:15 2009
@@ -120,6 +120,8 @@
LIBGSF_REQUIRED=1.13
EXEMPI_REQUIRED=1.99.2
HILDON_THUMBNAIL_REQUIRED=3.0.10
+EVO_REQUIRED=2.25.5
+EDS_REQUIRED=2.25.5
# Library Checks
PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= $GLIB_REQUIRED])
@@ -181,6 +183,28 @@
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
+EVOLUTION_PLUGIN_INSTALL_DIR=`$PKG_CONFIG evolution-plugin --variable=plugindir`
+else
+EVOLUTION_PLUGIN_INSTALL_DIR=/dev/null
+fi
+
+AC_SUBST(EVOLUTION_PLUGIN_INSTALL_DIR)
+
+if test x$have_evoplug == "xyes"; then
+ AC_DEFINE(HAVE_EVOLUTION_PLUGIN, 1, [Evolution plugin])
+fi
+
+AM_CONDITIONAL(HAVE_EVOLUTION_PLUGIN, 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 +1223,8 @@
src/tracker-search-tool/Makefile
src/tracker-search-tool/tracker-search-tool.desktop.in
src/tracker-utils/Makefile
+ src/plugins/Makefile
+ src/plugins/evolution/Makefile
tests/common/Makefile
tests/libtracker-common/Makefile
tests/libtracker-db/Makefile
@@ -1256,6 +1282,11 @@
Support MP3 album art (w/ GdkPixbuf): $have_gdkpixbuf
Support Playlists (w/ Totem): $have_playlist
+Plugins:
+
+ Evolution support (old): yes
+ Evolution plugin: $have_evoplug
+
Warning:
You must make sure SQLite is compiled with --enable-threadsafe
Modified: trunk/data/db/sqlite-stored-procs.sql
==============================================================================
--- trunk/data/db/sqlite-stored-procs.sql (original)
+++ trunk/data/db/sqlite-stored-procs.sql Thu Jan 15 12:58:15 2009
@@ -171,6 +171,11 @@
GetXesamMimePrefixForServiceId SELECT MimePrefix FROM XesamFileMimePrefixes WHERE ServiceTypeId = ?;
/*
+ * Turtle importing
+ */
+DeleteServiceAll DELETE FROM Services WHERE ServiceTypeID = ?;
+
+/*
* Deprecated
*/
GetNewID SELECT OptionValue FROM Options WHERE OptionKey = 'Sequence';
Modified: trunk/data/db/sqlite-tracker.sql
==============================================================================
--- trunk/data/db/sqlite-tracker.sql (original)
+++ trunk/data/db/sqlite-tracker.sql Thu Jan 15 12:58:15 2009
@@ -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 */
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Thu Jan 15 12:58:15 2009
@@ -37,6 +37,7 @@
libtracker-data \
libtracker \
$(build_sqlite_fts) \
+ plugins \
trackerd \
tracker-utils \
tracker-extract \
@@ -62,4 +63,5 @@
libtracker-gtk \
tracker-applet \
tracker-search-tool \
- tracker-preferences
+ tracker-preferences \
+ plugins
Modified: trunk/src/libtracker-data/tracker-data-update.c
==============================================================================
--- trunk/src/libtracker-data/tracker-data-update.c (original)
+++ trunk/src/libtracker-data/tracker-data-update.c Thu Jan 15 12:58:15 2009
@@ -607,6 +607,35 @@
}
}
+
+void
+tracker_data_update_delete_service_all (const gchar *rdf_type)
+{
+ TrackerService *service;
+ gchar *service_type_id;
+ TrackerDBInterface *iface;
+
+ if (!rdf_type)
+ return;
+
+ service = tracker_ontology_get_service_by_name (rdf_type);
+
+ g_return_if_fail (TRACKER_IS_SERVICE (service));
+
+ service_type_id = tracker_gint_to_string (tracker_service_get_id (service));
+
+ iface = tracker_db_manager_get_db_interface_by_type (tracker_service_get_name (service),
+ TRACKER_DB_CONTENT_TYPE_METADATA);
+
+ tracker_db_interface_execute_procedure (iface,
+ NULL,
+ "DeleteServiceAll",
+ service_type_id,
+ NULL);
+
+ g_free (service_type_id);
+}
+
static void
set_metadata (TrackerField *field,
gpointer value,
Modified: trunk/src/libtracker-data/tracker-data-update.h
==============================================================================
--- trunk/src/libtracker-data/tracker-data-update.h (original)
+++ trunk/src/libtracker-data/tracker-data-update.h Thu Jan 15 12:58:15 2009
@@ -58,6 +58,8 @@
GHashTable *metadata);
void tracker_data_update_delete_service_by_path (const gchar *path,
const gchar *rdf_type);
+void tracker_data_update_delete_service_all (const gchar *rdf_type);
+
/* Metadata */
void tracker_data_update_set_metadata (TrackerService *service,
Added: trunk/src/plugins/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/plugins/Makefile.am Thu Jan 15 12:58:15 2009
@@ -0,0 +1,6 @@
+SUBDIRS = .
+
+if HAVE_EVOLUTION_PLUGIN
+SUBDIRS += evolution
+endif
+
Added: trunk/src/plugins/evolution/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/Makefile.am Thu Jan 15 12:58:15 2009
@@ -0,0 +1,89 @@
+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 = $(EVOLUTION_PLUGIN_INSTALL_DIR)
+
+eplugin_DATA = org-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 \
+ 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 -,_,$*) $^
+
+BUILT_SOURCES = \
+ $(dbus_sources) \
+ $(eplugin_DATA)
+
+CLEANFILES = $(BUILT_SOURCES) \
+ org-freedesktop-Tracker-evolution-plugin.eplug
+
+EXTRA_DIST = \
+ $(BUILT_SOURCES) \
+ org-freedesktop-Tracker-evolution-plugin.eplug.xml
Added: trunk/src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml Thu Jan 15 12:58:15 2009
@@ -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="after-ui">
+
+ <_description>Support for Tracker.</_description>
+
+ <author name="Philip Van Hoof" email="philip codeminded be"/>
+ </e-plugin>
+</e-plugin-list>
Added: trunk/src/plugins/evolution/tracker-evolution-common.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-common.h Thu Jan 15 12:58:15 2009
@@ -0,0 +1,76 @@
+/* -*- 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__
+
+#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__ */
Added: trunk/src/plugins/evolution/tracker-evolution-indexer.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-indexer.c Thu Jan 15 12:58:15 2009
@@ -0,0 +1,606 @@
+/* -*- 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: we can access its symbols */
+#include <tracker-indexer/tracker-module.h>
+#include <tracker-indexer/tracker-module-metadata-private.h>
+
+#include "tracker-evolution-indexer.h"
+
+/* These defines/renames are necessary for -glue.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"
+
+/* Based on data/services/email.metadata */
+
+#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:Body"
+#define METADATA_EMAIL_TAG "User:Keywords"
+
+#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 {
+ TrackerIndexer *indexer;
+} TrackerEvolutionIndexerPrivate;
+
+enum {
+ PROP_0,
+ PROP_INDEXER
+};
+
+static void
+tracker_evolution_indexer_finalize (GObject *object)
+{
+ TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
+
+ if (priv->indexer)
+ g_object_unref (priv->indexer);
+
+ 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)
+{
+ TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
+
+ switch (prop_id) {
+
+ case PROP_INDEXER:
+
+ if (priv->indexer)
+ g_object_unref (priv->indexer);
+
+ priv->indexer = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+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) {
+ case PROP_INDEXER:
+ g_value_set_object (value, priv->indexer);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+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_object_class_install_property (object_class,
+ PROP_INDEXER,
+ g_param_spec_object ("indexer",
+ "Indexer",
+ "Indexer",
+ tracker_indexer_get_type (),
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ 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->indexer = NULL;
+}
+
+
+#if 0
+static void
+extract_mime_parts (GMimeObject *object,
+ gpointer user_data)
+{
+ const gchar *message_subject = user_data;
+ gchar *subject = NULL;
+ 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;
+ }
+
+ if (filename) {
+ GHashTable *data;
+ TrackerModuleMetadata *metadata;
+ gchar *subject;
+
+ /* This is not a path but a URI: don't use the OS's dir separator
+ * here, use the '/'. Another option is to use '#' instead of '/'
+ * here. This depends on how we want to format the URI and what
+ * Evolution can cope with as URI for an attachment (I don't
+ * think it can cope with any attachment URI, btw). */
+
+ subject = g_strdup_printf ("%s/%s", message_subject,
+ filename);
+
+ metadata = tracker_module_metadata_new ();
+
+ tracker_module_metadata_add_string (metadata,
+ "File:Path",
+ subject);
+
+ tracker_module_metadata_add_string (metadata,
+ "File:Name",
+ filename);
+
+ data = tracker_module_metadata_get_hash_table (metadata);
+
+ tracker_data_update_replace_service (subject, "EvolutionEmails", data);
+
+ g_hash_table_destroy (data);
+ g_object_unref (metadata);
+ g_free (subject);
+ }
+}
+
+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);
+ }
+}
+#endif
+
+static void
+perform_set (TrackerEvolutionIndexer *object,
+ const gchar *subject,
+ const GStrv predicates,
+ const GStrv values)
+{
+ guint i = 0;
+ TrackerModuleMetadata *metadata;
+ GHashTable *data;
+
+ metadata = tracker_module_metadata_new ();
+
+ while (predicates [i] != NULL && values[i] != NULL) {
+
+ /* TODO: TRACKER_EVOLUTION_PREDICATE_SEEN (!)
+ * TRACKER_EVOLUTION_PREDICATE_JUNK (!)
+ * TRACKER_EVOLUTION_PREDICATE_ANSWERED
+ * TRACKER_EVOLUTION_PREDICATE_FLAGGED
+ * TRACKER_EVOLUTION_PREDICATE_FORWARDED
+ * TRACKER_EVOLUTION_PREDICATE_DELETED (!)
+ * TRACKER_EVOLUTION_PREDICATE_SIZE (!) :
+ *
+ * I don't have predicates in Tracker's ontology for these. In
+ * JÃrg's vstore branch we are working with Nepomuk as ontology-
+ * set. Perhaps when we merge this to that branch that we can
+ * improve this situation. */
+
+
+#if 0
+
+ /* Disabling this as I can't find any version of GMime-2.0 that
+ * wont crash on any of my test E-mails. Going to ask Garnacho
+ * to migrate to GMime-2.4 with his old Evolution support. */
+
+ if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_FILE) == 0) {
+ GMimeStream *stream;
+ GMimeParser *parser;
+ GMimeMessage *message;
+ 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';
+ }
+
+ fd = tracker_file_open (path, FALSE);
+
+ g_free (path);
+
+ if (fd == -1)
+ goto cont;
+
+ stream = g_mime_stream_fs_new_with_bounds (fd, offset, -1);
+
+ if (!stream) {
+ close (fd);
+ goto cont;
+ }
+
+ parser = g_mime_parser_new_with_stream (stream);
+
+ if (!parser) {
+ g_object_unref (stream);
+ goto cont;
+ }
+
+ g_mime_parser_set_scan_from (parser, FALSE);
+
+ message = g_mime_parser_construct_message (parser);
+
+ if (!message) {
+ g_object_unref (parser);
+ g_object_unref (stream);
+ goto cont;
+ }
+
+ g_mime_message_foreach_part (message,
+ extract_mime_parts,
+ subject);
+
+ 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);
+ }
+#endif
+
+ if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_TAG) == 0) {
+ gchar *key, *value;
+
+ if (!values[i] || strlen (values[i]) < 1)
+ goto cont;
+
+ key = g_strdup (values[i]);
+
+ value = strchr (key, '=');
+
+ if (value) {
+ *value = '\0';
+ value++;
+ }
+
+ /* TODO: what about value? The format of Evolution is
+ * key=value, so we can store a value too here. Is this
+ * something Nepomuk can someday save us with? */
+
+ tracker_module_metadata_add_string (metadata,
+ METADATA_EMAIL_TAG,
+ key);
+
+ g_free (key);
+ }
+
+ 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) {
+ tracker_module_metadata_add_string (metadata,
+ METADATA_EMAIL_SENT_TO,
+ values[i]);
+ }
+
+ if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_CC) == 0) {
+ tracker_module_metadata_add_string (metadata,
+ METADATA_EMAIL_CC,
+ values[i]);
+ }
+
+ cont:
+
+ i++;
+ }
+
+ data = tracker_module_metadata_get_hash_table (metadata);
+
+ 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)
+{
+ tracker_data_update_delete_service_by_path (subject, "EvolutionEmails");
+}
+
+static void
+perform_cleanup (TrackerEvolutionIndexer *object)
+{
+ tracker_data_update_delete_service_all ("EvolutionEmails");
+}
+
+void
+tracker_evolution_indexer_set (TrackerEvolutionIndexer *object,
+ const gchar *subject,
+ const GStrv predicates,
+ const GStrv values,
+ DBusGMethodInvocation *context,
+ GError *derror)
+{
+ dbus_async_return_if_fail (subject != NULL, context);
+
+ if (predicates && values) {
+
+ dbus_async_return_if_fail (g_strv_length (predicates) ==
+ g_strv_length (values), 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,
+ GError *derror)
+{
+ guint len;
+ guint i = 0;
+
+ dbus_async_return_if_fail (subjects != NULL, context);
+ dbus_async_return_if_fail (predicates != NULL, context);
+ dbus_async_return_if_fail (values != NULL, context);
+
+ len = g_strv_length (subjects);
+
+ 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,
+ GError *derror)
+{
+ guint i = 0;
+
+ dbus_async_return_if_fail (subjects != NULL, context);
+
+ 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,
+ GError *derror)
+{
+ 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,
+ GError *derror)
+{
+ perform_cleanup (object);
+
+ dbus_g_method_return (context);
+}
+
+void
+tracker_evolution_storer_init (TrackerConfig *config,
+ TrackerIndexer *indexer)
+{
+ 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,
+ "indexer", 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_storer_shutdown (void)
+{
+ if (idx_indexer)
+ g_object_unref (idx_indexer);
+}
Added: trunk/src/plugins/evolution/tracker-evolution-indexer.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-indexer.h Thu Jan 15 12:58:15 2009
@@ -0,0 +1,100 @@
+/* -*- 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-indexer/tracker-indexer.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,
+ GError *derror);
+void tracker_evolution_indexer_set_many (TrackerEvolutionIndexer *object,
+ const GStrv subjects,
+ const GPtrArray *predicates,
+ const GPtrArray *values,
+ DBusGMethodInvocation *context,
+ GError *derror);
+void tracker_evolution_indexer_unset_many (TrackerEvolutionIndexer *object,
+ const GStrv subjects,
+ DBusGMethodInvocation *context,
+ GError *derror);
+void tracker_evolution_indexer_unset (TrackerEvolutionIndexer *object,
+ const gchar *subject,
+ DBusGMethodInvocation *context,
+ GError *derror);
+void tracker_evolution_indexer_cleanup (TrackerEvolutionIndexer *object,
+ DBusGMethodInvocation *context,
+ GError *derror);
+
+void tracker_evolution_storer_init (TrackerConfig *config,
+ TrackerIndexer *indexer);
+void tracker_evolution_storer_shutdown (void);
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_EVOLUTION_H__ */
Added: trunk/src/plugins/evolution/tracker-evolution-plugin.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-plugin.c Thu Jan 15 12:58:15 2009
@@ -0,0 +1,1738 @@
+/* -*- 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 <camel/camel-session.h>
+
+#include <mail/mail-config.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 "tracker-evolution-plugin.h"
+#include "tracker-evolution-plugin-glue.h"
+
+/* 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 MAX_BEFORE_SEND 2000
+
+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))
+
+/* Some helper-defines */
+#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func)
+#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);
+
+/* About the locks being used: Camel's API must be used in a multi-threaded
+ * fashion. Therefore it's necessary to guard against concurrent access of
+ * memory. Especially given that both the mainloop and the Camel-threads will
+ * be accessing the memory (mainloop for DBus calls, and Camel-threads mostly
+ * during registration of accounts and folders) */
+
+typedef struct {
+ guint64 last_checkout;
+ DBusGProxy *registrar;
+ guint signal;
+} 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;
+
+enum {
+ PROP_0,
+ PROP_CONNECTION
+};
+
+static DBusGProxy *dbus_proxy = NULL;
+static TrackerEvolutionPlugin *manager = NULL;
+static GStaticRecMutex glock = G_STATIC_REC_MUTEX_INIT;
+
+/* Prototype declarations */
+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);
+
+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
+folder_registry_free (FolderRegistry *registry)
+{
+ camel_object_remove_event (registry->folder, registry->hook_info->hook_id);
+ camel_object_unref (registry->folder);
+ 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);
+ 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) {
+ if (g_file_test (filen, G_FILE_TEST_EXISTS)) {
+ g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FILE));
+ g_ptr_array_add (values_temp, filen);
+ } else
+ g_free (filen);
+ }
+ }
+}
+
+/* When new messages arrive to- or got deleted from the summary, called in
+ * mainloop or by a thread (unknown, depends on Camel and Evolution code that
+ * executes the reason why this signal gets emitted) */
+
+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 ();
+
+ /* the uid_added member contains the added-to-the-summary items */
+
+ 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]);
+ }
+
+ /* the uid_changed member contains the changed-in-the-summary items */
+
+ 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;
+
+ 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);
+
+ /* Camel returns a time_t, I think a uint64 is the best fit here */
+ sent = g_strdup_printf ("%"PRIu64, (unsigned long long) camel_message_info_date_sent (linfo));
+
+ /* Camel returns a uint32, so %u */
+ size = g_strdup_printf ("%u", 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_printf ("%s=True", 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);
+
+ /* This is not a path but a URI, don't use the
+ * OS's directory separator here */
+
+ 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++) {
+
+ /* This is not a path but a URI, don't use the OS's
+ * directory separator here */
+
+ 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, called in the mainloop */
+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, " /* 0 - 3 */
+ "replied, important, junk, attachment, " /* 4 - 7 */
+ "size, dsent, dreceived, subject, " /* 8 - 11 */
+ "mail_from, mail_to, mail_cc, mlist, " /* 12 - 15 */
+ "labels, usertags " /* 16 - 17 */
+ "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);
+
+ g_static_rec_mutex_lock (priv->mutex);
+
+ 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);
+
+ g_static_rec_mutex_unlock (priv->mutex);
+
+ /* 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_printf ("%s=True", 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);
+
+ /* Extract User tags */
+ 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;
+
+ /* This is not a path but a URI, don't use the
+ * OS's directory separator here */
+
+ 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) {
+
+ /* Yield per MAX_BEFORE_SEND. This function is
+ * called as a result of a DBus call, so it runs
+ * in the mainloop. Therefore, yield he mainloop
+ * sometimes, indeed */
+
+ g_main_context_iteration (NULL, TRUE);
+
+ 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, called in
+ * the mainloop */
+
+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);
+
+ /* This is not a path but a URI, don't use the OS's
+ * directory separator here */
+
+ 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. This function is
+ * called as a result of a DBus call, so it runs
+ * in the mainloop. Therefore, yield he mainloop
+ * sometimes, indeed */
+
+ 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);
+}
+
+/* Get the oldest date in all of the deleted-tables, called in the mainloop */
+
+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;
+ 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;
+
+ 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);
+
+ g_static_rec_mutex_lock (priv->mutex);
+
+ 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);
+
+ g_static_rec_mutex_unlock (priv->mutex);
+
+ 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;
+
+ folder = camel_store_get_folder (store, titer->full_name, 0, NULL);
+
+ if (folder) {
+ g_static_rec_mutex_lock (priv->mutex);
+
+ g_hash_table_iter_init (&iter, priv->registered_folders);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ FolderRegistry *registry = value;
+
+ if (folder == registry->folder) {
+ g_hash_table_remove (priv->cached_folders, titer->full_name);
+ g_hash_table_iter_remove (&iter);
+ break;
+ }
+ }
+
+ camel_object_unref (folder);
+
+ g_static_rec_mutex_unlock (priv->mutex);
+ }
+
+ 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)
+{
+ if (info->signal != 0) /* known (see below) */
+ g_signal_handler_disconnect (info->registrar, info->signal);
+ 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->signal = 0; /* known */
+ 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 in on_got above */
+
+ 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,
+ guint dsignal)
+{
+ TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+ guint64 too_old = get_last_deleted_time (self);
+ ClientRegistry *info = g_slice_new (ClientRegistry);
+
+ info->signal = dsignal;
+ 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;
+ gchar *uri = reg_info->uri;
+ guint hook_id;
+
+ g_static_rec_mutex_lock (priv->mutex);
+
+ if (!priv->registered_stores)
+ priv->registered_stores = g_hash_table_new_full (g_int_hash, g_int_equal,
+ (GDestroyNotify) NULL,
+ (GDestroyNotify) store_registry_free);
+
+ /* Hook up catching folder changes in the store */
+ 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_static_rec_mutex_unlock (priv->mutex);
+
+ /* Register each folder to hook folder_changed everywhere */
+ register_walk_folders_in_folder (self, iter, store, uri);
+
+ 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);
+
+ /* Get the account's folder-info and register it asynchronously */
+ mail_get_folderinfo (store, NULL, on_got_folderinfo_register, reg_info);
+
+ camel_object_unref (store);
+}
+
+static gboolean
+on_got_folderinfo_unregister (CamelStore *store,
+ CamelFolderInfo *titer,
+ void *data)
+{
+ RegisterInfo *reg_info = data;
+ TrackerEvolutionPlugin *self = reg_info->self;
+ TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
+ gchar *uri = reg_info->uri;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ unregister_walk_folders_in_folder (self, titer, store, uri);
+
+ g_static_rec_mutex_lock (priv->mutex);
+
+ 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);
+ }
+ }
+
+ g_static_rec_mutex_unlock (priv->mutex);
+
+ g_object_unref (reg_info->self);
+ g_free (reg_info->uri);
+ g_free (reg_info);
+
+ return TRUE;
+}
+
+static void
+unregister_account (TrackerEvolutionPlugin *self,
+ EAccount *account)
+{
+ CamelProvider *provider;
+ CamelStore *store;
+ CamelException ex;
+ char *uri;
+ RegisterInfo *reg_info;
+
+
+ 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 = NULL;
+
+ /* Get the account's folder-info and unregister asynchronously */
+ mail_get_folderinfo (store, NULL, on_got_folderinfo_unregister, reg_info);
+
+ 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_warning ("Could not setup DBus, ReleaseName of %s: %s\n",
+ TRACKER_EVOLUTION_MANAGER_SERVICE, error->message);
+
+ 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 ();
+
+ if ((dbus_proxy && !manager) || (!dbus_proxy && manager))
+ return;
+
+ 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)) {
+
+ g_warning ("Could not setup DBus, failed at RequestName for %s\n",
+ TRACKER_EVOLUTION_MANAGER_SERVICE);
+
+ goto error_handler;
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+
+ g_warning ("Could not setup DBus, can't become primary owner of %s\n",
+ TRACKER_EVOLUTION_MANAGER_SERVICE);
+
+ 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_warning ("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,
+ GError *derror)
+{
+ TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
+ gchar *sender;
+ DBusGProxy *registrar;
+ guint dsignal;
+
+ 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);
+
+ dsignal = 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, dsignal);
+
+ 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);
+
+ g_static_rec_mutex_lock (priv->mutex);
+
+ g_list_foreach (priv->registered_clients,
+ (GFunc) client_registry_info_free,
+ NULL);
+
+ 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);
+
+ if (priv->connection)
+ dbus_g_connection_unref (priv->connection);
+
+ 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);
+
+ if (priv->connection)
+ dbus_g_connection_unref (priv->connection);
+
+ priv->connection = dbus_g_connection_ref (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);
+
+ g_static_rec_mutex_lock (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;
+
+ g_static_rec_mutex_unlock (priv->mutex);
+
+ 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);
+}
Added: trunk/src/plugins/evolution/tracker-evolution-plugin.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-plugin.h Thu Jan 15 12:58:15 2009
@@ -0,0 +1,60 @@
+/* -*- 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__
+
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib-lowlevel.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,
+ GError *derror);
+
+G_END_DECLS
+
+#endif /* __TRACKER_EVOLUTION_PLUGIN_H__ */
Added: trunk/src/plugins/evolution/tracker-evolution-plugin.xml
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-plugin.xml Thu Jan 15 12:58:15 2009
@@ -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>
+
Added: trunk/src/plugins/evolution/tracker-evolution-registrar.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-registrar.c Thu Jan 15 12:58:15 2009
@@ -0,0 +1,245 @@
+/* -*- 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>
+#define __TRACKER_EVOLUTION_REGISTRAR_C__
+#include "tracker-evolution-registrar.h"
+#include "tracker-evolution-registrar-glue.h"
+
+const DBusGMethodInfo *registrar_methods = dbus_glib_tracker_evolution_registrar_methods;
+
+#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 requests). */
+
+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)
+{
+}
+
+void
+tracker_evolution_registrar_set (TrackerEvolutionRegistrar *object,
+ const gchar *subject,
+ const GStrv predicates,
+ const GStrv values,
+ DBusGMethodInvocation *context,
+ GError *derror)
+{
+ TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+ dbus_async_return_if_fail (subject != NULL, context);
+
+ if (predicates && values) {
+
+ dbus_async_return_if_fail (g_strv_length (predicates) ==
+ g_strv_length (values), 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,
+ GError *derror)
+{
+ TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+ guint len;
+
+ dbus_async_return_if_fail (subjects != NULL, context);
+ dbus_async_return_if_fail (predicates != NULL, context);
+ dbus_async_return_if_fail (values != NULL, context);
+
+ len = g_strv_length (subjects);
+
+ dbus_async_return_if_fail (len == predicates->len, context);
+ dbus_async_return_if_fail (len == values->len, context);
+
+ 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,
+ GError *derror)
+{
+ TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
+
+ dbus_async_return_if_fail (subjects != NULL, context);
+
+ 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,
+ GError *derror)
+{
+ 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,
+ GError *derror)
+{
+ 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);
+}
Added: trunk/src/plugins/evolution/tracker-evolution-registrar.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-registrar.h Thu Jan 15 12:58:15 2009
@@ -0,0 +1,88 @@
+/* -*- 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 <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
+
+#ifndef __TRACKER_EVOLUTION_REGISTRAR_C__
+extern const DBusGMethodInfo *registrar_methods;
+#endif
+
+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,
+ GError *derror);
+void tracker_evolution_registrar_set_many (TrackerEvolutionRegistrar *object,
+ const GStrv subjects,
+ const GPtrArray *predicates,
+ const GPtrArray *values,
+ DBusGMethodInvocation *context,
+ GError *derror);
+void tracker_evolution_registrar_unset_many (TrackerEvolutionRegistrar *object,
+ const GStrv subjects,
+ DBusGMethodInvocation *context,
+ GError *derror);
+void tracker_evolution_registrar_unset (TrackerEvolutionRegistrar *object,
+ const gchar *subject,
+ DBusGMethodInvocation *context,
+ GError *derror);
+void tracker_evolution_registrar_cleanup (TrackerEvolutionRegistrar *object,
+ DBusGMethodInvocation *context,
+ GError *derror);
+
+
+G_END_DECLS
+
+#endif /* __LIBTRACKER_EVOLUTION_REGISTRAR_H__ */
Added: trunk/src/plugins/evolution/tracker-evolution-registrar.xml
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution-registrar.xml Thu Jan 15 12:58:15 2009
@@ -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>
Added: trunk/src/plugins/evolution/tracker-evolution.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution.c Thu Jan 15 12:58:15 2009
@@ -0,0 +1,358 @@
+/* -*- 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),
+ ®istrar_methods);
+ 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 (tracker_is_empty_string (new_owner) && !tracker_is_empty_string (old_owner))
+ deactivate_registrar ();
+ if (tracker_is_empty_string (old_owner) && !tracker_is_empty_string (new_owner))
+ 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)
+{
+ /* If none of the disabled modules include the Evolution module,
+ * we assume we are enabled in the configuration. */
+
+ return (g_slist_find_custom (tracker_config_get_disabled_modules (config),
+ "Evolution",
+ (GCompareFunc) g_strcmp0) != NULL);
+}
+
+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 ("Evolution support service %s",
+ private->is_enabled ? "enabled" : "disabled");
+}
+
+static void
+free_private (EvolutionSupportPrivate *private)
+{
+ dbus_g_connection_unref (private->connection);
+ g_object_unref (private->config);
+ g_free (private);
+}
+
+void
+tracker_evolution_init (TrackerConfig *config)
+{
+ DBusGConnection *connection;
+ GError *error = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+
+ if (!error) {
+ EvolutionSupportPrivate *private;
+
+ private = g_new0 (EvolutionSupportPrivate, 1);
+
+ private->deactivating = FALSE;
+ private->config = g_object_ref (config);
+ private->is_enabled = is_enabled (config);
+ private->connection = dbus_g_connection_ref (connection);
+
+ g_static_private_set (&private_key,
+ private,
+ (GDestroyNotify) free_private);
+
+ /* 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 ();
+ } else {
+ 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_static_private_set (&private_key, NULL, NULL);
+}
Added: trunk/src/plugins/evolution/tracker-evolution.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/evolution/tracker-evolution.h Thu Jan 15 12:58:15 2009
@@ -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__ */
Modified: trunk/src/tracker-indexer/Makefile.am
==============================================================================
--- trunk/src/tracker-indexer/Makefile.am (original)
+++ trunk/src/tracker-indexer/Makefile.am Thu Jan 15 12:58:15 2009
@@ -17,6 +17,7 @@
$(RAPTOR_CFLAGS) \
$(GMODULE_CFLAGS)
+
libtracker_moduledir = $(libdir)/tracker
libtracker_moduleincludedir=$(includedir)/tracker-1.0/libtracker-module/
libtracker_module_LTLIBRARIES = libtracker-module.la
@@ -55,6 +56,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/plugins/evolution/libtracker-evolution-indexer.la \
$(trackerd_win_libs) \
$(DBUS_LIBS) \
$(GMODULE_LIBS) \
Modified: trunk/src/tracker-indexer/modules/evolution.c
==============================================================================
--- trunk/src/tracker-indexer/modules/evolution.c (original)
+++ trunk/src/tracker-indexer/modules/evolution.c Thu Jan 15 12:58:15 2009
@@ -26,7 +26,10 @@
#include "evolution-pop.h"
#include "evolution-imap.h"
+
+#ifndef HAVE_EVOLUTION_PLUGIN
#include "evolution-imap-db.h"
+#endif
typedef enum MailStorageType MailStorageType;
@@ -34,7 +37,9 @@
MAIL_STORAGE_NONE,
MAIL_STORAGE_LOCAL,
MAIL_STORAGE_IMAP,
+#ifndef HAVE_EVOLUTION_PLUGIN
MAIL_STORAGE_IMAP_DB
+#endif
};
static gchar *local_dir = NULL;
@@ -76,9 +81,12 @@
} else if (g_str_has_prefix (path, imap_dir)) {
if (strcmp (basenam, "summary") == 0) {
type = MAIL_STORAGE_IMAP;
- } else if (strcmp (basenam, "folders.db") == 0) {
+ }
+#ifndef HAVE_EVOLUTION_PLUGIN
+ else if (strcmp (basenam, "folders.db") == 0) {
type = MAIL_STORAGE_IMAP_DB;
}
+#endif
}
/* Exclude non wanted folders */
@@ -110,9 +118,12 @@
return tracker_evolution_pop_file_new (file);
} else if (type == MAIL_STORAGE_IMAP) {
return tracker_evolution_imap_file_new (file);
- } else if (type == MAIL_STORAGE_IMAP_DB) {
+ }
+#ifndef HAVE_EVOLUTION_PLUGIN
+ else if (type == MAIL_STORAGE_IMAP_DB) {
return tracker_evolution_imap_db_file_new (file);
}
+#endif
return NULL;
}
Modified: trunk/src/tracker-indexer/tracker-main.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-main.c (original)
+++ trunk/src/tracker-indexer/tracker-main.c Thu Jan 15 12:58:15 2009
@@ -44,6 +44,9 @@
#include <libtracker-data/tracker-data-update.h>
#include <libtracker-data/tracker-turtle.h>
+#include <libtracker-data/tracker-data-manager.h>
+
+#include <plugins/evolution/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,15 @@
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);
+
+#ifdef HAVE_EVOLUTION_PLUGIN
+ tracker_evolution_storer_init (config, indexer);
+#endif
+
tracker_turtle_init ();
g_message ("Starting...");
@@ -383,15 +399,24 @@
tracker_turtle_shutdown ();
+
if (quit_timeout_id) {
g_source_remove (quit_timeout_id);
}
g_main_loop_unref (main_loop);
g_object_unref (indexer);
+
g_object_unref (config);
+ g_object_unref (language);
+
+ tracker_data_manager_shutdown ();
+
+#ifdef HAVE_EVOLUTION_PLUGIN
+ tracker_evolution_storer_shutdown ();
+#endif
- tracker_thumbnailer_shutdown ();
+ tracker_thumbnailer_shutdown ();
tracker_dbus_shutdown ();
tracker_db_index_manager_shutdown ();
tracker_db_manager_shutdown ();
Modified: trunk/src/trackerd/Makefile.am
==============================================================================
--- trunk/src/trackerd/Makefile.am (original)
+++ trunk/src/trackerd/Makefile.am Thu Jan 15 12:58:15 2009
@@ -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/plugins/evolution/libtracker-evolution.la \
$(inotify_libs) \
$(GMIME_LIBS) \
$(FAM_LIBS) \
Modified: trunk/src/trackerd/tracker-main.c
==============================================================================
--- trunk/src/trackerd/tracker-main.c (original)
+++ trunk/src/trackerd/tracker-main.c Thu Jan 15 12:58:15 2009
@@ -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 <plugins/evolution/tracker-evolution.h>
+
#include "tracker-crawler.h"
#include "tracker-dbus.h"
#include "tracker-indexer-client.h"
@@ -1030,11 +1033,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;
@@ -1132,6 +1135,10 @@
return EXIT_FAILURE;
}
+#ifdef HAVE_EVOLUTION_PLUGIN
+ tracker_evolution_init (config);
+#endif
+
g_message ("Waiting for DBus requests...");
/* Set our status as running, if this is FALSE, threads stop
@@ -1202,6 +1209,11 @@
shutdown_directories ();
/* Shutdown major subsystems */
+
+#ifdef HAVE_EVOLUTION_PLUGIN
+ tracker_evolution_shutdown ();
+#endif
+
tracker_cleanup_shutdown ();
tracker_xesam_manager_shutdown ();
tracker_dbus_shutdown ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]