[evolution-data-server] Bug 707116 - IMAPX: Normalize descendants of INBOX



commit 9a2e4a657b9ff694f2992e0da31311bdb1b6d356
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Sep 9 11:19:28 2013 -0400

    Bug 707116 - IMAPX: Normalize descendants of INBOX
    
    camel_imapx_parse_mailbox() was correctly normalizing INBOX itself,
    but leaving descendants of INBOX untouched.
    
    If the IMAP server names INBOX as, let's say, "Inbox" and INBOX has
    children, then we would end up parsing LIST responses like so:
    
        LIST "/" "Inbox"        -> "INBOX"
        LIST "/" "Inbox/Child"  -> "Inbox/Child"
    
    This screwed up parent/child relationships in the CamelFolderInfo,
    causing "INBOX" and "Inbox" to be represented as separator folders.

 camel/camel-imapx-list-response.c   |    8 +++++---
 camel/camel-imapx-server.c          |   12 +++++++++++-
 camel/camel-imapx-status-response.c |    6 ++++--
 camel/camel-imapx-status-response.h |    1 +
 camel/camel-imapx-store-summary.c   |    2 ++
 camel/camel-imapx-store.c           |   21 +--------------------
 camel/camel-imapx-utils.c           |   31 ++++++++++++++++++-------------
 camel/camel-imapx-utils.h           |    1 +
 8 files changed, 43 insertions(+), 39 deletions(-)
---
diff --git a/camel/camel-imapx-list-response.c b/camel/camel-imapx-list-response.c
index 0cca013..27ec415 100644
--- a/camel/camel-imapx-list-response.c
+++ b/camel/camel-imapx-list-response.c
@@ -196,7 +196,9 @@ imapx_list_response_parse_oldname (CamelIMAPXStream *stream,
                goto fail;
        }
 
-       mailbox_name = camel_imapx_parse_mailbox (stream, cancellable, error);
+       /* The separator character should be known by now. */
+       mailbox_name = camel_imapx_parse_mailbox (
+               stream, response->priv->separator, cancellable, error);
        if (mailbox_name == NULL)
                goto fail;
 
