[evolution/gnome-3-0] Bug 655263 - mail lost in MailDir migration



commit b8a3a342a0a9f2421e38b4d17ae52257c7b0f702
Author: Chenthill Palanisamy <pchenthill novell com>
Date:   Wed Jul 27 15:02:20 2011 +0530

    Bug 655263 - mail lost in MailDir migration

 mail/e-mail-migrate.c          |   75 ++++++++++++++++++---
 mail/em-utils.c                |  138 ++++++++++++++++++++++++++++++++++++++++
 mail/em-utils.h                |    8 ++
 mail/importers/mail-importer.c |  135 +--------------------------------------
 mail/importers/mail-importer.h |    7 --
 5 files changed, 212 insertions(+), 151 deletions(-)
---
diff --git a/mail/e-mail-migrate.c b/mail/e-mail-migrate.c
index 9d1452b..d101906 100644
--- a/mail/e-mail-migrate.c
+++ b/mail/e-mail-migrate.c
@@ -797,10 +797,16 @@ sanitize_maildir_folder_name (gchar *folder_name)
 }
 
 static void
-copy_folder (CamelStore *mbox_store, CamelStore *maildir_store, const gchar *mbox_fname, const gchar *maildir_fname)
+copy_folder (EShellBackend *shell_backend, CamelStore *mbox_store, CamelStore *maildir_store, const gchar *mbox_fname, const gchar *maildir_fname)
 {
 	CamelFolder *fromfolder, *tofolder;
-	GPtrArray *uids;
+	EMailSession *mail_session;
+	GPtrArray *uids, *single_uid;
+	GError *error = NULL;
+	gboolean use_fallback = FALSE;
+	guint i;
+
+	mail_session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
 
 	fromfolder = camel_store_get_folder_sync (
 		mbox_store, mbox_fname, 0, NULL, NULL);
@@ -820,18 +826,63 @@ copy_folder (CamelStore *mbox_store, CamelStore *maildir_store, const gchar *mbo
 	}
 
 	uids = camel_folder_get_uids (fromfolder);
-	camel_folder_transfer_messages_to_sync (
-			fromfolder, uids, tofolder,
-			FALSE, NULL,
-			NULL, NULL);
+	single_uid = g_ptr_array_new ();
+
+	/* import mails one by one to detect summary-mismatch errors */
+	for (i = 0; i < uids->len; i++) {
+		gpointer uid = g_ptr_array_index (uids, i);
+	
+		g_ptr_array_add (single_uid, uid);
+		camel_folder_transfer_messages_to_sync (
+				fromfolder, single_uid, tofolder,
+				FALSE, NULL,
+				NULL, &error);
+		g_ptr_array_remove_index (single_uid, 0);
+		if (error) {
+			g_warning ("Error migrating folder %s: %s \n", mbox_fname, error->message);
+		
+			g_clear_error (&error);
+			/* delete the maildir folder */
+			camel_store_delete_folder_sync (maildir_store, maildir_fname, NULL, NULL);
+			if (error)
+				g_warning ("Error deleting maildir folder %s: %s \n", maildir_fname, error->message);
+
+			use_fallback = TRUE;
+			break;
+		}
+	}
 	camel_folder_free_uids (fromfolder, uids);
+	g_ptr_array_free (single_uid, TRUE);
+
+	/* fallback, import the mbox file directly. All the flags will be lost in this method */
+	if (use_fallback) {
+		const gchar *to_uri;
+		CamelService *mbox_service;
+		gchar *mbox_file_name;
+		
+		g_message ("Using the fallback method to migrate \n");
+		to_uri = camel_folder_get_uri (tofolder);
+		
+		/* build the filename ourselves as there is no way i see to get the filename from the store */
+		mbox_service = (CamelService *) mbox_store;
+		mbox_file_name = g_build_filename (mbox_service->url->path, mbox_fname, NULL);
+
+		g_clear_error (&error);
+		em_utils_import_mbox (mail_session, to_uri, mbox_file_name, NULL, &error);
+		
+		g_free (mbox_file_name);
+	}
+
+	if (error)
+		g_warning ("Error migrating folder %s: %s \n", mbox_fname, error->message);
 
 	g_object_unref (fromfolder);
 	g_object_unref (tofolder);
+	g_clear_error (&error);
 }
 
 static void
