tracker r2740 - in trunk: . src/tracker-indexer/modules



Author: carlosg
Date: Tue Dec 23 17:24:38 2008
New Revision: 2740
URL: http://svn.gnome.org/viewvc/tracker?rev=2740&view=rev

Log:
2008-12-23  Carlos Garnacho  <carlos imendio com>

        Support new Evolution database storage. Based on a patch by Philip Van
        Hoof  <philip codeminded be>

        * src/tracker-indexer/modules/evolution-imap-db.[ch]: New
        TrackerModuleFile implementations which get messages information for
        the new Evolution sqlite storage.
        * src/tracker-indexer/modules/Makefile.am: Build evo modulewith
        sqlite3 libs/cflags, add the new files.
        * src/tracker-indexer/modules/evolution.c: Use the new implementation
        if folders.db is found.

Added:
   trunk/src/tracker-indexer/modules/evolution-imap-db.c
   trunk/src/tracker-indexer/modules/evolution-imap-db.h
Modified:
   trunk/ChangeLog
   trunk/src/tracker-indexer/modules/Makefile.am
   trunk/src/tracker-indexer/modules/evolution.c

Modified: trunk/src/tracker-indexer/modules/Makefile.am
==============================================================================
--- trunk/src/tracker-indexer/modules/Makefile.am	(original)
+++ trunk/src/tracker-indexer/modules/Makefile.am	Tue Dec 23 17:24:38 2008
@@ -17,7 +17,8 @@
 	$(GIO_CFLAGS)							\
 	$(GLIB2_CFLAGS)							\
 	$(GCONF_CFLAGS)							\
-	$(GMIME_CFLAGS)
+	$(GMIME_CFLAGS)							\
+	$(SQLITE3_CFLAGS)
 
 indexer_modules_LTLIBRARIES = 						\
 	libtracker-module-applications.la				\
@@ -57,6 +58,8 @@
 libtracker_module_evolution_la_SOURCES =				\
 	evolution-common.c						\
 	evolution-common.h						\
+	evolution-imap-db.c						\
+	evolution-imap-db.h						\
 	evolution-imap.c						\
 	evolution-imap.h						\
 	evolution-pop.c							\
@@ -68,6 +71,7 @@
 	$(GMODULE_LIBS)							\
 	$(GLIB2_LIBS)							\
 	$(GCONF_LIBS)							\
-	$(GMIME_LIBS)
+	$(GMIME_LIBS)							\
+	$(SQLITE3_LIBS)
 
 endif

