Add an ESource extension for the ldap backend.
authorMatthew Barnes <mbarnes@redhat.com>
Fri, 19 Nov 2010 23:22:54 +0000 (18:22 -0500)
committerMatthew Barnes <mbarnes@redhat.com>
Sun, 3 Jun 2012 23:51:08 +0000 (19:51 -0400)
addressbook/backends/ldap/Makefile.am
addressbook/backends/ldap/e-book-backend-ldap-factory.c
addressbook/backends/ldap/e-book-backend-ldap.c
addressbook/backends/ldap/e-source-ldap.c [new file with mode: 0644]
addressbook/backends/ldap/e-source-ldap.h [new file with mode: 0644]
libedataserver/e-system-source.c [deleted file]
libedataserver/e-system-source.h [deleted file]

index 05ea08f..28aab52 100644 (file)
@@ -15,7 +15,9 @@ libebookbackendldap_la_CPPFLAGS = \
 libebookbackendldap_la_SOURCES =                       \
        e-book-backend-ldap.c                           \
        e-book-backend-ldap.h                           \
-       e-book-backend-ldap-factory.c
+       e-book-backend-ldap-factory.c                   \
+       e-source-ldap.c                                 \
+       e-source-ldap.h
 
 libebookbackendldap_la_LIBADD =                                                \
        $(top_builddir)/addressbook/libebook/libebook-1.2.la            \
index 69d99b0..0620043 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <libedata-book/e-book-backend-factory.h>
 #include "e-book-backend-ldap.h"
+#include "e-source-ldap.h"
 
 #define FACTORY_NAME "ldap"
 
@@ -65,6 +66,7 @@ e_book_backend_ldap_factory_init (EBookBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+       e_source_ldap_type_register (type_module);
        e_book_backend_ldap_factory_register_type (type_module);
 }
 
index bcacebd..46fdf18 100644 (file)
 
 #include <glib/gi18n-lib.h>
 #include <libedataserver/e-sexp.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-offline.h>
 #include <libebook/e-contact.h>
 
 #include <libedata-book/e-book-backend-sexp.h>
 #include <libedata-book/e-book-backend-cache.h>
 #include <libedata-book/e-book-backend-summary.h>
 #include "e-book-backend-ldap.h"
+#include "e-source-ldap.h"
 
 /* this is broken currently, don't enable it */
 /*#define ENABLE_SASL_BINDS*/
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_BOOK_BACKEND_LDAP, EBookBackendLDAPPrivate))
 
-typedef enum {
-       E_BOOK_BACKEND_LDAP_TLS_NO,
-       E_BOOK_BACKEND_LDAP_TLS_ALWAYS,
-       E_BOOK_BACKEND_LDAP_TLS_WHEN_POSSIBLE
-} EBookBackendLDAPUseTLS;
-
 /* interval for our poll_ldap timeout */
 #define LDAP_POLL_INTERVAL 20
 
@@ -177,7 +174,17 @@ typedef struct LDAPOp LDAPOp;
 #define EDB_ERROR_NOT_CONNECTED() e_data_book_create_error (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Not connected"))
 #define EDB_ERROR_MSG_TYPE(_msg_type) e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_INVALID_ARG, "Incorrect msg type %d passed to %s", _msg_type, G_STRFUNC)
 
-G_DEFINE_TYPE (EBookBackendLDAP, e_book_backend_ldap, E_TYPE_BOOK_BACKEND)
+/* Forward Declarations */
+static void    e_book_backend_ldap_source_authenticator_init
+                               (ESourceAuthenticatorInterface *interface);
+
+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))
 
 struct _EBookBackendLDAPPrivate {
        gboolean connected;
@@ -199,7 +206,7 @@ struct _EBookBackendLDAPPrivate {
        gboolean starttls;     /* TRUE if the *library * supports
                                   starttls.  will be false if openssl
                                   was not built into openldap. */
-       EBookBackendLDAPUseTLS use_tls;
+       ESourceLDAPSecurity security;
 
        LDAP     *ldap;
 
@@ -441,20 +448,18 @@ static struct prop_info {
 static gboolean
 can_browse (EBookBackend *backend)
 {
-       ESource *source = NULL;
-       const gchar *can_browse;
+       ESource *source;
+       ESourceLDAP *extension;
+       const gchar *extension_name;
 
-       /* XXX Backend can really be NULL here, or
-        *     are we just being needlessly paranoid? */
-       if (backend == NULL)
+       if (E_IS_BOOK_BACKEND (backend))
                return FALSE;
 
        source = e_backend_get_source (E_BACKEND (backend));
-       g_return_val_if_fail (source != NULL, FALSE);
+       extension_name = E_SOURCE_EXTENSION_LDAP_BACKEND;
+       extension = e_source_get_extension (source, extension_name);
 
-       can_browse = e_source_get_property (source, "can-browse");
-
-       return (g_strcmp0 (can_browse, "1") == 0);
+       return e_source_ldap_get_can_browse (extension);
 }
 
 static gboolean
@@ -857,7 +862,7 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
        }
 
 #ifdef SUNLDAP
-       if (bl->priv->use_tls != E_BOOK_BACKEND_LDAP_TLS_NO) {
+       if (bl->priv->security == E_SOURCE_LDAP_SECURITY_LDAPS) {
                const gchar *user_data_dir = e_get_user_data_dir ();
                ldap_flag = ldapssl_client_init (user_data_dir, NULL);
                blpriv->ldap = ldapssl_init (blpriv->ldap_host, blpriv->ldap_port, 1);
@@ -883,22 +888,20 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                } else
                        bl->priv->ldap_v3 = TRUE;
 
-               if (bl->priv->use_tls != E_BOOK_BACKEND_LDAP_TLS_NO) {
-
-                       if (!bl->priv->ldap_v3 && bl->priv->use_tls == E_BOOK_BACKEND_LDAP_TLS_ALWAYS) {
-                               g_message ("TLS not available (fatal version), v3 protocol could not be established (ldap_error 0x%02x)", ldap_error);
-                               ldap_unbind (blpriv->ldap);
-                               blpriv->ldap = NULL;
-                               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-                               g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE));
-                               return FALSE;
-                       }
+               if (!bl->priv->ldap_v3 && bl->priv->security == E_SOURCE_LDAP_SECURITY_STARTTLS) {
+                       g_message ("TLS not available (fatal version), v3 protocol could not be established (ldap_error 0x%02x)", ldap_error);
+                       ldap_unbind (blpriv->ldap);
+                       blpriv->ldap = NULL;
+                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+                       g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE));
+                       return FALSE;
+               }
 
-                       if (bl->priv->ldap_port == LDAPS_PORT && bl->priv->use_tls == E_BOOK_BACKEND_LDAP_TLS_ALWAYS) {
+               if (bl->priv->ldap_port == LDAPS_PORT && bl->priv->security == E_SOURCE_LDAP_SECURITY_LDAPS) {
 #ifdef SUNLDAP
-                               if (ldap_error == LDAP_SUCCESS) {
-                                       ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON );
-                               }
+                       if (ldap_error == LDAP_SUCCESS) {
+                               ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON );
+                       }
 #else
 #if defined (LDAP_OPT_X_TLS_HARD) && defined (LDAP_OPT_X_TLS)
                                gint tls_level = LDAP_OPT_X_TLS_HARD;
@@ -908,46 +911,41 @@ e_book_backend_ldap_connect (EBookBackendLDAP *bl,
                                tls_level = LDAP_OPT_X_TLS_ALLOW;
                                ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &tls_level);
 #elif defined (G_OS_WIN32)
-                               ldap_set_option (blpriv->ldap, LDAP_OPT_SSL, LDAP_OPT_ON);
+                       ldap_set_option (blpriv->ldap, LDAP_OPT_SSL, LDAP_OPT_ON);
 #else
