diff options
Diffstat (limited to 'addressbook/util/addressbook.c')
-rw-r--r-- | addressbook/util/addressbook.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/addressbook/util/addressbook.c b/addressbook/util/addressbook.c new file mode 100644 index 0000000000..7caa545059 --- /dev/null +++ b/addressbook/util/addressbook.c @@ -0,0 +1,334 @@ +/* + * 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 Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <string.h> + +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include <libebook/e-book.h> +#include <libedataserver/e-url.h> +#include <libedataserverui/e-passwords.h> + +#include "e-util/e-error.h" +#include "addressbook.h" + +#define d(x) + +static void addressbook_authenticate (EBook *book, gboolean previous_failure, + ESource *source, EBookCallback cb, gpointer closure); +static void auth_required_cb (EBook *book, gpointer data); + +typedef struct { + EBookCallback cb; + ESource *source; + gpointer closure; + guint cancelled : 1; +} LoadSourceData; + +static void +free_load_source_data (LoadSourceData *data) +{ + if (data->source) + g_object_unref (data->source); + g_free (data); +} + +/*this function removes of anything present after semicolon +in uri*/ + +static gchar * +remove_parameters_from_uri (const gchar *uri) +{ + gchar *euri_str; + EUri *euri; + + euri = e_uri_new (uri); + euri_str = e_uri_to_string (euri, FALSE); + e_uri_free (euri); + return euri_str; +} + +static void +load_source_auth_cb (EBook *book, EBookStatus status, gpointer closure) +{ + LoadSourceData *data = closure; + gboolean was_in = g_object_get_data (G_OBJECT (book), "authenticated") != NULL; + + g_object_set_data (G_OBJECT (book), "authenticated", NULL); + + if (data->cancelled) { + free_load_source_data (data); + return; + } + + if (status != E_BOOK_ERROR_OK) { + + /* the user clicked cancel in the password dialog */ + if (status == E_BOOK_ERROR_CANCELLED) { + + if (e_book_check_static_capability (book, "anon-access")) { + + GtkWidget *dialog; + + /* XXX "LDAP" has to be removed from the folowing message + so that it wil valid for other servers which provide + anonymous access*/ + + dialog = gtk_message_dialog_new (NULL, + 0, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "%s", _("Accessing LDAP Server anonymously")); + g_signal_connect (dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + status = E_BOOK_ERROR_OK; + + goto done; + } + } else if (status == E_BOOK_ERROR_INVALID_SERVER_VERSION) { + e_error_run (NULL, "addressbook:server-version", NULL); + status = E_BOOK_ERROR_OK; + goto done; + } else if (status == E_BOOK_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD) { + goto done; + } else { + if (status == E_BOOK_ERROR_AUTHENTICATION_FAILED) { + const gchar *uri = e_book_get_uri (book); + gchar *stripped_uri = remove_parameters_from_uri (uri); + const gchar *auth_domain = e_source_get_property (data->source, "auth-domain"); + const gchar *component_name; + + component_name = auth_domain ? auth_domain : "Addressbook"; + + e_passwords_forget_password (component_name, stripped_uri); + + g_free (stripped_uri); + } else if (was_in) { + /* We already tried to authenticate to the server, and it failed with + other reason than with E_BOOK_ERROR_AUTHENTICATION_FAILED, thus stop + poking with the server and report error to the user. */ + goto done; + } + + g_object_set_data (G_OBJECT (book), "authenticated", GINT_TO_POINTER (1)); + addressbook_authenticate (book, TRUE, data->source, load_source_auth_cb, closure); + return; + } + } + +done: + if (data->cb) + data->cb (book, status, data->closure); + + free_load_source_data (data); +} + +static gboolean +get_remember_password (ESource *source) +{ + const gchar *value; + + value = e_source_get_property (source, "remember_password"); + if (value && !g_ascii_strcasecmp (value, "true")) + return TRUE; + + return FALSE; +} + +static void +set_remember_password (ESource *source, gboolean value) +{ + e_source_set_property (source, "remember_password", + value ? "true" : "false"); +} + +static void +addressbook_authenticate (EBook *book, gboolean previous_failure, ESource *source, + EBookCallback cb, gpointer closure) +{ + const gchar *password = NULL; + gchar *pass_dup = NULL; + const gchar *auth; + const gchar *user; + gchar *uri = remove_parameters_from_uri(e_book_get_uri (book)); + const gchar *auth_domain = e_source_get_property (source, "auth-domain"); + const gchar *component_name; + + component_name = auth_domain ? auth_domain : "Addressbook"; + + password = e_passwords_get_password (component_name, uri); + + auth = e_source_get_property (source, "auth"); + + if (auth && !strcmp ("ldap/simple-binddn", auth)) { + user = e_source_get_property (source, "binddn"); + } + else if (auth && !strcmp ("plain/password", auth)) { + user = e_source_get_property (source, "user"); + if (!user) { + user = e_source_get_property (source, "username"); + } + } + else { + user = e_source_get_property (source, "email_addr"); + } + if (!user) + user = ""; + + if (!password) { + gchar *prompt; + gchar *password_prompt; + gboolean remember; + const gchar *failed_auth; + guint32 flags = E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET|E_PASSWORDS_ONLINE; + + if (previous_failure) { + failed_auth = _("Failed to authenticate.\n"); + flags |= E_PASSWORDS_REPROMPT; + } + else { + failed_auth = ""; + } + + password_prompt = g_strdup_printf (_("Enter password for %s (user %s)"), + e_source_peek_name (source), user); + + prompt = g_strconcat (failed_auth, password_prompt, NULL); + g_free (password_prompt); + + remember = get_remember_password (source); + pass_dup = e_passwords_ask_password ( + _("Enter password"), component_name, + uri, prompt, flags, &remember, NULL); + if (remember != get_remember_password (source)) + set_remember_password (source, remember); + + g_free (prompt); + } + + if (password || pass_dup) { + e_book_async_authenticate_user (book, user, password ? password : pass_dup, + e_source_get_property (source, "auth"), + cb, closure); + g_free (pass_dup); + } + else { + /* they hit cancel */ + cb (book, E_BOOK_ERROR_CANCELLED, closure); + } + + g_free (uri); +} + +static void +auth_required_cb (EBook *book, gpointer data) +{ + LoadSourceData *load_source_data = g_new0(LoadSourceData, 1); + + load_source_data->source = g_object_ref (g_object_ref (e_book_get_source (book))); + load_source_data->cancelled = FALSE; + addressbook_authenticate (book, FALSE, load_source_data->source, + load_source_auth_cb, load_source_data); + +} +static void +load_source_cb (EBook *book, EBookStatus status, gpointer closure) +{ + LoadSourceData *load_source_data = closure; + + if (load_source_data->cancelled) { + free_load_source_data (load_source_data); + return; + } + + if (status == E_BOOK_ERROR_OK && book != NULL) { + const gchar *auth; + + auth = e_source_get_property (load_source_data->source, "auth"); + if (auth && strcmp (auth, "none")) { + g_signal_connect (book, "auth_required", G_CALLBACK(auth_required_cb), NULL); + + if (e_book_is_online (book)) { + addressbook_authenticate (book, FALSE, load_source_data->source, + load_source_auth_cb, closure); + return; + } + } + } + load_source_data->cb (book, status, load_source_data->closure); + free_load_source_data (load_source_data); +} + +guint +addressbook_load (EBook *book, + EBookCallback cb, gpointer closure) +{ + LoadSourceData *load_source_data = g_new0 (LoadSourceData, 1); + + load_source_data->cb = cb; + load_source_data->closure = closure; + load_source_data->source = g_object_ref (g_object_ref (e_book_get_source (book))); + load_source_data->cancelled = FALSE; + + e_book_async_open (book, FALSE, load_source_cb, load_source_data); + + return GPOINTER_TO_UINT (load_source_data); +} + +void +addressbook_load_cancel (guint id) +{ + LoadSourceData *load_source_data = GUINT_TO_POINTER (id); + + load_source_data->cancelled = TRUE; +} + +static void +default_book_cb (EBook *book, EBookStatus status, gpointer closure) +{ + LoadSourceData *load_source_data = closure; + + if (status == E_BOOK_ERROR_OK) + load_source_data->source = g_object_ref (e_book_get_source (book)); + + load_source_cb (book, status, closure); +} + +void +addressbook_load_default_book (EBookCallback cb, gpointer closure) +{ + LoadSourceData *load_source_data = g_new (LoadSourceData, 1); + EBook *book; + + load_source_data->cb = cb; + load_source_data->source = NULL; + load_source_data->closure = closure; + load_source_data->cancelled = FALSE; + + book = e_book_new_default_addressbook (NULL); + if (!book) + load_source_cb (NULL, E_BOOK_ERROR_OTHER_ERROR, load_source_data); /* XXX we should just use a GError and it's error code here */ + else + e_book_async_open (book, FALSE, default_book_cb, load_source_data); +} |