tracker r1754 - in branches/indexer-split: . src/tracker-indexer/modules



Author: carlosg
Date: Tue Jun 24 15:07:24 2008
New Revision: 1754
URL: http://svn.gnome.org/viewvc/tracker?rev=1754&view=rev

Log:
2008-06-24  Carlos Garnacho  <carlos imendio com>

        * src/tracker-indexer/modules/Makefile.am:
        * src/tracker-indexer/modules/evolution.c: Module for Evolution,
        initially it supports local and IMAP mailboxes. It's still missing
        message body and attachments retrieval.


Added:
   branches/indexer-split/src/tracker-indexer/modules/evolution.c
Modified:
   branches/indexer-split/ChangeLog
   branches/indexer-split/src/tracker-indexer/modules/Makefile.am

Modified: branches/indexer-split/src/tracker-indexer/modules/Makefile.am
==============================================================================
--- branches/indexer-split/src/tracker-indexer/modules/Makefile.am	(original)
+++ branches/indexer-split/src/tracker-indexer/modules/Makefile.am	Tue Jun 24 15:07:24 2008
@@ -6,15 +6,18 @@
 	-DLIBDIR=\""$(libdir)"\"					\
 	-DLOCALEDIR=\""$(localedir)"\" 					\
 	-DINDEXER_MODULES_DIR=\"$(indexer_modulesdir)\"			\
+	-D_GNU_SOURCE							\
 	-I$(top_srcdir)/src						\
 	$(GMODULE_CFLAGS)						\
 	$(GIO_LIBS)							\
-	$(GLIB2_CFLAGS)
+	$(GLIB2_CFLAGS)							\
+	$(GMIME_CFLAGS)
 
 indexer_modules_LTLIBRARIES = 						\
 	libtracker-indexer-applications.la				\
 	libtracker-indexer-files.la					\
-	libtracker-indexer-gaim-conversations.la
+	libtracker-indexer-gaim-conversations.la			\
+	libtracker-indexer-evolution.la
 
 # Applications module
 libtracker_indexer_applications_la_SOURCES = applications.c
@@ -41,3 +44,11 @@
 	$(GMODULE_LIBS)							\
 	$(GIO_LIBS)							\
 	$(GLIB2_LIBS)
+
+# Evolution
+libtracker_indexer_evolution_la_SOURCES = evolution.c
+libtracker_indexer_evolution_la_LDFLAGS = $(module_flags)
+libtracker_indexer_evolution_la_LIBADD = 				\
+	$(GMODULE_LIBS)							\
+	$(GLIB2_LIBS)							\
+	$(GMIME_LIBS)

