diff options
author | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2005-01-12 11:22:08 +0000 |
---|---|---|
committer | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2005-01-12 11:22:08 +0000 |
commit | b9ca7b1ef5cd1f96ae6e28ae78d12c1e3258c23f (patch) | |
tree | 1203adec5f70af1ddd49868528d8d3a5b9004329 /src/syldap.c |
Initial import of Sylpheed (GTK2 version).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src/syldap.c')
-rw-r--r-- | src/syldap.c | 1129 |
1 files changed, 1129 insertions, 0 deletions
diff --git a/src/syldap.c b/src/syldap.c new file mode 100644 index 00000000..2646dbf3 --- /dev/null +++ b/src/syldap.c @@ -0,0 +1,1129 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 2001 Match Grun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Functions necessary to access LDAP servers. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef USE_LDAP + +#include <glib.h> +#include <gdk/gdk.h> +#include <gtk/gtkmain.h> +#include <sys/time.h> +#include <string.h> +#include <ldap.h> +#include <lber.h> +#include <pthread.h> +/* #include <dlfcn.h> */ + +#include "mgutils.h" +#include "addritem.h" +#include "addrcache.h" +#include "syldap.h" +#include "utils.h" + +/* +* Create new LDAP server interface object. +*/ +SyldapServer *syldap_create() { + SyldapServer *ldapServer; + + debug_print("Creating LDAP server interface object\n"); + + ldapServer = g_new0( SyldapServer, 1 ); + ldapServer->name = NULL; + ldapServer->hostName = NULL; + ldapServer->port = SYLDAP_DFL_PORT; + ldapServer->baseDN = NULL; + ldapServer->bindDN = NULL; + ldapServer->bindPass = NULL; + ldapServer->searchCriteria = NULL; + ldapServer->searchValue = NULL; + ldapServer->entriesRead = 0; + ldapServer->maxEntries = SYLDAP_MAX_ENTRIES; + ldapServer->timeOut = SYLDAP_DFL_TIMEOUT; + ldapServer->newSearch = TRUE; + ldapServer->addressCache = addrcache_create(); + ldapServer->thread = NULL; + ldapServer->busyFlag = FALSE; + ldapServer->retVal = MGU_SUCCESS; + ldapServer->callBack = NULL; + ldapServer->accessFlag = FALSE; + ldapServer->idleId = 0; + return ldapServer; +} + +/* +* Specify name to be used. +*/ +void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) { + ldapServer->name = mgu_replace_string( ldapServer->name, value ); + g_strstrip( ldapServer->name ); +} + +/* +* Specify hostname to be used. +*/ +void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value ); + g_strstrip( ldapServer->hostName ); +} + +/* +* Specify port to be used. +*/ +void syldap_set_port( SyldapServer* ldapServer, const gint value ) { + addrcache_refresh( ldapServer->addressCache ); + if( value > 0 ) { + ldapServer->port = value; + } + else { + ldapServer->port = SYLDAP_DFL_PORT; + } +} + +/* +* Specify base DN to be used. +*/ +void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value ); + g_strstrip( ldapServer->baseDN ); +} + +/* +* Specify bind DN to be used. +*/ +void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value ); + g_strstrip( ldapServer->bindDN ); +} + +/* +* Specify bind password to be used. +*/ +void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value ); + g_strstrip( ldapServer->bindPass ); +} + +/* +* Specify search criteria to be used. +*/ +void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value ); + g_strstrip( ldapServer->searchCriteria ); + ldapServer->newSearch = TRUE; +} + +/* +* Specify search value to be searched for. +*/ +void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value ); + g_strstrip( ldapServer->searchValue ); + ldapServer->newSearch = TRUE; +} + +/* +* Specify maximum number of entries to retrieve. +*/ +void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) { + addrcache_refresh( ldapServer->addressCache ); + if( value > 0 ) { + ldapServer->maxEntries = value; + } + else { + ldapServer->maxEntries = SYLDAP_MAX_ENTRIES; + } +} + +/* +* Specify timeout value for LDAP operation (in seconds). +*/ +void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) { + addrcache_refresh( ldapServer->addressCache ); + if( value > 0 ) { + ldapServer->timeOut = value; + } + else { + ldapServer->timeOut = SYLDAP_DFL_TIMEOUT; + } +} + +/* +* Register a callback function. When called, the function will be passed +* this object as an argument. +*/ +void syldap_set_callback( SyldapServer *ldapServer, void *func ) { + ldapServer->callBack = func; +} + +void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) { + g_return_if_fail( ldapServer != NULL ); + ldapServer->accessFlag = value; +} + +/* +* Refresh internal variables to force a file read. +*/ +void syldap_force_refresh( SyldapServer *ldapServer ) { + addrcache_refresh( ldapServer->addressCache ); + ldapServer->newSearch = TRUE; +} + +gint syldap_get_status( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, -1 ); + return ldapServer->retVal; +} + +ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, NULL ); + return addrcache_get_root_folder( ldapServer->addressCache ); +} + +gchar *syldap_get_name( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, NULL ); + return ldapServer->name; +} + +gboolean syldap_get_accessed( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, FALSE ); + return ldapServer->accessFlag; +} + +/* +* Free up LDAP server interface object by releasing internal memory. +*/ +void syldap_free( SyldapServer *ldapServer ) { + g_return_if_fail( ldapServer != NULL ); + + debug_print("Freeing LDAP server interface object\n"); + + ldapServer->callBack = NULL; + + /* Free internal stuff */ + g_free( ldapServer->name ); + g_free( ldapServer->hostName ); + g_free( ldapServer->baseDN ); + g_free( ldapServer->bindDN ); + g_free( ldapServer->bindPass ); + g_free( ldapServer->searchCriteria ); + g_free( ldapServer->searchValue ); + g_free( ldapServer->thread ); + + ldapServer->port = 0; + ldapServer->entriesRead = 0; + ldapServer->maxEntries = 0; + ldapServer->newSearch = FALSE; + + /* Clear cache */ + addrcache_clear( ldapServer->addressCache ); + addrcache_free( ldapServer->addressCache ); + + /* Clear pointers */ + ldapServer->name = NULL; + ldapServer->hostName = NULL; + ldapServer->baseDN = NULL; + ldapServer->bindDN = NULL; + ldapServer->bindPass = NULL; + ldapServer->searchCriteria = NULL; + ldapServer->searchValue = NULL; + ldapServer->addressCache = NULL; + ldapServer->thread = NULL; + ldapServer->busyFlag = FALSE; + ldapServer->retVal = MGU_SUCCESS; + ldapServer->accessFlag = FALSE; + + /* Now release LDAP object */ + g_free( ldapServer ); + +} + +/* +* Display object to specified stream. +*/ +void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) { + g_return_if_fail( ldapServer != NULL ); + + fprintf( stream, "SyldapServer:\n" ); + fprintf( stream, " name: '%s'\n", ldapServer->name ); + fprintf( stream, "host name: '%s'\n", ldapServer->hostName ); + fprintf( stream, " port: %d\n", ldapServer->port ); + fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN ); + fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN ); + fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass ); + fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria ); + fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue ); + fprintf( stream, "max entry: %d\n", ldapServer->maxEntries ); + fprintf( stream, " num read: %d\n", ldapServer->entriesRead ); + fprintf( stream, " ret val: %d\n", ldapServer->retVal ); + addrcache_print( ldapServer->addressCache, stream ); + addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream ); +} + +/* +* Display object to specified stream. +*/ +void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) { + g_return_if_fail( ldapServer != NULL ); + + fprintf( stream, "SyldapServer:\n" ); + fprintf( stream, " name: '%s'\n", ldapServer->name ); + fprintf( stream, "host name: '%s'\n", ldapServer->hostName ); + fprintf( stream, " port: %d\n", ldapServer->port ); + fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN ); + fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN ); + fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass ); + fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria ); + fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue ); + fprintf( stream, "max entry: %d\n", ldapServer->maxEntries ); + fprintf( stream, " num read: %d\n", ldapServer->entriesRead ); + fprintf( stream, " ret val: %d\n", ldapServer->retVal ); +} + +#if 0 +/* +* Build an address list entry and append to list of address items. Name is formatted +* as it appears in the common name (cn) attribute. +*/ +static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) { + ItemPerson *person; + ItemEMail *email; + GSList *nodeName = listName; + + while( nodeName ) { + GSList *nodeAddress = listAddr; + person = addritem_create_item_person(); + addritem_person_set_common_name( person, nodeName->data ); + addrcache_id_person( ldapServer->addressCache, person ); + addrcache_add_person( ldapServer->addressCache, person ); + + while( nodeAddress ) { + email = addritem_create_item_email(); + addritem_email_set_address( email, nodeAddress->data ); + addrcache_id_email( ldapServer->addressCache, email ); + addrcache_person_add_email( ldapServer->addressCache, person, email ); + nodeAddress = g_slist_next( nodeAddress ); + ldapServer->entriesRead++; + } + nodeName = g_slist_next( nodeName ); + } +} +#endif + +/* +* Build an address list entry and append to list of address items. Name is formatted +* as "<first-name> <last-name>". +*/ +static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) { + GSList *nodeFirst = listFirst; + GSList *nodeAddress = listAddr; + gchar *firstName = NULL, *lastName = NULL, *fullName = NULL; + gint iLen = 0, iLenT = 0; + ItemPerson *person; + ItemEMail *email; + + /* Find longest first name in list */ + while( nodeFirst ) { + if( firstName == NULL ) { + firstName = nodeFirst->data; + iLen = strlen( firstName ); + } + else { + if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) { + firstName = nodeFirst->data; + iLen = iLenT; + } + } + nodeFirst = g_slist_next( nodeFirst ); + } + + /* Format name */ + if( listLast ) { + lastName = listLast->data; + } + + if( firstName ) { + if( lastName ) { + fullName = g_strdup_printf( "%s %s", firstName, lastName ); + } + else { + fullName = g_strdup_printf( "%s", firstName ); + } + } + else { + if( lastName ) { + fullName = g_strdup_printf( "%s", lastName ); + } + } + if( fullName ) { + g_strchug( fullName ); g_strchomp( fullName ); + } + + if( nodeAddress ) { + person = addritem_create_item_person(); + addritem_person_set_common_name( person, fullName ); + addritem_person_set_first_name( person, firstName ); + addritem_person_set_last_name( person, lastName ); + addrcache_id_person( ldapServer->addressCache, person ); + addrcache_add_person( ldapServer->addressCache, person ); + } + + /* Add address item */ + while( nodeAddress ) { + email = addritem_create_item_email(); + addritem_email_set_address( email, nodeAddress->data ); + addrcache_id_email( ldapServer->addressCache, email ); + addrcache_person_add_email( ldapServer->addressCache, person, email ); + nodeAddress = g_slist_next( nodeAddress ); + ldapServer->entriesRead++; + } + g_free( fullName ); + fullName = firstName = lastName = NULL; + +} + +/* +* Add all attribute values to a list. +*/ +static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) { + GSList *list = NULL; + gint i; + gchar **vals; + + if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) { + for( i = 0; vals[i] != NULL; i++ ) { + /* printf( "lv\t%s: %s\n", attr, vals[i] ); */ + list = g_slist_append( list, g_strdup( vals[i] ) ); + } + } + ldap_value_free( vals ); + return list; +} + +/* +* Add a single attribute value to a list. +*/ +static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) { + GSList *list = NULL; + gchar **vals; + + if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) { + if( vals[0] != NULL ) { + /* printf( "sv\t%s: %s\n", attr, vals[0] ); */ + list = g_slist_append( list, g_strdup( vals[0] ) ); + } + } + ldap_value_free( vals ); + return list; +} + +/* +* Free linked lists of character strings. +*/ +static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) { + mgu_free_list( listName ); + mgu_free_list( listAddr ); + mgu_free_list( listID ); + mgu_free_list( listDN ); + mgu_free_list( listFirst ); + mgu_free_list( listLast ); +} + +/* +* Check parameters that are required for a search. This should +* be called before performing a search. +* Return: TRUE if search criteria appear OK. +*/ +gboolean syldap_check_search( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, FALSE ); + + ldapServer->retVal = MGU_LDAP_CRITERIA; + + /* Test search criteria */ + if( ldapServer->searchCriteria == NULL ) { + return FALSE; + } + if( strlen( ldapServer->searchCriteria ) < 1 ) { + return FALSE; + } + + if( ldapServer->searchValue == NULL ) { + return FALSE; + } + if( strlen( ldapServer->searchValue ) < 1 ) { + return FALSE; + } + + ldapServer->retVal = MGU_SUCCESS; + return TRUE; +} + +/* +* Perform the LDAP search, reading LDAP entries into cache. +* Note that one LDAP entry can have multiple values for many of its +* attributes. If these attributes are E-Mail addresses; these are +* broken out into separate address items. For any other attribute, +* only the first occurrence is read. +*/ +gint syldap_search( SyldapServer *ldapServer ) { + LDAP *ld; + LDAPMessage *result, *e; + char *attribs[10]; + char *attribute; + gchar *criteria; + BerElement *ber; + gint rc; + GSList *listName = NULL, *listAddress = NULL, *listID = NULL; + GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL; + struct timeval timeout; + gboolean entriesFound = FALSE; + + g_return_val_if_fail( ldapServer != NULL, -1 ); + + ldapServer->retVal = MGU_SUCCESS; + if( ! syldap_check_search( ldapServer ) ) { + return ldapServer->retVal; + } + + /* Set timeout */ + timeout.tv_sec = ldapServer->timeOut; + timeout.tv_usec = 0L; + + ldapServer->entriesRead = 0; + if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) { + ldapServer->retVal = MGU_LDAP_INIT; + return ldapServer->retVal; + } + + /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */ + + /* Bind to the server, if required */ + if( ldapServer->bindDN ) { + if( * ldapServer->bindDN != '\0' ) { + /* printf( "binding...\n" ); */ + rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass ); + /* printf( "rc=%d\n", rc ); */ + if( rc != LDAP_SUCCESS ) { + /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */ + ldap_unbind( ld ); + ldapServer->retVal = MGU_LDAP_BIND; + return ldapServer->retVal; + } + } + } + + /* Define all attributes we are interested in. */ + attribs[0] = SYLDAP_ATTR_DN; + attribs[1] = SYLDAP_ATTR_COMMONNAME; + attribs[2] = SYLDAP_ATTR_GIVENNAME; + attribs[3] = SYLDAP_ATTR_SURNAME; + attribs[4] = SYLDAP_ATTR_EMAIL; + attribs[5] = SYLDAP_ATTR_UID; + attribs[6] = NULL; + + /* Create LDAP search string and apply search criteria */ + criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue ); + rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL, + &timeout, 0, &result ); + g_free( criteria ); + criteria = NULL; + if( rc == LDAP_TIMEOUT ) { + ldap_unbind( ld ); + ldapServer->retVal = MGU_LDAP_TIMEOUT; + return ldapServer->retVal; + } + if( rc != LDAP_SUCCESS ) { + /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */ + ldap_unbind( ld ); + ldapServer->retVal = MGU_LDAP_SEARCH; + return ldapServer->retVal; + } + + /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */ + + /* Clear the cache if we have new entries, otherwise leave untouched. */ + if( ldap_count_entries( ld, result ) > 0 ) { + addrcache_clear( ldapServer->addressCache ); + } + + /* Process results */ + ldapServer->entriesRead = 0; + for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { + entriesFound = TRUE; + if( ldapServer->entriesRead >= ldapServer->maxEntries ) break; + /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */ + + /* Process all attributes */ + for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL; + attribute = ldap_next_attribute( ld, e, ber ) ) { + if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) { + listName = syldap_add_list_values( ld, e, attribute ); + } + if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) { + listAddress = syldap_add_list_values( ld, e, attribute ); + } + if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) { + listID = syldap_add_single_value( ld, e, attribute ); + } + if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) { + listFirst = syldap_add_list_values( ld, e, attribute ); + } + if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) { + listLast = syldap_add_single_value( ld, e, attribute ); + } + if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) { + listDN = syldap_add_single_value( ld, e, attribute ); + } + } + + /* Free memory used to store attribute */ + ldap_memfree( attribute ); + + /* Format and add items to cache */ + syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast ); + + /* Free up */ + syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast ); + listName = listAddress = listID = listFirst = listLast = listDN = NULL; + + if( ber != NULL ) { + ber_free( ber, 0 ); + } + } + + syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast ); + listName = listAddress = listID = listFirst = listLast = listDN = NULL; + + /* Free up and disconnect */ + ldap_msgfree( result ); + ldap_unbind( ld ); + ldapServer->newSearch = FALSE; + if( entriesFound ) { + ldapServer->retVal = MGU_SUCCESS; + } + else { + ldapServer->retVal = MGU_LDAP_NOENTRIES; + } + return ldapServer->retVal; +} + +/* syldap_display_search_results() - updates the ui. this function is called from the + * main thread (the thread running the GTK event loop). */ +static gint syldap_display_search_results(SyldapServer *ldapServer) +{ + /* NOTE: when this function is called the accompanying thread should + * already be terminated. */ + gtk_idle_remove(ldapServer->idleId); + ldapServer->callBack(ldapServer); + /* FIXME: match should know whether to free this SyldapServer stuff. */ + g_free(ldapServer->thread); + ldapServer->thread = NULL; + return TRUE; +} + +/* ============================================================================================ */ +/* +* Read data into list. Main entry point +* Return: TRUE if file read successfully. +*/ +/* ============================================================================================ */ +gint syldap_read_data( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, -1 ); + + ldapServer->accessFlag = FALSE; + pthread_detach( pthread_self() ); + if( ldapServer->newSearch ) { + /* Read data into the list */ + syldap_search( ldapServer ); + + /* Mark cache */ + ldapServer->addressCache->modified = FALSE; + ldapServer->addressCache->dataRead = TRUE; + ldapServer->accessFlag = FALSE; + } + + /* Callback */ + ldapServer->busyFlag = FALSE; + if( ldapServer->callBack ) { + /* make the ui thread update the search results */ + /* TODO: really necessary to call gdk_threads_XXX()??? gtk_idle_add() + * should do this - could someone check the GTK sources please? */ + gdk_threads_enter(); + ldapServer->idleId = gtk_idle_add((GtkFunction)syldap_display_search_results, ldapServer); + gdk_threads_leave(); + } + + return ldapServer->retVal; +} + +/* ============================================================================================ */ +/* +* Cancel read with thread. +*/ +/* ============================================================================================ */ +void syldap_cancel_read( SyldapServer *ldapServer ) { + g_return_if_fail( ldapServer != NULL ); + + /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */ + if( ldapServer->thread ) { + /* printf( "thread cancelled\n" ); */ + pthread_cancel( *ldapServer->thread ); + } + g_free(ldapServer->thread); + ldapServer->thread = NULL; + ldapServer->busyFlag = FALSE; +} + +/* ============================================================================================ */ +/* +* Read data into list using a background thread. +* Return: TRUE if file read successfully. Callback function will be +* notified when search is complete. +*/ +/* ============================================================================================ */ +gint syldap_read_data_th( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, -1 ); + + ldapServer->busyFlag = FALSE; + syldap_check_search( ldapServer ); + if( ldapServer->retVal == MGU_SUCCESS ) { + /* debug_print("Staring LDAP read thread\n"); */ + + ldapServer->busyFlag = TRUE; + ldapServer->thread = g_new0(pthread_t, 1); + pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer ); + } + return ldapServer->retVal; +} + +/* +* Return link list of persons. +*/ +GList *syldap_get_list_person( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, NULL ); + return addrcache_get_list_person( ldapServer->addressCache ); +} + +/* +* Return link list of folders. This is always NULL since there are +* no folders in GnomeCard. +* Return: NULL. +*/ +GList *syldap_get_list_folder( SyldapServer *ldapServer ) { + g_return_val_if_fail( ldapServer != NULL, NULL ); + return NULL; +} + +#define SYLDAP_TEST_FILTER "(objectclass=*)" +#define SYLDAP_SEARCHBASE_V2 "cn=config" +#define SYLDAP_SEARCHBASE_V3 "" +#define SYLDAP_V2_TEST_ATTR "database" +#define SYLDAP_V3_TEST_ATTR "namingcontexts" + +/* +* Attempt to discover the base DN for the server. +* Enter: +* host Host name +* port Port number +* bindDN Bind DN (optional). +* bindPW Bind PW (optional). +* tov Timeout value (seconds), or 0 for none, default 30 secs. +* Return: List of Base DN's, or NULL if could not read. Base DN should +* be g_free() when done. +*/ +GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) { + GList *baseDN = NULL; + LDAP *ld; + gint rc, i; + LDAPMessage *result, *e; + gchar *attribs[10]; + BerElement *ber; + gchar *attribute; + gchar **vals; + struct timeval timeout; + + if( host == NULL ) return baseDN; + if( port < 1 ) return baseDN; + + /* Set timeout */ + timeout.tv_usec = 0L; + if( tov > 0 ) { + timeout.tv_sec = tov; + } + else { + timeout.tv_sec = 30L; + } + + /* Connect to server. */ + if( ( ld = ldap_init( host, port ) ) == NULL ) { + return baseDN; + } + + /* Bind to the server, if required */ + if( bindDN ) { + if( *bindDN != '\0' ) { + rc = ldap_simple_bind_s( ld, bindDN, bindPW ); + if( rc != LDAP_SUCCESS ) { + /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */ + ldap_unbind( ld ); + return baseDN; + } + } + } + + /* Test for LDAP version 3 */ + attribs[0] = SYLDAP_V3_TEST_ATTR; + attribs[1] = NULL; + rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs, + 0, NULL, NULL, &timeout, 0, &result ); + if( rc == LDAP_SUCCESS ) { + /* Process entries */ + for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { + /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */ + + /* Process attributes */ + for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL; + attribute = ldap_next_attribute( ld, e, ber ) ) { + if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) { + if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) { + for( i = 0; vals[i] != NULL; i++ ) { + /* printf( "\t%s: %s\n", attribute, vals[i] ); */ + baseDN = g_list_append( baseDN, g_strdup( vals[i] ) ); + } + } + ldap_value_free( vals ); + } + } + ldap_memfree( attribute ); + if( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( result ); + } + else { + } + + if( baseDN == NULL ) { + /* Test for LDAP version 2 */ + attribs[0] = NULL; + rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs, + 0, NULL, NULL, &timeout, 0, &result ); + if( rc == LDAP_SUCCESS ) { + /* Process entries */ + for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { + /* if( baseDN ) break; */ + /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */ + + /* Process attributes */ + for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL; + attribute = ldap_next_attribute( ld, e, ber ) ) { + /* if( baseDN ) break; */ + if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) { + if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) { + for( i = 0; vals[i] != NULL; i++ ) { + char *ch; + /* Strip the 'ldb:' from the front of the value */ + ch = ( char * ) strchr( vals[i], ':' ); + if( ch ) { + gchar *bn = g_strdup( ++ch ); + g_strchomp( bn ); + g_strchug( bn ); + baseDN = g_list_append( baseDN, g_strdup( bn ) ); + } + } + } + ldap_value_free( vals ); + } + } + ldap_memfree( attribute ); + if( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( result ); + } + } + ldap_unbind( ld ); + return baseDN; +} + +/* +* Attempt to discover the base DN for the server. +* Enter: ldapServer Server to test. +* Return: List of Base DN's, or NULL if could not read. Base DN should +* be g_free() when done. Return code set in ldapServer. +*/ +GList *syldap_read_basedn( SyldapServer *ldapServer ) { + GList *baseDN = NULL; + LDAP *ld; + gint rc, i; + LDAPMessage *result, *e; + gchar *attribs[10]; + BerElement *ber; + gchar *attribute; + gchar **vals; + struct timeval timeout; + + ldapServer->retVal = MGU_BAD_ARGS; + if( ldapServer == NULL ) return baseDN; + if( ldapServer->hostName == NULL ) return baseDN; + if( ldapServer->port < 1 ) return baseDN; + + /* Set timeout */ + timeout.tv_usec = 0L; + if( ldapServer->timeOut > 0 ) { + timeout.tv_sec = ldapServer->timeOut; + } + else { + timeout.tv_sec = 30L; + } + + /* Connect to server. */ + if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) { + ldapServer->retVal = MGU_LDAP_INIT; + return baseDN; + } + + /* Bind to the server, if required */ + if( ldapServer->bindDN ) { + if( *ldapServer->bindDN != '\0' ) { + rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass ); + if( rc != LDAP_SUCCESS ) { + /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */ + ldap_unbind( ld ); + ldapServer->retVal = MGU_LDAP_BIND; + return baseDN; + } + } + } + + ldapServer->retVal = MGU_LDAP_SEARCH; + + /* Test for LDAP version 3 */ + attribs[0] = SYLDAP_V3_TEST_ATTR; + attribs[1] = NULL; + rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs, + 0, NULL, NULL, &timeout, 0, &result ); + if( rc == LDAP_SUCCESS ) { + /* Process entries */ + for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { + /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */ + + /* Process attributes */ + for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL; + attribute = ldap_next_attribute( ld, e, ber ) ) { + if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) { + if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) { + for( i = 0; vals[i] != NULL; i++ ) { + /* printf( "\t%s: %s\n", attribute, vals[i] ); */ + baseDN = g_list_append( baseDN, g_strdup( vals[i] ) ); + } + } + ldap_value_free( vals ); + } + } + ldap_memfree( attribute ); + if( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( result ); + ldapServer->retVal = MGU_SUCCESS; + } + else if( rc == LDAP_TIMEOUT ) { + ldapServer->retVal = MGU_LDAP_TIMEOUT; + } + + if( baseDN == NULL ) { + /* Test for LDAP version 2 */ + attribs[0] = NULL; + rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs, + 0, NULL, NULL, &timeout, 0, &result ); + if( rc == LDAP_SUCCESS ) { + /* Process entries */ + for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { + /* if( baseDN ) break; */ + /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */ + + /* Process attributes */ + for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL; + attribute = ldap_next_attribute( ld, e, ber ) ) { + /* if( baseDN ) break; */ + if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) { + if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) { + for( i = 0; vals[i] != NULL; i++ ) { + char *ch; + /* Strip the 'ldb:' from the front of the value */ + ch = ( char * ) strchr( vals[i], ':' ); + if( ch ) { + gchar *bn = g_strdup( ++ch ); + g_strchomp( bn ); + g_strchug( bn ); + baseDN = g_list_append( baseDN, g_strdup( bn ) ); + } + } + } + ldap_value_free( vals ); + } + } + ldap_memfree( attribute ); + if( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( result ); + ldapServer->retVal = MGU_SUCCESS; + } + else if( rc == LDAP_TIMEOUT ) { + ldapServer->retVal = MGU_LDAP_TIMEOUT; + } + } + ldap_unbind( ld ); + + return baseDN; +} + +/* +* Attempt to connect to the server. +* Enter: +* host Host name +* port Port number +* Return: TRUE if connected successfully. +*/ +gboolean syldap_test_connect_s( const gchar *host, const gint port ) { + gboolean retVal = FALSE; + LDAP *ld; + + if( host == NULL ) return retVal; + if( port < 1 ) return retVal; + if( ( ld = ldap_open( host, port ) ) != NULL ) { + retVal = TRUE; + } + if( ld != NULL ) { + ldap_unbind( ld ); + } + return retVal; +} + +/* +* Attempt to connect to the server. +* Enter: ldapServer Server to test. +* Return: TRUE if connected successfully. Return code set in ldapServer. +*/ +gboolean syldap_test_connect( SyldapServer *ldapServer ) { + gboolean retVal = FALSE; + LDAP *ld; + + ldapServer->retVal = MGU_BAD_ARGS; + if( ldapServer == NULL ) return retVal; + if( ldapServer->hostName == NULL ) return retVal; + if( ldapServer->port < 1 ) return retVal; + ldapServer->retVal = MGU_LDAP_INIT; + if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) { + ldapServer->retVal = MGU_SUCCESS; + retVal = TRUE; + } + if( ld != NULL ) { + ldap_unbind( ld ); + } + return retVal; +} + +#define LDAP_LINK_LIB_NAME_1 "libldap.so" +#define LDAP_LINK_LIB_NAME_2 "liblber.so" +#define LDAP_LINK_LIB_NAME_3 "libresolv.so" +#define LDAP_LINK_LIB_NAME_4 "libpthread.so" + +/* +* Test whether LDAP libraries installed. +* Return: TRUE if library available. +*/ +#if 0 +gboolean syldap_test_ldap_lib() { + void *handle, *fun; + + /* Get library */ + handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY ); + if( ! handle ) { + return FALSE; + } + + /* Test for symbols we need */ + fun = dlsym( handle, "ldap_init" ); + if( ! fun ) { + dlclose( handle ); + return FALSE; + } + dlclose( handle ); handle = NULL; fun = NULL; + + handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY ); + if( ! handle ) { + return FALSE; + } + fun = dlsym( handle, "ber_init" ); + if( ! fun ) { + dlclose( handle ); + return FALSE; + } + dlclose( handle ); handle = NULL; fun = NULL; + + handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY ); + if( ! handle ) { + return FALSE; + } + fun = dlsym( handle, "res_query" ); + if( ! fun ) { + dlclose( handle ); + return FALSE; + } + dlclose( handle ); handle = NULL; fun = NULL; + + handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY ); + if( ! handle ) { + return FALSE; + } + fun = dlsym( handle, "pthread_create" ); + if( ! fun ) { + dlclose( handle ); + return FALSE; + } + dlclose( handle ); handle = NULL; fun = NULL; + + return TRUE; +} +#endif /* 0 */ + +#endif /* USE_LDAP */ + +/* +* End of Source. +*/ |