1935 lines
55 KiB
Diff
1935 lines
55 KiB
Diff
Index: plugins/pst-import/pst-importer.c
|
|
===================================================================
|
|
--- plugins/pst-import/pst-importer.c (revision 0)
|
|
+++ plugins/pst-import/pst-importer.c (revision 0)
|
|
@@ -0,0 +1,1813 @@
|
|
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
+/* pst-importer.c
|
|
+ *
|
|
+ * Copyright (C) 2006 Chris Halls
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of version 2 of the GNU General Public
|
|
+ * License as published by the Free Software Foundation.
|
|
+ *
|
|
+ * This program 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 program; if not, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
+ * Boston, MA 02111-1307, USA.
|
|
+ *
|
|
+ * Author: Chris Halls <chris.halls@credativ.co.uk>
|
|
+ Bharath Acharya <abharath@novell.com>
|
|
+ */
|
|
+
|
|
+#ifdef HAVE_CONFIG_H
|
|
+#include <config.h>
|
|
+#endif
|
|
+
|
|
+#define G_LOG_DOMAIN "eplugin-readpst"
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <fcntl.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <glib/gi18n-lib.h>
|
|
+#include <glib/gstdio.h>
|
|
+#include <glib/gprintf.h>
|
|
+
|
|
+#include <gtk/gtkwidget.h>
|
|
+#include <gtk/gtkframe.h>
|
|
+#include <gtk/gtkvbox.h>
|
|
+#include <gtk/gtkhbox.h>
|
|
+#include <gtk/gtklabel.h>
|
|
+#include <gtk/gtkcheckbutton.h>
|
|
+
|
|
+#include <e-util/e-import.h>
|
|
+
|
|
+#include <libebook/e-contact.h>
|
|
+#include <libebook/e-book.h>
|
|
+
|
|
+#include <libecal/e-cal.h>
|
|
+#include <libecal/e-cal-component.h>
|
|
+
|
|
+#include <libedataserver/e-data-server-util.h>
|
|
+
|
|
+#include <libedataserverui/e-source-selector-dialog.h>
|
|
+
|
|
+#include <camel/camel-folder.h>
|
|
+#include <camel/camel-store.h>
|
|
+#include <camel/camel-exception.h>
|
|
+#include <camel/camel-mime-message.h>
|
|
+#include <camel/camel-multipart.h>
|
|
+#include <camel/camel-data-wrapper.h>
|
|
+#include <camel/camel-stream-mem.h>
|
|
+#include <camel/camel-stream-fs.h>
|
|
+#include <camel/camel-file-utils.h>
|
|
+
|
|
+#include <mail/mail-component.h>
|
|
+#include <mail/mail-mt.h>
|
|
+#include <mail/mail-tools.h>
|
|
+#include <mail/em-utils.h>
|
|
+
|
|
+#include <libpst/libpst.h>
|
|
+#include <libpst/define.h>
|
|
+#include <libpst/timeconv.h>
|
|
+
|
|
+typedef struct _PstImporter PstImporter;
|
|
+
|
|
+int pst_init (pst_file *pst, char *filename);
|
|
+gchar *get_pst_rootname (pst_file *pst, gchar *filename);
|
|
+static void pst_error_msg (const char *fmt, ...);
|
|
+static void pst_import_folders (PstImporter *m, pst_desc_ll *topitem);
|
|
+static void pst_process_item (PstImporter *m, pst_desc_ll *d_ptr);
|
|
+static void pst_process_folder (PstImporter *m, pst_item *item);
|
|
+static void pst_process_email (PstImporter *m, pst_item *item);
|
|
+static void pst_process_contact (PstImporter *m, pst_item *item);
|
|
+static void pst_process_appointment (PstImporter *m, pst_item *item);
|
|
+static void pst_process_task (PstImporter *m, pst_item *item);
|
|
+static void pst_process_journal (PstImporter *m, pst_item *item);
|
|
+
|
|
+static void pst_import_file (PstImporter *m);
|
|
+gchar *foldername_to_utf8 (const gchar *pstname);
|
|
+gchar *string_to_utf8(const gchar *string);
|
|
+void contact_set_date (EContact *contact, EContactField id, FILETIME *date);
|
|
+struct icaltimetype get_ical_date (FILETIME *date, gboolean is_date);
|
|
+char *rfc2445_datetime_format (FILETIME *ft);
|
|
+
|
|
+gboolean org_credativ_evolution_readpst_supported (EPlugin *epl, EImportTarget *target);
|
|
+GtkWidget *org_credativ_evolution_readpst_getwidget (EImport *ei, EImportTarget *target, EImportImporter *im);
|
|
+void org_credativ_evolution_readpst_import (EImport *ei, EImportTarget *target, EImportImporter *im);
|
|
+void org_credativ_evolution_readpst_cancel (EImport *ei, EImportTarget *target, EImportImporter *im);
|
|
+int e_plugin_lib_enable (EPluginLib *ep, int enable);
|
|
+
|
|
+
|
|
+/* em-folder-selection-button.h is private, even though other internal evo plugins use it!
|
|
+ so declare the functions here
|
|
+ TODO: sort out whether this should really be private
|
|
+*/
|
|
+typedef struct _EMFolderSelectionButton EMFolderSelectionButton;
|
|
+GtkWidget *em_folder_selection_button_new (const char *title, const char *caption);
|
|
+void em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri);
|
|
+const char *em_folder_selection_button_get_selection (EMFolderSelectionButton *button);
|
|
+
|
|
+static unsigned char pst_signature [] = { '!', 'B', 'D', 'N' };
|
|
+
|
|
+struct _PstImporter {
|
|
+ MailMsg base;
|
|
+
|
|
+ EImport *import;
|
|
+ EImportTarget *target;
|
|
+
|
|
+ GMutex *status_lock;
|
|
+ char *status_what;
|
|
+ int status_pc;
|
|
+ int status_timeout_id;
|
|
+ CamelOperation *status;
|
|
+ CamelException ex;
|
|
+
|
|
+ pst_file pst;
|
|
+
|
|
+ CamelOperation *cancel;
|
|
+ CamelFolder *folder;
|
|
+ gchar *parent_uri;
|
|
+ gchar *folder_name;
|
|
+ gchar *folder_uri;
|
|
+ int folder_count;
|
|
+ int current_item;
|
|
+
|
|
+ EBook *addressbook;
|
|
+ ECal *calendar;
|
|
+ ECal *tasks;
|
|
+ ECal *journal;
|
|
+};
|
|
+
|
|
+gboolean
|
|
+org_credativ_evolution_readpst_supported (EPlugin *epl, EImportTarget *target)
|
|
+{
|
|
+ char signature[sizeof (pst_signature)];
|
|
+ gboolean ret = FALSE;
|
|
+ int fd, n;
|
|
+ EImportTargetURI *s;
|
|
+ char *filename;
|
|
+
|
|
+ if (target->type != E_IMPORT_TARGET_URI) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ s = (EImportTargetURI *)target;
|
|
+
|
|
+ if (s->uri_src == NULL) {
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ if (strncmp (s->uri_src, "file:///", strlen ("file:///")) != 0) {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ filename = g_filename_from_uri (s->uri_src, NULL, NULL);
|
|
+ fd = g_open (filename, O_RDONLY, 0);
|
|
+ g_free (filename);
|
|
+
|
|
+ if (fd != -1) {
|
|
+ n = read (fd, signature, sizeof (pst_signature));
|
|
+ ret = n == sizeof (pst_signature) && memcmp (signature, pst_signature, sizeof (pst_signature)) == 0;
|
|
+ close (fd);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void
|
|
+checkbox_mail_toggle_cb (GtkToggleButton *tb, EImportTarget *target)
|
|
+{
|
|
+ g_datalist_set_data (&target->data, "pst-do-mail", GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
|
|
+}
|
|
+
|
|
+static void
|
|
+checkbox_addr_toggle_cb (GtkToggleButton *tb, EImportTarget *target)
|
|
+{
|
|
+ g_datalist_set_data (&target->data, "pst-do-addr", GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
|
|
+}
|
|
+
|
|
+static void
|
|
+checkbox_appt_toggle_cb (GtkToggleButton *tb, EImportTarget *target)
|
|
+{
|
|
+ g_datalist_set_data (&target->data, "pst-do-appt", GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
|
|
+}
|
|
+
|
|
+static void
|
|
+checkbox_task_toggle_cb (GtkToggleButton *tb, EImportTarget *target)
|
|
+{
|
|
+ g_datalist_set_data (&target->data, "pst-do-task", GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
|
|
+}
|
|
+
|
|
+static void
|
|
+checkbox_journal_toggle_cb (GtkToggleButton *tb, EImportTarget *target)
|
|
+{
|
|
+ g_datalist_set_data (&target->data, "pst-do-journal", GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
|
|
+}
|
|
+
|
|
+static void
|
|
+folder_selected (EMFolderSelectionButton *button, EImportTargetURI *target)
|
|
+{
|
|
+ g_free (target->uri_dest);
|
|
+ target->uri_dest = g_strdup (em_folder_selection_button_get_selection (button));
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * Suggest a folder to import data into
|
|
+ * @param target
|
|
+ * @return
|
|
+ */
|
|
+static gchar*
|
|
+get_suggested_foldername (EImportTargetURI *target)
|
|
+{
|
|
+ const gchar *inbox;
|
|
+ gchar *delim, *filename;
|
|
+ gchar *rootname = NULL;
|
|
+ GString *foldername;
|
|
+ pst_file pst;
|
|
+
|
|
+ /* Suggest a folder that is in the same mail storage as the users' inbox,
|
|
+ with a name derived from the .PST file */
|
|
+ inbox = mail_component_get_folder_uri (NULL, MAIL_COMPONENT_FOLDER_INBOX);
|
|
+ g_message ("Inbox:%s", inbox);
|
|
+
|
|
+ delim = g_strrstr (inbox, "#");
|
|
+ if (delim != NULL) {
|
|
+ foldername = g_string_new_len (inbox, delim-inbox);
|
|
+ } else {
|
|
+ foldername = g_string_new (inbox);
|
|
+ }
|
|
+
|
|
+ g_string_append_c (foldername, '#');
|
|
+
|
|
+ filename = g_filename_from_uri (target->uri_src, NULL, NULL);
|
|
+
|
|
+ if (pst_init (&pst, filename) == 0) {
|
|
+ rootname = get_pst_rootname (&pst, filename);
|
|
+ }
|
|
+
|
|
+ g_free (filename);
|
|
+
|
|
+ if (rootname != NULL) {
|
|
+ gchar *utf8name;
|
|
+ utf8name = foldername_to_utf8 (rootname);
|
|
+ g_string_append (foldername, utf8name);
|
|
+ g_free (utf8name);
|
|
+ g_free (rootname);
|
|
+ } else {
|
|
+ g_string_append (foldername, "outlook_data");
|
|
+ }
|
|
+
|
|
+ if (mail_tool_uri_to_folder (foldername->str, 0, NULL) != NULL) {
|
|
+ /* Folder exists - add a number */
|
|
+ int i, len;
|
|
+ len = foldername->len;
|
|
+ CamelFolder *folder;
|
|
+
|
|
+ for (i=1; i<10000; i++) {
|
|
+ g_string_truncate (foldername, len);
|
|
+ g_string_append_printf (foldername, "_%d", i);
|
|
+ if ((folder=mail_tool_uri_to_folder (foldername->str, 0, NULL)) == NULL) {
|
|
+ /* Folder does not exist */
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (folder != NULL) {
|
|
+ pst_error_msg ("Error searching for an unused folder name. uri=%s", foldername);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return g_string_free (foldername, FALSE);
|
|
+
|
|
+}
|
|
+
|
|
+GtkWidget *
|
|
+org_credativ_evolution_readpst_getwidget (EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
+{
|
|
+ GtkWidget *hbox, *framebox, *w;
|
|
+ gchar *foldername;
|
|
+
|
|
+ g_datalist_set_data (&target->data, "pst-do-mail", GINT_TO_POINTER (TRUE));
|
|
+ g_datalist_set_data (&target->data, "pst-do-addr", GINT_TO_POINTER (TRUE));
|
|
+ g_datalist_set_data (&target->data, "pst-do-appt", GINT_TO_POINTER (TRUE));
|
|
+ g_datalist_set_data (&target->data, "pst-do-task", GINT_TO_POINTER (TRUE));
|
|
+ g_datalist_set_data (&target->data, "pst-do-journal", GINT_TO_POINTER (TRUE));
|
|
+
|
|
+ framebox = gtk_vbox_new (FALSE, 2);
|
|
+
|
|
+ /* Mail */
|
|
+ hbox = gtk_hbox_new (FALSE, 0);
|
|
+ w = gtk_check_button_new_with_mnemonic (_("_Mail"));
|
|
+ gtk_toggle_button_set_active ((GtkToggleButton *) w, TRUE);
|
|
+ g_signal_connect (w, "toggled", G_CALLBACK (checkbox_mail_toggle_cb), target);
|
|
+ gtk_box_pack_start ((GtkBox *) hbox, w, FALSE, FALSE, 0);
|
|
+
|
|
+ w = em_folder_selection_button_new (_("Select folder"), _("Select folder to import into"));
|
|
+ foldername = get_suggested_foldername ((EImportTargetURI *) target);
|
|
+ ((EImportTargetURI *) target)->uri_dest = g_strdup (foldername);
|
|
+ em_folder_selection_button_set_selection ((EMFolderSelectionButton *) w, foldername);
|
|
+ g_signal_connect (w, "selected", G_CALLBACK (folder_selected), target);
|
|
+ gtk_box_pack_end ((GtkBox *) hbox, w, FALSE, FALSE, 0);
|
|
+
|
|
+ w = gtk_label_new (_("Destination folder:"));
|
|
+ gtk_box_pack_end ((GtkBox *) hbox, w, FALSE, TRUE, 6);
|
|
+
|
|
+ gtk_box_pack_start ((GtkBox *) framebox, hbox, FALSE, FALSE, 0);
|
|
+
|
|
+ /* Address book */
|
|
+ w = gtk_check_button_new_with_mnemonic (_("_Address Book"));
|
|
+ gtk_toggle_button_set_active ((GtkToggleButton *) w, FALSE);
|
|
+ /*gtk_widget_set_sensitive ((GtkWidget *)w, FALSE);*/ /* Disable until implemented */
|
|
+ g_signal_connect (w, "toggled", G_CALLBACK (checkbox_addr_toggle_cb), target);
|
|
+ gtk_box_pack_start ((GtkBox *) framebox, w, FALSE, FALSE, 0);
|
|
+
|
|
+ /* Appointments */
|
|
+ w = gtk_check_button_new_with_mnemonic (_("A_ppointments"));
|
|
+ gtk_toggle_button_set_active ((GtkToggleButton *) w, FALSE);
|
|
+ g_signal_connect (w, "toggled", G_CALLBACK (checkbox_appt_toggle_cb), target);
|
|
+ gtk_box_pack_start ((GtkBox *)framebox, w, FALSE, FALSE, 0);
|
|
+
|
|
+ /* Tasks */
|
|
+ w = gtk_check_button_new_with_mnemonic (_("_Tasks"));
|
|
+ gtk_toggle_button_set_active ((GtkToggleButton *)w, FALSE);
|
|
+ g_signal_connect (w, "toggled", G_CALLBACK (checkbox_task_toggle_cb), target);
|
|
+ gtk_box_pack_start ((GtkBox *)framebox, w, FALSE, FALSE, 0);
|
|
+
|
|
+ /* Journal */
|
|
+ w = gtk_check_button_new_with_mnemonic (_("_Journal entries"));
|
|
+ gtk_toggle_button_set_active ((GtkToggleButton *)w, FALSE);
|
|
+ g_signal_connect (w, "toggled", G_CALLBACK (checkbox_journal_toggle_cb), target);
|
|
+ gtk_box_pack_start ((GtkBox *)framebox, w, FALSE, FALSE, 0);
|
|
+
|
|
+ gtk_widget_show_all (framebox);
|
|
+
|
|
+ g_free (foldername);
|
|
+
|
|
+ return framebox;
|
|
+}
|
|
+
|
|
+static char *
|
|
+pst_import_describe (PstImporter *m, int complete)
|
|
+{
|
|
+ return g_strdup (_("Importing Outlook data"));
|
|
+}
|
|
+
|
|
+static ECal*
|
|
+open_ecal (ECalSourceType type, char *name)
|
|
+{
|
|
+ /* Hack - grab the first calendar we can find
|
|
+ TODO - add a selection mechanism in get_widget */
|
|
+ ESource *primary;
|
|
+ ESourceList *source_list;
|
|
+ ECal *cal;
|
|
+
|
|
+ if ((e_cal_get_sources (&source_list, type, NULL)) == 0) {
|
|
+ g_warning ("Could not get any sources of type %s.", name);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ primary = e_source_list_peek_source_any (source_list);
|
|
+
|
|
+ if ((cal = e_cal_new (primary, type)) == NULL) {
|
|
+ g_warning ("Could not create %s.", name);
|
|
+ g_object_unref (source_list);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ e_cal_open (cal, TRUE, NULL);
|
|
+ g_object_unref (primary);
|
|
+ g_object_unref (source_list);
|
|
+
|
|
+ return cal;
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_import_import (PstImporter *m)
|
|
+{
|
|
+ CamelOperation *oldcancel = NULL;
|
|
+
|
|
+ oldcancel = camel_operation_register (m->status);
|
|
+
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-addr"))) {
|
|
+ /* Hack - grab the first address book we can find
|
|
+ TODO - add a selection mechanism in get_widget */
|
|
+ ESource *primary;
|
|
+ ESourceList *source_list;
|
|
+
|
|
+ if (e_book_get_addressbooks (&source_list, NULL)) {
|
|
+ primary = e_source_list_peek_source_any (source_list);
|
|
+
|
|
+ if ((m->addressbook = e_book_new (primary,NULL))) {
|
|
+ e_book_open (m->addressbook, TRUE, NULL);
|
|
+ g_object_unref (primary);
|
|
+ g_object_unref (source_list);
|
|
+ } else {
|
|
+ g_warning ("Could not create EBook.");
|
|
+ }
|
|
+ } else {
|
|
+ g_warning ("Could not get address books.");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-appt"))) {
|
|
+ m->calendar = open_ecal (E_CAL_SOURCE_TYPE_EVENT, "calendar");
|
|
+ }
|
|
+
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-task"))) {
|
|
+ m->tasks = open_ecal (E_CAL_SOURCE_TYPE_TODO, "task list");
|
|
+ }
|
|
+
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-journal"))) {
|
|
+ m->journal = open_ecal (E_CAL_SOURCE_TYPE_JOURNAL, "journal");
|
|
+ }
|
|
+
|
|
+ pst_import_file (m);
|
|
+
|
|
+/* FIXME: Crashes often in here.
|
|
+ if (m->addressbook) {
|
|
+ g_object_unref (m->addressbook);
|
|
+ }
|
|
+
|
|
+ if (m->calendar) {
|
|
+ g_object_unref (m->calendar);
|
|
+ }
|
|
+
|
|
+ if (m->tasks) {
|
|
+ g_object_unref (m->tasks);
|
|
+ }
|
|
+
|
|
+ if (m->journal) {
|
|
+ g_object_unref (m->journal);
|
|
+ }
|
|
+*/
|
|
+ camel_operation_register (oldcancel);
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_import_file (PstImporter *m)
|
|
+{
|
|
+ int ret;
|
|
+ gchar *filename;
|
|
+ pst_item *item = NULL;
|
|
+ pst_desc_ll *d_ptr;
|
|
+
|
|
+ filename = g_filename_from_uri (((EImportTargetURI *)m->target)->uri_src, NULL, NULL);
|
|
+ m->parent_uri = g_strdup (((EImportTargetURI *)m->target)->uri_dest); /* Destination folder, was set in our widget */
|
|
+
|
|
+ camel_operation_start (NULL, _("Importing `%s'"), filename);
|
|
+
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-mail"))) {
|
|
+ mail_tool_uri_to_folder (m->parent_uri, CAMEL_STORE_FOLDER_CREATE, &m->base.ex);
|
|
+ }
|
|
+
|
|
+ ret = pst_init (&m->pst, filename);
|
|
+
|
|
+ if (ret < 0) {
|
|
+ g_free (filename);
|
|
+ camel_operation_end (NULL);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ g_free (filename);
|
|
+
|
|
+ camel_operation_progress_count (NULL, 1);
|
|
+
|
|
+ if ((item = pst_parse_item (&m->pst, m->pst.d_head)) == NULL) {
|
|
+ pst_error_msg ("Could not get root record");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ camel_operation_progress_count (NULL, 2);
|
|
+
|
|
+ if ((d_ptr = pst_getTopOfFolders (&m->pst, item)) == NULL) {
|
|
+ pst_error_msg ("Top of folders record not found. Cannot continue");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ camel_operation_progress_count (NULL, 3);
|
|
+ pst_import_folders (m, d_ptr);
|
|
+
|
|
+ camel_operation_progress_count (NULL, 4);
|
|
+
|
|
+ camel_operation_end (NULL);
|
|
+
|
|
+ pst_freeItem (item);
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_import_folders (PstImporter *m, pst_desc_ll *topitem)
|
|
+{
|
|
+ pst_desc_ll *d_ptr;
|
|
+ gchar *seperator;
|
|
+
|
|
+ d_ptr = topitem->child;
|
|
+
|
|
+ /* Walk through folder tree */
|
|
+ while (d_ptr != NULL && (camel_operation_cancel_check (NULL) == FALSE)) {
|
|
+
|
|
+ pst_process_item (m, d_ptr);
|
|
+
|
|
+ if (d_ptr->child != NULL) {
|
|
+ g_free (m->parent_uri);
|
|
+ m->parent_uri = g_strdup (m->folder_uri);
|
|
+ d_ptr = d_ptr->child;
|
|
+ } else if (d_ptr->next != NULL) {
|
|
+ d_ptr = d_ptr->next;
|
|
+ } else {
|
|
+ while (d_ptr != topitem && d_ptr->next == NULL) {
|
|
+ if(m->folder_uri) {
|
|
+ g_free(m->folder_uri);
|
|
+ }
|
|
+
|
|
+ m->folder_uri = g_strdup (m->parent_uri);
|
|
+ seperator = g_strrstr (m->parent_uri, "/");
|
|
+
|
|
+ if (seperator != NULL) {
|
|
+ *seperator = '\0'; /* Truncate uri */
|
|
+ }
|
|
+
|
|
+ /*printf (" parent uri:%s\n", m->parent_uri);*/
|
|
+ /*printf (" folder uri:%s\n", m->folder_uri);*/
|
|
+ d_ptr = d_ptr->parent;
|
|
+
|
|
+ }
|
|
+ if (d_ptr == topitem) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ d_ptr = d_ptr->next;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_item (PstImporter *m, pst_desc_ll *d_ptr)
|
|
+{
|
|
+ pst_item *item = NULL;
|
|
+
|
|
+ if (d_ptr->desc == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ item = pst_parse_item (&m->pst, d_ptr);
|
|
+
|
|
+ if (item == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+
|
|
+ if (item->message_store != NULL) {
|
|
+ pst_error_msg ("A second message_store has been found - ignored");
|
|
+ pst_freeItem (item);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /*printf ("Item type: %i (%s)\n", item->type, (item->ascii_type ? item->ascii_type : "unknown"));*/
|
|
+
|
|
+ if (item->folder != NULL) {
|
|
+ pst_process_folder (m, item);
|
|
+ camel_operation_start (NULL, _("Importing `%s'"), item->file_as);
|
|
+ } else {
|
|
+ if (m->folder_count && (m->current_item < m->folder_count)) {
|
|
+ camel_operation_progress (NULL, (m->current_item * 100) / m->folder_count);
|
|
+ } else {
|
|
+ camel_operation_progress (NULL, 100);
|
|
+ }
|
|
+
|
|
+ if (item->email != NULL &&
|
|
+ (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
|
|
+
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-mail")))
|
|
+ pst_process_email (m, item);
|
|
+
|
|
+ } else if (item->contact && item->type == PST_TYPE_CONTACT) {
|
|
+
|
|
+ if (m->addressbook && GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-addr"))) {
|
|
+ pst_process_contact (m, item);
|
|
+ }
|
|
+
|
|
+ } else if (item->type == PST_TYPE_APPOINTMENT) {
|
|
+
|
|
+ if (m->calendar && GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-appt"))) {
|
|
+ pst_process_appointment (m, item);
|
|
+ }
|
|
+
|
|
+ } else if (item->type == PST_TYPE_TASK) {
|
|
+
|
|
+ if (m->tasks && GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-task"))) {
|
|
+ pst_process_task (m, item);
|
|
+ }
|
|
+
|
|
+ } else if (item->type == PST_TYPE_JOURNAL) {
|
|
+
|
|
+ if (m->journal && GPOINTER_TO_INT (g_datalist_get_data (&m->target->data, "pst-do-journal"))) {
|
|
+ pst_process_journal (m, item);
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ m->current_item++;
|
|
+ }
|
|
+
|
|
+ pst_freeItem (item);
|
|
+
|
|
+ if (d_ptr->next == NULL) {
|
|
+ camel_operation_end (NULL);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Convert string to utf8. Currently we just use the locale, but maybe there is encoding
|
|
+ * information hidden somewhere in the PST file?
|
|
+ *
|
|
+ * @param string String from PST file
|
|
+ * @return utf8 representation (caller should free), or NULL for error.
|
|
+ */
|
|
+gchar *
|
|
+string_to_utf8(const gchar *string)
|
|
+{
|
|
+ gchar *utf8;
|
|
+
|
|
+ utf8 = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
|
|
+
|
|
+ return utf8;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Convert foldername to utf8 and escape characters if needed
|
|
+ * @param foldername from PST file
|
|
+ * @return converted folder name, or NULL for error. Caller should free
|
|
+ */
|
|
+gchar *
|
|
+foldername_to_utf8 (const gchar *pstname)
|
|
+{
|
|
+ gchar *utf8name, *folder_name;
|
|
+
|
|
+ utf8name = string_to_utf8(pstname);
|
|
+
|
|
+ if (utf8name == NULL) {
|
|
+ folder_name = camel_url_encode (pstname, NULL);
|
|
+ g_warning ("foldername_to_utf8: Cannot convert to utf8! foldername=%s", folder_name);
|
|
+ } else {
|
|
+ /* Encode using the current locale */
|
|
+ folder_name = camel_url_encode (utf8name, NULL);
|
|
+ g_free (utf8name);
|
|
+ }
|
|
+
|
|
+ g_strdelimit (folder_name, "/", '_');
|
|
+ g_strescape (folder_name, NULL);
|
|
+
|
|
+ return folder_name;
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_folder (PstImporter *m, pst_item *item)
|
|
+{
|
|
+ gchar *uri;
|
|
+ g_free (m->folder_name);
|
|
+ g_free (m->folder_uri);
|
|
+
|
|
+ if (item->file_as != NULL) {
|
|
+ m->folder_name = foldername_to_utf8 (item->file_as);
|
|
+ } else {
|
|
+ g_critical ("Folder: No name! item->file_as=%s", item->file_as);
|
|
+ m->folder_name = g_strdup ("unknown_name");
|
|
+ }
|
|
+
|
|
+ uri = g_strjoin ("/", m->parent_uri, m->folder_name, NULL);
|
|
+ m->folder_uri = uri;
|
|
+
|
|
+ /*printf (" uri:%s\n", m->folder_uri);*/
|
|
+ g_debug ("Folder name=%s email_count=%d unseen=%d assoc=%d", item->file_as,
|
|
+ item->folder->email_count, item->folder->unseen_email_count, item->folder->assoc_count);
|
|
+
|
|
+ if (m->folder) {
|
|
+ camel_object_unref (m->folder);
|
|
+ m->folder = NULL;
|
|
+ }
|
|
+
|
|
+ m->folder_count = item->folder->email_count;
|
|
+ m->current_item = 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Create current folder in mail hierarchy. Parent folders will also be created.
|
|
+ * @param m PstImporter set to current folder
|
|
+ */
|
|
+static void
|
|
+pst_create_folder (PstImporter *m)
|
|
+{
|
|
+ const gchar *parent;
|
|
+ gchar *dest, *dest_end, *pos;
|
|
+ int dest_len;
|
|
+
|
|
+ parent = ((EImportTargetURI *)m->target)->uri_dest;
|
|
+ g_debug("Create folder: %s", m->folder_uri);
|
|
+ dest = g_strdup (m->folder_uri);
|
|
+
|
|
+ g_assert (g_str_has_prefix (dest, parent));
|
|
+
|
|
+ dest_len = strlen (dest);
|
|
+ dest_end = dest + dest_len;
|
|
+
|
|
+ pos = dest + strlen(parent);
|
|
+
|
|
+ while (pos != NULL && pos < dest_end) {
|
|
+ pos = g_strstr_len (pos+1, dest_end-pos, "/");
|
|
+ if (pos != NULL) {
|
|
+ CamelFolder *folder;
|
|
+
|
|
+ *pos = '\0';
|
|
+
|
|
+ g_debug ("Creating intermediate folder=%s", dest);
|
|
+ folder = mail_tool_uri_to_folder (dest, CAMEL_STORE_FOLDER_CREATE, &m->base.ex);
|
|
+ camel_object_unref(folder);
|
|
+ *pos = '/';
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_free (dest);
|
|
+
|
|
+ if (m->folder) {
|
|
+ camel_object_unref (m->folder);
|
|
+ }
|
|
+
|
|
+ m->folder = mail_tool_uri_to_folder (m->folder_uri, CAMEL_STORE_FOLDER_CREATE, &m->base.ex);
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Create a camel mime part from given PST attachment
|
|
+ * @param attach attachment to convert
|
|
+ * @return CamelMimePart containing data and mime type
|
|
+ */
|
|
+static CamelMimePart *
|
|
+attachment_to_part (PstImporter *m, pst_item_attach *attach)
|
|
+{
|
|
+ CamelMimePart *part;
|
|
+ char *mimetype;
|
|
+
|
|
+ part = camel_mime_part_new ();
|
|
+
|
|
+ if (attach->filename2 || attach->filename1) {
|
|
+ camel_mime_part_set_filename (part, (attach->filename2 ? attach->filename2 : attach->filename1));
|
|
+ camel_mime_part_set_disposition (part, "attachment");
|
|
+ camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
|
|
+ } else {
|
|
+ camel_mime_part_set_disposition (part, "inline");
|
|
+ }
|
|
+
|
|
+ if (attach->mimetype != NULL) {
|
|
+ mimetype = attach->mimetype;
|
|
+ } else {
|
|
+ mimetype = "application/octet-stream";
|
|
+ }
|
|
+
|
|
+ if (attach->data != NULL) {
|
|
+ camel_mime_part_set_content (part, attach->data, strlen (attach->data), mimetype);
|
|
+ } else {
|
|
+ char *buf = NULL;
|
|
+ size_t size;
|
|
+ size = pst_attach_to_mem (&m->pst, attach, &buf);
|
|
+
|
|
+ camel_mime_part_set_content (part, (char*) buf, size, mimetype);
|
|
+ free(buf);
|
|
+ }
|
|
+
|
|
+ return part;
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_email (PstImporter *m, pst_item *item)
|
|
+{
|
|
+ CamelMimeMessage *msg;
|
|
+ CamelInternetAddress *addr;
|
|
+ CamelMultipart *mp;
|
|
+ CamelMimePart *part;
|
|
+ CamelMessageInfo *info;
|
|
+
|
|
+ if (m->folder == NULL) {
|
|
+ pst_create_folder (m);
|
|
+ }
|
|
+
|
|
+ camel_folder_freeze (m->folder);
|
|
+
|
|
+ msg = camel_mime_message_new ();
|
|
+
|
|
+ if (item->email->subject != NULL) {
|
|
+ gchar *subj;
|
|
+ g_message ("Email subject=%s", item->email->subject->subj);
|
|
+
|
|
+ subj = string_to_utf8 (item->email->subject->subj);
|
|
+ if (subj == NULL) {
|
|
+ g_warning ("Could not convert email subject to utf8: %s", item->email->subject->subj);
|
|
+ camel_mime_message_set_subject (msg, "(lost subject)");
|
|
+ } else {
|
|
+ camel_mime_message_set_subject (msg, subj);
|
|
+ g_free(subj);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ addr = camel_internet_address_new ();
|
|
+
|
|
+ if (item->email->outlook_sender_name != NULL && item->email->outlook_sender != NULL) {
|
|
+ camel_internet_address_add (addr, item->email->outlook_sender_name, item->email->outlook_sender);
|
|
+ } else if (item->email->outlook_sender_name != NULL) {
|
|
+ camel_address_decode (CAMEL_ADDRESS (addr), item->email->outlook_sender_name);
|
|
+ } else if (item->email->outlook_sender != NULL) {
|
|
+ camel_address_decode (CAMEL_ADDRESS (addr), item->email->outlook_sender);
|
|
+ } else {
|
|
+ /* Evo prints a warning if no from is set, so supply an empty address */
|
|
+ camel_internet_address_add (addr, "", "");
|
|
+ }
|
|
+
|
|
+ camel_mime_message_set_from (msg, addr);
|
|
+ camel_object_unref (addr);
|
|
+
|
|
+ if (item->email->sent_date != NULL) {
|
|
+ camel_mime_message_set_date (msg, fileTimeToUnixTime (item->email->sent_date, 0), 0);
|
|
+ }
|
|
+
|
|
+ if (item->email->messageid != NULL) {
|
|
+ camel_mime_message_set_message_id (msg, item->email->messageid);
|
|
+ }
|
|
+
|
|
+ if (item->email->header != NULL) {
|
|
+ /* Use mime parser to read headers */
|
|
+ CamelStream *stream;
|
|
+ /*g_debug (" Email headers length=%zd", strlen (item->email->header));*/
|
|
+ /*g_message (" Email headers... %s...", item->email->header);*/
|
|
+
|
|
+ stream = camel_stream_mem_new_with_buffer (item->email->header, strlen (item->email->header));
|
|
+ if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)msg, stream) == -1)
|
|
+ g_warning ("Error reading headers, skipped");
|
|
+
|
|
+ } else {
|
|
+
|
|
+ if (item->email->sentto_address != NULL) {
|
|
+ addr = camel_internet_address_new ();
|
|
+
|
|
+ g_print("\n\n The to header is:%s", item->email->sentto_address);
|
|
+
|
|
+ if (camel_address_decode (CAMEL_ADDRESS (addr), item->email->sentto_address) > 0);
|
|
+ camel_mime_message_set_recipients (msg, "To", addr);
|
|
+
|
|
+ camel_object_unref (addr);
|
|
+ }
|
|
+
|
|
+ if (item->email->cc_address != NULL) {
|
|
+ addr = camel_internet_address_new ();
|
|
+
|
|
+ if (camel_address_decode (CAMEL_ADDRESS (addr), item->email->cc_address) > 0);
|
|
+ camel_mime_message_set_recipients (msg, "CC", addr);
|
|
+
|
|
+ camel_object_unref (addr);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ mp = camel_multipart_new ();
|
|
+
|
|
+ if (item->attach != NULL) {
|
|
+
|
|
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/mixed");
|
|
+
|
|
+ } else if (item->email->htmlbody && item->email->body) {
|
|
+
|
|
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/alternate");
|
|
+
|
|
+ } else if (item->email->htmlbody) {
|
|
+
|
|
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "text/html");
|
|
+
|
|
+ }
|
|
+
|
|
+ camel_multipart_set_boundary (mp, NULL);
|
|
+
|
|
+ if (item->email->body != NULL) {
|
|
+ /* Read internet headers */
|
|
+
|
|
+ /*g_debug (" Email body length=%zd", strlen (item->email->body));
|
|
+ g_message (" Email body %100s...", item->email->body);*/
|
|
+
|
|
+ part = camel_mime_part_new ();
|
|
+ camel_mime_part_set_content (part, item->email->body, strlen (item->email->body), "text/plain");
|
|
+ camel_multipart_add_part (mp, part);
|
|
+ camel_object_unref (part);
|
|
+ }
|
|
+
|
|
+ if (item->email->htmlbody != NULL) {
|
|
+ /*g_debug (" HTML body length=%zd", strlen (item->email->htmlbody));*/
|
|
+ part = camel_mime_part_new ();
|
|
+ camel_mime_part_set_content (part, item->email->htmlbody, strlen (item->email->htmlbody), "text/html");
|
|
+ camel_multipart_add_part (mp, part);
|
|
+ camel_object_unref (part);
|
|
+ }
|
|
+
|
|
+ item->current_attach = item->attach;
|
|
+
|
|
+ while (item->current_attach != NULL) {
|
|
+ pst_item_attach *attach;
|
|
+
|
|
+ attach = item->current_attach;
|
|
+ part = attachment_to_part(m, attach);
|
|
+
|
|
+ camel_multipart_add_part (mp, part);
|
|
+ camel_object_unref (part);
|
|
+
|
|
+ item->current_attach = item->current_attach->next;
|
|
+ }
|
|
+
|
|
+ /*camel_mime_message_dump (msg, TRUE);*/
|
|
+
|
|
+ if (item->email->htmlbody || item->attach) {
|
|
+ camel_medium_set_content_object (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (mp));
|
|
+ } else if (item->email->body) {
|
|
+ camel_mime_part_set_content (CAMEL_MIME_PART (msg), item->email->body, strlen (item->email->body), "text/plain");
|
|
+ } else {
|
|
+ g_warning ("Email without body. Subject:%s",
|
|
+ (item->email->subject->subj ? item->email->subject->subj : "(empty)"));
|
|
+ camel_mime_part_set_content (CAMEL_MIME_PART (msg), "\n", 1, "text/plain");
|
|
+ }
|
|
+
|
|
+ info = camel_message_info_new (NULL);
|
|
+
|
|
+ /* Read message flags (see comments in libpst.c */
|
|
+ if(item->email->flag && 0x01)
|
|
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);
|
|
+
|
|
+ if(item->email->importance == 2)
|
|
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_FLAGGED, ~0);
|
|
+
|
|
+ if(item->email->flag && 0x08)
|
|
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_DRAFT, ~0);
|
|
+
|
|
+ camel_folder_append_message (m->folder, msg, info, NULL, &m->ex);
|
|
+ camel_message_info_free (info);
|
|
+ camel_object_unref (msg);
|
|
+
|
|
+ camel_folder_sync (m->folder, FALSE, NULL);
|
|
+ camel_folder_thaw (m->folder);
|
|
+
|
|
+ if (camel_exception_is_set (&m->ex)) {
|
|
+ g_critical ("Exception!");
|
|
+ camel_exception_clear (&m->ex);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+contact_set_string (EContact *contact, EContactField id, char *string)
|
|
+{
|
|
+ if (string != NULL) {
|
|
+ e_contact_set (contact, id, string);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+unknown_field (EContact *contact, GString *notes, char *name, char *string)
|
|
+{
|
|
+ /* Field could not be mapped directly so add to notes field */
|
|
+ if (string != NULL) {
|
|
+ g_string_append_printf (notes, "%s: %s\n", name, string);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+contact_set_address (EContact *contact, EContactField id, char *address, char *city, char *country, char *po_box, char *postal_code, char *state, char *street)
|
|
+{
|
|
+ EContactAddress *eaddress;
|
|
+
|
|
+ if (address || city || country || po_box || postal_code || state || street) {
|
|
+ eaddress = g_new0 (EContactAddress, 1);
|
|
+ if (po_box) {
|
|
+ eaddress->po = g_strdup (po_box);
|
|
+ }
|
|
+ //eaddress->ext =
|
|
+
|
|
+ if (street) {
|
|
+ eaddress->street = g_strdup (street);
|
|
+ }
|
|
+
|
|
+ if (city) {
|
|
+ eaddress->locality = g_strdup (city);
|
|
+ }
|
|
+
|
|
+ if (state) {
|
|
+ eaddress->region = g_strdup (state);
|
|
+ }
|
|
+
|
|
+ if (postal_code) {
|
|
+ eaddress->code = g_strdup (postal_code);
|
|
+ }
|
|
+
|
|
+ if (country) {
|
|
+ eaddress->country = g_strdup (country);
|
|
+ }
|
|
+
|
|
+ e_contact_set (contact, id, eaddress);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+contact_set_date (EContact *contact, EContactField id, FILETIME *date)
|
|
+{
|
|
+ if (date && (date->dwLowDateTime || date->dwHighDateTime) ) {
|
|
+ time_t t1;
|
|
+ struct tm tm;
|
|
+ EContactDate *bday;
|
|
+ bday = e_contact_date_new ();
|
|
+
|
|
+ t1 = fileTimeToUnixTime (date, 0);
|
|
+ gmtime_r (&t1, &tm);
|
|
+
|
|
+ bday->year = tm.tm_year + 1900;
|
|
+ bday->month = tm.tm_mon + 1;
|
|
+ bday->day = tm.tm_mday;
|
|
+
|
|
+ e_contact_set (contact, id, bday);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_contact (PstImporter *m, pst_item *item)
|
|
+{
|
|
+ pst_item_contact *c;
|
|
+ EContact *ec;
|
|
+ c = item->contact;
|
|
+ GString *notes;
|
|
+
|
|
+ notes = g_string_sized_new (2048);
|
|
+ g_message ("Contact name=%s", c->fullname);
|
|
+
|
|
+ ec = e_contact_new ();
|
|
+ /* pst's fullname field only contains first, middle, surname */
|
|
+ if (c->display_name_prefix || c->suffix) {
|
|
+ GString *name = g_string_sized_new (128);
|
|
+
|
|
+ if (c->display_name_prefix) {
|
|
+ g_string_assign (name, c->display_name_prefix);
|
|
+ }
|
|
+
|
|
+ if (c->first_name) {
|
|
+ g_string_append_printf (name, "%s%s", (name->len ? " " : ""), c->first_name);
|
|
+ }
|
|
+
|
|
+ if (c->middle_name) {
|
|
+ g_string_append_printf (name, "%s%s", (name->len ? " " : ""), c->middle_name);
|
|
+ }
|
|
+
|
|
+ if (c->surname) {
|
|
+ g_string_append_printf (name, "%s%s", (name->len ? " " : ""), c->surname);
|
|
+ }
|
|
+
|
|
+ if (c->suffix) {
|
|
+ g_string_append_printf (name, "%s%s", (name->len ? " " : ""), c->suffix);
|
|
+ }
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_FULL_NAME, name->str);
|
|
+ g_string_free (name, TRUE);
|
|
+
|
|
+ } else {
|
|
+ contact_set_string (ec, E_CONTACT_FULL_NAME, c->fullname);
|
|
+ }
|
|
+
|
|
+ /* unknown_field (ec, notes, "initials", c->initials); */
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_NICKNAME, c->nickname);
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_ORG, c->company_name);
|
|
+ contact_set_string (ec, E_CONTACT_ORG_UNIT, c->department);
|
|
+ contact_set_string (ec, E_CONTACT_TITLE, c->job_title);
|
|
+
|
|
+ contact_set_address (ec,E_CONTACT_ADDRESS_WORK,
|
|
+ c->business_address, c->business_city, c->business_country,
|
|
+ c->business_po_box, c->business_postal_code, c->business_state, c->business_street);
|
|
+
|
|
+ contact_set_address (ec,E_CONTACT_ADDRESS_HOME,
|
|
+ c->home_address, c->home_city, c->home_country,
|
|
+ c->home_po_box, c->home_postal_code, c->home_state, c->home_street);
|
|
+
|
|
+ contact_set_address (ec,E_CONTACT_ADDRESS_OTHER,
|
|
+ c->other_address, c->other_city, c->other_country,
|
|
+ c->other_po_box, c->other_postal_code, c->other_state, c->other_street);
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_ASSISTANT, c->assistant_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_BUSINESS_FAX, c->business_fax);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_BUSINESS, c->business_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_BUSINESS_2, c->business_phone2);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_CALLBACK, c->callback_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_CAR, c->car_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_COMPANY, c->company_main_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_HOME_FAX, c->home_fax);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_HOME, c->home_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_HOME_2, c->home_phone2);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_ISDN, c->isdn_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_MOBILE, c->mobile_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_OTHER_FAX, c->primary_fax); /* ? */
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_PAGER, c->pager_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_PRIMARY, c->primary_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_RADIO, c->radio_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_TTYTDD, c->ttytdd_phone);
|
|
+ contact_set_string (ec, E_CONTACT_PHONE_TELEX, c->telex);
|
|
+ unknown_field (ec, notes, "account_name", c->account_name);
|
|
+ contact_set_date (ec, E_CONTACT_ANNIVERSARY, c->wedding_anniversary);
|
|
+ contact_set_string (ec, E_CONTACT_ASSISTANT, c->assistant_name);
|
|
+ unknown_field (ec, notes, "billing_information", c->billing_information);
|
|
+ contact_set_date (ec, E_CONTACT_BIRTH_DATE, c->birthday);
|
|
+ /* contact_set_string (ec, E_CONTACT_CATEGORIES, c->??); */
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_EMAIL_1 , c->address1);
|
|
+ contact_set_string (ec, E_CONTACT_EMAIL_2 , c->address2);
|
|
+ contact_set_string (ec, E_CONTACT_EMAIL_3 , c->address3);
|
|
+
|
|
+ /*unknown_field (ec, notes, "address1_desc" , c->address1_desc);
|
|
+ unknown_field (ec, notes, "address1_transport" , c->address1_transport);
|
|
+ unknown_field (ec, notes, "address2_desc" , c->address2_desc);
|
|
+ unknown_field (ec, notes, "address2_transport" , c->address2_transport);
|
|
+ unknown_field (ec, notes, "address3_desc" , c->address3_desc);
|
|
+ unknown_field (ec, notes, "address3_transport" , c->address3_transport);*/
|
|
+
|
|
+ /*unknown_field (ec, notes, "def_postal_address", c->def_postal_address);*/
|
|
+
|
|
+ /* unknown_field (ec, ??, c->gender); */
|
|
+ unknown_field (ec, notes, "access_method", c->access_method);
|
|
+ unknown_field (ec, notes, "gov_id", c->gov_id);
|
|
+ unknown_field (ec, notes, "customer_id", c->customer_id);
|
|
+ unknown_field (ec, notes, "hobbies", c->hobbies);
|
|
+ unknown_field (ec, notes, "followup", c->followup);
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_FREEBUSY_URL , c->free_busy_address);
|
|
+
|
|
+ unknown_field (ec, notes, "keyword", c->keyword);
|
|
+ unknown_field (ec, notes, "language", c->language);
|
|
+ unknown_field (ec, notes, "location", c->location);
|
|
+ contact_set_string (ec, E_CONTACT_OFFICE, c->office_loc);
|
|
+ unknown_field (ec, notes, "computer_name", c->computer_name);
|
|
+ unknown_field (ec, notes, "ftp_site", c->ftp_site);
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_MANAGER , c->manager_name);
|
|
+ unknown_field (ec, notes, "mileage", c->mileage);
|
|
+ unknown_field (ec, notes, "org_id", c->org_id);
|
|
+ contact_set_string (ec, E_CONTACT_ROLE, c->profession);
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_SPOUSE , c->spouse_name);
|
|
+
|
|
+ if (c->personal_homepage) {
|
|
+ contact_set_string (ec, E_CONTACT_HOMEPAGE_URL , c->personal_homepage);
|
|
+ if (c->business_homepage) {
|
|
+ unknown_field (ec, notes, "business_homepage", c->business_homepage);
|
|
+ }
|
|
+ } else if (c->business_homepage) {
|
|
+ contact_set_string (ec, E_CONTACT_HOMEPAGE_URL , c->business_homepage);
|
|
+ }
|
|
+
|
|
+ if (item->comment) {
|
|
+ g_string_append_printf (notes, "%s\n", item->comment);
|
|
+ }
|
|
+
|
|
+ if (item->email && item->email->body) {
|
|
+ g_string_append_printf (notes, "%s\n", item->email->body);
|
|
+ }
|
|
+
|
|
+ contact_set_string (ec, E_CONTACT_NOTE, notes->str);
|
|
+ g_string_free (notes, TRUE);
|
|
+
|
|
+ e_book_add_contact (m->addressbook, ec, NULL);
|
|
+ g_object_unref (ec);
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Convert pst time to icaltimetype
|
|
+ * @param date time value from libpst
|
|
+ * @param is_date treat as date only (all day event)?
|
|
+ * @return converted date
|
|
+ */
|
|
+struct icaltimetype
|
|
+get_ical_date (FILETIME *date, gboolean is_date)
|
|
+{
|
|
+ if (date && (date->dwLowDateTime || date->dwHighDateTime) ) {
|
|
+ time_t t;
|
|
+
|
|
+ t = fileTimeToUnixTime (date, 0);
|
|
+ return icaltime_from_timet_with_zone (t, is_date, NULL);
|
|
+ } else {
|
|
+ return icaltime_null_date ();
|
|
+ }
|
|
+}
|
|
+
|
|
+char *rfc2445_datetime_format (FILETIME *ft) {
|
|
+ static char* buffer = NULL;
|
|
+ struct tm *stm = NULL;
|
|
+
|
|
+ if (buffer == NULL) {
|
|
+ buffer = malloc (30); // should be enough
|
|
+ }
|
|
+
|
|
+ stm = fileTimeToStructTM (ft);
|
|
+ strftime (buffer, 30, "%Y%m%dT%H%M%SZ", stm);
|
|
+ return buffer;
|
|
+}
|
|
+
|
|
+static void
|
|
+set_cal_attachments (ECal *cal, ECalComponent *ec, PstImporter *m, pst_item_attach *attach)
|
|
+{
|
|
+ GSList *list = NULL;
|
|
+ const char *uid;
|
|
+ char *store_dir;
|
|
+
|
|
+ if (attach == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ e_cal_component_get_uid (ec, &uid);
|
|
+ store_dir = g_filename_from_uri (e_cal_get_local_attachment_store (cal), NULL, NULL);
|
|
+
|
|
+ while (attach != NULL) {
|
|
+ const char* orig_filename;
|
|
+ char *filename, *tmp, *path, *dirname, *uri;
|
|
+ CamelMimePart *part;
|
|
+ CamelDataWrapper *content;
|
|
+ CamelStream *stream;
|
|
+ struct stat st;
|
|
+
|
|
+ part = attachment_to_part(m, attach);
|
|
+
|
|
+ orig_filename = camel_mime_part_get_filename(part);
|
|
+
|
|
+ if (orig_filename == NULL) {
|
|
+ g_warning("Ignoring unnamed attachment");
|
|
+ attach = attach->next;
|
|
+ continue; /* Ignore unnamed attachments */
|
|
+ }
|
|
+
|
|
+ tmp = camel_file_util_safe_filename (orig_filename);
|
|
+ filename = g_strdup_printf ("%s-%s", uid, tmp);
|
|
+ path = g_build_filename (store_dir, filename, NULL);
|
|
+
|
|
+ g_free (tmp);
|
|
+ g_free (filename);
|
|
+
|
|
+ dirname = g_path_get_dirname(path);
|
|
+ if (g_mkdir_with_parents(dirname, 0777) == -1) {
|
|
+ g_warning("Could not create directory %s: %s", dirname, g_strerror(errno));
|
|
+ g_free(dirname);
|
|
+ attach = attach->next;
|
|
+ continue;
|
|
+ }
|
|
+ g_free(dirname);
|
|
+
|
|
+ if (g_access(path, F_OK) == 0) {
|
|
+ if (g_access(path, W_OK) != 0) {
|
|
+ g_warning("Could not write file %s - file exists", path);
|
|
+ attach = attach->next;
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (g_stat(path, &st) != -1 && !S_ISREG(st.st_mode)) {
|
|
+ g_warning("Could not write file %s - not a file", path);
|
|
+ attach = attach->next;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (!(stream = camel_stream_fs_new_with_name (path, O_WRONLY | O_CREAT | O_TRUNC, 0666))) {
|
|
+ g_warning ("Could not create stream for file %s - %s", path, g_strerror (errno));
|
|
+ attach = attach->next;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ content = camel_medium_get_content_object (CAMEL_MEDIUM (part));
|
|
+
|
|
+ if (camel_data_wrapper_decode_to_stream (content, stream) == -1
|
|
+ || camel_stream_flush (stream) == -1)
|
|
+ {
|
|
+ g_warning ("Could not write attachment to %s: %s", path, g_strerror (errno));
|
|
+ camel_object_unref (stream);
|
|
+ attach = attach->next;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ camel_object_unref (stream);
|
|
+
|
|
+ uri = g_filename_to_uri (path, NULL, NULL);
|
|
+ list = g_slist_append (list, g_strdup (uri));
|
|
+ g_free (uri);
|
|
+
|
|
+ camel_object_unref (part);
|
|
+ g_free (path);
|
|
+
|
|
+ attach = attach->next;
|
|
+
|
|
+ }
|
|
+
|
|
+ g_free (store_dir);
|
|
+
|
|
+ e_cal_component_set_attachment_list (ec, list);
|
|
+}
|
|
+
|
|
+static void
|
|
+fill_calcomponent (PstImporter *m, pst_item *item, ECalComponent *ec, const char *type)
|
|
+{
|
|
+ pst_item_appointment *a;
|
|
+ pst_item_email *e;
|
|
+
|
|
+ a = item->appointment;
|
|
+ e = item->email;
|
|
+ ECalComponentText text;
|
|
+ struct icaltimetype tt_start, tt_end;
|
|
+ ECalComponentDateTime dt_start, dt_end;
|
|
+
|
|
+ if (item->create_date) {
|
|
+ struct icaltimetype tt;
|
|
+ tt = get_ical_date (item->create_date, FALSE);
|
|
+ e_cal_component_set_created (ec, &tt);
|
|
+ }
|
|
+ if (item->modify_date) {
|
|
+ struct icaltimetype tt;
|
|
+ tt = get_ical_date (item->modify_date, FALSE);
|
|
+ e_cal_component_set_last_modified (ec, &tt);
|
|
+ }
|
|
+
|
|
+ if (e) {
|
|
+ if (e->subject || e->proc_subject) {
|
|
+ if (e->subject) {
|
|
+ text.value = e->subject->subj;
|
|
+ } else if (e->proc_subject) {
|
|
+ text.value = e->proc_subject;
|
|
+ }
|
|
+
|
|
+ text.altrep = NULL; /* email->proc_subject? */
|
|
+ e_cal_component_set_summary (ec, &text);
|
|
+ g_message ("%s: %s", type, text.value);
|
|
+ }
|
|
+ if (e->body) {
|
|
+ GSList l;
|
|
+ text.value = e->body;
|
|
+ text.altrep = NULL;
|
|
+ l.data = &text;
|
|
+ l.next = NULL;
|
|
+ e_cal_component_set_description_list (ec, &l);
|
|
+ }
|
|
+ } else {
|
|
+ g_warning ("%s without subject / body!", type);
|
|
+ }
|
|
+
|
|
+ if (a->location) {
|
|
+ e_cal_component_set_location (ec, a->location);
|
|
+ }
|
|
+
|
|
+ if (a->start) {
|
|
+ tt_start = get_ical_date (a->start, a->all_day);
|
|
+ dt_start.value = &tt_start;
|
|
+ dt_start.tzid = NULL;
|
|
+ e_cal_component_set_dtstart (ec, &dt_start);
|
|
+ g_message ("start:%s", rfc2445_datetime_format (a->start));
|
|
+ }
|
|
+
|
|
+ if (a->end) {
|
|
+ tt_end = get_ical_date (a->end, a->all_day);
|
|
+ dt_end.value = &tt_end;
|
|
+ dt_end.tzid = NULL;
|
|
+ e_cal_component_set_dtend (ec, &dt_end);
|
|
+ g_message ("end:%s", rfc2445_datetime_format (a->end));
|
|
+ }
|
|
+
|
|
+ switch (a->showas) {
|
|
+ case PST_FREEBUSY_TENTATIVE:
|
|
+ e_cal_component_set_status (ec, ICAL_STATUS_TENTATIVE);
|
|
+ break;
|
|
+ case PST_FREEBUSY_FREE:
|
|
+ // mark as transparent and as confirmed
|
|
+ e_cal_component_set_transparency (ec, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
|
|
+ case PST_FREEBUSY_BUSY:
|
|
+ case PST_FREEBUSY_OUT_OF_OFFICE:
|
|
+ e_cal_component_set_status (ec, ICAL_STATUS_CONFIRMED);
|
|
+ break;
|
|
+ }
|
|
+ switch (a->label) {
|
|
+ case PST_APP_LABEL_NONE:
|
|
+ break;
|
|
+ case PST_APP_LABEL_IMPORTANT:
|
|
+ e_cal_component_set_categories (ec, "Important"); break;
|
|
+ case PST_APP_LABEL_BUSINESS:
|
|
+ e_cal_component_set_categories (ec, "Business"); break;
|
|
+ case PST_APP_LABEL_PERSONAL:
|
|
+ e_cal_component_set_categories (ec, "Personal"); break;
|
|
+ case PST_APP_LABEL_VACATION:
|
|
+ e_cal_component_set_categories (ec, "Vacation"); break;
|
|
+ case PST_APP_LABEL_MUST_ATTEND:
|
|
+ e_cal_component_set_categories (ec, "Must-attend"); break;
|
|
+ case PST_APP_LABEL_TRAVEL_REQ:
|
|
+ e_cal_component_set_categories (ec, "Travel-required"); break;
|
|
+ case PST_APP_LABEL_NEEDS_PREP:
|
|
+ e_cal_component_set_categories (ec, "Needs-preparation"); break;
|
|
+ case PST_APP_LABEL_BIRTHDAY:
|
|
+ e_cal_component_set_categories (ec, "Birthday"); break;
|
|
+ case PST_APP_LABEL_ANNIVERSARY:
|
|
+ e_cal_component_set_categories (ec, "Anniversary"); break;
|
|
+ case PST_APP_LABEL_PHONE_CALL:
|
|
+ e_cal_component_set_categories (ec, "Phone-call"); break;
|
|
+ }
|
|
+
|
|
+ if (a->alarm || a->alarm_minutes) {
|
|
+ ECalComponentAlarm *alarm;
|
|
+ ECalComponentAlarmTrigger trigger;
|
|
+
|
|
+ alarm = e_cal_component_alarm_new ();
|
|
+
|
|
+ if (a->alarm_minutes) {
|
|
+ trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
|
|
+ trigger.u.rel_duration = icaldurationtype_from_int (- (a->alarm_minutes)*60);
|
|
+ e_cal_component_alarm_set_trigger (alarm, trigger);
|
|
+ }
|
|
+
|
|
+ if (a->alarm) {
|
|
+ if (a->alarm_filename) {
|
|
+ e_cal_component_alarm_set_action (alarm, E_CAL_COMPONENT_ALARM_AUDIO);
|
|
+ } else {
|
|
+ e_cal_component_alarm_set_action (alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ e_cal_component_add_alarm (ec, alarm);
|
|
+ e_cal_component_alarm_free(alarm);
|
|
+
|
|
+ }
|
|
+
|
|
+ if (a->recurrence != PST_APP_RECUR_NONE) {
|
|
+ struct icalrecurrencetype r;
|
|
+ GSList recur_list;
|
|
+
|
|
+ icalrecurrencetype_clear (&r);
|
|
+ r.interval = 1; /* Interval not implemented in libpst */
|
|
+ if (a->recurrence_end) {
|
|
+ r.until = get_ical_date (a->recurrence_end, FALSE);
|
|
+ }
|
|
+
|
|
+ switch (a->recurrence_type) {
|
|
+ case PST_APP_RECUR_DAILY:
|
|
+ r.freq = ICAL_DAILY_RECURRENCE; break;
|
|
+ case PST_APP_RECUR_WEEKLY:
|
|
+ r.freq = ICAL_WEEKLY_RECURRENCE; break;
|
|
+ case PST_APP_RECUR_MONTHLY:
|
|
+ r.freq = ICAL_MONTHLY_RECURRENCE; break;
|
|
+ case PST_APP_RECUR_YEARLY:
|
|
+ r.freq = ICAL_YEARLY_RECURRENCE; break;
|
|
+ default:
|
|
+ r.freq = ICAL_NO_RECURRENCE;
|
|
+ }
|
|
+
|
|
+ recur_list.data = &r;
|
|
+ recur_list.next = NULL;
|
|
+ e_cal_component_set_rrule_list (ec, &recur_list);
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_appointment (PstImporter *m, pst_item *item)
|
|
+{
|
|
+ ECalComponent *ec;
|
|
+
|
|
+ ec = e_cal_component_new ();
|
|
+ e_cal_component_set_new_vtype (ec, E_CAL_COMPONENT_EVENT);
|
|
+
|
|
+ fill_calcomponent (m, item, ec, "appointment");
|
|
+ set_cal_attachments (m->calendar, ec, m, item->attach);
|
|
+
|
|
+ if (!e_cal_create_object (m->calendar, e_cal_component_get_icalcomponent (ec), NULL, NULL)) {
|
|
+ g_warning("Creation of appointment failed");
|
|
+ g_free(ec);
|
|
+ }
|
|
+
|
|
+ g_object_unref (ec);
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_task (PstImporter *m, pst_item *item)
|
|
+{
|
|
+ ECalComponent *ec;
|
|
+
|
|
+ ec = e_cal_component_new ();
|
|
+ e_cal_component_set_new_vtype (ec, E_CAL_COMPONENT_TODO);
|
|
+
|
|
+ fill_calcomponent (m, item, ec, "task");
|
|
+ set_cal_attachments (m->tasks, ec, m, item->attach);
|
|
+
|
|
+ /* Note - libpst is missing many fields. E.g. task status, start/completion date, % complete */
|
|
+
|
|
+ if (!e_cal_create_object (m->tasks, e_cal_component_get_icalcomponent (ec), NULL, NULL)) {
|
|
+ g_warning("Creation of task failed");
|
|
+ g_free(ec);
|
|
+ }
|
|
+
|
|
+ g_object_unref (ec);
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_process_journal (PstImporter *m, pst_item *item)
|
|
+{
|
|
+ struct pst_item_journal *j;
|
|
+ ECalComponent *ec;
|
|
+
|
|
+ j = item->journal;
|
|
+ ec = e_cal_component_new ();
|
|
+ e_cal_component_set_new_vtype (ec, E_CAL_COMPONENT_JOURNAL);
|
|
+
|
|
+ fill_calcomponent (m, item, ec, "journal");
|
|
+ set_cal_attachments (m->journal, ec, m, item->attach);
|
|
+
|
|
+ /* Note - an Evo memo entry does not have date started/finished or type fields :( */
|
|
+ /*if (j) {
|
|
+ ECalComponentText text;
|
|
+ struct icaltimetype tt_start, tt_end;
|
|
+ ECalComponentDateTime dt_start, dt_end;
|
|
+
|
|
+ if (j->start) {
|
|
+ tt_start = get_ical_date (j->start, FALSE);
|
|
+ dt_start.value = &tt_start;
|
|
+ dt_start.tzid = NULL;
|
|
+ e_cal_component_set_dtstart (ec, &dt_start);
|
|
+ g_message ("journal start:%s", rfc2445_datetime_format (j->start));
|
|
+ }
|
|
+
|
|
+ if (j->end) {
|
|
+ tt_end = get_ical_date (j->end, FALSE);
|
|
+ dt_end.value = &tt_end;
|
|
+ dt_end.tzid = NULL;
|
|
+ e_cal_component_set_dtend (ec, &dt_end);
|
|
+ g_message ("end:%s", rfc2445_datetime_format (j->end));
|
|
+ }
|
|
+ g_message ("type: %s", j->type);
|
|
+ }*/
|
|
+
|
|
+ if (!e_cal_create_object (m->journal, e_cal_component_get_icalcomponent (ec), NULL, NULL)) {
|
|
+ g_warning("Creation of journal entry failed");
|
|
+ g_free(ec);
|
|
+ }
|
|
+
|
|
+ g_object_unref (ec);
|
|
+
|
|
+}
|
|
+
|
|
+/* Print an error message - maybe later bring up an error dialog? */
|
|
+static void
|
|
+pst_error_msg (const char *fmt, ...)
|
|
+{
|
|
+ va_list ap;
|
|
+
|
|
+ va_start (ap, fmt);
|
|
+ g_critical (fmt, ap);
|
|
+ va_end (ap);
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_import_imported (PstImporter *m)
|
|
+{
|
|
+ e_import_complete (m->target->import, (EImportTarget *)m->target);
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_import_free (PstImporter *m)
|
|
+{
|
|
+// pst_close (&m->pst);
|
|
+ camel_operation_unref (m->status);
|
|
+
|
|
+ g_free (m->status_what);
|
|
+ g_mutex_free (m->status_lock);
|
|
+
|
|
+ g_source_remove (m->status_timeout_id);
|
|
+ m->status_timeout_id = 0;
|
|
+
|
|
+ g_free (m->folder_name);
|
|
+ g_free (m->folder_uri);
|
|
+ g_free (m->parent_uri);
|
|
+
|
|
+ g_object_unref (m->import);
|
|
+}
|
|
+
|
|
+static MailMsgInfo pst_import_info = {
|
|
+ sizeof (PstImporter),
|
|
+ (MailMsgDescFunc) pst_import_describe,
|
|
+ (MailMsgExecFunc) pst_import_import,
|
|
+ (MailMsgDoneFunc) pst_import_imported,
|
|
+ (MailMsgFreeFunc) pst_import_free,
|
|
+};
|
|
+
|
|
+static gboolean
|
|
+pst_status_timeout (void *data)
|
|
+{
|
|
+ PstImporter *importer = data;
|
|
+ int pc;
|
|
+ char *what;
|
|
+
|
|
+ if (importer->status_what) {
|
|
+ g_mutex_lock (importer->status_lock);
|
|
+ what = importer->status_what;
|
|
+ importer->status_what = NULL;
|
|
+ pc = importer->status_pc;
|
|
+ g_mutex_unlock (importer->status_lock);
|
|
+
|
|
+ e_import_status (importer->target->import, (EImportTarget *)importer->target, what, pc);
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void
|
|
+pst_status (CamelOperation *op, const char *what, int pc, void *data)
|
|
+{
|
|
+ PstImporter *importer = data;
|
|
+
|
|
+ if (pc == CAMEL_OPERATION_START) {
|
|
+ pc = 0;
|
|
+ } else if (pc == CAMEL_OPERATION_END) {
|
|
+ pc = 100;
|
|
+ }
|
|
+
|
|
+ g_mutex_lock (importer->status_lock);
|
|
+ g_free (importer->status_what);
|
|
+ importer->status_what = g_strdup (what);
|
|
+ importer->status_pc = pc;
|
|
+ g_mutex_unlock (importer->status_lock);
|
|
+}
|
|
+
|
|
+static int
|
|
+pst_import (EImport *ei, EImportTarget *target)
|
|
+{
|
|
+ PstImporter *m;
|
|
+ int id;
|
|
+
|
|
+ m = mail_msg_new (&pst_import_info);
|
|
+ g_datalist_set_data (&target->data, "pst-msg", m);
|
|
+ m->import = ei;
|
|
+ g_object_ref (m->import);
|
|
+ m->target = target;
|
|
+ g_message ("pst_import pstimporter=%p EImport=%p target=%p", m, ei, target);
|
|
+
|
|
+ m->parent_uri = NULL;
|
|
+ m->folder_name = NULL;
|
|
+ m->folder_uri = NULL;
|
|
+
|
|
+ m->addressbook = NULL;
|
|
+ m->calendar = NULL;
|
|
+ m->tasks = NULL;
|
|
+ m->journal = NULL;
|
|
+
|
|
+ m->status_timeout_id = g_timeout_add (100, pst_status_timeout, m);
|
|
+ /*m->status_timeout_id = NULL;*/
|
|
+ m->status_lock = g_mutex_new ();
|
|
+ m->status = camel_operation_new (pst_status, m);
|
|
+
|
|
+ id = m->base.seq;
|
|
+
|
|
+ mail_msg_unordered_push (m);
|
|
+
|
|
+ return id;
|
|
+}
|
|
+
|
|
+/* Start the main import operation */
|
|
+void
|
|
+org_credativ_evolution_readpst_import (EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
+{
|
|
+ if (GPOINTER_TO_INT (g_datalist_get_data (&target->data, "pst-do-mail"))
|
|
+ || GPOINTER_TO_INT (g_datalist_get_data (&target->data, "pst-do-addr"))
|
|
+ || GPOINTER_TO_INT (g_datalist_get_data (&target->data, "pst-do-appt"))
|
|
+ || GPOINTER_TO_INT (g_datalist_get_data (&target->data, "pst-do-task"))
|
|
+ || GPOINTER_TO_INT (g_datalist_get_data (&target->data, "pst-do-journal"))) {
|
|
+ pst_import (ei, target);
|
|
+ } else {
|
|
+ e_import_complete (target->import, target);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+org_credativ_evolution_readpst_cancel (EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
+{
|
|
+ PstImporter *m = g_datalist_get_data (&target->data, "pst-msg");
|
|
+
|
|
+ if (m) {
|
|
+ camel_operation_cancel (m->status);
|
|
+ }
|
|
+}
|
|
+
|
|
+int
|
|
+e_plugin_lib_enable (EPluginLib *ep, int enable)
|
|
+{
|
|
+ if (enable) {
|
|
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
|
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
|
+ g_message ("pst Plugin enabled");
|
|
+ } else {
|
|
+ g_message ("pst Plugin disabled");
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Open PST file and determine root folder name
|
|
+ * @param pst: pst_file structure to be used by libpst
|
|
+ * @param filename : path to file
|
|
+ * @return 0 for sucess, -1 for failure
|
|
+ */
|
|
+int
|
|
+pst_init (pst_file *pst, gchar *filename)
|
|
+{
|
|
+
|
|
+#if 0
|
|
+ char *d_log = "readpst.log";
|
|
+ /* initialize log file */
|
|
+ DEBUG_INIT (d_log);
|
|
+ DEBUG_REGISTER_CLOSE ();
|
|
+#endif
|
|
+
|
|
+ DEBUG_ENT ("main");
|
|
+ if (pst_open (pst, filename) < 0) {
|
|
+ pst_error_msg ("Error opening PST file %s", filename);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+// if (1) {
|
|
+ printf("\n\n %i is the pst index type\n\n", pst->ind_type);
|
|
+/* if (pst->ind_type != 14) {
|
|
+ printf("\nentered or not??\n not unknown index structure. Could this be a new Outlook 2003 PST file?\n");
|
|
+ unicode_init();
|
|
+ set_read64();
|
|
+// DEBUG_RET();
|
|
+// return -1;
|
|
+ }
|
|
+ else {
|
|
+ printf("\n\n check maadi\n\n");
|
|
+// unicode_close();
|
|
+ reset_read();
|
|
+ }
|
|
+*/
|
|
+ if (pst_load_index (pst) < 0) {
|
|
+ pst_error_msg ("Error loading indexes");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (pst_load_extended_attributes (pst) < 0) {
|
|
+ pst_error_msg ("Error loading file items");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+// unicode_init();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Open determine root folder name of PST file
|
|
+ * @param pst: pst_file structure to be used by libpst
|
|
+ * @param filename : if non NULL, fallback to this name if folder name is not available
|
|
+ * @return pointer to name of root folder (should be freed by caller), or NULL if error
|
|
+ */
|
|
+gchar *
|
|
+get_pst_rootname (pst_file *pst, gchar *filename)
|
|
+{
|
|
+ pst_item *item = NULL;
|
|
+ gchar *rootname = NULL;
|
|
+
|
|
+ printf("\n reached here\n");
|
|
+ if ((item = pst_parse_item (pst, pst->d_head)) == NULL) {
|
|
+ pst_error_msg ("Could not get root record");
|
|
+ printf("\n crashed in if i guess\n");
|
|
+ return NULL;
|
|
+ }
|
|
+ printf("\n crashed here i guess\n");
|
|
+ if (item->message_store == NULL) {
|
|
+ pst_error_msg ("Could not get root message store");
|
|
+ pst_freeItem (item);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* default the file_as to the same as the main filename if it doesn't exist */
|
|
+ if (item->file_as == NULL) {
|
|
+ if (filename == NULL) {
|
|
+ pst_freeItem (item);
|
|
+ return NULL;
|
|
+ }
|
|
+ rootname = g_path_get_basename (filename);
|
|
+ } else {
|
|
+ rootname = g_strdup (item->file_as);
|
|
+ }
|
|
+
|
|
+ g_message ("Root folder name: '%s'", rootname);
|
|
+
|
|
+ pst_freeItem (item);
|
|
+
|
|
+ return rootname;
|
|
+}
|
|
Index: plugins/pst-import/ChangeLog
|
|
===================================================================
|
|
--- plugins/pst-import/ChangeLog (revision 0)
|
|
+++ plugins/pst-import/ChangeLog (revision 0)
|
|
@@ -0,0 +1,9 @@
|
|
+2008-09-18 Bharath Acharya <abharath@novell.com>
|
|
+
|
|
+ Basic functionality implemented by
|
|
+ Chris Halls <chris.halls@credativ.co.uk>
|
|
+
|
|
+ ** Added PST-Import plugin
|
|
+ * Makefile.am:
|
|
+ * org-gnome-pst.eplug.xml:
|
|
+ * pst-importer.c:
|
|
Index: plugins/pst-import/org-gnome-pst.eplug.xml
|
|
===================================================================
|
|
--- plugins/pst-import/org-gnome-pst.eplug.xml (revision 0)
|
|
+++ plugins/pst-import/org-gnome-pst.eplug.xml (revision 0)
|
|
@@ -0,0 +1,23 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<e-plugin-list>
|
|
+ <e-plugin
|
|
+ id="org.gnome.evolution.plugin.pst"
|
|
+ type="shlib"
|
|
+ location="@PLUGINDIR@/liborg-gnome-pst@SOEXT@"
|
|
+ _name="Outlook PST import">
|
|
+ <_description>Import Outlook messages from PST file</_description>
|
|
+ <author name="Bharath Acharya" email="abharath@novell.com"/>
|
|
+ <author name="Chris Halls" email="chris.halls@credativ.co.uk"/>
|
|
+ <hook class="org.gnome.evolution.import:1.0">
|
|
+ <importer
|
|
+ target="uri"
|
|
+ _name = "Outlook personal folders (.pst)"
|
|
+ supported="org_credativ_evolution_readpst_supported"
|
|
+ get-widget="org_credativ_evolution_readpst_getwidget"
|
|
+ import="org_credativ_evolution_readpst_import"
|
|
+ cancel="org_credativ_evolution_readpst_cancel">
|
|
+ </importer>
|
|
+ </hook>
|
|
+ </e-plugin>
|
|
+</e-plugin-list>
|
|
+
|
|
Index: plugins/pst-import/Makefile.am
|
|
===================================================================
|
|
--- plugins/pst-import/Makefile.am (revision 0)
|
|
+++ plugins/pst-import/Makefile.am (revision 0)
|
|
@@ -0,0 +1,24 @@
|
|
+INCLUDES = \
|
|
+ -I$(EVOLUTION_SOURCE) \
|
|
+ -I$(top_srcdir) \
|
|
+ -DGETTEXT_PACKAGE="\"$(GETTEXT_PACKAGE)\"" \
|
|
+ -DLOCALEDIR="\"$(LOCALEDIR)\"" \
|
|
+ $(EVOLUTION_CFLAGS) \
|
|
+ $(EVOLUTION_MAIL_CFLAGS)
|
|
+
|
|
+@EVO_PLUGIN_RULE@
|
|
+
|
|
+plugin_DATA = org-gnome-pst.eplug
|
|
+plugin_LTLIBRARIES = liborg-gnome-pst.la
|
|
+
|
|
+liborg_gnome_pst_la_SOURCES = pst-importer.c
|
|
+liborg_gnome_pst_la_LDFLAGS = -module -avoid-version
|
|
+liborg_gnome_pst_la_LIBADD = \
|
|
+ $(LIBPST_LIBS)
|
|
+
|
|
+EXTRA_DIST = org-gnome-pst.eplug.xml
|
|
+
|
|
+BUILT_SOURCES = org-gnome-pst.eplug
|
|
+
|
|
+CLEANFILES = $(BUILT_SOURCES)
|
|
+
|
|
Index: configure.in
|
|
===================================================================
|
|
--- configure.in (revision 36340)
|
|
+++ configure.in (working copy)
|
|
@@ -1738,7 +1738,7 @@
|
|
plugins_base="$plugins_base_always $SA_JUNK_PLUGIN $BF_JUNK_PLUGIN $EXCHANGE_PLUGIN $MONO_PLUGIN "
|
|
all_plugins_base="$plugins_base_always sa-junk-plugin bogo-junk-plugin exchange-operations mono"
|
|
|
|
-plugins_standard_always="bbdb subject-thread save-calendar select-one-source copy-tool mail-to-task mark-calendar-offline audio-inline mailing-list-actions default-mailer import-ics-attachments prefer-plain mail-notification attachment-reminder face backup-restore email-custom-header templates"
|
|
+plugins_standard_always="bbdb subject-thread save-calendar select-one-source copy-tool mail-to-task mark-calendar-offline audio-inline mailing-list-actions default-mailer import-ics-attachments prefer-plain mail-notification attachment-reminder face backup-restore email-custom-header templates pst-import"
|
|
|
|
plugins_standard="$plugins_standard_always"
|
|
all_plugins_standard="$plugins_standard"
|
|
@@ -1853,6 +1853,23 @@
|
|
fi
|
|
fi
|
|
|
|
+if echo ${plugins_enabled} | grep "pst-import" > /dev/null
|
|
+then
|
|
+ if ${PKG_CONFIG} --exists libpst
|
|
+ then
|
|
+ dnl *********************
|
|
+ dnl libpst
|
|
+ dnl *********************
|
|
+ PKG_CHECK_MODULES(LIBPST, libpst)
|
|
+ AC_SUBST(LIBPST_CFLAGS)
|
|
+ AC_SUBST(LIBPST_LIBS)
|
|
+ else
|
|
+ plugins_enabled=`echo $plugins_enabled | sed -e "s/pst-import//g"`
|
|
+ echo "warning: libpst was not found, pst-import plugin will not be built."
|
|
+ echo "you are probably missing libpst-devel package."
|
|
+ fi
|
|
+fi
|
|
+
|
|
dnl ***********
|
|
dnl GConf stuff
|
|
dnl ***********
|
|
@@ -2049,6 +2066,7 @@
|
|
plugins/imap-features/Makefile
|
|
plugins/tnef-attachments/Makefile
|
|
plugins/templates/Makefile
|
|
+plugins/pst-import/Makefile
|
|
plugins/face/Makefile
|
|
plugins/external-editor/Makefile
|
|
plugins/webdav-account-setup/Makefile
|