-copy_folders (CamelStore *mbox_store, CamelStore *maildir_store, CamelFolderInfo *fi, EMMigrateSession *session)
+copy_folders (EShellBackend *shell_backend, CamelStore *mbox_store, CamelStore *maildir_store, CamelFolderInfo *fi, EMMigrateSession *session)
 {
 	if (fi) {
 		if (!g_str_has_prefix (fi->full_name, ".#evolution")) {
@@ -839,19 +890,20 @@ copy_folders (CamelStore *mbox_store, CamelStore *maildir_store, CamelFolderInfo
 
 			/* sanitize folder names and copy folders */
 			maildir_folder_name = sanitize_maildir_folder_name (fi->full_name);
-			copy_folder (mbox_store, maildir_store, fi->full_name, maildir_folder_name);
+			copy_folder (shell_backend, mbox_store, maildir_store, fi->full_name, maildir_folder_name);
 			g_free (maildir_folder_name);
 		}
 
 		if (fi->child)
-			copy_folders (mbox_store, maildir_store, fi->child, session);
+			copy_folders (shell_backend, mbox_store, maildir_store, fi->child, session);
 
-		copy_folders (mbox_store, maildir_store, fi->next, session);
+		copy_folders (shell_backend, mbox_store, maildir_store, fi->next, session);
 	}
 }
 
 struct MigrateStore {
 	EMMigrateSession *session;
+	EShellBackend *shell_backend;
 	CamelStore *mbox_store;
 	CamelStore *maildir_store;
 	gboolean complete;
@@ -872,7 +924,7 @@ migrate_stores (struct MigrateStore *ms)
 		NULL, NULL);
 
 	/* FIXME progres dialog */
-	copy_folders (mbox_store, maildir_store, mbox_fi, ms->session);
+	copy_folders (ms->shell_backend, mbox_store, maildir_store, mbox_fi, ms->session);
 	ms->complete = TRUE;
 
 	return;
@@ -920,6 +972,7 @@ migrate_mbox_to_maildir (EShellBackend *shell_backend, EMMigrateSession *session
 	ms.mbox_store = mbox_store;
 	ms.maildir_store = maildir_store;
 	ms.session = session;
+	ms.shell_backend = shell_backend;
 	ms.complete = FALSE;
 
 	g_thread_create ((GThreadFunc) migrate_stores, &ms, TRUE, NULL);
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 15008ab..1cbb2ff 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -2446,3 +2446,141 @@ em_utils_is_local_delivery_mbox_file (const gchar *uri)
 
 	return FALSE;
 }
+
+static struct {
+	gchar tag;
+	guint32 mozflag;
+	guint32 flag;
+} status_flags[] = {
+	{ 'F', MSG_FLAG_MARKED, CAMEL_MESSAGE_FLAGGED },
+	{ 'A', MSG_FLAG_REPLIED, CAMEL_MESSAGE_ANSWERED },
+	{ 'D', MSG_FLAG_EXPUNGED, CAMEL_MESSAGE_DELETED },
+	{ 'R', MSG_FLAG_READ, CAMEL_MESSAGE_SEEN },
+};
+
+static guint32
+decode_status (const gchar *status)
+{
+	const gchar *p;
+	guint32 flags = 0;
+	gint i;
+
+	p = status;
+	while ((*p++)) {
+		for (i = 0; i < G_N_ELEMENTS (status_flags); i++)
+			if (status_flags[i].tag == *p)
+				flags |= status_flags[i].flag;
+	}
+
+	return flags;
+}
+
+static guint32
+decode_mozilla_status (const gchar *tmp)
+{
+	unsigned long status = strtoul (tmp, NULL, 16);
+	guint32 flags = 0;
+	gint i;
+
+	for (i = 0; i < G_N_ELEMENTS (status_flags); i++)
+		if (status_flags[i].mozflag & status)
+			flags |= status_flags[i].flag;
+	return flags;
+}
+
+void
+em_utils_import_mbox (EMailSession *mail_session, const gchar *folder_uri, const gchar *mbox_path, GCancellable *cancellable, GError **error)
+{
+	CamelFolder *folder;
+	CamelMimeParser *mp = NULL;
+	struct stat st;
+	gint fd;
+	CamelMessageInfo *info;
+
+	if (g_stat (mbox_path, &st) == -1) {
+		g_warning("cannot find source file to import '%s': %s", mbox_path, g_strerror(errno));
+		return;
+	}
+
+	if (folder_uri == NULL || folder_uri[0] == 0)
+		folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX);
+	else
+		folder = e_mail_session_uri_to_folder_sync (
+			mail_session, folder_uri, CAMEL_STORE_FOLDER_CREATE,
+			cancellable, error);
+
+	if (folder == NULL)
+		return;
+
+	if (S_ISREG (st.st_mode)) {
+		fd = g_open (mbox_path, O_RDONLY|O_BINARY, 0);
+		if (fd == -1) {
+			g_warning("cannot find source file to import '%s': %s", mbox_path, g_strerror(errno));
+			goto fail1;
+		}
+
+		mp = camel_mime_parser_new ();
+		camel_mime_parser_scan_from (mp, TRUE);
+		if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
+			/* will never happen - 0 is unconditionally returned */
+			goto fail2;
+		}
+
+		camel_operation_push_message (
+			cancellable, _("Importing '%s'"),
+			camel_folder_get_full_name (folder));
+		camel_folder_freeze (folder);
+		while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) {
+			CamelMimeMessage *msg;
+			const gchar *tmp;
+			gint pc = 0;
+			guint32 flags = 0;
+
+			if (st.st_size > 0)
+				pc = (gint)(100.0 * ((double)camel_mime_parser_tell (mp) / (double)st.st_size));
+			camel_operation_progress (cancellable, pc);
+
+			msg = camel_mime_message_new ();
+			if (!camel_mime_part_construct_from_parser_sync (
+				(CamelMimePart *)msg, mp, NULL, NULL)) {
+				/* set exception? */
+				g_object_unref (msg);
+				break;
+			}
+
+			info = camel_message_info_new (NULL);
+
+			tmp = camel_medium_get_header((CamelMedium *)msg, "X-Mozilla-Status");
+			if (tmp)
+				flags |= decode_mozilla_status (tmp);
+			tmp = camel_medium_get_header((CamelMedium *)msg, "Status");
+			if (tmp)
+				flags |= decode_status (tmp);
+			tmp = camel_medium_get_header((CamelMedium *)msg, "X-Status");
+			if (tmp)
+				flags |= decode_status (tmp);
+
+			camel_message_info_set_flags (info, flags, ~0);
+			camel_folder_append_message_sync (
+				folder, msg, info, NULL,
+				cancellable, error);
+			camel_message_info_free (info);
+			g_object_unref (msg);
+
+			if (error && *error != NULL)
+				break;
+
+			camel_mime_parser_step (mp, NULL, NULL);
+		}
+		/* FIXME Not passing a GCancellable or GError here. */
+		camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
+		camel_folder_thaw (folder);
+		camel_operation_pop_message (cancellable);
+	fail2:
+		g_object_unref (mp);
+	}
+fail1:
+	/* FIXME Not passing a GCancellable or GError here. */
+	camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
+	g_object_unref (folder);
+}
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 73916b1..1892c4c 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -35,6 +35,13 @@ G_BEGIN_DECLS
 
 struct _EMFormat;
 