-                               g_message ("TLS option not available");
+                       g_message ("TLS option not available");
 #endif
 #endif
-                       } else if (bl->priv->use_tls) {
+               } else if (bl->priv->security == E_SOURCE_LDAP_SECURITY_STARTTLS) {
 #ifdef SUNLDAP
-                               if (ldap_error == LDAP_SUCCESS) {
-                                       ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON );
-                               }
+                       if (ldap_error == LDAP_SUCCESS) {
+                               ldap_set_option (blpriv->ldap, LDAP_OPT_RECONNECT, LDAP_OPT_ON );
+                       }
 #else
 #ifdef _WIN32
-                               typedef ULONG (*PFN_ldap_start_tls_s)(PLDAP,PLDAPControl *,PLDAPControl *);
-                               PFN_ldap_start_tls_s pldap_start_tls_s =
-                               (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_s");
-                               if (!pldap_start_tls_s)
-                                       (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_sA");
-
-                               if (!pldap_start_tls_s)
-                                       ldap_error = LDAP_NOT_SUPPORTED;
-                               else
-                                       ldap_error = pldap_start_tls_s (blpriv->ldap, NULL, NULL);
+                       typedef ULONG (*PFN_ldap_start_tls_s)(PLDAP,PLDAPControl *,PLDAPControl *);
+                       PFN_ldap_start_tls_s pldap_start_tls_s =
+                       (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_s");
+                       if (!pldap_start_tls_s)
+                               (PFN_ldap_start_tls_s) GetProcAddress (GetModuleHandle ("wldap32.dll"), "ldap_start_tls_sA");
+
+                       if (!pldap_start_tls_s)
+                               ldap_error = LDAP_NOT_SUPPORTED;
+                       else
+                               ldap_error = pldap_start_tls_s (blpriv->ldap, NULL, NULL);
 #else /* !defined(_WIN32) */
-                               ldap_error = ldap_start_tls_s (blpriv->ldap, NULL, NULL);
+                       ldap_error = ldap_start_tls_s (blpriv->ldap, NULL, NULL);
 #endif /* _WIN32 */
 #endif
-                               if (ldap_error != LDAP_SUCCESS) {
-                                       if (bl->priv->use_tls == E_BOOK_BACKEND_LDAP_TLS_ALWAYS) {
-                                               g_message ("TLS not available (fatal version), (ldap_error 0x%02x)", ldap_error);
-                                               ldap_unbind (blpriv->ldap);
-                                               blpriv->ldap = NULL;
-                                               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-                                               g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE));
-                                               return FALSE;
-                                       } else {
-                                               g_message ("TLS not available (ldap_error 0x%02x)", ldap_error);
-                                       }
-                               } else if (enable_debug)
-                                       g_message ("TLS active");
-                       }
+                       if (ldap_error != LDAP_SUCCESS) {
+                               g_message ("TLS not available (fatal version), (ldap_error 0x%02x)", ldap_error);
+                               ldap_unbind (blpriv->ldap);
+                               blpriv->ldap = NULL;
+                               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+                               g_propagate_error (error, EDB_ERROR (TLS_NOT_AVAILABLE));
+                               return FALSE;
+                       } else if (enable_debug)
+                               g_message ("TLS active");
                }
 
                /* bind anonymously initially, we'll actually
@@ -5128,188 +5126,6 @@ generate_cache (EBookBackendLDAP *book_backend_ldap)
 }
 
 static void
-e_book_backend_ldap_authenticate_user (EBookBackend *backend,
-                                       GCancellable *cancellable,
-                                       ECredentials *credentials)
-{
-       EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
-       gint ldap_error;
-       gchar *dn = NULL;
-       const gchar *auth_method = e_credentials_peek (credentials, E_CREDENTIALS_KEY_AUTH_METHOD);
-       const gchar *user = e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME);
-
-       if (enable_debug)
-               printf ("e_book_backend_ldap_authenticate_user ... \n");
-
-       g_static_rec_mutex_lock (&eds_ldap_handler_lock);
-       if (!auth_method || !*auth_method) {
-               ESource *source;
-
-               source = e_backend_get_source (E_BACKEND (backend));
-               auth_method = e_source_get_property (source, "auth");
-       }
-
-       if (!e_backend_get_online (E_BACKEND (backend))) {
-               e_book_backend_notify_readonly (backend, TRUE);
-               e_book_backend_notify_online (backend, FALSE);
-               e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
-               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-               return;
-       }
-
-       if (bl->priv->connected) {
-               /* other client connected meanwhile, report success and return */
-               e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
-               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-               return;
-       }
-       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-
-       if (!g_ascii_strncasecmp (auth_method, LDAP_SIMPLE_PREFIX, strlen (LDAP_SIMPLE_PREFIX))) {
-
-               if (bl->priv->ldap && !strcmp (auth_method, "ldap/simple-email")) {
-                       LDAPMessage    *res, *e;
-                       gchar *query = g_strdup_printf ("(mail=%s)", user);
-
-                       g_static_rec_mutex_lock (&eds_ldap_handler_lock);
-                       ldap_error = ldap_search_s (bl->priv->ldap,
-                                                   bl->priv->ldap_rootdn,
-                                                   bl->priv->ldap_scope,
-                                                   query,
-                                                   NULL, 0, &res);
-                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-                       g_free (query);
-
-                       if (ldap_error == LDAP_SUCCESS) {
-                               gchar *entry_dn;
-
-                               g_static_rec_mutex_lock (&eds_ldap_handler_lock);
-                               e = ldap_first_entry (bl->priv->ldap, res);
-                               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-                               if (!e) {
-                                       g_warning ("Failed to get the DN for %s", user);
-                                       ldap_msgfree (res);
-                                       e_book_backend_notify_opened (backend, EDB_ERROR (AUTHENTICATION_FAILED));
-                                       return;
-                               }
-
-                               g_static_rec_mutex_lock (&eds_ldap_handler_lock);
-                               entry_dn = ldap_get_dn (bl->priv->ldap, e);
-                               bl->priv->connected = FALSE; /* to reconnect with credentials */
-                               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-                               dn = g_strdup (entry_dn);
-
-                               ldap_memfree (entry_dn);
-                               ldap_msgfree (res);
-                       } else {
-                               e_book_backend_notify_opened (backend, EDB_ERROR (PERMISSION_DENIED));
-                               return;
-                       }
-               }
-               else if (!g_strcmp0 (auth_method, "ldap/simple-binddn")) {
-                       dn = g_strdup (user);
-               }
-
-               g_free (bl->priv->auth_dn);
-               e_credentials_util_safe_free_string (bl->priv->auth_secret);
-
-               bl->priv->auth_dn = dn;
-               bl->priv->auth_secret = e_credentials_get (credentials, E_CREDENTIALS_KEY_PASSWORD);
-
-               /* now authenticate against the DN we were either supplied or queried for */
-               if (enable_debug)
-                       printf ("simple auth as %s\n", dn);
-               g_static_rec_mutex_lock (&eds_ldap_handler_lock);
-               if (!bl->priv->connected || !bl->priv->ldap) {
-                       GError *error = NULL;
-
-                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-
-                       if (!e_book_backend_ldap_connect (bl, &error)) {
-                               if (error)
-                                       e_book_backend_notify_opened (backend, error);
-                               return;
-                       }
-               }
-
-               ldap_error = ldap_simple_bind_s (bl->priv->ldap,
-                                               bl->priv->auth_dn,
-                                               bl->priv->auth_secret);
-               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-               /* Some ldap servers are returning (ex active directory ones) LDAP_SERVER_DOWN
-                * when we try to do an ldap operation  after being  idle
-                * for some time. This error is handled by poll_ldap in case of search operations
-                * We need to handle it explicitly for this bind call. We call reconnect so that
-                * we get a fresh ldap handle Fixes #67541 */
-
-               if (ldap_error == LDAP_SERVER_DOWN) {
-                       if (e_book_backend_ldap_reconnect (bl, find_book_view (bl), ldap_error)) {
-                               ldap_error = LDAP_SUCCESS;
-                       }
-
-               }
-
-               e_book_backend_notify_opened (backend, ldap_error_to_response (ldap_error));
-       }
-#ifdef ENABLE_SASL_BINDS
-       else if (!g_ascii_strncasecmp (auth_method, SASL_PREFIX, strlen (SASL_PREFIX))) {
-               g_print ("sasl bind (mech = %s) as %s", auth_method + strlen (SASL_PREFIX), user);
-               g_static_rec_mutex_lock (&eds_ldap_handler_lock);
-               if (!bl->priv->connected || !bl->priv->ldap) {
-                       GError *error = NULL;
-
-                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-
-                       if (!e_book_backend_ldap_connect (bl)) {
-                               if (error)
-                                       e_book_backend_notify_opened (backend, error);
-                               return;
-                       }
-               }
-               ldap_error = ldap_sasl_bind_s (bl->priv->ldap,
-                                              NULL,
-                                              auth_method + strlen (SASL_PREFIX),
-                                              e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD),
-                                              NULL,
-                                              NULL,
-                                              NULL);
-               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
-
-               if (ldap_error == LDAP_NOT_SUPPORTED)
-                       e_book_backend_notify_opened (backend, EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD));
-               else
-                       e_book_backend_notify_opened (backend, ldap_error_to_response (ldap_error));
-       }
-#endif
-       else {
-               e_book_backend_notify_opened (backend, EDB_ERROR (UNSUPPORTED_AUTHENTICATION_METHOD));
-               return;
-       }
-
-       if (ldap_error == LDAP_SUCCESS) {
-               e_book_backend_notify_readonly (backend, FALSE);
-
-               /* force a requery on the root dse since some ldap
-                * servers are set up such that they don't report
-                * anything (including the schema DN) until the user
-                * is authenticated */
-               if (!bl->priv->evolutionPersonChecked) {
-                       ldap_error = query_ldap_root_dse (bl);
-
-                       if (LDAP_SUCCESS == ldap_error) {
-                               if (!bl->priv->evolutionPersonChecked)
-                                       check_schema_support (bl);
-                       }
-                       else
-                               g_warning ("Failed to perform root dse query after authenticating, (ldap_error 0x%02x)", ldap_error);
-               }
-
-               if (bl->priv->marked_for_offline && bl->priv->cache)
-                       generate_cache (bl);
-       }
-}
-
-static void
 ldap_cancel_op (gpointer key,
                 gpointer value,
                 gpointer data)
