tracker r2535 - in trunk: . data/modules src/tracker-indexer src/tracker-indexer/modules



Author: carlosg
Date: Thu Nov 20 15:29:19 2008
New Revision: 2535
URL: http://svn.gnome.org/viewvc/tracker?rev=2535&view=rev

Log:
2008-11-20  Carlos Garnacho  <carlos imendio com>

        Make indexer modules API GObject oriented, which allows easier
        bindings development and more flexible behavior for modules.

        * src/tracker-indexer/tracker-module-file.[ch]:
        * src/tracker-indexer/tracker-module-iteratable.[ch]: Definition of
        abstract base object and interface for modules to implement.

        * src/tracker-indexer/tracker-indexer-module.[ch]: Build on top of
        GTypeModule.
        * src/tracker-indexer/tracker-indexer.c: Modify to use new modules
        API.

        * src/tracker-indexer/tracker-module.h: Removed, no longer needed.

        * src/tracker-indexer/tracker-metadata-utils.[ch]: Switch API to
        GFile, since modules API now also deals with it.

        * src/modules/evolution-common.[ch]:
        * src/modules/evolution-imap.[ch]:
        * src/modules/evolution-pop.[ch]:
        * src/modules/evolution.c: Implement new modules API, split POP3/IMAP
        implementations, and make the module return different
        TrackerModuleFile objects depending on the parsed file.

        * src/modules/dummy.c:
        * src/modules/files.c:
        * src/modules/applications.c: Implement new modules API.

        * data/modules/files.c: Specify service type.

Added:
   trunk/src/tracker-indexer/modules/evolution-common.c
   trunk/src/tracker-indexer/modules/evolution-common.h
   trunk/src/tracker-indexer/modules/evolution-imap.c
   trunk/src/tracker-indexer/modules/evolution-imap.h
   trunk/src/tracker-indexer/modules/evolution-pop.c
   trunk/src/tracker-indexer/modules/evolution-pop.h
   trunk/src/tracker-indexer/tracker-module-file.c
   trunk/src/tracker-indexer/tracker-module-file.h
   trunk/src/tracker-indexer/tracker-module-iteratable.c
   trunk/src/tracker-indexer/tracker-module-iteratable.h
Removed:
   trunk/src/tracker-indexer/tracker-module.h
Modified:
   trunk/ChangeLog
   trunk/data/modules/files.module
   trunk/src/tracker-indexer/Makefile.am
   trunk/src/tracker-indexer/modules/Makefile.am
   trunk/src/tracker-indexer/modules/applications.c
   trunk/src/tracker-indexer/modules/dummy.c
   trunk/src/tracker-indexer/modules/evolution.c
   trunk/src/tracker-indexer/modules/files.c
   trunk/src/tracker-indexer/tracker-indexer-module.c
   trunk/src/tracker-indexer/tracker-indexer-module.h
   trunk/src/tracker-indexer/tracker-indexer.c
   trunk/src/tracker-indexer/tracker-metadata-utils.c
   trunk/src/tracker-indexer/tracker-metadata-utils.h

Modified: trunk/data/modules/files.module
==============================================================================
--- trunk/data/modules/files.module	(original)
+++ trunk/data/modules/files.module	Thu Nov 20 15:29:19 2008
@@ -11,7 +11,7 @@
 Files=*~;*.o;*.la;*.lo;*.loT;*.in;*.csproj;*.m4;*.rej;*.gmo;*.orig;*.pc;*.omf;*.aux;*.tmp;*.po;*.vmdk;*.vm*;*.nvram;*.part;autom4te;conftest;confstat;Makefile;SCCS;litmain.sh;libtool;config.status;confdefs.h;
 
 [Index]
-Service=
+Service=Files
 MimeTypes=
 Files=
 

Modified: trunk/src/tracker-indexer/Makefile.am
==============================================================================
--- trunk/src/tracker-indexer/Makefile.am	(original)
+++ trunk/src/tracker-indexer/Makefile.am	Thu Nov 20 15:29:19 2008
@@ -20,12 +20,14 @@
 libtracker_indexer_LTLIBRARIES = libtracker-indexer.la
 
 libtracker_indexer_la_SOURCES =	 					\
-	tracker-metadata-utils.c
+	tracker-metadata-utils.c					\
+	tracker-module-file.c						\
+	tracker-module-iteratable.c
 
 libtracker_indexerinclude_HEADERS =					\
 	tracker-metadata-utils.h					\
-	tracker-module.h
-
+	tracker-module-file.h						\
+	tracker-module-iteratable.h
 
 libexec_PROGRAMS = tracker-indexer
 

Modified: trunk/src/tracker-indexer/modules/Makefile.am
==============================================================================
--- trunk/src/tracker-indexer/modules/Makefile.am	(original)
+++ trunk/src/tracker-indexer/modules/Makefile.am	Thu Nov 20 15:29:19 2008
@@ -54,7 +54,12 @@
 	libtracker-indexer-evolution.la
 
 # Evolution
-libtracker_indexer_evolution_la_SOURCES = evolution.c
+libtracker_indexer_evolution_la_SOURCES =				\
+	evolution-common.c						\
+	evolution-imap.c						\
+	evolution-pop.c							\
+	evolution.c
+
 libtracker_indexer_evolution_la_LDFLAGS = $(module_flags)
 libtracker_indexer_evolution_la_LIBADD = 				\
 	$(GMODULE_LIBS)							\

Modified: trunk/src/tracker-indexer/modules/applications.c
==============================================================================
--- trunk/src/tracker-indexer/modules/applications.c	(original)
+++ trunk/src/tracker-indexer/modules/applications.c	Thu Nov 20 15:29:19 2008
@@ -19,7 +19,7 @@
 
 #include <stdlib.h>
 #include <glib.h>
-#include <tracker-indexer/tracker-module.h>
+#include <tracker-indexer/tracker-module-file.h>
 #include <libtracker-data/tracker-data-metadata.h>
 
 #define GROUP_DESKTOP_ENTRY "Desktop Entry"
@@ -43,11 +43,43 @@
 #define METADATA_APP_MIMETYPE	  "App:MimeType"
 #define METADATA_APP_CATEGORIES   "App:Categories"
 
-G_CONST_RETURN gchar *
-tracker_module_get_name (void)
+#define TRACKER_TYPE_APPLICATION_FILE    (tracker_application_file_get_type ())
+#define TRACKER_APPLICATION_FILE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TRACKER_TYPE_APPLICATION_FILE, TrackerApplicationFile))
+
+typedef struct TrackerApplicationFile TrackerApplicationFile;
+typedef struct TrackerApplicationFileClass TrackerApplicationFileClass;
+
+struct TrackerApplicationFile {
+        TrackerModuleFile parent_instance;
+};
+
+struct TrackerApplicationFileClass {
+        TrackerModuleFileClass parent_class;
+};
+
+
+static TrackerDataMetadata * tracker_application_file_get_metadata  (TrackerModuleFile *file);
+
+
+G_DEFINE_DYNAMIC_TYPE (TrackerApplicationFile, tracker_application_file, TRACKER_TYPE_MODULE_FILE);
+
+
+static void
+tracker_application_file_class_init (TrackerApplicationFileClass *klass)
+{
+        TrackerModuleFileClass *file_class = TRACKER_MODULE_FILE_CLASS (klass);
+
+        file_class->get_metadata = tracker_application_file_get_metadata;
+}
+
+static void
+tracker_application_file_class_finalize (TrackerApplicationFileClass *klass)
+{
+}
+
+static void
+tracker_application_file_init (TrackerApplicationFile *file)
 {
-	/* Return module name here */
-	return "Applications";
 }
 
 static void
@@ -100,29 +132,36 @@
 	}
 }
 
-TrackerDataMetadata *
-tracker_module_file_get_metadata (TrackerFile *file)
+static TrackerDataMetadata *
+tracker_application_file_get_metadata (TrackerModuleFile *file)
 {
 	TrackerDataMetadata *metadata;
 	GKeyFile *key_file;
-	gchar *type, *filename;
+        GFile *f;
+	gchar *path, *type, *filename;
+
+        f = tracker_module_file_get_file (file);
+        path = g_file_get_path (f);
 
 	/* Check we're dealing with a desktop file */
-	if (!g_str_has_suffix (file->path, ".desktop")) {
+	if (!g_str_has_suffix (path, ".desktop")) {
+                g_free (path);
 		return NULL;
 	}
 
 	key_file = g_key_file_new ();
 
-	if (!g_key_file_load_from_file (key_file, file->path, G_KEY_FILE_NONE, NULL)) {
-                g_debug ("Couldn't load desktop file:'%s'", file->path);
+	if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, NULL)) {
+                g_debug ("Couldn't load desktop file:'%s'", path);
 		g_key_file_free (key_file);
+                g_free (path);
 		return NULL;
 	}
 
 	if (g_key_file_get_boolean (key_file, GROUP_DESKTOP_ENTRY, KEY_HIDDEN, NULL)) {
                 g_debug ("Desktop file is 'hidden', not gathering metadata for it");
 		g_key_file_free (key_file);
+                g_free (path);
 		return NULL;
 	}
 
@@ -132,6 +171,7 @@
                 g_debug ("Desktop file is not of type 'Application', not gathering metadata for it");
 		g_key_file_free (key_file);
 		g_free (type);
+                g_free (path);
 		return NULL;
 	}
 
@@ -148,11 +188,32 @@
 	insert_list_from_desktop_file (metadata, METADATA_APP_MIMETYPE, key_file, KEY_MIMETYPE, FALSE);
 	insert_list_from_desktop_file (metadata, METADATA_APP_CATEGORIES, key_file, KEY_CATEGORIES, FALSE);
 
-	filename = g_filename_display_basename (file->path);
+	filename = g_filename_display_basename (path);
 	tracker_data_metadata_insert (metadata, METADATA_FILE_NAME, filename);
 
 	g_key_file_free (key_file);
 	g_free (type);
+        g_free (path);
 
 	return metadata;
 }
+
+
+void
+indexer_module_initialize (GTypeModule *module)
+{
+        tracker_application_file_register_type (module);
+}
+
+void
+indexer_module_shutdown (void)
+{
+}
+
+TrackerModuleFile *
+indexer_module_create_file (GFile *file)
+{
+        return g_object_new (TRACKER_TYPE_APPLICATION_FILE,
+                             "file", file,
+                             NULL);
+}

Modified: trunk/src/tracker-indexer/modules/dummy.c
==============================================================================
--- trunk/src/tracker-indexer/modules/dummy.c	(original)
+++ trunk/src/tracker-indexer/modules/dummy.c	Thu Nov 20 15:29:19 2008
@@ -17,115 +17,146 @@
  * Boston, MA  02110-1301, USA.
  */
 
-#include <glib.h>
 #include <libtracker-data/tracker-data-metadata.h>
+#include <tracker-indexer/tracker-module-file.h>
+#include <tracker-indexer/tracker-module-iteratable.h>
 
