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.
32 #include <gtk/gtkmain.h>
41 #include "addrcache.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;
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
);
99 ldapServer
->port
= value
;
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
);
159 ldapServer
->maxEntries
= value
;
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
);
172 ldapServer
->timeOut
= value
;
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
;
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
);
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
) {
326 GSList
*nodeName
= listName
;
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;
359 /* Find longest first name in list */
361 if( firstName
== NULL
) {
362 firstName
= nodeFirst
->data
;
363 iLen
= strlen( firstName
);
366 if( ( iLenT
= strlen( nodeFirst
->data
) ) > iLen
) {
367 firstName
= nodeFirst
->data
;
371 nodeFirst
= g_slist_next( nodeFirst
);
376 lastName
= listLast
->data
;
381 fullName
= g_strdup_printf( "%s %s", firstName
, lastName
);
384 fullName
= g_strdup_printf( "%s", firstName
);
389 fullName
= g_strdup_printf( "%s", lastName
);
393 g_strchug( fullName
); g_strchomp( fullName
);
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
++;
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
) {
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
);
438 * Add a single attribute value to a list.
440 static GSList
*syldap_add_single_value( LDAP
*ld
, LDAPMessage
*entry
, char *attr
) {
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
);
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
) {
480 if( strlen( ldapServer
->searchCriteria
) < 1 ) {
484 if( ldapServer
->searchValue
== NULL
) {
487 if( strlen( ldapServer
->searchValue
) < 1 ) {
491 ldapServer
->retVal
= MGU_SUCCESS
;
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
) {
504 LDAPMessage
*result
, *e
;
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
;
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 ) ); */
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
;
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
);
564 if( rc
== LDAP_TIMEOUT
) {
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 ) ); */
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
) ) {
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
);
620 syldap_free_lists( listName
, listAddress
, listID
, listDN
, listFirst
, listLast
);
621 listName
= listAddress
= listID
= listFirst
= listLast
= listDN
= NULL
;
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
);
634 ldapServer
->newSearch
= FALSE
;
636 ldapServer
->retVal
= MGU_SUCCESS
;
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
;
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
);
674 ldapServer
->addressCache
->modified
= FALSE
;
675 ldapServer
->addressCache
->dataRead
= TRUE
;
676 ldapServer
->addressCache
->accessFlag
= FALSE
;
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? */
686 ldapServer
->idleId
= gtk_idle_add((GtkFunction
)syldap_display_search_results
,
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.
747 GList
*syldap_get_list_folder( SyldapServer
*ldapServer
) {
748 g_return_val_if_fail( ldapServer
!= NULL
, 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.
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
;
773 LDAPMessage
*result
, *e
;
778 struct timeval timeout
;
780 if( host
== NULL
) return baseDN
;
781 if( port
< 1 ) return baseDN
;
784 timeout
.tv_usec
= 0L;
786 timeout
.tv_sec
= tov
;
789 timeout
.tv_sec
= 30L;
792 /* Connect to server. */
793 if( ( ld
= ldap_init( host
, port
) ) == NULL
) {
797 /* Bind to the server, if required */
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 ) ); */
809 /* Test for LDAP version 3 */
810 attribs
[0] = SYLDAP_V3_TEST_ATTR
;
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
);
837 ldap_msgfree( result
);
842 if( baseDN
== NULL
) {
843 /* Test for LDAP version 2 */
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
++ ) {
861 /* Strip the 'ldb:' from the front of the value */
862 ch
= ( char * ) strchr( vals
[i
], ':' );
864 gchar
*bn
= g_strdup( ++ch
);
867 baseDN
= g_list_append( baseDN
, g_strdup( bn
) );
871 ldap_value_free( vals
);
874 ldap_memfree( attribute
);
879 ldap_msgfree( result
);
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
;
896 LDAPMessage
*result
, *e
;
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
;
909 timeout
.tv_usec
= 0L;
910 if( ldapServer
->timeOut
> 0 ) {
911 timeout
.tv_sec
= ldapServer
->timeOut
;
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
;
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 ) ); */
930 ldapServer
->retVal
= MGU_LDAP_BIND
;
936 ldapServer
->retVal
= MGU_LDAP_SEARCH
;
938 /* Test for LDAP version 3 */
939 attribs
[0] = SYLDAP_V3_TEST_ATTR
;
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
);
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 */
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
++ ) {
992 /* Strip the 'ldb:' from the front of the value */
993 ch
= ( char * ) strchr( vals
[i
], ':' );
995 gchar
*bn
= g_strdup( ++ch
);
998 baseDN
= g_list_append( baseDN
, g_strdup( bn
) );
1002 ldap_value_free( vals
);
1005 ldap_memfree( attribute
);
1010 ldap_msgfree( result
);
1011 ldapServer
->retVal
= MGU_SUCCESS
;
1013 else if( rc
== LDAP_TIMEOUT
) {
1014 ldapServer
->retVal
= MGU_LDAP_TIMEOUT
;
1023 * Attempt to connect to the server.
1027 * Return: TRUE if connected successfully.
1029 gboolean
syldap_test_connect_s( const gchar
*host
, const gint port
) {
1030 gboolean retVal
= FALSE
;
1033 if( host
== NULL
) return retVal
;
1034 if( port
< 1 ) return retVal
;
1035 if( ( ld
= ldap_open( host
, port
) ) != NULL
) {
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
;
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
;
1069 * Test whether LDAP libraries installed.
1070 * Return: TRUE if library available.
1072 gboolean
syldap_test_ldap_lib() {
1076 #endif /* USE_LDAP */