diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2009-07-19 16:48:31 +0100 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2009-07-19 16:48:31 +0100 |
commit | d2872bbe103b43e87d8469513df4f4ec55ea71ef (patch) | |
tree | 4a079e71912c418b94c1973fa689a5004ce1b3fc | |
parent | c0d41063dc52788d6597554280a7b0142a880dbf (diff) | |
download | evolution-data-server-libgdata-port.tar.gz |
Cleaned up error handling and fixed some attribute bugs in the Google Contacts backendlibgdata-port
-rw-r--r-- | addressbook/backends/google/e-book-backend-google.c | 68 | ||||
-rw-r--r-- | addressbook/backends/google/google-book.c | 175 | ||||
-rw-r--r-- | addressbook/backends/google/google-book.h | 15 | ||||
-rw-r--r-- | addressbook/backends/google/util.c | 8 |
4 files changed, 111 insertions, 155 deletions
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c index fc0ff618c..3a2b962f1 100644 --- a/addressbook/backends/google/e-book-backend-google.c +++ b/addressbook/backends/google/e-book-backend-google.c @@ -1,6 +1,7 @@ /* e-book-backend-google.c - Google contact backendy. * * Copyright (C) 2008 Joergen Scheibengruber + * Copyright (C) 2009 Philip Withnall * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the @@ -27,6 +28,7 @@ #include <libedata-book/e-data-book.h> #include <libedata-book/e-data-book-view.h> #include <libedata-book/e-book-backend-sexp.h> +#include <gdata/gdata-service.h> #include "e-book-backend-google.h" #include "google-book.h" @@ -48,7 +50,7 @@ struct _EBookBackendGooglePrivate gboolean __e_book_backend_google_debug__; -static EBookBackendSyncStatus e_book_backend_status_from_google_book_error (GoogleBookError error_code); +static EBookBackendSyncStatus e_book_backend_status_from_google_book_error (GError *error); static EBookBackendSyncStatus e_book_backend_google_create_contact (EBookBackendSync *backend, @@ -76,7 +78,7 @@ e_book_backend_google_create_contact (EBookBackendSync *backend, google_book_add_contact (priv->book, contact, out_contact, &error); g_object_unref (contact); if (error) { - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Creating contact failed: %s", error->message); g_clear_error (&error); *out_contact = NULL; @@ -114,7 +116,7 @@ e_book_backend_google_remove_contacts (EBookBackendSync *backend, google_book_remove_contact (priv->book, uid, &error); if (error) { /* Only last error will be reported */ - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Deleting contact %s failed: %s", uid, error->message); g_clear_error (&error); } else { @@ -154,7 +156,7 @@ e_book_backend_google_modify_contact (EBookBackendSync *backend, google_book_update_contact (priv->book, contact, out_contact, &error); g_object_unref (contact); if (error) { - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Modifying contact failed: %s", error->message); g_clear_error (&error); *out_contact = NULL; @@ -181,7 +183,7 @@ e_book_backend_google_get_contact (EBookBackendSync *backend, contact = google_book_get_contact (priv->book, uid, &error); if (error) { - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Getting contact with uid %s failed: %s", uid, error->message); g_clear_error (&error); return status; @@ -212,7 +214,7 @@ e_book_backend_google_get_contact_list (EBookBackendSync *backend, all_contacts = google_book_get_all_contacts (priv->book, &error); if (error) { - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Getting all contacts failed: %s", error->message); g_clear_error (&error); return status; @@ -283,9 +285,8 @@ on_google_book_sequence_complete (GoogleBook *book, GError *error, gpointer user priv = GET_PRIVATE (user_data); if (error) { - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Book-view query failed: %s", error->message); - status = e_book_backend_status_from_google_book_error (error->code); g_clear_error (&error); } for (iter = priv->bookviews; iter; iter = iter->next) { @@ -378,9 +379,8 @@ e_book_backend_google_authenticate_user (EBookBackendSync *backend, google_book_connect_to_google (priv->book, password, &error); if (error) { - status = e_book_backend_status_from_google_book_error (error->code); + status = e_book_backend_status_from_google_book_error (error); __debug__ ("Authentication failed: %s", error->message); - status = e_book_backend_status_from_google_book_error (error->code); g_clear_error (&error); } else { e_book_backend_notify_writable (E_BOOK_BACKEND (backend), TRUE); @@ -686,8 +686,54 @@ e_book_backend_google_new (void) } static EBookBackendSyncStatus -e_book_backend_status_from_google_book_error (GoogleBookError error_code) +e_book_backend_status_from_google_book_error (GError *error) { + if (!error) + return GNOME_Evolution_Addressbook_Success; + + if (error->domain == GDATA_AUTHENTICATION_ERROR) { + /* Authentication errors */ + switch (error->code) { + case GDATA_AUTHENTICATION_ERROR_BAD_AUTHENTICATION: + return GNOME_Evolution_Addressbook_AuthenticationFailed; + case GDATA_AUTHENTICATION_ERROR_NOT_VERIFIED: + case GDATA_AUTHENTICATION_ERROR_TERMS_NOT_AGREED: + case GDATA_AUTHENTICATION_ERROR_CAPTCHA_REQUIRED: + case GDATA_AUTHENTICATION_ERROR_ACCOUNT_DELETED: + case GDATA_AUTHENTICATION_ERROR_ACCOUNT_DISABLED: + return GNOME_Evolution_Addressbook_PermissionDenied; + case GDATA_AUTHENTICATION_ERROR_SERVICE_DISABLED: + return GNOME_Evolution_Addressbook_RepositoryOffline; + default: + return GNOME_Evolution_Addressbook_OtherError; + } + } else if (error->domain == GDATA_SERVICE_ERROR) { + /* General service errors */ + switch (error->code) { + case GDATA_SERVICE_ERROR_UNAVAILABLE: + return GNOME_Evolution_Addressbook_RepositoryOffline; + case GDATA_SERVICE_ERROR_PROTOCOL_ERROR: + return GNOME_Evolution_Addressbook_InvalidQuery; + case GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED: + return GNOME_Evolution_Addressbook_ContactIdAlreadyExists; + case GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED: + return GNOME_Evolution_Addressbook_AuthenticationRequired; + case GDATA_SERVICE_ERROR_NOT_FOUND: + return GNOME_Evolution_Addressbook_ContactNotFound; + case GDATA_SERVICE_ERROR_CONFLICT: + return GNOME_Evolution_Addressbook_ContactIdAlreadyExists; + case GDATA_SERVICE_ERROR_FORBIDDEN: + return GNOME_Evolution_Addressbook_QueryRefused; + case GDATA_SERVICE_ERROR_WITH_QUERY: + case GDATA_SERVICE_ERROR_WITH_INSERTION: + case GDATA_SERVICE_ERROR_WITH_UPDATE: + case GDATA_SERVICE_ERROR_WITH_DELETION: + return GNOME_Evolution_Addressbook_InvalidQuery; + default: + return GNOME_Evolution_Addressbook_OtherError; + } + } + return GNOME_Evolution_Addressbook_OtherError; } diff --git a/addressbook/backends/google/google-book.c b/addressbook/backends/google/google-book.c index 1dd5160c6..b23f0383a 100644 --- a/addressbook/backends/google/google-book.c +++ b/addressbook/backends/google/google-book.c @@ -26,6 +26,7 @@ #include <libedataserver/e-proxy.h> #include <gdata/gdata-service.h> #include <gdata/services/contacts/gdata-contacts-service.h> +#include <gdata/services/contacts/gdata-contacts-query.h> #include <gdata/services/contacts/gdata-contacts-contact.h> #include "util.h" @@ -101,11 +102,6 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book, GError **error); static void -google_book_error_from_soup_error (GError *soup_error, - GError **error, - const char *message); - -static void google_book_cache_init (GoogleBook *book, gboolean on_disk) { GoogleBookPrivate *priv = GET_PRIVATE (book); @@ -284,9 +280,8 @@ google_book_cache_get_last_update (GoogleBook *book) case ON_DISK_CACHE: return e_book_backend_cache_get_time (priv->cache.on_disk); case IN_MEMORY_CACHE: - if (priv->cache.in_memory.contacts) { + if (priv->cache.in_memory.contacts) return g_time_val_to_iso8601 (&priv->cache.in_memory.last_updated); - } break; case NO_CACHE: default: @@ -762,7 +757,6 @@ google_book_connect_to_google (GoogleBook *book, const char *password, GError ** { GoogleBookPrivate *priv; GDataService *service; - GError *soup_error = NULL; __debug__ (G_STRFUNC); g_return_val_if_fail (IS_GOOGLE_BOOK (book), FALSE); @@ -782,11 +776,7 @@ google_book_connect_to_google (GoogleBook *book, const char *password, GError ** proxy_settings_changed (priv->proxy, priv); priv->service = NULL; - gdata_service_authenticate (service, priv->username, password, NULL, &soup_error); - - if (soup_error) { - google_book_error_from_soup_error (soup_error, error, - "Connecting to Google failed"); + if (!gdata_service_authenticate (service, priv->username, password, NULL, error)) { priv->service = NULL; g_object_unref (service); g_object_unref (priv->proxy); @@ -839,7 +829,6 @@ google_book_add_contact (GoogleBook *book, GoogleBookPrivate *priv; GDataEntry *entry, *new_entry; gchar *xml; - GError *soup_error = NULL; *out_contact = NULL; @@ -856,16 +845,12 @@ google_book_add_contact (GoogleBook *book, g_free (xml); new_entry = GDATA_ENTRY (gdata_contacts_service_insert_contact (GDATA_CONTACTS_SERVICE (priv->service), GDATA_CONTACTS_CONTACT (entry), - NULL, &soup_error)); + NULL, error)); g_object_unref (entry); - if (soup_error) { - google_book_error_from_soup_error (soup_error, error, - "Adding entry failed"); + if (!new_entry) return FALSE; - } *out_contact = google_book_cache_add_contact (book, new_entry); - g_object_unref (new_entry); return TRUE; @@ -879,7 +864,6 @@ google_book_update_contact (GoogleBook *book, { GoogleBookPrivate *priv; GDataEntry *entry, *new_entry; - GError *soup_error = NULL; EContact *cached_contact; gchar *xml; const char *uid; @@ -899,9 +883,9 @@ google_book_update_contact (GoogleBook *book, cached_contact = google_book_cache_get_contact (book, uid, &entry); if (NULL == cached_contact) { g_set_error (error, - GOOGLE_BOOK_ERROR, - GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND, - "Contact with uid %s not found in cache.", uid); + GDATA_SERVICE_ERROR, + GDATA_SERVICE_ERROR_NOT_FOUND, + "Contact with uid %s not found in cache.", uid); return FALSE; } g_object_unref (cached_contact); @@ -912,14 +896,11 @@ google_book_update_contact (GoogleBook *book, g_free (xml); new_entry = GDATA_ENTRY (gdata_contacts_service_update_contact (GDATA_CONTACTS_SERVICE (priv->service), GDATA_CONTACTS_CONTACT (entry), - NULL, &soup_error)); + NULL, error)); g_object_unref (entry); - if (soup_error) { - google_book_error_from_soup_error (soup_error, error, - "Updating entry failed"); + if (!new_entry) return FALSE; - } xml = NULL; if (new_entry) @@ -928,7 +909,6 @@ google_book_update_contact (GoogleBook *book, g_free (xml); *out_contact = google_book_cache_add_contact (book, new_entry); - g_object_unref (new_entry); return TRUE; @@ -939,8 +919,8 @@ google_book_remove_contact (GoogleBook *book, const char *uid, GError **error) { GoogleBookPrivate *priv; GDataEntry *entry = NULL; - GError *soup_error = NULL; EContact *cached_contact; + gboolean success; __debug__ (G_STRFUNC); g_return_val_if_fail (IS_GOOGLE_BOOK (book), FALSE); @@ -951,25 +931,16 @@ google_book_remove_contact (GoogleBook *book, const char *uid, GError **error) cached_contact = google_book_cache_get_contact (book, uid, &entry); if (NULL == cached_contact) { - g_set_error (error, - GOOGLE_BOOK_ERROR, - GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND, - "Contact with uid %s not found in cache.", uid); + g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NOT_FOUND, "Contact with uid %s not found in cache.", uid); return FALSE; } google_book_cache_remove_contact (book, uid); - gdata_service_delete_entry (GDATA_SERVICE (priv->service), entry, NULL, &soup_error); + success = gdata_service_delete_entry (GDATA_SERVICE (priv->service), entry, NULL, error); g_object_unref (entry); g_object_unref (cached_contact); - if (soup_error) { - google_book_error_from_soup_error (soup_error, error, - "Removing entry failed"); - return FALSE; - } - - return TRUE; + return success; } static void @@ -1038,10 +1009,13 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book, GError **error) { GoogleBookPrivate *priv; - int start_index = 1; + GDataFeed *feed; + GDataQuery *query; char *last_updated; GError *our_error = NULL; gboolean rv = TRUE; + GTimeVal current_time; + int results; priv = GET_PRIVATE (book); @@ -1052,29 +1026,24 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book, google_book_cache_freeze (book); - while (start_index > 0) { - GDataFeed *feed; + /* Build our query */ + query = GDATA_QUERY (gdata_contacts_query_new_with_limits (NULL, 1, chunk_size)); + if (last_updated) { + GTimeVal updated; + + g_assert (g_time_val_from_iso8601 (last_updated, &updated) == TRUE); + gdata_query_set_updated_min (query, &updated); + gdata_contacts_query_set_show_deleted (GDATA_CONTACTS_QUERY (query), TRUE); + } + + /* Get the paginated results */ + do { GList *entries; - GString *uri; - int results; - GError *soup_error = NULL; - - /* TODO: Convert to GDataQuery */ - uri = g_string_new (priv->base_uri); - g_string_append_printf (uri, "?max-results=%d&start-index=%d", - chunk_size, start_index); - if (last_updated) { - g_string_append_printf (uri, "&updated-min=%s&showdeleted=true", - last_updated); - } - __debug__ ("URI is '%s'", uri->str); - feed = gdata_service_query (priv->service, uri->str, NULL, GDATA_TYPE_CONTACTS_CONTACT, NULL, NULL, NULL, &soup_error); - g_string_free (uri, TRUE); + /* Run the query */ + feed = gdata_contacts_service_query_contacts (GDATA_CONTACTS_SERVICE (priv->service), query, NULL, NULL, NULL, &our_error); - if (soup_error) { - google_book_error_from_soup_error (soup_error, &our_error, - "Downloading feed failed"); + if (our_error) { google_book_emit_sequence_complete (book, our_error); g_propagate_error (error, our_error); @@ -1086,24 +1055,22 @@ google_book_get_new_contacts_in_chunks (GoogleBook *book, results = entries ? g_list_length (entries) : 0; __debug__ ("Feed has %d entries", results); - if (last_updated) { + /* Process the entries from this page */ + if (last_updated) g_list_foreach (entries, process_subsequent_entry, book); - } else { + else g_list_foreach (entries, process_initial_entry, book); - } + g_object_unref (feed); - if (results == chunk_size) { - start_index += results; - } else { - GTimeVal current_time; + /* Move to the next page */ + gdata_query_next_page (query); + } while (results == chunk_size); + + /* Finish updating the cache */ + g_get_current_time (¤t_time); + google_book_cache_set_last_update (book, ¤t_time); + google_book_emit_sequence_complete (book, NULL); - start_index = -1; - g_get_current_time (¤t_time); - google_book_cache_set_last_update (book, ¤t_time); - google_book_emit_sequence_complete (book, NULL); - } - g_object_unref (feed); - } out: g_free (last_updated); google_book_cache_thaw (book); @@ -1136,12 +1103,8 @@ google_book_get_contact (GoogleBook *book, } return contact; } else { - if (NULL == *error) { - g_set_error (error, - GOOGLE_BOOK_ERROR, - GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND, - "Contact with uid %s not found in cache.", uid); - } + if (NULL == *error) + g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_NOT_FOUND, "Contact with uid %s not found in cache.", uid); } return NULL; } @@ -1235,47 +1198,3 @@ google_book_set_live_mode (GoogleBook *book, gboolean live_mode) google_book_cache_refresh_if_needed (book, NULL); } } - -static void -google_book_error_from_soup_error (GError *soup_error, - GError **error, - const char *message) -{ - GoogleBookError code; - - g_assert (soup_error); - - /* TODO: Convert this to deal with libgdata codes */ - if (soup_error->code < 100) { - code = GOOGLE_BOOK_ERROR_NETWORK_ERROR; - } else - if (soup_error->code == 200) { - code = GOOGLE_BOOK_ERROR_NONE; - } else - if (soup_error->code == 400) { - code = GOOGLE_BOOK_ERROR_INVALID_CONTACT; - } else - if (soup_error->code == 401) { - code = GOOGLE_BOOK_ERROR_AUTH_REQUIRED; - } else - if (soup_error->code == 403) { - code = GOOGLE_BOOK_ERROR_AUTH_FAILED; - } else - if (soup_error->code == 404) { - code = GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND; - } else - if (soup_error->code == 409) { - code = GOOGLE_BOOK_ERROR_CONFLICT; - } else { - code = GOOGLE_BOOK_ERROR_HTTP_ERROR; - } - g_set_error (error, - GOOGLE_BOOK_ERROR, - GOOGLE_BOOK_ERROR_HTTP_ERROR, - "%s due to '%s' (HTTP code %d)", - message ? message : "Action failed", - soup_error->message, - soup_error->code); - g_clear_error (&soup_error); -} - diff --git a/addressbook/backends/google/google-book.h b/addressbook/backends/google/google-book.h index 0d390ae32..6accbb410 100644 --- a/addressbook/backends/google/google-book.h +++ b/addressbook/backends/google/google-book.h @@ -45,7 +45,6 @@ G_BEGIN_DECLS typedef struct _GoogleBook GoogleBook; typedef struct _GoogleBookClass GoogleBookClass; -typedef enum _GoogleBookError GoogleBookError; struct _GoogleBook { @@ -64,20 +63,6 @@ struct _GoogleBookClass void (*auth_required) (void); }; -enum _GoogleBookError -{ - GOOGLE_BOOK_ERROR_NONE, - GOOGLE_BOOK_ERROR_CONTACT_NOT_FOUND, - GOOGLE_BOOK_ERROR_INVALID_CONTACT, - GOOGLE_BOOK_ERROR_CONFLICT, - GOOGLE_BOOK_ERROR_AUTH_FAILED, - GOOGLE_BOOK_ERROR_AUTH_REQUIRED, - GOOGLE_BOOK_ERROR_NETWORK_ERROR, - GOOGLE_BOOK_ERROR_HTTP_ERROR -}; - -#define GOOGLE_BOOK_ERROR (g_quark_from_string ("GoogleBookError")) - typedef void (*GoogleBookContactRetrievedCallback) (EContact *contact, gpointer user_data); GType google_book_get_type (void); diff --git a/addressbook/backends/google/util.c b/addressbook/backends/google/util.c index bddd440b3..7696f995c 100644 --- a/addressbook/backends/google/util.c +++ b/addressbook/backends/google/util.c @@ -101,6 +101,12 @@ _gdata_entry_update_from_e_contact (GDataEntry *entry, e_contact_name_free (name); } + /* Clear out all the old attributes */ + gdata_contacts_contact_remove_all_email_addresses (GDATA_CONTACTS_CONTACT (entry)); + gdata_contacts_contact_remove_all_phone_numbers (GDATA_CONTACTS_CONTACT (entry)); + gdata_contacts_contact_remove_all_postal_addresses (GDATA_CONTACTS_CONTACT (entry)); + gdata_contacts_contact_remove_all_im_addresses (GDATA_CONTACTS_CONTACT (entry)); + /* We walk them in reverse order, so we can find * the correct primaries */ iter = g_list_last (attributes); @@ -158,7 +164,7 @@ _gdata_entry_update_from_e_contact (GDataEntry *entry, (attr, &have_im_primary); if (im) gdata_contacts_contact_add_im_address (GDATA_CONTACTS_CONTACT (entry), im); - } else if (e_vcard_attribute_is_single_valued (attr)) { + } else if (e_vcard_attribute_is_single_valued (attr) && g_ascii_strcasecmp (name, "X-MOZILLA-HTML") != 0) { gchar *value; /* Add the attribute as an extended property */ |