-void
-tracker_module_init (void)
-{
-	/* Implementing this function is optional.
-	 *
-	 * Allocate here all static resources for the module.
-	 */
+#define DUMMY_TYPE_FILE    (dummy_file_get_type ())
+#define DUMMY_FILE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), DUMMY_TYPE_FILE, DummyFile))
+
+#define MODULE_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) \
+{ \
+    const GInterfaceInfo g_implement_interface_info = { \
+      (GInterfaceInitFunc) iface_init, NULL, NULL \
+  }; \
+  g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
 }
 
-void
-tracker_module_shutdown (void)
+typedef struct DummyFile DummyFile;
+typedef struct DummyFileClass DummyFileClass;
+
+struct DummyFile {
+        TrackerModuleFile parent_instance;
+};
+
+struct DummyFileClass {
+        TrackerModuleFileClass parent_class;
+};
+
+
+static void          dummy_file_iteratable_init  (TrackerModuleIteratableIface *iface);
+
+static void          dummy_file_finalize         (GObject           *object);
+
+static void          dummy_file_initialize       (TrackerModuleFile *file);
+static const gchar * dummy_file_get_service_type (TrackerModuleFile *file);
+static gchar *       dummy_file_get_uri          (TrackerModuleFile *file);
+static gchar *       dummy_file_get_text         (TrackerModuleFile *file);
+static TrackerDataMetadata *
+                     dummy_file_get_metadata     (TrackerModuleFile *file);
+
+static gboolean      dummy_file_iter_contents    (TrackerModuleIteratable *iteratable);
+static guint         dummy_file_get_count        (TrackerModuleIteratable *iteratable);
+
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (DummyFile, dummy_file, TRACKER_TYPE_MODULE_FILE, 0,
+                                MODULE_IMPLEMENT_INTERFACE (TRACKER_TYPE_MODULE_ITERATABLE,
+                                                            dummy_file_iteratable_init))
+
+static void
+dummy_file_class_init (DummyFileClass *klass)
 {
-	/* Implementing this function is optional.
-	 *
-	 * Free here all resources allocated in tracker_module_init()
-	 */
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        TrackerModuleFileClass *file_class = TRACKER_MODULE_FILE_CLASS (klass);
+
+        object_class->finalize = dummy_file_finalize;
+
+        file_class->initialize = dummy_file_initialize;
+        file_class->get_service_type = dummy_file_get_service_type;
+        file_class->get_uri = dummy_file_get_uri;
+        file_class->get_text = dummy_file_get_text;
+        file_class->get_metadata = dummy_file_get_metadata;
 }
 
-G_CONST_RETURN gchar *
-tracker_module_get_name (void)
+static void
+dummy_file_init (DummyFile *file)
 {
-	/* Return module name here */
-	return "Dummy";
+
 }
 
-gpointer
-tracker_module_file_get_data (const gchar *path)
+static void
+dummy_file_iteratable_init (TrackerModuleIteratableIface *iface)
 {
-	/* Implementing this function is optional.
-	 *
-	 * Return here private, module specific data for path.
-	 * Given this data is attached to the file until it isn't
-	 * needed anymore. This is usually used for files that
-	 * contain sets of data that should be considered as separate
-	 * entities (for example, mboxes), so the module can internally
-	 * keep the state. Also see tracker_module_file_iter_contents().
-	 */
-	return NULL;
+        iface->iter_contents = dummy_file_iter_contents;
+        iface->get_count = dummy_file_get_count;
 }
 
-gchar *
-tracker_module_file_get_service_type (TrackerFile *file)
+static void
+dummy_file_finalize (GObject *object)
 {
-	/* Implementing this function is optional.
-	 *
-	 * Return the service type for the incoming path.
-	 *
-	 * If this function is not implemented, the indexer will use
-	 * the name of the module (tracker_module_get_name) as service.
-	 *
-	 */
-	return NULL;
+        /* Free here all resources allocated by the object, if any */
+
+        /* Chain up to parent implementation */
+        G_OBJECT_CLASS (dummy_file_parent_class)->finalize (object);
 }
 
-void
-tracker_module_file_free_data (gpointer file_data)
+static void
+dummy_file_initialize (TrackerModuleFile *file)
 {
-	/* Implementing this function is optional
-	 *
-	 * Free the data created previously
-	 * through tracker_module_file_get_data()
-	 */
+        /* Allocate here all resources for the file, if any */
 }
 
-void
-tracker_module_file_get_uri (TrackerFile  *file,
-			     gchar	 **dirname,
-			     gchar	 **basename)
+static const gchar *
+dummy_file_get_service_type (TrackerModuleFile *file)
 {
-	/* Implementing this function is optional
-	 *
-	 * Return dirname/basename for the current item, with this
-	 * method modules can specify different URIs for different
-	 * elements contained in the file. Also see
-	 * tracker_module_file_iter_contents()
-	 */
-	*dirname = g_path_get_dirname (file->path);
-	*basename = g_path_get_basename (file->path);
+        /* Implementing this function is optional.
+         *
+         * Return the service type for the given file.
+         *
+         * If this function is not implemented, the indexer will use
+         * whatever service name is specified in the module configuration
+         * file.
+         */
+        return NULL;
 }
 
-TrackerMetadata *
-tracker_module_file_get_metadata (TrackerFile *file)
+static gchar *
+dummy_file_get_uri (TrackerModuleFile *file)
 {
-	/* Return a hashtable filled with metadata for file, given the
-	 * current state. Also see tracker_module_file_iter_contents()
-	 */
-	return NULL;
+        /* Implementing this function is optional
+         *
+         * Return URI for the current item, with this method
+         * modules can specify different URIs for different
+         * elements contained in the file. See also
+         * TrackerModuleIteratable.
+         */
+        return NULL;
 }
 
-gchar *
-tracker_module_file_get_text (TrackerFile *file)
+static gchar *
+dummy_file_get_text (TrackerModuleFile *file)
 {
 	/* Implementing this function is optional
 	 *
 	 * Return here full text for file, given the current state,
-	 * also see tracker_module_file_iter_contents()
+	 * see also TrackerModuleIteratable.
 	 */
 	return NULL;
 }
 
-gboolean
-tracker_module_file_iter_contents (TrackerFile *file)
+static TrackerDataMetadata *
+dummy_file_get_metadata (TrackerModuleFile *file)
 {
-	/* Implementing this function is optional
-	 *
-	 * This function is meant to iterate the internal state,
+	/* Return a TrackerDataMetadata filled with metadata for file,
+         * given the current state. Also see TrackerModuleIteratable.
+	 */
+	return NULL;
+}
+
+static gboolean
+dummy_file_iter_contents (TrackerModuleIteratable *iteratable)
+{
+	/* This function is meant to iterate the internal state,
 	 * so it points to the next entity inside the file.
 	 * In case there is such next entity, this function must
 	 * return TRUE, else, returning FALSE will make the indexer
@@ -134,5 +165,34 @@
 	 * What an "entity" is considered is left to the module
 	 * implementation.
 	 */
-	return FALSE;
+        return FALSE;
+}
+
+static guint
+dummy_file_get_count (TrackerModuleIteratable *iteratable)
+{
+        /* This function is meant to return the number of entities
+         * contained in the file, what an "entity" is considered is
+         * left to the module implementation.
+         */
+        return 0;
+}
+
+void
+indexer_module_initialize (GTypeModule *module)
+{
+        dummy_file_register_type (module);
+}
+
+void
+indexer_module_shutdown (void)
+{
+}
+
+TrackerModuleFile *
+indexer_module_create_file (GFile *file)
+{
+        return g_object_new (DUMMY_TYPE_FILE,
+                             "file", file,
+                             NULL);
 }

Added: trunk/src/tracker-indexer/modules/evolution-common.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-common.c	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,119 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <tracker-indexer/tracker-metadata-utils.h>
+#include "evolution-common.h"
+
+GMimeStream *
+evolution_common_get_stream (const gchar *path,
+                             gint         flags,
+                             off_t        start)
+{
+	GMimeStream *stream;
+	gint fd;
+
+	fd = g_open (path, flags, S_IRUSR | S_IWUSR);
+
+	if (fd == -1) {
+		return NULL;
+	}
+
+	stream = g_mime_stream_fs_new_with_bounds (fd, start, -1);
+
+	if (!stream) {
+		close (fd);
+	}
+
+	return stream;
+}
+
+TrackerDataMetadata *
+evolution_common_get_wrapper_metadata (GMimeDataWrapper *wrapper)
+{
+	TrackerDataMetadata *metadata;
+	GMimeStream *stream;
+	gchar *path;
+	gint fd;
+
+	path = g_build_filename (g_get_tmp_dir (), "tracker-evolution-module-XXXXXX", NULL);
+	fd = g_mkstemp (path);
+	metadata = NULL;
+
+	stream = g_mime_stream_fs_new (fd);
+
+	if (g_mime_data_wrapper_write_to_stream (wrapper, stream) != -1) {
+                GFile *file;
+
+                file = g_file_new_for_path (path);
+		g_mime_stream_flush (stream);
+
+		metadata = tracker_metadata_utils_get_data (file);
+
+                g_object_unref (file);
+		g_unlink (path);
+	}
+
+	g_mime_stream_close (stream);
+	g_object_unref (stream);
+	g_free (path);
+
+	return metadata;
+}
+
+gchar *
+evolution_common_get_object_encoding (GMimeObject *object)
+{
+        const gchar *start_encoding, *end_encoding;
+        const gchar *content_type = NULL;
+
+        if (GMIME_IS_MESSAGE (object)) {
+                content_type = g_mime_message_get_header (GMIME_MESSAGE (object), "Content-Type");
+        } else if (GMIME_IS_PART (object)) {
+                content_type = g_mime_part_get_content_header (GMIME_PART (object), "Content-Type");
+        }
+
+        if (!content_type) {
+                return NULL;
+        }
+
+        start_encoding = strstr (content_type, "charset=");
+
+        if (!start_encoding) {
+                return NULL;
+        }
+
+        start_encoding += strlen ("charset=");
+
+        if (start_encoding[0] == '"') {
+                /* encoding is quoted */
+                start_encoding++;
+                end_encoding = strstr (start_encoding, "\"");
+        } else {
+                end_encoding = strstr (start_encoding, ";");
+        }
+
+        if (end_encoding) {
+                return g_strndup (start_encoding, end_encoding - start_encoding);
+        } else {
+                return g_strdup (start_encoding);
+        }
+}

Added: trunk/src/tracker-indexer/modules/evolution-common.h
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-common.h	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,61 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __EVOLUTION_COMMON_H__
+#define __EVOLUTION_COMMON_H__
+
+#include <glib.h>
+#include <gmime/gmime.h>
+#include <libtracker-data/tracker-data-metadata.h>
+
+G_BEGIN_DECLS
+
+#define METADATA_FILE_PATH	     "File:Path"
+#define METADATA_FILE_NAME	     "File:Name"
+#define METADATA_EMAIL_RECIPIENT     "Email:Recipient"
+#define METADATA_EMAIL_DATE	     "Email:Date"
+#define METADATA_EMAIL_SENDER	     "Email:Sender"
+#define METADATA_EMAIL_SUBJECT	     "Email:Subject"
+#define METADATA_EMAIL_SENT_TO	     "Email:SentTo"
+#define METADATA_EMAIL_CC	     "Email:CC"
+
+
+enum EvolutionFlags {
+	EVOLUTION_MESSAGE_ANSWERED     = 1 << 0,
+	EVOLUTION_MESSAGE_DELETED      = 1 << 1,
+	EVOLUTION_MESSAGE_DRAFT        = 1 << 2,
+	EVOLUTION_MESSAGE_FLAGGED      = 1 << 3,
+	EVOLUTION_MESSAGE_SEEN	       = 1 << 4,
+	EVOLUTION_MESSAGE_ATTACHMENTS  = 1 << 5,
+	EVOLUTION_MESSAGE_ANSWERED_ALL = 1 << 6,
+	EVOLUTION_MESSAGE_JUNK	       = 1 << 7,
+	EVOLUTION_MESSAGE_SECURE       = 1 << 8
+};
+
+GMimeStream *         evolution_common_get_stream           (const gchar      *path,
+                                                             gint              flags,
+                                                             off_t             start);
+
+TrackerDataMetadata * evolution_common_get_wrapper_metadata (GMimeDataWrapper *wrapper);
+gchar *               evolution_common_get_object_encoding  (GMimeObject      *object);
+
+
+G_END_DECLS
+
+#endif /* __EVOLUTION_COMMON_H__ */

Added: trunk/src/tracker-indexer/modules/evolution-imap.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-imap.c	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,1142 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <libtracker-data/tracker-data-metadata.h>
+#include <tracker-indexer/tracker-module-file.h>
+#include <tracker-indexer/tracker-module-iteratable.h>
+#include <gconf/gconf-client.h>
+#include <string.h>
+#include "evolution-imap.h"
+#include "evolution-common.h"
+
+#define METADATA_EMAIL_RECIPIENT     "Email:Recipient"
+#define METADATA_EMAIL_DATE	     "Email:Date"
+#define METADATA_EMAIL_SENDER	     "Email:Sender"
+#define METADATA_EMAIL_SUBJECT	     "Email:Subject"
+#define METADATA_EMAIL_SENT_TO	     "Email:SentTo"
+#define METADATA_EMAIL_CC	     "Email:CC"
+
+#define MODULE_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) \
+{ \
+    const GInterfaceInfo g_implement_interface_info = { \
+      (GInterfaceInitFunc) iface_init, NULL, NULL \
+  }; \
+  g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+
+typedef struct EvolutionAccountContext EvolutionAccountContext;
+
+
+enum {
+	SUMMARY_TYPE_INT32,
+	SUMMARY_TYPE_UINT32,
+	SUMMARY_TYPE_STRING,
+	SUMMARY_TYPE_TOKEN,
+	SUMMARY_TYPE_TIME_T
+};
+
+struct EvolutionAccountContext {
+	gchar *account;
+	gchar *uid;
+};
+
+static GHashTable *accounts = NULL;
+
+
+static void          tracker_evolution_imap_file_finalize         (GObject *object);
+
+static void          tracker_evolution_imap_file_initialize       (TrackerModuleFile *file);
+static const gchar * tracker_evolution_imap_file_get_service_type (TrackerModuleFile *file);
+static gchar *       tracker_evolution_imap_file_get_uri          (TrackerModuleFile *file);
+static gchar *       tracker_evolution_imap_file_get_text         (TrackerModuleFile *file);
+static TrackerDataMetadata *
+                     tracker_evolution_imap_file_get_metadata     (TrackerModuleFile *file);
+
+static void          tracker_evolution_imap_file_iteratable_init  (TrackerModuleIteratableIface *iface);
+static gboolean      tracker_evolution_imap_file_iter_contents    (TrackerModuleIteratable *iteratable);
+static guint         tracker_evolution_imap_file_get_count        (TrackerModuleIteratable *iteratable);
+
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TrackerEvolutionImapFile, tracker_evolution_imap_file, TRACKER_TYPE_MODULE_FILE, 0,
+                                MODULE_IMPLEMENT_INTERFACE (TRACKER_TYPE_MODULE_ITERATABLE,
+                                                            tracker_evolution_imap_file_iteratable_init))
+
+
+static void
+tracker_evolution_imap_file_class_init (TrackerEvolutionImapFileClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        TrackerModuleFileClass *file_class = TRACKER_MODULE_FILE_CLASS (klass);
+
+        object_class->finalize = tracker_evolution_imap_file_finalize;
+
+        file_class->initialize = tracker_evolution_imap_file_initialize;
+        file_class->get_service_type = tracker_evolution_imap_file_get_service_type;
+        file_class->get_uri = tracker_evolution_imap_file_get_uri;
+        file_class->get_text = tracker_evolution_imap_file_get_text;
+        file_class->get_metadata = tracker_evolution_imap_file_get_metadata;
+}
+
+static void
+tracker_evolution_imap_file_class_finalize (TrackerEvolutionImapFileClass *klass)
+{
+}
+
+static void
+tracker_evolution_imap_file_init (TrackerEvolutionImapFile *file)
+{
+}
+
+static void
+tracker_evolution_imap_file_iteratable_init (TrackerModuleIteratableIface *iface)
+{
+        iface->iter_contents = tracker_evolution_imap_file_iter_contents;
+        iface->get_count = tracker_evolution_imap_file_get_count;
+}
+
+static void
+tracker_evolution_imap_file_finalize (GObject *object)
+{
+        TrackerEvolutionImapFile *file;
+
+        file = TRACKER_EVOLUTION_IMAP_FILE (object);
+
+        g_free (file->cur_message_uid);
+
+        fclose (file->summary);
+	close (file->fd);
+
+        G_OBJECT_CLASS (tracker_evolution_imap_file_parent_class)->finalize (object);
+}
+
+static gboolean
+read_summary (FILE *summary,
+	      ...)
+{
+	va_list args;
+	gint value_type;
+
+	if (!summary) {
+		return FALSE;
+	}
+
+	va_start (args, summary);
+
+	while ((value_type = va_arg (args, gint)) != -1) {
+		switch (value_type) {
+		case SUMMARY_TYPE_TIME_T: {
+                        time_t value = 0;
+                        time_t *dest;
+                        int size = sizeof (time_t) - 1;
+                        int c = EOF;
+
+                        while (size >= 0 && (c = fgetc (summary)) != EOF) {
+                                value |= ((time_t) c) << (size * 8);
+                                size--;
+                        }
+
+                        dest = va_arg (args, time_t*);
+
+                        if (dest) {
+                                *dest = value;
+                        }
+
+                        if (c == EOF) {
+                                return FALSE;
+                        }
+
+			break;
+		}
+		case SUMMARY_TYPE_INT32: {
+			gint32 value, *dest;
+
+			if (fread (&value, sizeof (gint32), 1, summary) != 1) {
+				return FALSE;
+			}
+
+			dest = va_arg (args, gint32*);
+
+			if (dest) {
+				*dest = g_ntohl (value);
+			}
+			break;
+		}
+		case SUMMARY_TYPE_UINT32: {
+			guint32 *dest, value = 0;
+			gint c;
+
+			while (((c = fgetc (summary)) & 0x80) == 0 && c != EOF) {
+				value |= c;
+				value <<= 7;
+			}
+
+			if (c == EOF) {
+				return FALSE;
+			} else {
+				value |= (c & 0x7f);
+			}
+
+			dest = va_arg (args, guint32*);
+
+			if (dest) {
+				*dest = value;
+			}
+			break;
+		}
+		case SUMMARY_TYPE_STRING:
+		case SUMMARY_TYPE_TOKEN: {
+			guint32 len;
+			gchar *str, **dest;
+
+			/* read string length */
+			read_summary (summary, SUMMARY_TYPE_UINT32, &len, -1);
+			dest = va_arg (args, gchar **);
+
+			if (dest) {
+				*dest = NULL;
+			}
+
+			if (value_type == SUMMARY_TYPE_TOKEN) {
+				if (len < 32) {
+					continue;
+				} else {
+					len -= 31;
+				}
+			}
+
+			if (len <= 1) {
+				continue;
+			}
+
+			str = g_try_malloc0 (len);
+			if (!str) {
+				return FALSE;
+			}
+
+			if (fread (str, len - 1, 1, summary) != 1) {
+				g_free (str);
+				return FALSE;
+			}
+
+			if (dest) {
+				*dest = str;
+			} else {
+				g_free (str);
+			}
+
+			break;
+		}
+		default:
+			break;
+		}
+	}
+
+	va_end (args);
+
+	return TRUE;
+}
+
+static gint
+read_summary_header (FILE *summary)
+{
+	gint32 version, n_messages;
+
+	read_summary (summary,
+		      SUMMARY_TYPE_INT32, &version,
+		      SUMMARY_TYPE_INT32, NULL,		/* flags */
+		      SUMMARY_TYPE_INT32, NULL,		/* nextuid */
+		      SUMMARY_TYPE_TIME_T, NULL,	/* time */
+		      SUMMARY_TYPE_INT32, &n_messages,
+		      -1);
+
+	if ((version < 0x100 && version >= 13)) {
+		read_summary (summary,
+			      SUMMARY_TYPE_INT32, NULL, /* unread count*/
+			      SUMMARY_TYPE_INT32, NULL, /* deleted count*/
+			      SUMMARY_TYPE_INT32, NULL, /* junk count */
+			      -1);
+	}
+
+	if (version != 0x30c) {
+		read_summary (summary,
+			      SUMMARY_TYPE_INT32, NULL,
+			      SUMMARY_TYPE_INT32, NULL,
+			      -1);
+	}
+
+	return n_messages;
+}
+
+static void
+skip_content_info (FILE *summary)
+{
+	guint32 count, i;
+
+	if (fgetc (summary)) {
+		read_summary (summary,
+			      SUMMARY_TYPE_TOKEN, NULL,
+			      SUMMARY_TYPE_TOKEN, NULL,
+			      SUMMARY_TYPE_UINT32, &count,
+			      -1);
+
+		if (count <= 500) {
+			for (i = 0; i < count; i++) {
+				read_summary (summary,
+					      SUMMARY_TYPE_TOKEN, NULL,
+					      SUMMARY_TYPE_TOKEN, NULL,
+					      -1);
+			}
+		}
+
+		read_summary (summary,
+			      SUMMARY_TYPE_TOKEN, NULL,
+			      SUMMARY_TYPE_TOKEN, NULL,
+			      SUMMARY_TYPE_TOKEN, NULL,
+			      SUMMARY_TYPE_UINT32, NULL,
+			      -1);
+	}
+
+	read_summary (summary,
+		      SUMMARY_TYPE_UINT32, &count,
+		      -1);
+
+	for (i = 0; i < count; i++) {
+		skip_content_info (summary);
+	}
+}
+
+static void
+account_start_element_handler (GMarkupParseContext *context,
+			       const gchar	   *element_name,
+			       const gchar	   **attr_names,
+			       const gchar	   **attr_values,
+			       gpointer		   user_data,
+			       GError		   **error)
+{
+	EvolutionAccountContext *account_context;
+	gint i = 0;
+
+	if (strcmp (element_name, "account") != 0) {
+		return;
+	}
+
+	account_context = (EvolutionAccountContext *) user_data;
+
+	while (attr_names[i]) {
+		if (strcmp (attr_names[i], "uid") == 0) {
+			account_context->uid = g_strdup (attr_values[i]);
+			return;
+		}
+
+		i++;
+	}
+}
+
+static gchar *
+get_account_name_from_imap_uri (const gchar *imap_uri)
+{
+	const gchar *start, *at, *semic;
+	gchar *user_name, *at_host_name, *account_name;
+
+	/* Assume url schema is:
+	 * imap://foo imap free fr/;etc
+	 * or
+	 * imap://foo;auth=DIGEST-MD5 imap bar com/;etc
+	 *
+	 * We try to get "foo imap free fr".
+	 */
+
+	if (!g_str_has_prefix (imap_uri, "imap://")) {
+		return NULL;
+	}
+
+	user_name = at_host_name = account_name = NULL;
+
+	/* check for embedded @ and then look for first colon after that */
+	start = imap_uri + 7;
+	at = strchr (start, '@');
+	semic = strchr (start, ';');
+
+	if ( strlen (imap_uri) < 7 || at == NULL ) {
+		return g_strdup ("Unknown");
+	}
+
+	if (semic < at) {
+		/* we have a ";auth=FOO host" schema
+		   Set semic to the next semicolon, which ends the hostname. */
+		user_name = g_strndup (start, semic - start);
+		/* look for ';' at the end of the domain name */
+		semic = strchr (at, ';');
+	} else {
+		user_name = g_strndup (start, at - start);
+	}
+
+	at_host_name = g_strndup (at, (semic - 1) - at);
+
+	account_name = g_strconcat (user_name, at_host_name, NULL);
+
+	g_free (user_name);
+	g_free (at_host_name);
+
+	return account_name;
+}
+
+static void
+account_text_handler (GMarkupParseContext  *context,
+		      const gchar	   *text,
+		      gsize		    text_len,
+		      gpointer		    user_data,
+		      GError		  **error)
+{
+	EvolutionAccountContext *account_context;
+	const GSList *uri_element, *source_element;
+	gchar *url;
+
+	uri_element = g_markup_parse_context_get_element_stack (context);
+	source_element = uri_element->next;
+
+	if (strcmp ((gchar *) uri_element->data, "url") != 0 ||
+	    !source_element ||
+	    strcmp ((gchar *) source_element->data, "source") != 0) {
+		return;
+	}
+
+	account_context = (EvolutionAccountContext *) user_data;
+
+	url = g_strndup (text, text_len);
+	account_context->account = get_account_name_from_imap_uri (url);
+	g_free (url);
+}
+
+static void
+ensure_imap_accounts (void)
+{
+	GConfClient *client;
+	GMarkupParser parser = { 0 };
+	GMarkupParseContext *parse_context;
+	GSList *list, *l;
+	EvolutionAccountContext account_context = { 0 };
+
+        if (G_LIKELY (accounts)) {
+                return;
+        }
+
+	client = gconf_client_get_default ();
+
+	list = gconf_client_get_list (client,
+				      "/apps/evolution/mail/accounts",
+				      GCONF_VALUE_STRING,
+				      NULL);
+
+	parser.start_element = account_start_element_handler;
+	parser.text = account_text_handler;
+	parse_context = g_markup_parse_context_new (&parser, 0, &account_context, NULL);
+
+	accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
+					  (GDestroyNotify) g_free,
+					  (GDestroyNotify) g_free);
+
+	for (l = list; l; l = l->next) {
+		g_markup_parse_context_parse (parse_context, (const gchar *) l->data, -1, NULL);
+
+		if (account_context.account &&
+		    account_context.uid) {
+			g_hash_table_insert (accounts,
+					     account_context.account,
+					     account_context.uid);
+		} else {
+			g_free (account_context.account);
+			g_free (account_context.uid);
+		}
+	}
+
+	g_markup_parse_context_free (parse_context);
+
+	g_slist_foreach (list, (GFunc) g_free, NULL);
+	g_slist_free (list);
+}
+
+static void
+tracker_evolution_imap_file_initialize (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapFile *self;
+        gchar *path;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+        self->imap_dir = g_build_filename (g_get_home_dir (),
+                                           ".evolution", "mail", "imap", G_DIR_SEPARATOR_S,
+                                           NULL);
+
+        path = g_file_get_path (tracker_module_file_get_file (file));
+        self->fd = tracker_file_open (path, TRUE);
+        g_free (path);
+
+        if (self->fd == -1) {
+                return;
+        }
+
+        self->summary = fdopen (self->fd, "r");
+        self->n_messages = read_summary_header (self->summary);
+        self->cur_message = 1;
+
+        if (self->n_messages > 0) {
+                /* save current message uid */
+                read_summary (self->summary,
+                              SUMMARY_TYPE_STRING, &self->cur_message_uid, /* message uid */
+                              -1);
+        }
+
+        ensure_imap_accounts ();
+}
+
+static const gchar *
+tracker_evolution_imap_file_get_service_type (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+        if (self->current_mime_part) {
+                return "EvolutionAttachments";
+        }
+
+        return "EvolutionEmails";
+}
+
+static gchar *
+get_message_path (TrackerModuleFile *file,
+                  const gchar       *uid)
+{
+	gchar *path, *prefix, *message_path;
+
+        path = g_file_get_path (tracker_module_file_get_file (file));
+	prefix = g_strndup (path, strlen (path) - strlen ("summary"));
+        g_free (path);
+
+        message_path = g_strconcat (prefix, uid, ".", NULL);
+	g_free (prefix);
+
+	return message_path;
+}
+
+static gboolean
+get_attachment_info (const gchar            *mime_file,
+                     gchar                 **name,
+                     GMimePartEncodingType  *encoding)
+{
+	GMimeContentType *mime;
+	gchar *tmp, *mime_content;
+	const gchar *pos_content_type, *pos_encoding, *pos_end_encoding;
+
+	if (name) {
+		*name = NULL;
+	}
+
+	if (encoding) {
+		*encoding = GMIME_PART_ENCODING_DEFAULT;
+	}
+
+	if (!g_file_get_contents (mime_file, &tmp, NULL, NULL)) {
+		return FALSE;
+	}
+
+	/* all text content in lower case for comparisons */
+	mime_content = g_ascii_strdown (tmp, -1);
+	g_free (tmp);
+
+	pos_content_type = strstr (mime_content, "content-type:");
+
+	if (pos_content_type) {
+		pos_encoding = strstr (pos_content_type, "content-transfer-encoding:");
+	}
+
+	if (!pos_content_type || !pos_encoding) {
+		g_free (mime_content);
+		return FALSE;
+	}
+
+	pos_content_type += strlen ("content-type:");
+	pos_encoding += strlen ("content-transfer-encoding:");
+
+	/* ignore spaces, tab or line returns */
+	while (*pos_content_type != '\0' && (*pos_content_type == ' ' || *pos_content_type == '\t' || *pos_content_type == '\n')) {
+		pos_content_type++;
+	}
+
+	while (*pos_encoding != '\0' && *pos_encoding == ' ') {
+		pos_encoding++;
+	}
+
+	if (*pos_content_type == '\0' ||
+	    *pos_encoding == '\0') {
+		g_free (mime_content);
+		return FALSE;
+	}
+
+	mime = g_mime_content_type_new_from_string (pos_content_type);
+
+	if (mime) {
+		if (name) {
+			*name = g_strdup (g_mime_content_type_get_parameter (mime, "name"));
+		}
+
+		g_mime_content_type_destroy (mime);
+	}
+
+	if (name && !*name) {
+		g_free (mime_content);
+		return FALSE;
+	}
+
+	/* Find end of encoding */
+	pos_end_encoding = pos_encoding;
+
+	while (*pos_end_encoding != '\0' &&
+	       *pos_end_encoding != ' ' &&
+	       *pos_end_encoding != '\n' &&
+	       *pos_end_encoding != '\t') {
+		pos_end_encoding++;
+	}
+
+	if (encoding && pos_encoding != pos_end_encoding) {
+		gchar *encoding_str = g_strndup (pos_encoding, pos_end_encoding - pos_encoding);
+
+		if (strcmp (encoding_str, "7bit") == 0) {
+			*encoding = GMIME_PART_ENCODING_7BIT;
+		} else if (strcmp (encoding_str, "8bit") == 0) {
+			*encoding = GMIME_PART_ENCODING_7BIT;
+		} else if (strcmp (encoding_str, "binary") == 0) {
+			*encoding = GMIME_PART_ENCODING_BINARY;
+		} else if (strcmp (encoding_str, "base64") == 0) {
+			*encoding = GMIME_PART_ENCODING_BASE64;
+		} else if (strcmp (encoding_str, "quoted-printable") == 0) {
+			*encoding = GMIME_PART_ENCODING_QUOTEDPRINTABLE;
+		} else if (strcmp (encoding_str, "x-uuencode") == 0) {
+			*encoding = GMIME_PART_ENCODING_UUENCODE;
+		}
+
+		g_free (encoding_str);
+	}
+
+	g_free (mime_content);
+
+	return TRUE;
+}
+
+static gchar *
+get_message_uri (TrackerModuleFile *file,
+                 const gchar       *message_uid)
+{
+        TrackerEvolutionImapFile *self;
+	gchar *path, *uri, *dir, *subdirs;
+        GList *keys, *k;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+        path = g_file_get_path (tracker_module_file_get_file (file));
+	keys = g_hash_table_get_keys (accounts);
+        uri = NULL;
+
+	for (k = keys; k; k = k->next) {
+		if (!strstr (path, k->data)) {
+                        continue;
+                }
+
+                dir = g_build_filename (self->imap_dir, k->data, NULL);
+
+                /* now remove all relevant info to create the email:// basename */
+                subdirs = path;
+                subdirs = tracker_string_remove (subdirs, dir);
+                subdirs = tracker_string_remove (subdirs, "/folders/");
+                subdirs = tracker_string_remove (subdirs, "/subfolders");
+                subdirs = tracker_string_remove (subdirs, "/summary");
+
+                uri = g_strdup_printf ("email://%s/%s;uid=%s",
+                                       (gchar *) g_hash_table_lookup (accounts, k->data),
+                                       subdirs,
+                                       message_uid);
+                g_free (subdirs);
+                g_free (dir);
+
+                break;
+	}
+
+	g_list_free (keys);
+
+        return uri;
+}
+
+static gchar *
+tracker_evolution_imap_file_get_uri (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapFile *self;
+        gchar *message_uri, *part_filename;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+        if (!self->cur_message_uid) {
+                return NULL;
+        }
+
+        message_uri = get_message_uri (file, self->cur_message_uid);
+
+        if (!message_uri) {
+                return NULL;
+        }
+
+        if (self->current_mime_part &&
+            get_attachment_info (self->current_mime_part->data, &part_filename, NULL)) {
+                gchar *attachment_uri;
+
+                attachment_uri = g_strdup_printf ("%s/%s", message_uri, part_filename);
+                g_free (message_uri);
+                g_free (part_filename);
+
+                return attachment_uri;
+        }
+
+        return message_uri;
+}
+
+static void
+extract_message_text (GMimeObject *object,
+                      gpointer     user_data)
+{
+        GString *body = (GString *) user_data;
+        GMimePartEncodingType part_encoding;
+        GMimePart *part;
+        const gchar *content, *disposition, *filename;
+        gchar *encoding, *part_body;
+        gsize len;
+
+        if (GMIME_IS_MESSAGE_PART (object)) {
+		GMimeMessage *message;
+
+		message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (object));
+
+		if (message) {
+			g_mime_message_foreach_part (message, extract_message_text, user_data);
+			g_object_unref (message);
+		}
+
+		return;
+        } else if (GMIME_IS_MULTIPART (object)) {
+                g_mime_multipart_foreach (GMIME_MULTIPART (object), extract_message_text, user_data);
+                return;
+        }
+
+	part = GMIME_PART (object);
+        filename = g_mime_part_get_filename (part);
+	disposition = g_mime_part_get_content_disposition (part);
+        part_encoding = g_mime_part_get_encoding (part);
+
+        if (part_encoding == GMIME_PART_ENCODING_BINARY ||
+            part_encoding == GMIME_PART_ENCODING_BASE64 ||
+            part_encoding == GMIME_PART_ENCODING_UUENCODE) {
+                return;
+        }
+
+	if (disposition &&
+	    strcmp (disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) {
+		return;
+	}
+
+        if (filename &&
+            (strcmp (filename, "signature.asc") == 0 ||
+             strcmp (filename, "signature.pgp") == 0)) {
+                return;
+        }
+
+        content = g_mime_part_get_content (GMIME_PART (object), &len);
+
+        if (!content) {
+                return;
+        }
+
+        if (g_utf8_validate (content, len, NULL)) {
+                g_string_append_len (body, content, (gssize) len);
+                return;
+        }
+
+        encoding = evolution_common_get_object_encoding (object);
+
+        if (!encoding) {
+                /* FIXME: This will break for non-utf8 text without
+                 * the proper content type set
+                 */
+                g_string_append_len (body, content, (gssize) len);
+        } else {
+                part_body = g_convert (content, (gssize) len, "utf8", encoding, NULL, NULL, NULL);
+                g_string_append (body, part_body);
+
+                g_free (part_body);
+                g_free (encoding);
+        }
+}
+
+static gchar *
+tracker_evolution_imap_file_get_text (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapFile *self;
+	gchar *message_path;
+        GMimeStream *stream;
+        GMimeParser *parser;
+        GMimeMessage *message;
+        GString *body = NULL;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+	if (self->current_mime_part) {
+		/* FIXME: Extract text from attachments */
+		return NULL;
+	}
+
+	message_path = get_message_path (file, self->cur_message_uid);
+
+#if defined(__linux__)
+        stream = evolution_common_get_stream (message_path, O_RDONLY | O_NOATIME, 0);
+#else
+        stream = evolution_common_get_stream (message_path, O_RDONLY, 0);
+#endif
+
+	g_free (message_path);
+
+        if (!stream) {
+                return NULL;
+        }
+
+        parser = g_mime_parser_new_with_stream (stream);
+        g_mime_parser_set_scan_from (parser, FALSE);
+        message = g_mime_parser_construct_message (parser);
+
+        if (message) {
+                body = g_string_new (NULL);
+                g_mime_message_foreach_part (message, extract_message_text, body);
+                g_object_unref (message);
+        }
+
+        g_object_unref (stream);
+        g_object_unref (parser);
+
+	return (body) ? g_string_free (body, FALSE) : NULL;
+}
+
+static GList *
+get_recipient_list (const gchar *str)
+{
+	GList *list = NULL;
+	gchar **arr;
+	gint i;
+
+	if (!str) {
+		return NULL;
+	}
+
+	arr = g_strsplit (str, ",", -1);
+
+	for (i = 0; arr[i]; i++) {
+		g_strstrip (arr[i]);
+		list = g_list_prepend (list, g_strdup (arr[i]));
+	}
+
+	g_strfreev (arr);
+
+	return g_list_reverse (list);
+}
+
+static TrackerDataMetadata *
+get_message_metadata (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapFile *self;
+	TrackerDataMetadata *metadata = NULL;
+	gchar *subject, *from, *to, *cc;
+	gint32 i, count, flags;
+	time_t date;
+	GList *list;
+	gboolean deleted;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+	if (!read_summary (self->summary,
+			   SUMMARY_TYPE_UINT32, &flags, /* flags */
+			   -1)) {
+		return NULL;
+	}
+
+	deleted = ((flags & EVOLUTION_MESSAGE_JUNK) != 0 ||
+		   (flags & EVOLUTION_MESSAGE_DELETED) != 0);
+
+	subject = NULL;
+	from = NULL;
+	to = NULL;
+	cc = NULL;
+
+	if (!read_summary (self->summary,
+			   SUMMARY_TYPE_UINT32, NULL,	  /* size */
+			   SUMMARY_TYPE_TIME_T, NULL,	  /* date sent */
+			   SUMMARY_TYPE_TIME_T, &date,	  /* date received */
+			   SUMMARY_TYPE_STRING, &subject, /* subject */
+			   SUMMARY_TYPE_STRING, &from,	  /* from */
+			   SUMMARY_TYPE_STRING, &to,	  /* to */
+			   SUMMARY_TYPE_STRING, &cc,	  /* cc */
+			   SUMMARY_TYPE_STRING, NULL,	  /* mlist */
+			   -1)) {
+		g_free (subject);
+		g_free (from);
+		g_free (to);
+		g_free (cc);
+		return NULL;
+	}
+
+	if (!deleted) {
+		metadata = tracker_data_metadata_new ();
+
+		tracker_data_metadata_insert (metadata, METADATA_EMAIL_DATE,
+                                              tracker_guint_to_string (date));
+
+		tracker_data_metadata_insert (metadata, METADATA_EMAIL_SENDER, from);
+		tracker_data_metadata_insert (metadata, METADATA_EMAIL_SUBJECT, subject);
+
+		list = get_recipient_list (to);
+		tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_SENT_TO, list);
+
+		list = get_recipient_list (cc);
+		tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_CC, list);
+	}
+
+	g_free (to);
+	g_free (cc);
+
+	if (!read_summary (self->summary,
+			   SUMMARY_TYPE_INT32, NULL,
+			   SUMMARY_TYPE_INT32, NULL,
+			   SUMMARY_TYPE_UINT32, &count,
+			   -1)) {
+		goto corruption;
+	}
+
+	/* references */
+	for (i = 0; i < count; i++) {
+		if (read_summary (self->summary,
+				  SUMMARY_TYPE_INT32, NULL,
+				  SUMMARY_TYPE_INT32, NULL,
+				  -1)) {
+			continue;
+		}
+
+		goto corruption;
+	}
+
+	if (!read_summary (self->summary, SUMMARY_TYPE_UINT32, &count, -1)) {
+		goto corruption;
+	}
+
+	/* user flags */
+	for (i = 0; i < count; i++) {
+		if (read_summary (self->summary, SUMMARY_TYPE_STRING, NULL, -1)) {
+			continue;
+		}
+
+		goto corruption;
+	}
+
+	if (!read_summary (self->summary, SUMMARY_TYPE_UINT32, &count, -1)) {
+		goto corruption;
+	}
+
+	/* user tags */
+	for (i = 0; i < count; i++) {
+		if (read_summary (self->summary,
+				  SUMMARY_TYPE_STRING, NULL,
+				  SUMMARY_TYPE_STRING, NULL,
+				  -1)) {
+			continue;
+		}
+
+		goto corruption;
+	}
+
+	/* server flags */
+	if (!read_summary (self->summary,
+			   SUMMARY_TYPE_UINT32, NULL,
+			   -1)) {
+		goto corruption;
+	}
+
+	skip_content_info (self->summary);
+
+	return metadata;
+
+corruption:
+	/* assume corruption */
+	if (metadata) {
+		tracker_data_metadata_free (metadata);
+	}
+
+	return NULL;
+}
+
+static TrackerDataMetadata *
+get_attachment_metadata (TrackerModuleFile *file,
+                         const gchar       *mime_file)
+{
+	TrackerDataMetadata *metadata;
+	GMimeStream *stream;
+	GMimeDataWrapper *wrapper;
+	GMimePartEncodingType encoding;
+	gchar *path, *name;
+
+	if (!get_attachment_info (mime_file, &name, &encoding)) {
+		return NULL;
+	}
+
+	path = g_strdup (mime_file);
+	path = tracker_string_remove (path, ".MIME");
+
+#if defined(__linux__)
+	stream = evolution_common_get_stream (path, O_RDONLY | O_NOATIME, 0);
+#else
+	stream = evolution_common_get_stream (path, O_RDONLY, 0);
+#endif
+
+	if (!stream) {
+		g_free (name);
+		g_free (path);
+		return NULL;
+	}
+
+	wrapper = g_mime_data_wrapper_new_with_stream (stream, encoding);
+	metadata = evolution_common_get_wrapper_metadata (wrapper);
+
+	g_object_unref (wrapper);
+	g_object_unref (stream);
+	g_free (name);
+	g_free (path);
+
+	return metadata;
+}
+
+static TrackerDataMetadata *
+tracker_evolution_imap_file_get_metadata (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (file);
+
+	if (self->cur_message > self->n_messages) {
+		return NULL;
+	}
+
+	if (self->current_mime_part) {
+		return get_attachment_metadata (file, self->current_mime_part->data);
+	} else {
+                return get_message_metadata (file);
+        }
+}
+
+static GList *
+extract_mime_parts (TrackerEvolutionImapFile *self)
+{
+	gboolean has_attachment = TRUE;
+	gint n_attachment = 0;
+	gchar *message_path;
+	GList *mime_parts = NULL;
+
+	message_path = get_message_path (TRACKER_MODULE_FILE (self),
+                                         self->cur_message_uid);
+
+	while (has_attachment) {
+		gchar *mime_file;
+
+		n_attachment++;
+		mime_file = g_strdup_printf ("%s%d.MIME", message_path, n_attachment);
+
+		if (g_file_test (mime_file, G_FILE_TEST_EXISTS)) {
+			mime_parts = g_list_prepend (mime_parts, mime_file);
+		} else {
+			g_free (mime_file);
+			has_attachment = FALSE;
+		}
+	}
+
+	g_free (message_path);
+
+	return g_list_reverse (mime_parts);
+}
+
+static gboolean
+tracker_evolution_imap_file_iter_contents (TrackerModuleIteratable *iteratable)
+{
+        TrackerEvolutionImapFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (iteratable);
+
+        /* Iterate through mime parts, if any */
+        if (!self->mime_parts) {
+                self->mime_parts = extract_mime_parts (self);
+                self->current_mime_part = self->mime_parts;
+        } else {
+                self->current_mime_part = self->current_mime_part->next;
+        }
+
+        if (self->current_mime_part) {
+                return TRUE;
+        }
+
+        g_list_foreach (self->mime_parts, (GFunc) g_free, NULL);
+        g_list_free (self->mime_parts);
+        self->mime_parts = NULL;
+
+        g_free (self->cur_message_uid);
+        self->cur_message_uid = NULL;
+
+        /* save current message uid */
+        read_summary (self->summary,
+                      SUMMARY_TYPE_STRING, &self->cur_message_uid, /* message uid */
+                      -1);
+
+        self->cur_message++;
+
+        return (self->cur_message < self->n_messages);
+}
+
+static guint
+tracker_evolution_imap_file_get_count (TrackerModuleIteratable *iteratable)
+{
+        TrackerEvolutionImapFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_FILE (iteratable);
+
+        return self->n_messages;
+}
+
+void
+tracker_evolution_imap_file_register (GTypeModule *module)
+{
+        tracker_evolution_imap_file_register_type (module);
+}
+
+TrackerModuleFile *
+tracker_evolution_imap_file_new (GFile *file)
+{
+        return g_object_new (TRACKER_TYPE_EVOLUTION_IMAP_FILE,
+                             "file", file,
+                             NULL);
+}

