Attachment 'implementation.diff'

Download

   1 Index: src/plugins/evolution/tracker-evolution-indexer.h
   2 ===================================================================
   3 --- src/plugins/evolution/tracker-evolution-indexer.h	(revision 0)
   4 +++ src/plugins/evolution/tracker-evolution-indexer.h	(revision 0)
   5 @@ -0,0 +1,100 @@
   6 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
   7 +/*
   8 + * Copyright (C) 2008, Nokia
   9 + *
  10 + * This library is free software; you can redistribute it and/or
  11 + * modify it under the terms of the GNU General Public
  12 + * License as published by the Free Software Foundation; either
  13 + * version 2 of the License, or (at your option) any later version.
  14 + *
  15 + * This library is distributed in the hope that it will be useful,
  16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18 + * General Public License for more details.
  19 + *
  20 + * You should have received a copy of the GNU General Public
  21 + * License along with this library; if not, write to the
  22 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  23 + * Boston, MA  02110-1301, USA.
  24 + *
  25 + * Authors:
  26 + *  Philip Van Hoof <philip@codeminded.be>
  27 + */
  28 +
  29 +#ifndef __LIBTRACKER_EVOLUTION_H__
  30 +#define __LIBTRACKER_EVOLUTION_H__
  31 +
  32 +#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
  33 +#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
  34 +#endif
  35 +
  36 +#include <glib.h>
  37 +
  38 +#include <libtracker-common/tracker-common.h>
  39 +
  40 +G_BEGIN_DECLS
  41 +
  42 +#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
  43 +#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
  44 +#endif
  45 +
  46 +#include <glib.h>
  47 +#include <dbus/dbus-glib-bindings.h>
  48 +
  49 +#include <tracker-indexer/tracker-indexer.h>
  50 +
  51 +#include "tracker-evolution-common.h"
  52 +
  53 +G_BEGIN_DECLS
  54 +
  55 +#define TRACKER_TYPE_EVOLUTION_INDEXER          (tracker_evolution_indexer_get_type())
  56 +#define TRACKER_EVOLUTION_INDEXER(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexer))
  57 +#define TRACKER_EVOLUTION_INDEXER_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexerClass))
  58 +#define TRACKER_EVOLUTION_INDEXER_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexerClass))
  59 +
  60 +G_BEGIN_DECLS
  61 +
  62 +typedef struct TrackerEvolutionIndexer TrackerEvolutionIndexer;
  63 +typedef struct TrackerEvolutionIndexerClass TrackerEvolutionIndexerClass;
  64 +
  65 +struct TrackerEvolutionIndexer {
  66 +	GObject parent;
  67 +};
  68 +
  69 +struct TrackerEvolutionIndexerClass {
  70 +	GObjectClass parent;
  71 +};
  72 +
  73 +GType  tracker_evolution_indexer_get_type   (void);
  74 +
  75 +void  tracker_evolution_indexer_set         (TrackerEvolutionIndexer *object, 
  76 +					     const gchar *subject, 
  77 +					     const GStrv predicates,
  78 +					     const GStrv values,
  79 +					     DBusGMethodInvocation *context,
  80 +					     GError *derror);
  81 +void  tracker_evolution_indexer_set_many    (TrackerEvolutionIndexer *object, 
  82 +					     const GStrv subjects, 
  83 +					     const GPtrArray *predicates,
  84 +					     const GPtrArray *values,
  85 +					     DBusGMethodInvocation *context,
  86 +					     GError *derror);
  87 +void  tracker_evolution_indexer_unset_many  (TrackerEvolutionIndexer *object, 
  88 +					     const GStrv subjects, 
  89 +					     DBusGMethodInvocation *context,
  90 +					     GError *derror);
  91 +void  tracker_evolution_indexer_unset       (TrackerEvolutionIndexer *object, 
  92 +					     const gchar *subject, 
  93 +					     DBusGMethodInvocation *context,
  94 +					     GError *derror);
  95 +void  tracker_evolution_indexer_cleanup     (TrackerEvolutionIndexer *object, 
  96 +					     DBusGMethodInvocation *context,
  97 +					     GError *derror);
  98 +
  99 +void  tracker_evolution_storer_init        (TrackerConfig *config, 
 100 +					    TrackerIndexer *indexer);
 101 +void  tracker_evolution_storer_shutdown    (void);
 102 +
 103 +G_END_DECLS
 104 +
 105 +#endif /* __LIBTRACKER_EVOLUTION_H__ */
 106 Index: src/plugins/evolution/tracker-evolution-plugin.h
 107 ===================================================================
 108 --- src/plugins/evolution/tracker-evolution-plugin.h	(revision 0)
 109 +++ src/plugins/evolution/tracker-evolution-plugin.h	(revision 0)
 110 @@ -0,0 +1,60 @@
 111 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 112 +/*
 113 + * Copyright (C) 2008, Nokia
 114 + *
 115 + * This library is free software; you can redistribute it and/or
 116 + * modify it under the terms of the GNU General Public
 117 + * License as published by the Free Software Foundation; either
 118 + * version 2 of the License, or (at your option) any later version.
 119 + *
 120 + * This library is distributed in the hope that it will be useful,
 121 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 122 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 123 + * General Public License for more details.
 124 + *
 125 + * You should have received a copy of the GNU General Public
 126 + * License along with this library; if not, write to the
 127 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 128 + * Boston, MA  02110-1301, USA.
 129 + *
 130 + * Authors:
 131 + *  Philip Van Hoof <philip@codeminded.be>
 132 + */
 133 +
 134 +#ifndef __TRACKER_EVOLUTION_PLUGIN_H__
 135 +#define __TRACKER_EVOLUTION_PLUGIN_H__
 136 +
 137 +#include <dbus/dbus-glib-bindings.h>
 138 +#include <dbus/dbus-glib-lowlevel.h>
 139 +
 140 +#include "tracker-evolution-common.h"
 141 +
 142 +#define TRACKER_TYPE_EVOLUTION_PLUGIN          (tracker_evolution_plugin_get_type())
 143 +#define TRACKER_EVOLUTION_PLUGIN(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPlugin))
 144 +#define TRACKER_EVOLUTION_PLUGIN_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginClass))
 145 +#define TRACKER_EVOLUTION_PLUGIN_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginClass))
 146 +
 147 +G_BEGIN_DECLS
 148 +
 149 +typedef struct TrackerEvolutionPlugin TrackerEvolutionPlugin;
 150 +typedef struct TrackerEvolutionPluginClass TrackerEvolutionPluginClass;
 151 +
 152 +struct TrackerEvolutionPlugin {
 153 +	GObject parent;
 154 +};
 155 +
 156 +struct TrackerEvolutionPluginClass {
 157 +	GObjectClass parent;
 158 +};
 159 +
 160 +GType tracker_evolution_plugin_get_type (void);
 161 +
 162 +void tracker_evolution_plugin_register  (TrackerEvolutionPlugin *object, 
 163 +					 gchar *registrar_path,
 164 +					 guint last_checkout, 
 165 +					 DBusGMethodInvocation *context,
 166 +					 GError *derror);
 167 +
 168 +G_END_DECLS
 169 +
 170 +#endif /* __TRACKER_EVOLUTION_PLUGIN_H__ */
 171 Index: src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml
 172 ===================================================================
 173 --- src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml	(revision 0)
 174 +++ src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml	(revision 0)
 175 @@ -0,0 +1,15 @@
 176 +<?xml version="1.0"?>
 177 +<e-plugin-list>
 178 +	<e-plugin id="org.freedesktop.Tracker.evolution_plugin" 
 179 +		type="shlib"
 180 +		location="+PLUGIN_INSTALL_DIR+/liborg-freedesktop-Tracker-evolution-plugin.so"
 181 +		domain="+GETTEXT_PACKAGE+"
 182 +		localedir="+LOCALEDIR+"
 183 +		_name="TrackerEvolutionPlugin"
 184 +		load-on-startup="after-ui">
 185 +
 186 +		<_description>Support for Tracker.</_description>
 187 +
 188 +		<author name="Philip Van Hoof" email="philip@codeminded.be"/>
 189 +	</e-plugin>
 190 +</e-plugin-list>
 191 Index: src/plugins/evolution/tracker-evolution.h
 192 ===================================================================
 193 --- src/plugins/evolution/tracker-evolution.h	(revision 0)
 194 +++ src/plugins/evolution/tracker-evolution.h	(revision 0)
 195 @@ -0,0 +1,42 @@
 196 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 197 +/*
 198 + * Copyright (C) 2008, Nokia
 199 + *
 200 + * This library is free software; you can redistribute it and/or
 201 + * modify it under the terms of the GNU General Public
 202 + * License as published by the Free Software Foundation; either
 203 + * version 2 of the License, or (at your option) any later version.
 204 + *
 205 + * This library is distributed in the hope that it will be useful,
 206 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 207 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 208 + * General Public License for more details.
 209 + *
 210 + * You should have received a copy of the GNU General Public
 211 + * License along with this library; if not, write to the
 212 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 213 + * Boston, MA  02110-1301, USA.
 214 + *
 215 + * Authors:
 216 + *  Philip Van Hoof <philip@codeminded.be>
 217 + */
 218 +
 219 +#ifndef __LIBTRACKER_EVOLUTION_H__
 220 +#define __LIBTRACKER_EVOLUTION_H__
 221 +
 222 +#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
 223 +#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
 224 +#endif
 225 +
 226 +#include <glib.h>
 227 +
 228 +#include <libtracker-common/tracker-common.h>
 229 +
 230 +G_BEGIN_DECLS
 231 +
 232 +void  tracker_evolution_init     (TrackerConfig *config);
 233 +void  tracker_evolution_shutdown (void);
 234 +
 235 +G_END_DECLS
 236 +
 237 +#endif /* __LIBTRACKER_EVOLUTION_H__ */
 238 Index: src/plugins/evolution/tracker-evolution-registrar.h
 239 ===================================================================
 240 --- src/plugins/evolution/tracker-evolution-registrar.h	(revision 0)
 241 +++ src/plugins/evolution/tracker-evolution-registrar.h	(revision 0)
 242 @@ -0,0 +1,88 @@
 243 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 244 +/*
 245 + * Copyright (C) 2008, Nokia
 246 + *
 247 + * This library is free software; you can redistribute it and/or
 248 + * modify it under the terms of the GNU General Public
 249 + * License as published by the Free Software Foundation; either
 250 + * version 2 of the License, or (at your option) any later version.
 251 + *
 252 + * This library is distributed in the hope that it will be useful,
 253 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 254 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 255 + * General Public License for more details.
 256 + *
 257 + * You should have received a copy of the GNU General Public
 258 + * License along with this library; if not, write to the
 259 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 260 + * Boston, MA  02110-1301, USA.
 261 + *
 262 + * Authors:
 263 + *  Philip Van Hoof <philip@codeminded.be>
 264 + */
 265 +
 266 +#ifndef __LIBTRACKER_EVOLUTION_REGISTRAR_H__
 267 +#define __LIBTRACKER_EVOLUTION_REGISTRAR_H__
 268 +
 269 +#if !defined (TRACKER_ENABLE_INTERNALS) && !defined (TRACKER_COMPILATION)
 270 +#error "TRACKER_ENABLE_INTERNALS not defined, this must be defined to use tracker's internal functions"
 271 +#endif
 272 +
 273 +#include <dbus/dbus-glib-bindings.h>
 274 +
 275 +#include "tracker-evolution-common.h"
 276 +
 277 +G_BEGIN_DECLS
 278 +
 279 +#define TRACKER_TYPE_EVOLUTION_REGISTRAR          (tracker_evolution_registrar_get_type())
 280 +#define TRACKER_EVOLUTION_REGISTRAR(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrar))
 281 +#define TRACKER_EVOLUTION_REGISTRAR_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarClass))
 282 +#define TRACKER_EVOLUTION_REGISTRAR_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarClass))
 283 +
 284 +G_BEGIN_DECLS
 285 +
 286 +#ifndef __TRACKER_EVOLUTION_REGISTRAR_C__
 287 +extern const DBusGMethodInfo *registrar_methods;
 288 +#endif
 289 +
 290 +typedef struct TrackerEvolutionRegistrar TrackerEvolutionRegistrar;
 291 +typedef struct TrackerEvolutionRegistrarClass TrackerEvolutionRegistrarClass;
 292 +
 293 +struct TrackerEvolutionRegistrar {
 294 +	GObject parent;
 295 +};
 296 +
 297 +struct TrackerEvolutionRegistrarClass {
 298 +	GObjectClass parent;
 299 +};
 300 +
 301 +GType  tracker_evolution_registrar_get_type   (void);
 302 +
 303 +void  tracker_evolution_registrar_set         (TrackerEvolutionRegistrar *object, 
 304 +					       const gchar *subject, 
 305 +					       const GStrv predicates,
 306 +					       const GStrv values,
 307 +					       DBusGMethodInvocation *context,
 308 +					       GError *derror);
 309 +void  tracker_evolution_registrar_set_many    (TrackerEvolutionRegistrar *object, 
 310 +					       const GStrv subjects, 
 311 +					       const GPtrArray *predicates,
 312 +					       const GPtrArray *values,
 313 +					       DBusGMethodInvocation *context,
 314 +					       GError *derror);
 315 +void  tracker_evolution_registrar_unset_many  (TrackerEvolutionRegistrar *object, 
 316 +					       const GStrv subjects, 
 317 +					       DBusGMethodInvocation *context,
 318 +					       GError *derror);
 319 +void  tracker_evolution_registrar_unset       (TrackerEvolutionRegistrar *object, 
 320 +					       const gchar *subject, 
 321 +					       DBusGMethodInvocation *context,
 322 +					       GError *derror);
 323 +void  tracker_evolution_registrar_cleanup     (TrackerEvolutionRegistrar *object, 
 324 +					       DBusGMethodInvocation *context,
 325 +					       GError *derror);
 326 +
 327 +
 328 +G_END_DECLS
 329 +
 330 +#endif /* __LIBTRACKER_EVOLUTION_REGISTRAR_H__ */
 331 Index: src/plugins/evolution/tracker-evolution-plugin.xml
 332 ===================================================================
 333 --- src/plugins/evolution/tracker-evolution-plugin.xml	(revision 0)
 334 +++ src/plugins/evolution/tracker-evolution-plugin.xml	(revision 0)
 335 @@ -0,0 +1,11 @@
 336 +<?xml version="1.0" encoding="UTF-8"?>
 337 +<node name="/">
 338 +  <interface name="org.gnome.evolution.metadata.Manager">  
 339 +    <method name="Register">
 340 +      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
 341 +      <arg type="o" name="registrar_path" direction="in" />
 342 +      <arg type="u" name="last_checkout" direction="in" />
 343 +    </method>
 344 +  </interface>
 345 +</node>
 346 +
 347 Index: src/plugins/evolution/tracker-evolution-common.h
 348 ===================================================================
 349 --- src/plugins/evolution/tracker-evolution-common.h	(revision 0)
 350 +++ src/plugins/evolution/tracker-evolution-common.h	(revision 0)
 351 @@ -0,0 +1,76 @@
 352 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 353 +/*
 354 + * Copyright (C) 2008, Nokia
 355 + *
 356 + * This library is free software; you can redistribute it and/or
 357 + * modify it under the terms of the GNU General Public
 358 + * License as published by the Free Software Foundation; either
 359 + * version 2 of the License, or (at your option) any later version.
 360 + *
 361 + * This library is distributed in the hope that it will be useful,
 362 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 363 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 364 + * General Public License for more details.
 365 + *
 366 + * You should have received a copy of the GNU General Public
 367 + * License along with this library; if not, write to the
 368 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 369 + * Boston, MA  02110-1301, USA.
 370 + *
 371 + * Authors:
 372 + *  Philip Van Hoof <philip@codeminded.be>
 373 + */
 374 +
 375 +#ifndef __TRACKER_EVOLUTION_COMMON_H__
 376 +#define __TRACKER_EVOLUTION_COMMON_H__
 377 +
 378 +#define TRACKER_EVOLUTION_INDEXER_PATH		"/org/freedesktop/Tracker/Indexer/Evolution/Registrar"
 379 +
 380 +#define TRACKER_EVOLUTION_REGISTRAR_SERVICE	"org.freedesktop.Tracker"
 381 +#define TRACKER_EVOLUTION_REGISTRAR_PATH	"/org/freedesktop/Tracker/Evolution/Registrar"
 382 +#define TRACKER_EVOLUTION_REGISTRAR_INTERFACE	"org.gnome.evolution.metadata.Registrar"
 383 +
 384 +#define TRACKER_EVOLUTION_MANAGER_SERVICE	"org.gnome.evolution"
 385 +#define TRACKER_EVOLUTION_MANAGER_PATH		"/org/gnome/evolution/metadata/Manager"
 386 +#define TRACKER_EVOLUTION_MANAGER_INTERFACE	"org.gnome.evolution.metadata.Manager"
 387 +
 388 +#define DBUS_ERROR_DOMAIN			"TrackerEvolution"
 389 +#define DBUS_ERROR				g_quark_from_static_string (DBUS_ERROR_DOMAIN)
 390 +
 391 +#define TRACKER_EVOLUTION_PREDICATE_SUBJECT	"Evolution:MessageSubject"
 392 +#define TRACKER_EVOLUTION_PREDICATE_SENT	"Evolution:MessageSent"
 393 +#define TRACKER_EVOLUTION_PREDICATE_FROM	"Evolution:MessageFrom"
 394 +#define TRACKER_EVOLUTION_PREDICATE_TO		"Evolution:MessageTo"
 395 +#define TRACKER_EVOLUTION_PREDICATE_FILE	"Evolution:MessageFile"
 396 +#define TRACKER_EVOLUTION_PREDICATE_CC		"Evolution:MessageCc"
 397 +#define TRACKER_EVOLUTION_PREDICATE_UID		"Evolution:MessageUid"
 398 +#define TRACKER_EVOLUTION_PREDICATE_SEEN	"Evolution:MessageSeen"
 399 +#define TRACKER_EVOLUTION_PREDICATE_JUNK	"Evolution:MessageJunk"
 400 +#define TRACKER_EVOLUTION_PREDICATE_ANSWERED	"Evolution:MessageAnswered"
 401 +#define TRACKER_EVOLUTION_PREDICATE_FLAGGED	"Evolution:MessageFlagged"
 402 +#define TRACKER_EVOLUTION_PREDICATE_TAG		"Evolution:MessageTag"
 403 +#define TRACKER_EVOLUTION_PREDICATE_FORWARDED	"Evolution:MessageForwarded"
 404 +#define TRACKER_EVOLUTION_PREDICATE_DELETED	"Evolution:MessageDeleted"
 405 +#define TRACKER_EVOLUTION_PREDICATE_SIZE	"Evolution:MessageSize"
 406 +
 407 +#define TRACKER_TYPE_G_STRV_ARRAY		(dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRV))
 408 +
 409 +#define dbus_async_return_if_fail(expr,context)				\
 410 +	G_STMT_START {							\
 411 +		if G_LIKELY(expr) { } else {				\
 412 +			GError *error = NULL;				\
 413 +									\
 414 +			g_set_error (&error,				\
 415 +				     DBUS_ERROR,			\
 416 +				     0,					\
 417 +				     "Assertion `%s' failed",		\
 418 +				     #expr);				\
 419 +									\
 420 +			dbus_g_method_return_error (context, error);	\
 421 +			g_error_free (error);				\
 422 +									\
 423 +			return;						\
 424 +		};							\
 425 +	} G_STMT_END
 426 +
 427 +#endif /* __TRACKER_EVOLUTION_COMMON_H__ */
 428 Index: src/plugins/evolution/Makefile.am
 429 ===================================================================
 430 --- src/plugins/evolution/Makefile.am	(revision 0)
 431 +++ src/plugins/evolution/Makefile.am	(revision 0)
 432 @@ -0,0 +1,89 @@
 433 +INCLUDES =						\
 434 +	-I$(top_srcdir)/src				\
 435 +	-DGETTEXT_PACKAGE="\"$(GETTEXT_PACKAGE)\""	\
 436 +	-DLOCALEDIR="\"$(LOCALEDIR)\""			\
 437 +	-DTRACKER_COMPILATION				\
 438 +	$(DBUS_CFLAGS)					\
 439 +	$(GMIME_CFLAGS)					\
 440 +	$(EVOPLUG_CFLAGS)
 441 +
 442 +%.eplug.in: %.eplug.xml
 443 +	LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@
 444 +
 445 +%.eplug: %.eplug.in
 446 +	sed -e "s%+PLUGIN_INSTALL_DIR+%$(EVOPLUG_INSTALL_DIR)%" \
 447 +	-e "s%+GETTEXT_PACKAGE+%$(GETTEXT_PACKAGE)%" \
 448 +	-e "s%+LOCALEDIR+%$(LOCALEDIR)%" \
 449 +	$< > $@
 450 +
 451 +eplugindir = $(EVOLUTION_PLUGIN_INSTALL_DIR)
 452 +
 453 +eplugin_DATA = org-freedesktop-Tracker-evolution-plugin.eplug
 454 +
 455 +eplugin_LTLIBRARIES = liborg-freedesktop-Tracker-evolution-plugin.la
 456 +
 457 +noinst_LTLIBRARIES = libtracker-evolution.la libtracker-evolution-indexer.la
 458 +
 459 +libtracker_evolution_indexer_la_SOURCES =				\
 460 +	tracker-evolution-indexer.c					\
 461 +	tracker-evolution-indexer.h					\
 462 +	tracker-evolution-registrar-glue.h				\
 463 +	tracker-evolution-common.h
 464 +
 465 +libtracker_evolution_la_SOURCES =	 				\
 466 +	tracker-evolution.c						\
 467 +	tracker-evolution.h						\
 468 +	tracker-evolution-registrar.c					\
 469 +	tracker-evolution-registrar.h					\
 470 +	tracker-evolution-common.h					\
 471 +	tracker-evolution-registrar-glue.h
 472 +
 473 +libtracker_evolution_la_LIBADD = 					\
 474 +	$(top_builddir)/src/libtracker-data/libtracker-data.la          \
 475 +	$(top_builddir)/src/libtracker-db/libtracker-db.la              \
 476 +	$(top_builddir)/src/libtracker-common/libtracker-common.la      \
 477 +	$(DBUS_LIBS)                                                    \
 478 +	$(GTHREAD_LIBS)                                                 \
 479 +	$(GIO_LIBS)                                                     \
 480 +	$(GLIB2_LIBS)                                                   \
 481 +	$(RAPTOR_LIBS)
 482 +
 483 +libtracker_evolution_indexer_la_LIBADD = 				\
 484 +	$(top_builddir)/src/libtracker-data/libtracker-data.la          \
 485 +	$(top_builddir)/src/libtracker-db/libtracker-db.la              \
 486 +	$(top_builddir)/src/libtracker-common/libtracker-common.la      \
 487 +	$(DBUS_LIBS)                                                    \
 488 +	$(GTHREAD_LIBS)                                                 \
 489 +	$(GIO_LIBS)                                                     \
 490 +	$(GLIB2_LIBS)                                                   \
 491 +	$(RAPTOR_LIBS)							\
 492 +	$(GMIME_LIBS)
 493 +
 494 +liborg_freedesktop_Tracker_evolution_plugin_la_SOURCES = 		\
 495 +	tracker-evolution-plugin.c 			 		\
 496 +	tracker-evolution-plugin.h					\
 497 +	tracker-evolution-common.h					\
 498 +	tracker-evolution-plugin-glue.h
 499 +
 500 +liborg_freedesktop_Tracker_evolution_plugin_la_LDFLAGS = -module -avoid-version
 501 +liborg_freedesktop_Tracker_evolution_plugin_la_LDLIBS = 		\
 502 +	$(EVOPLUG_LIBS)							\
 503 +	$(DBUS_LIBS)
 504 +
 505 +dbus_sources = 								\
 506 +	tracker-evolution-plugin-glue.h					\
 507 +	tracker-evolution-registrar-glue.h
 508 +
 509 +%-glue.h: %.xml
 510 +	$(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
 511 +
 512 +BUILT_SOURCES = 							\
 513 +	$(dbus_sources)							\
 514 +	$(eplugin_DATA)
 515 +
 516 +CLEANFILES = $(BUILT_SOURCES) \
 517 +	org-freedesktop-Tracker-evolution-plugin.eplug
 518 +
 519 +EXTRA_DIST = 								\
 520 +	$(BUILT_SOURCES)						\
 521 +	org-freedesktop-Tracker-evolution-plugin.eplug.xml
 522 Index: src/plugins/evolution/tracker-evolution-plugin.c
 523 ===================================================================
 524 --- src/plugins/evolution/tracker-evolution-plugin.c	(revision 0)
 525 +++ src/plugins/evolution/tracker-evolution-plugin.c	(revision 0)
 526 @@ -0,0 +1,1732 @@
 527 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 528 +/*
 529 + * Copyright (C) 2008, Nokia
 530 + *
 531 + * This library is free software; you can redistribute it and/or
 532 + * modify it under the terms of the GNU General Public
 533 + * License as published by the Free Software Foundation; either
 534 + * version 2 of the License, or (at your option) any later version.
 535 + *
 536 + * This library is distributed in the hope that it will be useful,
 537 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 538 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 539 + * General Public License for more details.
 540 + *
 541 + * You should have received a copy of the GNU General Public
 542 + * License along with this library; if not, write to the
 543 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 544 + * Boston, MA  02110-1301, USA.
 545 + *
 546 + * Authors:
 547 + *  Philip Van Hoof <philip@codeminded.be>
 548 + */
 549 +
 550 +#include "config.h"
 551 +
 552 +#include <sys/types.h>
 553 +#include <sys/stat.h>
 554 +#include <sys/wait.h>
 555 +#include <fcntl.h>
 556 +#include <errno.h>
 557 +#include <signal.h>
 558 +#include <string.h>
 559 +#include <pthread.h>
 560 +#include <signal.h>
 561 +#include <time.h>
 562 +#include <inttypes.h>
 563 +
 564 +#include <sqlite3.h>
 565 +
 566 +#include <camel/camel-mime-message.h>
 567 +#include <camel/camel-i18n.h>
 568 +#include <camel/camel-store.h>
 569 +#include <camel/camel-folder.h>
 570 +#include <camel/camel-db.h>
 571 +#include <camel/camel-offline-store.h>
 572 +#include <camel/camel-session.h>
 573 +
 574 +#include <mail/mail-config.h>
 575 +#include <mail/mail-session.h>
 576 +#include <mail/em-utils.h>
 577 +#include <mail/mail-ops.h>
 578 +
 579 +#include <e-util/e-config.h>
 580 +
 581 +#include <libedataserver/e-account.h>
 582 +#include <libedataserver/e-account-list.h>
 583 +
 584 +#include "tracker-evolution-plugin.h"
 585 +#include "tracker-evolution-plugin-glue.h"
 586 +
 587 +/* This runs in-process of evolution (in the mailer, as a EPlugin). It has 
 588 + * access to the CamelSession using the external variable 'session'. The header
 589 + * mail/mail-session.h makes this variable public */
 590 +
 591 +#define MAX_BEFORE_SEND 2000
 592 +
 593 +G_DEFINE_TYPE (TrackerEvolutionPlugin, tracker_evolution_plugin, G_TYPE_OBJECT)
 594 +
 595 +#define TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_PLUGIN, TrackerEvolutionPluginPrivate))
 596 +
 597 +/* Some helper-defines */
 598 +#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func)
 599 +#define EXTRACT_STRING(val) if (*part) part++; len=strtoul (part, &part, 10); if (*part) part++; val=g_strndup (part, len); part+=len;
 600 +#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10);
 601 +
 602 +/* About the locks being used: Camel's API must be used in a multi-threaded
 603 + * fashion. Therefore it's necessary to guard against concurrent access of
 604 + * memory. Especially given that both the mainloop and the Camel-threads will
 605 + * be accessing the memory (mainloop for DBus calls, and Camel-threads mostly
 606 + * during registration of accounts and folders) */
 607 +
 608 +typedef struct {
 609 +	guint64 last_checkout;
 610 +	DBusGProxy *registrar;
 611 +	guint signal;
 612 +} ClientRegistry;
 613 +
 614 +typedef struct {
 615 +	TrackerEvolutionPlugin *self;
 616 +	gchar *account_uri;
 617 +	guint hook_id;
 618 +} OnSummaryChangedInfo;
 619 +
 620 +typedef struct {
 621 +	OnSummaryChangedInfo *hook_info;
 622 +	CamelFolder *folder;
 623 +} FolderRegistry;
 624 +
 625 +typedef struct {
 626 +	EAccount *account;
 627 +	TrackerEvolutionPlugin *self;
 628 +	guint hook_id;
 629 +	CamelStore *store;
 630 +} StoreRegistry;
 631 +
 632 +typedef struct {
 633 +	TrackerEvolutionPlugin *self;
 634 +	gchar *account_uri;
 635 +	ClientRegistry *info;
 636 +} IntroductionInfo;
 637 +
 638 +typedef struct {
 639 +	TrackerEvolutionPlugin *self;
 640 +	gchar *uri;
 641 +	gboolean old_state;
 642 +	EAccount *account;
 643 +} RegisterInfo;
 644 +
 645 +typedef struct {
 646 +	DBusGConnection *connection;
 647 +	GHashTable *registrars;
 648 +	GStaticRecMutex *mutex;
 649 +	GHashTable *registered_folders;
 650 +	GHashTable *cached_folders;
 651 +	GHashTable *registered_stores;
 652 +	GList *registered_clients;
 653 +	EAccountList *accounts;
 654 +} TrackerEvolutionPluginPrivate;
 655 +
 656 +enum {
 657 +	PROP_0,
 658 +	PROP_CONNECTION
 659 +};
 660 +
 661 +static DBusGProxy *dbus_proxy = NULL;
 662 +static TrackerEvolutionPlugin *manager = NULL;
 663 +static GStaticRecMutex glock = G_STATIC_REC_MUTEX_INIT;
 664 +
 665 +/* Prototype declarations */
 666 +static void register_account (TrackerEvolutionPlugin *self, EAccount *account);
 667 +static void unregister_account (TrackerEvolutionPlugin *self, EAccount *account);
 668 +int e_plugin_lib_enable (EPluginLib *ep, int enable);
 669 +static void metadata_set_many (TrackerEvolutionPlugin *self, GStrv subjects, GPtrArray *predicates, GPtrArray *values);
 670 +static void metadata_unset_many (TrackerEvolutionPlugin *self, GStrv subjects);
 671 +
 672 +static GList *
 673 +get_recipient_list (const gchar *str)
 674 +{
 675 +	GList *list = NULL;
 676 +	gchar **arr;
 677 +	gint i;
 678 +
 679 +	if (!str) {
 680 +		return NULL;
 681 +	}
 682 +
 683 +	arr = g_strsplit (str, ",", -1);
 684 +
 685 +	for (i = 0; arr[i]; i++) {
 686 +		g_strstrip (arr[i]);
 687 +		list = g_list_prepend (list, g_strdup (arr[i]));
 688 +	}
 689 +
 690 +	g_strfreev (arr);
 691 +
 692 +	return g_list_reverse (list);
 693 +}
 694 +
 695 +static void
 696 +folder_registry_free (FolderRegistry *registry)
 697 +{
 698 +	camel_object_remove_event (registry->folder, registry->hook_info->hook_id);
 699 +	camel_object_unref (registry->folder);
 700 +	g_free (registry->hook_info->account_uri);
 701 +	g_slice_free (OnSummaryChangedInfo, registry->hook_info);
 702 +	g_slice_free (FolderRegistry, registry);
 703 +}
 704 +
 705 +static FolderRegistry*
 706 +folder_registry_new (const gchar *account_uri, 
 707 +		     CamelFolder *folder, 
 708 +		     TrackerEvolutionPlugin *self)
 709 +{
 710 +	FolderRegistry *registry = g_slice_new (FolderRegistry);
 711 +
 712 +	registry->hook_info = g_slice_new (OnSummaryChangedInfo);
 713 +	registry->hook_info->account_uri = g_strdup (account_uri);
 714 +	registry->hook_info->self = self; /* weak */
 715 +	registry->hook_info->hook_id = 0;
 716 +	camel_object_ref (folder);
 717 +	registry->folder = folder;
 718 +
 719 +	return registry;
 720 +}
 721 +
 722 +static void
 723 +process_fields (GPtrArray *predicates_temp, 
 724 +		GPtrArray *values_temp, 
 725 +		gchar *uid, 
 726 +		guint flags, 
 727 +		gchar *sent, 
 728 +		gchar *subject,
 729 +		gchar *from, 
 730 +		gchar *to, 
 731 +		gchar *cc, 
 732 +		gchar *size,
 733 +		CamelFolder *folder)
 734 +{
 735 +	GList *list, *l;
 736 +
 737 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_UID));
 738 +	g_ptr_array_add (values_temp, g_strdup (uid));
 739 +
 740 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SEEN));
 741 +	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_SEEN) ? "True" : "False"));
 742 +
 743 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_JUNK));
 744 +	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_JUNK) ? "True" : "False"));
 745 +
 746 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_DELETED));
 747 +	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_DELETED) ? "True" : "False"));
 748 +
 749 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_ANSWERED));
 750 +	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_ANSWERED) ? "True" : "False"));
 751 +
 752 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FLAGGED));
 753 +	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_FLAGGED) ? "True" : "False"));
 754 +
 755 +	g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FORWARDED));
 756 +	g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_FORWARDED) ? "True" : "False"));
 757 +
 758 +
 759 +	if (subject && g_utf8_validate (subject, -1, NULL)) {
 760 +		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SUBJECT));
 761 +		g_ptr_array_add (values_temp, g_strdup (subject));
 762 +	}
 763 +
 764 +	list = get_recipient_list (to);
 765 +	for (l = list; l; l = l->next) {
 766 +		if (l->data && g_utf8_validate (l->data, -1, NULL)) {
 767 +			g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TO));
 768 +			g_ptr_array_add (values_temp, l->data);
 769 +		} else
 770 +			g_free (l->data);
 771 +	}
 772 +	g_list_free (list);
 773 +
 774 +	if (from && g_utf8_validate (from, -1, NULL)) {
 775 +		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FROM));
 776 +		g_ptr_array_add (values_temp, g_strdup (from));
 777 +	}
 778 +
 779 +	if (size && g_utf8_validate (size, -1, NULL)) {
 780 +		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SIZE));
 781 +		g_ptr_array_add (values_temp, g_strdup (size));
 782 +	}
 783 +
 784 +	list = get_recipient_list (cc);
 785 +	for (l = list; l; l = l->next) {
 786 +		if (l->data && g_utf8_validate (l->data, -1, NULL)) {
 787 +			g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_CC));
 788 +			g_ptr_array_add (values_temp, l->data);
 789 +		} else
 790 +			g_free (l->data);
 791 +	}
 792 +	g_list_free (list);
 793 +
 794 +	if (sent && g_utf8_validate (sent, -1, NULL)) {
 795 +		g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_SENT));
 796 +		g_ptr_array_add (values_temp, g_strdup (sent));
 797 +	}
 798 +
 799 +	if (folder) {
 800 +		gchar *filen = camel_folder_get_filename (folder, uid, NULL);
 801 +		if (filen) {
 802 +			if (g_file_test (filen, G_FILE_TEST_EXISTS)) {
 803 +				g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FILE));
 804 +				g_ptr_array_add (values_temp, filen);
 805 +			} else
 806 +				g_free (filen);
 807 +		}
 808 +	}
 809 +}
 810 +
 811 +/* When new messages arrive to- or got deleted from the summary, called in
 812 + * mainloop or by a thread (unknown, depends on Camel and Evolution code that 
 813 + * executes the reason why this signal gets emitted) */
 814 +
 815 +static void
 816 +on_folder_summary_changed (CamelFolder *folder, 
 817 +			   CamelFolderChangeInfo *changes, 
 818 +			   gpointer user_data)
 819 +{
 820 +	OnSummaryChangedInfo *info = user_data;
 821 +	TrackerEvolutionPlugin *self  = info->self;
 822 +	CamelFolderSummary *summary;
 823 +	gchar *account_uri = info->account_uri;
 824 +	GPtrArray *merged;
 825 +	guint i;
 826 +	gchar *em_uri;
 827 +
 828 +	if (!folder)
 829 +		return;
 830 +
 831 +	summary = folder->summary;
 832 +	em_uri = em_uri_from_camel (account_uri);
 833 +
 834 +	merged = g_ptr_array_new ();
 835 +
 836 +	/* the uid_added member contains the added-to-the-summary items */
 837 +
 838 +	if (changes->uid_added && changes->uid_added->len > 0) {
 839 +		for (i = 0; i < changes->uid_added->len; i++)
 840 +			g_ptr_array_add (merged, changes->uid_added->pdata[i]);
 841 +	}
 842 +
 843 +	/* the uid_changed member contains the changed-in-the-summary items */
 844 +
 845 +	if (changes->uid_changed && changes->uid_changed->len > 0) {
 846 +		gboolean found = FALSE;
 847 +		guint y;
 848 +
 849 +		for (i = 0; i < changes->uid_changed->len; i++) {
 850 +			for (y = 0; y < merged->len; y++) {
 851 +				if (strcmp (merged->pdata[y], changes->uid_changed->pdata[i]) == 0) {
 852 +					found = TRUE;
 853 +					break;
 854 +				}
 855 +			}
 856 +
 857 +			if (!found)
 858 +				g_ptr_array_add (merged, changes->uid_changed->pdata[i]);
 859 +		}
 860 +	}
 861 +
 862 +	if (merged->len > 0) {
 863 +		GPtrArray *predicates_array = g_ptr_array_new ();
 864 +		GPtrArray *values_array = g_ptr_array_new ();
 865 +		gchar **subjects = (gchar **) g_malloc0 (sizeof (gchar *) * merged->len + 1);
 866 +		guint y;
 867 +
 868 +		y = 0;
 869 +
 870 +		for (i = 0; i< merged->len; i++) {
 871 +			gchar *subject, *to, *from, *cc, *uid = NULL, *sent, *size;
 872 +			guint flags;
 873 +			gchar **values, **predicates;
 874 +			CamelMessageInfo *linfo;
 875 +			GPtrArray *values_temp = g_ptr_array_new ();
 876 +			GPtrArray *predicates_temp = g_ptr_array_new ();
 877 +			const CamelTag *ctags;
 878 +			const CamelFlag *cflags;
 879 +
 880 +			linfo = camel_folder_summary_uid (summary, merged->pdata[i]);
 881 +
 882 +			if (linfo)
 883 +				uid = (gchar *) camel_message_info_uid (linfo);
 884 +
 885 +			if (linfo && uid) {
 886 +				guint j, max;
 887 +
 888 +				subject = (gchar *) camel_message_info_subject (linfo);
 889 +				to =      (gchar *) camel_message_info_to (linfo);
 890 +				from =    (gchar *) camel_message_info_from (linfo);
 891 +				cc =      (gchar *) camel_message_info_cc (linfo);
 892 +				flags =   (guint)   camel_message_info_flags (linfo);
 893 +
 894 +				/* Camel returns a time_t, I think a uint64 is the best fit here */
 895 +				sent = g_strdup_printf ("%"PRIu64, (unsigned long long) camel_message_info_date_sent (linfo));
 896 +
 897 +				/* Camel returns a uint32, so %u */
 898 +				size = g_strdup_printf ("%u", camel_message_info_size (linfo));
 899 +
 900 +				process_fields (predicates_temp, values_temp, uid,
 901 +						flags, sent, subject, from, to, cc, 
 902 +						size, folder);
 903 +
 904 +				cflags = camel_message_info_user_flags (linfo);
 905 +				while (cflags) {
 906 +					g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
 907 +					g_ptr_array_add (values_temp, g_strdup_printf ("%s=True", cflags->name));
 908 +					cflags = cflags->next;
 909 +				}
 910 +
 911 +				ctags = camel_message_info_user_tags (linfo);
 912 +				while (ctags) {
 913 +					g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
 914 +					g_ptr_array_add (values_temp, g_strdup_printf ("%s=%s", ctags->name, ctags->value));
 915 +					ctags = ctags->next;
 916 +				}
 917 +
 918 +				if (values_temp->len != predicates_temp->len)
 919 +					g_critical ("values_temp->len != predicates_temp->len");
 920 +
 921 +				max = MIN (values_temp->len, predicates_temp->len);
 922 +
 923 +				values = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
 924 +				predicates = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
 925 +
 926 +				for (j = 0; j < max; j++) {
 927 +					predicates[j] = predicates_temp->pdata[j];
 928 +					values[j] = values_temp->pdata[j];
 929 +				}
 930 +
 931 +				predicates[j] = NULL;
 932 +				values[j] = NULL;
 933 +
 934 +				g_ptr_array_add (values_array, values);
 935 +				g_ptr_array_add (predicates_array, predicates);
 936 +
 937 +				/* This is not a path but a URI, don't use the 
 938 +				 * OS's directory separator here */
 939 +
 940 +				subjects[y] = g_strdup_printf ("%s%s/%s", 
 941 +							       em_uri, 
 942 +							       camel_folder_get_full_name (folder),
 943 +							       uid);
 944 +
 945 +				g_ptr_array_free (predicates_temp, TRUE);
 946 +				g_ptr_array_free (values_temp, TRUE);
 947 +
 948 +				y++;
 949 +			}
 950 +
 951 +			if (linfo)
 952 +				camel_message_info_free (linfo);
 953 +		}
 954 +
 955 +		subjects[y] = NULL;
 956 +
 957 +		/* This goes to all currently registered registrars */
 958 +
 959 +		metadata_set_many (self, subjects, predicates_array, values_array);
 960 +
 961 +		g_strfreev (subjects);
 962 +		for (i = 0; i < values_array->len; i++)
 963 +			g_strfreev (values_array->pdata[i]);
 964 +		g_ptr_array_free (values_array, TRUE);
 965 +		for (i = 0; i < predicates_array->len; i++)
 966 +			g_strfreev (predicates_array->pdata[i]);
 967 +		g_ptr_array_free (predicates_array, TRUE);
 968 +	}
 969 +
 970 +	g_ptr_array_free (merged, TRUE);
 971 +
 972 +	/* the uid_removed member contains the removed-from-the-summary items */
 973 +
 974 +	if (changes->uid_removed && changes->uid_removed->len > 0) {
 975 +		gchar **subjects = (gchar **) g_malloc0 (sizeof (gchar *) * changes->uid_removed->len + 1);
 976 +
 977 +		for (i = 0; i< changes->uid_removed->len; i++) {
 978 +
 979 +			/* This is not a path but a URI, don't use the OS's 
 980 +			 * directory separator here */
 981 +
 982 +			subjects[i] = g_strdup_printf ("%s%s/%s", em_uri, 
 983 +						       camel_folder_get_full_name (folder),
 984 +						       (char*) changes->uid_removed->pdata[i]);
 985 +		}
 986 +
 987 +		subjects[i] = NULL;
 988 +
 989 +		/* This goes to all currently registered registrars */
 990 +
 991 +		metadata_unset_many (self, subjects);
 992 +
 993 +		g_strfreev (subjects);
 994 +	}
 995 +	g_free (em_uri);
 996 +}
 997 +
 998 +/* Initial upload of more recent than last_checkout items, called in the mainloop */
 999 +static void
