[evolution-data-server/gnome-3-8] Bug #704740 - WebDAV - Do not store ETag into REV attribute
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-3-8] Bug #704740 - WebDAV - Do not store ETag into REV attribute
- Date: Thu, 25 Jul 2013 06:08:18 +0000 (UTC)
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]