[evolution-data-server/gnome-3-8] Bug #704740 - WebDAV - Do not store ETag into REV attribute



commit 749de2b157cff0abd64ddbddc1c5a9770ea3d51f
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jul 25 08:07:54 2013 +0200

    Bug #704740 - WebDAV - Do not store ETag into REV attribute

 .../backends/webdav/e-book-backend-webdav.c        |  116 +++++++++++++++++---
 1 files changed, 99 insertions(+), 17 deletions(-)
---
diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c 
b/addressbook/backends/webdav/e-book-backend-webdav.c
index 4079623..670d495 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -22,7 +22,7 @@
 /*
  * Implementation notes:
  *   We use the DavResource URIs as UID in the evolution contact
- *   ETags are saved in the E_CONTACT_REV field so we know which cached contacts
+ *   ETags are saved in the WEBDAV_CONTACT_ETAG field so we know which cached contacts
  *   are outdated.
  */
 #include <config.h>
@@ -51,6 +51,9 @@
 #define USERAGENT             "Evolution/" VERSION
 #define WEBDAV_CLOSURE_NAME   "EBookBackendWebdav.BookView::closure"
 #define WEBDAV_CTAG_KEY "WEBDAV_CTAG"
+#define WEBDAV_CACHE_VERSION_KEY "WEBDAV_CACHE_VERSION"
+#define WEBDAV_CACHE_VERSION "1"
+#define WEBDAV_CONTACT_ETAG "X-EVOLUTION-WEBDAV-ETAG"
 
 /* Forward Declarations */
 static void    e_book_backend_webdav_source_authenticator_init
@@ -110,6 +113,47 @@ webdav_debug_setup (SoupSession *session)
 }
 
 static void