Added: trunk/src/tracker-indexer/modules/evolution-imap.h
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-imap.h	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,68 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __TRACKER_EVOLUTION_IMAP_H__
+#define __TRACKER_EVOLUTION_IMAP_H__
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <tracker-indexer/tracker-module-file.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_EVOLUTION_IMAP_FILE         (tracker_evolution_imap_file_get_type())
+#define TRACKER_EVOLUTION_IMAP_FILE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_IMAP_FILE, TrackerEvolutionImapFile))
+#define TRACKER_EVOLUTION_IMAP_FILE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_EVOLUTION_IMAP_FILE, TrackerEvolutionImapFileClass))
+#define TRACKER_IS_EVOLUTION_IMAP_FILE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_EVOLUTION_IMAP_FILE))
+#define TRACKER_IS_EVOLUTION_IMAP_FILE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_EVOLUTION_IMAP_FILE))
+#define TRACKER_EVOLUTION_IMAP_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_EVOLUTION_IMAP_FILE, TrackerEvolutionImapFileClass))
+
+
+typedef struct TrackerEvolutionImapFile TrackerEvolutionImapFile;
+typedef struct TrackerEvolutionImapFileClass TrackerEvolutionImapFileClass;
+
+struct TrackerEvolutionImapFile {
+        TrackerModuleFile parent_instance;
+
+        gchar *imap_dir;
+
+        gint fd;
+        FILE *summary;
+        guint n_messages;
+        guint cur_message;
+        gchar *cur_message_uid;
+
+        GList *mime_parts;
+        GList *current_mime_part;
+};
+
+struct TrackerEvolutionImapFileClass {
+        TrackerModuleFileClass parent_class;
+};
+
+void                tracker_evolution_pop_file_register (GTypeModule *module);
+
+TrackerModuleFile * tracker_evolution_imap_file_new     (GFile *file);
+
+
+G_END_DECLS
+
+#endif /* __TRACKER_EVOLUTION_IMAP_H__ */

Added: trunk/src/tracker-indexer/modules/evolution-pop.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-pop.c	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,493 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <libtracker-data/tracker-data-metadata.h>
+#include <tracker-indexer/tracker-module-file.h>
+#include <tracker-indexer/tracker-module-iteratable.h>
+#include <string.h>
+#include <fcntl.h>
+#include "evolution-pop.h"
+#include "evolution-common.h"
+
+#define MODULE_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) \
+{ \
+    const GInterfaceInfo g_implement_interface_info = { \
+      (GInterfaceInitFunc) iface_init, NULL, NULL \
+  }; \
+  g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
+}
+
+static void          tracker_evolution_pop_file_finalize         (GObject *object);
+
+static void          tracker_evolution_pop_file_initialize       (TrackerModuleFile *file);
+static const gchar * tracker_evolution_pop_file_get_service_type (TrackerModuleFile *file);
+static gchar *       tracker_evolution_pop_file_get_uri          (TrackerModuleFile *file);
+static gchar *       tracker_evolution_pop_file_get_text         (TrackerModuleFile *file);
+static TrackerDataMetadata *
+                     tracker_evolution_pop_file_get_metadata     (TrackerModuleFile *file);
+
+static void          tracker_evolution_pop_file_iteratable_init  (TrackerModuleIteratableIface *iface);
+static gboolean      tracker_evolution_pop_file_iter_contents    (TrackerModuleIteratable *iteratable);
+static guint         tracker_evolution_pop_file_get_count        (TrackerModuleIteratable *iteratable);
+
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TrackerEvolutionPopFile, tracker_evolution_pop_file, TRACKER_TYPE_MODULE_FILE, 0,
+                                MODULE_IMPLEMENT_INTERFACE (TRACKER_TYPE_MODULE_ITERATABLE,
+                                                            tracker_evolution_pop_file_iteratable_init))
+
+
+static void
+tracker_evolution_pop_file_class_init (TrackerEvolutionPopFileClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        TrackerModuleFileClass *file_class = TRACKER_MODULE_FILE_CLASS (klass);
+
+        object_class->finalize = tracker_evolution_pop_file_finalize;
+
+        file_class->initialize = tracker_evolution_pop_file_initialize;
+        file_class->get_service_type = tracker_evolution_pop_file_get_service_type;
+        file_class->get_uri = tracker_evolution_pop_file_get_uri;
+        file_class->get_text = tracker_evolution_pop_file_get_text;
+        file_class->get_metadata = tracker_evolution_pop_file_get_metadata;
+}
+
+static void
+tracker_evolution_pop_file_class_finalize (TrackerEvolutionPopFileClass *klass)
+{
+}
+
+static void
+tracker_evolution_pop_file_init (TrackerEvolutionPopFile *file)
+{
+}
+
+static void
+tracker_evolution_pop_file_iteratable_init (TrackerModuleIteratableIface *iface)
+{
+        iface->iter_contents = tracker_evolution_pop_file_iter_contents;
+}
+
+static void
+tracker_evolution_pop_file_finalize (GObject *object)
+{
+        TrackerEvolutionPopFile *file;
+
+        file = TRACKER_EVOLUTION_POP_FILE (object);
+
+        if (file->mime_parts) {
+		g_list_foreach (file->mime_parts, (GFunc) g_object_unref, NULL);
+		g_list_free (file->mime_parts);
+	}
+
+	if (file->message) {
+		g_object_unref (file->message);
+	}
+
+	if (file->parser) {
+		g_object_unref (file->parser);
+	}
+
+	if (file->stream) {
+		g_mime_stream_close (file->stream);
+		g_object_unref (file->stream);
+	}
+
+        g_free (file->local_folder);
+
+        G_OBJECT_CLASS (tracker_evolution_pop_file_parent_class)->finalize (object);
+}
+
+static void
+tracker_evolution_pop_file_initialize (TrackerModuleFile *file)
+{
+        TrackerEvolutionPopFile *self;
+        gchar *path;
+
+        self = TRACKER_EVOLUTION_POP_FILE (file);
+        path = g_file_get_path (tracker_module_file_get_file (file));
+
+        self->local_folder = g_build_filename (g_get_home_dir (),
+                                               ".evolution", "mail", "local", G_DIR_SEPARATOR_S,
+                                               NULL);
+
+#if defined(__linux__)
+        self->stream = evolution_common_get_stream (path, O_RDONLY | O_NOATIME, 0);
+#else
+        self->stream = evolution_common_get_stream (path, O_RDONLY, 0);
+#endif
+
+        if (self->stream) {
+                self->parser = g_mime_parser_new_with_stream (self->stream);
+                g_mime_parser_set_scan_from (self->parser, TRUE);
+
+                /* Initialize to the first message */
+                self->message = g_mime_parser_construct_message (self->parser);
+        }
+
+        g_free (path);
+}
+
+static const gchar *
+tracker_evolution_pop_file_get_service_type (TrackerModuleFile *file)
+{
+        TrackerEvolutionPopFile *self;
+
+        self = TRACKER_EVOLUTION_POP_FILE (file);
+
+        if (self->current_mime_part) {
+                return "EvolutionAttachments";
+        }
+
+        return "EvolutionEmails";
+}
+
+static gint
+get_message_id (GMimeMessage *message)
+{
+	const gchar *header, *pos;
+	gchar *number;
+	gint id;
+
+	header = g_mime_message_get_header (message, "X-Evolution");
+
+        if (!header) {
+                return -1;
+        }
+
+        pos = strchr (header, '-');
+
+	number = g_strndup (header, pos - header);
+	id = strtoul (number, NULL, 16);
+
+	g_free (number);
+
+	return id;
+}
+
+static gchar *
+get_message_uri (TrackerModuleFile *file,
+                 GMimeMessage      *message)
+{
+        TrackerEvolutionPopFile *self;
+	gchar *path, *uri, *name;
+        gint message_id;
+
+        self = TRACKER_EVOLUTION_POP_FILE (file);
+        message_id = get_message_id (message);
+
+        if (message_id < 0) {
+                return NULL;
+        }
+
+        path = g_file_get_path (tracker_module_file_get_file (file));
+        path = tracker_string_remove (path, self->local_folder);
+	path = tracker_string_remove (path, ".sbd");
+
+        uri = g_strdup_printf ("email://local local/%s;uid=%d", path, message_id);
+
+        g_free (path);
+
+        return uri;
+}
+
+static gchar *
+tracker_evolution_pop_file_get_uri (TrackerModuleFile *file)
+{
+        TrackerEvolutionPopFile *self;
+        gchar *message_uri;
+
+        self = TRACKER_EVOLUTION_POP_FILE (file);
+
+        if (!self->message) {
+                return NULL;
+        }
+
+        message_uri = get_message_uri (file, self->message);
+
+        if (!message_uri) {
+                return NULL;
+        }
+
+        if (self->current_mime_part) {
+                gchar *attachment_uri;
+                const gchar *part_filename;
+
+                part_filename = g_mime_part_get_filename (self->current_mime_part->data);
+                attachment_uri = g_strdup_printf ("%s/%s", message_uri, part_filename);
+                g_free (message_uri);
+
+                return attachment_uri;
+        }
+
+        return message_uri;
+}
+
+static gchar *
+tracker_evolution_pop_file_get_text (TrackerModuleFile *file)
+{
+        TrackerEvolutionPopFile *self;
+        gchar *text, *encoding, *utf8_text;
+        gboolean is_html;
+
+        self = TRACKER_EVOLUTION_POP_FILE (file);
+
+	if (self->current_mime_part) {
+		/* FIXME: Extract text from attachments */
+		return NULL;
+	}
+
+        text = g_mime_message_get_body (self->message, TRUE, &is_html);
+
+        if (!text) {
+                return NULL;
+        }
+
+        encoding = evolution_common_get_object_encoding (GMIME_OBJECT (self->message));
+
+        if (!encoding) {
+                /* FIXME: could still puke on non-utf8
+                 * messages without proper content type
+                 */
+                return text;
+        }
+
+        utf8_text = g_convert (text, -1, "utf8", encoding, NULL, NULL, NULL);
+
+        g_free (encoding);
+        g_free (text);
+
+        return utf8_text;
+}
+
+static guint
+get_message_flags (GMimeMessage *message)
+{
+	const gchar *header, *pos;
+
+	header = g_mime_message_get_header (message, "X-Evolution");
+	pos = strchr (header, '-');
+
+	return (guint) strtoul (pos + 1, NULL, 16);
+}
+
+static GList *
+get_message_recipients (GMimeMessage *message,
+                        const gchar  *type)
+{
+	GList *list = NULL;
+	const InternetAddressList *addresses;
+
+	addresses = g_mime_message_get_recipients (message, type);
+
+	while (addresses) {
+		InternetAddress *address;
+		gchar *str;
+
+		address = addresses->address;
+
+		if (address->name && address->value.addr) {
+			str = g_strdup_printf ("%s %s", address->name, address->value.addr);
+		} else if (address->value.addr) {
+			str = g_strdup (address->value.addr);
+		} else if (address->name) {
+			str = g_strdup (address->name);
+		} else {
+			str = NULL;
+		}
+
+		if (str) {
+			list = g_list_prepend (list, str);
+		}
+
+		addresses = addresses->next;
+	}
+
+	return g_list_reverse (list);
+}
+
+static TrackerDataMetadata *
+get_message_metadata (GMimeMessage *message)
+{
+	TrackerDataMetadata *metadata;
+	time_t date;
+	GList *list;
+
+	metadata = tracker_data_metadata_new ();
+
+	g_mime_message_get_date (message, &date, NULL);
+	tracker_data_metadata_insert (metadata, METADATA_EMAIL_DATE,
+                                      tracker_guint_to_string (date));
+
+	tracker_data_metadata_insert (metadata, METADATA_EMAIL_SENDER,
+                                      g_strdup (g_mime_message_get_sender (message)));
+	tracker_data_metadata_insert (metadata, METADATA_EMAIL_SUBJECT,
+                                      g_strdup (g_mime_message_get_subject (message)));
+
+	list = get_message_recipients (message, GMIME_RECIPIENT_TYPE_TO);
+	tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_SENT_TO, list);
+
+	list = get_message_recipients (message, GMIME_RECIPIENT_TYPE_CC);
+	tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_CC, list);
+
+	return metadata;
+}
+
+static TrackerDataMetadata *
+get_attachment_metadata (GMimePart *part)
+{
+	TrackerDataMetadata *metadata;
+	GMimeDataWrapper *content;
+
+	content = g_mime_part_get_content_object (part);
+
+	if (!content) {
+		return NULL;
+	}
+
+	metadata = evolution_common_get_wrapper_metadata (content);
+	g_object_unref (content);
+
+	return metadata;
+}
+
+static TrackerDataMetadata *
+tracker_evolution_pop_file_get_metadata (TrackerModuleFile *file)
+{
+        TrackerEvolutionPopFile *self;
+        TrackerDataMetadata *metadata;
+        guint flags;
+
+        self = TRACKER_EVOLUTION_POP_FILE (file);
+
+        if (!self->message) {
+                return NULL;
+        }
+
+        flags = get_message_flags (self->message);
+
+	if (flags & EVOLUTION_MESSAGE_JUNK ||
+	    flags & EVOLUTION_MESSAGE_DELETED) {
+		return NULL;
+	}
+
+        if (self->current_mime_part) {
+                metadata = get_attachment_metadata (self->current_mime_part->data);
+        } else {
+                metadata = get_message_metadata (self->message);
+        }
+
+        return metadata;
+}
+
+static void
+extract_mime_parts (GMimeObject *object,
+                    gpointer     user_data)
+{
+	GList **list = (GList **) user_data;
+	const gchar *disposition, *filename;
+	GMimePart *part;
+
+	if (GMIME_IS_MESSAGE_PART (object)) {
+		GMimeMessage *message;
+
+		message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (object));
+
+		if (message) {
+			g_mime_message_foreach_part (message, extract_mime_parts, user_data);
+			g_object_unref (message);
+		}
+
+		return;
+	} else if (GMIME_IS_MULTIPART (object)) {
+		g_mime_multipart_foreach (GMIME_MULTIPART (object), extract_mime_parts, user_data);
+		return;
+	}
+
+	part = GMIME_PART (object);
+	disposition = g_mime_part_get_content_disposition (part);
+
+	if (!disposition ||
+	    (strcmp (disposition, GMIME_DISPOSITION_ATTACHMENT) != 0 &&
+	     strcmp (disposition, GMIME_DISPOSITION_INLINE) != 0)) {
+		return;
+	}
+
+	filename = g_mime_part_get_filename (GMIME_PART (object));
+
+	if (!filename ||
+	    strcmp (filename, "signature.asc") == 0 ||
+	    strcmp (filename, "signature.pgp") == 0) {
+		return;
+	}
+
+	*list = g_list_prepend (*list, g_object_ref (object));
+}
+
+static gboolean
+tracker_evolution_pop_file_iter_contents (TrackerModuleIteratable *iteratable)
+{
+        TrackerEvolutionPopFile *self;
+
+        self = TRACKER_EVOLUTION_POP_FILE (iteratable);
+
+        if (!self->parser) {
+                return FALSE;
+        }
+
+        if (self->message) {
+                /* Iterate through mime parts, if any */
+                if (!self->mime_parts) {
+                        g_mime_message_foreach_part (self->message,
+                                                     extract_mime_parts,
+                                                     &self->mime_parts);
+                        self->current_mime_part = self->mime_parts;
+                } else {
+                        self->current_mime_part = self->current_mime_part->next;
+                }
+
+                if (self->current_mime_part) {
+                        return TRUE;
+                }
+
+                /* all possible mime parts have been already iterated, move on */
+                g_object_unref (self->message);
+
+                g_list_foreach (self->mime_parts, (GFunc) g_object_unref, NULL);
+                g_list_free (self->mime_parts);
+                self->mime_parts = NULL;
+        }
+
+        self->message = g_mime_parser_construct_message (self->parser);
+
+        return (self->message != NULL);
+}
+
+void
+tracker_evolution_pop_file_register (GTypeModule *module)
+{
+        tracker_evolution_pop_file_register_type (module);
+}
+
+TrackerModuleFile *
+tracker_evolution_pop_file_new (GFile *file)
+{
+        return g_object_new (TRACKER_TYPE_EVOLUTION_POP_FILE,
+                             "file", file,
+                             NULL);
+}