@@ -5342,78 +5158,68 @@ e_book_backend_ldap_open (EBookBackend *backend,
                           gboolean only_if_exists)
 {
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
+       ESourceAuthentication *auth_extension;
+       ESourceLDAP *ldap_extension;
+       ESourceOffline *offline_extension;
+       ESourceRegistry *registry;
        ESource *source;
-       LDAPURLDesc    *lud;
-       gint ldap_error;
-       gint limit = 100;
-       gint timeout = 60; /* 1 minute */
-       gchar *uri;
+       const gchar *extension_name;
        const gchar *cache_dir;
-       const gchar *str;
-       const gchar *offline;
        gchar *filename;
-       GError *err = NULL;
        gboolean auth_required;
+       GError *error = NULL;
 
-       g_assert (bl->priv->connected == FALSE);
+       g_return_if_fail (!bl->priv->connected);
 
        if (enable_debug)
                printf ("%s ... \n", G_STRFUNC);
 
        source = e_backend_get_source (E_BACKEND (backend));
-       uri = e_source_get_uri (source);
        cache_dir = e_book_backend_get_cache_dir (backend);
 
-       offline = e_source_get_property (source, "offline_sync");
-       if (offline  &&   g_str_equal (offline, "1"))
-               bl->priv->marked_for_offline = TRUE;
-       str = e_source_get_property (source, "limit");
-       if (str)
-               limit = atoi (str);
+       registry = e_book_backend_get_registry (backend);
 
-       bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_NO;
+       extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+       auth_extension = e_source_get_extension (source, extension_name);
 
-       str = e_source_get_property (source, "ssl");
-       if (str) {
-               if (!strcmp (str, "always"))
-                       bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_ALWAYS;
-               else if (!strcmp (str, "whenever_possible"))
-                       bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_WHEN_POSSIBLE;
-               else if (strcmp (str, "never"))
-                       g_warning ("Unhandled value for 'ssl', not using it.");
-       }
+       extension_name = E_SOURCE_EXTENSION_LDAP_BACKEND;
+       ldap_extension = e_source_get_extension (source, extension_name);
 
-       str = e_source_get_property (source, "timeout");
-       if (str)
-               timeout = atoi (str);
+       extension_name = E_SOURCE_EXTENSION_OFFLINE;
+       offline_extension = e_source_get_extension (source, extension_name);
 
-       ldap_error = ldap_url_parse ((gchar *) uri, &lud);
+       bl->priv->marked_for_offline =
+               e_source_offline_get_stay_synchronized (offline_extension);
 
-       if (ldap_error == LDAP_SUCCESS) {
-               bl->priv->ldap_host = g_strdup (lud->lud_host);
-               bl->priv->ldap_port = lud->lud_port;
-               /* if a port wasn't specified, default to LDAP_PORT */
-               if (bl->priv->ldap_port == 0)
-                       bl->priv->ldap_port = LDAP_PORT;
-               bl->priv->ldap_rootdn = g_strdup (lud->lud_dn);
-               /* in case of migration, filter will be set to NULL and hence the search will fail */
-               if (lud->lud_filter)
-                       bl->priv->ldap_search_filter = g_strdup (lud->lud_filter);
-               bl->priv->ldap_limit = limit;
-               bl->priv->ldap_timeout = timeout;
-               bl->priv->ldap_scope = lud->lud_scope;
-
-               ldap_free_urldesc (lud);
-       } else {
-               if (enable_debug)
-                       printf ("%s ... failed to parse the ldap URI %s\n", G_STRFUNC, uri);
-               g_free (uri);
-               e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, "Failed to parse LDAP URI"));
-               return;
-       }
+       bl->priv->security = e_source_ldap_get_security (ldap_extension);
+
+       bl->priv->ldap_host =
+               e_source_authentication_dup_host (auth_extension);
 
-       if (bl->priv->ldap_port == LDAPS_PORT)
-               bl->priv->use_tls = E_BOOK_BACKEND_LDAP_TLS_ALWAYS;
+       bl->priv->ldap_port =
+               e_source_authentication_get_port (auth_extension);
+       /* If a port wasn't specified, default to LDAP_PORT. */
+       if (bl->priv->ldap_port == 0)
+               bl->priv->ldap_port = LDAP_PORT;
+
+       bl->priv->ldap_rootdn =
+               e_source_ldap_dup_root_dn (ldap_extension);
+
+       bl->priv->ldap_search_filter =
+               e_source_ldap_dup_filter (ldap_extension);
+
+       bl->priv->ldap_limit = e_source_ldap_get_limit (ldap_extension);
+
+       switch (e_source_ldap_get_scope (ldap_extension)) {
+               case E_SOURCE_LDAP_SCOPE_ONELEVEL:
+                       bl->priv->ldap_scope = LDAP_SCOPE_ONELEVEL;
+                       break;
+               case E_SOURCE_LDAP_SCOPE_SUBTREE:
+                       bl->priv->ldap_scope = LDAP_SCOPE_SUBTREE;
+                       break;
+               default:
+                       g_warn_if_reached ();
+       }
 
        if (bl->priv->cache) {
                g_object_unref (bl->priv->cache);
@@ -5424,66 +5230,48 @@ e_book_backend_ldap_open (EBookBackend *backend,
        bl->priv->cache = e_book_backend_cache_new (filename);
        g_free (filename);
 
-       g_free (uri);
-
        if (!e_backend_get_online (E_BACKEND (backend))) {
 
                /* Offline */
                e_book_backend_notify_readonly (backend, TRUE);
                e_book_backend_notify_online (backend, FALSE);
 
-               if (!bl->priv->marked_for_offline) {
-                       e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE));
-                       return;
-               }
+               if (!bl->priv->marked_for_offline)
+                       error = EDB_ERROR (OFFLINE_UNAVAILABLE);
 
-#if 0
-               if (!e_book_backend_cache_is_populated (bl->priv->cache)) {
-                       e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE));
-                       return;
-               }
-#endif
-               e_book_backend_respond_opened (backend, book, opid, NULL /* Success */);
+               e_book_backend_respond_opened (backend, book, opid, error);
                return;
