[evolution-data-server] I#37 - [IMAPx] Disable request of BODYSTRUCTURE when its response is broken



commit ccfa3eed49202cccbc9f94f91badd5c425655b9e
Author: Milan Crha <mcrha redhat com>
Date:   Tue Oct 2 15:11:51 2018 +0200

    I#37 - [IMAPx] Disable request of BODYSTRUCTURE when its response is broken
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/37

 src/camel/providers/imapx/camel-imapx-server.c | 55 ++++++++++++++++++++------
 src/camel/providers/imapx/camel-imapx-store.c  | 22 +++++++++++
 src/camel/providers/imapx/camel-imapx-store.h  |  5 +++
 3 files changed, 70 insertions(+), 12 deletions(-)
---
diff --git a/src/camel/providers/imapx/camel-imapx-server.c b/src/camel/providers/imapx/camel-imapx-server.c
index acf67ca3d..f006a9681 100644
--- a/src/camel/providers/imapx/camel-imapx-server.c
+++ b/src/camel/providers/imapx/camel-imapx-server.c
@@ -3383,20 +3383,27 @@ preauthed:
 
                g_mutex_unlock (&is->priv->stream_lock);
 
+               #define NOTIFY_CMD(x) "NOTIFY SET " \
+                       "(selected " \
+                       "(MessageNew (UID RFC822.SIZE RFC822.HEADER FLAGS" x ")" \
+                       " MessageExpunge" \
+                       " FlagChange)) " \
+                       "(personal " \
+                       "(MessageNew" \
+                       " MessageExpunge" \
+                       " MailboxName" \
+                       " SubscriptionChange))"
+
                /* XXX The list of FETCH attributes is negotiable. */
-               ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_NOTIFY, "NOTIFY SET "
-                       "(selected "
-                       "(MessageNew (UID RFC822.SIZE RFC822.HEADER BODYSTRUCTURE FLAGS)"
-                       " MessageExpunge"
-                       " FlagChange)) "
-                       "(personal "
-                       "(MessageNew"
-                       " MessageExpunge"
-                       " MailboxName"
-                       " SubscriptionChange))");
+               if (camel_imapx_store_get_bodystructure_enabled (store))
+                       ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_NOTIFY, NOTIFY_CMD (" 
BODYSTRUCTURE"));
+               else
+                       ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_NOTIFY, NOTIFY_CMD (""));
                camel_imapx_server_process_command_sync (is, ic, _("Failed to issue NOTIFY"), cancellable, 
&local_error);
                camel_imapx_command_unref (ic);
 
+               #undef NOTIFY_CMD
+
                if (local_error != NULL) {
                        g_propagate_error (error, local_error);
                        goto exception;
@@ -5290,13 +5297,37 @@ imapx_server_fetch_changes (CamelIMAPXServer *is,
                                ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_REFRESH_INFO, "UID FETCH ");
 
                        if (imapx_uidset_add (&uidset, ic, uid) == 1 || (!link->next && ic && 
imapx_uidset_done (&uidset, ic))) {
-                               camel_imapx_command_add (ic, " (RFC822.SIZE RFC822.HEADER BODYSTRUCTURE 
FLAGS)");
+                               GError *local_error = NULL;
+                               gboolean bodystructure_enabled;
+                               CamelIMAPXStore *imapx_store;
+
+                               imapx_store = camel_imapx_server_ref_store (is);
+                               bodystructure_enabled = imapx_store && 
camel_imapx_store_get_bodystructure_enabled (imapx_store);
 
-                               success = camel_imapx_server_process_command_sync (is, ic, _("Error fetching 
message info"), cancellable, error);
+                               if (bodystructure_enabled)
+                                       camel_imapx_command_add (ic, " (RFC822.SIZE RFC822.HEADER 
BODYSTRUCTURE FLAGS)");
+                               else
+                                       camel_imapx_command_add (ic, " (RFC822.SIZE RFC822.HEADER FLAGS)");
+
+                               success = camel_imapx_server_process_command_sync (is, ic, _("Error fetching 
message info"), cancellable, &local_error);
 
                                camel_imapx_command_unref (ic);
                                ic = NULL;
 
+                               /* Some servers can return broken BODYSTRUCTURE response, thus disable it
+                                  even when it's not 100% sure the BODYSTRUCTURE response was the broken 
one. */
+                               if (bodystructure_enabled && !success &&
+                                   g_error_matches (local_error, CAMEL_IMAPX_ERROR, 
CAMEL_IMAPX_ERROR_SERVER_RESPONSE_MALFORMED)) {
+                                       camel_imapx_store_set_bodystructure_enabled (imapx_store, FALSE);
+                                       local_error->domain = CAMEL_IMAPX_SERVER_ERROR;
+                                       local_error->code = CAMEL_IMAPX_SERVER_ERROR_TRY_RECONNECT;
+                               }
+
+                               g_clear_object (&imapx_store);
+
+                               if (local_error)
+                                       g_propagate_error (error, local_error);
+
                                if (!success)
                                        break;
 
diff --git a/src/camel/providers/imapx/camel-imapx-store.c b/src/camel/providers/imapx/camel-imapx-store.c
index e8302e3e6..b4669dd17 100644
--- a/src/camel/providers/imapx/camel-imapx-store.c
+++ b/src/camel/providers/imapx/camel-imapx-store.c
@@ -81,6 +81,8 @@ struct _CamelIMAPXStorePrivate {
 
        GHashTable *mailboxes;
        GMutex mailboxes_lock;
+
+       gboolean bodystructure_enabled;
 };
 
 enum {
@@ -2532,6 +2534,24 @@ camel_imapx_store_is_gmail_server (CamelIMAPXStore *imapx_store)
        return is_gmail;
 }
 
+gboolean
+camel_imapx_store_get_bodystructure_enabled (CamelIMAPXStore *store)
+{
+       g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (store), FALSE);
+
+       return store->priv->bodystructure_enabled;
+}
+
+void
+camel_imapx_store_set_bodystructure_enabled (CamelIMAPXStore *store,
+                                            gboolean enabled)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_STORE (store));
+
+       if ((!store->priv->bodystructure_enabled) != (!enabled))
+               store->priv->bodystructure_enabled = enabled;
+}
+
 static gchar *
 imapx_find_folder_for_initial_setup (CamelFolderInfo *root,
                                     const gchar *path)
@@ -3324,6 +3344,8 @@ camel_imapx_store_init (CamelIMAPXStore *store)
 
        g_mutex_init (&store->priv->settings_lock);
 
+       store->priv->bodystructure_enabled = TRUE;
+
        imapx_utils_init ();
 
        g_signal_connect (
diff --git a/src/camel/providers/imapx/camel-imapx-store.h b/src/camel/providers/imapx/camel-imapx-store.h
index ce1eade1b..bc697e040 100644
--- a/src/camel/providers/imapx/camel-imapx-store.h
+++ b/src/camel/providers/imapx/camel-imapx-store.h
@@ -80,6 +80,11 @@ struct _CamelIMAPXStoreClass {
 GType          camel_imapx_store_get_type      (void);
 gboolean       camel_imapx_store_is_gmail_server
                                                (CamelIMAPXStore *store);
+gboolean       camel_imapx_store_get_bodystructure_enabled
+                                               (CamelIMAPXStore *store);
+void           camel_imapx_store_set_bodystructure_enabled
+                                               (CamelIMAPXStore *store,
+                                                gboolean enabled);
 CamelIMAPXConnManager *
                camel_imapx_store_get_conn_manager
                                                (CamelIMAPXStore *store);


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