Added: trunk/src/tracker-indexer/modules/evolution-pop.h
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-pop.h	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,64 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __TRACKER_EVOLUTION_POP_H__
+#define __TRACKER_EVOLUTION_POP_H__
+
+#include <glib.h>
+#include <tracker-indexer/tracker-module-file.h>
+#include <gmime/gmime.h>
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_EVOLUTION_POP_FILE         (tracker_evolution_pop_file_get_type())
+#define TRACKER_EVOLUTION_POP_FILE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_POP_FILE, TrackerEvolutionPopFile))
+#define TRACKER_EVOLUTION_POP_FILE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_EVOLUTION_POP_FILE, TrackerEvolutionPopFileClass))
+#define TRACKER_IS_EVOLUTION_POP_FILE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_EVOLUTION_POP_FILE))
+#define TRACKER_IS_EVOLUTION_POP_FILE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_EVOLUTION_POP_FILE))
+#define TRACKER_EVOLUTION_POP_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_EVOLUTION_POP_FILE, TrackerEvolutionPopFileClass))
+
+
+typedef struct TrackerEvolutionPopFile TrackerEvolutionPopFile;
+typedef struct TrackerEvolutionPopFileClass TrackerEvolutionPopFileClass;
+
+struct TrackerEvolutionPopFile {
+        TrackerModuleFile parent_instance;
+
+        gchar *local_folder;
+
+	GMimeStream *stream;
+	GMimeParser *parser;
+	GMimeMessage *message;
+
+	GList *mime_parts;
+	GList *current_mime_part;
+};
+
+struct TrackerEvolutionPopFileClass {
+        TrackerModuleFileClass parent_class;
+};
+
+void                tracker_evolution_pop_file_register (GTypeModule *module);
+
+TrackerModuleFile * tracker_evolution_pop_file_new      (GFile *file);
+
+
+G_END_DECLS
+
+#endif /* __TRACKER_EVOLUTION_POP_H__ */

Modified: trunk/src/tracker-indexer/modules/evolution.c
==============================================================================
--- trunk/src/tracker-indexer/modules/evolution.c	(original)
+++ trunk/src/tracker-indexer/modules/evolution.c	Thu Nov 20 15:29:19 2008
@@ -17,35 +17,10 @@
  * Boston, MA  02110-1301, USA.
  */
 
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gmime/gmime.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <string.h>
-#include <stdlib.h>
-#include <gconf/gconf-client.h>
-#include <tracker-indexer/tracker-module.h>
-#include <libtracker-data/tracker-data-metadata.h>
-#include <tracker-indexer/tracker-metadata-utils.h>
-#include <libtracker-common/tracker-utils.h>
-#include <libtracker-common/tracker-file-utils.h>
-#include <libtracker-common/tracker-type-utils.h>
+#include "evolution-pop.h"
+#include "evolution-imap.h"
 
-#define METADATA_FILE_PATH	     "File:Path"
-#define METADATA_FILE_NAME	     "File:Name"
-#define METADATA_EMAIL_RECIPIENT     "Email:Recipient"
-#define METADATA_EMAIL_DATE	     "Email:Date"
-#define METADATA_EMAIL_SENDER	     "Email:Sender"
-#define METADATA_EMAIL_SUBJECT	     "Email:Subject"
-#define METADATA_EMAIL_SENT_TO	     "Email:SentTo"
-#define METADATA_EMAIL_CC	     "Email:CC"
-
-typedef union EvolutionFileData EvolutionFileData;
-typedef struct EvolutionLocalData EvolutionLocalData;
-typedef struct EvolutionImapData EvolutionImapData;
-typedef struct EvolutionAccountContext EvolutionAccountContext;
 typedef enum MailStorageType MailStorageType;
 
 enum MailStorageType {
@@ -54,369 +29,30 @@
 	MAIL_STORAGE_IMAP
 };
 
-struct EvolutionLocalData {
-	MailStorageType type;
-	GMimeStream *stream;
-	GMimeParser *parser;
-	GMimeMessage *message;
-
-	GList *mime_parts;
-	GList *current_mime_part;
-};
-
-struct EvolutionImapData {
-	MailStorageType type;
-	gint fd;
-	FILE *summary;
-	guint n_messages;
-	guint cur_message;
-	gchar *cur_message_uid;
-
-	GList *mime_parts;
-	GList *current_mime_part;
-};
-
-union EvolutionFileData {
-	MailStorageType type;
-	EvolutionLocalData mbox;
-	EvolutionImapData imap;
-};
-
-enum SummaryDataType {
-	SUMMARY_TYPE_INT32,
-	SUMMARY_TYPE_UINT32,
-	SUMMARY_TYPE_STRING,
-	SUMMARY_TYPE_TOKEN,
-	SUMMARY_TYPE_TIME_T
-};
-
-struct EvolutionAccountContext {
-	gchar *account;
-	gchar *uid;
-};
-
-enum EvolutionFlags {
-	EVOLUTION_MESSAGE_ANSWERED     = 1 << 0,
-	EVOLUTION_MESSAGE_DELETED      = 1 << 1,
-	EVOLUTION_MESSAGE_DRAFT        = 1 << 2,
-	EVOLUTION_MESSAGE_FLAGGED      = 1 << 3,
-	EVOLUTION_MESSAGE_SEEN	       = 1 << 4,
-	EVOLUTION_MESSAGE_ATTACHMENTS  = 1 << 5,
-	EVOLUTION_MESSAGE_ANSWERED_ALL = 1 << 6,
-	EVOLUTION_MESSAGE_JUNK	       = 1 << 7,
-	EVOLUTION_MESSAGE_SECURE       = 1 << 8
-};
-
-
 static gchar *local_dir = NULL;
 static gchar *imap_dir = NULL;
-static GHashTable *accounts = NULL;
-
-
-void   get_imap_accounts (void);
-
-
-static gboolean
-read_summary (FILE *summary,
-	      ...)
-{
-	va_list args;
-	gint value_type;
-
-	if (!summary) {
-		return FALSE;
-	}
-
-	va_start (args, summary);
-
-	while ((value_type = va_arg (args, gint)) != -1) {
-		switch (value_type) {
-		case SUMMARY_TYPE_TIME_T: {
-                        time_t value = 0;
-                        time_t *dest;
-                        int size = sizeof (time_t) - 1;
-                        int c = EOF;
-
-                        while (size >= 0 && (c = fgetc (summary)) != EOF) {
-                                value |= ((time_t) c) << (size * 8);
-                                size--;
-                        }
-
-                        dest = va_arg (args, time_t*);
-
-                        if (dest) {
-                                *dest = value;
-                        }
-
-                        if (c == EOF) {
-                                return FALSE;
-                        }
-
-			break;
-		}
-		case SUMMARY_TYPE_INT32: {
-			gint32 value, *dest;
-
-			if (fread (&value, sizeof (gint32), 1, summary) != 1) {
-				return FALSE;
-			}
-
-			dest = va_arg (args, gint32*);
-
-			if (dest) {
-				*dest = g_ntohl (value);
-			}
-			break;
-		}
-		case SUMMARY_TYPE_UINT32: {
-			guint32 *dest, value = 0;
-			gint c;
-
-			while (((c = fgetc (summary)) & 0x80) == 0 && c != EOF) {
-				value |= c;
-				value <<= 7;
-			}
-
-			if (c == EOF) {
-				return FALSE;
-			} else {
-				value |= (c & 0x7f);
-			}
-
-			dest = va_arg (args, guint32*);
-
-			if (dest) {
-				*dest = value;
-			}
-			break;
-		}
-		case SUMMARY_TYPE_STRING:
-		case SUMMARY_TYPE_TOKEN: {
-			guint32 len;
-			gchar *str, **dest;
-
-			/* read string length */
-			read_summary (summary, SUMMARY_TYPE_UINT32, &len, -1);
-			dest = va_arg (args, gchar **);
-
-			if (dest) {
-				*dest = NULL;
-			}
-
-			if (value_type == SUMMARY_TYPE_TOKEN) {
-				if (len < 32) {
-					continue;
-				} else {
-					len -= 31;
-				}
-			}
-
-			if (len <= 1) {
-				continue;
-			}
-
-			str = g_try_malloc0 (len);
-			if (!str) {
-				return FALSE;
-			}
-
-			if (fread (str, len - 1, 1, summary) != 1) {
-				g_free (str);
-				return FALSE;
-			}
-
-			if (dest) {
-				*dest = str;
-			} else {
-				g_free (str);
-			}
-
-			break;
-		}
-		default:
-			break;
-		}
-	}
-
-	va_end (args);
-
-	return TRUE;
-}
 
 void
-tracker_module_init (void)
+indexer_module_initialize (GTypeModule *module)
 {
 	g_mime_init (0);
-	get_imap_accounts ();
 
 	local_dir = g_build_filename (g_get_home_dir (), ".evolution", "mail", "local", G_DIR_SEPARATOR_S, NULL);
 	imap_dir = g_build_filename (g_get_home_dir (), ".evolution", "mail", "imap", G_DIR_SEPARATOR_S, NULL);
+
+        tracker_evolution_pop_file_register (module);
+        tracker_evolution_imap_file_register (module);
 }
 
 void
-tracker_module_shutdown (void)
+indexer_module_shutdown (void)
 {
-	g_mime_shutdown ();
+        g_mime_shutdown ();
 
-	g_hash_table_destroy (accounts);
 	g_free (local_dir);
 	g_free (imap_dir);
 }
 
-G_CONST_RETURN gchar *
-tracker_module_get_name (void)
-{
-	/* Return module name here */
-	return "EvolutionEmails";
-}
-
-static void
-account_start_element_handler (GMarkupParseContext *context,
-			       const gchar	   *element_name,
-			       const gchar	   **attr_names,
-			       const gchar	   **attr_values,
-			       gpointer		   user_data,
-			       GError		   **error)
-{
-	EvolutionAccountContext *account_context;
-	gint i = 0;
-
-	if (strcmp (element_name, "account") != 0) {
-		return;
-	}
-
-	account_context = (EvolutionAccountContext *) user_data;
-
-	while (attr_names[i]) {
-		if (strcmp (attr_names[i], "uid") == 0) {
-			account_context->uid = g_strdup (attr_values[i]);
-			return;
-		}
-
-		i++;
-	}
-}
-
-static gchar *
-get_account_name_from_imap_uri (const gchar *imap_uri)
-{
-	const gchar *start, *at, *semic;
-	gchar *user_name, *at_host_name, *account_name;
-
-	/* Assume url schema is:
-	 * imap://foo imap free fr/;etc
-	 * or
-	 * imap://foo;auth=DIGEST-MD5 imap bar com/;etc
-	 *
-	 * We try to get "foo imap free fr".
-	 */
-
-	if (!g_str_has_prefix (imap_uri, "imap://")) {
-		return NULL;
-	}
-
-	user_name = at_host_name = account_name = NULL;
-
-	/* check for embedded @ and then look for first colon after that */
-	start = imap_uri + 7;
-	at = strchr (start, '@');
-	semic = strchr (start, ';');
-
-	if ( strlen (imap_uri) < 7 || at == NULL ) {
-		return g_strdup ("Unknown");
-	}
-
-	if (semic < at) {
-		/* we have a ";auth=FOO host" schema
-		   Set semic to the next semicolon, which ends the hostname. */
-		user_name = g_strndup (start, semic - start);
-		/* look for ';' at the end of the domain name */
-		semic = strchr (at, ';');
-	} else {
-		user_name = g_strndup (start, at - start);
-	}
-
-	at_host_name = g_strndup (at, (semic - 1) - at);
-
-	account_name = g_strconcat (user_name, at_host_name, NULL);
-
-	g_free (user_name);
-	g_free (at_host_name);
-
-	return account_name;
-}
-
-static void
-account_text_handler (GMarkupParseContext  *context,
-		      const gchar	   *text,
-		      gsize		    text_len,
-		      gpointer		    user_data,
-		      GError		  **error)
-{
-	EvolutionAccountContext *account_context;
-	const GSList *uri_element, *source_element;
-	gchar *url;
-
-	uri_element = g_markup_parse_context_get_element_stack (context);
-	source_element = uri_element->next;
-
-	if (strcmp ((gchar *) uri_element->data, "url") != 0 ||
-	    !source_element ||
-	    strcmp ((gchar *) source_element->data, "source") != 0) {
-		return;
-	}
-
-	account_context = (EvolutionAccountContext *) user_data;
-
-	url = g_strndup (text, text_len);
-	account_context->account = get_account_name_from_imap_uri (url);
-	g_free (url);
-}
-
-void
-get_imap_accounts (void)
-{
-	GConfClient *client;
-	GMarkupParser parser = { 0 };
-	GMarkupParseContext *parse_context;
-	GSList *list, *l;
-	EvolutionAccountContext account_context = { 0 };
-
-	client = gconf_client_get_default ();
-
-	list = gconf_client_get_list (client,
-				      "/apps/evolution/mail/accounts",
-				      GCONF_VALUE_STRING,
-				      NULL);
-
-	parser.start_element = account_start_element_handler;
-	parser.text = account_text_handler;
-	parse_context = g_markup_parse_context_new (&parser, 0, &account_context, NULL);
-
-	accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
-					  (GDestroyNotify) g_free,
-					  (GDestroyNotify) g_free);
-
-	for (l = list; l; l = l->next) {
-		g_markup_parse_context_parse (parse_context, (const gchar *) l->data, -1, NULL);
-
-		if (account_context.account &&
-		    account_context.uid) {
-			g_hash_table_insert (accounts,
-					     account_context.account,
-					     account_context.uid);
-		} else {
-			g_free (account_context.account);
-			g_free (account_context.uid);
-		}
-	}
-
-	g_markup_parse_context_free (parse_context);
-
-	g_slist_foreach (list, (GFunc) g_free, NULL);
-	g_slist_free (list);
-}
-
 static MailStorageType
 get_mail_storage_type_from_path (const gchar *path)
 {
@@ -448,1320 +84,21 @@
 	return type;
 }
 