+/* Defines copied from nsMsgMessageFlags.h in Mozilla source. */
+/* Evolution only cares about these headers I think */
+#define MSG_FLAG_READ 0x0001
+#define MSG_FLAG_REPLIED 0x0002
+#define MSG_FLAG_MARKED 0x0004
+#define MSG_FLAG_EXPUNGED 0x0008
+
 gboolean em_utils_ask_open_many (GtkWindow *parent, gint how_many);
 gboolean em_utils_prompt_user (GtkWindow *parent, const gchar *promptkey, const gchar *tag, ...);
 
@@ -101,6 +108,7 @@ void emu_remove_from_mail_cache_1 (const gchar *address);
 void emu_free_mail_cache (void);
 
 void emu_restore_folder_tree_state (EMFolderTree *folder_tree);
+void em_utils_import_mbox (EMailSession *mail_session, const gchar *folder_uri, const gchar *mbox_path, GCancellable *cancellable, GError **error);
 
 gboolean em_utils_is_local_delivery_mbox_file (const gchar *uri);
 
diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c
index f6cbbbb..a47fa30 100644
--- a/mail/importers/mail-importer.c
+++ b/mail/importers/mail-importer.c
@@ -40,6 +40,7 @@
 #include "e-util/e-util-private.h"
 #include "shell/e-shell-backend.h"
 
+#include "em-utils.h"
 #include "mail-mt.h"
 #include "mail-tools.h"
 #include "e-mail-local.h"
@@ -65,144 +66,12 @@ import_mbox_desc (struct _import_mbox_msg *m)
 	return g_strdup (_("Importing mailbox"));
 }
 
