diff options
Diffstat (limited to 'modules/book-config-ldap/evolution-book-config-ldap.c')
-rw-r--r-- | modules/book-config-ldap/evolution-book-config-ldap.c | 990 |
1 files changed, 990 insertions, 0 deletions
diff --git a/modules/book-config-ldap/evolution-book-config-ldap.c b/modules/book-config-ldap/evolution-book-config-ldap.c new file mode 100644 index 0000000000..a957e4c94a --- /dev/null +++ b/modules/book-config-ldap/evolution-book-config-ldap.c @@ -0,0 +1,990 @@ +/* + * evolution-book-config-ldap.c + * + * 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/> + * + */ + +#include <config.h> +#include <stdlib.h> +#include <glib/gi18n-lib.h> + +#include <libebackend/e-extension.h> +#include <libedataserver/e-source-authentication.h> + +#include <libevolution-utils/e-alert-dialog.h> +#include <misc/e-source-config-backend.h> +#include <addressbook/gui/widgets/e-book-source-config.h> + +#include "e-source-ldap.h" + +#ifndef G_OS_WIN32 +#include <ldap.h> +#ifndef SUNLDAP +#include <ldap_schema.h> +#endif +#else +#include <winldap.h> +#include "openldap-extract.h" +#endif + +/* Combo box ordering */ +#define LDAP_PORT 389 +#define LDAPS_PORT 636 +#define MSGC_PORT 3268 +#define MSGCS_PORT 3269 + +typedef ESourceConfigBackend EBookConfigLDAP; +typedef ESourceConfigBackendClass EBookConfigLDAPClass; + +typedef struct _Closure Closure; +typedef struct _Context Context; + +struct _Closure { + ESourceConfigBackend *backend; + ESource *scratch_source; +}; + +struct _Context { + GtkWidget *auth_combo; + GtkWidget *auth_entry; + GtkWidget *host_entry; + GtkWidget *port_combo; + GtkWidget *security_combo; + GtkWidget *search_base_combo; + GtkWidget *search_base_button; + GtkWidget *search_scope_combo; + GtkWidget *search_filter_entry; + GtkWidget *limit_spinbutton; + GtkWidget *can_browse_toggle; +}; + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +/* Forward Declarations */ +GType e_book_config_ldap_get_type (void); + +G_DEFINE_DYNAMIC_TYPE ( + EBookConfigLDAP, + e_book_config_ldap, + E_TYPE_SOURCE_CONFIG_BACKEND) + +static Closure * +book_config_ldap_closure_new (ESourceConfigBackend *backend, + ESource *scratch_source) +{ + Closure *closure; + + closure = g_slice_new (Closure); + closure->backend = g_object_ref (backend); + closure->scratch_source = g_object_ref (scratch_source); + + return closure; +} + +static void +book_config_ldap_closure_free (Closure *closure) +{ + g_object_unref (closure->backend); + g_object_unref (closure->scratch_source); + + g_slice_free (Closure, closure); +} + +static void +book_config_ldap_context_free (Context *context) +{ + g_object_unref (context->auth_combo); + g_object_unref (context->auth_entry); + g_object_unref (context->host_entry); + g_object_unref (context->port_combo); + g_object_unref (context->security_combo); + g_object_unref (context->search_base_combo); + g_object_unref (context->search_base_button); + g_object_unref (context->search_scope_combo); + g_object_unref (context->search_filter_entry); + g_object_unref (context->limit_spinbutton); + g_object_unref (context->can_browse_toggle); + + g_slice_free (Context, context); +} + +static GtkTreeModel * +book_config_ldap_root_dse_query (ESourceConfigBackend *backend, + ESource *scratch_source) +{ + LDAP *ldap; + LDAPMessage *result = NULL; + GtkListStore *store = NULL; + ESourceAuthentication *extension; + struct timeval timeout; + const gchar *alert_id = NULL; + const gchar *extension_name; + const gchar *host; + gchar **values = NULL; + gint ldap_error; + gint option; + gint version; + guint16 port; + gint ii; + + const gchar *attrs[] = { "namingContexts", NULL }; + + /* FIXME This all runs synchronously in the main loop. + * We should do this in a separate thread behind + * async/finish functions. May need to define + * some custom GError codes, or maybe just an + * LDAP GError domain that reuses LDAP result + * codes from <ldap.h>. */ + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + extension = e_source_get_extension (scratch_source, extension_name); + + host = e_source_authentication_get_host (extension); + port = e_source_authentication_get_port (extension); + + timeout.tv_sec = 60; + timeout.tv_usec = 0; + + ldap = ldap_init (host, port); + if (ldap == NULL) { + alert_id = "addressbook:ldap-init"; + goto exit; + } + + version = LDAP_VERSION3; + option = LDAP_OPT_PROTOCOL_VERSION; + if (ldap_set_option (ldap, option, &version) != LDAP_SUCCESS) { + /* XXX Define an alert for this. */ + g_warning ("Failed to set protocol version to LDAPv3"); + goto exit; + } + + /* FIXME Use the user's actual authentication settings. */ + if (ldap_simple_bind_s (ldap, NULL, NULL) != LDAP_SUCCESS) { + alert_id = "addressbook:ldap-auth"; + goto exit; + } + + ldap_error = ldap_search_ext_s ( + ldap, LDAP_ROOT_DSE, LDAP_SCOPE_BASE, + "(objectclass=*)", (gchar **) attrs, 0, + NULL, NULL, &timeout, LDAP_NO_LIMIT, &result); + if (ldap_error != LDAP_SUCCESS) { + alert_id = "addressbook:ldap-search-base"; + goto exit; + } + + values = ldap_get_values (ldap, result, "namingContexts"); + if (values == NULL || values[0] == NULL || *values[0] == '\0') { + alert_id = "addressbook:ldap-search-base"; + goto exit; + } + + store = gtk_list_store_new (1, G_TYPE_STRING); + + for (ii = 0; values[ii] != NULL; ii++) { + GtkTreeIter iter; + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, values[ii], -1); + } + +exit: + if (alert_id != NULL) { + ESourceConfig *config; + gpointer parent; + + config = e_source_config_backend_get_config (backend); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (config)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + e_alert_run_dialog_for_args (parent, alert_id, NULL); + } + + if (values != NULL) + ldap_value_free (values); + + if (result != NULL) + ldap_msgfree (result); + + if (ldap != NULL) + ldap_unbind_s (ldap); + + /* This may be NULL, so don't use a cast macro. */ + return (GtkTreeModel *) store; +} + +static gboolean +book_config_ldap_port_to_active (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + guint port; + gint active; + + port = g_value_get_uint (source_value); + + switch (port) { + case 0: /* initialize to LDAP_PORT */ + case LDAP_PORT: + active = 0; + break; + + case LDAPS_PORT: + active = 1; + break; + + case MSGC_PORT: + active = 2; + break; + + case MSGCS_PORT: + active = 3; + break; + + default: + active = -1; + break; + } + + g_value_set_int (target_value, active); + + if (active == -1) { + GObject *target; + GtkWidget *entry; + gchar *text; + + target = g_binding_get_target (binding); + entry = gtk_bin_get_child (GTK_BIN (target)); + + text = g_strdup_printf ("%u", port); + gtk_entry_set_text (GTK_ENTRY (entry), text); + g_free (text); + } + + return TRUE; +} + +static gboolean +book_config_ldap_active_to_port (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + guint port = LDAP_PORT; + gint active; + + active = g_value_get_int (source_value); + + switch (active) { + case 0: + port = LDAP_PORT; + break; + + case 1: + port = LDAPS_PORT; + break; + + case 2: + port = MSGC_PORT; + break; + + case 3: + port = MSGCS_PORT; + break; + + default: + active = -1; + break; + } + + if (active == -1) { + GObject *source; + GtkWidget *entry; + const gchar *text; + glong v_long; + + source = g_binding_get_source (binding); + entry = gtk_bin_get_child (GTK_BIN (source)); + text = gtk_entry_get_text (GTK_ENTRY (entry)); + + v_long = strtol (text, NULL, 10); + if (v_long != 0 && v_long == CLAMP (v_long, 0, G_MAXUINT16)) + port = (guint) v_long; + } + + g_value_set_uint (target_value, port); + + return TRUE; +} + +static gboolean +book_config_ldap_port_to_security (GBinding *binding, + const GValue *source_value, + GValue *target_value, + gpointer unused) +{ + switch (g_value_get_int (source_value)) { + case 0: /* LDAP_PORT -> StartTLS */ + g_value_set_int ( + target_value, + E_SOURCE_LDAP_SECURITY_STARTTLS); + return TRUE; + + case 1: /* LDAPS_PORT -> LDAP over SSL */ + g_value_set_int ( + target_value, + E_SOURCE_LDAP_SECURITY_LDAPS); + return TRUE; + + case 2: /* MSGC_PORT -> StartTLS */ + g_value_set_int ( + target_value, + E_SOURCE_LDAP_SECURITY_STARTTLS); + return TRUE; + + case 3: /* MSGCS_PORT -> LDAP over SSL */ + g_value_set_int ( + target_value, + E_SOURCE_LDAP_SECURITY_LDAPS); + return TRUE; + + default: + break; + } + + return FALSE; +} + +static void +book_config_ldap_search_base_button_clicked_cb (GtkButton *button, + Closure *closure) +{ + Context *context; + GtkComboBox *combo_box; + GtkTreeModel *model; + const gchar *uid; + + uid = e_source_get_uid (closure->scratch_source); + context = g_object_get_data (G_OBJECT (closure->backend), uid); + g_return_if_fail (context != NULL); + + model = book_config_ldap_root_dse_query ( + closure->backend, closure->scratch_source); + + combo_box = GTK_COMBO_BOX (context->search_base_combo); + gtk_combo_box_set_model (combo_box, model); + gtk_combo_box_set_active (combo_box, 0); + + if (model != NULL) + g_object_unref (model); +} + +static gboolean +book_config_ldap_query_port_tooltip_cb (GtkComboBox *combo_box, + gint x, + gint y, + gboolean keyboard_mode, + GtkTooltip *tooltip) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gchar *text; + + /* XXX This only works if the port number was selected from + * the drop down menu. No tooltip is shown if the user + * types the port number, even if the same port number + * is listed in the drop down menu. That's fixable but + * the code would be a lot messier, and is arguably a + * job for GtkComboBox. */ + + if (!gtk_combo_box_get_active_iter (combo_box, &iter)) + return FALSE; + + model = gtk_combo_box_get_model (combo_box); + gtk_tree_model_get (model, &iter, 1, &text, -1); + gtk_tooltip_set_text (tooltip, text); + g_free (text); + + return TRUE; +} + +static GtkWidget * +book_config_build_port_combo (void) +{ + GtkWidget *widget; + GtkComboBox *combo_box; + GtkCellRenderer *renderer; + GtkListStore *store; + GtkTreeIter iter; + + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + + gtk_list_store_append (store, &iter); + gtk_list_store_set ( + store, &iter, + 0, G_STRINGIFY (LDAP_PORT), + 1, _("Standard LDAP Port"), -1); + + gtk_list_store_append (store, &iter); + gtk_list_store_set ( + store, &iter, + 0, G_STRINGIFY (LDAPS_PORT), + 1, _("LDAP over SSL (deprecated)"), -1); + + gtk_list_store_append (store, &iter); + gtk_list_store_set ( + store, &iter, + 0, G_STRINGIFY (MSGC_PORT), + 1, _("Microsoft Global Catalog"), -1); + + gtk_list_store_append (store, &iter); + gtk_list_store_set ( + store, &iter, + 0, G_STRINGIFY (MSGCS_PORT), + 1, _("Microsoft Global Catalog over SSL"), -1); + + widget = gtk_combo_box_new_with_entry (); + + combo_box = GTK_COMBO_BOX (widget); + gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (store)); + gtk_combo_box_set_entry_text_column (combo_box, 0); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "sensitive", FALSE, NULL); + gtk_cell_layout_pack_start ( + GTK_CELL_LAYOUT (widget), renderer, FALSE); + gtk_cell_layout_add_attribute ( + GTK_CELL_LAYOUT (widget), renderer, "text", 1); + + gtk_widget_set_has_tooltip (widget, TRUE); + + g_signal_connect ( + widget, "query-tooltip", + G_CALLBACK (book_config_ldap_query_port_tooltip_cb), NULL); + + g_object_unref (store); + + return widget; +} + +static void +book_config_ldap_insert_notebook_widget (GtkWidget *vbox, + GtkSizeGroup *size_group, + const gchar *caption, + GtkWidget *widget) +{ + GtkWidget *hbox; + GtkWidget *label; + + /* This is similar to e_source_config_insert_widget(), + * but instead adds the widget to the LDAP notebook. */ + + hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (caption); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); + gtk_size_group_add_widget (size_group, label); + gtk_widget_show (label); + + gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); +} + +static void +book_config_ldap_insert_widgets (ESourceConfigBackend *backend, + ESource *scratch_source) +{ + ESourceConfig *config; + ESourceExtension *extension; + GtkSizeGroup *size_group; + GtkNotebook *notebook; + GtkWidget *container; + GtkWidget *widget; + GtkWidget *page; + GtkWidget *hbox; + Context *context; + PangoAttribute *attr; + PangoAttrList *attr_list; + const gchar *extension_name; + const gchar *tab_label; + const gchar *uid; + + context = g_slice_new (Context); + uid = e_source_get_uid (scratch_source); + config = e_source_config_backend_get_config (backend); + + g_object_set_data_full ( + G_OBJECT (backend), uid, context, + (GDestroyNotify) book_config_ldap_context_free); + + e_book_source_config_add_offline_toggle ( + E_BOOK_SOURCE_CONFIG (config), scratch_source); + + container = e_source_config_get_page (config, scratch_source); + + /* Extra padding between the notebook and the options above. */ + widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 6, 0, 0, 0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_notebook_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + notebook = GTK_NOTEBOOK (widget); + + /* For bold section headers. */ + attr_list = pango_attr_list_new (); + attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); + pango_attr_list_insert (attr_list, attr); + + /* Page 1 */ + + tab_label = _("Connecting to LDAP"); + page = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + gtk_notebook_append_page (notebook, page, NULL); + gtk_notebook_set_tab_label_text (notebook, page, tab_label); + gtk_widget_show (page); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + /* Page 1 : Server Information */ + + widget = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new (_("Server Information")); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_attributes (GTK_LABEL (widget), attr_list); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_entry_new (); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Server:"), widget); + context->host_entry = g_object_ref (widget); + gtk_widget_show (widget); + + widget = book_config_build_port_combo (); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Port:"), widget); + context->port_combo = g_object_ref (widget); + gtk_widget_show (widget); + + /* This must follow the order of ESourceLDAPSecurity. */ + widget = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), + _("None")); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), + _("LDAP over SSL (deprecated)")); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), + _("StartTLS (recommended)")); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Encryption:"), widget); + context->security_combo = g_object_ref (widget); + gtk_widget_show (widget); + + g_object_bind_property_full ( + context->port_combo, "active", + context->security_combo, "active", + G_BINDING_DEFAULT, + book_config_ldap_port_to_security, + NULL, /* binding is one-way */ + NULL, (GDestroyNotify) NULL); + + /* If this is a new source, initialize security to StartTLS. */ + if (e_source_config_get_original_source (config) == NULL) + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2); + + /* Page 1 : Authentication */ + + widget = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new (_("Authentication")); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_attributes (GTK_LABEL (widget), attr_list); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + /* This must follow the order of ESourceLDAPAuthentication. */ + widget = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), + _("Anonymous")); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), + _("Using email address")); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), + _("Using distinguished name (DN)")); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Method:"), widget); + context->auth_combo = g_object_ref (widget); + gtk_widget_show (widget); + + gtk_widget_set_tooltip_text ( + widget, _("This is the method Evolution will use to " + "authenticate you. Note that setting this to \"Using " + "email address\" requires anonymous access to your LDAP " + "server.")); + + widget = gtk_entry_new (); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Username:"), widget); + context->auth_entry = g_object_ref (widget); + gtk_widget_show (widget); + + g_object_unref (size_group); + + /* Page 2 */ + + tab_label = _("Using LDAP"); + page = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + gtk_notebook_append_page (notebook, page, NULL); + gtk_notebook_set_tab_label_text (notebook, page, tab_label); + gtk_widget_show (page); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + /* Page 2 : Searching */ + + widget = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new (_("Searching")); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_attributes (GTK_LABEL (widget), attr_list); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_combo_box_new_with_entry (); + gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (widget), 0); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Search Base:"), widget); + context->search_base_combo = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_button_new_with_label ( + _("Find Possible Search Bases")); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_stock ( + GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON)); + book_config_ldap_insert_notebook_widget ( + container, size_group, NULL, widget); + context->search_base_button = g_object_ref (widget); + gtk_widget_show (widget); + + /* Only sensitive when we have complete + * server and authentication details. */ + g_object_bind_property ( + config, "complete", + context->search_base_button, "sensitive", + G_BINDING_DEFAULT); + + g_signal_connect_data ( + widget, "clicked", + G_CALLBACK (book_config_ldap_search_base_button_clicked_cb), + book_config_ldap_closure_new (backend, scratch_source), + (GClosureNotify) book_config_ldap_closure_free, 0); + + /* This must follow the order of ESourceLDAPScope. */ + widget = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), _("One Level")); + gtk_combo_box_text_append_text ( + GTK_COMBO_BOX_TEXT (widget), _("Subtree")); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Search Scope:"), widget); + context->search_scope_combo = g_object_ref (widget); + gtk_widget_show (widget); + + gtk_widget_set_tooltip_text ( + widget, _("The search scope defines how deep you would " + "like the search to extend down the directory tree. A " + "search scope of \"Subtree\" will include all entries " + "below your search base. A search scope of \"One Level\" " + "will only include the entries one level beneath your " + "search base.")); + + widget = gtk_entry_new (); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Search Filter:"), widget); + context->search_filter_entry = g_object_ref (widget); + gtk_widget_show (widget); + + /* Page 2 : Downloading */ + + widget = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new (_("Downloading")); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_label_set_attributes (GTK_LABEL (widget), attr_list); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_hbox_new (FALSE, 6); + book_config_ldap_insert_notebook_widget ( + container, size_group, _("Limit:"), widget); + gtk_widget_show (widget); + + hbox = widget; + + widget = gtk_spin_button_new_with_range (0, G_MAXUINT, 1); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (widget), TRUE); + gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); + context->limit_spinbutton = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (_("contacts")); + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = gtk_check_button_new_with_label ( + _("Browse until limit is reached")); + book_config_ldap_insert_notebook_widget ( + container, size_group, NULL, widget); + context->can_browse_toggle = g_object_ref (widget); + gtk_widget_show (widget); + + g_object_unref (size_group); + + pango_attr_list_unref (attr_list); + + /* Bind widgets to extension properties. */ + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + extension = e_source_get_extension (scratch_source, extension_name); + + g_object_bind_property ( + extension, "host", + context->host_entry, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property_full ( + extension, "port", + context->port_combo, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE, + book_config_ldap_port_to_active, + book_config_ldap_active_to_port, + NULL, (GDestroyNotify) NULL); + + g_object_bind_property ( + extension, "user", + context->auth_entry, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + extension_name = E_SOURCE_EXTENSION_LDAP_BACKEND; + extension = e_source_get_extension (scratch_source, extension_name); + + g_object_bind_property ( + extension, "authentication", + context->auth_combo, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + extension, "can-browse", + context->can_browse_toggle, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + extension, "limit", + context->limit_spinbutton, "value", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + widget = gtk_bin_get_child (GTK_BIN (context->search_base_combo)); + + g_object_bind_property ( + extension, "root-dn", + widget, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + extension, "scope", + context->search_scope_combo, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + extension, "filter", + context->search_filter_entry, "text", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + g_object_bind_property ( + extension, "security", + context->security_combo, "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); +} + +static gboolean +book_config_ldap_check_complete (ESourceConfigBackend *backend, + ESource *scratch_source) +{ + ESourceLDAPAuthentication auth; + ESourceExtension *extension; + const gchar *extension_name; + const gchar *host; + const gchar *user; + guint16 port; + + extension_name = E_SOURCE_EXTENSION_LDAP_BACKEND; + extension = e_source_get_extension (scratch_source, extension_name); + + auth = e_source_ldap_get_authentication (E_SOURCE_LDAP (extension)); + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + extension = e_source_get_extension (scratch_source, extension_name); + + host = e_source_authentication_get_host ( + E_SOURCE_AUTHENTICATION (extension)); + port = e_source_authentication_get_port ( + E_SOURCE_AUTHENTICATION (extension)); + user = e_source_authentication_get_user ( + E_SOURCE_AUTHENTICATION (extension)); + + if (host == NULL || *host == '\0' || port == 0) + return FALSE; + + if (auth != E_SOURCE_LDAP_AUTHENTICATION_NONE) + if (user == NULL || *user == '\0') + return FALSE; + + return TRUE; +} + +static void +e_book_config_ldap_class_init (ESourceConfigBackendClass *class) +{ + EExtensionClass *extension_class; + + extension_class = E_EXTENSION_CLASS (class); + extension_class->extensible_type = E_TYPE_BOOK_SOURCE_CONFIG; + + class->parent_uid = "ldap-stub"; + class->backend_name = "ldap"; + class->insert_widgets = book_config_ldap_insert_widgets; + class->check_complete = book_config_ldap_check_complete; +} + +static void +e_book_config_ldap_class_finalize (ESourceConfigBackendClass *class) +{ +} + +static void +e_book_config_ldap_init (ESourceConfigBackend *backend) +{ +} + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + e_source_ldap_type_register (type_module); + e_book_config_ldap_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} |