[evolution-mapi] Bug #608327 - Cannot recover after connection lost (mailer part)
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug #608327 - Cannot recover after connection lost (mailer part)
- Date: Mon, 16 Jul 2012 16:00:56 +0000 (UTC)
commit 4f8268749ecb66b129785f1be8edfe854b7728a9
Author: Milan Crha <mcrha redhat com>
Date: Mon Jul 16 18:00:05 2012 +0200
Bug #608327 - Cannot recover after connection lost (mailer part)
configure.ac | 2 +-
src/camel/camel-mapi-folder.c | 160 ++++++++++++--------
src/camel/camel-mapi-store.c | 85 ++++++++---
src/camel/camel-mapi-store.h | 10 +-
.../e-mapi-subscribe-foreign-folder.c | 4 +-
src/libexchangemapi/e-mapi-connection.c | 66 +++++++--
src/libexchangemapi/e-mapi-connection.h | 5 +-
7 files changed, 233 insertions(+), 99 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 81df317..a5760cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,7 +28,7 @@ dnl *******************
m4_define([eds_minimum_version], [ema_version])
m4_define([evo_minimum_version], [ema_version])
m4_define([libmapi_minimum_version], [1.0])
-m4_define([glib_minimum_version], [2.16.1])
+m4_define([glib_minimum_version], [2.32.0])
m4_define([gtk_minimum_version], [2.99.2])
dnl ***********************************
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index b74d09c..c5d23dd 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -67,17 +67,27 @@ cmf_open_folder (CamelMapiFolder *mapi_folder,
GError **perror)
{
gboolean res;
+ GError *mapi_error = NULL;
g_return_val_if_fail (mapi_folder != NULL, FALSE);
g_return_val_if_fail (conn != NULL, FALSE);
g_return_val_if_fail (obj_folder != NULL, FALSE);
if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
- res = e_mapi_connection_open_foreign_folder (conn, mapi_folder->priv->foreign_username, mapi_folder->folder_id, obj_folder, cancellable, perror);
+ res = e_mapi_connection_open_foreign_folder (conn, mapi_folder->priv->foreign_username, mapi_folder->folder_id, obj_folder, cancellable, &mapi_error);
else if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
- res = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, perror);
+ res = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, &mapi_error);
else
- res = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, perror);
+ res = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, &mapi_error);
+
+ if (mapi_error) {
+ CamelMapiStore *mapi_store;
+
+ mapi_store = CAMEL_MAPI_STORE (camel_folder_get_parent_store (CAMEL_FOLDER (mapi_folder)));
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+
+ g_propagate_error (perror, mapi_error);
+ }
return res;
}
@@ -746,12 +756,12 @@ camel_mapi_folder_fetch_summary (CamelFolder *folder, GCancellable *cancellable,
CamelMapiStoreInfo *msi = NULL;
CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (store);
CamelMapiFolder *mapi_folder = CAMEL_MAPI_FOLDER (folder);
- EMapiConnection *conn = camel_mapi_store_get_connection (mapi_store);
+ EMapiConnection *conn = camel_mapi_store_get_connection (mapi_store, cancellable, mapi_error);
struct FolderBasicPropertiesData fbp;
struct GatherChangedObjectsData gco;
mapi_object_t obj_folder;
- if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
+ if (!conn)
return FALSE;
camel_folder_freeze (folder);
@@ -869,6 +879,9 @@ camel_mapi_folder_fetch_summary (CamelFolder *folder, GCancellable *cancellable,
msi->last_obj_total = fbp.obj_total;
}
+ if (mapi_error && *mapi_error)
+ camel_mapi_store_maybe_disconnect (mapi_store, *mapi_error);
+
camel_folder_summary_save_to_db (folder->summary, NULL);
camel_folder_thaw (folder);
@@ -917,7 +930,7 @@ mapi_refresh_folder (CamelFolder *folder, GCancellable *cancellable, GError **er
goto end1;
}
- if (!camel_mapi_store_connected (mapi_store, &mapi_error)) {
+ if (!camel_mapi_store_connected (mapi_store, cancellable, &mapi_error)) {
if (mapi_error) {
if (!e_mapi_utils_propagate_cancelled_error (mapi_error, error))
g_set_error (
@@ -1153,7 +1166,6 @@ mapi_folder_append_message_sync (CamelFolder *folder,
GError **error)
{
CamelMapiStore *mapi_store;
- CamelOfflineStore *offline;
CamelStoreInfo *si;
CamelStore *parent_store;
mapi_id_t fid = 0, mid = 0;
@@ -1168,7 +1180,6 @@ mapi_folder_append_message_sync (CamelFolder *folder,
parent_store = camel_folder_get_parent_store (folder);
mapi_store = CAMEL_MAPI_STORE (parent_store);
- offline = CAMEL_OFFLINE_STORE (parent_store);
/*Reject outbox / sent & trash*/
si = camel_store_summary_path (mapi_store->summary, full_name);
@@ -1186,7 +1197,8 @@ mapi_folder_append_message_sync (CamelFolder *folder,
return FALSE;
}
- if (!camel_offline_store_get_online (offline)) {
+ conn = camel_mapi_store_get_connection (mapi_store, cancellable, error);
+ if (!conn) {
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Offline."));
@@ -1197,7 +1209,6 @@ mapi_folder_append_message_sync (CamelFolder *folder,
e_mapi_util_mapi_id_from_string (folder_id, &fid);
/* Convert MIME to Item */
- conn = camel_mapi_store_get_connection (mapi_store);
if (cmf_open_folder (CAMEL_MAPI_FOLDER (folder), conn, &obj_folder, cancellable, &mapi_error)) {
struct CamelMapiCreateData cmc;
@@ -1215,6 +1226,7 @@ mapi_folder_append_message_sync (CamelFolder *folder,
if (mapi_error) {
if (!e_mapi_utils_propagate_cancelled_error (mapi_error, error))
g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, mapi_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
g_error_free (mapi_error);
} else {
g_set_error (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Offline."));
@@ -1254,7 +1266,10 @@ mapi_folder_expunge_sync (CamelFolder *folder,
mapi_folder = CAMEL_MAPI_FOLDER (folder);
mapi_store = CAMEL_MAPI_STORE (parent_store);
- conn = camel_mapi_store_get_connection (mapi_store);
+ conn = camel_mapi_store_get_connection (mapi_store, cancellable, error);
+
+ if (!conn)
+ return FALSE;
if ((mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) {
mapi_object_t obj_folder;
@@ -1296,6 +1311,7 @@ mapi_folder_expunge_sync (CamelFolder *folder,
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Failed to empty Trash: %s"), mapi_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
g_error_free (mapi_error);
} else {
g_set_error_literal (
@@ -1338,11 +1354,17 @@ mapi_folder_expunge_sync (CamelFolder *folder,
if (deleted_items) {
mapi_object_t obj_folder;
+ GError *mapi_error = NULL;
- status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, NULL);
+ status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
- status = e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, NULL);
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, NULL);
+ status = e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+ }
+
+ if (mapi_error) {
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+ g_clear_error (&mapi_error);
}
if (status) {
@@ -1484,7 +1506,7 @@ mapi_folder_get_message_sync (CamelFolder *folder,
}
/* Check if we are really offline */
- if (!camel_mapi_store_connected (mapi_store, &mapi_error)) {
+ if (!camel_mapi_store_connected (mapi_store, cancellable, &mapi_error)) {
if (mapi_error) {
if (!e_mapi_utils_propagate_cancelled_error (mapi_error, error))
g_set_error (
@@ -1501,9 +1523,11 @@ mapi_folder_get_message_sync (CamelFolder *folder,
return NULL;
}
- e_mapi_util_mapi_id_from_string (uid, &id_message);
+ conn = camel_mapi_store_get_connection (mapi_store, cancellable, error);
+ if (!conn)
+ return NULL;
- conn = camel_mapi_store_get_connection (mapi_store);
+ e_mapi_util_mapi_id_from_string (uid, &id_message);
success = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
if (success) {
@@ -1518,6 +1542,7 @@ mapi_folder_get_message_sync (CamelFolder *folder,
g_set_error (
error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_INVALID,
_("Could not get message: %s"), mapi_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
g_error_free (mapi_error);
} else {
g_set_error (
@@ -1568,6 +1593,7 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
gint i;
gboolean is_junk_folder, has_obj_folder = FALSE;
mapi_object_t obj_folder;
+ GError *mapi_error = NULL;
full_name = camel_folder_get_full_name (folder);
parent_store = camel_folder_get_parent_store (folder);
@@ -1586,7 +1612,8 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
folder_id = camel_mapi_store_folder_id_lookup (mapi_store, full_name);
e_mapi_util_mapi_id_from_string (folder_id, &fid);
- if (!camel_mapi_store_connected (mapi_store, error))
+ conn = camel_mapi_store_get_connection (mapi_store, cancellable, error);
+ if (!conn)
return FALSE;
is_junk_folder = (mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_JUNK;
@@ -1663,37 +1690,30 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
Evo doesnt not take care of it, as I find that scenario to be impractical.
*/
- conn = camel_mapi_store_get_connection (mapi_store);
- has_obj_folder = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, NULL);
+ has_obj_folder = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
if (read_items && has_obj_folder) {
if (read_with_receipt)
- e_mapi_connection_set_flags (conn, &obj_folder, read_with_receipt, CLEAR_RN_PENDING, cancellable, NULL);
- e_mapi_connection_set_flags (conn, &obj_folder, read_items, 0, cancellable, NULL);
+ e_mapi_connection_set_flags (conn, &obj_folder, read_with_receipt, CLEAR_RN_PENDING, cancellable, &mapi_error);
+ e_mapi_connection_set_flags (conn, &obj_folder, read_items, 0, cancellable, &mapi_error);
}
if (unread_items && has_obj_folder) {
- e_mapi_connection_set_flags (conn, &obj_folder, unread_items, CLEAR_READ_FLAG, cancellable, NULL);
+ e_mapi_connection_set_flags (conn, &obj_folder, unread_items, CLEAR_READ_FLAG, cancellable, &mapi_error);
}
/* Remove messages from server*/
if (deleted_items && has_obj_folder) {
if ((mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) {
- e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, NULL);
+ e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, &mapi_error);
} else {
- GError *err = NULL;
mapi_id_t deleted_items_fid;
mapi_object_t deleted_obj_folder;
e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderDeletedItems), &deleted_items_fid);
- if (e_mapi_connection_open_personal_folder (conn, deleted_items_fid, &deleted_obj_folder, cancellable, &err)) {
- e_mapi_connection_copymove_items (conn, &obj_folder, &deleted_obj_folder, FALSE, deleted_items, cancellable, &err);
- e_mapi_connection_close_folder (conn, &deleted_obj_folder, cancellable, &err);
- }
-
- if (err) {
- g_warning ("%s: Failed to move deleted items: %s", G_STRFUNC, err->message);
- g_error_free (err);
+ if (e_mapi_connection_open_personal_folder (conn, deleted_items_fid, &deleted_obj_folder, cancellable, &mapi_error)) {
+ e_mapi_connection_copymove_items (conn, &obj_folder, &deleted_obj_folder, FALSE, deleted_items, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &deleted_obj_folder, cancellable, &mapi_error);
}
}
}
@@ -1701,27 +1721,21 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
if (junk_items && has_obj_folder) {
mapi_id_t junk_fid = 0;
mapi_object_t junk_obj_folder;
- GError *err = NULL;
if (has_obj_folder) {
e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderJunk), &junk_fid);
- if (e_mapi_connection_open_personal_folder (conn, junk_fid, &junk_obj_folder, cancellable, &err)) {
- e_mapi_connection_copymove_items (conn, &obj_folder, &junk_obj_folder, FALSE, junk_items, cancellable, &err);
- e_mapi_connection_close_folder (conn, &junk_obj_folder, cancellable, &err);
+ if (e_mapi_connection_open_personal_folder (conn, junk_fid, &junk_obj_folder, cancellable, &mapi_error)) {
+ e_mapi_connection_copymove_items (conn, &obj_folder, &junk_obj_folder, FALSE, junk_items, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &junk_obj_folder, cancellable, &mapi_error);
}
}
/* in junk_items are only emails which are not deleted */
deleted_items = g_slist_concat (deleted_items, g_slist_copy (junk_items));
-
- if (err) {
- g_warning ("%s: Failed to move junk items: %s", G_STRFUNC, err->message);
- g_error_free (err);
- }
}
if (has_obj_folder)
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, NULL);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
/*Remove messages from local cache*/
for (l = deleted_items; l; l = l->next) {
@@ -1752,6 +1766,11 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
g_slist_foreach (to_free, (GFunc) g_free, NULL);
g_slist_free (to_free);
+ if (mapi_error) {
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+ g_clear_error (&mapi_error);
+ }
+
if (expunge) {
/* TODO */
}
@@ -1777,7 +1796,7 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
gint i = 0;
GSList *src_msg_ids = NULL;
gboolean success = TRUE;
- GError *err = NULL;
+ GError *mapi_error = NULL;
mapi_object_t src_obj_folder, des_obj_folder;
gboolean copymoved = FALSE;
EMapiConnection *conn;
@@ -1788,7 +1807,11 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
return FALSE;
}
- if (!CAMEL_IS_MAPI_FOLDER (source) || !CAMEL_IS_MAPI_FOLDER (destination) ||
+ source_parent_store = camel_folder_get_parent_store (source);
+ mapi_store = CAMEL_MAPI_STORE (source_parent_store);
+ conn = camel_mapi_store_get_connection (mapi_store, cancellable, error);
+
+ if (!conn || !CAMEL_IS_MAPI_FOLDER (source) || !CAMEL_IS_MAPI_FOLDER (destination) ||
(CAMEL_MAPI_FOLDER (source)->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ||
(CAMEL_MAPI_FOLDER (destination)->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0) {
CamelFolderClass *folder_class;
@@ -1801,10 +1824,11 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
transferred_uids, cancellable, error);
}
- source_parent_store = camel_folder_get_parent_store (source);
+ if (!conn)
+ return FALSE;
+
destination_parent_store = camel_folder_get_parent_store (destination);
- mapi_store = CAMEL_MAPI_STORE (source_parent_store);
offline = CAMEL_OFFLINE_STORE (destination_parent_store);
/* check for offline operation */
@@ -1822,23 +1846,22 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
src_msg_ids = g_slist_prepend (src_msg_ids, mid);
}
- conn = camel_mapi_store_get_connection (mapi_store);
-
- if (cmf_open_folder (src_mapi_folder, conn, &src_obj_folder, cancellable, &err)) {
- if (cmf_open_folder (des_mapi_folder, conn, &des_obj_folder, cancellable, &err)) {
- copymoved = e_mapi_connection_copymove_items (conn, &src_obj_folder, &des_obj_folder, !delete_originals, src_msg_ids, cancellable, &err);
- e_mapi_connection_close_folder (conn, &des_obj_folder, cancellable, &err);
+ if (cmf_open_folder (src_mapi_folder, conn, &src_obj_folder, cancellable, &mapi_error)) {
+ if (cmf_open_folder (des_mapi_folder, conn, &des_obj_folder, cancellable, &mapi_error)) {
+ copymoved = e_mapi_connection_copymove_items (conn, &src_obj_folder, &des_obj_folder, !delete_originals, src_msg_ids, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &des_obj_folder, cancellable, &mapi_error);
}
- e_mapi_connection_close_folder (conn, &src_obj_folder, cancellable, &err);
+ e_mapi_connection_close_folder (conn, &src_obj_folder, cancellable, &mapi_error);
}
if (!copymoved) {
- if (!e_mapi_utils_propagate_cancelled_error (err, error))
+ if (!e_mapi_utils_propagate_cancelled_error (mapi_error, error))
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
- "%s", err ? err->message : _("Unknown error"));
- g_clear_error (&err);
+ "%s", mapi_error ? mapi_error->message : _("Unknown error"));
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+ g_clear_error (&mapi_error);
success = FALSE;
} else if (delete_originals) {
changes = camel_folder_change_info_new ();
@@ -1852,7 +1875,7 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
}
- g_clear_error (&err);
+ g_clear_error (&mapi_error);
g_slist_foreach (src_msg_ids, (GFunc) g_free, NULL);
g_slist_free (src_msg_ids);
@@ -1872,6 +1895,7 @@ mapi_folder_get_quota_info_sync (CamelFolder *folder,
CamelMapiStore *mapi_store;
CamelFolderQuotaInfo *quota_info = NULL;
EMapiConnection *conn;
+ GError *mapi_error = NULL;
uint64_t current_size = -1, receive_quota = -1, send_quota = -1;
g_return_val_if_fail (folder != NULL, NULL);
@@ -1884,11 +1908,11 @@ mapi_folder_get_quota_info_sync (CamelFolder *folder,
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (mapi_store)))
return NULL;
- conn = camel_mapi_store_get_connection (mapi_store);
+ conn = camel_mapi_store_get_connection (mapi_store, cancellable, error);
if (conn && e_mapi_connection_get_store_quotas (
conn, NULL,
¤t_size, &receive_quota, &send_quota,
- cancellable, error)) {
+ cancellable, &mapi_error)) {
if (current_size != -1) {
if (receive_quota != -1) {
quota_info = camel_folder_quota_info_new (_("Receive quota"), current_size, receive_quota);
@@ -1906,9 +1930,19 @@ mapi_folder_get_quota_info_sync (CamelFolder *folder,
}
}
- if (!quota_info)
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- _("No quota information available"));
+ if (!quota_info) {
+ if (mapi_error) {
+ if (!e_mapi_utils_propagate_cancelled_error (mapi_error, error))
+ g_set_error (
+ error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ "%s", mapi_error ? mapi_error->message : _("Unknown error"));
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+ g_clear_error (&mapi_error);
+ } else {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("No quota information available"));
+ }
+ }
return quota_info;
}
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 9a8eed5..14e7a45 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -119,6 +119,7 @@ cms_open_folder (CamelMapiStore *mapi_store,
{
CamelStoreInfo *si;
CamelMapiStoreInfo *msi;
+ GError *mapi_error = NULL;
gboolean res;
g_return_val_if_fail (mapi_store != NULL, FALSE);
@@ -136,11 +137,16 @@ cms_open_folder (CamelMapiStore *mapi_store,
msi = (CamelMapiStoreInfo *) si;
if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
- res = e_mapi_connection_open_foreign_folder (conn, msi->foreign_username, fid, obj_folder, cancellable, perror);
+ res = e_mapi_connection_open_foreign_folder (conn, msi->foreign_username, fid, obj_folder, cancellable, &mapi_error);
else if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
- res = e_mapi_connection_open_public_folder (conn, fid, obj_folder, cancellable, perror);
+ res = e_mapi_connection_open_public_folder (conn, fid, obj_folder, cancellable, &mapi_error);
else
- res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+ res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, &mapi_error);
+
+ if (mapi_error) {
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+ g_propagate_error (perror, mapi_error);
+ }
return res;
}
@@ -155,6 +161,7 @@ cms_peek_folder_store (CamelMapiStore *mapi_store,
{
CamelStoreInfo *si;
CamelMapiStoreInfo *msi;
+ GError *mapi_error = NULL;
gboolean res;
g_return_val_if_fail (mapi_store != NULL, FALSE);
@@ -172,11 +179,16 @@ cms_peek_folder_store (CamelMapiStore *mapi_store,
msi = (CamelMapiStoreInfo *) si;
if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
- res = e_mapi_connection_peek_store (conn, FALSE, msi->foreign_username, obj_store, cancellable, perror);
+ res = e_mapi_connection_peek_store (conn, FALSE, msi->foreign_username, obj_store, cancellable, &mapi_error);
else if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
- res = e_mapi_connection_peek_store (conn, TRUE, NULL, obj_store, cancellable, perror);
+ res = e_mapi_connection_peek_store (conn, TRUE, NULL, obj_store, cancellable, &mapi_error);
else
- res = e_mapi_connection_peek_store (conn, FALSE, NULL, obj_store, cancellable, perror);
+ res = e_mapi_connection_peek_store (conn, FALSE, NULL, obj_store, cancellable, &mapi_error);
+
+ if (mapi_error) {
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
+ g_propagate_error (perror, mapi_error);
+ }
return res;
}
@@ -463,7 +475,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
GHashTable *old_cache_folders;
GError *err = NULL;
- if (!camel_mapi_store_connected (store, NULL)) {
+ if (!camel_mapi_store_connected (store, cancellable, NULL)) {
g_set_error_literal (
error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
_("Folder list is not available in offline mode"));
@@ -472,9 +484,10 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
status = e_mapi_connection_get_folders_list (priv->conn, &folder_list, camel_mapi_update_operation_progress_cb, NULL, cancellable, &err);
if (!status) {
+ camel_mapi_store_maybe_disconnect (store, err);
+
g_warning ("Could not get folder list (%s)\n", err ? err->message : "Unknown error");
- if (err)
- g_error_free (err);
+ g_clear_error (&err);
return TRUE;
}
@@ -507,8 +520,8 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
if (!status)
g_warning ("Could not get Public folder list (%s)\n", err ? err->message : "Unknown error");
- if (err)
- g_error_free (err);
+ camel_mapi_store_maybe_disconnect (store, err);
+ g_clear_error (&err);
}
temp_list = folder_list;
@@ -1323,6 +1336,7 @@ mapi_store_create_folder_sync (CamelStore *store,
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Cannot create folder '%s': %s"), folder_name, mapi_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, mapi_error);
g_error_free (mapi_error);
} else {
g_set_error (
@@ -1358,7 +1372,7 @@ mapi_store_delete_folder_sync (CamelStore *store,
return FALSE;
}
- if (!camel_mapi_store_connected ((CamelMapiStore *)store, &local_error)) {
+ if (!camel_mapi_store_connected ((CamelMapiStore *)store, cancellable, &local_error)) {
if (local_error != NULL) {
g_propagate_error (error, local_error);
return FALSE;
@@ -1396,7 +1410,7 @@ mapi_store_delete_folder_sync (CamelStore *store,
status = FALSE;
if (status) {
- success = mapi_forget_folder (mapi_store, folder_name, error);
+ success = mapi_forget_folder (mapi_store, folder_name, &local_error);
if (success) {
/* remove from name_cache at the end, because the folder_id is from there */
@@ -1404,6 +1418,11 @@ mapi_store_delete_folder_sync (CamelStore *store,
g_hash_table_remove (priv->id_hash, folder_id);
g_hash_table_remove (priv->name_hash, folder_name);
}
+
+ if (local_error) {
+ camel_mapi_store_maybe_disconnect (mapi_store, local_error);
+ g_propagate_error (error, local_error);
+ }
} else {
success = FALSE;
@@ -1414,6 +1433,7 @@ mapi_store_delete_folder_sync (CamelStore *store,
_("Cannot remove folder '%s': %s"),
folder_name, local_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, local_error);
g_error_free (local_error);
} else {
g_set_error (
@@ -1454,7 +1474,7 @@ mapi_store_rename_folder_sync (CamelStore *store,
service = CAMEL_SERVICE (store);
user_cache_dir = camel_service_get_user_cache_dir (service);
- if (!camel_mapi_store_connected ((CamelMapiStore *)store, &local_error)) {
+ if (!camel_mapi_store_connected ((CamelMapiStore *)store, cancellable, &local_error)) {
if (local_error != NULL) {
g_propagate_error (error, local_error);
return FALSE;
@@ -1537,6 +1557,7 @@ mapi_store_rename_folder_sync (CamelStore *store,
The last '%s' is a detailed error message. */
_("Cannot rename MAPI folder '%s' to '%s': %s"),
old_name, new_name, local_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, local_error);
g_error_free (local_error);
} else {
g_set_error (
@@ -1615,6 +1636,7 @@ mapi_store_rename_folder_sync (CamelStore *store,
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Cannot rename MAPI folder '%s' to '%s': %s"),
old_name, new_name, local_error->message);
+ camel_mapi_store_maybe_disconnect (mapi_store, local_error);
g_error_free (local_error);
} else {
g_set_error (
@@ -2095,7 +2117,6 @@ mapi_connect_sync (CamelService *service,
if (!camel_session_authenticate_sync (session, service, empd.krb_sso ? "MAPIKRB" : NULL, cancellable, error)) {
camel_operation_pop_message (cancellable);
- camel_service_disconnect_sync (service, TRUE, cancellable, NULL);
g_free (name);
return FALSE;
}
@@ -2157,6 +2178,8 @@ mapi_disconnect_sync (CamelService *service,
e_mapi_connection_disable_notifications (store->priv->conn, NULL, cancellable, error);
/* Close the mapi subsystem */
+ e_mapi_connection_disconnect (store->priv->conn, clean, clean ? cancellable : NULL, error);
+
g_object_unref (store->priv->conn);
store->priv->conn = NULL;
}
@@ -2640,10 +2663,29 @@ mapi_build_folder_info (CamelMapiStore *mapi_store, const gchar *parent_name, co
}
gboolean
-camel_mapi_store_connected (CamelMapiStore *store, GError **error)
+camel_mapi_store_connected (CamelMapiStore *mapi_store,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return camel_offline_store_get_online (CAMEL_OFFLINE_STORE (mapi_store))
+ && camel_service_connect_sync (CAMEL_SERVICE (mapi_store), cancellable, error);
+}
+
+void
+camel_mapi_store_maybe_disconnect (CamelMapiStore *mapi_store,
+ const GError *mapi_error)
{
- return camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))
- && camel_service_connect_sync ((CamelService *)store, NULL, error);
+ g_return_if_fail (CAMEL_IS_MAPI_STORE (mapi_store));
+
+ /* no error or already disconnected */
+ if (!mapi_error || !mapi_store->priv->conn)
+ return;
+
+ if (g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR) ||
+ g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED))
+ camel_service_disconnect_sync (CAMEL_SERVICE (mapi_store),
+ !g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR),
+ NULL, NULL);
}
static void
@@ -2775,12 +2817,17 @@ camel_mapi_store_folder_lookup (CamelMapiStore *mapi_store, const gchar *folder_
}
EMapiConnection *
-camel_mapi_store_get_connection (CamelMapiStore *mapi_store)
+camel_mapi_store_get_connection (CamelMapiStore *mapi_store,
+ GCancellable *cancellable,
+ GError **error)
{
g_return_val_if_fail (mapi_store != NULL, NULL);
g_return_val_if_fail (CAMEL_IS_MAPI_STORE (mapi_store), NULL);
g_return_val_if_fail (mapi_store->priv != NULL, NULL);
+ if (!mapi_store->priv->conn)
+ camel_mapi_store_connected (mapi_store, cancellable, error);
+
return mapi_store->priv->conn;
}
diff --git a/src/camel/camel-mapi-store.h b/src/camel/camel-mapi-store.h
index 5eee816..0720c8e 100644
--- a/src/camel/camel-mapi-store.h
+++ b/src/camel/camel-mapi-store.h
@@ -71,14 +71,20 @@ struct _CamelMapiStoreClass {
};
GType camel_mapi_store_get_type (void);
-gboolean camel_mapi_store_connected (CamelMapiStore *mapi_store, GError **error);
+gboolean camel_mapi_store_connected (CamelMapiStore *mapi_store,
+ GCancellable *cancellable,
+ GError **error);
+void camel_mapi_store_maybe_disconnect (CamelMapiStore *mapi_store,
+ const GError *mapi_error);
const gchar * camel_mapi_store_folder_id_lookup (CamelMapiStore *mapi_store, const gchar *folder_name);
const gchar * camel_mapi_store_folder_lookup (CamelMapiStore *mapi_store, const gchar *folder_id);
const gchar * camel_mapi_store_system_folder_fid (CamelMapiStore *mapi_store, guint folder_type);
const gchar * mapi_folders_hash_table_name_lookup (CamelMapiStore *store, const gchar *fid, gboolean use_cache);
-EMapiConnection * camel_mapi_store_get_connection (CamelMapiStore *mapi_store);
+EMapiConnection * camel_mapi_store_get_connection (CamelMapiStore *mapi_store,
+ GCancellable *cancellable,
+ GError **error);
void camel_mapi_store_ensure_unique_path (CamelMapiStore *mapi_store, gchar **ppath);
void camel_mapi_store_announce_subscribed_folder (CamelMapiStore *mapi_store, const gchar *path);
diff --git a/src/configuration/e-mapi-subscribe-foreign-folder.c b/src/configuration/e-mapi-subscribe-foreign-folder.c
index ff77e62..bd53893 100644
--- a/src/configuration/e-mapi-subscribe-foreign-folder.c
+++ b/src/configuration/e-mapi-subscribe-foreign-folder.c
@@ -292,7 +292,7 @@ check_foreign_folder_thread (GObject *with_object,
if (g_cancellable_set_error_if_cancelled (cancellable, perror))
return;
- conn = camel_mapi_store_get_connection (CAMEL_MAPI_STORE (with_object));
+ conn = camel_mapi_store_get_connection (CAMEL_MAPI_STORE (with_object), cancellable, perror);
if (!conn || !e_mapi_connection_connected (conn)) {
make_mapi_error (perror, "EMapiConnection", MAPI_E_NOT_INITIALIZED);
return;
@@ -538,7 +538,7 @@ pick_gal_user_clicked_cb (GtkButton *button,
text = g_strstrip (g_strdup (gtk_entry_get_text (entry)));
if (e_mapi_search_gal_user_modal (GTK_WINDOW (dialog),
- camel_mapi_store_get_connection (mapi_store),
+ camel_mapi_store_get_connection (mapi_store, NULL, NULL),
text,
&searched_type,
&display_name,
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index c83954b..9143077 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -283,7 +283,8 @@ release_foreign_stores_cb (gpointer pusername, gpointer pmsg_store, gpointer use
/* should have session_lock locked already, when calling this function */
static void
-disconnect (EMapiConnectionPrivate *priv)
+disconnect (EMapiConnectionPrivate *priv,
+ gboolean clean)
{
g_return_if_fail (priv != NULL);
@@ -302,9 +303,11 @@ disconnect (EMapiConnectionPrivate *priv)
g_hash_table_foreach (priv->foreign_stores, release_foreign_stores_cb, NULL);
g_hash_table_remove_all (priv->foreign_stores);
- Logoff (&priv->msg_store);
- /* it's released by the Logoff() call
- mapi_object_release (&priv->msg_store); */
+ if (clean) {
+ Logoff (&priv->msg_store);
+ /* it's released by the Logoff() call
+ mapi_object_release (&priv->msg_store); */
+ }
if (priv->named_ids)
g_hash_table_remove_all (priv->named_ids);
@@ -410,7 +413,7 @@ e_mapi_connection_finalize (GObject *object)
if (priv) {
LOCK_VOID (NULL, NULL);
- disconnect (priv);
+ disconnect (priv, TRUE);
g_free (priv->profile);
priv->profile = NULL;
@@ -643,18 +646,19 @@ e_mapi_connection_new (ESourceRegistry *registry,
}
gboolean
-e_mapi_connection_close (EMapiConnection *conn)
+e_mapi_connection_disconnect (EMapiConnection *conn,
+ gboolean clean,
+ GCancellable *cancellable,
+ GError **perror)
{
gboolean res = FALSE;
- /* to have this used in the below macros */
- GError **perror = NULL;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- LOCK (NULL, NULL, FALSE);
+ LOCK (cancellable, perror, FALSE);
res = priv->session != NULL;
- disconnect (priv);
+ disconnect (priv, clean);
UNLOCK ();
@@ -675,7 +679,7 @@ e_mapi_connection_reconnect (EMapiConnection *conn,
LOCK (cancellable, perror, FALSE);
if (priv->session)
- e_mapi_connection_close (conn);
+ e_mapi_connection_disconnect (conn, FALSE, cancellable, perror);
priv->session = mapi_profile_load (priv->registry, priv->mapi_ctx, priv->profile, password ? password->str : NULL, cancellable, perror);
if (!priv->session) {
@@ -6682,6 +6686,33 @@ try_create_profile (ESourceRegistry *registry,
return data.has_profile;
}
+static gboolean
+can_reach_mapi_server (const gchar *server_address,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ GNetworkMonitor *network_monitor;
+ GSocketConnectable *connectable;
+ GError *local_error = NULL;
+ gboolean reachable;
+
+ g_return_val_if_fail (server_address != NULL, FALSE);
+
+ network_monitor = g_network_monitor_get_default ();
+ connectable = g_network_address_new (server_address, 135);
+ reachable = g_network_monitor_can_reach (network_monitor, connectable, cancellable, &local_error);
+ g_object_unref (connectable);
+
+ if (!reachable) {
+ if (local_error)
+ g_propagate_error (perror, local_error);
+ else
+ g_set_error (perror, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE, _("Server '%s' cannot be reached"), server_address);
+ }
+
+ return reachable;
+}
+
static struct mapi_session *
mapi_profile_load (ESourceRegistry *registry,
struct mapi_context *mapi_ctx,
@@ -6692,6 +6723,7 @@ mapi_profile_load (ESourceRegistry *registry,
{
enum MAPISTATUS ms = MAPI_E_SUCCESS;
struct mapi_session *session = NULL;
+ struct mapi_profile profile = { 0 };
guint32 debug_log_level = 0;
e_return_val_mapi_error_if_fail (mapi_ctx != NULL, MAPI_E_INVALID_PARAMETER, NULL);
@@ -6709,6 +6741,15 @@ mapi_profile_load (ESourceRegistry *registry,
SetMAPIDebugLevel (mapi_ctx, debug_log_level);
}
+ if (MAPI_E_SUCCESS == OpenProfile (mapi_ctx, &profile, profname, NULL)) {
+ if (!can_reach_mapi_server (profile.server, cancellable, perror)) {
+ ShutDown (&profile);
+ goto cleanup;
+ }
+
+ ShutDown (&profile);
+ }
+
e_mapi_debug_print("Loading profile %s ", profname);
ms = MapiLogonEx (mapi_ctx, &session, profname, password);
@@ -6772,6 +6813,9 @@ mapi_profile_create (struct mapi_context *mapi_ctx,
e_return_val_mapi_error_if_fail (COMPLETE_PROFILEDATA (empd) && (empd->krb_sso || (empd->password && empd->password->len)),
MAPI_E_INVALID_PARAMETER, FALSE);
+ if (!can_reach_mapi_server (empd->server, cancellable, perror))
+ return FALSE;
+
if (use_locking) {
if (!e_mapi_utils_global_lock (cancellable, perror))
return FALSE;
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 6f63868..0a49273 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -241,7 +241,10 @@ gboolean e_mapi_connection_reconnect (EMapiConnection *conn,
const GString *password,
GCancellable *cancellable,
GError **perror);
-gboolean e_mapi_connection_close (EMapiConnection *conn);
+gboolean e_mapi_connection_disconnect (EMapiConnection *conn,
+ gboolean clean,
+ GCancellable *cancellable,
+ GError **perror);
gboolean e_mapi_connection_connected (EMapiConnection *conn);
gboolean e_mapi_connection_test_foreign_folder (EMapiConnection *conn,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]