Added: trunk/src/tracker-indexer/modules/evolution-imap-db.c
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-imap-db.c	Tue Dec 23 17:24:38 2008
@@ -0,0 +1,885 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * 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 "config.h"
+
+#include <string.h>
+
+#include <gconf/gconf-client.h>
+
+#include <libtracker-data/tracker-data-metadata.h>
+
+#include <tracker-indexer/tracker-module-file.h>
+#include <tracker-indexer/tracker-module-iteratable.h>
+
+#include "evolution-imap-db.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_db_file_finalize         (GObject *object);
+
+static void          tracker_evolution_imap_db_file_initialize       (TrackerModuleFile *file);
+static const gchar * tracker_evolution_imap_db_file_get_service_type (TrackerModuleFile *file);
+static gchar *       tracker_evolution_imap_db_file_get_uri          (TrackerModuleFile *file);
+static gchar *       tracker_evolution_imap_db_file_get_text         (TrackerModuleFile *file);
+static TrackerModuleMetadata *
+                     tracker_evolution_imap_db_file_get_metadata     (TrackerModuleFile *file);
+
+static void          tracker_evolution_imap_db_file_iteratable_init  (TrackerModuleIteratableIface *iface);
+static gboolean      tracker_evolution_imap_db_file_iter_contents    (TrackerModuleIteratable *iteratable);
+static guint         tracker_evolution_imap_db_file_get_count        (TrackerModuleIteratable *iteratable);
+
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TrackerEvolutionImapDbFile, tracker_evolution_imap_db_file, TRACKER_TYPE_MODULE_FILE, 0,
+                                MODULE_IMPLEMENT_INTERFACE (TRACKER_TYPE_MODULE_ITERATABLE,
+                                                            tracker_evolution_imap_db_file_iteratable_init))
+
+
+static void
+tracker_evolution_imap_db_file_class_init (TrackerEvolutionImapDbFileClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        TrackerModuleFileClass *file_class = TRACKER_MODULE_FILE_CLASS (klass);
+
+        object_class->finalize = tracker_evolution_imap_db_file_finalize;
+
+        file_class->initialize = tracker_evolution_imap_db_file_initialize;
+        file_class->get_service_type = tracker_evolution_imap_db_file_get_service_type;
+        file_class->get_uri = tracker_evolution_imap_db_file_get_uri;
+        file_class->get_text = tracker_evolution_imap_db_file_get_text;
+        file_class->get_metadata = tracker_evolution_imap_db_file_get_metadata;
+}
+
+static void
+tracker_evolution_imap_db_file_class_finalize (TrackerEvolutionImapDbFileClass *klass)
+{
+}
+
+static void
+tracker_evolution_imap_db_file_init (TrackerEvolutionImapDbFile *file)
+{
+}
+
+static void
+tracker_evolution_imap_db_file_iteratable_init (TrackerModuleIteratableIface *iface)
+{
+        iface->iter_contents = tracker_evolution_imap_db_file_iter_contents;
+        iface->get_count = tracker_evolution_imap_db_file_get_count;
+}
+
+static void
+tracker_evolution_imap_db_file_finalize (GObject *object)
+{
+        TrackerEvolutionImapDbFile *file;
+
+        file = TRACKER_EVOLUTION_IMAP_DB_FILE (object);
+
+        g_free (file->imap_dir);
+        g_free (file->cur_message_uid);
+
+	if (file->db) {
+		sqlite3_close (file->db);
+	}
+
+	if (file->stmt) {
+		sqlite3_finalize (file->stmt);
+	}
+
+        G_OBJECT_CLASS (tracker_evolution_imap_db_file_parent_class)->finalize (object);
+}
+
+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_db_file_initialize (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapDbFile *self;
+        gchar *path;
+	sqlite3_stmt *stmt;
+	gint result = SQLITE_OK;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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));
+	sqlite3_open (path, &self->db);
+	g_free (path);
+
+	sqlite3_prepare_v2 (self->db,
+			    "select saved_count from folders where folder_name = 'INBOX'",
+			    -1, &stmt, NULL);
+
+	result = sqlite3_step (stmt);
+	self->n_messages = sqlite3_column_int (stmt, 0);
+	self->cur_message = 1;
+
+	if (self->n_messages > 0) {
+		sqlite3_prepare_v2 (self->db,
+				    "SELECT uid, deleted, attachment, dsent, subject, mail_from, mail_to, mail_cc, mlist FROM INBOX",
+				    -1, &self->stmt, NULL);
+		if (self->stmt) {
+			result = sqlite3_step (self->stmt);
+			self->cur_message_uid = g_strdup (sqlite3_column_text (self->stmt, 0));
+			self->cur_message = 1;
+		}
+	}
+
+        ensure_imap_accounts ();
+}
+
+static const gchar *
+tracker_evolution_imap_db_file_get_service_type (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapDbFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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 ("folders.db"));
+        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)
+{
+        TrackerEvolutionImapDbFile *self;
+	gchar *path, *uri, *dir, *subdirs;
+        GList *keys, *k;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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_db_file_get_uri (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapDbFile *self;
+        gchar *message_uri, *part_filename;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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_db_file_get_text (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapDbFile *self;
+	gchar *message_path;
+        GMimeStream *stream;
+        GMimeParser *parser;
+        GMimeMessage *message;
+        GString *body = NULL;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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 TrackerModuleMetadata *
+get_message_metadata (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapDbFile *self;
+	TrackerModuleMetadata *metadata = NULL;
+	gchar *subject, *from, *to, *cc, *date;
+	GList *list, *l;
+	gboolean deleted;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_FILE (file);
+
+	deleted = sqlite3_column_int (self->stmt, 1);
+	/* hasattach = sqlite3_column_int (self->stmt, 2); */
+	date = g_strdup (sqlite3_column_text (self->stmt, 3));
+	subject = g_strdup (sqlite3_column_text (self->stmt, 4));
+	from = g_strdup (sqlite3_column_text (self->stmt, 5));
+	to = g_strdup (sqlite3_column_text (self->stmt, 6));
+	cc = g_strdup (sqlite3_column_text (self->stmt, 7));
+
+	if (!deleted) {
+		metadata = tracker_module_metadata_new ();
+
+		tracker_module_metadata_add_string (metadata, METADATA_EMAIL_DATE, date);
+		tracker_module_metadata_add_string (metadata, METADATA_EMAIL_SENDER, from);
+		tracker_module_metadata_add_string (metadata, METADATA_EMAIL_SUBJECT, subject);
+
+		list = get_recipient_list (to);
+
+		for (l = list; l; l = l->next) {
+			tracker_module_metadata_add_string (metadata, METADATA_EMAIL_SENT_TO, l->data);
+			g_free (l->data);
+		}
+
+		g_list_free (list);
+
+		list = get_recipient_list (cc);
+
+		for (l = list; l; l = l->next) {
+			tracker_module_metadata_add_string (metadata, METADATA_EMAIL_CC, l->data);
+			g_free (l->data);
+		}
+
+		g_list_free (list);
+	}
+
+	g_free (subject);
+	g_free (from);
+	g_free (to);
+	g_free (cc);
+
+	return metadata;
+}
+
+static TrackerModuleMetadata *
+get_attachment_metadata (TrackerModuleFile *file,
+                         const gchar       *mime_file)
+{
+	TrackerModuleMetadata *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 TrackerModuleMetadata *
+tracker_evolution_imap_db_file_get_metadata (TrackerModuleFile *file)
+{
+        TrackerEvolutionImapDbFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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 (TrackerEvolutionImapDbFile *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_db_file_iter_contents (TrackerModuleIteratable *iteratable)
+{
+        TrackerEvolutionImapDbFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_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;
+
+	self->cur_message_uid = g_strdup (sqlite3_column_text (self->stmt, 0));
+	sqlite3_step (self->stmt);
+
+        self->cur_message++;
+
+        return (self->cur_message < self->n_messages);
+}
+
+static guint
+tracker_evolution_imap_db_file_get_count (TrackerModuleIteratable *iteratable)
+{
+        TrackerEvolutionImapDbFile *self;
+
+        self = TRACKER_EVOLUTION_IMAP_DB_FILE (iteratable);
+
+        return self->n_messages;
+}
+
+void
+tracker_evolution_imap_db_file_register (GTypeModule *module)
+{
+        tracker_evolution_imap_db_file_register_type (module);
+}
+
+TrackerModuleFile *
+tracker_evolution_imap_db_file_new (GFile *file)
+{
+        return g_object_new (TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE,
+                             "file", file,
+                             NULL);
+}

Added: trunk/src/tracker-indexer/modules/evolution-imap-db.h
==============================================================================
--- (empty file)
+++ trunk/src/tracker-indexer/modules/evolution-imap-db.h	Tue Dec 23 17:24:38 2008
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * 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 <stdlib.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <sqlite3.h>
+
+#include <tracker-indexer/tracker-module-file.h>
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE         (tracker_evolution_imap_db_file_get_type())
+#define TRACKER_EVOLUTION_IMAP_DB_FILE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE, TrackerEvolutionImapDbFile))
+#define TRACKER_EVOLUTION_IMAP_DB_FILE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE, TrackerEvolutionImapDbFileClass))
+#define TRACKER_IS_EVOLUTION_IMAP_DB_FILE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE))
+#define TRACKER_IS_EVOLUTION_IMAP_DB_FILE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE))
+#define TRACKER_EVOLUTION_IMAP_DB_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_EVOLUTION_IMAP_DB_FILE, TrackerEvolutionImapDbFileClass))
+
+
+typedef struct TrackerEvolutionImapDbFile TrackerEvolutionImapDbFile;
+typedef struct TrackerEvolutionImapDbFileClass TrackerEvolutionImapDbFileClass;
+
+struct TrackerEvolutionImapDbFile {
+        TrackerModuleFile parent_instance;
+
+        gchar *imap_dir;
+
+	sqlite3 *db;
+	sqlite3_stmt *stmt;
+
+        guint n_messages;
+        guint cur_message;
+        gchar *cur_message_uid;
+
+        GList *mime_parts;
+        GList *current_mime_part;
+};
+
+struct TrackerEvolutionImapDbFileClass {
+        TrackerModuleFileClass parent_class;
+};
+
+GType               tracker_evolution_imap_db_file_get_type (void) G_GNUC_CONST;
+
+void                tracker_evolution_imap_db_file_register (GTypeModule *module);
+
+TrackerModuleFile * tracker_evolution_imap_db_file_new      (GFile *file);
+
+
+G_END_DECLS
+
+#endif /* __TRACKER_EVOLUTION_IMAP_H__ */

Modified: trunk/src/tracker-indexer/modules/evolution.c
==============================================================================
--- trunk/src/tracker-indexer/modules/evolution.c	(original)
+++ trunk/src/tracker-indexer/modules/evolution.c	Tue Dec 23 17:24:38 2008
@@ -26,13 +26,15 @@
 
 #include "evolution-pop.h"
 #include "evolution-imap.h"
+#include "evolution-imap-db.h"
 
 typedef enum MailStorageType MailStorageType;
 
 enum MailStorageType {
 	MAIL_STORAGE_NONE,
 	MAIL_STORAGE_LOCAL,
-	MAIL_STORAGE_IMAP
+	MAIL_STORAGE_IMAP,
+	MAIL_STORAGE_IMAP_DB
 };
 
 static gchar *local_dir = NULL;
@@ -70,9 +72,12 @@
 	if (g_str_has_prefix (path, local_dir) &&
 	    strchr (basename, '.') == NULL) {
 		type = MAIL_STORAGE_LOCAL;
-	} else if (g_str_has_prefix (path, imap_dir) &&
-		   strcmp (basename, "summary") == 0) {
-		type = MAIL_STORAGE_IMAP;
+	} else if (g_str_has_prefix (path, imap_dir)) {
+		if (strcmp (basename, "summary") == 0) {
+			type = MAIL_STORAGE_IMAP;
+		} else if (strcmp (basename, "folders.db") == 0) {
+			type = MAIL_STORAGE_IMAP_DB;
+		}
 	}
 
 	/* Exclude non wanted folders */
@@ -104,7 +109,9 @@
                 return tracker_evolution_pop_file_new (file);
         } else if (type == MAIL_STORAGE_IMAP) {
                 return tracker_evolution_imap_file_new (file);
-        }
+        } else if (type == MAIL_STORAGE_IMAP_DB) {
+		return tracker_evolution_imap_file_new (file);
+	}
 
         return NULL;
 }



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