Added: branches/indexer-split/src/tracker-indexer/modules/evolution.c
==============================================================================
--- (empty file)
+++ branches/indexer-split/src/tracker-indexer/modules/evolution.c	Tue Jun 24 15:07:24 2008
@@ -0,0 +1,597 @@
+/* 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 <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 <tracker-indexer/tracker-module.h>
+#include <libtracker-common/tracker-file-utils.h>
+#include <libtracker-common/tracker-type-utils.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"
+
+typedef union EvolutionFileData EvolutionFileData;
+typedef struct EvolutionLocalData EvolutionLocalData;
+typedef struct EvolutionImapData EvolutionImapData;
+typedef enum MailStorageType MailStorageType;
+
+enum MailStorageType {
+        MAIL_STORAGE_NONE,
+        MAIL_STORAGE_LOCAL,
+        MAIL_STORAGE_IMAP
+};
+
+struct EvolutionLocalData {
+        MailStorageType type;
+        GMimeStream *stream;
+        GMimeParser *parser;
+        GMimeMessage *message;
+};
+
+struct EvolutionImapData {
+        MailStorageType type;
+        gint fd;
+        FILE *summary;
+        guint n_messages;
+        guint cur_message;
+};
+
+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
+};
+
+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:
+                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_malloc0 (len);
+
+                        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;
+}
+
+G_CONST_RETURN gchar *
+tracker_module_get_name (void)
+{
+        /* Return module name here */
+        return "Evolution";
+}
+
+gchar **
+tracker_module_get_directories (void)
+{
+        gchar **dirs;
+
+        g_mime_init (0);
+
+        dirs = g_new0 (gchar *, 3);
+        dirs[0] = g_build_filename (g_get_home_dir (), ".evolution", "mail", "local", NULL);
+        dirs[1] = g_build_filename (g_get_home_dir (), ".evolution", "mail", "imap", NULL);
+
+        return dirs;
+}
+
+static MailStorageType
+get_mail_storage_type_from_path (const gchar *path)
+{
+        MailStorageType type = MAIL_STORAGE_NONE;
+        gchar *basename, *local_dir, *imap_dir;
+
+        basename = g_path_get_basename (path);
+        local_dir = g_build_filename (g_get_home_dir (), ".evolution", "mail", "local", NULL);
+        imap_dir = g_build_filename (g_get_home_dir (), ".evolution", "mail", "imap", NULL);
+
+        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;
+        }
+
+        /* Exclude non wanted folders */
+        if (strcasestr (path, "junk") ||
+            strcasestr (path, "spam") ||
+            strcasestr (path, "trash") ||
+            strcasestr (path, "drafts") ||
+            strcasestr (path, "outbox")) {
+                type = MAIL_STORAGE_NONE;
+        }
+
+        g_free (local_dir);
+        g_free (imap_dir);
+        g_free (basename);
+
+        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)
+{
+        gint32 version, n_messages;
+
+        read_summary (summary,
+                      SUMMARY_TYPE_INT32, &version,
+                      SUMMARY_TYPE_INT32, NULL,
+                      SUMMARY_TYPE_INT32, NULL,
+                      SUMMARY_TYPE_INT32, NULL,
+                      SUMMARY_TYPE_INT32, &n_messages,
+                      -1);
+
+        if ((version < 0x100 && version >= 13)) {
+                read_summary (summary,
+                              SUMMARY_TYPE_INT32, NULL,
+                              SUMMARY_TYPE_INT32, NULL,
+                              SUMMARY_TYPE_INT32, NULL,
+                              -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;
+
+        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;
+                }
+
+                imap_data->summary = fdopen (imap_data->fd, "r");
+                imap_data->n_messages = read_summary_header (imap_data->summary);
+                imap_data->cur_message = 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->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);
+}
+
+GHashTable *
+get_metadata_for_mbox (TrackerFile *file)
+{
+        EvolutionLocalData *data;
+        GMimeMessage *message;
+        GHashTable *metadata;
+        time_t date;
+
+        data = file->data;
+        message = data->message;
+
+        if (!message) {
+                return NULL;
+        }
+
+	metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
+					  NULL,
+					  (GDestroyNotify) g_free);
+
+        g_mime_message_get_date (message, &date, NULL);
+	g_hash_table_insert (metadata, METADATA_EMAIL_DATE,
+                             tracker_uint_to_string (date));
+
+        g_hash_table_insert (metadata, METADATA_EMAIL_SENDER,
+                             g_strdup (g_mime_message_get_sender (message)));
+        g_hash_table_insert (metadata, METADATA_EMAIL_SUBJECT,
+                             g_strdup (g_mime_message_get_subject (message)));
+
+        /* Missing:
+         *
+         * Recipients:
+         *   To
+         *   CC
+         *   BCC
+         * Body
+         * Attachments
+         */
+
+        return metadata;
+}
+
+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);
+        }
+}
+
+GHashTable *
+get_metadata_for_imap (TrackerFile *file)
+{
+        EvolutionImapData *data;
+        GHashTable *metadata;
+        gchar *uid, *subject, *from, *to;
+        gint32 i, count;
+        time_t date;
+
+        data = file->data;
+
+        if (data->cur_message > data->n_messages) {
+                return NULL;
+        }
+
+        read_summary (data->summary,
+                      SUMMARY_TYPE_STRING, &uid, /* message uid */
+                      SUMMARY_TYPE_UINT32, NULL, /* flags */
+                      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, NULL, /* cc */
+                      SUMMARY_TYPE_STRING, NULL, /* mlist */
+                      -1);
+
+	metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
+					  NULL,
+					  (GDestroyNotify) g_free);
+
+	g_hash_table_insert (metadata, METADATA_EMAIL_DATE,
+                             tracker_uint_to_string (date));
+
+        g_hash_table_insert (metadata, METADATA_EMAIL_SENDER, from);
+        g_hash_table_insert (metadata, METADATA_EMAIL_SUBJECT, subject);
+
+        g_free (uid);
+        g_free (to);
+
+        read_summary (data->summary,
+                      SUMMARY_TYPE_INT32, NULL,
+                      SUMMARY_TYPE_INT32, NULL,
+                      SUMMARY_TYPE_UINT32, &count,
+                      -1);
+
+        /* references */
+        for (i = 0; i < count; i++) {
+                read_summary (data->summary,
+                              SUMMARY_TYPE_INT32, NULL,
+                              SUMMARY_TYPE_INT32, NULL,
+                              -1);
+        }
+
+        read_summary (data->summary, SUMMARY_TYPE_UINT32, &count, -1);
+
+        /* user flags */
+        for (i = 0; i < count; i++) {
+                read_summary (data->summary, SUMMARY_TYPE_STRING, NULL, -1);
+        }
+
+        read_summary (data->summary, SUMMARY_TYPE_UINT32, &count, -1);
+
+        /* user tags */
+        for (i = 0; i < count; i++) {
+                read_summary (data->summary,
+                              SUMMARY_TYPE_STRING, NULL,
+                              SUMMARY_TYPE_STRING, NULL,
+                              -1);
+        }
+
+        /* server flags */
+        read_summary (data->summary,
+                      SUMMARY_TYPE_UINT32, NULL,
+                      -1);
+
+        skip_content_info (data->summary);
+
+        return metadata;
+}
+
+GHashTable *
+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;
+}
+
+gboolean
+tracker_module_file_iter_contents (TrackerFile *file)
+{
+        EvolutionFileData *data;
+
+        data = file->data;
+
+        if (data->type == MAIL_STORAGE_IMAP) {
+                EvolutionImapData *imap_data = file->data;
+
+                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) {
+                        g_object_unref (local_data->message);
+                }
+
+                local_data->message = g_mime_parser_construct_message (local_data->parser);
+
+                return (local_data->message != NULL);
+        }
+
+        return FALSE;
+}



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