-static GMimeStream *
-email_get_stream (const gchar *path,
-		  gint	       flags,
-		  off_t        start)
-{
-	GMimeStream *stream;
-	gint fd;
-
-	fd = g_open (path, flags, S_IRUSR | S_IWUSR);
-
-	if (fd == -1) {
-		return NULL;
-	}
-
-	stream = g_mime_stream_fs_new_with_bounds (fd, start, -1);
-
-	if (!stream) {
-		close (fd);
-	}
-
-	return stream;
-}
-
-static gint
-read_summary_header (FILE *summary)
+TrackerModuleFile *
+indexer_module_create_file (GFile *file)
 {
-	gint32 version, n_messages;
-
-	read_summary (summary,
-		      SUMMARY_TYPE_INT32, &version,
-		      SUMMARY_TYPE_INT32, NULL,		/* flags */
-		      SUMMARY_TYPE_INT32, NULL,		/* nextuid */
-		      SUMMARY_TYPE_TIME_T, NULL,	/* time */
-		      SUMMARY_TYPE_INT32, &n_messages,
-		      -1);
-
-	if ((version < 0x100 && version >= 13)) {
-		read_summary (summary,
-			      SUMMARY_TYPE_INT32, NULL, /* unread count*/
-			      SUMMARY_TYPE_INT32, NULL, /* deleted count*/
-			      SUMMARY_TYPE_INT32, NULL, /* junk count */
-			      -1);
-	}
-
-	if (version != 0x30c) {
-		read_summary (summary,
-			      SUMMARY_TYPE_INT32, NULL,
-			      SUMMARY_TYPE_INT32, NULL,
-			      -1);
-	}
-
-	return n_messages;
-}
-
-gpointer
-tracker_module_file_get_data (const gchar *path)
-{
-	EvolutionFileData *data = NULL;
 	MailStorageType type;
+        gchar *path;
 
-	type = get_mail_storage_type_from_path (path);
-
-	if (type == MAIL_STORAGE_NONE) {
-		return NULL;
-	}
-
-	data = g_slice_new0 (EvolutionFileData);
-	data->type = type;
-
-	if (type == MAIL_STORAGE_IMAP) {
-		EvolutionImapData *imap_data;
-
-		imap_data = (EvolutionImapData *) data;
-
-		imap_data->fd = tracker_file_open (path, TRUE);
-
-		if (imap_data->fd == -1) {
-			return NULL;
-		}
+        path = g_file_get_path (file);
+        type = get_mail_storage_type_from_path (path);
+        g_free (path);
 
-		imap_data->summary = fdopen (imap_data->fd, "r");
-		imap_data->n_messages = read_summary_header (imap_data->summary);
-		imap_data->cur_message = 1;
-
-                if (imap_data->n_messages > 0) {
-                        /* save current message uid */
-                        read_summary (imap_data->summary,
-                                      SUMMARY_TYPE_STRING, &imap_data->cur_message_uid,	/* message uid */
-                                      -1);
-                }
-        } else {
-		EvolutionLocalData *local_data;
-
-		local_data = (EvolutionLocalData *) data;
-
-#if defined(__linux__)
-		local_data->stream = email_get_stream (path, O_RDONLY | O_NOATIME, 0);
-#else
-		local_data->stream = email_get_stream (path, O_RDONLY, 0);
-#endif
-
-		if (local_data->stream) {
-			local_data->parser = g_mime_parser_new_with_stream (local_data->stream);
-			g_mime_parser_set_scan_from (local_data->parser, TRUE);
-
-			/* Initialize to the first message */
-			local_data->message = g_mime_parser_construct_message (local_data->parser);
-		}
-	}
-
-	return data;
-}
-
-static void
-free_imap_data (EvolutionImapData *data)
-{
-	fclose (data->summary);
-	close (data->fd);
-}
-
-static void
-free_local_data (EvolutionLocalData *data)
-{
-	if (data->mime_parts) {
-		g_list_foreach (data->mime_parts, (GFunc) g_object_unref, NULL);
-		g_list_free (data->mime_parts);
-	}
-
-	if (data->message) {
-		g_object_unref (data->message);
-	}
-
-	if (data->parser) {
-		g_object_unref (data->parser);
-	}
-
-	if (data->stream) {
-		g_mime_stream_close (data->stream);
-		g_object_unref (data->stream);
-	}
-}
-
-void
-tracker_module_file_free_data (gpointer file_data)
-{
-	EvolutionFileData *data;
-
-	data = (EvolutionFileData *) file_data;
-
-	if (data->type == MAIL_STORAGE_LOCAL) {
-		free_local_data ((EvolutionLocalData *) data);
-	} else if (data->type == MAIL_STORAGE_IMAP) {
-		free_imap_data ((EvolutionImapData *) data);
-	}
-
-	g_slice_free (EvolutionFileData, data);
-}
-
-static gint
-get_mbox_message_id (GMimeMessage *message)
-{
-	const gchar *header, *pos;
-	gchar *number;
-	gint id;
-
-	header = g_mime_message_get_header (message, "X-Evolution");
-
-        if (!header) {
-                return -1;
-        }
-
-        pos = strchr (header, '-');
-
-	number = g_strndup (header, pos - header);
-	id = strtoul (number, NULL, 16);
-
-	g_free (number);
-
-	return id;
-}
-
-static guint
-get_mbox_message_flags (GMimeMessage *message)
-{
-	const gchar *header, *pos;
-
-	header = g_mime_message_get_header (message, "X-Evolution");
-	pos = strchr (header, '-');
-
-	return (guint) strtoul (pos + 1, NULL, 16);
-}
-
-static void
-get_mbox_uri (TrackerFile   *file,
-	      GMimeMessage  *message,
-	      gchar	   **dirname,
-	      gchar	   **basename)
-{
-	gchar *dir, *name;
-        gint message_id;
-
-        message_id = get_mbox_message_id (message);
-
-        if (message_id < 0) {
-                *dirname = NULL;
-                *basename = NULL;
-                return;
+        if (type == MAIL_STORAGE_LOCAL) {
+                return tracker_evolution_pop_file_new (file);
+        } else if (type == MAIL_STORAGE_IMAP) {
+                return tracker_evolution_imap_file_new (file);
         }
 
-	dir = tracker_string_replace (file->path, local_dir, NULL);
-	dir = tracker_string_remove (dir, ".sbd");
-
-        name = g_strdup_printf ("%s;uid=%d", dir, message_id);
-
-	*dirname = g_strdup ("email://local local");
-	*basename = name;
-
-	g_free (dir);
-}
-
-static void
-get_mbox_attachment_uri (TrackerFile   *file,
-			 GMimeMessage  *message,
-			 GMimePart     *part,
-			 gchar	      **dirname,
-			 gchar	      **basename)
-{
-        gint message_id;
-	gchar *dir;
-
-        message_id = get_mbox_message_id (message);
-
-        if (message_id < 0) {
-                *dirname = NULL;
-                *basename = NULL;
-                return;
-        }
-
-	dir = tracker_string_replace (file->path, local_dir, NULL);
-	dir = tracker_string_remove (dir, ".sbd");
-
-	*dirname = g_strdup_printf ("email://local local/%s;uid=%d",
-				    dir, message_id);
-	*basename = g_strdup (g_mime_part_get_filename (part));
-
-	g_free (dir);
-}
-
-static GList *
-get_mbox_recipient_list (GMimeMessage *message,
-			 const gchar  *type)
-{
-	GList *list = NULL;
-	const InternetAddressList *addresses;
-
-	addresses = g_mime_message_get_recipients (message, type);
-
-	while (addresses) {
-		InternetAddress *address;
-		gchar *str;
-
-		address = addresses->address;
-
-		if (address->name && address->value.addr) {
-			str = g_strdup_printf ("%s %s", address->name, address->value.addr);
-		} else if (address->value.addr) {
-			str = g_strdup (address->value.addr);
-		} else if (address->name) {
-			str = g_strdup (address->name);
-		} else {
-			str = NULL;
-		}
-
-		if (str) {
-			list = g_list_prepend (list, str);
-		}
-
-		addresses = addresses->next;
-	}
-
-	return g_list_reverse (list);
-}
-
-static TrackerDataMetadata *
-get_metadata_for_data_wrapper (GMimeDataWrapper *wrapper)
-{
-	TrackerDataMetadata *metadata;
-	GMimeStream *stream;
-	gchar *path;
-	gint fd;
-
-	path = g_build_filename (g_get_tmp_dir (), "tracker-evolution-module-XXXXXX", NULL);
-	fd = g_mkstemp (path);
-	metadata = NULL;
-
-	stream = g_mime_stream_fs_new (fd);
-
-	if (g_mime_data_wrapper_write_to_stream (wrapper, stream) != -1) {
-		g_mime_stream_flush (stream);
-
-		metadata = tracker_metadata_utils_get_data (path);
-		g_unlink (path);
-	}
-
-	g_mime_stream_close (stream);
-	g_object_unref (stream);
-	g_free (path);
-
-	return metadata;
-}
-
-static TrackerDataMetadata *
-get_metadata_for_mbox_attachment (TrackerFile  *file,
-				  GMimeMessage *message,
-				  GMimePart    *part)
-{
-	TrackerDataMetadata *metadata;
-	GMimeDataWrapper *content;
-
-	content = g_mime_part_get_content_object (part);
-
-	if (!content) {
-		return NULL;
-	}
-
-	metadata = get_metadata_for_data_wrapper (content);
-
-	if (metadata) {
-		gchar *dirname, *basename;
-
-		get_mbox_attachment_uri (file, message, part,
-					 &dirname, &basename);
-
-		tracker_data_metadata_insert (metadata, METADATA_FILE_PATH, dirname);
-		tracker_data_metadata_insert (metadata, METADATA_FILE_NAME, basename);
-	}
-
-	g_object_unref (content);
-
-	return metadata;
-}
-
-static TrackerDataMetadata *
-get_metadata_for_mbox (TrackerFile *file)
-{
-	EvolutionLocalData *data;
-	GMimeMessage *message;
-	TrackerDataMetadata *metadata;
-	gchar *dirname, *basename;
-	time_t date;
-	GList *list;
-	guint flags;
-
-	data = file->data;
-	message = data->message;
-
-	if (!message) {
-		return NULL;
-	}
-
-	flags = get_mbox_message_flags (message);
-
-	if (flags & EVOLUTION_MESSAGE_JUNK ||
-	    flags & EVOLUTION_MESSAGE_DELETED) {
-		return NULL;
-	}
-
-	if (data->current_mime_part) {
-		/* We're processing an attachment */
-		return get_metadata_for_mbox_attachment (file, message, data->current_mime_part->data);
-	}
-
-	metadata = tracker_data_metadata_new ();
-
-	get_mbox_uri (file, message, &dirname, &basename);
-	tracker_data_metadata_insert (metadata, METADATA_FILE_PATH, dirname);
-	tracker_data_metadata_insert (metadata, METADATA_FILE_NAME, basename);
-
-	g_mime_message_get_date (message, &date, NULL);
-	tracker_data_metadata_insert (metadata, METADATA_EMAIL_DATE,
-				 tracker_guint_to_string (date));
-
-	tracker_data_metadata_insert (metadata, METADATA_EMAIL_SENDER,
-				 g_strdup (g_mime_message_get_sender (message)));
-	tracker_data_metadata_insert (metadata, METADATA_EMAIL_SUBJECT,
-				 g_strdup (g_mime_message_get_subject (message)));
-
-	list = get_mbox_recipient_list (message, GMIME_RECIPIENT_TYPE_TO);
-	tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_SENT_TO, list);
-
-	list = get_mbox_recipient_list (message, GMIME_RECIPIENT_TYPE_CC);
-	tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_CC, list);
-
-	return metadata;
-}
-
-static void
-skip_content_info (FILE *summary)
-{
-	guint32 count, i;
-
-	if (fgetc (summary)) {
-		read_summary (summary,
-			      SUMMARY_TYPE_TOKEN, NULL,
-			      SUMMARY_TYPE_TOKEN, NULL,
-			      SUMMARY_TYPE_UINT32, &count,
-			      -1);
-
-		if (count <= 500) {
-			for (i = 0; i < count; i++) {
-				read_summary (summary,
-					      SUMMARY_TYPE_TOKEN, NULL,
-					      SUMMARY_TYPE_TOKEN, NULL,
-					      -1);
-			}
-		}
-
-		read_summary (summary,
-			      SUMMARY_TYPE_TOKEN, NULL,
-			      SUMMARY_TYPE_TOKEN, NULL,
-			      SUMMARY_TYPE_TOKEN, NULL,
-			      SUMMARY_TYPE_UINT32, NULL,
-			      -1);
-	}
-
-	read_summary (summary,
-		      SUMMARY_TYPE_UINT32, &count,
-		      -1);
-
-	for (i = 0; i < count; i++) {
-		skip_content_info (summary);
-	}
-}
-
-static gboolean
-get_imap_attachment_info (const gchar		 *mime_file,
-			  gchar			**name,
-			  GMimePartEncodingType  *encoding)
-{
-	GMimeContentType *mime;
-	gchar *tmp, *mime_content;
-	const gchar *pos_content_type, *pos_encoding, *pos_end_encoding;
-
-	if (name) {
-		*name = NULL;
-	}
-
-	if (encoding) {
-		*encoding = GMIME_PART_ENCODING_DEFAULT;
-	}
-
-	if (!g_file_get_contents (mime_file, &tmp, NULL, NULL)) {
-		return FALSE;
-	}
-
-	/* all text content in lower case for comparisons */
-	mime_content = g_ascii_strdown (tmp, -1);
-	g_free (tmp);
-
-	pos_content_type = strstr (mime_content, "content-type:");
-
-	if (pos_content_type) {
-		pos_encoding = strstr (pos_content_type, "content-transfer-encoding:");
-	}
-
-	if (!pos_content_type || !pos_encoding) {
-		g_free (mime_content);
-		return FALSE;
-	}
-
-	pos_content_type += strlen ("content-type:");
-	pos_encoding += strlen ("content-transfer-encoding:");
-
-	/* ignore spaces, tab or line returns */
-	while (*pos_content_type != '\0' && (*pos_content_type == ' ' || *pos_content_type == '\t' || *pos_content_type == '\n')) {
-		pos_content_type++;
-	}
-
-	while (*pos_encoding != '\0' && *pos_encoding == ' ') {
-		pos_encoding++;
-	}
-
-	if (*pos_content_type == '\0' ||
-	    *pos_encoding == '\0') {
-		g_free (mime_content);
-		return FALSE;
-	}
-
-	mime = g_mime_content_type_new_from_string (pos_content_type);
-
-	if (mime) {
-		if (name) {
-			*name = g_strdup (g_mime_content_type_get_parameter (mime, "name"));
-		}
-
-		g_mime_content_type_destroy (mime);
-	}
-
-	if (name && !*name) {
-		g_free (mime_content);
-		return FALSE;
-	}
-
-	/* Find end of encoding */
-	pos_end_encoding = pos_encoding;
-
-	while (*pos_end_encoding != '\0' &&
-	       *pos_end_encoding != ' ' &&
-	       *pos_end_encoding != '\n' &&
-	       *pos_end_encoding != '\t') {
-		pos_end_encoding++;
-	}
-
-	if (encoding && pos_encoding != pos_end_encoding) {
-		gchar *encoding_str = g_strndup (pos_encoding, pos_end_encoding - pos_encoding);
-
-		if (strcmp (encoding_str, "7bit") == 0) {
-			*encoding = GMIME_PART_ENCODING_7BIT;
-		} else if (strcmp (encoding_str, "8bit") == 0) {
-			*encoding = GMIME_PART_ENCODING_7BIT;
-		} else if (strcmp (encoding_str, "binary") == 0) {
-			*encoding = GMIME_PART_ENCODING_BINARY;
-		} else if (strcmp (encoding_str, "base64") == 0) {
-			*encoding = GMIME_PART_ENCODING_BASE64;
-		} else if (strcmp (encoding_str, "quoted-printable") == 0) {
-			*encoding = GMIME_PART_ENCODING_QUOTEDPRINTABLE;
-		} else if (strcmp (encoding_str, "x-uuencode") == 0) {
-			*encoding = GMIME_PART_ENCODING_UUENCODE;
-		}
-
-		g_free (encoding_str);
-	}
-
-	g_free (mime_content);
-
-	return TRUE;
-}
-
-static void
-get_imap_uri (TrackerFile  *file,
-	      const gchar  *uid,
-	      gchar	  **uri_base,
-	      gchar	  **basename)
-{
-	GList *keys, *k;
-	gchar *path, *uri, *dir, *subdirs;
-
-	path = file->path;
-	keys = g_hash_table_get_keys (accounts);
-	*uri_base = *basename = NULL;
-
-	for (k = keys; k; k = k->next) {
-		if (strstr (path, k->data)) {
-			dir = g_build_filename (imap_dir, k->data, NULL);
-
-			/* now remove all relevant info to create the email:// basename */
-			subdirs = g_strdup (path);
-			subdirs = tracker_string_remove (subdirs, dir);
-			subdirs = tracker_string_remove (subdirs, "/folders/");
-			subdirs = tracker_string_remove (subdirs, "/subfolders");
-			subdirs = tracker_string_remove (subdirs, "/summary");
-
-                        uri = g_strdup_printf ("email://%s/%s;uid=%s",
-                                               (gchar *) g_hash_table_lookup (accounts, k->data),
-                                               subdirs, uid);
-
-                        tracker_file_get_path_and_name (uri, uri_base, basename);
-
-			g_free (subdirs);
-			g_free (dir);
-                        g_free (uri);
-
-			break;
-		}
-	}
-
-	g_list_free (keys);
-
-	return;
-}
-
-static void
-get_imap_attachment_uri (TrackerFile  *file,
-			 gchar	     **dirname,
-			 gchar	     **basename)
-{
-	EvolutionImapData *data;
-	gchar *message_dirname, *message_basename, *name;
-
-	data = file->data;
-
-	if (!get_imap_attachment_info (data->current_mime_part->data, &name, NULL)) {
-		return;
-	}
-
-	get_imap_uri (file, data->cur_message_uid, &message_dirname, &message_basename);
-	*dirname = g_strdup_printf ("%s/%s", message_dirname, message_basename);
-	*basename = name;
-
-	g_free (message_dirname);
-	g_free (message_basename);
-}
-
-static GList *
-get_imap_recipient_list (const gchar *str)
-{
-	GList *list = NULL;
-	gchar **arr;
-	gint i;
-
-	if (!str) {
-		return NULL;
-	}
-
-	arr = g_strsplit (str, ",", -1);
-
-	for (i = 0; arr[i]; i++) {
-		g_strstrip (arr[i]);
-		list = g_list_prepend (list, g_strdup (arr[i]));
-	}
-
-	g_strfreev (arr);
-
-	return g_list_reverse (list);
-}
-
-static gchar *
-get_imap_message_path (TrackerFile *file,
-		       const gchar *uid)
-{
-	gchar *prefix, *message_path;
-
-	prefix = g_strndup (file->path, strlen (file->path) - strlen ("summary"));
-	message_path = g_strconcat (prefix, uid, ".", NULL);
-	g_free (prefix);
-
-	return message_path;
-}
-
-static TrackerDataMetadata *
-get_metadata_for_imap_attachment (TrackerFile *file,
-				  const gchar *mime_file)
-{
-	TrackerDataMetadata *metadata;
-	GMimeStream *stream;
-	GMimeDataWrapper *wrapper;
-	GMimePartEncodingType encoding;
-	gchar *path, *name;
-
-	if (!get_imap_attachment_info (mime_file, &name, &encoding)) {
-		return NULL;
-	}
-
-	path = g_strdup (mime_file);
-	path = tracker_string_remove (path, ".MIME");
-
-#if defined(__linux__)
-	stream = email_get_stream (path, O_RDONLY | O_NOATIME, 0);
-#else
-	stream = email_get_stream (path, O_RDONLY, 0);
-#endif
-
-	if (!stream) {
-		g_free (name);
-		g_free (path);
-		return NULL;
-	}
-
-	wrapper = g_mime_data_wrapper_new_with_stream (stream, encoding);
-	metadata = get_metadata_for_data_wrapper (wrapper);
-
-	if (metadata) {
-		EvolutionImapData *data;
-		gchar *dirname, *basename;
-
-		data = file->data;
-
-		get_imap_uri (file,
-			      data->cur_message_uid,
-			      &dirname, &basename);
-
-		tracker_data_metadata_insert (metadata, METADATA_FILE_NAME, g_strdup (name));
-		tracker_data_metadata_insert (metadata, METADATA_FILE_PATH,
-					 g_strdup_printf ("%s/%s", dirname, basename));
-
-		g_free (dirname);
-		g_free (basename);
-	}
-
-	g_object_unref (wrapper);
-	g_object_unref (stream);
-	g_free (name);
-	g_free (path);
-
-	return metadata;
-}
-
-static TrackerDataMetadata *
-get_metadata_for_imap (TrackerFile *file)
-{
-	EvolutionImapData *data;
-	TrackerDataMetadata *metadata = NULL;
-	gchar *dirname, *basename;
-	gchar *subject, *from, *to, *cc;
-	gint32 i, count, flags;
-	time_t date;
-	GList *list;
-	gboolean deleted;
-
-	data = file->data;
-
-	if (data->cur_message > data->n_messages) {
-		return NULL;
-	}
-
-	if (data->current_mime_part) {
-		return get_metadata_for_imap_attachment (file, data->current_mime_part->data);
-	}
-
-	if (!read_summary (data->summary,
-			   SUMMARY_TYPE_UINT32, &flags, /* flags */
-			   -1)) {
-		return NULL;
-	}
-
-	deleted = ((flags & EVOLUTION_MESSAGE_JUNK) != 0 ||
-		   (flags & EVOLUTION_MESSAGE_DELETED) != 0);
-
-	subject = NULL;
-	from = NULL;
-	to = NULL;
-	cc = NULL;
-
-	if (!read_summary (data->summary,
-			   SUMMARY_TYPE_UINT32, NULL,	  /* size */
-			   SUMMARY_TYPE_TIME_T, NULL,	  /* date sent */
-			   SUMMARY_TYPE_TIME_T, &date,	  /* date received */
-			   SUMMARY_TYPE_STRING, &subject, /* subject */
-			   SUMMARY_TYPE_STRING, &from,	  /* from */
-			   SUMMARY_TYPE_STRING, &to,	  /* to */
-			   SUMMARY_TYPE_STRING, &cc,	  /* cc */
-			   SUMMARY_TYPE_STRING, NULL,	  /* mlist */
-			   -1)) {
-		g_free (subject);
-		g_free (from);
-		g_free (to);
-		g_free (cc);
-		return NULL;
-	}
-
-	if (!deleted) {
-		metadata = tracker_data_metadata_new ();
-		get_imap_uri (file, data->cur_message_uid, &dirname, &basename);
-
-		tracker_data_metadata_insert (metadata, METADATA_FILE_PATH, dirname);
-		tracker_data_metadata_insert (metadata, METADATA_FILE_NAME, basename);
-
-		tracker_data_metadata_insert (metadata, METADATA_EMAIL_DATE,
-					 tracker_guint_to_string (date));
-
-		tracker_data_metadata_insert (metadata, METADATA_EMAIL_SENDER, from);
-		tracker_data_metadata_insert (metadata, METADATA_EMAIL_SUBJECT, subject);
-
-		list = get_imap_recipient_list (to);
-		tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_SENT_TO, list);
-
-		list = get_imap_recipient_list (cc);
-		tracker_data_metadata_insert_values (metadata, METADATA_EMAIL_CC, list);
-	}
-
-	g_free (to);
-	g_free (cc);
-
-	if (!read_summary (data->summary,
-			   SUMMARY_TYPE_INT32, NULL,
-			   SUMMARY_TYPE_INT32, NULL,
-			   SUMMARY_TYPE_UINT32, &count,
-			   -1)) {
-		goto corruption;
-	}
-
-	/* references */
-	for (i = 0; i < count; i++) {
-		if (read_summary (data->summary,
-				  SUMMARY_TYPE_INT32, NULL,
-				  SUMMARY_TYPE_INT32, NULL,
-				  -1)) {
-			continue;
-		}
-
-		goto corruption;
-	}
-
-	if (!read_summary (data->summary, SUMMARY_TYPE_UINT32, &count, -1)) {
-		goto corruption;
-	}
-
-	/* user flags */
-	for (i = 0; i < count; i++) {
-		if (read_summary (data->summary, SUMMARY_TYPE_STRING, NULL, -1)) {
-			continue;
-		}
-
-		goto corruption;
-	}
-
-	if (!read_summary (data->summary, SUMMARY_TYPE_UINT32, &count, -1)) {
-		goto corruption;
-	}
-
-	/* user tags */
-	for (i = 0; i < count; i++) {
-		if (read_summary (data->summary,
-				  SUMMARY_TYPE_STRING, NULL,
-				  SUMMARY_TYPE_STRING, NULL,
-				  -1)) {
-			continue;
-		}
-
-		goto corruption;
-	}
-
-	/* server flags */
-	if (!read_summary (data->summary,
-			   SUMMARY_TYPE_UINT32, NULL,
-			   -1)) {
-		goto corruption;
-	}
-
-	skip_content_info (data->summary);
-
-	return metadata;
-
-corruption:
-	/* assume corruption */
-	if (metadata) {
-		tracker_data_metadata_free (metadata);
-	}
-
-	return NULL;
-}
-
-void
-tracker_module_file_get_uri (TrackerFile  *file,
-			     gchar	 **dirname,
-			     gchar	 **basename)
-{
-	EvolutionFileData *file_data;
-
-	file_data = file->data;
-
-	if (!file_data) {
-		/* It isn't any of the files the
-		 * module is interested for */
-		return;
-	}
-
-	switch (file_data->type) {
-	case MAIL_STORAGE_LOCAL: {
-		EvolutionLocalData *data = file->data;
-
-		if (!data->message) {
-			return;
-		}
-
-		if (data->current_mime_part) {
-			/* We're currently on an attachment */
-			get_mbox_attachment_uri (file, data->message,
-						 data->current_mime_part->data,
-						 dirname, basename);
-		} else {
-			get_mbox_uri (file, data->message, dirname, basename);
-		}
-
-		break;
-	}
-	case MAIL_STORAGE_IMAP: {
-		EvolutionImapData *data = file->data;
-
-		if (data->current_mime_part) {
-			/* We're currently on an attachment */
-			get_imap_attachment_uri (file, dirname, basename);
-		} else {
-			get_imap_uri (file, data->cur_message_uid, dirname, basename);
-		}
-
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-gchar *
-tracker_module_file_get_service_type (TrackerFile *file)
-{
-	EvolutionFileData *data;
-
-	data = file->data;
-
-	if (!data) {
-		/* It isn't any of the files the module handles */
-		return NULL;
-	}
-
-	if (data->type == MAIL_STORAGE_LOCAL) {
-		EvolutionLocalData *local_data = file->data;
-
-		if (local_data->current_mime_part) {
-			return g_strdup ("EvolutionAttachments");
-		}
-	} else if (data->type == MAIL_STORAGE_IMAP) {
-		EvolutionImapData *imap_data = file->data;
-
-		if (imap_data->current_mime_part) {
-			return g_strdup ("EvolutionAttachments");
-		}
-	}
-
-	return g_strdup ("EvolutionEmails");
-}
-
-TrackerDataMetadata *
-tracker_module_file_get_metadata (TrackerFile *file)
-{
-	EvolutionFileData *data;
-
-	data = file->data;
-
-	if (!data) {
-		/* It isn't any of the files the
-		 * module is interested for */
-		return NULL;
-	}
-
-	switch (data->type) {
-	case MAIL_STORAGE_LOCAL:
-		return get_metadata_for_mbox (file);
-	case MAIL_STORAGE_IMAP:
-		return get_metadata_for_imap (file);
-	default:
-		break;
-	}
-
-	return NULL;
-}
-
-static gchar *
-get_object_encoding (GMimeObject *object)
-{
-        const gchar *start_encoding, *end_encoding;
-        const gchar *content_type = NULL;
-
-        if (GMIME_IS_MESSAGE (object)) {
-                content_type = g_mime_message_get_header (GMIME_MESSAGE (object), "Content-Type");
-        } else if (GMIME_IS_PART (object)) {
-                content_type = g_mime_part_get_content_header (GMIME_PART (object), "Content-Type");
-        }
-
-        if (!content_type) {
-                return NULL;
-        }
-
-        start_encoding = strstr (content_type, "charset=");
-
-        if (!start_encoding) {
-                return NULL;
-        }
-
-        start_encoding += strlen ("charset=");
-
-        if (start_encoding[0] == '"') {
-                /* encoding is quoted */
-                start_encoding++;
-                end_encoding = strstr (start_encoding, "\"");
-        } else {
-                end_encoding = strstr (start_encoding, ";");
-        }
-
-        if (end_encoding) {
-                return g_strndup (start_encoding, end_encoding - start_encoding);
-        } else {
-                return g_strdup (start_encoding);
-        }
-}
-
-static gchar *
-get_text_for_mbox (TrackerFile *file)
-{
-        EvolutionLocalData *data;
-        gboolean is_html;
-        gchar *text, *encoding, *utf8_text;
-
-	data = file->data;
-
-	if (data->current_mime_part) {
-		/* FIXME: Extract text from attachments */
-		return NULL;
-	}
-
-        text = g_mime_message_get_body (data->message, TRUE, &is_html);
-
-        if (!text) {
-                return NULL;
-        }
-
-        encoding = get_object_encoding (GMIME_OBJECT (data->message));
-
-        if (!encoding) {
-                /* FIXME: could still puke on non-utf8
-                 * messages without proper content type
-                 */
-                return text;
-        }
-
-        utf8_text = g_convert (text, -1, "utf8", encoding, NULL, NULL, NULL);
-
-        g_free (encoding);
-        g_free (text);
-
-        return utf8_text;
-}
-
-static void
-extract_message_text (GMimeObject *object,
-                      gpointer     user_data)
-{
-        GString *body = (GString *) user_data;
-        GMimePartEncodingType part_encoding;
-        GMimePart *part;
-        const gchar *content, *disposition, *filename;
-        gchar *encoding, *part_body;
-        gsize len;
-
-        if (GMIME_IS_MESSAGE_PART (object)) {
-		GMimeMessage *message;
-
-		message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (object));
-
-		if (message) {
-			g_mime_message_foreach_part (message, extract_message_text, user_data);
-			g_object_unref (message);
-		}
-
-		return;
-        } else if (GMIME_IS_MULTIPART (object)) {
-                g_mime_multipart_foreach (GMIME_MULTIPART (object), extract_message_text, user_data);
-                return;
-        }
-
-	part = GMIME_PART (object);
-        filename = g_mime_part_get_filename (part);
-	disposition = g_mime_part_get_content_disposition (part);
-        part_encoding = g_mime_part_get_encoding (part);
-
-        if (part_encoding == GMIME_PART_ENCODING_BINARY ||
-            part_encoding == GMIME_PART_ENCODING_BASE64 ||
-            part_encoding == GMIME_PART_ENCODING_UUENCODE) {
-                return;
-        }
-
-	if (disposition &&
-	    strcmp (disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) {
-		return;
-	}
-
-        if (filename &&
-            (strcmp (filename, "signature.asc") == 0 ||
-             strcmp (filename, "signature.pgp") == 0)) {
-                return;
-        }
-
-        content = g_mime_part_get_content (GMIME_PART (object), &len);
-
-        if (!content) {
-                return;
-        }
-
-        if (g_utf8_validate (content, len, NULL)) {
-                g_string_append_len (body, content, (gssize) len);
-                return;
-        }
-
-        encoding = get_object_encoding (object);
-
-        if (!encoding) {
-                /* FIXME: This will break for non-utf8 text without
-                 * the proper content type set
-                 */
-                g_string_append_len (body, content, (gssize) len);
-        } else {
-                part_body = g_convert (content, (gssize) len, "utf8", encoding, NULL, NULL, NULL);
-                g_string_append (body, part_body);
-
-                g_free (part_body);
-                g_free (encoding);
-        }
-}
-
-static gchar *
-get_text_for_imap (TrackerFile *file)
-{
-	EvolutionImapData *data;
-	gchar *message_path;
-        GMimeStream *stream;
-        GMimeParser *parser;
-        GMimeMessage *message;
-        GString *body = NULL;
-
-	data = file->data;
-
-	if (data->current_mime_part) {
-		/* FIXME: Extract text from attachments */
-		return NULL;
-	}
-
-	message_path = get_imap_message_path (file, data->cur_message_uid);
-
-#if defined(__linux__)
-        stream = email_get_stream (message_path, O_RDONLY | O_NOATIME, 0);
-#else
-        stream = email_get_stream (message_path, O_RDONLY, 0);
-#endif
-
-        if (!stream) {
-                return NULL;
-        }
-
-        parser = g_mime_parser_new_with_stream (stream);
-        g_mime_parser_set_scan_from (parser, FALSE);
-        message = g_mime_parser_construct_message (parser);
-
-        if (message) {
-                body = g_string_new (NULL);
-                g_mime_message_foreach_part (message, extract_message_text, body);
-                g_object_unref (message);
-        }
-
-        g_object_unref (stream);
-        g_object_unref (parser);
-	g_free (message_path);
-
-	return (body) ? g_string_free (body, FALSE) : NULL;
-}
-
-gchar *
-tracker_module_file_get_text (TrackerFile *file)
-{
-	EvolutionFileData *data;
-	gchar *text = NULL;
-
-	data = file->data;
-
-	if (!data) {
-		/* It isn't any of the files the
-		 * module is interested in */
-		return NULL;
-	}
-
-	if (data->type == MAIL_STORAGE_LOCAL) {
-		text = get_text_for_mbox (file);
-	} else if (data->type == MAIL_STORAGE_IMAP) {
-		text = get_text_for_imap (file);
-	}
-
-	return text;
-}
-
-static GList *
-extract_imap_mime_parts (TrackerFile *file)
-{
-	EvolutionImapData *data;
-	gboolean has_attachment = TRUE;
-	gint n_attachment = 0;
-	gchar *message_path;
-	GList *mime_parts = NULL;
-
-	data = file->data;
-	message_path = get_imap_message_path (file, data->cur_message_uid);
-
-	while (has_attachment) {
-		gchar *mime_file;
-
-		n_attachment++;
-		mime_file = g_strdup_printf ("%s%d.MIME", message_path, n_attachment);
-
-		if (g_file_test (mime_file, G_FILE_TEST_EXISTS)) {
-			mime_parts = g_list_prepend (mime_parts, mime_file);
-		} else {
-			g_free (mime_file);
-			has_attachment = FALSE;
-		}
-	}
-
-	g_free (message_path);
-
-	return g_list_reverse (mime_parts);;
-}
-
-static void
-extract_mbox_mime_parts (GMimeObject *object,
-			 gpointer     user_data)
-{
-	GList **list = (GList **) user_data;
-	GMimePart *part;
-	const gchar *disposition, *filename;
-
-	if (GMIME_IS_MESSAGE_PART (object)) {
-		GMimeMessage *message;
-
-		message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (object));
-
-		if (message) {
-			g_mime_message_foreach_part (message, extract_mbox_mime_parts, user_data);
-			g_object_unref (message);
-		}
-
-		return;
-	} else if (GMIME_IS_MULTIPART (object)) {
-		g_mime_multipart_foreach (GMIME_MULTIPART (object), extract_mbox_mime_parts, user_data);
-		return;
-	}
-
-	part = GMIME_PART (object);
-	disposition = g_mime_part_get_content_disposition (part);
-
-	if (!disposition ||
-	    (strcmp (disposition, GMIME_DISPOSITION_ATTACHMENT) != 0 &&
-	     strcmp (disposition, GMIME_DISPOSITION_INLINE) != 0)) {
-		return;
-	}
-
-	filename = g_mime_part_get_filename (GMIME_PART (object));
-
-	if (!filename ||
-	    strcmp (filename, "signature.asc") == 0 ||
-	    strcmp (filename, "signature.pgp") == 0) {
-		return;
-	}
-
-	*list = g_list_prepend (*list, g_object_ref (object));
-}
-
-gboolean
-tracker_module_file_iter_contents (TrackerFile *file)
-{
-	EvolutionFileData *data;
-
-	data = file->data;
-
-	if (data->type == MAIL_STORAGE_IMAP) {
-		EvolutionImapData *imap_data = file->data;
-
-		/* Iterate through mime parts, if any */
-		if (!imap_data->mime_parts) {
-			imap_data->mime_parts = extract_imap_mime_parts (file);
-			imap_data->current_mime_part = imap_data->mime_parts;
-		} else {
-			imap_data->current_mime_part = imap_data->current_mime_part->next;
-		}
-
-		if (imap_data->current_mime_part) {
-			return TRUE;
-		}
-
-		g_list_foreach (imap_data->mime_parts, (GFunc) g_free, NULL);
-		g_list_free (imap_data->mime_parts);
-		imap_data->mime_parts = NULL;
-
-		g_free (imap_data->cur_message_uid);
-		imap_data->cur_message_uid = NULL;
-
-                /* save current message uid */
-                read_summary (imap_data->summary,
-                              SUMMARY_TYPE_STRING, &imap_data->cur_message_uid,	/* message uid */
-                              -1);
-
-		imap_data->cur_message++;
-
-		return (imap_data->cur_message < imap_data->n_messages);
-	} else if (data->type == MAIL_STORAGE_LOCAL) {
-		EvolutionLocalData *local_data = file->data;
-
-		if (!local_data->parser) {
-			return FALSE;
-		}
-
-		if (local_data->message) {
-			/* Iterate through mime parts, if any */
-			if (!local_data->mime_parts) {
-				g_mime_message_foreach_part (local_data->message,
-							     extract_mbox_mime_parts,
-							     &local_data->mime_parts);
-				local_data->current_mime_part = local_data->mime_parts;
-			} else {
-				local_data->current_mime_part = local_data->current_mime_part->next;
-			}
-
-			if (local_data->current_mime_part) {
-				return TRUE;
-			}
-
-			/* all possible mime parts have been already iterated, move on */
-			g_object_unref (local_data->message);
-
-			g_list_foreach (local_data->mime_parts, (GFunc) g_object_unref, NULL);
-			g_list_free (local_data->mime_parts);
-			local_data->mime_parts = NULL;
-		}
-
-		local_data->message = g_mime_parser_construct_message (local_data->parser);
-
-		return (local_data->message != NULL);
-	}
-
-	return FALSE;
+        return NULL;
 }

Modified: trunk/src/tracker-indexer/modules/files.c
==============================================================================
--- trunk/src/tracker-indexer/modules/files.c	(original)
+++ trunk/src/tracker-indexer/modules/files.c	Thu Nov 20 15:29:19 2008
@@ -25,22 +25,10 @@
 #include <glib/gstdio.h>
 #include <gio/gio.h>
 
-#include <libtracker-common/tracker-config.h>
 #include <libtracker-common/tracker-file-utils.h>
-#include <libtracker-common/tracker-os-dependant.h>
 #include <libtracker-common/tracker-ontology.h>
 #include <tracker-indexer/tracker-metadata-utils.h>
-#include <tracker-indexer/tracker-module.h>
-
-#define METADATA_FILE_NAME_DELIMITED "File:NameDelimited"
-#define METADATA_FILE_EXT	     "File:Ext"
-#define METADATA_FILE_PATH	     "File:Path"
-#define METADATA_FILE_NAME	     "File:Name"
-#define METADATA_FILE_LINK	     "File:Link"
-#define METADATA_FILE_MIMETYPE	     "File:Mime"
-#define METADATA_FILE_SIZE	     "File:Size"
-#define METADATA_FILE_MODIFIED	     "File:Modified"
-#define METADATA_FILE_ACCESSED	     "File:Accessed"
+#include <tracker-indexer/tracker-module-file.h>
 
 /* This is ONLY needed for the indexer to run standalone with
  * the -p option, otherwise it will pick up all sorts of crap
@@ -49,22 +37,64 @@
  */
 #undef ENABLE_FILE_EXCLUDE_CHECKING
 
-G_CONST_RETURN gchar *
-tracker_module_get_name (void)
+#define TRACKER_TYPE_REGULAR_FILE    (tracker_regular_file_get_type ())
+#define TRACKER_REGULAR_FILE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TRACKER_TYPE_REGULAR_FILE, TrackerRegularFile))
+
+typedef struct TrackerRegularFile TrackerRegularFile;
+typedef struct TrackerRegularFileClass TrackerRegularFileClass;
+
+struct TrackerRegularFile {
+        TrackerModuleFile parent_instance;
+};
+
+struct TrackerRegularFileClass {
+        TrackerModuleFileClass parent_class;
+};
+
+
+static const gchar *         tracker_regular_file_get_service_type (TrackerModuleFile *file);
+static gchar *               tracker_regular_file_get_text         (TrackerModuleFile *file);
+static TrackerDataMetadata * tracker_regular_file_get_metadata     (TrackerModuleFile *file);
+
+
+G_DEFINE_DYNAMIC_TYPE (TrackerRegularFile, tracker_regular_file, TRACKER_TYPE_MODULE_FILE);
+
+
+static void
+tracker_regular_file_class_init (TrackerRegularFileClass *klass)
+{
+        TrackerModuleFileClass *file_class = TRACKER_MODULE_FILE_CLASS (klass);
+
+        file_class->get_service_type = tracker_regular_file_get_service_type;
+        file_class->get_text = tracker_regular_file_get_text;
+        file_class->get_metadata = tracker_regular_file_get_metadata;
+}
+
+static void
+tracker_regular_file_class_finalize (TrackerRegularFileClass *klass)
 {
-	/* Return module name here */
-	return "Files";
 }
 
-gchar *
-tracker_module_file_get_service_type (TrackerFile *file)
+static void
+tracker_regular_file_init (TrackerRegularFile *file)
 {
-	gchar *mime_type;
-	gchar *service_type;
+}
 
-	mime_type = tracker_file_get_mime_type (file->path);
+static const gchar *
+tracker_regular_file_get_service_type (TrackerModuleFile *file)
+{
+        GFile *f;
+	const gchar *service_type;
+	gchar *mime_type, *path;
+
+        f = tracker_module_file_get_file (file);
+        path = g_file_get_path (f);
+
+	mime_type = tracker_file_get_mime_type (path);
 	service_type = tracker_ontology_get_service_by_mime (mime_type);
+
 	g_free (mime_type);
+        g_free (path);
 
 	return service_type;
 }
@@ -139,26 +169,46 @@
 
 #endif /* ENABLE_FILE_EXCLUDE_CHECKING */
 
-TrackerDataMetadata *
-tracker_module_file_get_metadata (TrackerFile *file)
+static TrackerDataMetadata *
+tracker_regular_file_get_metadata (TrackerModuleFile *file)
 {
 #ifdef ENABLE_FILE_EXCLUDE_CHECKING
 	if (check_exclude_file (file->path)) {
 		return NULL;
 	}
-#endif /* ENABLE_FILE_EXCLUDE_CHECKING */
+#endif
 
-	return tracker_metadata_utils_get_data (file->path);
+	return tracker_metadata_utils_get_data (tracker_module_file_get_file (file));
 }
 
-gchar *
-tracker_module_file_get_text (TrackerFile *file)
+static gchar *
+tracker_regular_file_get_text (TrackerModuleFile *file)
 {
 #ifdef ENABLE_FILE_EXCLUDE_CHECKING
 	if (check_exclude_file (file->path)) {
 		return NULL;
 	}
-#endif /* ENABLE_FILE_EXCLUDE_CHECKING */
+#endif
+
+	return tracker_metadata_utils_get_text (tracker_module_file_get_file (file));
+}
+
 
-	return tracker_metadata_utils_get_text (file->path);
+void
+indexer_module_initialize (GTypeModule *module)
+{
+        tracker_regular_file_register_type (module);
+}
+
+void
+indexer_module_shutdown (void)
+{
+}
+
+TrackerModuleFile *
+indexer_module_create_file (GFile *file)
+{
+        return g_object_new (TRACKER_TYPE_REGULAR_FILE,
+                             "file", file,
+                             NULL);
 }

Modified: trunk/src/tracker-indexer/tracker-indexer-module.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-indexer-module.c	(original)
+++ trunk/src/tracker-indexer/tracker-indexer-module.c	Thu Nov 20 15:29:19 2008
@@ -20,196 +20,121 @@
  */
 
 #include <gmodule.h>
-
 #include "tracker-indexer-module.h"
 
-GModule *
-tracker_indexer_module_load (const gchar *module_name)
-{
-	gchar *full_name, *path;
-	GModule *module;
-
-	g_return_val_if_fail (module_name != NULL, NULL);
 
-	full_name = g_strdup_printf ("libtracker-indexer-%s", module_name);
-	path = g_build_filename (INDEXER_MODULES_DIR, full_name, NULL);
+static gboolean tracker_indexer_module_load   (GTypeModule *module);
+static void     tracker_indexer_module_unload (GTypeModule *module);
 
-	module = g_module_open (path, G_MODULE_BIND_LOCAL);
 
-	if (!module) {
-		g_warning ("Could not load indexer module '%s', %s\n", module_name, g_module_error ());
-	} else {
-		g_module_make_resident (module);
-	}
-
-	g_free (full_name);
-	g_free (path);
-
-	return module;
-}
+G_DEFINE_TYPE (TrackerIndexerModule, tracker_indexer_module, G_TYPE_TYPE_MODULE)
 
-void
-tracker_indexer_module_init (GModule *module)
+static void
+tracker_indexer_module_class_init (TrackerIndexerModuleClass *klass)
 {
-	TrackerModuleInit func;
+  GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);
 
-	if (g_module_symbol (module, "tracker_module_init", (gpointer *) &func)) {
-		(func) ();
-	}
+  module_class->load = tracker_indexer_module_load;
+  module_class->unload = tracker_indexer_module_unload;
 }
 
-void
-tracker_indexer_module_shutdown (GModule *module)
+static void
+tracker_indexer_module_init (TrackerIndexerModule *module)
 {
-	TrackerModuleShutdown func;
-
-	if (g_module_symbol (module, "tracker_module_shutdown", (gpointer *) &func)) {
-		(func) ();
-	}
 }
 
-G_CONST_RETURN gchar *
-tracker_indexer_module_get_name (GModule *module)
+static gboolean
+tracker_indexer_module_load (GTypeModule *module)
 {
-	TrackerModuleGetNameFunc func;
-
-	if (g_module_symbol (module, "tracker_module_get_name", (gpointer *) &func)) {
-		return (func) ();
-	}
+	TrackerIndexerModule *indexer_module;
+	gchar *full_name, *path;
 
-	return NULL;
-}
+	indexer_module = TRACKER_INDEXER_MODULE (module);
 
-TrackerFile *
-tracker_indexer_module_file_new (GModule     *module,
-				 const gchar *path)
-{
-	TrackerModuleFileGetDataFunc func;
-	TrackerFile *file = NULL;
-
-	file = g_slice_new0 (TrackerFile);
-	file->path = g_strdup (path);
+	full_name = g_strdup_printf ("libtracker-indexer-%s", indexer_module->name);
+	path = g_build_filename (INDEXER_MODULES_DIR, full_name, NULL);
 
-	if (g_module_symbol (module, "tracker_module_file_get_data", (gpointer *) &func)) {
-		file->data = (func) (path);
-	}
+	indexer_module->module = g_module_open (path, G_MODULE_BIND_LOCAL);
 
-	return file;
-}
+	g_free (full_name);
+	g_free (path);
 
-void
-tracker_indexer_module_file_free (GModule     *module,
-				  TrackerFile *file)
-{
-	TrackerModuleFileFreeDataFunc func;
+	if (G_UNLIKELY (!indexer_module->module)) {
+		g_warning ("Could not load indexer module '%s': %s\n",
+			   indexer_module->name,
+			   g_module_error ());
 
-	if (file->data &&
-	    g_module_symbol (module, "tracker_module_file_free_data", (gpointer *) &func)) {
-		(func) (file->data);
+		return FALSE;
 	}
 
-	g_free (file->path);
-	g_slice_free (TrackerFile, file);
-}
-
-gboolean
-tracker_indexer_module_file_get_uri (GModule	  *module,
-				     TrackerFile  *file,
-				     gchar	 **dirname,
-				     gchar	 **basename)
-{
-	TrackerModuleFileGetUriFunc func;
-	gchar *tmp_dirname;
-	gchar *tmp_basename;
-
-	tmp_dirname = tmp_basename = NULL;
-
-	if (g_module_symbol (module, "tracker_module_file_get_uri", (gpointer *) &func)) {
-		(func) (file, &tmp_dirname, &tmp_basename);
-	} else {
-		tmp_dirname = g_path_get_dirname (file->path);
-		tmp_basename = g_path_get_basename (file->path);
-	}
+	g_module_make_resident (indexer_module->module);
 
-	if (tmp_dirname && tmp_basename) {
-		if (dirname) {
-			*dirname = tmp_dirname;
-		} else {
-			g_free (tmp_dirname);
-		}
-
-		if (basename) {
-			*basename = tmp_basename;
-		} else {
-			g_free (tmp_basename);
-		}
-
-		return TRUE;
-	} else {
-		g_free (tmp_dirname);
-		g_free (tmp_basename);
-
-		if (dirname) {
-			*dirname = NULL;
-		}
-
-		if (basename) {
-			*basename = NULL;
-		}
+	if (!g_module_symbol (indexer_module->module, "indexer_module_initialize",
+			      (gpointer *) &indexer_module->initialize) ||
+	    !g_module_symbol (indexer_module->module, "indexer_module_shutdown",
+			      (gpointer *) &indexer_module->shutdown) ||
+	    !g_module_symbol (indexer_module->module, "indexer_module_create_file",
+			      (gpointer *) &indexer_module->create_file)) {
+		g_warning ("Could not load module symbols for '%s': %s",
+			   indexer_module->name,
+			   g_module_error ());
 
 		return FALSE;
 	}
-}
 
-gchar *
-tracker_indexer_module_file_get_service_type (GModule	  *module,
-					      TrackerFile *file)
-{
-	TrackerModuleFileGetServiceTypeFunc func;
-
-	if (g_module_symbol (module, "tracker_module_file_get_service_type", (gpointer *) &func)) {
-		return (func) (file);
-	} else {
-		return g_strdup (tracker_indexer_module_get_name (module));
-	}
+	indexer_module->initialize (module);
 
+	return TRUE;
 }
 
-TrackerDataMetadata *
-tracker_indexer_module_file_get_metadata (GModule     *module,
-					  TrackerFile *file)
+static void
+tracker_indexer_module_unload (GTypeModule *module)
 {
-	TrackerModuleFileGetMetadataFunc func;
+	TrackerIndexerModule *indexer_module;
 
-	if (g_module_symbol (module, "tracker_module_file_get_metadata", (gpointer *) &func)) {
-		return (func) (file);
-	}
+	indexer_module = TRACKER_INDEXER_MODULE (module);
+	indexer_module->shutdown ();
+
+	g_module_close (indexer_module->module);
+	indexer_module->module = NULL;
 
-	return NULL;
+	indexer_module->initialize = NULL;
+	indexer_module->shutdown = NULL;
+	indexer_module->create_file = NULL;
 }
 
-gchar *
-tracker_indexer_module_file_get_text (GModule	  *module,
-				      TrackerFile *file)
+TrackerIndexerModule *
+tracker_indexer_module_get (const gchar *name)
 {
-	TrackerModuleFileGetText func;
+	static GHashTable *modules;
+	TrackerIndexerModule *module;
+
+	g_return_val_if_fail (name != NULL, NULL);
 
-	if (g_module_symbol (module, "tracker_module_file_get_text", (gpointer *) &func)) {
-		return (func) (file);
+	if (G_UNLIKELY (!modules)) {
+		modules = g_hash_table_new (g_str_hash, g_str_equal);
 	}
 
-	return NULL;
-}
+	module = g_hash_table_lookup (modules, name);
 
-gboolean
-tracker_indexer_module_file_iter_contents (GModule     *module,
-					   TrackerFile *file)
-{
-	TrackerModuleFileIterContents func;
+	if (G_UNLIKELY (!module)) {
+		module = g_object_new (TRACKER_TYPE_INDEXER_MODULE, NULL);
+		g_type_module_set_name (G_TYPE_MODULE (module), name);
+		module->name = g_strdup (name);
 
-	if (file->data && g_module_symbol (module, "tracker_module_file_iter_contents", (gpointer *) &func)) {
-		return (func) (file);
+		g_hash_table_insert (modules, module->name, module);
 	}
 
-	return FALSE;
+	if (!g_type_module_use (G_TYPE_MODULE (module))) {
+		return NULL;
+	}
+
+	return module;
+}
+
+TrackerModuleFile *
+tracker_indexer_module_create_file (TrackerIndexerModule *module,
+				    GFile                *file)
+{
+	return module->create_file (file);
 }

Modified: trunk/src/tracker-indexer/tracker-indexer-module.h
==============================================================================
--- trunk/src/tracker-indexer/tracker-indexer-module.h	(original)
+++ trunk/src/tracker-indexer/tracker-indexer-module.h	Thu Nov 20 15:29:19 2008
@@ -23,36 +23,39 @@
 #define __TRACKER_INDEXER_MODULE_H__
 
 #include <glib.h>
-#include "tracker-module.h"
-#include <libtracker-data/tracker-data-metadata.h>
+#include "tracker-module-file.h"
+#include "tracker-module-iteratable.h"
 
 G_BEGIN_DECLS
 
-GModule *		tracker_indexer_module_load		      (const gchar  *module_name);
+#define TRACKER_TYPE_INDEXER_MODULE    (tracker_indexer_module_get_type ())
+#define TRACKER_INDEXER_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TRACKER_TYPE_INDEXER_MODULE, TrackerIndexerModule))
 
-void			tracker_indexer_module_init		      (GModule	    *module);
-void			tracker_indexer_module_shutdown		      (GModule	    *module);
+typedef struct TrackerIndexerModule TrackerIndexerModule;
+typedef struct TrackerIndexerModuleClass TrackerIndexerModuleClass;
 
-G_CONST_RETURN gchar *	tracker_indexer_module_get_name		      (GModule	    *module);
+struct TrackerIndexerModule {
+	GTypeModule parent_instance;
 
-TrackerFile *		tracker_indexer_module_file_new		      (GModule	    *module,
-								       const gchar  *path);
-void			tracker_indexer_module_file_free	      (GModule	    *module,
-								       TrackerFile  *file);
-
-gboolean		tracker_indexer_module_file_get_uri	      (GModule	    *module,
-								       TrackerFile  *file,
-								       gchar	   **dirname,
-								       gchar	   **basename);
-gchar *			tracker_indexer_module_file_get_service_type  (GModule	    *module,
-								       TrackerFile  *file);
-TrackerDataMetadata *	tracker_indexer_module_file_get_metadata      (GModule	    *module,
-								       TrackerFile  *file);
-gchar *			tracker_indexer_module_file_get_text	      (GModule	    *module,
-								       TrackerFile  *file);
+	GModule *module;
+	gchar *name;
+
+	void (* initialize) (GTypeModule *module);
+	void (* shutdown) (void);
+	TrackerModuleFile * (* create_file) (GFile *file);
+};
+
+struct TrackerIndexerModuleClass {
+	GTypeModuleClass parent_class;
+};
+
+
+GType                   tracker_indexer_module_get_type               (void) G_GNUC_CONST;
+
+TrackerIndexerModule *  tracker_indexer_module_get                    (const gchar          *name);
+TrackerModuleFile *     tracker_indexer_module_create_file            (TrackerIndexerModule *module,
+								       GFile                *file);
 
-gboolean		tracker_indexer_module_file_iter_contents     (GModule	    *module,
-								       TrackerFile  *file);
 
 G_END_DECLS
 

Modified: trunk/src/tracker-indexer/tracker-indexer.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-indexer.c	(original)
+++ trunk/src/tracker-indexer/tracker-indexer.c	Thu Nov 20 15:29:19 2008
@@ -74,7 +74,6 @@
 #include "tracker-indexer.h"
 #include "tracker-indexer-module.h"
 #include "tracker-marshal.h"
-#include "tracker-module.h"
 
 #define TRACKER_INDEXER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_INDEXER, TrackerIndexerPrivate))
 
@@ -153,10 +152,11 @@
 };
 
 struct PathInfo {
-	GModule *module;
-	TrackerFile *file;
-	TrackerFile *other_file;
-	gchar *module_name;
+	TrackerIndexerModule *module;
+	GFile *file;
+	GFile *other_file;
+	TrackerModuleFile *module_file;
+	TrackerModuleFile *other_module_file;
 };
 
 struct MetadataForeachData {
@@ -209,22 +209,24 @@
 G_DEFINE_TYPE (TrackerIndexer, tracker_indexer, G_TYPE_OBJECT)
 
 static PathInfo *
-path_info_new (GModule *module,
-	       const gchar *module_name,
-	       const gchar *path,
-	       const gchar *other_path)
+path_info_new (TrackerIndexerModule *module,
+	       GFile                *file,
+	       GFile                *other_file)
 {
 	PathInfo *info;
 
 	info = g_slice_new (PathInfo);
 	info->module = module;
-	info->module_name = g_strdup (module_name);
-	info->file = tracker_indexer_module_file_new (module, path);
 
-	if (G_UNLIKELY (other_path)) {
-		info->other_file = tracker_indexer_module_file_new (module, other_path);
+	info->file = g_object_ref (file);
+	info->module_file = tracker_indexer_module_create_file (module, file);
+
+	if (G_UNLIKELY (other_file)) {
+		info->other_file = g_object_ref (other_file);
+		info->other_module_file = tracker_indexer_module_create_file (module, other_file);
 	} else {
 		info->other_file = NULL;
+		info->other_module_file = NULL;
 	}
 
 	return info;
@@ -234,11 +236,18 @@
 path_info_free (PathInfo *info)
 {
 	if (G_UNLIKELY (info->other_file)) {
-		tracker_indexer_module_file_free (info->module, info->other_file);
+		g_object_unref (info->other_file);
+	}
+
+	if (G_UNLIKELY (info->other_module_file)) {
+		g_object_unref (info->other_module_file);
+	}
+
+	if (G_LIKELY (info->module_file)) {
+		g_object_unref (info->module_file);
 	}
 
-	tracker_indexer_module_file_free (info->module, info->file);
-	g_free (info->module_name);
+	g_object_unref (info->file);
 	g_slice_free (PathInfo, info);
 }
 
@@ -634,13 +643,6 @@
 }
 
 static void
-close_module (GModule *module)
-{
-	tracker_indexer_module_shutdown (module);
-	g_module_close (module);
-}
-
-static void
 check_started (TrackerIndexer *indexer)
 {
 	TrackerIndexerState state;
@@ -859,23 +861,18 @@
 		g_quark_from_string (l->data);
 	}
 
-	priv->indexer_modules = g_hash_table_new_full (g_str_hash,
-						       g_str_equal,
-						       NULL,
-						       (GDestroyNotify) close_module);
+	priv->indexer_modules = g_hash_table_new (g_str_hash, g_str_equal);
 
 	for (l = priv->module_names; l; l = l->next) {
-		GModule *module;
+		TrackerIndexerModule *module;
 
 		if (!tracker_module_config_get_enabled (l->data)) {
 			continue;
 		}
 
-		module = tracker_indexer_module_load (l->data);
+		module = tracker_indexer_module_get (l->data);
 
 		if (module) {
-			tracker_indexer_module_init (module);
-
 			g_hash_table_insert (priv->indexer_modules,
 					     l->data, module);
 		}
@@ -1297,6 +1294,26 @@
 	g_hash_table_unref (new_words);
 }
 
+static TrackerService *
+get_service_for_file (TrackerModuleFile    *file,
+		      TrackerIndexerModule *module)
+{
+	TrackerService *service;
+	const gchar *service_type;
+
+	service_type = tracker_module_file_get_service_type (file);
+
+	if (!service_type) {
+		service_type = tracker_module_config_get_index_service (module->name);
+	}
+
+	if (!service_type) {
+		return NULL;
+	}
+
+	return tracker_ontology_get_service_by_name (service_type);
+}
+
 static gboolean
 remove_existing_non_emb_metadata (TrackerField *field,
 				  gpointer value,
@@ -1325,19 +1342,10 @@
 		    TrackerDataMetadata *metadata)
 {
 	TrackerService *service;
-	gchar *service_type;
 	gchar *text;
 	guint32 id;
 
-	service_type = tracker_indexer_module_file_get_service_type (info->module,
-								     info->file);
-
-	if (!service_type) {
-		return;
-	}
-
-	service = tracker_ontology_get_service_by_name (service_type);
-	g_free (service_type);
+	service = get_service_for_file (info->module_file, info->module);
 
 	if (!service) {
 		return;
@@ -1377,7 +1385,7 @@
 		 * difference and add the words.
 		 */
 		old_text = tracker_data_query_content (service, id);
-		new_text = tracker_indexer_module_file_get_text (info->module, info->file);
+		new_text = tracker_module_file_get_text (info->module_file);
 
 		item_update_content (indexer, service, id, old_text, new_text);
 		g_free (old_text);
@@ -1406,7 +1414,7 @@
 
 	index_metadata (indexer, id, service, metadata);
 
-	text = tracker_indexer_module_file_get_text (info->module, info->file);
+	text = tracker_module_file_get_text (info->module_file);
 
 	if (text) {
 		/* Save in the index */
@@ -1443,25 +1451,20 @@
 	TrackerDataMetadata *old_metadata, *new_metadata;
 	gchar *service_type;
 	gchar *new_path, *new_name, *ext;
+	GFile *file, *other_file;
+	gchar *path, *other_path;
 	guint32 id;
 
-	service_type = tracker_indexer_module_file_get_service_type (info->module,
-								     info->other_file);
-
-	if (!service_type) {
-		return;
-	}
-
-	service = tracker_ontology_get_service_by_name (service_type);
-	g_free (service_type);
+	service = get_service_for_file (info->other_module_file, info->module);
 
 	if (!service) {
 		return;
 	}
 
-	g_debug ("Moving item from '%s' to '%s'",
-		 info->file->path,
-		 info->other_file->path);
+	path = g_file_get_path (info->file);
+	other_path = g_file_get_path (info->other_file);
+
+	g_debug ("Moving item from '%s' to '%s'", path, other_path);
 
 	/* Get 'source' ID */
 	if (!tracker_data_query_service_exists (service,
@@ -1469,37 +1472,36 @@
 				       basename,
 				       &id,
 				       NULL)) {
-		g_message ("Source file '%s' not found in database to move",
-			   info->file->path);
+		g_message ("Source file '%s' not found in database to move", path);
+		g_free (path);
+		g_free (other_path);
+
 		return;
 	}
 
-	tracker_data_update_move_service (service,
-				 info->file->path,
-				 info->other_file->path);
+	tracker_data_update_move_service (service, path, other_path);
 
 	/*
 	 *  Updating what changes in move event (Path related properties)
 	 */
 	old_metadata = tracker_data_query_embedded_metadata (service, id);
 
-	tracker_data_metadata_foreach_remove (old_metadata, 
-					      filter_invalid_after_move_properties, 
+	tracker_data_metadata_foreach_remove (old_metadata,
+					      filter_invalid_after_move_properties,
 					      NULL);
 
 	unindex_metadata (indexer, id, service, old_metadata);
 
-	
 	new_metadata = tracker_data_metadata_new ();
 
-	tracker_file_get_path_and_name (info->other_file->path, &new_path, &new_name);
+	tracker_file_get_path_and_name (other_path, &new_path, &new_name);
 	tracker_data_metadata_insert (new_metadata, METADATA_FILE_PATH, new_path);
 	tracker_data_metadata_insert (new_metadata, METADATA_FILE_NAME, new_name);
-	tracker_data_metadata_insert (new_metadata, 
-				      METADATA_FILE_NAME_DELIMITED, 
-				      g_strdup (info->other_file->path));
+	tracker_data_metadata_insert (new_metadata,
+				      METADATA_FILE_NAME_DELIMITED,
+				      g_strdup (other_path));
 
-	ext = strrchr (info->other_file->path, '.');
+	ext = strrchr (other_path, '.');
 	if (ext) {
 		tracker_data_metadata_insert (new_metadata, METADATA_FILE_EXT, g_strdup (ext + 1));
 	}
@@ -1510,6 +1512,9 @@
 	/* tracker_data_metadata_free frees the values */
 	tracker_data_metadata_free (old_metadata);
 	tracker_data_metadata_free (new_metadata);
+
+	g_free (path);
+	g_free (other_path);
 }
 
 static void
@@ -1524,7 +1529,7 @@
 	const gchar *service_type;
 	guint service_id, service_type_id;
 
-	service_type = tracker_module_config_get_index_service (info->module_name);
+	service_type = tracker_module_config_get_index_service (info->module->name);
 
 	g_debug ("Removing item: '%s/%s' (no metadata was given by module)", 
 		 dirname, 
@@ -1880,21 +1885,14 @@
 		   const gchar	  *basename)
 {
 	TrackerService *service;
-	gchar *service_type;
+	gchar *path;
 	const gchar *str;
 	gboolean is_dir;
 	gboolean should_be_cached;
 	struct stat st;
 	time_t mtime;
 
-	service_type = tracker_indexer_module_file_get_service_type (info->module, info->file);
-
-	if (!service_type) {
-		return FALSE;
-	}
-
-	service = tracker_ontology_get_service_by_name (service_type);
-	g_free (service_type);
+	service = get_service_for_file (info->module_file, info->module);
 
 	if (!service) {
 		return TRUE;
@@ -1917,7 +1915,10 @@
 	 * the database. If it does, then we can ignore any files
 	 * immediately in this parent directory.
 	 */
-	if (g_lstat (info->file->path, &st) == -1) {
+	path = g_file_get_path (info->file);
+
+	if (g_lstat (path, &st) == -1) {
+		g_free (path);
 		return TRUE;
 	}
 
@@ -1958,7 +1959,7 @@
 	 * or not. All operations are done using the same string.
 	 */
 	if (is_dir) {
-		str = info->file->path;
+		str = path;
 	} else {
 		str = dirname;
 	}
@@ -1982,6 +1983,8 @@
 			 str,
 			 should_index ? "should index" : "should not index");
 
+		g_free (path);
+
 		return should_index;
 	}
 
@@ -2010,6 +2013,7 @@
 
 			g_free (parent_basename);
 			g_free (parent_dirname);
+			g_free (path);
 
 			return TRUE;
 		}
@@ -2020,6 +2024,7 @@
 
 			g_free (parent_basename);
 			g_free (parent_dirname);
+			g_free (path);
 
 			return TRUE;
 		}
@@ -2032,6 +2037,7 @@
 		g_debug ("%s:'%s' has indifferent mtime and should not be indexed",
 			 is_dir ? "Path" : "Parent path",
 			 str);
+		g_free (path);
 
 		return FALSE;
 	}
@@ -2045,30 +2051,41 @@
 			      g_strdup (str),
 			      GINT_TO_POINTER (1));
 
+	g_free (path);
+
 	return TRUE;
 }
+
 static gboolean
 process_file (TrackerIndexer *indexer,
 	      PathInfo	     *info)
 {
 	TrackerDataMetadata *metadata;
-	gchar *dirname;
-	gchar *basename;
+	gchar *uri, *dirname, *basename;
 
 	/* Note: If info->other_file is set, the PathInfo is for a
 	 * MOVE event not for normal file event.
 	 */
 
+	if (!info->module_file) {
+		return TRUE;
+	}
+
 	/* Set the current module */
-	indexer->private->current_module = g_quark_from_string (info->module_name);
+	indexer->private->current_module = g_quark_from_string (info->module->name);
+	uri = tracker_module_file_get_uri (info->module_file);
+
+	if (!uri) {
+		if (TRACKER_IS_MODULE_ITERATABLE (info->module_file)) {
+			return !tracker_module_iteratable_iter_contents (TRACKER_MODULE_ITERATABLE (info->module_file));
+		}
 
-	if (!tracker_indexer_module_file_get_uri (info->module,
-						  info->file,
-						  &dirname,
-						  &basename)) {
-		return !tracker_indexer_module_file_iter_contents (info->module, info->file);
+		return TRUE;
 	}
 
+	tracker_file_get_path_and_name (uri, &dirname, &basename);
+	g_free (uri);
+
 	/*
 	 * FIRST:
 	 * ======
@@ -2087,17 +2104,22 @@
 	 * basename which are returned by the module are combined to
 	 * look like:
 	 *
-	 *   email://1192717939 16218 20 petunia//INBOX;uid=1
+	 *   email://1192717939 16218 20 petunia/INBOX;uid=1
 	 *
 	 * We simply check the dirname[0] to make sure it isn't an
 	 * email based dirname.
 	 */
 	if (G_LIKELY (!info->other_file) && dirname[0] == G_DIR_SEPARATOR) {
 		if (!should_index_file (indexer, info, dirname, basename)) {
-			g_debug ("File is already up to date: '%s'", info->file->path);
+			gchar *path;
+
+			path = g_file_get_path (info->file);
+
+			g_debug ("File is already up to date: '%s'", path);
 
 			g_free (dirname);
 			g_free (basename);
+			g_free (path);
 
 			return TRUE;
 		}
@@ -2113,7 +2135,7 @@
 	if (G_UNLIKELY (info->other_file)) {
 		item_move (indexer, info, dirname, basename);
 	} else {
-		metadata = tracker_indexer_module_file_get_metadata (info->module, info->file);
+		metadata = tracker_module_file_get_metadata (info->module_file);
 
 		if (metadata) {
 			item_add_or_update (indexer, info, dirname, basename, metadata);
@@ -2128,7 +2150,11 @@
 	g_free (dirname);
 	g_free (basename);
 
-	return !tracker_indexer_module_file_iter_contents (info->module, info->file);
+	if (TRACKER_IS_MODULE_ITERATABLE (info->module_file)) {
+		return !tracker_module_iteratable_iter_contents (TRACKER_MODULE_ITERATABLE (info->module_file));
+	}
+
+	return TRUE;
 }
 
 static void
@@ -2136,39 +2162,48 @@
 		   PathInfo *info,
 		   gboolean recurse)
 {
+	gchar *path;
 	const gchar *name;
 	GDir *dir;
 
-	g_debug ("Processing directory:'%s'", info->file->path);
+	path = g_file_get_path (info->file);
+
+	/* FIXME: Use gio to iterate the directory */
+	g_debug ("Processing directory:'%s'", path);
 
-	dir = g_dir_open (info->file->path, 0, NULL);
+	dir = g_dir_open (path, 0, NULL);
 
 	if (!dir) {
+		g_free (path);
 		return;
 	}
 
 	while ((name = g_dir_read_name (dir)) != NULL) {
 		PathInfo *new_info;
-		gchar *path;
+		GFile *child;
+		gchar *child_path;
 
 		if (name[0] == '.') {
 			continue;
 		}
 
-		path = g_build_filename (info->file->path, name, NULL);
+		child = g_file_get_child (info->file, name);
+		child_path = g_file_get_path (child);
 
-		new_info = path_info_new (info->module, info->module_name, path, NULL);
+		new_info = path_info_new (info->module, child, NULL);
 		add_file (indexer, new_info);
 
-		if (recurse && g_file_test (path, G_FILE_TEST_IS_DIR)) {
-			new_info = path_info_new (info->module, info->module_name, path, NULL);
+		if (recurse && g_file_test (child_path, G_FILE_TEST_IS_DIR)) {
+			new_info = path_info_new (info->module, child, NULL);
 			add_directory (indexer, new_info);
 		}
 
-		g_free (path);
+		g_object_unref (child);
+		g_free (child_path);
 	}
 
 	g_dir_close (dir);
+	g_free (path);
 }
 
 static void
@@ -2193,7 +2228,7 @@
 process_module (TrackerIndexer *indexer,
 		const gchar *module_name)
 {
-	GModule *module;
+	TrackerIndexerModule *module;
 	GList *dirs, *d;
 
 	module = g_hash_table_lookup (indexer->private->indexer_modules, module_name);
@@ -2216,9 +2251,13 @@
 
 	for (d = dirs; d; d = d->next) {
 		PathInfo *info;
+		GFile *file;
 
-		info = path_info_new (module, module_name, d->data, NULL);
+		file = g_file_new_for_path (d->data);
+		info = path_info_new (module, file, NULL);
 		add_directory (indexer, info);
+
+		g_object_unref (file);
 	}
 
 	g_list_free (dirs);
@@ -2562,7 +2601,7 @@
 			     DBusGMethodInvocation *context,
 			     GError **error)
 {
-	GModule *module;
+	TrackerIndexerModule *module;
 	guint request_id;
 	gint i;
 	GError *actual_error = NULL;
@@ -2591,9 +2630,13 @@
 	/* Add files to the queue */
 	for (i = 0; files[i]; i++) {
 		PathInfo *info;
+		GFile *file;
 
-		info = path_info_new (module, module_name, files[i], NULL);
+		file = g_file_new_for_path (files[i]);
+		info = path_info_new (module, file, NULL);
 		add_file (indexer, info);
+
+		g_object_unref (file);
 	}
 
 	dbus_g_method_return (context);
@@ -2632,7 +2675,7 @@
 			   DBusGMethodInvocation  *context,
 			   GError		 **error)
 {
-	GModule *module;
+	TrackerIndexerModule *module;
 	guint request_id;
 	GError *actual_error;
 	PathInfo *info;
@@ -2660,7 +2703,9 @@
 	}
 
 	/* Add files to the queue */
-	info = path_info_new (module, module_name, from, to);
+	info = path_info_new (module,
+			      g_file_new_for_path (from),
+			      g_file_new_for_path (to));
 	add_file (indexer, info);
 
 	dbus_g_method_return (context);

Modified: trunk/src/tracker-indexer/tracker-metadata-utils.c
==============================================================================
--- trunk/src/tracker-indexer/tracker-metadata-utils.c	(original)
+++ trunk/src/tracker-indexer/tracker-metadata-utils.c	Thu Nov 20 15:29:19 2008
@@ -882,11 +882,11 @@
  * Returns: A newly allocated string containing the file text, or %NULL.
  **/
 gchar *
-tracker_metadata_utils_get_text (const gchar *path)
+tracker_metadata_utils_get_text (GFile *file)
 {
-	gchar *mime_type;
-	gchar *service_type;
-	gchar *text;
+	gchar *path, *mime_type, *service_type, *text;
+
+	path = g_file_get_path (file);
 
 	mime_type = tracker_file_get_mime_type (path);
 	service_type = tracker_ontology_get_service_by_mime (mime_type);
@@ -902,6 +902,7 @@
 
 	g_free (service_type);
 	g_free (mime_type);
+	g_free (path);
 
 	return text;
 }
@@ -916,14 +917,17 @@
  * Returns: A newly created #TrackerDataMetadata, or %NULL if the file is not found.
  **/
 TrackerDataMetadata *
-tracker_metadata_utils_get_data (const gchar *path)
+tracker_metadata_utils_get_data (GFile *file)
 {
 	TrackerDataMetadata *metadata;
 	struct stat st;
 	const gchar *ext;
-	gchar *mime_type;
+	gchar *mime_type, *path;
+
+	path = g_file_get_path (file);
 
 	if (g_lstat (path, &st) < 0) {
+		g_free (path);
 		return NULL;
 	}
 
@@ -937,13 +941,13 @@
 	mime_type = tracker_file_get_mime_type (path);
 
 	tracker_data_metadata_insert (metadata, METADATA_FILE_NAME,
-				 g_filename_display_basename (path));
+				      g_filename_display_basename (path));
 	tracker_data_metadata_insert (metadata, METADATA_FILE_PATH,
-				 g_path_get_dirname (path));
+				      g_path_get_dirname (path));
 	tracker_data_metadata_insert (metadata, METADATA_FILE_NAME_DELIMITED,
-				 g_filename_to_utf8 (path, -1, NULL, NULL, NULL));
+				      g_filename_to_utf8 (path, -1, NULL, NULL, NULL));
 	tracker_data_metadata_insert (metadata, METADATA_FILE_MIMETYPE,
-				 mime_type);
+				      mime_type);
 
 	if (mime_type) {
 		/* FIXME:
@@ -958,19 +962,21 @@
 
 		link_path = g_file_read_link (path, NULL);
 		tracker_data_metadata_insert (metadata, METADATA_FILE_LINK,
-					 g_filename_to_utf8 (link_path, -1, NULL, NULL, NULL));
+					      g_filename_to_utf8 (link_path, -1, NULL, NULL, NULL));
 		g_free (link_path);
 	}
 
 	/* FIXME: These should be dealt directly as integer/times/whatever, not strings */
 	tracker_data_metadata_insert (metadata, METADATA_FILE_SIZE,
-				 tracker_guint_to_string (st.st_size));
+				      tracker_guint_to_string (st.st_size));
 	tracker_data_metadata_insert (metadata, METADATA_FILE_MODIFIED,
-				 tracker_date_to_string (st.st_mtime));
+				      tracker_date_to_string (st.st_mtime));
 	tracker_data_metadata_insert (metadata, METADATA_FILE_ACCESSED,
-				 tracker_date_to_string (st.st_atime));
+				      tracker_date_to_string (st.st_atime));
 
 	metadata_utils_get_embedded (path, mime_type, metadata);
 
+	g_free (path);
+
 	return metadata;
 }

Modified: trunk/src/tracker-indexer/tracker-metadata-utils.h
==============================================================================
--- trunk/src/tracker-indexer/tracker-metadata-utils.h	(original)
+++ trunk/src/tracker-indexer/tracker-metadata-utils.h	Thu Nov 20 15:29:19 2008
@@ -23,11 +23,12 @@
 #define __TRACKER_METADATA_UTILS_H__
 
 #include <libtracker-data/tracker-data-metadata.h>
+#include <tracker-indexer/tracker-module-file.h>
 
 G_BEGIN_DECLS
 
-TrackerDataMetadata *tracker_metadata_utils_get_data (const gchar *path);
-gchar *		     tracker_metadata_utils_get_text (const gchar *path);
+TrackerDataMetadata *tracker_metadata_utils_get_data (GFile *file);
+gchar *		     tracker_metadata_utils_get_text (GFile *file);
 
 G_END_DECLS
 

Added: trunk/src/tracker-indexer/tracker-module-file.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/tracker-module-file.c	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,224 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <libtracker-common/tracker-file-utils.h>
+#include "tracker-module-file.h"
+
+#define METADATA_FILE_PATH	     "File:Path"
+#define METADATA_FILE_NAME	     "File:Name"
+
+#define TRACKER_MODULE_FILE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MODULE_FILE, TrackerModuleFilePrivate))
+
+typedef struct TrackerModuleFilePrivate TrackerModuleFilePrivate;
+
+struct TrackerModuleFilePrivate {
+        GFile *file;
+};
+
+enum {
+        PROP_0,
+        PROP_FILE
+};
+
+
+static void   tracker_module_file_finalize     (GObject      *object);
+static void   tracker_module_file_constructed  (GObject      *object);
+static void   tracker_module_file_set_property (GObject      *object,
+                                                guint         prop_id,
+                                                const GValue *value,
+                                                GParamSpec   *pspec);
+static void   tracker_module_file_get_property (GObject      *object,
+                                                guint         prop_id,
+                                                GValue       *value,
+                                                GParamSpec   *pspec);
+
+
+
+G_DEFINE_ABSTRACT_TYPE (TrackerModuleFile, tracker_module_file, G_TYPE_OBJECT)
+
+static void
+tracker_module_file_class_init (TrackerModuleFileClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->finalize = tracker_module_file_finalize;
+        object_class->constructed = tracker_module_file_constructed;
+        object_class->set_property = tracker_module_file_set_property;
+        object_class->get_property = tracker_module_file_get_property;
+
+        g_object_class_install_property (object_class,
+					 PROP_FILE,
+					 g_param_spec_object ("file",
+                                                              "File",
+                                                              "File corresponding to the TrackerModuleFile",
+                                                              G_TYPE_FILE,
+                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+        g_type_class_add_private (object_class, sizeof (TrackerModuleFilePrivate));
+}
+
+static void
+tracker_module_file_init (TrackerModuleFile *file)
+{
+}
+
+static void
+tracker_module_file_finalize (GObject *object)
+{
+        TrackerModuleFilePrivate *priv;
+
+        priv = TRACKER_MODULE_FILE_GET_PRIVATE (object);
+
+        g_object_unref (priv->file);
+
+        G_OBJECT_CLASS (tracker_module_file_parent_class)->finalize (object);
+}
+
+static void
+tracker_module_file_constructed (GObject *object)
+{
+        if (TRACKER_MODULE_FILE_GET_CLASS (object)->initialize) {
+                TrackerModuleFile *file;
+
+                file = TRACKER_MODULE_FILE (object);
+                TRACKER_MODULE_FILE_GET_CLASS (object)->initialize (file);
+        }
+
+        if (G_OBJECT_CLASS (tracker_module_file_parent_class)->constructed) {
+                G_OBJECT_CLASS (tracker_module_file_parent_class)->constructed (object);
+        }
+}
+
+static void
+tracker_module_file_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+        TrackerModuleFilePrivate *priv;
+
+        priv = TRACKER_MODULE_FILE_GET_PRIVATE (object);
+
+        switch (prop_id) {
+        case PROP_FILE:
+                priv->file = g_value_dup_object (value);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        }
+
+}
+
+static void
+tracker_module_file_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+        TrackerModuleFilePrivate *priv;
+
+        priv = TRACKER_MODULE_FILE_GET_PRIVATE (object);
+
+        switch (prop_id) {
+        case PROP_FILE:
+                g_value_set_object (value, priv->file);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        }
+}
+
+GFile *
+tracker_module_file_get_file (TrackerModuleFile *file)
+{
+        TrackerModuleFilePrivate *priv;
+
+        priv = TRACKER_MODULE_FILE_GET_PRIVATE (file);
+
+        return priv->file;
+}
+
+G_CONST_RETURN gchar *
+tracker_module_file_get_service_type (TrackerModuleFile *file)
+{
+        if (TRACKER_MODULE_FILE_GET_CLASS (file)->get_service_type == NULL) {
+                return NULL;
+        }
+
+        return TRACKER_MODULE_FILE_GET_CLASS (file)->get_service_type (file);
+}
+
+gchar *
+tracker_module_file_get_uri (TrackerModuleFile *file)
+{
+        gchar *uri = NULL;
+
+        if (TRACKER_MODULE_FILE_GET_CLASS (file)->get_uri) {
+                uri = TRACKER_MODULE_FILE_GET_CLASS (file)->get_uri (file);
+        }
+
+        if (!uri) {
+                GFile *f;
+
+                f = tracker_module_file_get_file (file);
+
+                /* FIXME: When we agree on storing URIs in the
+                 * database, this should stop returning the path
+                 */
+                uri = g_file_get_path (f);
+        }
+
+        return uri;
+}
+
+gchar *
+tracker_module_file_get_text (TrackerModuleFile *file)
+{
+        if (TRACKER_MODULE_FILE_GET_CLASS (file)->get_text == NULL) {
+                return NULL;
+        }
+
+        return TRACKER_MODULE_FILE_GET_CLASS (file)->get_text (file);
+}
+
+TrackerDataMetadata *
+tracker_module_file_get_metadata (TrackerModuleFile *file)
+{
+        TrackerDataMetadata *metadata = NULL;
+
+        if (TRACKER_MODULE_FILE_GET_CLASS (file)->get_metadata != NULL) {
+                metadata = TRACKER_MODULE_FILE_GET_CLASS (file)->get_metadata (file);
+        }
+
+        if (metadata &&
+            !tracker_data_metadata_lookup (metadata, METADATA_FILE_PATH) &&
+            !tracker_data_metadata_lookup (metadata, METADATA_FILE_NAME)) {
+                gchar *uri, *dirname, *basename;
+
+                uri = tracker_module_file_get_uri (file);
+                tracker_file_get_path_and_name (uri, &dirname, &basename);
+
+                tracker_data_metadata_insert (metadata, METADATA_FILE_PATH, dirname);
+                tracker_data_metadata_insert (metadata, METADATA_FILE_NAME, basename);
+
+                g_free (uri);
+        }
+
+        return metadata;
+}

Added: trunk/src/tracker-indexer/tracker-module-file.h
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/tracker-module-file.h	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,66 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __TRACKER_MODULE_FILE_H__
+#define __TRACKER_MODULE_FILE_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <libtracker-data/tracker-data-metadata.h>
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_MODULE_FILE         (tracker_module_file_get_type())
+#define TRACKER_MODULE_FILE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MODULE_FILE, TrackerModuleFile))
+#define TRACKER_MODULE_FILE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_MODULE_FILE, TrackerModuleFileClass))
+#define TRACKER_IS_MODULE_FILE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MODULE_FILE))
+#define TRACKER_IS_MODULE_FILE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_MODULE_FILE))
+#define TRACKER_MODULE_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_MODULE_FILE, TrackerModuleFileClass))
+
+
+typedef struct TrackerModuleFile TrackerModuleFile;
+typedef struct TrackerModuleFileClass TrackerModuleFileClass;
+
+struct TrackerModuleFile {
+        GObject parent_instance;
+};
+
+struct TrackerModuleFileClass {
+        GObjectClass parent_class;
+
+        void (* initialize) (TrackerModuleFile *file);
+        G_CONST_RETURN gchar * (* get_service_type) (TrackerModuleFile *file);
+        gchar * (* get_uri) (TrackerModuleFile *file);
+        gchar * (* get_text) (TrackerModuleFile *file);
+        TrackerDataMetadata * (* get_metadata) (TrackerModuleFile *file);
+};
+
+
+GType tracker_module_file_get_type (void) G_GNUC_CONST;
+
+GFile *                tracker_module_file_get_file         (TrackerModuleFile *file);
+G_CONST_RETURN gchar * tracker_module_file_get_service_type (TrackerModuleFile *file);
+gchar *                tracker_module_file_get_uri          (TrackerModuleFile *file);
+gchar *                tracker_module_file_get_text         (TrackerModuleFile *file);
+TrackerDataMetadata *  tracker_module_file_get_metadata     (TrackerModuleFile *file);
+
+
+G_END_DECLS
+
+#endif /* __TRACKER_MODULE_FILE_H__ */

Added: trunk/src/tracker-indexer/tracker-module-iteratable.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/tracker-module-iteratable.c	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,54 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "tracker-module-iteratable.h"
+#include "tracker-module-file.h"
+
+GType
+tracker_module_iteratable_get_type (void)
+{
+        static GType type = 0;
+
+        if (G_UNLIKELY (type == 0)) {
+                type = g_type_register_static_simple (G_TYPE_INTERFACE,
+                                                      "TrackerModuleIteratable",
+                                                      sizeof (TrackerModuleIteratableIface),
+                                                      NULL, 0, NULL, 0);
+
+                g_type_interface_add_prerequisite (type, TRACKER_TYPE_MODULE_FILE);
+        }
+
+        return type;
+}
+
+gboolean
+tracker_module_iteratable_iter_contents (TrackerModuleIteratable *iteratable)
+{
+        return TRACKER_MODULE_ITERATABLE_GET_IFACE (iteratable)->iter_contents (iteratable);
+}
+
+guint
+tracker_module_iteratable_get_count (TrackerModuleIteratable *iteratable)
+{
+        if (TRACKER_MODULE_ITERATABLE_GET_IFACE (iteratable)->get_count) {
+                return TRACKER_MODULE_ITERATABLE_GET_IFACE (iteratable)->get_count (iteratable);
+        }
+
+        return 0;
+}

Added: trunk/src/tracker-indexer/tracker-module-iteratable.h
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/tracker-module-iteratable.h	Thu Nov 20 15:29:19 2008
@@ -0,0 +1,52 @@
+/* Copyright (C) 2006, Mr Jamie McCracken (jamiemcc gnome org)
+ * Copyright (C) 2008, Nokia
+
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __TRACKER_MODULE_ITERATABLE_H__
+#define __TRACKER_MODULE_ITERATABLE_H__
+
+#include <glib-object.h>
+#include "tracker-module-file.h"
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_MODULE_ITERATABLE         (tracker_module_iteratable_get_type ())
+#define TRACKER_MODULE_ITERATABLE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MODULE_ITERATABLE, TrackerModuleIteratable))
+#define TRACKER_IS_MODULE_ITERATABLE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MODULE_ITERATABLE))
+#define TRACKER_MODULE_ITERATABLE_GET_IFACE(i) (G_TYPE_INSTANCE_GET_INTERFACE ((i), TRACKER_TYPE_MODULE_ITERATABLE, TrackerModuleIteratableIface))
+
+typedef struct TrackerModuleIteratable TrackerModuleIteratable; /* dummy typedef */
+typedef struct TrackerModuleIteratableIface TrackerModuleIteratableIface;
+
+struct TrackerModuleIteratableIface {
+        GTypeInterface parent_iface;
+
+        gboolean (* iter_contents) (TrackerModuleIteratable *iteratable);
+        guint (* get_count) (TrackerModuleIteratable *iteratable);
+};
+
+
+GType tracker_module_iteratable_get_type (void) G_GNUC_CONST;
+
+gboolean tracker_module_iteratable_iter_contents (TrackerModuleIteratable *iteratable);
+guint    tracker_module_iteratable_get_count     (TrackerModuleIteratable *iteratable);
+
+
+G_END_DECLS
+
+#endif /* __TRACKER_MODULE_ITERATABLE_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]