This commit was manufactured by cvs2svn to create tag 'LAST_STABLE'.
[claws.git] / src / syldap.c
blobbf7711ae1c920c1546d706f851db2ae76eb84f03
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2002 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Functions necessary to access LDAP servers.
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #ifdef USE_LDAP
30 #include <glib.h>
31 #include <gdk/gdk.h>
32 #include <gtk/gtkmain.h>
33 #include <sys/time.h>
34 #include <string.h>
35 #include <ldap.h>
36 #include <lber.h>
37 #include <pthread.h>
39 #include "mgutils.h"
40 #include "addritem.h"
41 #include "addrcache.h"
42 #include "syldap.h"
43 #include "utils.h"
44 #include "adbookbase.h"
47 * Create new LDAP server interface object.
49 SyldapServer *syldap_create() {
50 SyldapServer *ldapServer;
52 debug_print("Creating LDAP server interface object\n");
54 ldapServer = g_new0( SyldapServer, 1 );
55 ldapServer->type = ADBOOKTYPE_LDAP;
56 ldapServer->addressCache = addrcache_create();
57 ldapServer->retVal = MGU_SUCCESS;
58 ldapServer->hostName = NULL;
59 ldapServer->port = SYLDAP_DFL_PORT;
60 ldapServer->baseDN = NULL;
61 ldapServer->bindDN = NULL;
62 ldapServer->bindPass = NULL;
63 ldapServer->searchCriteria = NULL;
64 ldapServer->searchValue = NULL;
65 ldapServer->entriesRead = 0;
66 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
67 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
68 ldapServer->newSearch = TRUE;
69 ldapServer->thread = NULL;
70 ldapServer->busyFlag = FALSE;
71 ldapServer->callBack = NULL;
72 ldapServer->idleId = 0;
73 return ldapServer;
77 * Specify name to be used.
79 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
80 g_return_if_fail( ldapServer != NULL );
81 addrcache_set_name( ldapServer->addressCache, value );
85 * Specify hostname to be used.
87 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
88 addrcache_refresh( ldapServer->addressCache );
89 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
90 g_strstrip( ldapServer->hostName );
94 * Specify port to be used.
96 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
97 addrcache_refresh( ldapServer->addressCache );
98 if( value > 0 ) {
99 ldapServer->port = value;
101 else {
102 ldapServer->port = SYLDAP_DFL_PORT;
107 * Specify base DN to be used.
109 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
110 addrcache_refresh( ldapServer->addressCache );
111 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
112 g_strstrip( ldapServer->baseDN );
116 * Specify bind DN to be used.
118 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
119 addrcache_refresh( ldapServer->addressCache );
120 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
121 g_strstrip( ldapServer->bindDN );
125 * Specify bind password to be used.
127 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
128 addrcache_refresh( ldapServer->addressCache );
129 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
130 g_strstrip( ldapServer->bindPass );
134 * Specify search criteria to be used.
136 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
137 addrcache_refresh( ldapServer->addressCache );
138 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
139 g_strstrip( ldapServer->searchCriteria );
140 ldapServer->newSearch = TRUE;
144 * Specify search value to be searched for.
146 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
147 addrcache_refresh( ldapServer->addressCache );
148 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
149 g_strstrip( ldapServer->searchValue );
150 ldapServer->newSearch = TRUE;
154 * Specify maximum number of entries to retrieve.
156 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
157 addrcache_refresh( ldapServer->addressCache );
158 if( value > 0 ) {
159 ldapServer->maxEntries = value;
161 else {
162 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
167 * Specify timeout value for LDAP operation (in seconds).
169 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
170 addrcache_refresh( ldapServer->addressCache );
171 if( value > 0 ) {
172 ldapServer->timeOut = value;
174 else {
175 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
180 * Register a callback function. When called, the function will be passed
181 * this object as an argument.
183 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
184 ldapServer->callBack = func;
188 * Refresh internal variables to force a file read.
190 void syldap_force_refresh( SyldapServer *ldapServer ) {
191 addrcache_refresh( ldapServer->addressCache );
192 ldapServer->newSearch = TRUE;
195 gint syldap_get_status( SyldapServer *ldapServer ) {
196 g_return_val_if_fail( ldapServer != NULL, -1 );
197 return ldapServer->retVal;
200 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
201 g_return_val_if_fail( ldapServer != NULL, NULL );
202 return addrcache_get_root_folder( ldapServer->addressCache );
205 gchar *syldap_get_name( SyldapServer *ldapServer ) {
206 g_return_val_if_fail( ldapServer != NULL, NULL );
207 return addrcache_get_name( ldapServer->addressCache );
210 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
211 g_return_val_if_fail( ldapServer != NULL, FALSE );
212 return ldapServer->addressCache->accessFlag;
215 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
216 g_return_if_fail( ldapServer != NULL );
217 ldapServer->addressCache->accessFlag = value;
220 gboolean syldap_get_modified( SyldapServer *ldapServer ) {
221 g_return_val_if_fail( ldapServer != NULL, FALSE );
222 return ldapServer->addressCache->modified;
225 void syldap_set_modified( SyldapServer *ldapServer, const gboolean value ) {
226 g_return_if_fail( ldapServer != NULL );
227 ldapServer->addressCache->modified = value;
231 * Free up LDAP server interface object by releasing internal memory.
233 void syldap_free( SyldapServer *ldapServer ) {
234 g_return_if_fail( ldapServer != NULL );
236 debug_print("Freeing LDAP server interface object\n");
238 ldapServer->callBack = NULL;
240 /* Clear cache */
241 addrcache_clear( ldapServer->addressCache );
242 addrcache_free( ldapServer->addressCache );
244 /* Free internal stuff */
245 g_free( ldapServer->hostName );
246 g_free( ldapServer->baseDN );
247 g_free( ldapServer->bindDN );
248 g_free( ldapServer->bindPass );
249 g_free( ldapServer->searchCriteria );
250 g_free( ldapServer->searchValue );
251 g_free( ldapServer->thread );
254 /* Clear pointers */
255 ldapServer->hostName = NULL;
256 ldapServer->port = 0;
257 ldapServer->baseDN = NULL;
258 ldapServer->bindDN = NULL;
259 ldapServer->bindPass = NULL;
260 ldapServer->searchCriteria = NULL;
261 ldapServer->searchValue = NULL;
262 ldapServer->entriesRead = 0;
263 ldapServer->maxEntries = 0;
264 ldapServer->timeOut = 0;
265 ldapServer->newSearch = FALSE;
266 ldapServer->thread = NULL;
267 ldapServer->busyFlag = FALSE;
268 ldapServer->callBack = NULL;
269 ldapServer->idleId = 0;
271 ldapServer->type = ADBOOKTYPE_NONE;
272 ldapServer->addressCache = NULL;
273 ldapServer->retVal = MGU_SUCCESS;
275 /* Now release LDAP object */
276 g_free( ldapServer );
280 * Display object to specified stream.
282 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
283 g_return_if_fail( ldapServer != NULL );
285 fprintf( stream, "SyldapServer:\n" );
286 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
287 fprintf( stream, " port: %d\n", ldapServer->port );
288 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
289 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
290 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
291 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
292 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
293 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
294 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
295 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
296 addrcache_print( ldapServer->addressCache, stream );
297 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
301 * Display object to specified stream.
303 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
304 g_return_if_fail( ldapServer != NULL );
306 fprintf( stream, "SyldapServer:\n" );
307 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
308 fprintf( stream, " port: %d\n", ldapServer->port );
309 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
310 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
311 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
312 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
313 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
314 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
315 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
316 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
320 * Build an address list entry and append to list of address items. Name is formatted
321 * as it appears in the common name (cn) attribute.
323 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
324 ItemPerson *person;
325 ItemEMail *email;
326 GSList *nodeName = listName;
328 while( nodeName ) {
329 GSList *nodeAddress = listAddr;
330 person = addritem_create_item_person();
331 addritem_person_set_common_name( person, nodeName->data );
332 addrcache_id_person( ldapServer->addressCache, person );
333 addrcache_add_person( ldapServer->addressCache, person );
335 while( nodeAddress ) {
336 email = addritem_create_item_email();
337 addritem_email_set_address( email, nodeAddress->data );
338 addrcache_id_email( ldapServer->addressCache, email );
339 addrcache_person_add_email( ldapServer->addressCache, person, email );
340 nodeAddress = g_slist_next( nodeAddress );
341 ldapServer->entriesRead++;
343 nodeName = g_slist_next( nodeName );
348 * Build an address list entry and append to list of address items. Name is formatted
349 * as "<first-name> <last-name>".
351 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
352 GSList *nodeFirst = listFirst;
353 GSList *nodeAddress = listAddr;
354 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
355 gint iLen = 0, iLenT = 0;
356 ItemPerson *person;
357 ItemEMail *email;
359 /* Find longest first name in list */
360 while( nodeFirst ) {
361 if( firstName == NULL ) {
362 firstName = nodeFirst->data;
363 iLen = strlen( firstName );
365 else {
366 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
367 firstName = nodeFirst->data;
368 iLen = iLenT;
371 nodeFirst = g_slist_next( nodeFirst );
374 /* Format name */
375 if( listLast ) {
376 lastName = listLast->data;
379 if( firstName ) {
380 if( lastName ) {
381 fullName = g_strdup_printf( "%s %s", firstName, lastName );
383 else {
384 fullName = g_strdup_printf( "%s", firstName );
387 else {
388 if( lastName ) {
389 fullName = g_strdup_printf( "%s", lastName );
392 if( fullName ) {
393 g_strchug( fullName ); g_strchomp( fullName );
396 if( nodeAddress ) {
397 person = addritem_create_item_person();
398 addritem_person_set_common_name( person, fullName );
399 addritem_person_set_first_name( person, firstName );
400 addritem_person_set_last_name( person, lastName );
401 addrcache_id_person( ldapServer->addressCache, person );
402 addrcache_add_person( ldapServer->addressCache, person );
405 /* Add address item */
406 while( nodeAddress ) {
407 email = addritem_create_item_email();
408 addritem_email_set_address( email, nodeAddress->data );
409 addrcache_id_email( ldapServer->addressCache, email );
410 addrcache_person_add_email( ldapServer->addressCache, person, email );
411 nodeAddress = g_slist_next( nodeAddress );
412 ldapServer->entriesRead++;
414 g_free( fullName );
415 fullName = firstName = lastName = NULL;
420 * Add all attribute values to a list.
422 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
423 GSList *list = NULL;
424 gint i;
425 gchar **vals;
427 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
428 for( i = 0; vals[i] != NULL; i++ ) {
429 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
430 list = g_slist_append( list, g_strdup( vals[i] ) );
433 ldap_value_free( vals );
434 return list;
438 * Add a single attribute value to a list.
440 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
441 GSList *list = NULL;
442 gchar **vals;
444 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
445 if( vals[0] != NULL ) {
446 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
447 list = g_slist_append( list, g_strdup( vals[0] ) );
450 ldap_value_free( vals );
451 return list;
455 * Free linked lists of character strings.
457 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
458 mgu_free_list( listName );
459 mgu_free_list( listAddr );
460 mgu_free_list( listID );
461 mgu_free_list( listDN );
462 mgu_free_list( listFirst );
463 mgu_free_list( listLast );
467 * Check parameters that are required for a search. This should
468 * be called before performing a search.
469 * Return: TRUE if search criteria appear OK.
471 gboolean syldap_check_search( SyldapServer *ldapServer ) {
472 g_return_val_if_fail( ldapServer != NULL, FALSE );
474 ldapServer->retVal = MGU_LDAP_CRITERIA;
476 /* Test search criteria */
477 if( ldapServer->searchCriteria == NULL ) {
478 return FALSE;
480 if( strlen( ldapServer->searchCriteria ) < 1 ) {
481 return FALSE;
484 if( ldapServer->searchValue == NULL ) {
485 return FALSE;
487 if( strlen( ldapServer->searchValue ) < 1 ) {
488 return FALSE;
491 ldapServer->retVal = MGU_SUCCESS;
492 return TRUE;
496 * Perform the LDAP search, reading LDAP entries into cache.
497 * Note that one LDAP entry can have multiple values for many of its
498 * attributes. If these attributes are E-Mail addresses; these are
499 * broken out into separate address items. For any other attribute,
500 * only the first occurrence is read.
502 gint syldap_search( SyldapServer *ldapServer ) {
503 LDAP *ld;
504 LDAPMessage *result, *e;
505 char *attribs[10];
506 char *attribute;
507 gchar *criteria;
508 BerElement *ber;
509 gint rc;
510 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
511 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
512 struct timeval timeout;
513 gboolean entriesFound = FALSE;
515 g_return_val_if_fail( ldapServer != NULL, -1 );
517 ldapServer->retVal = MGU_SUCCESS;
518 if( ! syldap_check_search( ldapServer ) ) {
519 return ldapServer->retVal;
522 /* Set timeout */
523 timeout.tv_sec = ldapServer->timeOut;
524 timeout.tv_usec = 0L;
526 ldapServer->entriesRead = 0;
527 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
528 ldapServer->retVal = MGU_LDAP_INIT;
529 return ldapServer->retVal;
532 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
534 /* Bind to the server, if required */
535 if( ldapServer->bindDN ) {
536 if( * ldapServer->bindDN != '\0' ) {
537 /* printf( "binding...\n" ); */
538 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
539 /* printf( "rc=%d\n", rc ); */
540 if( rc != LDAP_SUCCESS ) {
541 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
542 ldap_unbind( ld );
543 ldapServer->retVal = MGU_LDAP_BIND;
544 return ldapServer->retVal;
549 /* Define all attributes we are interested in. */
550 attribs[0] = SYLDAP_ATTR_DN;
551 attribs[1] = SYLDAP_ATTR_COMMONNAME;
552 attribs[2] = SYLDAP_ATTR_GIVENNAME;
553 attribs[3] = SYLDAP_ATTR_SURNAME;
554 attribs[4] = SYLDAP_ATTR_EMAIL;
555 attribs[5] = SYLDAP_ATTR_UID;
556 attribs[6] = NULL;
558 /* Create LDAP search string and apply search criteria */
559 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
560 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
561 &timeout, 0, &result );
562 g_free( criteria );
563 criteria = NULL;
564 if( rc == LDAP_TIMEOUT ) {
565 ldap_unbind( ld );
566 ldapServer->retVal = MGU_LDAP_TIMEOUT;
567 return ldapServer->retVal;
569 if( rc != LDAP_SUCCESS ) {
570 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
571 ldap_unbind( ld );
572 ldapServer->retVal = MGU_LDAP_SEARCH;
573 return ldapServer->retVal;
576 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
578 /* Clear the cache if we have new entries, otherwise leave untouched. */
579 if( ldap_count_entries( ld, result ) > 0 ) {
580 addrcache_clear( ldapServer->addressCache );
583 /* Process results */
584 ldapServer->entriesRead = 0;
585 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
586 entriesFound = TRUE;
587 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
588 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
590 /* Process all attributes */
591 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
592 attribute = ldap_next_attribute( ld, e, ber ) ) {
593 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
594 listName = syldap_add_list_values( ld, e, attribute );
596 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
597 listAddress = syldap_add_list_values( ld, e, attribute );
599 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
600 listID = syldap_add_single_value( ld, e, attribute );
602 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
603 listFirst = syldap_add_list_values( ld, e, attribute );
605 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
606 listLast = syldap_add_single_value( ld, e, attribute );
608 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
609 listDN = syldap_add_single_value( ld, e, attribute );
613 /* Free memory used to store attribute */
614 ldap_memfree( attribute );
616 /* Format and add items to cache */
617 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
619 /* Free up */
620 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
621 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
623 if( ber != NULL ) {
624 ber_free( ber, 0 );
628 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
629 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
631 /* Free up and disconnect */
632 ldap_msgfree( result );
633 ldap_unbind( ld );
634 ldapServer->newSearch = FALSE;
635 if( entriesFound ) {
636 ldapServer->retVal = MGU_SUCCESS;
638 else {
639 ldapServer->retVal = MGU_LDAP_NOENTRIES;
641 return ldapServer->retVal;
644 /* syldap_display_search_results() - updates the ui. this function is called from the
645 * main thread (the thread running the GTK event loop). */
646 static gint syldap_display_search_results(SyldapServer *ldapServer)
648 /* NOTE: when this function is called the accompanying thread should
649 * already be terminated. */
650 gtk_idle_remove(ldapServer->idleId);
651 ldapServer->callBack(ldapServer);
652 /* FIXME: match should know whether to free this SyldapServer stuff. */
653 g_free(ldapServer->thread);
654 ldapServer->thread = NULL;
655 return TRUE;
658 /* ============================================================================================ */
660 * Read data into list. Main entry point
661 * Return: TRUE if file read successfully.
663 /* ============================================================================================ */
664 gint syldap_read_data( SyldapServer *ldapServer ) {
665 g_return_val_if_fail( ldapServer != NULL, -1 );
667 ldapServer->addressCache->accessFlag = FALSE;
668 pthread_detach( pthread_self() );
669 if( ldapServer->newSearch ) {
670 /* Read data into the list */
671 syldap_search( ldapServer );
673 /* Mark cache */
674 ldapServer->addressCache->modified = FALSE;
675 ldapServer->addressCache->dataRead = TRUE;
676 ldapServer->addressCache->accessFlag = FALSE;
679 /* Callback */
680 ldapServer->busyFlag = FALSE;
681 if( ldapServer->callBack ) {
682 /* make the ui thread update the search results */
683 /* TODO: really necessary to call gdk_threads_XXX()??? gtk_idle_add()
684 * should do this - could someone check the GTK sources please? */
685 gdk_threads_enter();
686 ldapServer->idleId = gtk_idle_add((GtkFunction)syldap_display_search_results,
687 ldapServer);
688 gdk_threads_leave();
691 return ldapServer->retVal;
694 /* ============================================================================================ */
696 * Cancel read with thread.
698 /* ============================================================================================ */
699 void syldap_cancel_read( SyldapServer *ldapServer ) {
700 g_return_if_fail( ldapServer != NULL );
702 /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */
703 if( ldapServer->thread ) {
704 /* printf( "thread cancelled\n" ); */
705 pthread_cancel( *ldapServer->thread );
707 g_free(ldapServer->thread);
708 ldapServer->thread = NULL;
709 ldapServer->busyFlag = FALSE;
712 /* ============================================================================================ */
714 * Read data into list using a background thread.
715 * Return: TRUE if file read successfully. Callback function will be
716 * notified when search is complete.
718 /* ============================================================================================ */
719 gint syldap_read_data_th( SyldapServer *ldapServer ) {
720 g_return_val_if_fail( ldapServer != NULL, -1 );
722 ldapServer->busyFlag = FALSE;
723 syldap_check_search( ldapServer );
724 if( ldapServer->retVal == MGU_SUCCESS ) {
725 /* debug_print("Staring LDAP read thread\n"); */
727 ldapServer->busyFlag = TRUE;
728 ldapServer->thread = g_new0(pthread_t, 1);
729 pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer );
731 return ldapServer->retVal;
735 * Return link list of persons.
737 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
738 g_return_val_if_fail( ldapServer != NULL, NULL );
739 return addrcache_get_list_person( ldapServer->addressCache );
743 * Return link list of folders. This is always NULL since there are
744 * no folders in GnomeCard.
745 * Return: NULL.
747 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
748 g_return_val_if_fail( ldapServer != NULL, NULL );
749 return NULL;
752 #define SYLDAP_TEST_FILTER "(objectclass=*)"
753 #define SYLDAP_SEARCHBASE_V2 "cn=config"
754 #define SYLDAP_SEARCHBASE_V3 ""
755 #define SYLDAP_V2_TEST_ATTR "database"
756 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
759 * Attempt to discover the base DN for the server.
760 * Enter:
761 * host Host name
762 * port Port number
763 * bindDN Bind DN (optional).
764 * bindPW Bind PW (optional).
765 * tov Timeout value (seconds), or 0 for none, default 30 secs.
766 * Return: List of Base DN's, or NULL if could not read. Base DN should
767 * be g_free() when done.
769 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
770 GList *baseDN = NULL;
771 LDAP *ld;
772 gint rc, i;
773 LDAPMessage *result, *e;
774 gchar *attribs[10];
775 BerElement *ber;
776 gchar *attribute;
777 gchar **vals;
778 struct timeval timeout;
780 if( host == NULL ) return baseDN;
781 if( port < 1 ) return baseDN;
783 /* Set timeout */
784 timeout.tv_usec = 0L;
785 if( tov > 0 ) {
786 timeout.tv_sec = tov;
788 else {
789 timeout.tv_sec = 30L;
792 /* Connect to server. */
793 if( ( ld = ldap_init( host, port ) ) == NULL ) {
794 return baseDN;
797 /* Bind to the server, if required */
798 if( bindDN ) {
799 if( *bindDN != '\0' ) {
800 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
801 if( rc != LDAP_SUCCESS ) {
802 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
803 ldap_unbind( ld );
804 return baseDN;
809 /* Test for LDAP version 3 */
810 attribs[0] = SYLDAP_V3_TEST_ATTR;
811 attribs[1] = NULL;
812 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
813 0, NULL, NULL, &timeout, 0, &result );
814 if( rc == LDAP_SUCCESS ) {
815 /* Process entries */
816 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
817 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
819 /* Process attributes */
820 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
821 attribute = ldap_next_attribute( ld, e, ber ) ) {
822 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
823 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
824 for( i = 0; vals[i] != NULL; i++ ) {
825 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
826 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
829 ldap_value_free( vals );
832 ldap_memfree( attribute );
833 if( ber != NULL ) {
834 ber_free( ber, 0 );
837 ldap_msgfree( result );
839 else {
842 if( baseDN == NULL ) {
843 /* Test for LDAP version 2 */
844 attribs[0] = NULL;
845 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
846 0, NULL, NULL, &timeout, 0, &result );
847 if( rc == LDAP_SUCCESS ) {
848 /* Process entries */
849 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
850 /* if( baseDN ) break; */
851 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
853 /* Process attributes */
854 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
855 attribute = ldap_next_attribute( ld, e, ber ) ) {
856 /* if( baseDN ) break; */
857 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
858 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
859 for( i = 0; vals[i] != NULL; i++ ) {
860 char *ch;
861 /* Strip the 'ldb:' from the front of the value */
862 ch = ( char * ) strchr( vals[i], ':' );
863 if( ch ) {
864 gchar *bn = g_strdup( ++ch );
865 g_strchomp( bn );
866 g_strchug( bn );
867 baseDN = g_list_append( baseDN, g_strdup( bn ) );
871 ldap_value_free( vals );
874 ldap_memfree( attribute );
875 if( ber != NULL ) {
876 ber_free( ber, 0 );
879 ldap_msgfree( result );
882 ldap_unbind( ld );
883 return baseDN;
887 * Attempt to discover the base DN for the server.
888 * Enter: ldapServer Server to test.
889 * Return: List of Base DN's, or NULL if could not read. Base DN should
890 * be g_free() when done. Return code set in ldapServer.
892 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
893 GList *baseDN = NULL;
894 LDAP *ld;
895 gint rc, i;
896 LDAPMessage *result, *e;
897 gchar *attribs[10];
898 BerElement *ber;
899 gchar *attribute;
900 gchar **vals;
901 struct timeval timeout;
903 ldapServer->retVal = MGU_BAD_ARGS;
904 if( ldapServer == NULL ) return baseDN;
905 if( ldapServer->hostName == NULL ) return baseDN;
906 if( ldapServer->port < 1 ) return baseDN;
908 /* Set timeout */
909 timeout.tv_usec = 0L;
910 if( ldapServer->timeOut > 0 ) {
911 timeout.tv_sec = ldapServer->timeOut;
913 else {
914 timeout.tv_sec = 30L;
917 /* Connect to server. */
918 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
919 ldapServer->retVal = MGU_LDAP_INIT;
920 return baseDN;
923 /* Bind to the server, if required */
924 if( ldapServer->bindDN ) {
925 if( *ldapServer->bindDN != '\0' ) {
926 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
927 if( rc != LDAP_SUCCESS ) {
928 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
929 ldap_unbind( ld );
930 ldapServer->retVal = MGU_LDAP_BIND;
931 return baseDN;
936 ldapServer->retVal = MGU_LDAP_SEARCH;
938 /* Test for LDAP version 3 */
939 attribs[0] = SYLDAP_V3_TEST_ATTR;
940 attribs[1] = NULL;
941 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
942 0, NULL, NULL, &timeout, 0, &result );
943 if( rc == LDAP_SUCCESS ) {
944 /* Process entries */
945 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
946 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
948 /* Process attributes */
949 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
950 attribute = ldap_next_attribute( ld, e, ber ) ) {
951 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
952 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
953 for( i = 0; vals[i] != NULL; i++ ) {
954 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
955 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
958 ldap_value_free( vals );
961 ldap_memfree( attribute );
962 if( ber != NULL ) {
963 ber_free( ber, 0 );
966 ldap_msgfree( result );
967 ldapServer->retVal = MGU_SUCCESS;
969 else if( rc == LDAP_TIMEOUT ) {
970 ldapServer->retVal = MGU_LDAP_TIMEOUT;
973 if( baseDN == NULL ) {
974 /* Test for LDAP version 2 */
975 attribs[0] = NULL;
976 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
977 0, NULL, NULL, &timeout, 0, &result );
978 if( rc == LDAP_SUCCESS ) {
979 /* Process entries */
980 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
981 /* if( baseDN ) break; */
982 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
984 /* Process attributes */
985 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
986 attribute = ldap_next_attribute( ld, e, ber ) ) {
987 /* if( baseDN ) break; */
988 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
989 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
990 for( i = 0; vals[i] != NULL; i++ ) {
991 char *ch;
992 /* Strip the 'ldb:' from the front of the value */
993 ch = ( char * ) strchr( vals[i], ':' );
994 if( ch ) {
995 gchar *bn = g_strdup( ++ch );
996 g_strchomp( bn );
997 g_strchug( bn );
998 baseDN = g_list_append( baseDN, g_strdup( bn ) );
1002 ldap_value_free( vals );
1005 ldap_memfree( attribute );
1006 if( ber != NULL ) {
1007 ber_free( ber, 0 );
1010 ldap_msgfree( result );
1011 ldapServer->retVal = MGU_SUCCESS;
1013 else if( rc == LDAP_TIMEOUT ) {
1014 ldapServer->retVal = MGU_LDAP_TIMEOUT;
1017 ldap_unbind( ld );
1019 return baseDN;
1023 * Attempt to connect to the server.
1024 * Enter:
1025 * host Host name
1026 * port Port number
1027 * Return: TRUE if connected successfully.
1029 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1030 gboolean retVal = FALSE;
1031 LDAP *ld;
1033 if( host == NULL ) return retVal;
1034 if( port < 1 ) return retVal;
1035 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1036 retVal = TRUE;
1038 if( ld != NULL ) {
1039 ldap_unbind( ld );
1041 return retVal;
1045 * Attempt to connect to the server.
1046 * Enter: ldapServer Server to test.
1047 * Return: TRUE if connected successfully. Return code set in ldapServer.
1049 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1050 gboolean retVal = FALSE;
1051 LDAP *ld;
1053 ldapServer->retVal = MGU_BAD_ARGS;
1054 if( ldapServer == NULL ) return retVal;
1055 if( ldapServer->hostName == NULL ) return retVal;
1056 if( ldapServer->port < 1 ) return retVal;
1057 ldapServer->retVal = MGU_LDAP_INIT;
1058 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1059 ldapServer->retVal = MGU_SUCCESS;
1060 retVal = TRUE;
1062 if( ld != NULL ) {
1063 ldap_unbind( ld );
1065 return retVal;
1069 * Test whether LDAP libraries installed.
1070 * Return: TRUE if library available.
1072 gboolean syldap_test_ldap_lib() {
1073 return TRUE;
1076 #endif /* USE_LDAP */
1079 * End of Source.