-static struct {
-	gchar tag;
-	guint32 mozflag;
-	guint32 flag;
-} status_flags[] = {
-	{ 'F', MSG_FLAG_MARKED, CAMEL_MESSAGE_FLAGGED },
-	{ 'A', MSG_FLAG_REPLIED, CAMEL_MESSAGE_ANSWERED },
-	{ 'D', MSG_FLAG_EXPUNGED, CAMEL_MESSAGE_DELETED },
-	{ 'R', MSG_FLAG_READ, CAMEL_MESSAGE_SEEN },
-};
-
-static guint32
-decode_status (const gchar *status)
-{
-	const gchar *p;
-	guint32 flags = 0;
-	gint i;
-
-	p = status;
-	while ((*p++)) {
-		for (i = 0; i < G_N_ELEMENTS (status_flags); i++)
-			if (status_flags[i].tag == *p)
-				flags |= status_flags[i].flag;
-	}
-
-	return flags;
-}
-
-static guint32
-decode_mozilla_status (const gchar *tmp)
-{
-	unsigned long status = strtoul (tmp, NULL, 16);
-	guint32 flags = 0;
-	gint i;
-
-	for (i = 0; i < G_N_ELEMENTS (status_flags); i++)
-		if (status_flags[i].mozflag & status)
-			flags |= status_flags[i].flag;
-	return flags;
-}
-
 static void
 import_mbox_exec (struct _import_mbox_msg *m,
                   GCancellable *cancellable,
                   GError **error)
 {
-	CamelFolder *folder;
-	CamelMimeParser *mp = NULL;
-	struct stat st;
-	gint fd;
-	CamelMessageInfo *info;
-
-	if (g_stat (m->path, &st) == -1) {
-		g_warning("cannot find source file to import '%s': %s", m->path, g_strerror(errno));
-		return;
-	}
-
-	if (m->uri == NULL || m->uri[0] == 0)
-		folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX);
-	else
-		folder = e_mail_session_uri_to_folder_sync (
-			m->session, m->uri, CAMEL_STORE_FOLDER_CREATE,
-			cancellable, error);
-
-	if (folder == NULL)
-		return;
-
-	if (S_ISREG (st.st_mode)) {
-		fd = g_open (m->path, O_RDONLY|O_BINARY, 0);
-		if (fd == -1) {
-			g_warning("cannot find source file to import '%s': %s", m->path, g_strerror(errno));
-			goto fail1;
-		}
-
-		mp = camel_mime_parser_new ();
-		camel_mime_parser_scan_from (mp, TRUE);
-		if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
-			/* will never happen - 0 is unconditionally returned */
-			goto fail2;
-		}
-
-		camel_operation_push_message (
-			cancellable, _("Importing '%s'"),
-			camel_folder_get_full_name (folder));
-		camel_folder_freeze (folder);
-		while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) {
-			CamelMimeMessage *msg;
-			const gchar *tmp;
-			gint pc = 0;
-			guint32 flags = 0;
-
-			if (st.st_size > 0)
-				pc = (gint)(100.0 * ((double)camel_mime_parser_tell (mp) / (double)st.st_size));
-			camel_operation_progress (cancellable, pc);
-
-			msg = camel_mime_message_new ();
-			if (!camel_mime_part_construct_from_parser_sync (
-				(CamelMimePart *)msg, mp, NULL, NULL)) {
-				/* set exception? */
-				g_object_unref (msg);
-				break;
-			}
-
-			info = camel_message_info_new (NULL);
-
-			tmp = camel_medium_get_header((CamelMedium *)msg, "X-Mozilla-Status");
-			if (tmp)
-				flags |= decode_mozilla_status (tmp);
-			tmp = camel_medium_get_header((CamelMedium *)msg, "Status");
-			if (tmp)
-				flags |= decode_status (tmp);
-			tmp = camel_medium_get_header((CamelMedium *)msg, "X-Status");
-			if (tmp)
-				flags |= decode_status (tmp);
-
-			camel_message_info_set_flags (info, flags, ~0);
-			camel_folder_append_message_sync (
-				folder, msg, info, NULL,
-				cancellable, error);
-			camel_message_info_free (info);
-			g_object_unref (msg);
-
-			if (error && *error != NULL)
-				break;
-
-			camel_mime_parser_step (mp, NULL, NULL);
-		}
-		/* FIXME Not passing a GCancellable or GError here. */
-		camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
-		camel_folder_thaw (folder);
-		camel_operation_pop_message (cancellable);
-	fail2:
-		g_object_unref (mp);
-	}
-fail1:
-	/* FIXME Not passing a GCancellable or GError here. */
-	camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
-	g_object_unref (folder);
+	em_utils_import_mbox (m->session, m->uri, m->path, cancellable, error);
 }
 
 static void
diff --git a/mail/importers/mail-importer.h b/mail/importers/mail-importer.h
index 93d1897..e22131b 100644
--- a/mail/importers/mail-importer.h
+++ b/mail/importers/mail-importer.h
@@ -40,13 +40,6 @@ void mbox_importer_set_preview_funcs (MboxImporterCreatePreviewFunc create_func,
 EImportImporter *elm_importer_peek (void);
 EImportImporter *pine_importer_peek (void);
 
-/* Defines copied from nsMsgMessageFlags.h in Mozilla source. */
-/* Evolution only cares about these headers I think */
-#define MSG_FLAG_READ 0x0001
-#define MSG_FLAG_REPLIED 0x0002
-#define MSG_FLAG_MARKED 0x0004
-#define MSG_FLAG_EXPUNGED 0x0008
-
 gint		mail_importer_import_mbox	(EMailSession *session,
 						 const gchar *path,
 						 const gchar *folderuri,



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