@@ -364,8 +366,8 @@ camel_imapx_list_response_new (CamelIMAPXStream *stream,
 
        /* Parse mailbox name. */
 
-       response->priv->mailbox_name =
-               camel_imapx_parse_mailbox (stream, cancellable, error);
+       response->priv->mailbox_name = camel_imapx_parse_mailbox (
+               stream, response->priv->separator, cancellable, error);
        if (response->priv->mailbox_name == NULL)
                goto fail;
 
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index d8049a1..07b00d5 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -351,6 +351,12 @@ struct _CamelIMAPXServerPrivate {
 
        GHashTable *known_alerts;
        GMutex known_alerts_lock;
+
+       /* INBOX separator character, so we can correctly normalize
+        * INBOX and descendants of INBOX in IMAP responses that do
+        * not include a separator character with the mailbox name,
+        * such as STATUS.  Used for camel_imapx_parse_mailbox(). */
+       gchar inbox_separator;
 };
 
 enum {
@@ -2021,6 +2027,10 @@ imapx_untagged_list (CamelIMAPXServer *is,
        mailbox_name = camel_imapx_list_response_get_mailbox_name (response);
        separator = camel_imapx_list_response_get_separator (response);
 
+       /* Record the INBOX separator character once we know it. */
+       if (camel_imapx_mailbox_is_inbox (mailbox_name))
+               is->priv->inbox_separator = separator;
+
        job = imapx_match_active_job (is, IMAPX_JOB_LIST, mailbox_name);
 
        data = camel_imapx_job_get_data (job);
@@ -2224,7 +2234,7 @@ imapx_untagged_status (CamelIMAPXServer *is,
        g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
 
        response = camel_imapx_status_response_new (
-               stream, cancellable, error);
+               stream, is->priv->inbox_separator, cancellable, error);
        if (response == NULL)
                return FALSE;
 
diff --git a/camel/camel-imapx-status-response.c b/camel/camel-imapx-status-response.c
index d560ca0..367e802 100644
--- a/camel/camel-imapx-status-response.c
+++ b/camel/camel-imapx-status-response.c
@@ -84,6 +84,7 @@ camel_imapx_status_response_init (CamelIMAPXStatusResponse *response)
 /**
  * camel_imapx_status_response_new:
  * @stream: a #CamelIMAPXStream
+ * @inbox_separator: the separator character for INBOX
  * @cancellable: a #GCancellable
  * @error: return location for a #GError, or %NULL
  *
@@ -97,6 +98,7 @@ camel_imapx_status_response_init (CamelIMAPXStatusResponse *response)
  **/
 CamelIMAPXStatusResponse *
 camel_imapx_status_response_new (CamelIMAPXStream *stream,
+                                 gchar inbox_separator,
                                  GCancellable *cancellable,
                                  GError **error)
 {
@@ -111,8 +113,8 @@ camel_imapx_status_response_new (CamelIMAPXStream *stream,
 
        /* Parse mailbox name. */
 
-       response->priv->mailbox_name =
-               camel_imapx_parse_mailbox (stream, cancellable, error);
+       response->priv->mailbox_name = camel_imapx_parse_mailbox (
+               stream, inbox_separator, cancellable, error);
        if (response->priv->mailbox_name == NULL)
                goto fail;
 
diff --git a/camel/camel-imapx-status-response.h b/camel/camel-imapx-status-response.h
index 3a346d0..d69635b 100644
--- a/camel/camel-imapx-status-response.h
+++ b/camel/camel-imapx-status-response.h
@@ -73,6 +73,7 @@ GType         camel_imapx_status_response_get_type
 CamelIMAPXStatusResponse *
                camel_imapx_status_response_new
                                        (CamelIMAPXStream *stream,
+                                        gchar inbox_separator,
                                         GCancellable *cancellable,
                                         GError **error);
 const gchar *  camel_imapx_status_response_get_mailbox_name
diff --git a/camel/camel-imapx-store-summary.c b/camel/camel-imapx-store-summary.c
index 15f2301..e02811b 100644
--- a/camel/camel-imapx-store-summary.c
+++ b/camel/camel-imapx-store-summary.c
@@ -276,6 +276,8 @@ imapx_store_summary_store_info_load (CamelStoreSummary *s,
                return NULL;
        }
 
+       camel_imapx_normalize_mailbox (mailbox_name, *separator);
+
        /* NB: this is done again for compatability */
        if (camel_imapx_mailbox_is_inbox (mailbox_name))
                si->flags |=
diff --git a/camel/camel-imapx-store.c b/camel/camel-imapx-store.c
index e65f85d..8828fa0 100644
--- a/camel/camel-imapx-store.c
+++ b/camel/camel-imapx-store.c
@@ -652,38 +652,19 @@ get_folder_offline (CamelStore *store,
        CamelService *service;
        CamelStoreSummary *store_summary;
        const gchar *user_cache_dir;
-       gboolean is_inbox;
 
        service = CAMEL_SERVICE (store);
        user_cache_dir = camel_service_get_user_cache_dir (service);
 
        store_summary = CAMEL_STORE_SUMMARY (imapx_store->summary);
        si = camel_store_summary_path (store_summary, folder_name);
-       is_inbox = camel_imapx_mailbox_is_inbox (folder_name);
-
-       if (si == NULL && is_inbox) {
-               /* XXX This function takes a mailbox name but we're passing
-                *     a folder path.  Are they always identical for INBOX? */
-               si = (CamelStoreInfo *) camel_imapx_store_summary_mailbox (
-                       imapx_store->summary, folder_name);
-       }
 
        if (si != NULL) {
                gchar *base_dir;
                gchar *folder_dir;
 
-               /* Note: Although the INBOX is defined to be case-insensitive
-                *       in the IMAP RFC, it is still up to the server how to
-                *       acutally name it in a LIST response. Since we stored
-                *       the name as the server provided it us in the summary
-                *       we take that name to look up the folder.
-                *
-                *       But for the on-disk cache we always capitalize the
-                *       Inbox no matter what the server provided.
-                */
                base_dir = g_build_filename (user_cache_dir, "folders", NULL);
-               folder_dir = imapx_path_to_physical (
-                       base_dir, is_inbox ? "INBOX" : folder_name);
+               folder_dir = imapx_path_to_physical (base_dir, folder_name);
                new_folder = camel_imapx_folder_new (
                        store, folder_dir, folder_name, error);
                g_free (folder_dir);
diff --git a/camel/camel-imapx-utils.c b/camel/camel-imapx-utils.c
index a443385..be0167e 100644
--- a/camel/camel-imapx-utils.c
+++ b/camel/camel-imapx-utils.c
@@ -2517,6 +2517,7 @@ exit:
 /**
  * camel_imapx_parse_mailbox:
  * @is: a #CamelIMAPXStream
+ * @separator: the mailbox separator character
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -2524,34 +2525,38 @@ exit:
  * described in <ulink url="http://tools.ietf.org/html/rfc3501#section-5.1";>
  * RFC 3501 section 5.1</ulink>.
  *
+ * The @separator character is used to identify INBOX and convert its name
+ * to all caps, both for INBOX itself and its descendants.  If a separator
+ * character was provided in the server response being parsed (such as for
+ * LIST or LSUB), pass that for @separator.  If no separator character was
+ * provided in the server response being parsed (such as for STATUS), then
+ * pass the separator character specifically for INBOX.
+ *
+ * If an error occurs, the function sets @error and returns %NULL.
+ *
+ * Returns: a newly-allocated mailbox name, or %NULL
+ *
  * Since: 3.10
  **/
 gchar *
 camel_imapx_parse_mailbox (CamelIMAPXStream *is,
+                           gchar separator,
                            GCancellable *cancellable,
                            GError **error)
 {
        guchar *token;
-       gchar *mailbox;
+       gchar *mailbox_name;
 
        g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (is), NULL);
 
-       /* mailbox ::= "INBOX" / astring
-        *             INBOX is case-insensitive.  All case variants of
-        *             INBOX (e.g., "iNbOx") MUST be interpreted as INBOX
-        *             not as an astring.  An astring which consists of
-        *             the case-insensitive sequence "I" "N" "B" "O" "X"
-        *             is considered to be INBOX and not an astring. */
-
        if (!camel_imapx_stream_astring (is, &token, cancellable, error))
                return NULL;
 
-       if (g_ascii_strcasecmp ((gchar *) token, "INBOX") == 0)
-               mailbox = g_strdup ("INBOX");
-       else
-               mailbox = camel_utf7_utf8 ((gchar *) token);
+       mailbox_name = camel_utf7_utf8 ((gchar *) token);
+
+       camel_imapx_normalize_mailbox (mailbox_name, separator);
 
-       return mailbox;
+       return mailbox_name;
 }
 
 /**
diff --git a/camel/camel-imapx-utils.h b/camel/camel-imapx-utils.h
index 70c8ab2..9777898 100644
--- a/camel/camel-imapx-utils.h
+++ b/camel/camel-imapx-utils.h
@@ -319,6 +319,7 @@ gboolean    camel_imapx_command_add_qresync_parameter
 /* ********************************************************************** */
 
 gchar *                camel_imapx_parse_mailbox       (struct _CamelIMAPXStream *is,
+                                                gchar separator,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           camel_imapx_normalize_mailbox   (gchar *mailbox_name,


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