-       } else {
-               e_book_backend_notify_readonly (backend, FALSE);
-               e_book_backend_notify_online (backend, TRUE);
        }
 
-       str = e_source_get_property (source, "auth");
-       auth_required = str && *str && !g_str_equal (str, "none") && !g_str_equal (str, "0");
-       if (auth_required && !g_str_equal (str, "ldap/simple-email")) {
-               /* Requires authentication, do not try to bind without it,
-                * but report success instead, as we are loaded. */
-               if (enable_debug)
-                       printf ("%s ... skipping anonymous bind, because auth required\n", G_STRFUNC);
+       e_book_backend_notify_readonly (backend, FALSE);
+       e_book_backend_notify_online (backend, TRUE);
 
-               if (!e_book_backend_is_opened (backend))
-                       e_book_backend_notify_auth_required (backend, TRUE, NULL);
-               else
-                       e_book_backend_notify_opened (backend, NULL);
-               e_data_book_respond_open (book, opid, NULL /* Success */);
-               return;
-       }
+       auth_required = e_source_authentication_required (auth_extension);
 
-       /* Online */
-       if (!e_book_backend_ldap_connect (bl, &err)) {
-               if (enable_debug)
-                       printf ("%s ... failed to connect to server \n", G_STRFUNC);
-               e_book_backend_respond_opened (backend, book, opid, err);
-               return;
-       }
+       if (!auth_required)
+               e_book_backend_ldap_connect (bl, &error);
 
-       if (auth_required && !e_book_backend_is_opened (backend)) {
-               e_book_backend_notify_auth_required (E_BOOK_BACKEND (bl), TRUE, NULL);
-               e_data_book_respond_open (book, opid, NULL /* Success */);
-               return;
+       if (g_error_matches (
+               error, E_DATA_BOOK_ERROR,
+               E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED)) {
+
+               g_clear_error (&error);
+               auth_required = TRUE;
        }
 
-       if (bl->priv->marked_for_offline)
+       if (auth_required && error == NULL)
+               e_source_registry_authenticate_sync (
+                       registry, source,
+                       E_SOURCE_AUTHENTICATOR (backend),
+                       cancellable, &error);
+
+       if (error != NULL && enable_debug)
+               printf ("%s ... failed to connect to server \n", G_STRFUNC);
+
+       if (error == NULL && bl->priv->marked_for_offline)
                generate_cache (bl);
 
-       e_book_backend_respond_opened (backend, book, opid, NULL /* Success */);
+       e_book_backend_respond_opened (backend, book, opid, error);
 }
 
 static void
