summaryrefslogtreecommitdiff
path: root/addressbook
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2015-02-02 14:44:05 +0100
committerMilan Crha <mcrha@redhat.com>2015-02-02 14:44:05 +0100
commit884fb8d872787d9c9e8132d4cfca47f275d9da3e (patch)
tree13875694627f5539660d776a520cff230632acfd /addressbook
parenta83cc09fc20edb2401f1e08d9d7b9f2eca408641 (diff)
downloadevolution-data-server-884fb8d872787d9c9e8132d4cfca47f275d9da3e.tar.gz
Move authentication of backends back to the client
Since this change the client is responsible to provide credentials to use to authenticate backends (through ESource-s, to be more precise), unless the credentials are already saved.
Diffstat (limited to 'addressbook')
-rw-r--r--addressbook/backends/file/e-book-backend-file.c3
-rw-r--r--addressbook/backends/google/e-book-backend-google.c163
-rw-r--r--addressbook/backends/ldap/e-book-backend-ldap.c120
-rw-r--r--addressbook/backends/webdav/e-book-backend-webdav.c180
-rw-r--r--addressbook/libebook/e-book-client.c101
-rw-r--r--addressbook/libebook/e-book-client.h4
-rw-r--r--addressbook/libedata-book/e-book-backend.c19
-rw-r--r--addressbook/libedata-book/e-data-book.c67
8 files changed, 453 insertions, 204 deletions
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 8f8f085a6..b0dbe79b9 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -1140,6 +1140,9 @@ book_backend_file_open_sync (EBookBackend *backend,
source = e_backend_get_source (E_BACKEND (backend));
+ /* Local source is always connected. */
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+
g_type_ensure (E_TYPE_SOURCE_REVISION_GUARDS);
guards = e_source_get_extension (source, E_SOURCE_EXTENSION_REVISION_GUARDS);
diff --git a/addressbook/backends/google/e-book-backend-google.c b/addressbook/backends/google/e-book-backend-google.c
index 19d1ac784..7f4d29bc0 100644
--- a/addressbook/backends/google/e-book-backend-google.c
+++ b/addressbook/backends/google/e-book-backend-google.c
@@ -44,17 +44,7 @@
#define GDATA_CHECK_VERSION(major,minor,micro) 0
#endif
-/* Forward Declarations */
-static void e_book_backend_google_source_authenticator_init
- (ESourceAuthenticatorInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (
- EBookBackendGoogle,
- e_book_backend_google,
- E_TYPE_BOOK_BACKEND,
- G_IMPLEMENT_INTERFACE (
- E_TYPE_SOURCE_AUTHENTICATOR,
- e_book_backend_google_source_authenticator_init))
+G_DEFINE_TYPE (EBookBackendGoogle, e_book_backend_google, E_TYPE_BOOK_BACKEND)
struct _EBookBackendGooglePrivate {
EBookBackendCache *cache;
@@ -1209,9 +1199,9 @@ fallback_set_proxy_uri (EBookBackend *backend)
#endif
static gboolean
-request_authorization (EBookBackend *backend,
- GCancellable *cancellable,
- GError **error)
+connect_without_password (EBookBackend *backend,
+ GCancellable *cancellable,
+ GError **error)
{
EBookBackendGooglePrivate *priv;
@@ -1277,10 +1267,7 @@ request_authorization (EBookBackend *backend,
return TRUE;
/* Otherwise it's up to us to obtain a login secret. */
- return e_backend_authenticate_sync (
- E_BACKEND (backend),
- E_SOURCE_AUTHENTICATOR (backend),
- cancellable, error);
+ return FALSE;
}
typedef enum {
@@ -1421,6 +1408,7 @@ e_book_backend_google_notify_online_cb (EBookBackend *backend,
GParamSpec *pspec)
{
EBookBackendGooglePrivate *priv;
+ ESource *source;
gboolean is_online;
priv = E_BOOK_BACKEND_GOOGLE_GET_PRIVATE (backend);
@@ -1428,11 +1416,22 @@ e_book_backend_google_notify_online_cb (EBookBackend *backend,
g_debug (G_STRFUNC);
is_online = e_backend_get_online (E_BACKEND (backend));
+ source = e_backend_get_source (E_BACKEND (backend));
if (is_online && e_book_backend_is_opened (backend)) {
- request_authorization (backend, NULL, NULL);
- if (backend_is_authorized (backend))
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
+
+ if (connect_without_password (backend, NULL, NULL)) {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+
e_book_backend_set_writable (backend, TRUE);
+ cache_refresh_if_needed (backend);
+ } else {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+
+ e_backend_schedule_credentials_required (E_BACKEND (backend), E_SOURCE_CREDENTIALS_REASON_REQUIRED,
+ NULL, 0, NULL, NULL, G_STRFUNC);
+ }
} else {
/* Going offline, so cancel all running operations */
google_cancel_all_operations (backend);
@@ -1443,6 +1442,9 @@ e_book_backend_google_notify_online_cb (EBookBackend *backend,
* as writeable again once the user's authenticated again. */
e_book_backend_set_writable (backend, FALSE);
+ if (e_source_get_connection_status (source) != E_SOURCE_CONNECTION_STATUS_DISCONNECTED)
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+
/* We can free our service. */
g_clear_object (&priv->service);
}
@@ -1711,19 +1713,52 @@ book_backend_google_open_sync (EBookBackend *backend,
e_book_backend_set_writable (backend, FALSE);
if (is_online) {
- success = request_authorization (backend, cancellable, error);
+ ESource *source = e_backend_get_source (E_BACKEND (backend));
+
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
+
+ success = connect_without_password (backend, cancellable, error);
if (success) {
+ GError *local_error = NULL;
+
/* Refresh the authorizer. This may block. */
success = gdata_authorizer_refresh_authorization (
- priv->authorizer, cancellable, error);
+ priv->authorizer, cancellable, &local_error);
+
+ if (success) {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+ } else {
+ GError *local_error2 = NULL;
+
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+
+ if (local_error && !e_backend_credentials_required_sync (E_BACKEND (backend), E_SOURCE_CREDENTIALS_REASON_ERROR,
+ NULL, 0, local_error, cancellable, &local_error2)) {
+ g_warning ("%s: Failed to call credentials required: %s", G_STRFUNC, local_error2 ? local_error2->message : "Unknown error");
+ }
+
+ g_clear_error (&local_error2);
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+ }
+ } else {
+ GError *local_error = NULL;
+
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+
+ if (!e_backend_credentials_required_sync (E_BACKEND (backend), E_SOURCE_CREDENTIALS_REASON_REQUIRED,
+ NULL, 0, NULL, cancellable, &local_error)) {
+ g_warning ("%s: Failed to call credentials required: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error");
+ }
+
+ g_clear_error (&local_error);
}
}
- if (!is_online || backend_is_authorized (backend)) {
- if (is_online) {
- e_book_backend_set_writable (backend, TRUE);
- cache_refresh_if_needed (backend);
- }
+ if (is_online && backend_is_authorized (backend)) {
+ e_book_backend_set_writable (backend, TRUE);
+ cache_refresh_if_needed (backend);
}
return success;
@@ -2281,16 +2316,18 @@ book_backend_google_refresh_sync (EBookBackend *backend,
}
static ESourceAuthenticationResult
-book_backend_google_try_password_sync (ESourceAuthenticator *authenticator,
- const GString *password,
- GCancellable *cancellable,
- GError **error)
+book_backend_google_authenticate_sync (EBackend *backend,
+ const ENamedParameters *credentials,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
{
EBookBackendGooglePrivate *priv;
ESourceAuthentication *auth_extension;
ESourceAuthenticationResult result;
ESource *source;
- const gchar *extension_name;
+ const gchar *username;
gchar *user;
GError *local_error = NULL;
@@ -2298,24 +2335,34 @@ book_backend_google_try_password_sync (ESourceAuthenticator *authenticator,
/* We should not have gotten here if we're offline. */
g_return_val_if_fail (
- e_backend_get_online (E_BACKEND (authenticator)),
+ e_backend_get_online (E_BACKEND (backend)),
E_SOURCE_AUTHENTICATION_ERROR);
/* Nor should we have gotten here if we're already authorized. */
g_return_val_if_fail (
- !backend_is_authorized (E_BOOK_BACKEND (authenticator)),
+ !backend_is_authorized (E_BOOK_BACKEND (backend)),
E_SOURCE_AUTHENTICATION_ERROR);
- priv = E_BOOK_BACKEND_GOOGLE (authenticator)->priv;
+ priv = E_BOOK_BACKEND_GOOGLE (backend)->priv;
- source = e_backend_get_source (E_BACKEND (authenticator));
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- auth_extension = e_source_get_extension (source, extension_name);
+ source = e_backend_get_source (backend);
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
user = e_source_authentication_dup_user (auth_extension);
- gdata_client_login_authorizer_authenticate (
- GDATA_CLIENT_LOGIN_AUTHORIZER (priv->authorizer),
- user, password->str, cancellable, &local_error);
+ username = e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_USERNAME);
+ if (!username || !*username)
+ username = user;
+
+ if (gdata_client_login_authorizer_authenticate (GDATA_CLIENT_LOGIN_AUTHORIZER (priv->authorizer),
+ user, e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD), cancellable, &local_error)) {
+ EBookBackend *book_backend = E_BOOK_BACKEND (backend);
+
+ if (gdata_authorizer_refresh_authorization (priv->authorizer, cancellable, &local_error) &&
+ backend_is_authorized (book_backend)) {
+ e_book_backend_set_writable (book_backend, TRUE);
+ cache_refresh_if_needed (book_backend);
+ }
+ }
g_free (user);
@@ -2341,7 +2388,8 @@ static void
e_book_backend_google_class_init (EBookBackendGoogleClass *class)
{
GObjectClass *object_class;
- EBookBackendClass *backend_class;
+ EBackendClass *backend_class;
+ EBookBackendClass *book_backend_class;
g_type_class_add_private (class, sizeof (EBookBackendGooglePrivate));
@@ -2349,23 +2397,20 @@ e_book_backend_google_class_init (EBookBackendGoogleClass *class)
object_class->dispose = book_backend_google_dispose;
object_class->finalize = book_backend_google_finalize;
- backend_class = E_BOOK_BACKEND_CLASS (class);
- backend_class->get_backend_property = book_backend_google_get_backend_property;
- backend_class->open_sync = book_backend_google_open_sync;
- backend_class->create_contacts_sync = book_backend_google_create_contacts_sync;
- backend_class->modify_contacts_sync = book_backend_google_modify_contacts_sync;
- backend_class->remove_contacts_sync = book_backend_google_remove_contacts_sync;
- backend_class->get_contact_sync = book_backend_google_get_contact_sync;
- backend_class->get_contact_list_sync = book_backend_google_get_contact_list_sync;
- backend_class->start_view = book_backend_google_start_view;
- backend_class->stop_view = book_backend_google_stop_view;
- backend_class->refresh_sync = book_backend_google_refresh_sync;
-}
-
-static void
-e_book_backend_google_source_authenticator_init (ESourceAuthenticatorInterface *iface)
-{
- iface->try_password_sync = book_backend_google_try_password_sync;
+ backend_class = E_BACKEND_CLASS (class);
+ backend_class->authenticate_sync = book_backend_google_authenticate_sync;
+
+ book_backend_class = E_BOOK_BACKEND_CLASS (class);
+ book_backend_class->get_backend_property = book_backend_google_get_backend_property;
+ book_backend_class->open_sync = book_backend_google_open_sync;
+ book_backend_class->create_contacts_sync = book_backend_google_create_contacts_sync;
+ book_backend_class->modify_contacts_sync = book_backend_google_modify_contacts_sync;
+ book_backend_class->remove_contacts_sync = book_backend_google_remove_contacts_sync;
+ book_backend_class->get_contact_sync = book_backend_google_get_contact_sync;
+ book_backend_class->get_contact_list_sync = book_backend_google_get_contact_list_sync;
+ book_backend_class->start_view = book_backend_google_start_view;
+ book_backend_class->stop_view = book_backend_google_stop_view;
+ book_backend_class->refresh_sync = book_backend_google_refresh_sync;
}
static void
diff --git a/addressbook/backends/ldap/e-book-backend-ldap.c b/addressbook/backends/ldap/e-book-backend-ldap.c
index 52ce591db..559ebbfd5 100644
--- a/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -117,17 +117,7 @@ typedef struct LDAPOp LDAPOp;
"Incorrect msg type %d passed to %s", \
_msg_type, G_STRFUNC))
-/* Forward Declarations */
-static void e_book_backend_ldap_source_authenticator_init
- (ESourceAuthenticatorInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (
- EBookBackendLDAP,
- e_book_backend_ldap,
- E_TYPE_BOOK_BACKEND,
- G_IMPLEMENT_INTERFACE (
- E_TYPE_SOURCE_AUTHENTICATOR,
- e_book_backend_ldap_source_authenticator_init))
+G_DEFINE_TYPE (EBookBackendLDAP, e_book_backend_ldap, E_TYPE_BOOK_BACKEND)
struct _EBookBackendLDAPPrivate {
gboolean connected;
@@ -4940,6 +4930,8 @@ book_backend_ldap_open (EBookBackend *backend,
e_book_backend_set_writable (backend, TRUE);
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
+
auth_required = e_source_authentication_required (auth_extension);
if (!auth_required)
@@ -4953,11 +4945,16 @@ book_backend_ldap_open (EBookBackend *backend,
auth_required = TRUE;
}
- if (auth_required && error == NULL)
- e_backend_authenticate_sync (
- E_BACKEND (backend),
- E_SOURCE_AUTHENTICATOR (backend),
- cancellable, &error);
+ if (auth_required && error == NULL) {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+
+ e_backend_credentials_required_sync (E_BACKEND (backend), E_SOURCE_CREDENTIALS_REASON_REQUIRED,
+ NULL, 0, NULL, cancellable, &error);
+ } else if (!auth_required && !error) {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+ } else {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+ }
if (error != NULL && enable_debug)
printf ("%s ... failed to connect to server \n", G_STRFUNC);
@@ -5545,10 +5542,12 @@ book_backend_ldap_get_contact_list_uids (EBookBackend *backend,
}
static ESourceAuthenticationResult
-book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
- const GString *password,
- GCancellable *cancellable,
- GError **error)
+book_backend_ldap_authenticate_sync (EBackend *backend,
+ const ENamedParameters *credentials,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
{
ESourceAuthenticationResult result;
EBookBackendLDAP *bl;
@@ -5556,23 +5555,27 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
ESource *source;
gint ldap_error;
gchar *dn = NULL;
- const gchar *extension_name;
+ const gchar *username;
gchar *method;
- gchar *user;
+ gchar *auth_user;
- bl = E_BOOK_BACKEND_LDAP (authenticator);
- source = e_backend_get_source (E_BACKEND (authenticator));
+ bl = E_BOOK_BACKEND_LDAP (backend);
+ source = e_backend_get_source (backend);
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- auth_extension = e_source_get_extension (source, extension_name);
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
/* We should not have gotten here if we're offline. */
g_return_val_if_fail (
- e_backend_get_online (E_BACKEND (authenticator)),
+ e_backend_get_online (backend),
E_SOURCE_AUTHENTICATION_ERROR);
method = e_source_authentication_dup_method (auth_extension);
- user = e_source_authentication_dup_user (auth_extension);
+ auth_user = e_source_authentication_dup_user (auth_extension);
+
+ username = e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_USERNAME);
+ if (!username || !*username) {
+ username = auth_user;
+ }
if (!method)
method = g_strdup ("none");
@@ -5581,7 +5584,7 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
if (bl->priv->ldap && !strcmp (method, "ldap/simple-email")) {
LDAPMessage *res, *e;
- gchar *query = g_strdup_printf ("(mail=%s)", user);
+ gchar *query = g_strdup_printf ("(mail=%s)", username);
gchar *entry_dn;
g_rec_mutex_lock (&eds_ldap_handler_lock);
@@ -5606,7 +5609,11 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
error, G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
_("Failed to get the DN "
- "for user '%s'"), user);
+ "for user '%s'"), username);
+
+ g_free (method);
+ g_free (auth_user);
+
return E_SOURCE_AUTHENTICATION_ERROR;
}
@@ -5620,14 +5627,14 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
ldap_msgfree (res);
} else if (!g_strcmp0 (method, "ldap/simple-binddn")) {
- dn = g_strdup (user);
+ dn = g_strdup (username);
}
g_free (bl->priv->auth_dn);
g_free (bl->priv->auth_secret);
bl->priv->auth_dn = dn;
- bl->priv->auth_secret = g_strdup (password->str);
+ bl->priv->auth_secret = g_strdup (e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD));
/* now authenticate against the DN we were either supplied or queried for */
if (enable_debug)
@@ -5642,6 +5649,9 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
e_book_backend_ldap_connect (bl, &local_error);
+ g_free (method);
+ g_free (auth_user);
+
if (local_error == NULL) {
return E_SOURCE_AUTHENTICATION_ACCEPTED;
@@ -5679,7 +5689,7 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
}
#ifdef ENABLE_SASL_BINDS
else if (!g_ascii_strncasecmp (method, SASL_PREFIX, strlen (SASL_PREFIX))) {
- g_print ("sasl bind (mech = %s) as %s", method + strlen (SASL_PREFIX), user);
+ g_print ("sasl bind (mech = %s) as %s", method + strlen (SASL_PREFIX), username);
g_rec_mutex_lock (&eds_ldap_handler_lock);
if (!bl->priv->connected || !bl->priv->ldap) {
@@ -5689,6 +5699,9 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
e_book_backend_ldap_connect (bl, &local_error);
+ g_free (method);
+ g_free (auth_user);
+
if (local_error == NULL) {
return E_SOURCE_AUTHENTICATION_ACCEPTED;
@@ -5723,8 +5736,7 @@ book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
exit:
switch (ldap_error) {
case LDAP_SUCCESS:
- e_book_backend_set_writable (
- E_BOOK_BACKEND (authenticator), TRUE);
+ e_book_backend_set_writable (E_BOOK_BACKEND (backend), TRUE);
/* force a requery on the root dse since some ldap
* servers are set up such that they don't report
@@ -5765,7 +5777,7 @@ exit:
}
g_free (method);
- g_free (user);
+ g_free (auth_user);
return result;
}
@@ -5774,7 +5786,8 @@ static void
e_book_backend_ldap_class_init (EBookBackendLDAPClass *class)
{
GObjectClass *object_class;
- EBookBackendClass *backend_class;
+ EBackendClass *backend_class;
+ EBookBackendClass *book_backend_class;
g_type_class_add_private (class, sizeof (EBookBackendLDAPPrivate));
@@ -5786,30 +5799,27 @@ e_book_backend_ldap_class_init (EBookBackendLDAPClass *class)
object_class = G_OBJECT_CLASS (class);
object_class->finalize = book_backend_ldap_finalize;
- backend_class = E_BOOK_BACKEND_CLASS (class);
- backend_class->get_backend_property = book_backend_ldap_get_backend_property;
- backend_class->open = book_backend_ldap_open;
- backend_class->create_contacts = book_backend_ldap_create_contacts;
- backend_class->modify_contacts = book_backend_ldap_modify_contacts;
- backend_class->remove_contacts = book_backend_ldap_remove_contacts;
- backend_class->get_contact = book_backend_ldap_get_contact;
- backend_class->get_contact_list = book_backend_ldap_get_contact_list;
- backend_class->get_contact_list_uids = book_backend_ldap_get_contact_list_uids;
- backend_class->start_view = book_backend_ldap_start_view;
- backend_class->stop_view = book_backend_ldap_stop_view;
- backend_class->refresh_sync = book_backend_ldap_refresh_sync;
+ backend_class = E_BACKEND_CLASS (class);
+ backend_class->authenticate_sync = book_backend_ldap_authenticate_sync;
+
+ book_backend_class = E_BOOK_BACKEND_CLASS (class);
+ book_backend_class->get_backend_property = book_backend_ldap_get_backend_property;
+ book_backend_class->open = book_backend_ldap_open;
+ book_backend_class->create_contacts = book_backend_ldap_create_contacts;
+ book_backend_class->modify_contacts = book_backend_ldap_modify_contacts;
+ book_backend_class->remove_contacts = book_backend_ldap_remove_contacts;
+ book_backend_class->get_contact = book_backend_ldap_get_contact;
+ book_backend_class->get_contact_list = book_backend_ldap_get_contact_list;
+ book_backend_class->get_contact_list_uids = book_backend_ldap_get_contact_list_uids;
+ book_backend_class->start_view = book_backend_ldap_start_view;
+ book_backend_class->stop_view = book_backend_ldap_stop_view;
+ book_backend_class->refresh_sync = book_backend_ldap_refresh_sync;
/* Register our ESource extension. */
E_TYPE_SOURCE_LDAP;
}
static void
-e_book_backend_ldap_source_authenticator_init (ESourceAuthenticatorInterface *iface)
-{
- iface->try_password_sync = book_backend_ldap_try_password_sync;
-}
-
-static void
e_book_backend_ldap_init (EBookBackendLDAP *backend)
{
backend->priv = E_BOOK_BACKEND_LDAP_GET_PRIVATE (backend);
diff --git a/addressbook/backends/webdav/e-book-backend-webdav.c b/addressbook/backends/webdav/e-book-backend-webdav.c
index 4402a9e14..5f130a5d7 100644
--- a/addressbook/backends/webdav/e-book-backend-webdav.c
+++ b/addressbook/backends/webdav/e-book-backend-webdav.c
@@ -51,17 +51,7 @@
#define WEBDAV_CONTACT_ETAG "X-EVOLUTION-WEBDAV-ETAG"
#define WEBDAV_CONTACT_HREF "X-EVOLUTION-WEBDAV-HREF"
-/* Forward Declarations */
-static void e_book_backend_webdav_source_authenticator_init
- (ESourceAuthenticatorInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (
- EBookBackendWebdav,
- e_book_backend_webdav,
- E_TYPE_BOOK_BACKEND,
- G_IMPLEMENT_INTERFACE (
- E_TYPE_SOURCE_AUTHENTICATOR,
- e_book_backend_webdav_source_authenticator_init))
+G_DEFINE_TYPE (EBookBackendWebdav, e_book_backend_webdav, E_TYPE_BOOK_BACKEND)
struct _EBookBackendWebdavPrivate {
gboolean marked_for_offline;
@@ -230,10 +220,7 @@ send_and_handle_ssl (EBookBackendWebdav *webdav,
{
guint status_code;
- e_soup_ssl_trust_connect (
- message, e_backend_get_source (E_BACKEND (webdav)),
- e_book_backend_get_registry (E_BOOK_BACKEND (webdav)),
- cancellable);
+ e_soup_ssl_trust_connect (message, e_backend_get_source (E_BACKEND (webdav)));
status_code = soup_session_send_message (webdav->priv->session, message);
@@ -1133,7 +1120,7 @@ soup_authenticate (SoupSession *session,
if (retrying)
return;
- if (!priv->username || !*priv->username)
+ if (!priv->username || !*priv->username || !priv->password)
soup_message_set_status (message, SOUP_STATUS_FORBIDDEN);
else
soup_auth_authenticate (auth, priv->username, priv->password);
@@ -1221,6 +1208,8 @@ book_backend_webdav_get_backend_property (EBookBackend *backend,
static gboolean
book_backend_webdav_test_can_connect (EBookBackendWebdav *webdav,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error)
{
@@ -1257,11 +1246,32 @@ book_backend_webdav_test_can_connect (EBookBackendWebdav *webdav,
e_client_error_to_string (E_CLIENT_ERROR_AUTHENTICATION_REQUIRED));
break;
+ case SOUP_STATUS_SSL_FAILED:
+ if (out_certificate_pem && out_certificate_errors) {
+ GTlsCertificate *certificate = NULL;
+
+ g_object_get (G_OBJECT (message),
+ "tls-certificate", &certificate,
+ "tls-errors", out_certificate_errors,
+ NULL);
+
+ if (certificate) {
+ g_object_get (certificate, "certificate-pem", out_certificate_pem, NULL);
+ g_object_unref (certificate);
+ }
+ }
+
+ g_set_error_literal (
+ error, SOUP_HTTP_ERROR,
+ message->status_code,
+ message->reason_phrase);
+ break;
+
default:
- g_set_error (
+ g_set_error_literal (
error, SOUP_HTTP_ERROR,
message->status_code,
- "%s", message->reason_phrase);
+ message->reason_phrase);
break;
}
@@ -1370,13 +1380,55 @@ book_backend_webdav_open_sync (EBookBackend *backend,
e_backend_set_online (E_BACKEND (backend), TRUE);
e_book_backend_set_writable (backend, TRUE);
- if (e_source_authentication_required (auth_extension))
- success = e_backend_authenticate_sync (
- E_BACKEND (backend),
- E_SOURCE_AUTHENTICATOR (backend),
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
+
+ if (e_source_authentication_required (auth_extension)) {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+
+ success = e_backend_credentials_required_sync (E_BACKEND (backend),
+ E_SOURCE_CREDENTIALS_REASON_REQUIRED, NULL, 0, NULL,
cancellable, error);
- else
- success = book_backend_webdav_test_can_connect (webdav, cancellable, error);
+ } else {
+ gchar *certificate_pem = NULL;
+ GTlsCertificateFlags certificate_errors = 0;
+ GError *local_error = NULL;
+
+ success = book_backend_webdav_test_can_connect (webdav, &certificate_pem, &certificate_errors, cancellable, &local_error);
+ if (!success && !g_cancellable_is_cancelled (cancellable)) {
+ ESourceCredentialsReason reason;
+ GError *local_error2 = NULL;
+
+ if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_SSL_FAILED);
+ } else if (g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED) ||
+ g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED)) {
+ reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
+ } else {
+ reason = E_SOURCE_CREDENTIALS_REASON_ERROR;
+ }
+
+ if (!e_backend_credentials_required_sync (E_BACKEND (backend), reason, certificate_pem, certificate_errors,
+ local_error, cancellable, &local_error2)) {
+ g_warning ("%s: Failed to call credentials required: %s", G_STRFUNC, local_error2 ? local_error2->message : "Unknown error");
+ }
+
+ if (!local_error2 && g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ /* These cerificate errors are treated through the authentication */
+ g_clear_error (&local_error);
+ } else {
+ g_propagate_error (error, local_error);
+ local_error = NULL;
+ }
+
+ g_clear_error (&local_error2);
+ }
+
+ g_free (certificate_pem);
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+ }
soup_uri_free (suri);
@@ -1764,31 +1816,49 @@ book_backend_webdav_get_contact_list_sync (EBookBackend *backend,
}
static ESourceAuthenticationResult
-book_backend_webdav_try_password_sync (ESourceAuthenticator *authenticator,
- const GString *password,
- GCancellable *cancellable,
- GError **error)
+book_backend_webdav_authenticate_sync (EBackend *backend,
+ const ENamedParameters *credentials,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
{
- EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (authenticator);
+ EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend);
ESourceAuthentication *auth_extension;
ESourceAuthenticationResult result;
ESource *source;
- const gchar *extension_name;
+ const gchar *username;
GError *local_error = NULL;
- source = e_backend_get_source (E_BACKEND (authenticator));
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- auth_extension = e_source_get_extension (source, extension_name);
+ source = e_backend_get_source (backend);
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ g_free (webdav->priv->username);
+ webdav->priv->username = NULL;
+
+ g_free (webdav->priv->password);
+ webdav->priv->password = g_strdup (e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD));
- webdav->priv->username =
- e_source_authentication_dup_user (auth_extension);
- webdav->priv->password = g_strdup (password->str);
+ username = e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_USERNAME);
+ if (username && *username) {
+ webdav->priv->username = g_strdup (username);
+ } else {
+ webdav->priv->username = e_source_authentication_dup_user (auth_extension);
+ }
- if (book_backend_webdav_test_can_connect (webdav, cancellable, &local_error)) {
+ if (book_backend_webdav_test_can_connect (webdav, out_certificate_pem, out_certificate_errors, cancellable, &local_error)) {
result = E_SOURCE_AUTHENTICATION_ACCEPTED;
- } else if (g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
- result = E_SOURCE_AUTHENTICATION_REJECTED;
+ } else if (g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED) ||
+ g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED)) {
+ if (!e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_PASSWORD) ||
+ g_error_matches (local_error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_REQUIRED))
+ result = E_SOURCE_AUTHENTICATION_REQUIRED;
+ else
+ result = E_SOURCE_AUTHENTICATION_REJECTED;
g_clear_error (&local_error);
+ } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
+ result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED;
+ g_propagate_error (error, local_error);
} else {
result = E_SOURCE_AUTHENTICATION_ERROR;
g_propagate_error (error, local_error);
@@ -1801,7 +1871,8 @@ static void
e_book_backend_webdav_class_init (EBookBackendWebdavClass *class)
{
GObjectClass *object_class;
- EBookBackendClass *backend_class;
+ EBackendClass *backend_class;
+ EBookBackendClass *book_backend_class;
g_type_class_add_private (class, sizeof (EBookBackendWebdavPrivate));
@@ -1809,22 +1880,19 @@ e_book_backend_webdav_class_init (EBookBackendWebdavClass *class)
object_class->dispose = book_backend_webdav_dispose;
object_class->finalize = book_backend_webdav_finalize;
- backend_class = E_BOOK_BACKEND_CLASS (class);
- backend_class->get_backend_property = book_backend_webdav_get_backend_property;
- backend_class->open_sync = book_backend_webdav_open_sync;
- backend_class->create_contacts_sync = book_backend_webdav_create_contacts_sync;
- backend_class->modify_contacts_sync = book_backend_webdav_modify_contacts_sync;
- backend_class->remove_contacts_sync = book_backend_webdav_remove_contacts_sync;
- backend_class->get_contact_sync = book_backend_webdav_get_contact_sync;
- backend_class->get_contact_list_sync = book_backend_webdav_get_contact_list_sync;
- backend_class->start_view = e_book_backend_webdav_start_view;
- backend_class->stop_view = e_book_backend_webdav_stop_view;
-}
-
-static void
-e_book_backend_webdav_source_authenticator_init (ESourceAuthenticatorInterface *iface)
-{
- iface->try_password_sync = book_backend_webdav_try_password_sync;
+ backend_class = E_BACKEND_CLASS (class);
+ backend_class->authenticate_sync = book_backend_webdav_authenticate_sync;
+
+ book_backend_class = E_BOOK_BACKEND_CLASS (class);
+ book_backend_class->get_backend_property = book_backend_webdav_get_backend_property;
+ book_backend_class->open_sync = book_backend_webdav_open_sync;
+ book_backend_class->create_contacts_sync = book_backend_webdav_create_contacts_sync;
+ book_backend_class->modify_contacts_sync = book_backend_webdav_modify_contacts_sync;
+ book_backend_class->remove_contacts_sync = book_backend_webdav_remove_contacts_sync;
+ book_backend_class->get_contact_sync = book_backend_webdav_get_contact_sync;
+ book_backend_class->get_contact_list_sync = book_backend_webdav_get_contact_list_sync;
+ book_backend_class->start_view = e_book_backend_webdav_start_view;
+ book_backend_class->stop_view = e_book_backend_webdav_stop_view;
}
static void
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index ebd1a2cac..609b0a2d7 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -96,6 +96,7 @@ struct _SignalClosure {
struct _ConnectClosure {
ESource *source;
GCancellable *cancellable;
+ guint32 wait_for_connected_seconds;
};
struct _RunInThreadClosure {
@@ -1001,6 +1002,34 @@ book_client_refresh_sync (EClient *client,
return TRUE;
}
+static gboolean
+book_client_retrieve_properties_sync (EClient *client,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EBookClient *book_client;
+ gchar **properties = NULL;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (E_IS_BOOK_CLIENT (client), FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+
+ e_dbus_address_book_call_retrieve_properties_sync (
+ book_client->priv->dbus_proxy, &properties, cancellable, &local_error);
+
+ book_client_process_properties (book_client, properties);
+ g_strfreev (properties);
+
+ if (local_error != NULL) {
+ g_dbus_error_strip_remote_error (local_error);
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
GObject *source_object,
@@ -1246,6 +1275,7 @@ e_book_client_class_init (EBookClientClass *class)
client_class->set_backend_property_sync = book_client_set_backend_property_sync;
client_class->open_sync = book_client_open_sync;
client_class->refresh_sync = book_client_refresh_sync;
+ client_class->retrieve_properties_sync = book_client_retrieve_properties_sync;
/**
* EBookClient:locale:
@@ -1293,6 +1323,7 @@ e_book_client_init (EBookClient *client)
/**
* e_book_client_connect_sync:
* @source: an #ESource
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
@@ -1302,6 +1333,15 @@ e_book_client_init (EBookClient *client)
* Unlike with e_book_client_new(), there is no need to call
* e_client_open_sync() after obtaining the #EBookClient.
*
+ * The @wait_for_connected_seconds argument had been added since 3.14,
+ * to let the caller decide how long to wait for the backend to fully
+ * connect to its (possibly remote) data store. This is required due
+ * to a change in the authentication process, which is fully asynchronous
+ * and done on the client side, while not every client is supposed to
+ * response to authentication requests. In case the backend will not connect
+ * within the set interval, then it is opened in an offline mode. A special
+ * value -1 can be used to not wait for the connected state at all.
+ *
* For error handling convenience, any error message returned by this
* function will have a descriptive prefix that includes the display
* name of @source.
@@ -1312,6 +1352,7 @@ e_book_client_init (EBookClient *client)
**/
EClient *
e_book_client_connect_sync (ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error)
{
@@ -1336,6 +1377,12 @@ e_book_client_connect_sync (ESource *source,
g_strfreev (properties);
}
+ if (!local_error && wait_for_connected_seconds != (guint32) -1) {
+ /* These errors are ignored, the book is left opened in an offline mode. */
+ e_client_wait_for_connected_sync (E_CLIENT (client),
+ wait_for_connected_seconds, cancellable, NULL);
+ }
+
if (local_error != NULL) {
g_dbus_error_strip_remote_error (local_error);
g_propagate_error (error, local_error);
@@ -1349,6 +1396,23 @@ e_book_client_connect_sync (ESource *source,
return E_CLIENT (client);
}
+static void
+book_client_connect_wait_for_connected_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ /* These errors are ignored, the book is left opened in an offline mode. */
+ e_client_wait_for_connected_finish (E_CLIENT (source_object), result, NULL);
+
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
/* Helper for e_book_client_connect() */
static void
book_client_connect_open_cb (GObject *source_object,
@@ -1368,6 +1432,24 @@ book_client_connect_open_cb (GObject *source_object,
client_object = g_async_result_get_source_object (G_ASYNC_RESULT (simple));
if (client_object) {
book_client_process_properties (E_BOOK_CLIENT (client_object), properties);
+
+ if (!local_error) {
+ ConnectClosure *closure;
+
+ closure = g_simple_async_result_get_op_res_gpointer (simple);
+ if (closure->wait_for_connected_seconds != (guint32) -1) {
+ e_client_wait_for_connected (E_CLIENT (client_object),
+ closure->wait_for_connected_seconds,
+ closure->cancellable,
+ book_client_connect_wait_for_connected_cb, g_object_ref (simple));
+
+ g_clear_object (&client_object);
+ g_object_unref (simple);
+ g_strfreev (properties);
+ return;
+ }
+ }
+
g_clear_object (&client_object);
}
@@ -1427,6 +1509,7 @@ exit:
/**
* e_book_client_connect:
* @source: an #ESource
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
* @callback: (scope async): a #GAsyncReadyCallback to call when the request
* is satisfied
@@ -1434,6 +1517,15 @@ exit:
*
* Asynchronously creates a new #EBookClient for @source.
*
+ * The @wait_for_connected_seconds argument had been added since 3.14,
+ * to let the caller decide how long to wait for the backend to fully
+ * connect to its (possibly remote) data store. This is required due
+ * to a change in the authentication process, which is fully asynchronous
+ * and done on the client side, while not every client is supposed to
+ * response to authentication requests. In case the backend will not connect
+ * within the set interval, then it is opened in an offline mode. A special
+ * value -1 can be used to not wait for the connected state at all.
+ *
* Unlike with e_book_client_new(), there is no need to call e_client_open()
* after obtaining the #EBookClient.
*
@@ -1444,6 +1536,7 @@ exit:
**/
void
e_book_client_connect (ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -1462,6 +1555,7 @@ e_book_client_connect (ESource *source,
closure = g_slice_new0 (ConnectClosure);
closure->source = g_object_ref (source);
+ closure->wait_for_connected_seconds = wait_for_connected_seconds;
if (G_IS_CANCELLABLE (cancellable))
closure->cancellable = g_object_ref (cancellable);
@@ -1625,6 +1719,7 @@ connect_direct (EBookClient *client,
* e_book_client_connect_direct_sync:
* @registry: an #ESourceRegistry
* @source: an #ESource
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
@@ -1638,12 +1733,13 @@ connect_direct (EBookClient *client,
EClient *
e_book_client_connect_direct_sync (ESourceRegistry *registry,
ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error)
{
EClient *client;
- client = e_book_client_connect_sync (source, cancellable, error);
+ client = e_book_client_connect_sync (source, wait_for_connected_seconds, cancellable, error);
if (!client)
return NULL;
@@ -1702,6 +1798,7 @@ exit:
/**
* e_book_client_connect_direct:
* @source: an #ESource
+ * @wait_for_connected_seconds: timeout, in seconds, to wait for the backend to be fully connected
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
* @callback: (scope async): a #GAsyncReadyCallback to call when the request
* is satisfied
@@ -1717,6 +1814,7 @@ exit:
**/
void
e_book_client_connect_direct (ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -1734,6 +1832,7 @@ e_book_client_connect_direct (ESource *source,
* time and block other clients from receiving signals. */
closure = g_slice_new0 (ConnectClosure);
closure->source = g_object_ref (source);
+ closure->wait_for_connected_seconds = wait_for_connected_seconds;
if (G_IS_CANCELLABLE (cancellable))
closure->cancellable = g_object_ref (cancellable);
diff --git a/addressbook/libebook/e-book-client.h b/addressbook/libebook/e-book-client.h
index feb3df815..3a557f98a 100644
--- a/addressbook/libebook/e-book-client.h
+++ b/addressbook/libebook/e-book-client.h
@@ -102,9 +102,11 @@ struct _EBookClientClass {
GType e_book_client_get_type (void) G_GNUC_CONST;
EClient * e_book_client_connect_sync (ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error);
void e_book_client_connect (ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
@@ -113,9 +115,11 @@ EClient * e_book_client_connect_finish (GAsyncResult *result,
EClient * e_book_client_connect_direct_sync
(ESourceRegistry *registry,
ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GError **error);
void e_book_client_connect_direct (ESource *source,
+ guint32 wait_for_connected_seconds,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index acc6e67e0..51cc2f4e3 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -568,24 +568,6 @@ book_backend_constructed (GObject *object)
}
}
-static gboolean
-book_backend_authenticate_sync (EBackend *backend,
- ESourceAuthenticator *auth,
- GCancellable *cancellable,
- GError **error)
-{
- EBookBackend *book_backend;
- ESourceRegistry *registry;
- ESource *source;
-
- book_backend = E_BOOK_BACKEND (backend);
- registry = e_book_backend_get_registry (book_backend);
- source = e_backend_get_source (backend);
-
- return e_source_registry_authenticate_sync (
- registry, source, auth, cancellable, error);
-}
-
static void
book_backend_prepare_shutdown (EBackend *backend)
{
@@ -721,7 +703,6 @@ e_book_backend_class_init (EBookBackendClass *class)
object_class->constructed = book_backend_constructed;
backend_class = E_BACKEND_CLASS (class);
- backend_class->authenticate_sync = book_backend_authenticate_sync;
backend_class->prepare_shutdown = book_backend_prepare_shutdown;
class->get_backend_property = book_backend_get_backend_property;
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 4d66ec715..165fcda74 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -545,24 +545,20 @@ e_data_book_string_slist_to_comma_string (const GSList *strings)
return res;
}
-static void
-data_book_complete_open_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
+static GPtrArray *
+data_book_encode_properties (EDBusAddressBook *dbus_interface)
{
- AsyncContext *async_context = user_data;
- GError *error = NULL;
+ GPtrArray *properties_array;
- e_book_backend_open_finish (
- E_BOOK_BACKEND (source_object), result, &error);
+ g_warn_if_fail (E_DBUS_IS_ADDRESS_BOOK (dbus_interface));
- if (error == NULL) {
- GPtrArray *properties_array;
+ properties_array = g_ptr_array_new_with_free_func (g_free);
+
+ if (dbus_interface) {
GParamSpec **properties;
guint ii, n_properties = 0;
- properties_array = g_ptr_array_new_with_free_func (g_free);
- properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (async_context->dbus_interface), &n_properties);
+ properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (dbus_interface), &n_properties);
for (ii = 0; ii < n_properties; ii++) {
gboolean can_process =
@@ -581,7 +577,7 @@ data_book_complete_open_cb (GObject *source_object,
GVariant *stored = NULL;
g_value_init (&value, properties[ii]->value_type);
- g_object_get_property ((GObject *) async_context->dbus_interface, properties[ii]->name, &value);
+ g_object_get_property ((GObject *) dbus_interface, properties[ii]->name, &value);
#define WORKOUT(gvl, gvr) \
if (g_type_is_a (properties[ii]->value_type, G_TYPE_ ## gvl)) \
@@ -611,8 +607,47 @@ data_book_complete_open_cb (GObject *source_object,
}
g_free (properties);
+ }
+
+ g_ptr_array_add (properties_array, NULL);
+
+ return properties_array;
+}
+
+static gboolean
+data_book_handle_retrieve_properties_cb (EDBusAddressBook *dbus_interface,
+ GDBusMethodInvocation *invocation,
+ EDataBook *data_book)
+{
+ GPtrArray *properties_array;
+
+ properties_array = data_book_encode_properties (dbus_interface);
+
+ e_dbus_address_book_complete_retrieve_properties (
+ dbus_interface,
+ invocation,
+ (const gchar * const *) properties_array->pdata);
- g_ptr_array_add (properties_array, NULL);
+ g_ptr_array_free (properties_array, TRUE);
+
+ return TRUE;
+}
+
+static void
+data_book_complete_open_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ AsyncContext *async_context = user_data;
+ GError *error = NULL;
+
+ e_book_backend_open_finish (
+ E_BOOK_BACKEND (source_object), result, &error);
+
+ if (error == NULL) {
+ GPtrArray *properties_array;
+
+ properties_array = data_book_encode_properties (async_context->dbus_interface);
e_dbus_address_book_complete_open (
async_context->dbus_interface,
@@ -2066,6 +2101,10 @@ e_data_book_init (EDataBook *data_book)
(GDestroyNotify) g_ptr_array_unref);
g_signal_connect (
+ dbus_interface, "handle-retrieve-properties",
+ G_CALLBACK (data_book_handle_retrieve_properties_cb),
+ data_book);
+ g_signal_connect (
dbus_interface, "handle-open",
G_CALLBACK (data_book_handle_open_cb),
data_book);