1000 +introduce_walk_folders_in_folder (TrackerEvolutionPlugin *self, 
1001 +				  CamelFolderInfo *iter, 
1002 +				  CamelStore *store, 
1003 +				  gchar *account_uri, 
1004 +				  ClientRegistry *info)
1005 +{
1006 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1007 +	gchar *em_uri = em_uri_from_camel (account_uri);
1008 +
1009 +	while (iter) {
1010 +		guint i, ret = SQLITE_OK;
1011 +		CamelDB *cdb_r = store->cdb_r;
1012 +		gchar *query;
1013 +		sqlite3_stmt *stmt = NULL;
1014 +		gboolean more = TRUE;
1015 +
1016 +		query = sqlite3_mprintf ("SELECT uid, flags, read, deleted, "            /* 0  - 3  */
1017 +					        "replied, important, junk, attachment, " /* 4  - 7  */
1018 +					        "size, dsent, dreceived, subject, "      /* 8  - 11 */
1019 +					        "mail_from, mail_to, mail_cc, mlist, "   /* 12 - 15 */
1020 +					        "labels, usertags "                      /* 16 - 17 */
1021 +					 "FROM %Q "
1022 +					 "WHERE modified > %"PRIu64, 
1023 +
1024 +					 iter->full_name, 
1025 +					 info->last_checkout);
1026 +
1027 +		g_mutex_lock (cdb_r->lock);
1028 +
1029 +		ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL);
1030 +
1031 +		while (more) {
1032 +			GPtrArray *subjects_a = g_ptr_array_new ();
1033 +			GPtrArray *predicates_array = g_ptr_array_new ();
1034 +			GPtrArray *values_array = g_ptr_array_new ();
1035 +			guint count = 0;
1036 +
1037 +			more = FALSE;
1038 +
1039 +			while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) {
1040 +				gchar **values, **predicates;
1041 +				gchar *subject, *to, *from, *cc, *sent, *uid, *size;
1042 +				gchar *part, *label, *p;
1043 +				guint flags;
1044 +
1045 +				ret = sqlite3_step (stmt);
1046 +
1047 +				if (ret == SQLITE_BUSY) {
1048 +					usleep (10);
1049 +					continue;
1050 +				}
1051 +
1052 +				if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) {
1053 +					more = FALSE;
1054 +					break;
1055 +				}
1056 +
1057 +				uid = (gchar *) sqlite3_column_text (stmt, 0);
1058 +
1059 +				if (uid) {
1060 +					GPtrArray *predicates_temp = g_ptr_array_new ();
1061 +					GPtrArray *values_temp = g_ptr_array_new ();
1062 +					CamelFolder *folder;
1063 +					guint max = 0, j;
1064 +
1065 +					flags =   (guint  ) sqlite3_column_int  (stmt, 1);
1066 +					size =    (gchar *) sqlite3_column_text (stmt, 8);
1067 +					sent =    (gchar *) sqlite3_column_text (stmt, 9);
1068 +					subject = (gchar *) sqlite3_column_text (stmt, 11);
1069 +					from =    (gchar *) sqlite3_column_text (stmt, 12);
1070 +					to =      (gchar *) sqlite3_column_text (stmt, 13);
1071 +					cc =      (gchar *) sqlite3_column_text (stmt, 14);
1072 +
1073 +					g_static_rec_mutex_lock (priv->mutex);
1074 +
1075 +					folder = g_hash_table_lookup (priv->cached_folders, iter->full_name);
1076 +
1077 +					process_fields (predicates_temp, values_temp, uid, flags, sent, 
1078 +							subject, from, to, cc, size, folder);
1079 +
1080 +					g_static_rec_mutex_unlock (priv->mutex);
1081 +
1082 +					/* Extract User flags/labels */
1083 +					p = part = g_strdup ((const gchar *) sqlite3_column_text (stmt, 16));
1084 +					if (part) {
1085 +						label = part;
1086 +						for (j=0; part[j]; j++) {
1087 +
1088 +							if (part[j] == ' ') {
1089 +								part[j] = 0;
1090 +								g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
1091 +								g_ptr_array_add (values_temp, g_strdup_printf ("%s=True", label));
1092 +								label = &(part[j+1]);
1093 +							}
1094 +						}
1095 +						g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
1096 +						g_ptr_array_add (values_temp, g_strdup (label));
1097 +					}
1098 +					g_free (p);
1099 +
1100 +					/* Extract User tags */
1101 +					p = part = g_strdup ((const gchar *) sqlite3_column_text (stmt, 17));
1102 +					EXTRACT_FIRST_DIGIT (max)
1103 +					for (j = 0; j < max; j++) {
1104 +						int len;
1105 +						char *name, *value;
1106 +						EXTRACT_STRING (name)
1107 +						EXTRACT_STRING (value)
1108 +						if (name && g_utf8_validate (name, -1, NULL) &&
1109 +						    value && g_utf8_validate (value, -1, NULL)) {
1110 +							g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_TAG));
1111 +							g_ptr_array_add (values_temp, g_strdup_printf ("%s=%s", name, value));
1112 +						}
1113 +						g_free(name);
1114 +						g_free(value);
1115 +					}
1116 +					g_free (p);
1117 +
1118 +					if (values_temp->len != predicates_temp->len)
1119 +						g_critical ("values_temp->len != predicates_temp->len");
1120 +
1121 +					max = MIN (values_temp->len, predicates_temp->len);
1122 +
1123 +					values = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
1124 +					predicates = (gchar **) g_malloc0 (sizeof (gchar*) * max + 1);
1125 +
1126 +					for (j = 0; j < max; j++) {
1127 +						predicates[j] = predicates_temp->pdata[j];
1128 +						values[j] = values_temp->pdata[j];
1129 +					}
1130 +
1131 +					predicates[j] = NULL;
1132 +					values[j] = NULL;
1133 +
1134 +					/* This is not a path but a URI, don't use the 
1135 +					 * OS's directory separator here */
1136 +
1137 +					g_ptr_array_add (subjects_a, g_strdup_printf ("%s%s/%s", em_uri, 
1138 +										      iter->full_name, uid));
1139 +
1140 +					g_ptr_array_add (predicates_array, predicates);
1141 +					g_ptr_array_add (values_array, values);
1142 +
1143 +					g_ptr_array_free (predicates_temp, TRUE);
1144 +					g_ptr_array_free (values_temp, TRUE);
1145 +
1146 +					count++;
1147 +				}
1148 +
1149 +				if (count > MAX_BEFORE_SEND) {
1150 +
1151 +					/* Yield per MAX_BEFORE_SEND. This function is 
1152 +					 * called as a result of a DBus call, so it runs
1153 +					 * in the mainloop. Therefore, yield he mainloop
1154 +					 * sometimes, indeed */
1155 +
1156 +					g_main_context_iteration (NULL, TRUE);
1157 +
1158 +					more = TRUE;
1159 +					break;
1160 +				}
1161 +
1162 +				more = FALSE;
1163 +			}
1164 +
1165 +
1166 +			if (count > 0) {
1167 +				gchar **subjects;
1168 +
1169 +				subjects = (gchar **) g_malloc0 (sizeof (gchar *) * subjects_a->len + 1);
1170 +				for (i = 0; i < subjects_a->len; i++)
1171 +					subjects[i] = g_ptr_array_index (subjects_a, i);
1172 +				subjects[i] = NULL;
1173 +
1174 +				dbus_g_proxy_call_no_reply (info->registrar,
1175 +							    "SetMany",
1176 +							    G_TYPE_STRV, subjects,
1177 +							    TRACKER_TYPE_G_STRV_ARRAY, predicates_array,
1178 +							    TRACKER_TYPE_G_STRV_ARRAY, values_array,
1179 +							    G_TYPE_INVALID, 
1180 +							    G_TYPE_INVALID);
1181 +
1182 +				g_strfreev (subjects);
1183 +			}
1184 +
1185 +			g_ptr_array_free (subjects_a, TRUE);
1186 +
1187 +			for (i = 0; i < values_array->len; i++)
1188 +				g_strfreev (values_array->pdata[i]); 
1189 +			g_ptr_array_free (values_array, TRUE);
1190 +
1191 +			for (i = 0; i < predicates_array->len; i++)
1192 +				g_strfreev (predicates_array->pdata[i]); 
1193 +			g_ptr_array_free (predicates_array, TRUE);
1194 +		}
1195 +
1196 +		sqlite3_finalize (stmt);
1197 +		sqlite3_free (query);
1198 +
1199 +		g_mutex_unlock (cdb_r->lock);
1200 +
1201 +		if (iter->child) {
1202 +			introduce_walk_folders_in_folder (self, iter->child, store, account_uri, info);
1203 +		}
1204 +
1205 +		iter = iter->next;
1206 +	}
1207 +
1208 +	g_free (em_uri);
1209 +}
1210 +
1211 +/* Initial notify of deletes that are more recent than last_checkout, called in 
1212 + * the mainloop */
1213 +
1214 +static void
1215 +introduce_store_deal_with_deleted (TrackerEvolutionPlugin *self, 
1216 +				   CamelStore *store, 
1217 +				   char *account_uri, 
1218 +				   gpointer user_data)
1219 +{
1220 +	ClientRegistry *info = user_data;
1221 +	gboolean more = TRUE;
1222 +	gchar *query;
1223 +	sqlite3_stmt *stmt = NULL;
1224 +	CamelDB *cdb_r;
1225 +	guint i, ret;
1226 +	gchar *em_uri = em_uri_from_camel (account_uri);
1227 +
1228 +	query = sqlite3_mprintf ("SELECT uid, mailbox FROM Deletes WHERE modified > %" PRIu64, 
1229 +				 info->last_checkout);
1230 +
1231 +	cdb_r = store->cdb_r;
1232 +
1233 +	g_mutex_lock (cdb_r->lock);
1234 +
1235 +	sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL);
1236 +
1237 +	ret = SQLITE_OK;
1238 +
1239 +	while (more) {
1240 +		GPtrArray *subjects_a = g_ptr_array_new ();
1241 +		guint count = 0;
1242 +
1243 +		more = FALSE;
1244 +
1245 +		while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) {
1246 +			const gchar *uid;
1247 +			const gchar *mailbox;
1248 +
1249 +			ret = sqlite3_step (stmt);
1250 +
1251 +			if (ret == SQLITE_BUSY) {
1252 +				usleep (10);
1253 +				continue;
1254 +			}
1255 +
1256 +			if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) {
1257 +				more = FALSE;
1258 +				break;
1259 +			}
1260 +
1261 +			uid     = (const gchar *) sqlite3_column_text (stmt, 0);
1262 +			mailbox = (const gchar *) sqlite3_column_text (stmt, 1);
1263 +
1264 +			/* This is not a path but a URI, don't use the OS's 
1265 +			 * directory separator here */
1266 +
1267 +			g_ptr_array_add (subjects_a, g_strdup_printf ("%s%s/%s", em_uri, 
1268 +								      mailbox, uid));
1269 +
1270 +			if (count > MAX_BEFORE_SEND) {
1271 +
1272 +				/* Yield per MAX_BEFORE_SEND. This function is 
1273 +				 * called as a result of a DBus call, so it runs
1274 +				 * in the mainloop. Therefore, yield he mainloop
1275 +				 * sometimes, indeed */
1276 +
1277 +				g_main_context_iteration (NULL, TRUE);
1278 +
1279 +				more = TRUE;
1280 +				break;
1281 +			}
1282 +
1283 +			count++;
1284 +
1285 +			more = FALSE;
1286 +		}
1287 +
1288 +		if (count > 0) {
1289 +			gchar **subjects;
1290 +
1291 +			subjects = (gchar **) g_malloc0 (sizeof (gchar *) * subjects_a->len + 1);
1292 +			for (i = 0; i < subjects_a->len; i++)
1293 +				subjects[i] = g_ptr_array_index (subjects_a, i);
1294 +			subjects[i] = NULL;
1295 +
1296 +			dbus_g_proxy_call_no_reply (info->registrar,
1297 +						    "UnsetMany",
1298 +						    G_TYPE_STRV, subjects,
1299 +						    G_TYPE_INVALID,
1300 +						    G_TYPE_INVALID);
1301 +
1302 +			g_strfreev (subjects);
1303 +		}
1304 +
1305 +		g_ptr_array_free (subjects_a, TRUE);
1306 +
1307 +	}
1308 +
1309 +	sqlite3_finalize (stmt);
1310 +	sqlite3_free (query);
1311 +
1312 +	g_mutex_unlock (cdb_r->lock);
1313 +
1314 +	g_free (em_uri);
1315 +}
1316 +
1317 +/* Get the oldest date in all of the deleted-tables, called in the mainloop */
1318 +
1319 +static guint64
1320 +get_last_deleted_time (TrackerEvolutionPlugin *self)
1321 +{
1322 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1323 +	guint64 smallest = (guint64) time (NULL);
1324 +
1325 +	if (priv->accounts) {
1326 +		EIterator *it;
1327 +
1328 +		for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it)) {
1329 +			EAccount *account = (EAccount *) e_iterator_get (it);
1330 +			CamelProvider *provider;
1331 +			CamelStore *store;
1332 +			CamelException ex;
1333 +			char *uri;
1334 +			CamelDB *cdb_r;
1335 +			sqlite3_stmt *stmt = NULL;
1336 +			gchar *query;
1337 +			guint ret = SQLITE_OK;
1338 +			guint64 latest = smallest;
1339 +
1340 +			camel_exception_init (&ex);
1341 +
1342 +			if (!account->enabled || !(uri = account->source->url))
1343 +				continue;
1344 +
1345 +			if (!(provider = camel_provider_get(uri, NULL))) {
1346 +				camel_exception_clear (&ex);
1347 +				continue;
1348 +			}
1349 +
1350 +			if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
1351 +				continue;
1352 +
1353 +			if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
1354 +				camel_exception_clear (&ex);
1355 +				continue;
1356 +			}
1357 +
1358 +			cdb_r = store->cdb_r;
1359 +
1360 +			query = sqlite3_mprintf ("SELECT time FROM Deletes ORDER BY time LIMIT 1");
1361 +
1362 +			g_mutex_lock (cdb_r->lock);
1363 +
1364 +			ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL);
1365 +
1366 +			ret = sqlite3_step (stmt);
1367 +			if (ret == SQLITE_OK || ret == SQLITE_ROW)
1368 +				latest = sqlite3_column_int64 (stmt, 0);
1369 +
1370 +			if (latest < smallest)
1371 +				smallest = latest;
1372 +
1373 +			sqlite3_finalize (stmt);
1374 +			sqlite3_free (query);
1375 +
1376 +			g_mutex_unlock (cdb_r->lock);
1377 +
1378 +		}
1379 +
1380 +		g_object_unref (it);
1381 +	}
1382 +
1383 +	return smallest;
1384 +}
1385 +
1386 +
1387 +static void
1388 +register_walk_folders_in_folder (TrackerEvolutionPlugin *self, 
1389 +				 CamelFolderInfo *iter, 
1390 +				 CamelStore *store, 
1391 +				 gchar *account_uri)
1392 +{
1393 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1394 +
1395 +	while (iter) {
1396 +		CamelFolder *folder;
1397 +
1398 +		folder = camel_store_get_folder (store, iter->full_name, 0, NULL);
1399 +
1400 +		if (folder) {
1401 +			guint hook_id;
1402 +			FolderRegistry *registry;
1403 +
1404 +			registry = folder_registry_new (account_uri, folder, self);
1405 +
1406 +			g_static_rec_mutex_lock (priv->mutex);
1407 +
1408 +			if (!priv->registered_folders) {
1409 +				priv->registered_folders = g_hash_table_new_full (g_int_hash, g_int_equal,
1410 +										  (GDestroyNotify) NULL,
1411 +										  (GDestroyNotify) folder_registry_free);
1412 +				priv->cached_folders = g_hash_table_new_full (g_str_hash, g_str_equal,
1413 +									      (GDestroyNotify) g_free,
1414 +									      (GDestroyNotify) NULL);
1415 +			}
1416 +
1417 +			hook_id = camel_object_hook_event (folder, "folder_changed", 
1418 +							   CAMEL_CALLBACK (on_folder_summary_changed), 
1419 +							   registry->hook_info);
1420 +			registry->hook_info->hook_id = hook_id;
1421 +
1422 +			g_hash_table_replace (priv->registered_folders, &hook_id, 
1423 +					      registry);
1424 +			g_hash_table_replace (priv->cached_folders, g_strdup (iter->full_name), 
1425 +					      folder);
1426 +
1427 +			g_static_rec_mutex_unlock (priv->mutex);
1428 +
1429 +			camel_object_unref (folder);
1430 +		}
1431 +
1432 +		if (iter->child) {
1433 +			register_walk_folders_in_folder (self, iter->child, store, 
1434 +							 account_uri);
1435 +		}
1436 +
1437 +		iter = iter->next;
1438 +	}
1439 +}
1440 +
1441 +
1442 +static void
1443 +unregister_walk_folders_in_folder (TrackerEvolutionPlugin *self, 
1444 +				   CamelFolderInfo *titer, 
1445 +				   CamelStore *store, 
1446 +				   gchar *account_uri)
1447 +{
1448 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1449 +
1450 +	while (titer) {
1451 +		CamelFolder *folder;
1452 +		GHashTableIter iter;
1453 +		gpointer key, value;
1454 +
1455 +		folder = camel_store_get_folder (store, titer->full_name, 0, NULL);
1456 +
1457 +		if (folder) {
1458 +			g_static_rec_mutex_lock (priv->mutex);
1459 +
1460 +			g_hash_table_iter_init (&iter, priv->registered_folders);
1461 +			while (g_hash_table_iter_next (&iter, &key, &value)) {
1462 +				FolderRegistry *registry = value;
1463 +
1464 +				if (folder == registry->folder) {
1465 +					g_hash_table_remove (priv->cached_folders, titer->full_name);
1466 +					g_hash_table_iter_remove (&iter);
1467 +					break;
1468 +				}
1469 +			}
1470 +
1471 +			camel_object_unref (folder);
1472 +
1473 +			g_static_rec_mutex_unlock (priv->mutex);
1474 +		}
1475 +
1476 +		if (titer->child) {
1477 +			unregister_walk_folders_in_folder (self, titer->child, store, 
1478 +							   account_uri);
1479 +		}
1480 +
1481 +		titer = titer->next;
1482 +	}
1483 +}
1484 +
1485 +static void
1486 +client_registry_info_free (ClientRegistry *info)
1487 +{
1488 +	if (info->signal != 0) /* known (see below) */
1489 +		g_signal_handler_disconnect (info->registrar, info->signal);
1490 +	g_object_unref (info->registrar);
1491 +	g_slice_free (ClientRegistry, info);
1492 +}
1493 +
1494 +static ClientRegistry*
1495 +client_registry_info_copy (ClientRegistry *info)
1496 +{
1497 +	ClientRegistry *ninfo = g_slice_new0 (ClientRegistry);
1498 +
1499 +	ninfo->signal = 0; /* known */
1500 +	ninfo->last_checkout = info->last_checkout;
1501 +	ninfo->registrar = g_object_ref (info->registrar);
1502 +
1503 +	return ninfo;
1504 +}
1505 +
1506 +static gboolean
1507 +on_got_folderinfo_introduce (CamelStore *store, 
1508 +			     CamelFolderInfo *iter, 
1509 +			     void *data)
1510 +{
1511 +	IntroductionInfo *intro_info = data;
1512 +
1513 +	introduce_walk_folders_in_folder (intro_info->self, iter, store, 
1514 +					  intro_info->account_uri, 
1515 +					  intro_info->info);
1516 +
1517 +	client_registry_info_free (intro_info->info);
1518 +	g_free (intro_info->account_uri);
1519 +	g_object_unref (intro_info->self);
1520 +	g_free (intro_info);
1521 +
1522 +	return TRUE;
1523 +}
1524 +
1525 +static void
1526 +introduce_account_to (TrackerEvolutionPlugin *self, 
1527 +		      EAccount *account, 
1528 +		      ClientRegistry *info)
1529 +{
1530 +	CamelProvider *provider;
1531 +	CamelStore *store;
1532 +	CamelException ex;
1533 +	char *uri, *account_uri, *ptr;
1534 +	IntroductionInfo *intro_info;
1535 +
1536 +	if (!account->enabled || !(uri = account->source->url))
1537 +		return;
1538 +
1539 +	camel_exception_init (&ex);
1540 +	if (!(provider = camel_provider_get(uri, &ex))) {
1541 +		camel_exception_clear (&ex);
1542 +		return;
1543 +	}
1544 +
1545 +	if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
1546 +		return;
1547 +
1548 +	if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
1549 +		camel_exception_clear (&ex);
1550 +		return;
1551 +	}
1552 +
1553 +	account_uri = g_strdup (uri);
1554 +
1555 +	ptr = strchr (account_uri, ';');
1556 +
1557 +	if (ptr)
1558 +		*ptr = '\0';
1559 +
1560 +	introduce_store_deal_with_deleted (self, store, account_uri, info);
1561 +
1562 +	intro_info = g_new0 (IntroductionInfo, 1);
1563 +
1564 +	intro_info->self = g_object_ref (self);
1565 +	intro_info->info = client_registry_info_copy (info);
1566 +	intro_info->account_uri = account_uri; /* is freed in on_got above */
1567 +
1568 +	mail_get_folderinfo (store, NULL, on_got_folderinfo_introduce, intro_info);
1569 +
1570 +	camel_object_unref (store);
1571 +
1572 +}
1573 +
1574 +
1575 +static void
1576 +introduce_account_to_all (TrackerEvolutionPlugin *self, 
1577 +			  EAccount *account)
1578 +{
1579 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1580 +	GList *copy = priv->registered_clients;
1581 +
1582 +	while (copy) {
1583 +		ClientRegistry *info = copy->data;
1584 +		introduce_account_to (self, account, info);
1585 +		copy = g_list_next (copy);
1586 +	}
1587 +
1588 +}
1589 +
1590 +static void
1591 +introduce_accounts_to (TrackerEvolutionPlugin *self, 
1592 +		       ClientRegistry *info)
1593 +{
1594 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1595 +	EIterator *it;
1596 +
1597 +	for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it))
1598 +		introduce_account_to (self, (EAccount *) e_iterator_get (it), info);
1599 +
1600 +	g_object_unref (it);
1601 +}
1602 +
1603 +
1604 +static void
1605 +register_client (TrackerEvolutionPlugin *self, 
1606 +		 guint64 last_checkout, 
1607 +		 DBusGProxy *registrar, 
1608 +		 guint dsignal)
1609 +{
1610 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1611 +	guint64 too_old = get_last_deleted_time (self);
1612 +	ClientRegistry *info = g_slice_new (ClientRegistry);
1613 +
1614 +	info->signal = dsignal;
1615 +	info->registrar = g_object_ref (registrar);
1616 +
1617 +	if (last_checkout < too_old) {
1618 +		dbus_g_proxy_call_no_reply (registrar,
1619 +					    "Cleanup",
1620 +					    G_TYPE_INVALID,
1621 +					    G_TYPE_INVALID);
1622 +		info->last_checkout = 0;
1623 +	} else
1624 +		info->last_checkout = last_checkout;
1625 +
1626 +	introduce_accounts_to (self, info);
1627 +
1628 +	priv->registered_clients = 
1629 +		g_list_prepend (priv->registered_clients, info);
1630 +
1631 +}
1632 +
1633 +
1634 +static void
1635 +metadata_set_many (TrackerEvolutionPlugin *self, 
1636 +		   GStrv subjects, 
1637 +		   GPtrArray *predicates, 
1638 +		   GPtrArray *values)
1639 +{
1640 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1641 +	GHashTableIter iter;
1642 +	gpointer key, value;
1643 +
1644 +	g_static_rec_mutex_lock (priv->mutex);
1645 +
1646 +	g_hash_table_iter_init (&iter, priv->registrars);
1647 +
1648 +	while (g_hash_table_iter_next (&iter, &key, &value)) {
1649 +		DBusGProxy *registrar = value;
1650 +
1651 +		dbus_g_proxy_call_no_reply (registrar,
1652 +					    "SetMany",
1653 +					    G_TYPE_STRV, subjects,
1654 +					    TRACKER_TYPE_G_STRV_ARRAY, predicates,
1655 +					    TRACKER_TYPE_G_STRV_ARRAY, values,
1656 +					    G_TYPE_INVALID, 
1657 +					    G_TYPE_INVALID);
1658 +	}
1659 +
1660 +	g_static_rec_mutex_unlock (priv->mutex);
1661 +}
1662 +
1663 +static void
1664 +metadata_unset_many (TrackerEvolutionPlugin *self, 
1665 +		     GStrv subjects)
1666 +{
1667 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1668 +	GHashTableIter iter;
1669 +	gpointer key, value;
1670 +
1671 +	g_static_rec_mutex_lock (priv->mutex);
1672 +
1673 +	g_hash_table_iter_init (&iter, priv->registrars);
1674 +
1675 +	while (g_hash_table_iter_next (&iter, &key, &value)) {
1676 +		DBusGProxy *registrar = value;
1677 +
1678 +		dbus_g_proxy_call_no_reply (registrar,
1679 +					    "UnsetMany",
1680 +					    G_TYPE_STRV, subjects,
1681 +					    G_TYPE_INVALID, 
1682 +					    G_TYPE_INVALID);
1683 +	}
1684 +
1685 +	g_static_rec_mutex_unlock (priv->mutex);
1686 +
1687 +}
1688 +
1689 +static void
1690 +on_folder_created (CamelStore *store, void *event_data, 
1691 +		   StoreRegistry *registry)
1692 +{
1693 +	unregister_account (registry->self, registry->account);
1694 +	register_account (registry->self, registry->account);
1695 +	introduce_account_to_all (registry->self, registry->account);
1696 +}
1697 +
1698 +static void
1699 +on_folder_deleted (CamelStore *store, 
1700 +		   void *event_data, 
1701 +		   StoreRegistry *registry)
1702 +{
1703 +	unregister_account (registry->self, registry->account);
1704 +	register_account (registry->self, registry->account);
1705 +	introduce_account_to_all (registry->self, registry->account);
1706 +}
1707 +
1708 +static void
1709 +on_folder_renamed (CamelStore *store, 
1710 +		   CamelRenameInfo *info, 
1711 +		   StoreRegistry *registry)
1712 +{
1713 +	unregister_account (registry->self, registry->account);
1714 +	register_account (registry->self, registry->account);
1715 +	introduce_account_to_all (registry->self, registry->account);
1716 +}
1717 +
1718 +static StoreRegistry*
1719 +store_registry_new (gpointer co, 
1720 +		    EAccount *account, 
1721 +		    TrackerEvolutionPlugin *self)
1722 +{
1723 +	StoreRegistry *registry = g_slice_new (StoreRegistry);
1724 +
1725 +	registry->store = co;
1726 +	registry->account = account; /* weak */
1727 +	registry->self = self; /* weak */
1728 +	camel_object_ref (co);
1729 +
1730 +	return registry;
1731 +}
1732 +
1733 +static void
1734 +store_registry_free (StoreRegistry *registry) 
1735 +{
1736 +	camel_object_remove_event (registry->store, registry->hook_id);
1737 +	camel_object_unref (registry->store);
1738 +	g_slice_free (StoreRegistry, registry);
1739 +}
1740 +
1741 +
1742 +static gboolean
1743 +on_got_folderinfo_register (CamelStore *store, 
1744 +			    CamelFolderInfo *iter, 
1745 +			    void *data)
1746 +{
1747 +	RegisterInfo *reg_info = data;
1748 +	TrackerEvolutionPlugin *self = reg_info->self;
1749 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1750 +	EAccount *account = reg_info->account;
1751 +	StoreRegistry *registry;
1752 +	gchar *uri = reg_info->uri;
1753 +	guint hook_id;
1754 +
1755 +	g_static_rec_mutex_lock (priv->mutex);
1756 +
1757 +	if (!priv->registered_stores)
1758 +		priv->registered_stores = g_hash_table_new_full (g_int_hash, g_int_equal,
1759 +								 (GDestroyNotify) NULL,
1760 +								 (GDestroyNotify) store_registry_free);
1761 +
1762 +	/* Hook up catching folder changes in the store */
1763 +	registry = store_registry_new (store, account, self);
1764 +	hook_id = camel_object_hook_event (store, "folder_created", 
1765 +					   CAMEL_CALLBACK (on_folder_created), 
1766 +					   registry);
1767 +	registry->hook_id = hook_id;
1768 +	g_hash_table_replace (priv->registered_stores, &hook_id, registry);
1769 +
1770 +	registry = store_registry_new (store, account, self);
1771 +	hook_id = camel_object_hook_event (store, "folder_renamed", 
1772 +					   CAMEL_CALLBACK (on_folder_renamed), 
1773 +					   registry);
1774 +	registry->hook_id = hook_id;
1775 +	g_hash_table_replace (priv->registered_stores, &hook_id, registry);
1776 +
1777 +	registry = store_registry_new (store, account, self);
1778 +	hook_id = camel_object_hook_event (store, "folder_deleted", 
1779 +					   CAMEL_CALLBACK (on_folder_deleted), 
1780 +					   registry);
1781 +	registry->hook_id = hook_id;
1782 +	g_hash_table_replace (priv->registered_stores, &hook_id, registry);
1783 +
1784 +	g_static_rec_mutex_unlock (priv->mutex);
1785 +
1786 +	/* Register each folder to hook folder_changed everywhere */
1787 +	register_walk_folders_in_folder (self, iter, store, uri);
1788 +
1789 +	g_object_unref (reg_info->account);
1790 +	g_object_unref (reg_info->self);
1791 +	g_free (reg_info->uri);
1792 +	g_free (reg_info);
1793 +
1794 +	return TRUE;
1795 +}
1796 +
1797 +static void
1798 +register_account (TrackerEvolutionPlugin *self,
1799 +		  EAccount *account)
1800 +{
1801 +	CamelProvider *provider;
1802 +	CamelStore *store;
1803 +	CamelException ex;
1804 +	char *uri;
1805 +	RegisterInfo *reg_info;
1806 +
1807 +	if (!account->enabled || !(uri = account->source->url))
1808 +		return;
1809 +
1810 +	camel_exception_init (&ex);
1811 +	if (!(provider = camel_provider_get(uri, &ex))) {
1812 +		camel_exception_clear (&ex);
1813 +		return;
1814 +	}
1815 +
1816 +	if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
1817 +		return;
1818 +
1819 +	if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
1820 +		camel_exception_clear (&ex);
1821 +		return;
1822 +	}
1823 +
1824 +	reg_info = g_new0 (RegisterInfo, 1);
1825 +
1826 +	reg_info->self = g_object_ref (self);
1827 +	reg_info->uri = g_strdup (uri);
1828 +	reg_info->account = g_object_ref (account);
1829 +
1830 +	/* Get the account's folder-info and register it asynchronously */
1831 +	mail_get_folderinfo (store, NULL, on_got_folderinfo_register, reg_info);
1832 +
1833 +	camel_object_unref (store);
1834 +}
1835 +
1836 +static gboolean
1837 +on_got_folderinfo_unregister (CamelStore *store, 
1838 +			      CamelFolderInfo *titer,
1839 +			      void *data)
1840 +{
1841 +	RegisterInfo *reg_info = data;
1842 +	TrackerEvolutionPlugin *self = reg_info->self;
1843 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
1844 +	gchar *uri = reg_info->uri;
1845 +	GHashTableIter iter;
1846 +	gpointer key, value;
1847 +
1848 +	unregister_walk_folders_in_folder (self, titer, store, uri);
1849 +
1850 +	g_static_rec_mutex_lock (priv->mutex);
1851 +
1852 +	if (priv->registered_stores) {
1853 +		g_hash_table_iter_init (&iter, priv->registered_stores);
1854 +
1855 +		while (g_hash_table_iter_next (&iter, &key, &value)) {
1856 +			if (value == store) 
1857 +				g_hash_table_iter_remove (&iter);
1858 +		}
1859 +	}
1860 +
1861 +	g_static_rec_mutex_unlock (priv->mutex);
1862 +
1863 +	g_object_unref (reg_info->self);
1864 +	g_free (reg_info->uri);
1865 +	g_free (reg_info);
1866 +
1867 +	return TRUE;
1868 +}
1869 +
1870 +static void
1871 +unregister_account (TrackerEvolutionPlugin *self,
1872 +		    EAccount *account)
1873 +{
1874 +	CamelProvider *provider;
1875 +	CamelStore *store;
1876 +	CamelException ex;
1877 +	char *uri;
1878 +	RegisterInfo *reg_info;
1879 +
1880 +
1881 +	camel_exception_init (&ex);
1882 +	if (!(provider = camel_provider_get(uri, &ex))) {
1883 +		camel_exception_clear (&ex);
1884 +		return;
1885 +	}
1886 +
1887 +	if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE))
1888 +		return;
1889 +
1890 +	if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) {
1891 +		camel_exception_clear (&ex);
1892 +		return;
1893 +	}
1894 +
1895 +	reg_info = g_new0 (RegisterInfo, 1);
1896 +
1897 +	reg_info->self = g_object_ref (self);
1898 +	reg_info->uri = g_strdup (uri);
1899 +	reg_info->account = NULL;
1900 +
1901 +	/* Get the account's folder-info and unregister asynchronously */
1902 +	mail_get_folderinfo (store, NULL, on_got_folderinfo_unregister, reg_info);
1903 +
1904 +	camel_object_unref (store);
1905 +}
1906 +
1907 +static void
1908 +on_account_added (EAccountList *list, 
1909 +		  EAccount *account, 
1910 +		  TrackerEvolutionPlugin *self)
1911 +{
1912 +	register_account (self, account);
1913 +	introduce_account_to_all (self, account);
1914 +}
1915 +
1916 +static void
1917 +on_account_removed (EAccountList *list,
1918 +		    EAccount *account,
1919 +		    TrackerEvolutionPlugin *self)
1920 +{
1921 +	unregister_account (self, account);
1922 +}
1923 +
1924 +static void
1925 +on_account_changed (EAccountList *list, 
1926 +		    EAccount *account,
1927 +		    TrackerEvolutionPlugin *self)
1928 +{
1929 +	unregister_account (self, account);
1930 +	register_account (self, account);
1931 +	introduce_account_to_all (self, account);
1932 +}
1933 +
1934 +static void
1935 +disable_plugin (void) 
1936 +{
1937 +	GError *error = NULL;
1938 +	guint result;
1939 +
1940 +	org_freedesktop_DBus_release_name (dbus_proxy, TRACKER_EVOLUTION_MANAGER_SERVICE, 
1941 +					   &result, &error);
1942 +
1943 +	if (!error) {
1944 +		if (manager) {
1945 +			g_object_unref (manager);
1946 +			manager = NULL;
1947 +		}
1948 +
1949 +		if (dbus_proxy) {
1950 +			g_object_unref (dbus_proxy);
1951 +			dbus_proxy = NULL;
1952 +		}
1953 +	} else {
1954 +		g_warning ("Could not setup DBus, ReleaseName of %s: %s\n", 
1955 +			   TRACKER_EVOLUTION_MANAGER_SERVICE, error->message);
1956 +
1957 +		g_error_free (error);
1958 +	}
1959 +}
1960 +
1961 +static void
1962 +enable_plugin (void)
1963 +{
1964 +	DBusGConnection *connection;
1965 +	GError *error = NULL;
1966 +	guint result;
1967 +
1968 +	if (dbus_proxy && manager)
1969 +		return;
1970 +
1971 +	if ((dbus_proxy && !manager) || (!dbus_proxy && manager))
1972 +		disable_plugin ();
1973 +
1974 +	if ((dbus_proxy && !manager) || (!dbus_proxy && manager))
1975 +		return;
1976 +
1977 +	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
1978 +
1979 +	if (error)
1980 +		goto error_handler;
1981 +
1982 +	dbus_proxy = dbus_g_proxy_new_for_name (connection, 
1983 +						DBUS_SERVICE_DBUS,
1984 +						DBUS_PATH_DBUS,
1985 +						DBUS_INTERFACE_DBUS);
1986 +
1987 +	if (!org_freedesktop_DBus_request_name (dbus_proxy, TRACKER_EVOLUTION_MANAGER_SERVICE,
1988 +						DBUS_NAME_FLAG_DO_NOT_QUEUE,
1989 +						&result, &error)) {
1990 +
1991 +		g_warning ("Could not setup DBus, failed at RequestName for %s\n", 
1992 +			   TRACKER_EVOLUTION_MANAGER_SERVICE);
1993 +
1994 +		goto error_handler;
1995 +	}
1996 +
1997 +	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1998 +
1999 +		g_warning ("Could not setup DBus, can't become primary owner of %s\n", 
2000 +			   TRACKER_EVOLUTION_MANAGER_SERVICE);
2001 +
2002 +		goto error_handler;
2003 +	}
2004 +
2005 +	if (error)
2006 +		goto error_handler;
2007 +
2008 +	manager = g_object_new (TRACKER_TYPE_EVOLUTION_PLUGIN, 
2009 +				"connection", connection, NULL);
2010 +
2011 +	dbus_g_object_type_install_info (G_OBJECT_TYPE (manager), 
2012 +					 &dbus_glib_tracker_evolution_plugin_object_info);
2013 +
2014 +	dbus_g_connection_register_g_object (connection, 
2015 +					     TRACKER_EVOLUTION_MANAGER_PATH, 
2016 +					     G_OBJECT (manager));
2017 +
2018 +	error_handler:
2019 +
2020 +	if (error) {
2021 +		g_warning ("Could not setup DBus, %s\n", error->message);
2022 +		disable_plugin();
2023 +		g_error_free (error);
2024 +	}
2025 +}
2026 +
2027 +static gboolean 
2028 +do_remove_or_not (gpointer key, gpointer value, gpointer user_data)
2029 +{
2030 +	if (user_data == value)
2031 +		return TRUE;
2032 +
2033 +	return FALSE;
2034 +}
2035 +
2036 +static void
2037 +service_gone (DBusGProxy *lproxy, TrackerEvolutionPlugin *plugin)
2038 +{
2039 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
2040 +	GList *copy = priv->registered_clients;
2041 +	GList *to_delete = NULL;
2042 +
2043 +	g_static_rec_mutex_lock (priv->mutex);
2044 +
2045 +	g_hash_table_foreach_remove (priv->registrars, 
2046 +				     do_remove_or_not,
2047 +				     lproxy);
2048 +
2049 +	while (copy) {
2050 +		ClientRegistry *creg = copy->data;
2051 +		if (creg->registrar == lproxy)
2052 +			to_delete = g_list_prepend (to_delete, copy);
2053 +		copy = g_list_next (copy);
2054 +	}
2055 +
2056 +	copy = to_delete;
2057 +	while (copy) {
2058 +		GList *node = copy->data;
2059 +		ClientRegistry *creg = node->data;
2060 +		priv->registered_clients = g_list_delete_link (priv->registered_clients, node);
2061 +		client_registry_info_free (creg);
2062 +		copy = g_list_next (copy);
2063 +	}
2064 +
2065 +	g_list_free (to_delete);
2066 +
2067 +	g_static_rec_mutex_unlock (priv->mutex);
2068 +}
2069 +
2070 +void 
2071 +tracker_evolution_plugin_register  (TrackerEvolutionPlugin *plugin, 
2072 +				    gchar *registrar_path,
2073 +				    guint last_checkout, 
2074 +				    DBusGMethodInvocation *context,
2075 +				    GError *derror)
2076 +{
2077 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
2078 +	gchar *sender;
2079 +	DBusGProxy *registrar;
2080 +	guint dsignal;
2081 +
2082 +	g_static_rec_mutex_lock (priv->mutex);
2083 +
2084 +	sender = dbus_g_method_get_sender (context);
2085 +
2086 +	registrar = dbus_g_proxy_new_for_name (priv->connection, sender, 
2087 +					       registrar_path,
2088 +					       TRACKER_EVOLUTION_REGISTRAR_INTERFACE);
2089 +
2090 +	g_hash_table_replace (priv->registrars, g_strdup (sender), 
2091 +			      registrar);
2092 +
2093 +	dsignal = g_signal_connect (registrar, "destroy",
2094 +				    G_CALLBACK (service_gone),
2095 +				    plugin);
2096 +
2097 +	g_static_rec_mutex_unlock (priv->mutex);
2098 +
2099 +	/* Passing uint64 over DBus ain't working :-\ */
2100 +	register_client (plugin, (guint64) last_checkout, registrar, dsignal);
2101 +
2102 +	dbus_g_method_return (context);
2103 +}
2104 +
2105 +
2106 +int
2107 +e_plugin_lib_enable (EPluginLib *ep, int enabled)
2108 +{
2109 +	g_static_rec_mutex_lock (&glock);
2110 +
2111 +	if (enabled)
2112 +		enable_plugin ();
2113 +	else
2114 +		disable_plugin ();
2115 +
2116 +	g_static_rec_mutex_unlock (&glock);
2117 +
2118 +	return 0;
2119 +}
2120 +
2121 +
2122 +static void
2123 +tracker_evolution_plugin_finalize (GObject *plugin)
2124 +{
2125 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
2126 +
2127 +	g_static_rec_mutex_lock (priv->mutex);
2128 +
2129 +	g_list_foreach (priv->registered_clients,
2130 +			(GFunc) client_registry_info_free,
2131 +			NULL);
2132 +	g_list_free (priv->registered_clients);
2133 +
2134 +	g_list_free (priv->registered_clients);
2135 +
2136 +	if (priv->registered_folders) {
2137 +		g_hash_table_destroy (priv->registered_folders);
2138 +		g_hash_table_destroy (priv->cached_folders);
2139 +		priv->cached_folders = NULL;
2140 +		priv->registered_folders = NULL;
2141 +	}
2142 +
2143 +	if (priv->registered_stores) {
2144 +		g_hash_table_destroy (priv->registered_stores);
2145 +		priv->registered_stores = NULL;
2146 +	}
2147 +
2148 +	g_object_unref (priv->accounts);
2149 +
2150 +	g_hash_table_destroy (priv->registrars);
2151 +
2152 +	g_static_rec_mutex_unlock (priv->mutex);
2153 +
2154 +	g_slice_free (GStaticRecMutex, priv->mutex);
2155 +
2156 +	G_OBJECT_CLASS (tracker_evolution_plugin_parent_class)->finalize (plugin);
2157 +}
2158 +
2159 +static void 
2160 +tracker_evolution_plugin_set_connection (TrackerEvolutionPlugin *plugin, 
2161 +					 DBusGConnection *connection)
2162 +{
2163 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
2164 +	priv->connection = connection;
2165 +}
2166 +
2167 +static void
2168 +tracker_evolution_plugin_set_property (GObject     *plugin,
2169 +				      guint         prop_id,
2170 +				      const GValue *value,
2171 +				      GParamSpec   *pspec)
2172 +{
2173 +	switch (prop_id) {
2174 +	case PROP_CONNECTION:
2175 +		tracker_evolution_plugin_set_connection (TRACKER_EVOLUTION_PLUGIN (plugin),
2176 +							 g_value_get_pointer (value));
2177 +		break;
2178 +	default:
2179 +		G_OBJECT_WARN_INVALID_PROPERTY_ID (plugin, prop_id, pspec);
2180 +	}
2181 +}
2182 +
2183 +static void
2184 +tracker_evolution_plugin_get_property (GObject   *plugin,
2185 +				      guint       prop_id,
2186 +				      GValue     *value,
2187 +				      GParamSpec *pspec)
2188 +{
2189 +	TrackerEvolutionPluginPrivate *priv;
2190 +
2191 +	priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
2192 +
2193 +	switch (prop_id) {
2194 +	case PROP_CONNECTION:
2195 +		g_value_set_pointer (value, priv->connection);
2196 +		break;
2197 +	default:
2198 +		G_OBJECT_WARN_INVALID_PROPERTY_ID (plugin, prop_id, pspec);
2199 +	}
2200 +}
2201 +
2202 +static void
2203 +tracker_evolution_plugin_class_init (TrackerEvolutionPluginClass *klass)
2204 +{
2205 +	GObjectClass *object_class = G_OBJECT_CLASS (klass);
2206 +
2207 +	object_class->finalize = tracker_evolution_plugin_finalize;
2208 +	object_class->set_property = tracker_evolution_plugin_set_property;
2209 +	object_class->get_property = tracker_evolution_plugin_get_property;
2210 +
2211 +	g_object_class_install_property (object_class,
2212 +					 PROP_CONNECTION,
2213 +					 g_param_spec_pointer ("connection",
2214 +							       "DBus connection",
2215 +							       "DBus connection",
2216 +							       G_PARAM_READWRITE |
2217 +							       G_PARAM_CONSTRUCT));
2218 +
2219 +	g_type_class_add_private (object_class, sizeof (TrackerEvolutionPluginPrivate));
2220 +}
2221 +
2222 +static void
2223 +tracker_evolution_plugin_init (TrackerEvolutionPlugin *plugin)
2224 +{
2225 +	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (plugin);
2226 +	EIterator *it;
2227 +
2228 +	priv->mutex = g_slice_new0 (GStaticRecMutex);
2229 +	g_static_rec_mutex_init (priv->mutex);
2230 +
2231 +	g_static_rec_mutex_lock (priv->mutex);
2232 +
2233 +	priv->registrars = g_hash_table_new_full (g_str_hash, g_str_equal,
2234 +						  (GDestroyNotify) g_free, 
2235 +						  (GDestroyNotify) g_object_unref);
2236 +
2237 +
2238 +	priv->cached_folders = NULL;
2239 +	priv->registered_folders = NULL;
2240 +	priv->registered_stores = NULL;
2241 +	priv->registered_clients = NULL;
2242 +
2243 +	g_static_rec_mutex_unlock (priv->mutex);
2244 +
2245 +	priv->accounts = g_object_ref (mail_config_get_accounts ());
2246 +
2247 +	for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it))
2248 +		register_account (plugin, (EAccount *) e_iterator_get (it));
2249 +
2250 +	g_object_unref (it);
2251 +
2252 +	g_signal_connect (priv->accounts, "account-added", 
2253 +			  G_CALLBACK (on_account_added), plugin);
2254 +	g_signal_connect (priv->accounts, "account-removed", 
2255 +			  G_CALLBACK (on_account_removed), plugin);
2256 +	g_signal_connect (priv->accounts, "account-changed", 
2257 +			  G_CALLBACK (on_account_changed), plugin);
2258 +}
2259 Index: src/plugins/evolution/tracker-evolution-indexer.c
2260 ===================================================================
2261 --- src/plugins/evolution/tracker-evolution-indexer.c	(revision 0)
2262 +++ src/plugins/evolution/tracker-evolution-indexer.c	(revision 0)
2263 @@ -0,0 +1,603 @@
2264 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2265 +/*
2266 + * Copyright (C) 2008, Nokia
2267 + *
2268 + * This library is free software; you can redistribute it and/or
2269 + * modify it under the terms of the GNU General Public
2270 + * License as published by the Free Software Foundation; either
2271 + * version 2 of the License, or (at your option) any later version.
2272 + *
2273 + * This library is distributed in the hope that it will be useful,
2274 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2275 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2276 + * General Public License for more details.
2277 + *
2278 + * You should have received a copy of the GNU General Public
2279 + * License along with this library; if not, write to the
2280 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2281 + * Boston, MA  02110-1301, USA.
2282 + *
2283 + * Authors:
2284 + *  Philip Van Hoof <philip@codeminded.be>
2285 + */
2286 +
2287 +#include "config.h"
2288 +
2289 +#include <string.h>
2290 +#include <fcntl.h>
2291 +#include <sys/types.h>
2292 +#include <sys/stat.h>
2293 +#include <glib.h>
2294 +#include <gio/gio.h>
2295 +#include <glib/gstdio.h>
2296 +#include <stdlib.h>
2297 +#include <stdio.h>
2298 +
2299 +#include <gmime/gmime.h>
2300 +
2301 +#include <libtracker-data/tracker-data-update.h>
2302 +
2303 +/* This is okay, we run in-process of the indexer: we can access its symbols */
2304 +#include <tracker-indexer/tracker-module.h>
2305 +#include <tracker-indexer/tracker-module-metadata-private.h>
2306 +
2307 +#include "tracker-evolution-indexer.h"
2308 +
2309 +/* These defines/renames are necessary for -glue.h */
2310 +#define tracker_evolution_registrar_set tracker_evolution_indexer_set
2311 +#define tracker_evolution_registrar_set_many tracker_evolution_indexer_set_many
2312 +#define tracker_evolution_registrar_unset_many tracker_evolution_indexer_unset_many
2313 +#define tracker_evolution_registrar_unset tracker_evolution_indexer_unset
2314 +#define tracker_evolution_registrar_cleanup tracker_evolution_indexer_cleanup
2315 +#define dbus_glib_tracker_evolution_indexer_object_info dbus_glib_tracker_evolution_registrar_object_info
2316 +
2317 +#include "tracker-evolution-registrar-glue.h"
2318 +
2319 +/* Based on data/services/email.metadata */
2320 +
2321 +#define METADATA_EMAIL_RECIPIENT     "Email:Recipient"
2322 +#define METADATA_EMAIL_DATE	     "Email:Date"
2323 +#define METADATA_EMAIL_SENDER	     "Email:Sender"
2324 +#define METADATA_EMAIL_SUBJECT	     "Email:Subject"
2325 +#define METADATA_EMAIL_SENT_TO	     "Email:SentTo"
2326 +#define METADATA_EMAIL_CC	     "Email:CC"
2327 +#define METADATA_EMAIL_TEXT	     "Email:Body"
2328 +#define METADATA_EMAIL_TAG	     "User:Keywords"
2329 +
2330 +#define TRACKER_EVOLUTION_INDEXER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_INDEXER, TrackerEvolutionIndexerPrivate))
2331 +
2332 +G_DEFINE_TYPE (TrackerEvolutionIndexer, tracker_evolution_indexer, G_TYPE_OBJECT)
2333 +
2334 +/* This runs in-process of tracker-indexer */
2335 +
2336 +static GObject *idx_indexer = NULL;
2337 +
2338 +typedef struct {
2339 +	TrackerIndexer *indexer;
2340 +} TrackerEvolutionIndexerPrivate;
2341 +
2342 +enum {
2343 +	PROP_0,
2344 +	PROP_INDEXER
2345 +};
2346 +
2347 +static void
2348 +tracker_evolution_indexer_finalize (GObject *object)
2349 +{
2350 +	TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
2351 +
2352 +	if (priv->indexer)
2353 +		g_object_unref (priv->indexer);
2354 +
2355 +	G_OBJECT_CLASS (tracker_evolution_indexer_parent_class)->finalize (object);
2356 +}
2357 +
2358 +static void
2359 +tracker_evolution_indexer_set_property (GObject      *object,
2360 +					guint         prop_id,
2361 +					const GValue *value,
2362 +					GParamSpec   *pspec)
2363 +{
2364 +	TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
2365 +
2366 +	switch (prop_id) {
2367 +
2368 +	case PROP_INDEXER:
2369 +		priv->indexer = g_value_dup_object (value);
2370 +		break;
2371 +
2372 +	default:
2373 +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2374 +		break;
2375 +	}
2376 +}
2377 +
2378 +static void
2379 +tracker_evolution_indexer_get_property (GObject    *object,
2380 +					guint       prop_id,
2381 +					GValue     *value,
2382 +					GParamSpec *pspec)
2383 +{
2384 +	TrackerEvolutionIndexerPrivate *priv;
2385 +
2386 +	priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
2387 +
2388 +	switch (prop_id) {
2389 +	case PROP_INDEXER:
2390 +		g_value_set_object (value, priv->indexer);
2391 +		break;
2392 +	default:
2393 +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2394 +		break;
2395 +	}
2396 +}
2397 +
2398 +static void
2399 +tracker_evolution_indexer_class_init (TrackerEvolutionIndexerClass *klass)
2400 +{
2401 +	GObjectClass *object_class = G_OBJECT_CLASS (klass);
2402 +
2403 +	object_class->finalize = tracker_evolution_indexer_finalize;
2404 +	object_class->set_property = tracker_evolution_indexer_set_property;
2405 +	object_class->get_property = tracker_evolution_indexer_get_property;
2406 +
2407 +	g_object_class_install_property (object_class,
2408 +					 PROP_INDEXER,
2409 +					 g_param_spec_object ("indexer",
2410 +							      "Indexer",
2411 +							      "Indexer",
2412 +							      tracker_indexer_get_type (),
2413 +							      G_PARAM_READWRITE |
2414 +							      G_PARAM_CONSTRUCT));
2415 +
2416 +	g_type_class_add_private (object_class, sizeof (TrackerEvolutionIndexerPrivate));
2417 +}
2418 +
2419 +static void
2420 +tracker_evolution_indexer_init (TrackerEvolutionIndexer *object)
2421 +{
2422 +	TrackerEvolutionIndexerPrivate *priv = TRACKER_EVOLUTION_INDEXER_GET_PRIVATE (object);
2423 +
2424 +	priv->indexer = NULL;
2425 +}
2426 +
2427 +
2428 +#if 0
2429 +static void
2430 +extract_mime_parts (GMimeObject *object,
2431 +		    gpointer     user_data)
2432 +{
2433 +	const gchar *message_subject = user_data;
2434 +	gchar *subject = NULL;
2435 +	const gchar *disposition, *filename;
2436 +	GMimePart *part;
2437 +
2438 +	if (GMIME_IS_MESSAGE_PART (object)) {
2439 +		GMimeMessage *message;
2440 +
2441 +		message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (object));
2442 +
2443 +		if (message) {
2444 +			g_mime_message_foreach_part (message, extract_mime_parts, user_data);
2445 +			g_object_unref (message);
2446 +		}
2447 +
2448 +		return;
2449 +	} else if (GMIME_IS_MULTIPART (object)) {
2450 +		g_mime_multipart_foreach (GMIME_MULTIPART (object), extract_mime_parts, user_data);
2451 +		return;
2452 +	}
2453 +
2454 +	part = GMIME_PART (object);
2455 +	disposition = g_mime_part_get_content_disposition (part);
2456 +
2457 +	if (!disposition ||
2458 +	    (g_strcmp0 (disposition, GMIME_DISPOSITION_ATTACHMENT) != 0 &&
2459 +	     g_strcmp0 (disposition, GMIME_DISPOSITION_INLINE) != 0)) {
2460 +		return;
2461 +	}
2462 +
2463 +	filename = g_mime_part_get_filename (GMIME_PART (object));
2464 +
2465 +	if (!filename ||
2466 +	    g_strcmp0 (filename, "signature.asc") == 0 ||
2467 +	    g_strcmp0 (filename, "signature.pgp") == 0) {
2468 +		return;
2469 +	}
2470 +
2471 +	if (filename) {
2472 +		GHashTable *data;
2473 +		TrackerModuleMetadata *metadata;
2474 +		gchar *subject;
2475 +
2476 +		/* This is not a path but a URI: don't use the OS's dir separator
2477 +		 * here, use the '/'. Another option is to use '#' instead of '/'
2478 +		 * here. This depends on how we want to format the URI and what
2479 +		 * Evolution can cope with as URI for an attachment (I don't 
2480 +		 * think it can cope with any attachment URI, btw). */
2481 +
2482 +		subject = g_strdup_printf ("%s/%s", message_subject, 
2483 +					   filename);
2484 +
2485 +		metadata = tracker_module_metadata_new ();
2486 +
2487 +		tracker_module_metadata_add_string (metadata, 
2488 +						    "File:Path", 
2489 +						    subject);
2490 +
2491 +		tracker_module_metadata_add_string (metadata, 
2492 +						    "File:Name", 
2493 +						    filename);
2494 +
2495 +		data = tracker_module_metadata_get_hash_table (metadata);
2496 +
2497 +		tracker_data_update_replace_service (subject, "EvolutionEmails", data);
2498 +
2499 +		g_hash_table_destroy (data);
2500 +		g_object_unref (metadata);
2501 +		g_free (subject);
2502 +	}
2503 +}
2504 +
2505 +static gchar *
2506 +get_object_encoding (GMimeObject *object)
2507 +{
2508 +	const gchar *start_encoding, *end_encoding;
2509 +	const gchar *content_type = NULL;
2510 +
2511 +	if (GMIME_IS_MESSAGE (object)) {
2512 +		content_type = g_mime_message_get_header (GMIME_MESSAGE (object), "Content-Type");
2513 +	} else if (GMIME_IS_PART (object)) {
2514 +		content_type = g_mime_part_get_content_header (GMIME_PART (object), "Content-Type");
2515 +	}
2516 +
2517 +	if (!content_type) {
2518 +		return NULL;
2519 +	}
2520 +
2521 +	start_encoding = strstr (content_type, "charset=");
2522 +
2523 +	if (!start_encoding) {
2524 +		return NULL;
2525 +	}
2526 +
2527 +	start_encoding += strlen ("charset=");
2528 +
2529 +	if (start_encoding[0] == '"') {
2530 +		/* encoding is quoted */
2531 +		start_encoding++;
2532 +		end_encoding = strstr (start_encoding, "\"");
2533 +	} else {
2534 +		end_encoding = strstr (start_encoding, ";");
2535 +	}
2536 +
2537 +	if (end_encoding) {
2538 +		return g_strndup (start_encoding, end_encoding - start_encoding);
2539 +	} else {
2540 +		return g_strdup (start_encoding);
2541 +	}
2542 +}
2543 +#endif
2544 +
2545 +static void
2546 +perform_set (TrackerEvolutionIndexer *object, 
2547 +	     const gchar *subject, 
2548 +	     const GStrv predicates, 
2549 +	     const GStrv values)
2550 +{
2551 +	guint i = 0;
2552 +	TrackerModuleMetadata *metadata;
2553 +	GHashTable *data;
2554 +
2555 +	metadata = tracker_module_metadata_new ();
2556 +
2557 +	while (predicates [i] != NULL && values[i] != NULL) {
2558 +
2559 +		/* TODO: TRACKER_EVOLUTION_PREDICATE_SEEN (!)
2560 +		 *       TRACKER_EVOLUTION_PREDICATE_JUNK (!)
2561 +		 *       TRACKER_EVOLUTION_PREDICATE_ANSWERED
2562 +		 *       TRACKER_EVOLUTION_PREDICATE_FLAGGED
2563 +		 *       TRACKER_EVOLUTION_PREDICATE_FORWARDED
2564 +		 *       TRACKER_EVOLUTION_PREDICATE_DELETED (!)
2565 +		 *       TRACKER_EVOLUTION_PREDICATE_SIZE (!) :
2566 +		 *
2567 +		 * I don't have predicates in Tracker's ontology for these. In
2568 +		 * Jürg's vstore branch we are working with Nepomuk as ontology-
2569 +		 * set. Perhaps when we merge this to that branch that we can 
2570 +		 * improve this situation. */
2571 +
2572 +
2573 +#if 0
2574 +
2575 +		/* Disabling this as I can't find any version of GMime-2.0 that
2576 +		 * wont crash on any of my test E-mails. Going to ask Garnacho
2577 +		 * to migrate to GMime-2.4 with his old Evolution support. */
2578 +
2579 +		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_FILE) == 0) {
2580 +			GMimeStream *stream;
2581 +			GMimeParser *parser;
2582 +			GMimeMessage *message;
2583 +			gint fd;
2584 +			gchar *text, *orig_text, *ptr, *encoding;
2585 +			gchar *path = g_strdup (values[i]);
2586 +			off_t offset = 0;
2587 +			gboolean is_html;
2588 +
2589 +			ptr = strstr (path, "/!");
2590 +			if (ptr) {
2591 +				offset = (off_t) atol (ptr+2);
2592 +				*ptr = '\0';
2593 +			}
2594 +
2595 +			fd = tracker_file_open (path, FALSE);
2596 +
2597 +			g_free (path);
2598 +
2599 +			if (fd == -1) 
2600 +				goto cont;
2601 +
2602 +			stream = g_mime_stream_fs_new_with_bounds (fd, offset, -1);
2603 +
2604 +			if (!stream) {
2605 +				close (fd);
2606 +				goto cont;
2607 +			}
2608 +
2609 +			parser = g_mime_parser_new_with_stream (stream);
2610 +
2611 +			if (!parser) {
2612 +				g_object_unref (stream);
2613 +				goto cont;
2614 +			}
2615 +
2616 +			g_mime_parser_set_scan_from (parser, FALSE);
2617 +
2618 +			message = g_mime_parser_construct_message (parser);
2619 +
2620 +			if (!message) {
2621 +				g_object_unref (parser);
2622 +				g_object_unref (stream);
2623 +				goto cont;
2624 +			}
2625 +
2626 +			g_mime_message_foreach_part (message,
2627 +						     extract_mime_parts,
2628 +						     subject);
2629 +
2630 +			orig_text = g_mime_message_get_body (message, TRUE, &is_html);
2631 +
2632 +			if (orig_text) {
2633 +
2634 +				encoding = get_object_encoding (GMIME_OBJECT (message));
2635 +
2636 +				if (encoding) {
2637 +					text = g_convert (text, -1, "utf8", encoding, NULL, NULL, NULL);
2638 +					g_free (orig_text);
2639 +				} else
2640 +					text = orig_text;
2641 +
2642 +				tracker_module_metadata_add_string (metadata, 
2643 +								    METADATA_EMAIL_TEXT, 
2644 +								    text);
2645 +
2646 +				g_free (text);
2647 +				g_free (encoding);
2648 +			}
2649 +
2650 +			g_object_unref (message);
2651 +			g_object_unref (parser);
2652 +			g_object_unref (stream);
2653 +		}
2654 +#endif
2655 +
2656 +		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_TAG) == 0) {
2657 +			gchar *key, *value;
2658 +
2659 +			if (!values[i] || strlen (values[i]) < 1)
2660 +				goto cont;
2661 +
2662 +			key = g_strdup (values[i]);
2663 +
2664 +			value = strchr (key, '=');
2665 +
2666 +			if (value) {
2667 +				*value = '\0';
2668 +				value++;
2669 +			}
2670 +
2671 +			/* TODO: what about value? The format of Evolution is
2672 +			 * key=value, so we can store a value too here. Is this 
2673 +			 * something Nepomuk can someday save us with? */
2674 +
2675 +			tracker_module_metadata_add_string (metadata, 
2676 +							    METADATA_EMAIL_TAG, 
2677 +							    key);
2678 +
2679 +			g_free (key);
2680 +		}
2681 +
2682 +		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_SUBJECT) == 0) {
2683 +			tracker_module_metadata_add_string (metadata, 
2684 +							    METADATA_EMAIL_SUBJECT, 
2685 +							    values[i]);
2686 +		}
2687 +
2688 +		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_SENT) == 0) {
2689 +			tracker_module_metadata_add_string (metadata, 
2690 +							    METADATA_EMAIL_DATE, 
2691 +							    values[i]);
2692 +		}
2693 +
2694 +		if (g_strcmp0 (predicates[i], METADATA_EMAIL_SENDER) == 0) {
2695 +			tracker_module_metadata_add_string (metadata, 
2696 +							    METADATA_EMAIL_SENDER, 
2697 +							    values[i]);
2698 +		}
2699 +
2700 +		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_TO) == 0) {
2701 +			tracker_module_metadata_add_string (metadata, 
2702 +							    METADATA_EMAIL_SENT_TO, 
2703 +							    values[i]);
2704 +		}
2705 +
2706 +		if (g_strcmp0 (predicates[i], TRACKER_EVOLUTION_PREDICATE_CC) == 0) {
2707 +			tracker_module_metadata_add_string (metadata, 
2708 +							    METADATA_EMAIL_CC, 
2709 +							    values[i]);
2710 +		}
2711 +
2712 +		cont:
2713 +
2714 +		i++;
2715 +	}
2716 +
2717 +	data = tracker_module_metadata_get_hash_table (metadata);
2718 +
2719 +	tracker_data_update_replace_service (subject, "EvolutionEmails", data);
2720 +
2721 +	g_hash_table_destroy (data);
2722 +	g_object_unref (metadata);
2723 +}
2724 +
2725 +static void 
2726 +perform_unset (TrackerEvolutionIndexer *object, 
2727 +	       const gchar *subject)
2728 +{
2729 +	tracker_data_update_delete_service_by_path (subject, "EvolutionEmails"); 
2730 +}
2731 +
2732 +static void
2733 +perform_cleanup (TrackerEvolutionIndexer *object)
2734 +{
2735 +	tracker_data_update_delete_service_all ("EvolutionEmails");
2736 +}
2737 +
2738 +void
2739 +tracker_evolution_indexer_set (TrackerEvolutionIndexer *object, 
2740 +			       const gchar *subject, 
2741 +			       const GStrv predicates,
2742 +			       const GStrv values,
2743 +			       DBusGMethodInvocation *context,
2744 +			       GError *derror)
2745 +{
2746 +	dbus_async_return_if_fail (subject != NULL, context);
2747 +
2748 +	if (predicates && values) {
2749 +
2750 +		dbus_async_return_if_fail (g_strv_length (predicates) == 
2751 +					   g_strv_length (values), context);
2752 +
2753 +		perform_set (object, subject, predicates, values);
2754 +	}
2755 +
2756 +	dbus_g_method_return (context);
2757 +}
2758 +
2759 +void
2760 +tracker_evolution_indexer_set_many (TrackerEvolutionIndexer *object, 
2761 +				    const GStrv subjects, 
2762 +				    const GPtrArray *predicates,
2763 +				    const GPtrArray *values,
2764 +				    DBusGMethodInvocation *context,
2765 +				    GError *derror)
2766 +{
2767 +	guint len;
2768 +	guint i = 0;
2769 +
2770 +	dbus_async_return_if_fail (subjects != NULL, context);
2771 +	dbus_async_return_if_fail (predicates != NULL, context);
2772 +	dbus_async_return_if_fail (values != NULL, context);
2773 +
2774 +	len = g_strv_length (subjects);
2775 +
2776 +	dbus_async_return_if_fail (len == predicates->len, context);
2777 +	dbus_async_return_if_fail (len == values->len, context);
2778 +
2779 +	while (subjects[i] != NULL) {
2780 +		GStrv preds = g_ptr_array_index (predicates, i);
2781 +		GStrv vals = g_ptr_array_index (values, i);
2782 +
2783 +		perform_set (object, subjects[i], preds, vals);
2784 +
2785 +		i++;
2786 +	}
2787 +
2788 +	dbus_g_method_return (context);
2789 +}
2790 +
2791 +void
2792 +tracker_evolution_indexer_unset_many (TrackerEvolutionIndexer *object, 
2793 +				      const GStrv subjects, 
2794 +				      DBusGMethodInvocation *context,
2795 +				      GError *derror)
2796 +{
2797 +	guint i = 0;
2798 +
2799 +	dbus_async_return_if_fail (subjects != NULL, context);
2800 +
2801 +	while (subjects[i] != NULL) {
2802 +
2803 +		perform_unset (object, subjects[i]);
2804 +
2805 +		i++;
2806 +	}
2807 +
2808 +	dbus_g_method_return (context);
2809 +}
2810 +
2811 +void
2812 +tracker_evolution_indexer_unset (TrackerEvolutionIndexer *object, 
2813 +				 const gchar *subject, 
2814 +				 DBusGMethodInvocation *context,
2815 +				 GError *derror)
2816 +{
2817 +	dbus_async_return_if_fail (subject != NULL, context);
2818 +
2819 +	perform_unset (object, subject);
2820 +
2821 +	dbus_g_method_return (context);
2822 +}
2823 +
2824 +void
2825 +tracker_evolution_indexer_cleanup (TrackerEvolutionIndexer *object, 
2826 +				   DBusGMethodInvocation *context,
2827 +				   GError *derror)
2828 +{
2829 +	perform_cleanup (object);
2830 +
2831 +	dbus_g_method_return (context);
2832 +}
2833 +
2834 +void
2835 +tracker_evolution_storer_init (TrackerConfig *config, 
2836 +			       TrackerIndexer *indexer)
2837 +{
2838 +	GError *error = NULL;
2839 +	DBusGConnection *connection;
2840 +
2841 +	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
2842 +
2843 +	if (!error) {
2844 +		idx_indexer = g_object_new (TRACKER_TYPE_EVOLUTION_INDEXER, 
2845 +					    "indexer", indexer, NULL);
2846 +
2847 +		dbus_g_object_type_install_info (G_OBJECT_TYPE (idx_indexer), 
2848 +						 &dbus_glib_tracker_evolution_indexer_object_info);
2849 +
2850 +		dbus_g_connection_register_g_object (connection, 
2851 +						     TRACKER_EVOLUTION_INDEXER_PATH, 
2852 +						     idx_indexer);
2853 +	}
2854 +
2855 +	if (error) {
2856 +		g_critical ("Can't init DBus for Evolution support: %s", error->message);
2857 +		g_error_free (error);
2858 +	}
2859 +}
2860 +
2861 +void
2862 +tracker_evolution_storer_shutdown (void)
2863 +{
2864 +	if (idx_indexer)
2865 +		g_object_unref (idx_indexer);
2866 +}
2867 Index: src/plugins/evolution/tracker-evolution-registrar.xml
2868 ===================================================================
2869 --- src/plugins/evolution/tracker-evolution-registrar.xml	(revision 0)
2870 +++ src/plugins/evolution/tracker-evolution-registrar.xml	(revision 0)
2871 @@ -0,0 +1,34 @@
2872 +<?xml version="1.0" encoding="UTF-8"?>
2873 +<node name="/">
2874 +  <interface name="org.gnome.evolution.metadata.Registrar">
2875 +
2876 +  <method name="Set">
2877 +      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
2878 +      <arg type="s" name="subject" direction="in" />
2879 +      <arg type="as" name="predicates" direction="in" />
2880 +      <arg type="as" name="values" direction="in" />
2881 +    </method>
2882 +
2883 +    <method name="SetMany">
2884 +      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
2885 +      <arg type="as" name="subjects" direction="in" />
2886 +      <arg type="aas" name="predicates" direction="in" />
2887 +      <arg type="aas" name="values" direction="in" />
2888 +    </method>
2889 +
2890 +    <method name="Unset">
2891 +      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
2892 +      <arg type="s" name="subject" direction="in" />
2893 +    </method>
2894 +
2895 +    <method name="UnsetMany">
2896 +      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
2897 +      <arg type="as" name="subjects" direction="in" />
2898 +    </method>
2899 +
2900 +    <method name="Cleanup">
2901 +      <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
2902 +    </method>
2903 +
2904 +  </interface>
2905 +</node>
2906 Index: src/plugins/evolution/tracker-evolution.c
2907 ===================================================================
2908 --- src/plugins/evolution/tracker-evolution.c	(revision 0)
2909 +++ src/plugins/evolution/tracker-evolution.c	(revision 0)
2910 @@ -0,0 +1,357 @@
2911 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2912 +/*
2913 + * Copyright (C) 2008, Nokia
2914 + *
2915 + * This library is free software; you can redistribute it and/or
2916 + * modify it under the terms of the GNU General Public
2917 + * License as published by the Free Software Foundation; either
2918 + * version 2 of the License, or (at your option) any later version.
2919 + *
2920 + * This library is distributed in the hope that it will be useful,
2921 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2922 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2923 + * General Public License for more details.
2924 + *
2925 + * You should have received a copy of the GNU General Public
2926 + * License along with this library; if not, write to the
2927 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2928 + * Boston, MA  02110-1301, USA.
2929 + *
2930 + * Authors:
2931 + *  Philip Van Hoof <philip@codeminded.be>
2932 + */
2933 +
2934 +#include "config.h"
2935 +
2936 +#include <string.h>
2937 +#include <time.h>
2938 +
2939 +#include <libtracker-data/tracker-data-manager.h>
2940 +
2941 +#include "tracker-evolution.h"
2942 +#include "tracker-evolution-registrar.h"
2943 +
2944 +typedef struct {
2945 +	TrackerConfig *config;
2946 +	DBusGConnection *connection;
2947 +	gboolean is_enabled;
2948 +	DBusGProxy *dbus_proxy;
2949 +	DBusGProxy *manager_proxy;
2950 +	GObject *object;
2951 +	gboolean deactivating;
2952 +} EvolutionSupportPrivate;
2953 +
2954 +static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
2955 +
2956 +static guint
2957 +get_stored_last_checkout (void)
2958 +{
2959 +	return (guint) tracker_data_manager_get_db_option_int ("EvolutionLastCheckout");
2960 +}
2961 +
2962 +static void
2963 +set_stored_last_checkout (guint last_checkout)
2964 +{
2965 +	tracker_data_manager_set_db_option_int ("EvolutionLastCheckout", (gint) last_checkout);
2966 +}
2967 +
2968 +static void
2969 +deactivate_registrar (void)
2970 +{
2971 +	EvolutionSupportPrivate *private;
2972 +
2973 +	private = g_static_private_get (&private_key);
2974 +	g_return_if_fail (private != NULL);
2975 +
2976 +	set_stored_last_checkout (time(NULL));
2977 +
2978 +	if (private->object) {
2979 +		g_object_unref (private->object);
2980 +		private->object = NULL;
2981 +	}
2982 +
2983 +	if (private->manager_proxy && !private->deactivating)
2984 +		g_object_unref (private->manager_proxy);
2985 +
2986 +	private->manager_proxy = NULL;
2987 +}
2988 +
2989 +static void
2990 +deactivate_dbus_client (void)
2991 +{
2992 +	EvolutionSupportPrivate *private;
2993 +
2994 +	private = g_static_private_get (&private_key);
2995 +	g_return_if_fail (private != NULL);
2996 +
2997 +	deactivate_registrar ();
2998 +
2999 +	if (private->dbus_proxy) {
3000 +		g_object_unref (private->dbus_proxy);
3001 +		private->dbus_proxy = NULL;
3002 +	}
3003 +}
3004 +
3005 +static void
3006 +on_manager_destroy (DBusGProxy *proxy, gpointer user_data)
3007 +{
3008 +	EvolutionSupportPrivate *private;
3009 +	gboolean old_setting;
3010 +
3011 +	private = g_static_private_get (&private_key);
3012 +	g_return_if_fail (private != NULL);
3013 +
3014 +	old_setting = private->deactivating;
3015 +
3016 +	private->deactivating = TRUE;
3017 +	deactivate_registrar ();
3018 +	private->deactivating = old_setting;
3019 +}
3020 +
3021 +
3022 +static void
3023 +activate_registrar (void)
3024 +{
3025 +	EvolutionSupportPrivate *private;
3026 +
3027 +	private = g_static_private_get (&private_key);
3028 +	g_return_if_fail (private != NULL);
3029 +
3030 +	if (private->object)
3031 +		return;
3032 +
3033 +	private->manager_proxy = 
3034 +		dbus_g_proxy_new_for_name (private->connection,
3035 +					   TRACKER_EVOLUTION_MANAGER_SERVICE,
3036 +					   TRACKER_EVOLUTION_MANAGER_PATH,
3037 +					   TRACKER_EVOLUTION_MANAGER_INTERFACE);
3038 +
3039 +	/* If while we had a proxy for the manager the manager shut itself down,
3040 +	 * then we'll get rid of our registrar too, in on_manager_destroy */
3041 +
3042 +	g_signal_connect (private->manager_proxy, "destroy",
3043 +			  G_CALLBACK (on_manager_destroy), NULL);
3044 +
3045 +	if (private->manager_proxy) {
3046 +		GError *error = NULL;
3047 +		guint result;
3048 +
3049 +		/* Creation of the registrar */
3050 +		if (!org_freedesktop_DBus_request_name (private->dbus_proxy, 
3051 +							   TRACKER_EVOLUTION_REGISTRAR_SERVICE,
3052 +							   DBUS_NAME_FLAG_DO_NOT_QUEUE,
3053 +							   &result, &error)) {
3054 +			g_critical ("Could not setup DBus, %s in use\n", TRACKER_EVOLUTION_REGISTRAR_SERVICE);
3055 +			goto error_handler;
3056 +		}
3057 +
3058 +		if (error)
3059 +			goto error_handler;
3060 +
3061 +		private->object = g_object_new (TRACKER_TYPE_EVOLUTION_REGISTRAR, 
3062 +						"connection", private->connection, 
3063 +						NULL);
3064 +
3065 +		dbus_g_object_type_install_info (G_OBJECT_TYPE (private->object), 
3066 +						 &registrar_methods);
3067 +		dbus_g_connection_register_g_object (private->connection, 
3068 +						     TRACKER_EVOLUTION_REGISTRAR_PATH, 
3069 +						     private->object);
3070 +
3071 +		/* Registration of the registrar to the manager */
3072 +		dbus_g_proxy_call_no_reply (private->manager_proxy, "Register",
3073 +					    G_TYPE_OBJECT, private->object, /* TRACKER_EVOLUTION_REGISTRAR_PATH, */
3074 +					    G_TYPE_UINT, get_stored_last_checkout (),
3075 +					    G_TYPE_INVALID,
3076 +					    G_TYPE_INVALID);
3077 +
3078 +		error_handler:
3079 +
3080 +		if (error) {
3081 +			g_critical ("Could not setup DBus, %s\n", error->message);
3082 +			g_error_free (error);
3083 +		}
3084 +	}
3085 +}
3086 +
3087 +static void
3088 +name_owner_changed_cb (DBusGProxy *proxy, 
3089 +		       gchar *name, 
3090 +		       gchar *old_owner, 
3091 +		       gchar *new_owner, 
3092 +		       gpointer user_data)
3093 +{
3094 +
3095 +	/* If we receive a NameOwnerChanged about the manager's service */
3096 +
3097 +	if (g_strcmp0 (name, TRACKER_EVOLUTION_MANAGER_SERVICE) == 0) {
3098 +		if (tracker_is_empty_string (new_owner) && !tracker_is_empty_string (old_owner))
3099 +			deactivate_registrar ();
3100 +		if (tracker_is_empty_string (old_owner) && !tracker_is_empty_string (new_owner))
3101 +			activate_registrar ();
3102 +	}
3103 +}
3104 +
3105 +static void
3106 +list_names_reply_cb (DBusGProxy     *proxy,
3107 +		     DBusGProxyCall *call,
3108 +		     gpointer        user_data)
3109 +{
3110 +	GError *error = NULL;
3111 +	GStrv names = NULL;
3112 +	guint i = 0;
3113 +
3114 +	dbus_g_proxy_end_call (proxy, call, &error,
3115 +			       G_TYPE_STRV, &names,
3116 +			       G_TYPE_INVALID);
3117 +
3118 +	if (error) {
3119 +		g_warning ("%s", error->message);
3120 +		g_error_free (error);
3121 +		if (names)
3122 +			g_strfreev (names); 
3123 +		return;
3124 +	}
3125 +
3126 +	while (names[i] != NULL) {
3127 +		/* If the manager's service is found, start the registrar */
3128 +		if (g_strcmp0 (names[i], TRACKER_EVOLUTION_MANAGER_SERVICE) == 0) {
3129 +			activate_registrar ();
3130 +			break;
3131 +		}
3132 +		i++;
3133 +	}
3134 +
3135 +	g_strfreev (names); 
3136 +}
3137 +
3138 +static void
3139 +activate_dbus_client (void)
3140 +{
3141 +	EvolutionSupportPrivate *private;
3142 +
3143 +	private = g_static_private_get (&private_key);
3144 +	g_return_if_fail (private != NULL);
3145 +
3146 +	private->dbus_proxy = dbus_g_proxy_new_for_name (private->connection, 
3147 +							 DBUS_SERVICE_DBUS,
3148 +							 DBUS_PATH_DBUS,
3149 +							 DBUS_INTERFACE_DBUS);
3150 +
3151 +	/* We listen for NameOwnerChanged to know when the manager's service 
3152 +	 * comes up and to know when it goes down */
3153 +
3154 +	dbus_g_proxy_add_signal (private->dbus_proxy, "NameOwnerChanged",
3155 +				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
3156 +				 G_TYPE_INVALID);
3157 +
3158 +	dbus_g_proxy_connect_signal (private->dbus_proxy, "NameOwnerChanged",
3159 +				     G_CALLBACK (name_owner_changed_cb),
3160 +				     NULL, NULL);
3161 +
3162 +	/* If the manager service is up and running, then list_names_reply_cb
3163 +	 * will execute activate_registrar, as it'll appear in the results of
3164 +	 * the ListNames DBus function. If not then we will just wait for the
3165 +	 * NameOwnerChanged to emit that the manager's service has came up. */
3166 +
3167 +	dbus_g_proxy_begin_call (private->dbus_proxy, "ListNames",
3168 +				 list_names_reply_cb, NULL, NULL,
3169 +				 G_TYPE_INVALID,
3170 +				 G_TYPE_INVALID);
3171 +}
3172 +
3173 +static gboolean 
3174 +is_enabled (TrackerConfig *config)
3175 +{
3176 +	/* If none of the disabled modules include the Evolution module,
3177 +	 * we assume we are enabled in the configuration. */
3178 +
3179 +	return (g_slist_find_custom (tracker_config_get_disabled_modules (config),
3180 +				    "Evolution",
3181 +				    (GCompareFunc) g_strcmp0) != NULL);
3182 +}
3183 +
3184 +static void 
3185 +disabled_notify (GObject    *pspec,
3186 +		 GParamSpec *gobject,
3187 +		 gpointer    user_data)
3188 +{
3189 +	EvolutionSupportPrivate *private;
3190 +	gboolean new_value;
3191 +
3192 +	private = g_static_private_get (&private_key);
3193 +	g_return_if_fail (private != NULL);
3194 +
3195 +	new_value = is_enabled (private->config);
3196 +
3197 +	if (private->is_enabled != new_value) {
3198 +		if (private->is_enabled) {
3199 +			/* If we were enabled, disable */
3200 +			deactivate_dbus_client ();
3201 +		} else {
3202 +			/* If we were disabled, enable */
3203 +			activate_dbus_client ();
3204 +		}
3205 +		private->is_enabled = new_value;
3206 +	}
3207 +
3208 +	g_message ("Evolution support service %s", 
3209 +		   private->is_enabled ? "enabled" : "disabled");
3210 +}
3211 +
3212 +static void
3213 +free_private (EvolutionSupportPrivate *private)
3214 +{
3215 +	g_object_unref (private->config);
3216 +	g_free (private);
3217 +}
3218 +
3219 +void
3220 +tracker_evolution_init (TrackerConfig *config)
3221 +{
3222 +	DBusGConnection *connection;
3223 +	GError *error = NULL;
3224 +
3225 +	connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
3226 +
3227 +	if (!error) {
3228 +		EvolutionSupportPrivate *private;
3229 +
3230 +		private = g_new0 (EvolutionSupportPrivate, 1);
3231 +
3232 +		private->deactivating = FALSE;
3233 +		private->config = g_object_ref (config);
3234 +		private->is_enabled = is_enabled (config);
3235 +		private->connection = connection;
3236 +
3237 +		g_static_private_set (&private_key,
3238 +				      private,
3239 +				      (GDestroyNotify) free_private);
3240 +
3241 +		/* Hook configuration changes */
3242 +		g_signal_connect (private->config, "notify::disabled-modules",
3243 +				  G_CALLBACK (disabled_notify), 
3244 +				  NULL);
3245 +
3246 +		/* If in configuration we are enabled now */
3247 +		if (private->is_enabled)
3248 +			activate_dbus_client ();
3249 +	} else {
3250 +		g_critical ("Could not setup DBus, %s\n", error->message);
3251 +		g_error_free (error);
3252 +	}
3253 +}
3254 +
3255 +void
3256 +tracker_evolution_shutdown ()
3257 +{
3258 +	EvolutionSupportPrivate *private;
3259 +
3260 +	private = g_static_private_get (&private_key);
3261 +	g_return_if_fail (private != NULL);
3262 +
3263 +	if (private->is_enabled)
3264 +		deactivate_dbus_client ();
3265 +
3266 +	g_static_private_set (&private_key, NULL, NULL);
3267 +}
3268 Index: src/plugins/evolution/tracker-evolution-registrar.c
3269 ===================================================================
3270 --- src/plugins/evolution/tracker-evolution-registrar.c	(revision 0)
3271 +++ src/plugins/evolution/tracker-evolution-registrar.c	(revision 0)
3272 @@ -0,0 +1,245 @@
3273 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3274 +/*
3275 + * Copyright (C) 2008, Nokia
3276 + *
3277 + * This library is free software; you can redistribute it and/or
3278 + * modify it under the terms of the GNU General Public
3279 + * License as published by the Free Software Foundation; either
3280 + * version 2 of the License, or (at your option) any later version.
3281 + *
3282 + * This library is distributed in the hope that it will be useful,
3283 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3284 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3285 + * General Public License for more details.
3286 + *
3287 + * You should have received a copy of the GNU General Public
3288 + * License along with this library; if not, write to the
3289 + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
3290 + * Boston, MA  02110-1301, USA.
3291 + *
3292 + * Authors:
3293 + *  Philip Van Hoof <philip@codeminded.be>
3294 + */
3295 +
3296 +#include "config.h"
3297 +
3298 +#include <libtracker-data/tracker-data-update.h>
3299 +#define __TRACKER_EVOLUTION_REGISTRAR_C__
3300 +#include "tracker-evolution-registrar.h"
3301 +#include "tracker-evolution-registrar-glue.h"
3302 +
3303 +const DBusGMethodInfo *registrar_methods = dbus_glib_tracker_evolution_registrar_methods;
3304 +
3305 +#define TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EVOLUTION_REGISTRAR, TrackerEvolutionRegistrarPrivate))
3306 +
3307 +G_DEFINE_TYPE (TrackerEvolutionRegistrar, tracker_evolution_registrar, G_TYPE_OBJECT)
3308 +
3309 +/* This runs in-process of trackerd. It simply proxies everything to the indexer
3310 + * who wont always be running. Which is why this is needed (trackerd is always
3311 + * running, so it's more suitable to respond to Evolution's requests). */
3312 +
3313 +typedef struct {
3314 +	DBusGProxy *idx_proxy;
3315 +	DBusGConnection *connection;
3316 +} TrackerEvolutionRegistrarPrivate;
3317 +
3318 +enum {
3319 +	PROP_0,
3320 +	PROP_CONNECTION
3321 +};
3322 +
3323 +static void
3324 +tracker_evolution_registrar_finalize (GObject *object)
3325 +{
3326 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3327 +
3328 +	if (priv->idx_proxy)
3329 +		g_object_unref (priv->idx_proxy);
3330 +
3331 +	G_OBJECT_CLASS (tracker_evolution_registrar_parent_class)->finalize (object);
3332 +}
3333 +
3334 +static void 
3335 +tracker_evolution_registrar_set_connection (TrackerEvolutionRegistrar *object, 
3336 +					    DBusGConnection *connection)
3337 +{
3338 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3339 +
3340 +	priv->connection = connection; /* weak */
3341 +
3342 +	priv->idx_proxy = dbus_g_proxy_new_for_name (priv->connection, 
3343 +						     "org.freedesktop.Tracker.Indexer",
3344 +						     TRACKER_EVOLUTION_INDEXER_PATH,
3345 +						     TRACKER_EVOLUTION_REGISTRAR_INTERFACE);
3346 +}
3347 +
3348 +static void
3349 +tracker_evolution_registrar_set_property (GObject      *object,
3350 +					  guint         prop_id,
3351 +					  const GValue *value,
3352 +					  GParamSpec   *pspec)
3353 +{
3354 +	switch (prop_id) {
3355 +	case PROP_CONNECTION:
3356 +		tracker_evolution_registrar_set_connection (TRACKER_EVOLUTION_REGISTRAR (object),
3357 +							    g_value_get_pointer (value));
3358 +		break;
3359 +	default:
3360 +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3361 +	}
3362 +}
3363 +
3364 +static void
3365 +tracker_evolution_registrar_get_property (GObject    *object,
3366 +					  guint       prop_id,
3367 +					  GValue     *value,
3368 +					  GParamSpec *pspec)
3369 +{
3370 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3371 +
3372 +	switch (prop_id) {
3373 +	case PROP_CONNECTION:
3374 +		g_value_set_pointer (value, priv->connection);
3375 +		break;
3376 +	default:
3377 +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3378 +	}
3379 +}
3380 +
3381 +static void
3382 +tracker_evolution_registrar_class_init (TrackerEvolutionRegistrarClass *klass)
3383 +{
3384 +	GObjectClass *object_class = G_OBJECT_CLASS (klass);
3385 +
3386 +	object_class->finalize = tracker_evolution_registrar_finalize;
3387 +	object_class->set_property = tracker_evolution_registrar_set_property;
3388 +	object_class->get_property = tracker_evolution_registrar_get_property;
3389 +
3390 +	g_object_class_install_property (object_class,
3391 +					 PROP_CONNECTION,
3392 +					 g_param_spec_pointer ("connection",
3393 +							       "DBus connection",
3394 +							       "DBus connection",
3395 +							       G_PARAM_READWRITE |
3396 +							       G_PARAM_CONSTRUCT));
3397 +
3398 +	g_type_class_add_private (object_class, sizeof (TrackerEvolutionRegistrarPrivate));
3399 +}
3400 +
3401 +static void
3402 +tracker_evolution_registrar_init (TrackerEvolutionRegistrar *object)
3403 +{
3404 +}
3405 +
3406 +void
3407 +tracker_evolution_registrar_set (TrackerEvolutionRegistrar *object, 
3408 +				 const gchar *subject, 
3409 +				 const GStrv predicates,
3410 +				 const GStrv values,
3411 +				 DBusGMethodInvocation *context,
3412 +				 GError *derror)
3413 +{
3414 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3415 +
3416 +	dbus_async_return_if_fail (subject != NULL, context);
3417 +
3418 +	if (predicates && values) {
3419 +
3420 +		dbus_async_return_if_fail (g_strv_length (predicates) == 
3421 +					   g_strv_length (values), context);
3422 +
3423 +		dbus_g_proxy_call_no_reply (priv->idx_proxy,
3424 +					    "Set",
3425 +					    G_TYPE_STRING, subject,
3426 +					    G_TYPE_STRV, predicates,
3427 +					    G_TYPE_STRV, values,
3428 +					    G_TYPE_INVALID, 
3429 +					    G_TYPE_INVALID);
3430 +	}
3431 +
3432 +	dbus_g_method_return (context);
3433 +}
3434 +
3435 +void
3436 +tracker_evolution_registrar_set_many (TrackerEvolutionRegistrar *object, 
3437 +				      const GStrv subjects, 
3438 +				      const GPtrArray *predicates,
3439 +				      const GPtrArray *values,
3440 +				      DBusGMethodInvocation *context,
3441 +				      GError *derror)
3442 +{
3443 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3444 +	guint len;
3445 +
3446 +	dbus_async_return_if_fail (subjects != NULL, context);
3447 +	dbus_async_return_if_fail (predicates != NULL, context);
3448 +	dbus_async_return_if_fail (values != NULL, context);
3449 +
3450 +	len = g_strv_length (subjects);
3451 +
3452 +	dbus_async_return_if_fail (len == predicates->len, context);
3453 +	dbus_async_return_if_fail (len == values->len, context);
3454 +
3455 +	dbus_g_proxy_call_no_reply (priv->idx_proxy,
3456 +				    "SetMany",
3457 +				    G_TYPE_STRV, subjects,
3458 +				    TRACKER_TYPE_G_STRV_ARRAY, predicates,
3459 +				    TRACKER_TYPE_G_STRV_ARRAY, values,
3460 +				    G_TYPE_INVALID, 
3461 +				    G_TYPE_INVALID);
3462 +
3463 +	dbus_g_method_return (context);
3464 +}
3465 +
3466 +void
3467 +tracker_evolution_registrar_unset_many (TrackerEvolutionRegistrar *object, 
3468 +					const GStrv subjects, 
3469 +					DBusGMethodInvocation *context,
3470 +					GError *derror)
3471 +{
3472 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3473 +
3474 +	dbus_async_return_if_fail (subjects != NULL, context);
3475 +
3476 +	dbus_g_proxy_call_no_reply (priv->idx_proxy,
3477 +				    "UnsetMany",
3478 +				    G_TYPE_STRV, subjects,
3479 +				    G_TYPE_INVALID, 
3480 +				    G_TYPE_INVALID);
3481 +
3482 +	dbus_g_method_return (context);
3483 +}
3484 +
3485 +void
3486 +tracker_evolution_registrar_unset (TrackerEvolutionRegistrar *object, 
3487 +				   const gchar *subject, 
3488 +				   DBusGMethodInvocation *context,
3489 +				   GError *derror)
3490 +{
3491 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3492 +
3493 +	dbus_async_return_if_fail (subject != NULL, context);
3494 +
3495 +	dbus_g_proxy_call_no_reply (priv->idx_proxy,
3496 +				    "Unset",
3497 +				    G_TYPE_STRING, subject,
3498 +				    G_TYPE_INVALID, 
3499 +				    G_TYPE_INVALID);
3500 +
3501 +	dbus_g_method_return (context);
3502 +}
3503 +
3504 +void
3505 +tracker_evolution_registrar_cleanup (TrackerEvolutionRegistrar *object, 
3506 +				     DBusGMethodInvocation *context,
3507 +				     GError *derror)
3508 +{
3509 +	TrackerEvolutionRegistrarPrivate *priv = TRACKER_EVOLUTION_REGISTRAR_GET_PRIVATE (object);
3510 +
3511 +	dbus_g_proxy_call_no_reply (priv->idx_proxy,
3512 +				    "Cleanup",
3513 +				    G_TYPE_INVALID, 
3514 +				    G_TYPE_INVALID);
3515 +
3516 +	dbus_g_method_return (context);
3517 +}
3518 Index: src/plugins/Makefile.am
3519 ===================================================================
3520 --- src/plugins/Makefile.am	(revision 0)
3521 +++ src/plugins/Makefile.am	(revision 0)
3522 @@ -0,0 +1,6 @@
3523 +SUBDIRS = .
3524 +
3525 +if HAVE_EVOLUTION_PLUGIN
3526 +SUBDIRS += evolution
3527 +endif
3528 +
3529 Index: src/tracker-indexer/tracker-main.c
3530 ===================================================================
3531 --- src/tracker-indexer/tracker-main.c	(revision 2782)
3532 +++ src/tracker-indexer/tracker-main.c	(working copy)
3533 @@ -44,7 +44,10 @@
3534  
3535  #include <libtracker-data/tracker-data-update.h>
3536  #include <libtracker-data/tracker-turtle.h>
3537 +#include <libtracker-data/tracker-data-manager.h>
3538  
3539 +#include <plugins/evolution/tracker-evolution-indexer.h>
3540 +
3541  #include "tracker-dbus.h"
3542  #include "tracker-indexer.h"
3543  
3544 @@ -254,11 +257,14 @@
3545  main (gint argc, gchar *argv[])
3546  {
3547  	TrackerConfig *config;
3548 +	TrackerLanguage *language;
3549  	TrackerIndexer *indexer;
3550  	TrackerDBManagerFlags flags = 0;
3551  	GOptionContext *context;
3552  	GError *error = NULL;
3553  	gchar *filename;
3554 +	TrackerDBIndex *file_index;
3555 +	TrackerDBIndex *email_index;
3556  
3557  	g_type_init ();
3558  
3559 @@ -296,6 +302,7 @@
3560  
3561  	/* Initialize logging */
3562  	config = tracker_config_new ();
3563 +	language = tracker_language_new (config);
3564  
3565  	if (verbosity > -1) {
3566  		tracker_config_set_verbosity (config, verbosity);
3567 @@ -371,6 +378,15 @@
3568                  tracker_indexer_process_modules (indexer, modules);
3569          }
3570  
3571 +	file_index = tracker_db_index_manager_get_index (TRACKER_DB_INDEX_FILE);
3572 +	email_index = tracker_db_index_manager_get_index (TRACKER_DB_INDEX_EMAIL);
3573 +
3574 +	tracker_data_manager_init (config, language, file_index, email_index);
3575 +
3576 +#ifdef HAVE_EVOLUTION_PLUGIN
3577 +	tracker_evolution_storer_init (config, indexer);
3578 +#endif
3579 +
3580  	tracker_turtle_init ();
3581  
3582  	g_message ("Starting...");
3583 @@ -383,15 +399,24 @@
3584  
3585  	tracker_turtle_shutdown ();
3586  
3587 +
3588  	if (quit_timeout_id) {
3589  		g_source_remove (quit_timeout_id);
3590  	}
3591  
3592  	g_main_loop_unref (main_loop);
3593  	g_object_unref (indexer);
3594 +
3595  	g_object_unref (config);
3596 +	g_object_unref (language);
3597  
3598 -        tracker_thumbnailer_shutdown ();
3599 +	tracker_data_manager_shutdown ();
3600 +
3601 +#ifdef HAVE_EVOLUTION_PLUGIN
3602 +	tracker_evolution_storer_shutdown ();
3603 +#endif
3604 +
3605 +	tracker_thumbnailer_shutdown ();
3606  	tracker_dbus_shutdown ();
3607  	tracker_db_index_manager_shutdown ();
3608  	tracker_db_manager_shutdown ();
3609 Index: src/tracker-indexer/modules/evolution.c
3610 ===================================================================
3611 --- src/tracker-indexer/modules/evolution.c	(revision 2782)
3612 +++ src/tracker-indexer/modules/evolution.c	(working copy)
3613 @@ -26,7 +26,10 @@
3614  
3615  #include "evolution-pop.h"
3616  #include "evolution-imap.h"
3617 +
3618 +#ifndef HAVE_EVOLUTION_PLUGIN
3619  #include "evolution-imap-db.h"
3620 +#endif
3621  
3622  typedef enum MailStorageType MailStorageType;
3623  
3624 @@ -34,7 +37,9 @@
3625  	MAIL_STORAGE_NONE,
3626  	MAIL_STORAGE_LOCAL,
3627  	MAIL_STORAGE_IMAP,
3628 +#ifndef HAVE_EVOLUTION_PLUGIN
3629  	MAIL_STORAGE_IMAP_DB
3630 +#endif
3631  };
3632  
3633  static gchar *local_dir = NULL;
3634 @@ -76,9 +81,12 @@
3635  	} else if (g_str_has_prefix (path, imap_dir)) {
3636  		if (strcmp (basenam, "summary") == 0) {
3637  			type = MAIL_STORAGE_IMAP;
3638 -		} else if (strcmp (basenam, "folders.db") == 0) {
3639 +		}
3640 +#ifndef HAVE_EVOLUTION_PLUGIN
3641 +		else if (strcmp (basenam, "folders.db") == 0) {
3642  			type = MAIL_STORAGE_IMAP_DB;
3643  		}
3644 +#endif
3645  	}
3646  
3647  	/* Exclude non wanted folders */
3648 @@ -110,9 +118,12 @@
3649                  return tracker_evolution_pop_file_new (file);
3650          } else if (type == MAIL_STORAGE_IMAP) {
3651                  return tracker_evolution_imap_file_new (file);
3652 -        } else if (type == MAIL_STORAGE_IMAP_DB) {
3653 +        }
3654 +#ifndef HAVE_EVOLUTION_PLUGIN
3655 +	else if (type == MAIL_STORAGE_IMAP_DB) {
3656  		return tracker_evolution_imap_db_file_new (file);
3657  	}
3658 +#endif
3659  
3660          return NULL;
3661  }
3662 Index: src/tracker-indexer/Makefile.am
3663 ===================================================================
3664 --- src/tracker-indexer/Makefile.am	(revision 2782)
3665 +++ src/tracker-indexer/Makefile.am	(working copy)
3666 @@ -17,6 +17,7 @@
3667  	$(RAPTOR_CFLAGS)						\
3668  	$(GMODULE_CFLAGS)
3669  
3670 +
3671  libtracker_moduledir = $(libdir)/tracker
3672  libtracker_moduleincludedir=$(includedir)/tracker-1.0/libtracker-module/
3673  libtracker_module_LTLIBRARIES = libtracker-module.la
3674 @@ -55,6 +56,7 @@
3675  	$(top_builddir)/src/libtracker-db/libtracker-db.la 		\
3676  	$(top_builddir)/src/libtracker-common/libtracker-common.la 	\
3677  	$(top_builddir)/src/libstemmer/libstemmer.la	 		\
3678 +	$(top_builddir)/src/plugins/evolution/libtracker-evolution-indexer.la \
3679  	$(trackerd_win_libs)						\
3680  	$(DBUS_LIBS)							\
3681  	$(GMODULE_LIBS)							\
3682 Index: src/libtracker-data/tracker-data-update.c
3683 ===================================================================
3684 --- src/libtracker-data/tracker-data-update.c	(revision 2782)
3685 +++ src/libtracker-data/tracker-data-update.c	(working copy)
3686 @@ -607,6 +607,35 @@
3687  	}
3688  }
3689  
3690 +
3691 +void
3692 +tracker_data_update_delete_service_all (const gchar *rdf_type)
3693 +{
3694 +	TrackerService     *service;
3695 +	gchar              *service_type_id; 
3696 +	TrackerDBInterface *iface;
3697 +
3698 +	if (!rdf_type)
3699 +		return;
3700 +
3701 +	service = tracker_ontology_get_service_by_name (rdf_type);
3702 +
3703 +	g_return_if_fail (TRACKER_IS_SERVICE (service));
3704 +
3705 +	service_type_id = tracker_gint_to_string (tracker_service_get_id (service));
3706 +
3707 +	iface = tracker_db_manager_get_db_interface_by_type (tracker_service_get_name (service),
3708 +							     TRACKER_DB_CONTENT_TYPE_METADATA);
3709 +
3710 +	tracker_db_interface_execute_procedure (iface,
3711 +						NULL,
3712 +						"DeleteServiceAll",
3713 +						service_type_id,
3714 +						NULL);
3715 +
3716 +	g_free (service_type_id);
3717 +}
3718 +
3719  static void
3720  set_metadata (TrackerField *field, 
3721  	      gpointer value, 
3722 Index: src/libtracker-data/tracker-data-update.h
3723 ===================================================================
3724 --- src/libtracker-data/tracker-data-update.h	(revision 2782)
3725 +++ src/libtracker-data/tracker-data-update.h	(working copy)
3726 @@ -58,7 +58,9 @@
3727  							 GHashTable          *metadata);
3728  void     tracker_data_update_delete_service_by_path     (const gchar         *path,
3729  							 const gchar         *rdf_type);
3730 +void     tracker_data_update_delete_service_all         (const gchar *rdf_type);
3731  
3732 +
3733  /* Metadata */
3734  void     tracker_data_update_set_metadata               (TrackerService      *service,
3735  							 guint32              service_id,
3736 Index: src/trackerd/tracker-main.c
3737 ===================================================================
3738 --- src/trackerd/tracker-main.c	(revision 2782)
3739 +++ src/trackerd/tracker-main.c	(working copy)
3740 @@ -53,8 +53,11 @@
3741  #include <libtracker-db/tracker-db-index.h>
3742  #include <libtracker-db/tracker-db-index-manager.h>
3743  
3744 +#include <libtracker-data/tracker-data-manager.h>
3745  #include <libtracker-data/tracker-turtle.h>
3746  
3747 +#include <plugins/evolution/tracker-evolution.h>
3748 +
3749  #include "tracker-crawler.h"
3750  #include "tracker-dbus.h"
3751  #include "tracker-indexer-client.h"
3752 @@ -1030,11 +1033,11 @@
3753  		return EXIT_FAILURE;
3754  	}
3755  
3756 +	tracker_module_config_init ();
3757 +
3758  	tracker_turtle_init ();
3759  	tracker_thumbnailer_init (config);
3760  
3761 -	tracker_module_config_init ();
3762 -
3763  	flags |= TRACKER_DB_MANAGER_REMOVE_CACHE;
3764  	index_flags |= TRACKER_DB_INDEX_MANAGER_READONLY;
3765  
3766 @@ -1132,6 +1135,10 @@
3767  		return EXIT_FAILURE;
3768  	}
3769  
3770 +#ifdef HAVE_EVOLUTION_PLUGIN
3771 +	tracker_evolution_init (config);
3772 +#endif
3773 +
3774  	g_message ("Waiting for DBus requests...");
3775  
3776  	/* Set our status as running, if this is FALSE, threads stop
3777 @@ -1202,6 +1209,11 @@
3778  	shutdown_directories ();
3779  
3780  	/* Shutdown major subsystems */
3781 +	
3782 +#ifdef HAVE_EVOLUTION_PLUGIN
3783 +	tracker_evolution_shutdown ();
3784 +#endif
3785 +
3786  	tracker_cleanup_shutdown ();
3787  	tracker_xesam_manager_shutdown ();
3788  	tracker_dbus_shutdown ();
3789 Index: src/trackerd/Makefile.am
3790 ===================================================================
3791 --- src/trackerd/Makefile.am	(revision 2782)
3792 +++ src/trackerd/Makefile.am	(working copy)
3793 @@ -77,6 +77,7 @@
3794  	$(top_builddir)/src/libtracker-db/libtracker-db.la 		\
3795  	$(top_builddir)/src/libtracker-common/libtracker-common.la 	\
3796  	$(top_builddir)/src/libstemmer/libstemmer.la	 		\
3797 +	$(top_builddir)/src/plugins/evolution/libtracker-evolution.la	\
3798  	$(inotify_libs)							\
3799  	$(GMIME_LIBS)							\
3800  	$(FAM_LIBS)							\
3801 Index: src/Makefile.am
3802 ===================================================================
3803 --- src/Makefile.am	(revision 2782)
3804 +++ src/Makefile.am	(working copy)
3805 @@ -37,6 +37,7 @@
3806  	libtracker-data				\
3807  	libtracker				\
3808  	$(build_sqlite_fts)			\
3809 +	plugins					\
3810  	trackerd				\
3811  	tracker-utils				\
3812  	tracker-extract				\
3813 @@ -62,4 +63,5 @@
3814  	libtracker-gtk				\
3815  	tracker-applet	 			\
3816  	tracker-search-tool			\
3817 -	tracker-preferences
3818 +	tracker-preferences			\
3819 +	plugins
3820 Index: configure.ac
3821 ===================================================================
3822 --- configure.ac	(revision 2782)
3823 +++ configure.ac	(working copy)
3824 @@ -120,6 +120,8 @@
3825  LIBGSF_REQUIRED=1.13
3826  EXEMPI_REQUIRED=1.99.2
3827  HILDON_THUMBNAIL_REQUIRED=3.0.10
3828 +EVO_REQUIRED=2.25.5
3829 +EDS_REQUIRED=2.25.5
3830  
3831  # Library Checks
3832  PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= $GLIB_REQUIRED])
3833 @@ -181,6 +183,28 @@
3834    AC_DEFINE(HAVE_RAPTOR, 1, [Raptor RDF parsers])
3835  fi
3836  
3837 +# Check for Evolution's plugin system
3838 +PKG_CHECK_MODULES(EVOPLUG, [
3839 +	evolution-plugin >= $EVO_REQUIRED
3840 +	evolution-data-server-1.2 >= $EDS_REQUIRED], 
3841 +	have_evoplug=yes, have_evoplug=no)
3842 +AC_SUBST(EVOPLUG_CFLAGS)
3843 +AC_SUBST(EVOPLUG_LIBS)
3844 +
3845 +if test x$have_evoplug == "xyes"; then
3846 +EVOLUTION_PLUGIN_INSTALL_DIR=`$PKG_CONFIG evolution-plugin --variable=plugindir`
3847 +else
3848 +EVOLUTION_PLUGIN_INSTALL_DIR=/dev/null
3849 +fi
3850 +
3851 +AC_SUBST(EVOLUTION_PLUGIN_INSTALL_DIR)
3852 +
3853 +if test x$have_evoplug == "xyes"; then
3854 +  AC_DEFINE(HAVE_EVOLUTION_PLUGIN, 1, [Evolution plugin])
3855 +fi
3856 +
3857 +AM_CONDITIONAL(HAVE_EVOLUTION_PLUGIN, test "$have_evoplug" = "yes")
3858 +
3859  # Check we have the DBUS binding tool we need
3860  AC_PATH_PROG(DBUSBINDINGTOOL, dbus-binding-tool)
3861  if test -z $DBUSBINDINGTOOL; then
3862 @@ -1199,6 +1223,8 @@
3863  	src/tracker-search-tool/Makefile
3864  	src/tracker-search-tool/tracker-search-tool.desktop.in
3865  	src/tracker-utils/Makefile
3866 +	src/plugins/Makefile
3867 +	src/plugins/evolution/Makefile
3868  	tests/common/Makefile
3869  	tests/libtracker-common/Makefile
3870  	tests/libtracker-db/Makefile
3871 @@ -1256,6 +1282,11 @@
3872  	Support MP3 album art (w/ GdkPixbuf):	$have_gdkpixbuf
3873  	Support Playlists (w/ Totem):           $have_playlist
3874  
3875 +Plugins:
3876 +
3877 +	Evolution support (old):	yes
3878 +	Evolution plugin:			$have_evoplug
3879 +
3880  Warning:
3881  
3882          You must make sure SQLite is compiled with --enable-threadsafe
3883 Index: data/db/sqlite-stored-procs.sql
3884 ===================================================================
3885 --- data/db/sqlite-stored-procs.sql	(revision 2782)
3886 +++ data/db/sqlite-stored-procs.sql	(working copy)
3887 @@ -171,6 +171,11 @@
3888  GetXesamMimePrefixForServiceId SELECT MimePrefix FROM XesamFileMimePrefixes WHERE ServiceTypeId = ?;
3889  
3890  /*
3891 + * Turtle importing
3892 + */
3893 +DeleteServiceAll               DELETE FROM Services WHERE ServiceTypeID = ?;
3894 +
3895 +/*
3896   * Deprecated
3897   */
3898  GetNewID                       SELECT OptionValue FROM Options WHERE OptionKey = 'Sequence';
3899 Index: data/db/sqlite-tracker.sql
3900 ===================================================================
3901 --- data/db/sqlite-tracker.sql	(revision 2782)
3902 +++ data/db/sqlite-tracker.sql	(working copy)
3903 @@ -8,6 +8,7 @@
3904  insert Into Options (OptionKey, OptionValue) values ('Sequence', '1');
3905  insert Into Options (OptionKey, OptionValue) values ('EventSequence', '1');
3906  insert Into Options (OptionKey, OptionValue) values ('UpdateCount', '0');
3907 +insert Into Options (OptionKey, OptionValue) values ('EvolutionLastCheckout', '0');
3908  
3909  
3910  /* store volume and HAL info here for files */

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2021-02-25 09:43:14, 112.9 KB) [[attachment:implementation.diff]]
  • [get | view] (2021-02-25 09:43:14, 12.7 KB) [[attachment:kmail_implementation.diff]]
  • [get | view] (2021-02-25 09:43:14, 4.7 KB) [[attachment:valaclientsample.vala]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.