@@ -5643,10 +5431,12 @@ e_book_backend_ldap_notify_online_cb (EBookBackend *backend,
                if (e_book_backend_is_opened (backend)) {
                        GError *error = NULL;
 
-                       if (e_book_backend_ldap_connect (bl, &error))
-                               e_book_backend_notify_auth_required (backend, TRUE, NULL);
+                       if (!e_book_backend_ldap_connect (bl, &error)) {
+                               e_book_backend_notify_error (
+                                       backend, error->message);
+                               g_error_free (error);
+                       }
 
-                       g_clear_error (&error);
 #if 0
                        start_views (backend);
 #endif
@@ -5725,6 +5515,226 @@ e_book_backend_ldap_finalize (GObject *object)
        G_OBJECT_CLASS (e_book_backend_ldap_parent_class)->finalize (object);
 }
 
+static ESourceAuthenticationResult
+book_backend_ldap_try_password_sync (ESourceAuthenticator *authenticator,
+                                     const GString *password,
+                                     GCancellable *cancellable,
+                                     GError **error)
+{
+       ESourceAuthenticationResult result;
+       EBookBackendLDAP *bl;
+       ESourceAuthentication *auth_extension;
+       ESource *source;
+       gint ldap_error;
+       gchar *dn = NULL;
+       const gchar *extension_name;
+       gchar *method;
+       gchar *user;
+
+       bl = E_BOOK_BACKEND_LDAP (authenticator);
+       source = e_backend_get_source (E_BACKEND (authenticator));
+
+       extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+       auth_extension = e_source_get_extension (source, extension_name);
+
+       /* We should not have gotten here if we're offline. */
+       g_return_val_if_fail (
+               e_backend_get_online (E_BACKEND (authenticator)),
+               E_SOURCE_AUTHENTICATION_ERROR);
+
+       method = e_source_authentication_dup_method (auth_extension);
+       user = e_source_authentication_dup_user (auth_extension);
+
+       if (!g_ascii_strncasecmp (method, LDAP_SIMPLE_PREFIX, strlen (LDAP_SIMPLE_PREFIX))) {
+
+               if (bl->priv->ldap && !strcmp (method, "ldap/simple-email")) {
+                       LDAPMessage    *res, *e;
+                       gchar *query = g_strdup_printf ("(mail=%s)", user);
+                       gchar *entry_dn;
+
+                       g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+                       ldap_error = ldap_search_s (bl->priv->ldap,
+                                                   bl->priv->ldap_rootdn,
+                                                   bl->priv->ldap_scope,
+                                                   query,
+                                                   NULL, 0, &res);
+                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+                       g_free (query);
+
+                       if (ldap_error != LDAP_SUCCESS)
+                               goto exit;
+
+                       g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+                       e = ldap_first_entry (bl->priv->ldap, res);
+                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+                       if (!e) {
+                               ldap_msgfree (res);
+                               g_set_error (
+                                       error, G_IO_ERROR,
+                                       G_IO_ERROR_INVALID_DATA,
+                                       _("Failed to get the DN "
+                                         "for user '%s'"), user);
+                               return E_SOURCE_AUTHENTICATION_ERROR;
+                       }
+
+                       g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+                       entry_dn = ldap_get_dn (bl->priv->ldap, e);
+                       bl->priv->connected = FALSE; /* to reconnect with credentials */
+                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+                       dn = g_strdup (entry_dn);
+
+                       ldap_memfree (entry_dn);
+                       ldap_msgfree (res);
+
+               } else if (!g_strcmp0 (method, "ldap/simple-binddn")) {
+                       dn = g_strdup (user);
+               }
+
+               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);
+
+               /* now authenticate against the DN we were either supplied or queried for */
+               if (enable_debug)
+                       printf ("simple auth as %s\n", dn);
+
+               g_static_rec_mutex_lock (&eds_ldap_handler_lock);
+
+               if (!bl->priv->connected || !bl->priv->ldap) {
+                       GError *local_error = NULL;
+
+                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+
+                       e_book_backend_ldap_connect (bl, &local_error);
+
+                       if (local_error == NULL) {
+                               return E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+                       } else if (g_error_matches (
+                               local_error, E_DATA_BOOK_ERROR,
+                               E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) {
+
+                               g_clear_error (&local_error);
+                               return E_SOURCE_AUTHENTICATION_REJECTED;
+
+                       } else {
+                               g_propagate_error (error, local_error);
+                               return E_SOURCE_AUTHENTICATION_ERROR;
+                       }
+               }
+
+               ldap_error = ldap_simple_bind_s (bl->priv->ldap,
+                                                bl->priv->auth_dn,
+                                                bl->priv->auth_secret);
+               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+
+               /* Some ldap servers are returning (ex active directory ones)
+                * LDAP_SERVER_DOWN when we try to do an ldap operation after
+                * being idle for some time. This error is handled by poll_ldap
+                * in case of search operations. 
+                *
+                * We need to handle it explicitly for this bind call.
+                * We call reconnect so that we get a fresh ldap handle.
+                * Fixes #67541 */
+               if (ldap_error == LDAP_SERVER_DOWN) {
+                       if (e_book_backend_ldap_reconnect (bl, find_book_view (bl), ldap_error))
+                               ldap_error = LDAP_SUCCESS;
+               }
+       }
+#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_static_rec_mutex_lock (&eds_ldap_handler_lock);
+
+               if (!bl->priv->connected || !bl->priv->ldap) {
+                       GError *local_error = NULL;
+
+                       g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+
+                       e_book_backend_ldap_connect (bl, &local_error);
+
+                       if (local_error == NULL) {
+                               return E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+                       } else if (g_error_matches (
+                               local_error, E_DATA_BOOK_ERROR,
+                               E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED)) {
+
+                               g_clear_error (&local_error);
+                               return E_SOURCE_AUTHENTICATION_REJECTED;
+
+                       } else {
+                               g_propagate_error (error, local_error);
+                               return E_SOURCE_AUTHENTICATION_ERROR;
+                       }
+               }
+
+               ldap_error = ldap_sasl_bind_s (bl->priv->ldap,
+                                              NULL,
+                                              method + strlen (SASL_PREFIX),
+                                              bl->priv->auth_secret,
+                                              NULL,
+                                              NULL,
+                                              NULL);
+               g_static_rec_mutex_unlock (&eds_ldap_handler_lock);
+       }
+#endif
+       else {
+               ldap_error = LDAP_NOT_SUPPORTED;
+       }
+
+exit:
+       switch (ldap_error) {
+               case LDAP_SUCCESS:
+                       e_book_backend_notify_readonly (
+                               E_BOOK_BACKEND (authenticator), FALSE);
+
+                       /* force a requery on the root dse since some ldap
+                        * servers are set up such that they don't report
+                        * anything (including the schema DN) until the user
+                        * is authenticated */
+                       if (!bl->priv->evolutionPersonChecked) {
+                               ldap_error = query_ldap_root_dse (bl);
+
+                               if (LDAP_SUCCESS == ldap_error) {
+                                       if (!bl->priv->evolutionPersonChecked)
+                                               check_schema_support (bl);
+                               } else
+                                       g_warning ("Failed to perform root dse query after authenticating, (ldap_error 0x%02x)", ldap_error);
+                       }
+
+                       if (bl->priv->marked_for_offline && bl->priv->cache)
+                               generate_cache (bl);
+
+                       result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+                       break;
+
+               case LDAP_INVALID_CREDENTIALS:
+                       result = E_SOURCE_AUTHENTICATION_REJECTED;
+                       break;
+
+               case LDAP_NOT_SUPPORTED:
+                       g_propagate_error (
+                               error, EDB_ERROR (
+                               UNSUPPORTED_AUTHENTICATION_METHOD));
+                       result = E_SOURCE_AUTHENTICATION_ERROR;
+                       break;
+
+               default:
+                       g_propagate_error (
+                               error, ldap_error_to_response (ldap_error));
+                       result = E_SOURCE_AUTHENTICATION_ERROR;
+                       break;
+       }
+
+       g_free (method);
+       g_free (user);
+
+       return result;
+}
+
 static void
 e_book_backend_ldap_class_init (EBookBackendLDAPClass *class)
 {
@@ -5752,9 +5762,17 @@ e_book_backend_ldap_class_init (EBookBackendLDAPClass *class)
        parent_class->get_contact_list_uids     = e_book_backend_ldap_get_contact_list_uids;
        parent_class->start_book_view           = e_book_backend_ldap_start_book_view;
        parent_class->stop_book_view            = e_book_backend_ldap_stop_book_view;
-       parent_class->authenticate_user         = e_book_backend_ldap_authenticate_user;
 
        object_class->finalize = e_book_backend_ldap_finalize;
+
+       /* Register our ESource extension. */
+       E_TYPE_SOURCE_LDAP;
+}
+
+static void
+e_book_backend_ldap_source_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+       interface->try_password_sync = book_backend_ldap_try_password_sync;
 }
 
 static void
