On 26/04/14 12:57, Andreas Henriksson wrote: > Hello Daniel! > > On Sat, Apr 26, 2014 at 12:34:08PM +0200, Daniel Pocock wrote: >> Hi Andreas, >> >> Thanks for the feedback about this >> >> Can you just clarify about backporting the fix - do you mean backporting >> the whole version from testing to wheezy-backports or just copying the >> individual patch into a rebuild of the version currently in stable? > > I think backporting only the fix should (hopefully) be easier (unless > the commit is entangled with lots of other changes happening between > 3.4 and 3.8). >
The patch did not apply cleanly on 3.4.4 I've manually adapted the patch and tested it with 3.4.4-3 from Debian Please find the revised version enclosed - I believe this is good for the 3.4 branch in upstream evolution-data-server too: git checkout gnome-3-4 git cherry-pick 198bceaf20df82764c36ad6787bd828705dc31c5 - merge conflict appears, resolve it by using my patch and then commit > Maybe both can be done, but jordi says that backporting the entire > evolution "is not fun". It is probably more than what I need anyway - I'm happy to keep running 3.4.x as long as this issue is fixed > Personally, I'm not going to work on either though... someone else > will need to take on the task that motivates them. > > So we can go either way or both ways. > > If you're interested in working on evolution, please contact jordi. I'm very busy with my own packages, but I need this to work, so I've adapted the patch for 3.4.4 and I hope you will push it out as part of an update to stable. Just put it in the debian/patches directory and update debian/patches/series Personally, I'm more interested in things like making click-to-dial work (see my sipdialer package for example) - it almost works from icedove now and I would appreciate feedback about how to get it working from Evolution too. Regards, Daniel
--- ../e-book-backend-webdav.c.orig 2014-04-27 20:46:28.031504658 +0200 +++ ./addressbook/backends/webdav/e-book-backend-webdav.c 2014-04-27 21:28:44.912193111 +0200 @@ -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> @@ -62,6 +62,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" G_DEFINE_TYPE (EBookBackendWebdav, e_book_backend_webdav, E_TYPE_BOOK_BACKEND) @@ -109,6 +112,47 @@ } 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); @@ -178,9 +222,9 @@ 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); @@ -225,7 +269,7 @@ * 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, "If-None-Match", "*"); @@ -234,10 +278,14 @@ } else { 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, request, strlen (request)); @@ -247,8 +295,8 @@ redir_uri = soup_message_headers_get (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 */ @@ -310,7 +358,7 @@ 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,}; @@ -336,8 +384,8 @@ 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); if (status != 201 && status != 204) { @@ -358,7 +406,8 @@ 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; @@ -374,6 +423,8 @@ return; } contact = new_contact; + } else { + g_free (stored_etag); } e_book_backend_cache_add_contact (priv->cache, contact); @@ -464,7 +515,7 @@ 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; @@ -519,7 +570,7 @@ uid = e_contact_get_const (contact, E_CONTACT_UID); 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] == '/')) { @@ -528,9 +579,13 @@ g_warning("Server didn't return etag for modified address resource"); new_contact = download_contact (webdav, uid); if (new_contact != NULL) { + g_object_unref (contact); contact = new_contact; } } + + g_free (etag); + e_book_backend_cache_add_contact (priv->cache, contact); modified_contacts.data = contact; @@ -845,6 +900,14 @@ 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; + + 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); if (txt && *txt) { gint len = strlen (txt); @@ -861,12 +924,21 @@ const gchar *my_ctag; 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_free (txt); + + if (old_version) { + 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); + } } xmlXPathFreeContext (xpctx); @@ -964,7 +1036,7 @@ 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)) @@ -996,9 +1068,12 @@ etag = (const gchar *) element->etag; contact = e_book_backend_cache_get_contact (priv->cache, complete_uri); + + 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); if (contact != NULL) { e_book_backend_cache_remove_contact (priv->cache, complete_uri); @@ -1011,6 +1086,7 @@ } g_free (complete_uri); + g_free (stored_etag); } /* free element list */