+webdav_contact_set_etag (EContact *contact,
+                        const gchar *etag)
+{
+       EVCardAttribute *attr;
+
+       g_return_if_fail (E_IS_CONTACT (contact));
+
+       attr = e_vcard_get_attribute (E_VCARD (contact), WEBDAV_CONTACT_ETAG);
+
+       if (attr) {
+               e_vcard_attribute_remove_values (attr);
+               if (etag) {
+                       e_vcard_attribute_add_value (attr, etag);
+               } else {
+                       e_vcard_remove_attribute (E_VCARD (contact), attr);
+               }
+       } else if (etag) {
+               e_vcard_append_attribute_with_value (
+                       E_VCARD (contact),
+                       e_vcard_attribute_new (NULL, WEBDAV_CONTACT_ETAG),
+                       etag);
+       }
+}
+
+static gchar *
+webdav_contact_get_etag (EContact *contact)
+{
+       EVCardAttribute *attr;
+       GList *v = NULL;
+
+       g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
+
+       attr = e_vcard_get_attribute (E_VCARD (contact), WEBDAV_CONTACT_ETAG);
+
+       if (attr)
+               v = e_vcard_attribute_get_values (attr);
+
+       return ((v && v->data) ? g_strstrip (g_strdup (v->data)) : NULL);
+}
+
+static void
 closure_destroy (WebdavBackendSearchClosure *closure)
 {
        e_flag_free (closure->running);
@@ -225,9 +269,9 @@ download_contact (EBookBackendWebdav *webdav,
                return NULL;
        }
 
-       /* the etag is remembered in the revision field */
+       /* the etag is remembered in the WEBDAV_CONTACT_ETAG field */
        if (etag != NULL) {
-               e_contact_set (contact, E_CONTACT_REV, (gconstpointer) etag);
+               webdav_contact_set_etag (contact, etag);
        }
 
        g_object_unref (message);
@@ -274,7 +318,7 @@ upload_contact (EBookBackendWebdav *webdav,
         * we can leave it out */
        if (!avoid_ifmatch) {
                /* only override if etag is still the same on the server */
-               etag = e_contact_get (contact, E_CONTACT_REV);
+               etag = webdav_contact_get_etag (contact);
                if (etag == NULL) {
                        soup_message_headers_append (
                                message->request_headers,
@@ -285,10 +329,14 @@ upload_contact (EBookBackendWebdav *webdav,
                        soup_message_headers_append (
                                message->request_headers,
                                "If-Match", etag);
-                       g_free (etag);
                }
+
+               g_free (etag);
        }
 
+       /* Remove the stored ETag, before saving to the server */
+       webdav_contact_set_etag (contact, NULL);
+
        request = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
        soup_message_set_request (
                message, "text/vcard", SOUP_MEMORY_TEMPORARY,
@@ -299,8 +347,8 @@ upload_contact (EBookBackendWebdav *webdav,
 
        redir_uri = soup_message_headers_get_list (message->response_headers, "Location");
 
-       /* set UID and REV fields */
-       e_contact_set (contact, E_CONTACT_REV, (gconstpointer) new_etag);
+       /* set UID and WEBDAV_CONTACT_ETAG fields */
+       webdav_contact_set_etag (contact, new_etag);
        if (redir_uri && *redir_uri) {
                if (!strstr (redir_uri, "://")) {
                        /* it's a relative URI */
@@ -376,7 +424,7 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
        EContact                  *contact;
        gchar                     *uid;
        guint                      status;
-       gchar                     *status_reason = NULL;
+       gchar                     *status_reason = NULL, *stored_etag;
        const gchar               *vcard = (const gchar *) vcards->data;
        GSList                     added_contacts = {NULL,};
 
@@ -404,8 +452,8 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
 
        contact = e_contact_new_from_vcard_with_uid (vcard, uid);
 
-       /* kill revision field (might have been set by some other backend) */
-       e_contact_set (contact, E_CONTACT_REV, NULL);
+       /* kill WEBDAV_CONTACT_ETAG field (might have been set by some other backend) */
+       webdav_contact_set_etag (contact, NULL);
 
        status = upload_contact (webdav, contact, &status_reason, cancellable);
        if (status != 201 && status != 204) {
@@ -429,7 +477,8 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
        g_free (status_reason);
 
        /* PUT request didn't return an etag? try downloading to get one */
-       if (e_contact_get_const (contact, E_CONTACT_REV) == NULL) {
+       stored_etag = webdav_contact_get_etag (contact);
+       if (!stored_etag) {
                const gchar *new_uid;
                EContact *new_contact;
 
@@ -446,6 +495,8 @@ e_book_backend_webdav_create_contacts (EBookBackend *backend,
                        return;
                }
                contact = new_contact;
+       } else {
+               g_free (stored_etag);
        }
 
        g_mutex_lock (&priv->cache_lock);
@@ -545,7 +596,7 @@ e_book_backend_webdav_modify_contacts (EBookBackend *backend,
        EContact                  *contact;
        GSList                     modified_contacts = {NULL,};
        const gchar                *uid;
-       const gchar                *etag;
+       gchar                *etag;
        guint status;
        gchar *status_reason = NULL;
        const gchar *vcard = vcards->data;
@@ -607,7 +658,7 @@ e_book_backend_webdav_modify_contacts (EBookBackend *backend,
        g_mutex_lock (&priv->cache_lock);
        e_book_backend_cache_remove_contact (priv->cache, uid);
 
-       etag = e_contact_get_const (contact, E_CONTACT_REV);
+       etag = webdav_contact_get_etag (contact);
 
        /* PUT request didn't return an etag? try downloading to get one */
        if (etag == NULL || (etag[0] == 'W' && etag[1] == '/')) {
@@ -616,9 +667,13 @@ e_book_backend_webdav_modify_contacts (EBookBackend *backend,
                g_warning ("Server didn't return etag for modified address resource");
                new_contact = download_contact (webdav, uid, cancellable);
                if (new_contact != NULL) {
+                       g_object_unref (contact);
                        contact = new_contact;
                }
        }
+
+       g_free (etag);
+
        e_book_backend_cache_add_contact (priv->cache, contact);
        g_mutex_unlock (&priv->cache_lock);
 
@@ -938,6 +993,16 @@ check_addressbook_changed (EBookBackendWebdav *webdav,
 
                        if (xp_object_get_status (xpath_eval (xpctx, GETCTAG_XPATH_STATUS)) == 200) {
                                gchar *txt = xp_object_get_string (xpath_eval (xpctx, GETCTAG_XPATH_VALUE));
+                               const gchar *stored_version;
+                               gboolean old_version;
+
+                               g_mutex_lock (&priv->cache_lock);
+                               stored_version = e_file_cache_get_object (E_FILE_CACHE (priv->cache), 
WEBDAV_CACHE_VERSION_KEY);
+
+                               /* The ETag was moved from REV to its own attribute, thus
+                                  if the cache version is too low, update it. */
+                               old_version = !stored_version || atoi (stored_version) < atoi 
(WEBDAV_CACHE_VERSION);
+                               g_mutex_unlock (&priv->cache_lock);
 
                                if (txt && *txt) {
                                        gint len = strlen (txt);
@@ -955,13 +1020,27 @@ check_addressbook_changed (EBookBackendWebdav *webdav,
 
                                                g_mutex_lock (&priv->cache_lock);
                                                my_ctag = e_file_cache_get_object (E_FILE_CACHE 
(priv->cache), WEBDAV_CTAG_KEY);
-                                               res = !my_ctag || !g_str_equal (my_ctag, *new_ctag);
+                                               res = old_version || !my_ctag || !g_str_equal (my_ctag, 
*new_ctag);
+
                                                priv->supports_getctag = TRUE;
                                                g_mutex_unlock (&priv->cache_lock);
                                        }
                                }
 
                                g_free (txt);
+
+                               if (old_version) {
+                                       g_mutex_lock (&priv->cache_lock);
+
+                                       if (!e_file_cache_replace_object (E_FILE_CACHE (priv->cache),
+                                               WEBDAV_CACHE_VERSION_KEY,
+                                               WEBDAV_CACHE_VERSION))
+                                               e_file_cache_add_object (E_FILE_CACHE (priv->cache),
+                                                       WEBDAV_CACHE_VERSION_KEY,
+                                                       WEBDAV_CACHE_VERSION);
+
+                                       g_mutex_unlock (&priv->cache_lock);
+                               }
                        }
 
                        xmlXPathFreeContext (xpctx);
@@ -1071,7 +1150,7 @@ download_contacts (EBookBackendWebdav *webdav,
                const gchar  *uri;
                const gchar *etag;
                EContact    *contact;
-               gchar *complete_uri;
+               gchar *complete_uri, *stored_etag;
 
                /* stop downloading if search was aborted */
                if (running != NULL && !e_flag_is_set (running))
@@ -1106,9 +1185,11 @@ download_contacts (EBookBackendWebdav *webdav,
                contact = e_book_backend_cache_get_contact (priv->cache, complete_uri);
                g_mutex_unlock (&priv->cache_lock);
 
+               stored_etag = webdav_contact_get_etag (contact);
+
                /* download contact if it is not cached or its ETag changed */
-               if (contact == NULL || etag == NULL ||
-                   strcmp (e_contact_get_const (contact, E_CONTACT_REV), etag) != 0) {
+               if (contact == NULL || etag == NULL || !stored_etag ||
+                   strcmp (stored_etag, etag) != 0) {
                        contact = download_contact (webdav, complete_uri, cancellable);
                        if (contact != NULL) {
                                g_mutex_lock (&priv->cache_lock);
@@ -1121,6 +1202,7 @@ download_contacts (EBookBackendWebdav *webdav,
                }
 
                g_free (complete_uri);
+               g_free (stored_etag);
        }
 
        /* free element list */


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