diff --git a/addressbook/backends/ldap/e-source-ldap.c b/addressbook/backends/ldap/e-source-ldap.c
new file mode 100644 (file)
index 0000000..4e182dc
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * e-source-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 "e-source-ldap.h"
+
+#include <ldap.h>
+
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-security.h>
+
+#define E_SOURCE_LDAP_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), E_TYPE_SOURCE_LDAP, ESourceLDAPPrivate))
+
+struct _ESourceLDAPPrivate {
+       GMutex *property_lock;
+       gboolean can_browse;
+       gchar *filter;
+       guint limit;
+       gchar *root_dn;
+       ESourceLDAPScope scope;
+
+       /* These are bound to other extensions. */
+       ESourceLDAPAuthentication authentication;
+       ESourceLDAPSecurity security;
+};
+
+enum {
+       PROP_0,
+       PROP_AUTHENTICATION,
+       PROP_CAN_BROWSE,
+       PROP_FILTER,
+       PROP_LIMIT,
+       PROP_ROOT_DN,
+       PROP_SCOPE,
+       PROP_SECURITY
+};
+
+static GType e_source_ldap_authentication_type = G_TYPE_INVALID;
+static GType e_source_ldap_scope_type = G_TYPE_INVALID;
+static GType e_source_ldap_security_type = G_TYPE_INVALID;
+
+G_DEFINE_DYNAMIC_TYPE (
+       ESourceLDAP,
+       e_source_ldap,
+       E_TYPE_SOURCE_EXTENSION)
+
+static gboolean
+source_ldap_transform_enum_nick_to_value (GBinding *binding,
+                                          const GValue *source_value,
+                                          GValue *target_value,
+                                          gpointer not_used)
+{
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+       const gchar *string;
+       gboolean success = FALSE;
+
+       enum_class = g_type_class_peek (G_VALUE_TYPE (target_value));
+       g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
+
+       string = g_value_get_string (source_value);
+       enum_value = g_enum_get_value_by_nick (enum_class, string);
+       if (enum_value != NULL) {
+               g_value_set_enum (target_value, enum_value->value);
+               success = TRUE;
+       }
+
+       return success;
+}
+
+static gboolean
+source_ldap_transform_enum_value_to_nick (GBinding *binding,
+                                          const GValue *source_value,
+                                          GValue *target_value,
+                                          gpointer not_used)
+{
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+       gint value;
+       gboolean success = FALSE;
+
+       enum_class = g_type_class_peek (G_VALUE_TYPE (source_value));
+       g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
+
+       value = g_value_get_enum (source_value);
+       enum_value = g_enum_get_value (enum_class, value);
+       if (enum_value != NULL) {
+               g_value_set_string (target_value, enum_value->value_nick);
+               success = TRUE;
+       }
+
+       return success;
+}
+
+static void
+source_ldap_set_property (GObject *object,
+                          guint property_id,
+                          const GValue *value,
+                          GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_AUTHENTICATION:
+                       e_source_ldap_set_authentication (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_enum (value));
+                       return;
+
+               case PROP_CAN_BROWSE:
+                       e_source_ldap_set_can_browse (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_boolean (value));
+                       return;
+
+               case PROP_FILTER:
+                       e_source_ldap_set_filter (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_string (value));
+                       return;
+
+               case PROP_LIMIT:
+                       e_source_ldap_set_limit (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_uint (value));
+                       return;
+
+               case PROP_ROOT_DN:
+                       e_source_ldap_set_root_dn (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_string (value));
+                       return;
+
+               case PROP_SCOPE:
+                       e_source_ldap_set_scope (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_enum (value));
+                       return;
+
+               case PROP_SECURITY:
+                       e_source_ldap_set_security (
+                               E_SOURCE_LDAP (object),
+                               g_value_get_enum (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_ldap_get_property (GObject *object,
+                          guint property_id,
+                          GValue *value,
+                          GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_AUTHENTICATION:
+                       g_value_set_enum (
+                               value,
+                               e_source_ldap_get_authentication (
+                               E_SOURCE_LDAP (object)));
+                       return;
+
+               case PROP_CAN_BROWSE:
+                       g_value_set_boolean (
+                               value,
+                               e_source_ldap_get_can_browse (
+                               E_SOURCE_LDAP (object)));
+                       return;
+
+               case PROP_FILTER:
+                       g_value_take_string (
+                               value,
+                               e_source_ldap_dup_filter (
+                               E_SOURCE_LDAP (object)));
+                       return;
+
+               case PROP_LIMIT:
+                       g_value_set_uint (
+                               value,
+                               e_source_ldap_get_limit (
+                               E_SOURCE_LDAP (object)));
+                       return;
+
+               case PROP_ROOT_DN:
+                       g_value_take_string (
+                               value,
+                               e_source_ldap_dup_root_dn (
+                               E_SOURCE_LDAP (object)));
+                       return;
+
+               case PROP_SCOPE:
+                       g_value_set_enum (
+                               value,
+                               e_source_ldap_get_scope (
+                               E_SOURCE_LDAP (object)));
+                       return;
+
+               case PROP_SECURITY:
+                       g_value_set_enum (
+                               value,
+                               e_source_ldap_get_security (
+                               E_SOURCE_LDAP (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_ldap_finalize (GObject *object)
+{
+       ESourceLDAPPrivate *priv;
+
+       priv = E_SOURCE_LDAP_GET_PRIVATE (object);
+
+       g_mutex_free (priv->property_lock);
+
+       g_free (priv->filter);
+       g_free (priv->root_dn);
+
+       /* Chain up to parent's finalize() method. */
+       G_OBJECT_CLASS (e_source_ldap_parent_class)->finalize (object);
+}
+
+static void
+source_ldap_constructed (GObject *object)
+{
+       ESource *source;
+       ESourceExtension *this_extension;
+       ESourceExtension *other_extension;
+       const gchar *extension_name;
+
+       this_extension = E_SOURCE_EXTENSION (object);
+       source = e_source_extension_get_source (this_extension);
+
+       extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+       other_extension = e_source_get_extension (source, extension_name);
+
+       g_object_bind_property_full (
+               other_extension, "method",
+               this_extension, "authentication",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE,
+               source_ldap_transform_enum_nick_to_value,
+               source_ldap_transform_enum_value_to_nick,
+               NULL, (GDestroyNotify) NULL);
+
+       extension_name = E_SOURCE_EXTENSION_SECURITY;
+       other_extension = e_source_get_extension (source, extension_name);
+
+       g_object_bind_property_full (
+               other_extension, "method",
+               this_extension, "security",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE,
+               source_ldap_transform_enum_nick_to_value,
+               source_ldap_transform_enum_value_to_nick,
+               NULL, (GDestroyNotify) NULL);
+}
+
+static void
+e_source_ldap_class_init (ESourceLDAPClass *class)
+{
+       GObjectClass *object_class;
+       ESourceExtensionClass *extension_class;
+
+       g_type_class_add_private (class, sizeof (ESourceLDAPPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = source_ldap_set_property;
+       object_class->get_property = source_ldap_get_property;
+       object_class->finalize = source_ldap_finalize;
+       object_class->constructed = source_ldap_constructed;
+
+       extension_class = E_SOURCE_EXTENSION_CLASS (class);
+       extension_class->name = E_SOURCE_EXTENSION_LDAP_BACKEND;
+
+       /* This is bound to the authentication extension.
+        * Do not use E_SOURCE_PARAM_SETTING here. */
+       g_object_class_install_property (
+               object_class,
+               PROP_AUTHENTICATION,
+               g_param_spec_enum (
+                       "authentication",
+                       "Authentication",
+                       "LDAP authentication method",
+                       E_TYPE_SOURCE_LDAP_AUTHENTICATION,
+                       E_SOURCE_LDAP_AUTHENTICATION_NONE,
+                       G_PARAM_READWRITE));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_CAN_BROWSE,
+               g_param_spec_boolean (
+                       "can-browse",
+                       "Can Browse",
+                       "Allow browsing contacts",
+                       FALSE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_FILTER,
+               g_param_spec_string (
+                       "filter",
+                       "Filter",
+                       "LDAP search filter",
+                       "",
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_LIMIT,
+               g_param_spec_uint (
+                       "limit",
+                       "Limit",
+                       "Download limit",
+                       0, G_MAXUINT, 100,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_ROOT_DN,
+               g_param_spec_string (
+                       "root-dn",
+                       "Root DN",
+                       "LDAP search base",
+                       "",
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_SCOPE,
+               g_param_spec_enum (
+                       "scope",
+                       "Scope",
+                       "LDAP search scope",
+                       E_TYPE_SOURCE_LDAP_SCOPE,
+                       E_SOURCE_LDAP_SCOPE_ONELEVEL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       E_SOURCE_PARAM_SETTING));
+
+       /* This is bound to the security extension.
+        * Do not use E_SOURCE_PARAM_SETTING here. */
+       g_object_class_install_property (
+               object_class,
+               PROP_SECURITY,
+               g_param_spec_enum (
+                       "security",
+                       "Security",
+                       "LDAP security method",
+                       E_TYPE_SOURCE_LDAP_SECURITY,
+                       E_SOURCE_LDAP_SECURITY_NONE,
+                       G_PARAM_READWRITE));
+}
+
+static void
+e_source_ldap_class_finalize (ESourceLDAPClass *class)
+{
+}
+
+static void
+e_source_ldap_init (ESourceLDAP *extension)
+{
+       extension->priv = E_SOURCE_LDAP_GET_PRIVATE (extension);
+       extension->priv->property_lock = g_mutex_new ();
+}
+
+void
+e_source_ldap_type_register (GTypeModule *type_module)
+{
+       static const GEnumValue e_source_ldap_authentication_values[] = {
+               { E_SOURCE_LDAP_AUTHENTICATION_NONE,
+                 "E_SOURCE_LDAP_AUTHENTICATION_NONE",
+                 "none" },
+               { E_SOURCE_LDAP_AUTHENTICATION_EMAIL,
+                 "E_SOURCE_LDAP_AUTHENTICATION_EMAIL",
+                 "ldap/simple-email" },
+               { E_SOURCE_LDAP_AUTHENTICATION_BINDDN,
+                 "E_SOURCE_LDAP_AUTHENTICATION_BINDDN",
+                 "ldap/simple-binddn" },
+               { 0, NULL, NULL }
+       };
+
+       static const GEnumValue e_source_ldap_scope_values[] = {
+               { E_SOURCE_LDAP_SCOPE_ONELEVEL,
+                 "E_SOURCE_LDAP_SCOPE_ONELEVEL",
+                 "onelevel" },
+               { E_SOURCE_LDAP_SCOPE_SUBTREE,
+                 "E_SOURCE_LDAP_SCOPE_SUBTREE",
+                 "subtree" },
+               { 0, NULL, NULL }
+       };
+
+       static const GEnumValue e_source_ldap_security_values[] = {
+               { E_SOURCE_LDAP_SECURITY_NONE,
+                 "E_SOURCE_LDAP_SECURITY_NONE",
+                 "none" },
+               { E_SOURCE_LDAP_SECURITY_LDAPS,
+                 "E_SOURCE_LDAP_SECURITY_LDAPS",
+                 "ldaps" },
+               { E_SOURCE_LDAP_SECURITY_STARTTLS,
+                 "E_SOURCE_LDAP_SECURITY_STARTTLS",
+                 "starttls" },
+               { 0, NULL, NULL }
+       };
+
+       e_source_ldap_authentication_type =
+               g_type_module_register_enum (
+               type_module, "ESourceLDAPAuthentication",
+               e_source_ldap_authentication_values);
+
+       e_source_ldap_scope_type =
+               g_type_module_register_enum (
+               type_module, "ESourceLDAPScope",
+               e_source_ldap_scope_values);
+
+       e_source_ldap_security_type =
+               g_type_module_register_enum (
+               type_module, "ESourceLDAPSecurity",
+               e_source_ldap_security_values);
+
+       /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+        *     function, so we have to wrap it with a public function in
+        *     order to register types from a separate compilation unit. */
+       e_source_ldap_register_type (type_module);
+}
+
+ESourceLDAPAuthentication
+e_source_ldap_get_authentication (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
+
+       return extension->priv->authentication;
+}
+
+void
+e_source_ldap_set_authentication (ESourceLDAP *extension,
+                                  ESourceLDAPAuthentication authentication)
+{
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       extension->priv->authentication = authentication;
+
+       g_object_notify (G_OBJECT (extension), "authentication");
+}
+
+gboolean
+e_source_ldap_get_can_browse (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), FALSE);
+
+       return extension->priv->can_browse;
+}
+
+void
+e_source_ldap_set_can_browse (ESourceLDAP *extension,
+                              gboolean can_browse)
+{
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       extension->priv->can_browse = can_browse;
+
+       g_object_notify (G_OBJECT (extension), "can-browse");
+}
+
+const gchar *
+e_source_ldap_get_filter (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
+
+       return extension->priv->filter;
+}
+
+gchar *
+e_source_ldap_dup_filter (ESourceLDAP *extension)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
+
+       g_mutex_lock (extension->priv->property_lock);
+
+       protected = e_source_ldap_get_filter (extension);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (extension->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+e_source_ldap_set_filter (ESourceLDAP *extension,
+                          const gchar *filter)
+{
+       gboolean needs_parens;
+
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       needs_parens =
+               (filter != NULL) && (*filter != '\0') &&
+               !g_str_has_prefix (filter, "(") &&
+               !g_str_has_suffix (filter, ")");
+
+       g_mutex_lock (extension->priv->property_lock);
+
+       g_free (extension->priv->filter);
+       if (needs_parens)
+               extension->priv->filter = g_strdup_printf ("(%s)", filter);
+       else
+               extension->priv->filter = g_strdup (filter);
+
+       g_mutex_unlock (extension->priv->property_lock);
+
+       g_object_notify (G_OBJECT (extension), "filter");
+}
+
+guint
+e_source_ldap_get_limit (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
+
+       return extension->priv->limit;
+}
+
+void
+e_source_ldap_set_limit (ESourceLDAP *extension,
+                         guint limit)
+{
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       extension->priv->limit = limit;
+
+       g_object_notify (G_OBJECT (extension), "limit");
+}
+
+const gchar *
+e_source_ldap_get_root_dn (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
+
+       return extension->priv->root_dn;
+}
+
+gchar *
+e_source_ldap_dup_root_dn (ESourceLDAP *extension)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
+
+       g_mutex_lock (extension->priv->property_lock);
+
+       protected = e_source_ldap_get_root_dn (extension);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (extension->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+e_source_ldap_set_root_dn (ESourceLDAP *extension,
+                           const gchar *root_dn)
+{
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       g_mutex_lock (extension->priv->property_lock);
+
+       g_free (extension->priv->root_dn);
+       extension->priv->root_dn = e_util_strdup_strip (root_dn);
+
+       g_mutex_unlock (extension->priv->property_lock);
+
+       g_object_notify (G_OBJECT (extension), "root-dn");
+}
+
+ESourceLDAPScope
+e_source_ldap_get_scope (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
+
+       return extension->priv->scope;
+}
+
+void
+e_source_ldap_set_scope (ESourceLDAP *extension,
+                         ESourceLDAPScope scope)
+{
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       extension->priv->scope = scope;
+
+       g_object_notify (G_OBJECT (extension), "scope");
+}
+
+ESourceLDAPSecurity
+e_source_ldap_get_security (ESourceLDAP *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
+
+       return extension->priv->security;
+}
+
+void
+e_source_ldap_set_security (ESourceLDAP *extension,
+                            ESourceLDAPSecurity security)
+{
+       g_return_if_fail (E_IS_SOURCE_LDAP (extension));
+
+       extension->priv->security = security;
+
+       g_object_notify (G_OBJECT (extension), "security");
+}
+
+GType
+e_source_ldap_authentication_get_type (void)
+{
+       return e_source_ldap_authentication_type;
+}
+
+GType
+e_source_ldap_scope_get_type (void)
+{
+       return e_source_ldap_scope_type;
+}
+
+GType
+e_source_ldap_security_get_type (void)
+{
+       return e_source_ldap_security_type;
+}
diff --git a/addressbook/backends/ldap/e-source-ldap.h b/addressbook/backends/ldap/e-source-ldap.h
new file mode 100644 (file)
index 0000000..ea9cb9f
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * e-source-ldap.h
+ *
+ * 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/>
+ *
+ */
+
+#ifndef E_SOURCE_LDAP_H
+#define E_SOURCE_LDAP_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_LDAP \
+       (e_source_ldap_get_type ())
+#define E_SOURCE_LDAP(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SOURCE_LDAP, ESourceLDAP))
+#define E_SOURCE_LDAP_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SOURCE_LDAP, ESourceLDAPClass))
+#define E_IS_SOURCE_LDAP(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SOURCE_LDAP))
+#define E_IS_SOURCE_LDAP_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SOURCE_LDAP))
+#define E_SOURCE_LDAP_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SOURCE_LDAP, ESourceLDAPClass))
+
+#define E_TYPE_SOURCE_LDAP_AUTHENTICATION \
+       (e_source_ldap_authentication_get_type ())
+
+#define E_TYPE_SOURCE_LDAP_SCOPE \
+       (e_source_ldap_scope_get_type ())
+
+#define E_TYPE_SOURCE_LDAP_SECURITY \
+       (e_source_ldap_security_get_type ())
+
+#define E_SOURCE_EXTENSION_LDAP_BACKEND "LDAP Backend"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceLDAP ESourceLDAP;
+typedef struct _ESourceLDAPClass ESourceLDAPClass;
+typedef struct _ESourceLDAPPrivate ESourceLDAPPrivate;
+
+struct _ESourceLDAP {
+       ESourceExtension parent;
+       ESourceLDAPPrivate *priv;
+};
+
+struct _ESourceLDAPClass {
+       ESourceExtensionClass parent_class;
+};
+
+typedef enum {
+       E_SOURCE_LDAP_AUTHENTICATION_NONE,
+       E_SOURCE_LDAP_AUTHENTICATION_EMAIL,
+       E_SOURCE_LDAP_AUTHENTICATION_BINDDN
+} ESourceLDAPAuthentication;
+
+typedef enum {
+       E_SOURCE_LDAP_SCOPE_ONELEVEL,
+       E_SOURCE_LDAP_SCOPE_SUBTREE
+} ESourceLDAPScope;
+
+typedef enum {
+       E_SOURCE_LDAP_SECURITY_NONE,
+       E_SOURCE_LDAP_SECURITY_LDAPS,
+       E_SOURCE_LDAP_SECURITY_STARTTLS
+} ESourceLDAPSecurity;
+
+GType          e_source_ldap_get_type          (void);
+void           e_source_ldap_type_register     (GTypeModule *type_module);
+ESourceLDAPAuthentication
+               e_source_ldap_get_authentication
+                                               (ESourceLDAP *extension);
+void           e_source_ldap_set_authentication
+                                               (ESourceLDAP *extension,
+                                                ESourceLDAPAuthentication authentication);
+gboolean       e_source_ldap_get_can_browse    (ESourceLDAP *extension);
+void           e_source_ldap_set_can_browse    (ESourceLDAP *extension,
+                                                gboolean can_browse);
+const gchar *  e_source_ldap_get_filter        (ESourceLDAP *extension);
+gchar *                e_source_ldap_dup_filter        (ESourceLDAP *extension);
+void           e_source_ldap_set_filter        (ESourceLDAP *extension,
+                                                const gchar *filter);
+guint          e_source_ldap_get_limit         (ESourceLDAP *extension);
+void           e_source_ldap_set_limit         (ESourceLDAP *extension,
+                                                guint limit);
+const gchar *  e_source_ldap_get_root_dn       (ESourceLDAP *extension);
+gchar *                e_source_ldap_dup_root_dn       (ESourceLDAP *extension);
+void           e_source_ldap_set_root_dn       (ESourceLDAP *extension,
+                                                const gchar *root_dn);
+ESourceLDAPScope
+               e_source_ldap_get_scope         (ESourceLDAP *extension);
+void           e_source_ldap_set_scope         (ESourceLDAP *extension,
+                                                ESourceLDAPScope scope);
+ESourceLDAPSecurity
+               e_source_ldap_get_security      (ESourceLDAP *extension);
+void           e_source_ldap_set_security      (ESourceLDAP *extension,
+                                                ESourceLDAPSecurity security);
+
+GType          e_source_ldap_authentication_get_type   (void);
+GType          e_source_ldap_scope_get_type            (void);
+GType          e_source_ldap_security_get_type         (void);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_LDAP_H */
diff --git a/libedataserver/e-system-source.c b/libedataserver/e-system-source.c
deleted file mode 100644 (file)
index 12a7d1a..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * e-system-source.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 "e-system-source.h"
-
-#include <config.h>
-#include <glib/gi18n-lib.h>
-
-#include "e-data-server-util.h"
-
-G_DEFINE_TYPE (
-       ESystemSource,
-       e_system_source,
-       E_TYPE_SOURCE)
-
-static void
-system_source_notify (GObject *object,
-                      GParamSpec *pspec)
-{
-       ESource *source = E_SOURCE (object);
-
-       /* GObject does not allow subclasses to override property flags,
-        * so we'll keep the "backend-name" and "display-name" properties
-        * fixed by intercepting attempts to change them and setting them
-        * back to their proper values.  Hokey but works. */
-
-       if (g_strcmp0 (pspec->name, "backend-name") == 0) {
-               if (e_source_get_backend_name (source) != NULL) {
-                       e_source_set_backend_name (source, NULL);
-                       return;
-               }
-       }
-
-       if (g_strcmp0 (pspec->name, "display-name") == 0) {
-               const gchar *display_name;
-               const gchar *proper_value;
-
-               display_name = e_source_get_display_name (source);
-               proper_value = _("Personal");
-
-               if (g_strcmp0 (display_name, proper_value) != 0) {
-                       e_source_set_display_name (source, proper_value);
-                       return;
-               }
-       }
-
-       /* Chain up to parent's notify() method. */
-       G_OBJECT_CLASS (e_system_source_parent_class)->notify (object, pspec);
-}
-
-static void
-e_system_source_class_init (ESystemSourceClass *class)
-{
-       GObjectClass *object_class;
-
-       object_class = G_OBJECT_CLASS (class);
-       object_class->notify = system_source_notify;
-}
-
-static void
-e_system_source_init (ESystemSource *source)
-{
-}
-
-ESource *
-e_system_source_new (void)
-{
-       GSettings *settings;
-       ESource *source;
-       GFile *file;
-       const gchar *data_dir;
-       gchar *path;
-
-       data_dir = e_get_user_data_dir ();
-       path = g_build_filename (data_dir, "sources", "system", NULL);
-       file = g_file_new_for_path (path);
-       g_free (path);
-
-       /* This function must not fail, so if a "system" key file
-        * exists and fails to load, delete it and try again. */
-       source = g_initable_new (
-               E_TYPE_SYSTEM_SOURCE, NULL, NULL, "file", file, NULL);
-       if (source == NULL) {
-               g_file_delete (file, NULL, NULL);
-               source = g_initable_new (
-                       E_TYPE_SYSTEM_SOURCE, NULL, NULL, "file", file, NULL);
-       }
-
-       g_object_unref (file);
-
-       g_return_val_if_fail (E_IS_SYSTEM_SOURCE (source), NULL);
-
-       /* Set the "parent" key directly through its GSettings.
-        *
-        * XXX To set this during object construction we would have
-        *     to override the GInitable interface.  Too much hassle
-        *     for now.  Maybe revisit this in the future. */
-       settings = e_source_get_settings (source);
-       g_settings_set_string (settings, "parent", "local");
-
-       return source;
-}
diff --git a/libedataserver/e-system-source.h b/libedataserver/e-system-source.h
deleted file mode 100644 (file)
index 959a8f2..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * e-system-source.h
- *
- * 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/>
- *
- */
-
-#ifndef E_SYSTEM_SOURCE_H
-#define E_SYSTEM_SOURCE_H
-
-#include <libedataserver/e-source.h>
-
-/* Standard GObject macros */
-#define E_TYPE_SYSTEM_SOURCE \
-       (e_system_source_get_type ())
-#define E_SYSTEM_SOURCE(obj) \
-       (G_TYPE_CHECK_INSTANCE_CAST \
-       ((obj), E_TYPE_SYSTEM_SOURCE, ESystemSource))
-#define E_SYSTEM_SOURCE_CLASS(cls) \
-       (G_TYPE_CHECK_CLASS_CAST \
-       ((cls), E_TYPE_SYSTEM_SOURCE, ESystemSourceClass))
-#define E_IS_SYSTEM_SOURCE(obj) \
-       (G_TYPE_CHECK_INSTANCE_TYPE \
-       ((obj), E_TYPE_SYSTEM_SOURCE))
-#define E_IS_SYSTEM_SOURCE_CLASS(cls) \
-       (G_TYPE_CHECK_CLASS_TYPE \
-       ((cls), E_TYPE_SYSTEM_SOURCE))
-#define E_SYSTEM_SOURCE_GET_CLASS(obj) \
-       (G_TYPE_INSTANCE_GET_CLASS \
-       ((obj), E_TYPE_SOURCE, ESystemSourceClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ESystemSource ESystemSource;
-typedef struct _ESystemSourceClass ESystemSourceClass;
-typedef struct _ESystemSourcePrivate ESystemSourcePrivate;
-
-struct _ESystemSource {
-       ESource parent;
-       ESystemSourcePrivate *priv;
-};
-
-struct _ESystemSourceClass {
-       ESourceClass parent_class;
-};
-
-GType          e_system_source_get_type        (void) G_GNUC_CONST;
-ESource *      e_system_source_new             (void);
-
-G_END_DECLS
-
-#endif /* E_SYSTEM_SOURCE_H */