/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2003 Match Grun
+ * Copyright (C) 2003-2007 Match Grun and the Claws Mail team
*
* 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* 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.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
*/
/*
#include <glib.h>
#include <sys/time.h>
#include <string.h>
-#include <ldap.h>
#include <lber.h>
+#include "ldaputil.h"
#include "ldapquery.h"
#include "ldapctrl.h"
#include "mgutils.h"
#include "addritem.h"
#include "addrcache.h"
+#include "common/utils.h"
/*
* Key for thread specific data.
static pthread_key_t _queryThreadKey_;
static gboolean _queryThreadInit_ = FALSE;
+static gboolean callbackend (gpointer data)
+{
+ LdapQuery *qry = (LdapQuery *)data;
+ qry->callBackEnd( qry, ADDRQUERY_ID(qry), ADDRQUERY_RETVAL(qry), qry->data );
+ return FALSE;
+}
+
+
/**
* Create new LDAP query object.
* \return Initialized query object.
LdapQuery *qry;
qry = g_new0( LdapQuery, 1 );
+ ADDRQUERY_TYPE(qry) = ADDRQUERY_LDAP;
+ ADDRQUERY_ID(qry) = 0;
+ ADDRQUERY_SEARCHTYPE(qry) = ADDRSEARCH_NONE;
+ ADDRQUERY_NAME(qry) = NULL;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
+ ADDRQUERY_FOLDER(qry) = NULL;
+ ADDRQUERY_SEARCHVALUE(qry) = NULL;
qry->control = NULL;
- qry->retVal = LDAPRC_SUCCESS;
- qry->queryType = LDAPQUERY_NONE;
- qry->queryName = NULL;
- qry->searchValue = NULL;
- qry->queryID = 0;
+ qry->server = NULL;
qry->entriesRead = 0;
qry->elapsedTime = 0;
qry->stopFlag = FALSE;
qry->agedFlag = FALSE;
qry->completed = FALSE;
qry->thread = NULL;
- qry->callBackStart = NULL;
qry->callBackEntry = NULL;
qry->callBackEnd = NULL;
- qry->folder = NULL;
- qry->server = NULL;
+ qry->ldap = NULL;
+ qry->data = NULL;
/* Mutex to protect stop and busy flags */
qry->mutexStop = g_malloc0( sizeof( pthread_mutex_t ) );
* \param value Name.
*/
void ldapqry_set_name( LdapQuery* qry, const gchar *value ) {
- qry->queryName = mgu_replace_string( qry->queryName, value );
- g_strstrip( qry->queryName );
+ g_return_if_fail( qry != NULL );
+ ADDRQUERY_NAME(qry) = mgu_replace_string( ADDRQUERY_NAME(qry), value );
+ if (ADDRQUERY_NAME(qry) == NULL)
+ return;
+ g_strstrip( ADDRQUERY_NAME(qry) );
+ debug_print("set name: %s\n", ADDRQUERY_NAME(qry));
}
/**
* \param value
*/
void ldapqry_set_search_value( LdapQuery *qry, const gchar *value ) {
- qry->searchValue = mgu_replace_string( qry->searchValue, value );
- g_strstrip( qry->searchValue );
-}
-
-/**
- * Specify error/status.
- * \param qry Query object.
- * \param value Status.
- */
-void ldapqry_set_error_status( LdapQuery* qry, const gint value ) {
- qry->retVal = value;
+ g_return_if_fail( qry != NULL );
+ ADDRQUERY_SEARCHVALUE(qry) = mgu_replace_string( ADDRQUERY_SEARCHVALUE(qry), value );
+ if (ADDRQUERY_SEARCHVALUE(qry) == NULL)
+ return;
+ g_strstrip( ADDRQUERY_SEARCHVALUE(qry) );
+ debug_print("search value: %s\n", ADDRQUERY_SEARCHVALUE(qry));
}
/**
* <li><code>LDAPQUERY_DYNAMIC</code></li>
* </ul>
*/
+/*
void ldapqry_set_query_type( LdapQuery* qry, const gint value ) {
- qry->queryType = value;
-}
-
-/**
- * Specify query ID.
- * \param qry Query object.
- * \param value ID for the query.
- */
-void ldapqry_set_query_id( LdapQuery* qry, const gint value ) {
- qry->queryID = value;
+ ADDRQUERY_TYPE(qry) = value;
}
+*/
/**
- * Specify maximum number of LDAP entries to retrieve.
- * \param qry Query object.
- * \param value Entries to read.
+ * Specify search type.
+ * \param qry Query object.
+ * \param value Type.
*/
-void ldapqry_set_entries_read( LdapQuery* qry, const gint value ) {
- if( value > 0 ) {
- qry->entriesRead = value;
- }
- else {
- qry->entriesRead = 0;
- }
+void ldapqry_set_search_type( LdapQuery *qry, const AddrSearchType value ) {
+ g_return_if_fail( qry != NULL );
+ ADDRQUERY_SEARCHTYPE(qry) = value;
}
/**
- * Register a callback function that will be executed when the search
- * starts. When called, the function will be passed this query object
- * as an argument.
+ * Specify query ID.
* \param qry Query object.
- * \param func Function.
+ * \param value ID for the query.
*/
-void ldapqry_set_callback_start( LdapQuery *qry, void *func ) {
- qry->callBackStart = func;
+void ldapqry_set_query_id( LdapQuery* qry, const gint value ) {
+ g_return_if_fail( qry != NULL );
+ ADDRQUERY_ID(qry) = value;
}
/**
* \param qry Query object.
* \return Value of stop flag.
*/
-gboolean ldapqry_get_stop_flag( LdapQuery *qry ) {
+static gboolean ldapqry_get_stop_flag( LdapQuery *qry ) {
gboolean value;
- g_return_if_fail( qry != NULL );
+ g_return_val_if_fail( qry != NULL, TRUE );
pthread_mutex_lock( qry->mutexStop );
value = qry->stopFlag;
* \param qry Query object.
* \param value Value of busy flag.
*/
-void ldapqry_set_busy_flag( LdapQuery *qry, const gboolean value ) {
+static void ldapqry_set_busy_flag( LdapQuery *qry, const gboolean value ) {
g_return_if_fail( qry != NULL );
+ if (qry->mutexBusy == NULL)
+ return; /* exiting, mutex already freed */
pthread_mutex_lock( qry->mutexBusy );
qry->busyFlag = value;
* \param qry Query object.
* \return Value of busy flag.
*/
-gboolean ldapqry_get_busy_flag( LdapQuery *qry ) {
+static gboolean ldapqry_get_busy_flag( LdapQuery *qry ) {
gboolean value;
- g_return_if_fail( qry != NULL );
+ g_return_val_if_fail( qry != NULL, FALSE );
pthread_mutex_lock( qry->mutexBusy );
value = qry->busyFlag;
* \param qry Query object.
* \param value Value of aged flag.
*/
-void ldapqry_set_aged_flag( LdapQuery *qry, const gboolean value ) {
+static void ldapqry_set_aged_flag( LdapQuery *qry, const gboolean value ) {
g_return_if_fail( qry != NULL );
qry->agedFlag = value;
}
-/**
- * Test value of aged flag.
- * \param qry Query object.
- * \return <i>TRUE</i> if query has been marked as aged (and can be retired).
- */
-gboolean ldapqry_get_aged_flag( LdapQuery *qry ) {
- g_return_if_fail( qry != NULL );
- return qry->agedFlag;
-}
-
-/**
- * Release the LDAP control data associated with the query.
- * \param qry Query object to process.
- */
-void ldapqry_release_control( LdapQuery *qry ) {
- g_return_if_fail( qry != NULL );
- if( qry->control != NULL ) {
- ldapctl_free( qry->control );
- }
- qry->control = NULL;
-}
-
/**
* Clear LDAP query member variables.
* \param qry Query object.
*/
-void ldapqry_clear( LdapQuery *qry ) {
+static void ldapqry_clear( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
/* Free internal stuff */
- g_free( qry->queryName );
- g_free( qry->searchValue );
+ g_free( ADDRQUERY_NAME(qry) );
+ g_free( ADDRQUERY_SEARCHVALUE(qry) );
/* Clear pointers and value */
- qry->queryName = NULL;
- qry->searchValue = NULL;
- qry->retVal = LDAPRC_SUCCESS;
- qry->queryType = LDAPQUERY_NONE;
- qry->queryID = 0;
+ ADDRQUERY_NAME(qry) = NULL;
+ ADDRQUERY_SEARCHVALUE(qry) = NULL;
+ ADDRQUERY_ID(qry) = 0;
+ ADDRQUERY_SEARCHTYPE(qry) = ADDRSEARCH_NONE;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
qry->entriesRead = 0;
qry->elapsedTime = 0;
qry->stopFlag = FALSE;
qry->busyFlag = FALSE;
qry->agedFlag = FALSE;
qry->completed = FALSE;
- qry->callBackStart = NULL;
qry->callBackEntry = NULL;
qry->callBackEnd = NULL;
+ qry->ldap = NULL;
+ qry->data = NULL;
}
/**
g_return_if_fail( qry != NULL );
/* Clear out internal members */
+ ADDRQUERY_TYPE(qry) = ADDRQUERY_NONE;
ldapqry_clear( qry );
/* Free the mutex */
qry->mutexStop = NULL;
/* Do not free folder - parent server object should free */
- qry->folder = NULL;
+ ADDRQUERY_FOLDER(qry) = NULL;
/* Do not free thread - thread should be terminated before freeing */
qry->thread = NULL;
g_free( qry );
}
-/**
- * Display object to specified stream.
- * \param qry Query object to process.
- * \param stream Output stream.
- */
-void ldapqry_print( const LdapQuery *qry, FILE *stream ) {
- g_return_if_fail( qry != NULL );
-
- fprintf( stream, "LdapQuery:\n" );
- fprintf( stream, " control?: %s\n", qry->control ? "yes" : "no" );
- fprintf( stream, "err/status: %d\n", qry->retVal );
- fprintf( stream, "query type: %d\n", qry->queryType );
- fprintf( stream, "query name: '%s'\n", qry->queryName );
- fprintf( stream, "search val: '%s'\n", qry->searchValue );
- fprintf( stream, " queryID: %d\n", qry->queryID );
- fprintf( stream, " entries: %d\n", qry->entriesRead );
- fprintf( stream, " elapsed: %d\n", qry->elapsedTime );
- fprintf( stream, " stop flag: %s\n", qry->stopFlag ? "yes" : "no" );
- fprintf( stream, " busy flag: %s\n", qry->busyFlag ? "yes" : "no" );
- fprintf( stream, " aged flag: %s\n", qry->agedFlag ? "yes" : "no" );
- fprintf( stream, " completed: %s\n", qry->completed ? "yes" : "no" );
-}
-
/**
* Free linked lists of character strings.
* \param listName List of common names.
*/
static void ldapqry_free_lists(
GSList *listName, GSList *listAddr, GSList *listFirst,
- GSList *listLast )
+ GSList *listLast, GSList *listDisplay, GSList *other_attrs )
{
+ GSList *cur = other_attrs;
mgu_free_list( listName );
mgu_free_list( listAddr );
mgu_free_list( listFirst );
mgu_free_list( listLast );
+ mgu_free_list( listDisplay );
+ for(;cur; cur = cur->next)
+ addritem_free_attribute((UserAttribute *)cur->data);
+ g_slist_free(other_attrs);
}
/**
{
GSList *list = NULL;
gint i;
- gchar **vals;
+ struct berval **vals;
- if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
+ if( ( vals = ldap_get_values_len( 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] ) );
+ /*debug_print("lv\t%s: %s\n", attr?attr:"null",
+ vals[i]->bv_val?vals[i]->bv_val:"null");*/
+ list = g_slist_append( list, g_strndup( vals[i]->bv_val, vals[i]->bv_len) );
}
}
- ldap_value_free( vals );
+ ldap_value_free_len( vals );
return list;
}
*/
static GSList *ldapqry_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
GSList *list = NULL;
- gchar **vals;
+ struct berval **vals;
- if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
+ if( ( vals = ldap_get_values_len( 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] ) );
+ debug_print("sv\t%s: %s\n", attr?attr:"null",
+ vals[0]->bv_val?vals[0]->bv_val:"null");
+ list = g_slist_append( list, g_strndup( vals[0]->bv_val, vals[0]->bv_len ));
}
}
- ldap_value_free( vals );
+ ldap_value_free_len( vals );
return list;
}
static GList *ldapqry_build_items_fl(
AddressCache *cache, LdapQuery *qry, gchar *dn,
GSList *listName, GSList *listAddr, GSList *listFirst,
- GSList *listLast )
+ GSList *listLast, GSList *listDisplay, GSList *attributes )
{
- GSList *nodeAddress;
+ GSList *nodeAddress, *cur;
gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
- gboolean allocated;
+ gboolean allocated = FALSE;
ItemPerson *person;
ItemEMail *email;
ItemFolder *folder;
- GList *listReturn;
+ GList *listReturn = NULL;
- listReturn = NULL;
+ folder = ADDRQUERY_FOLDER(qry);
+ if( folder == NULL ) return listReturn;
if( listAddr == NULL ) return listReturn;
+ if ( listDisplay ) {
+ allocated = FALSE;
+ fullName = listDisplay->data;
+ }
+
/* Find longest first name in list */
firstName = mgu_slist_longest_entry( listFirst );
lastName = listLast->data;
}
- /* Find longest common name */
- allocated = FALSE;
- fullName = mgu_slist_longest_entry( listName );
- if( fullName == NULL ) {
- /* Format a full name from first and last names */
- if( firstName ) {
- if( lastName ) {
- fullName = g_strdup_printf( "%s %s", firstName, lastName );
+ if ( fullName == NULL ) {
+ /* Find longest common name */
+ allocated = FALSE;
+ fullName = mgu_slist_longest_entry( listName );
+ if( fullName == NULL ) {
+ /* Format a full name from first and last names */
+ if( firstName ) {
+ if( lastName ) {
+ fullName = g_strdup_printf( "%s %s", firstName, lastName );
+ }
+ else {
+ fullName = g_strdup_printf( "%s", firstName );
+ }
}
else {
- fullName = g_strdup_printf( "%s", firstName );
+ if( lastName ) {
+ fullName = g_strdup_printf( "%s", lastName );
+ }
}
- }
- else {
- if( lastName ) {
- fullName = g_strdup_printf( "%s", lastName );
+ if( fullName ) {
+ g_strchug( fullName ); g_strchomp( fullName );
+ allocated = TRUE;
}
}
- if( fullName ) {
- g_strchug( fullName ); g_strchomp( fullName );
- allocated = TRUE;
- }
- }
-
- /* Create new folder for results */
- if( qry->folder == NULL ) {
- folder = addritem_create_item_folder();
- addritem_folder_set_name( folder, qry->queryName );
- addritem_folder_set_remarks( folder, "" );
- addrcache_id_folder( cache, folder );
- addrcache_add_folder( cache, folder );
- qry->folder = folder;
-
- /* Specify folder type and back reference */
- folder->folderType = ADDRFOLDER_LDAP_QUERY;
- folder->folderData = ( gpointer ) qry;
- folder->isHidden = TRUE;
}
/* Add person into folder */
addritem_person_set_common_name( person, fullName );
addritem_person_set_first_name( person, firstName );
addritem_person_set_last_name( person, lastName );
+ addritem_person_set_nick_name( person, fullName );
addrcache_id_person( cache, person );
addritem_person_set_external_id( person, dn );
- addrcache_folder_add_person( cache, qry->folder, person );
+
+ for (cur = attributes; cur; cur = cur->next) {
+ UserAttribute *attrib = addritem_copy_attribute((UserAttribute *)cur->data);
+ addritem_person_add_attribute( person, attrib );
+ }
+
+ addrcache_folder_add_person( cache, ADDRQUERY_FOLDER(qry), person );
qry->entriesRead++;
addrcache_id_email( cache, email );
addrcache_person_add_email( cache, person, email );
addritem_person_add_email( person, email );
+ /*if (debug_get_mode()) {
+ addritem_print_item_email(email, stdout);
+ }*/
listReturn = g_list_append( listReturn, email );
nodeAddress = g_slist_next( nodeAddress );
}
BerElement *ber;
GSList *listName = NULL, *listAddress = NULL;
GSList *listFirst = NULL, *listLast = NULL;
+ GSList *listDisplay = NULL;
+ GSList *other_attrs = NULL;
GList *listReturn;
listReturn = NULL;
ctl = qry->control;
dnEntry = ldap_get_dn( ld, e );
- /* printf( "DN: %s\n", dnEntry ); */
+ debug_print( "DN: %s\n", dnEntry?dnEntry:"null" );
/* Process all attributes */
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
attribute = ldap_next_attribute( ld, e, ber ) ) {
-
if( strcasecmp( attribute, ctl->attribEMail ) == 0 ) {
listAddress = ldapqry_add_list_values( ld, e, attribute );
}
}
else if( strcasecmp( attribute, ctl->attribLName ) == 0 ) {
listLast = ldapqry_add_single_value( ld, e, attribute );
+ } else if( strcasecmp( attribute, ctl->attribDName ) == 0 ) {
+ listDisplay = ldapqry_add_single_value( ld, e, attribute );
+ } else {
+ GSList *attlist = ldapqry_add_single_value( ld, e, attribute );
+ UserAttribute *attrib = addritem_create_attribute();
+ const gchar *attvalue = attlist?((gchar *)attlist->data):NULL;
+ if (attvalue) {
+ addritem_attrib_set_name( attrib, attribute );
+ addritem_attrib_set_value( attrib, attvalue );
+ other_attrs = g_slist_prepend(other_attrs, attrib);
+ }
+ mgu_free_list(attlist);
}
-
/* Free memory used to store attribute */
ldap_memfree( attribute );
}
/* Format and add items to cache */
listReturn = ldapqry_build_items_fl(
- cache, qry, dnEntry, listName, listAddress, listFirst, listLast );
+ cache, qry, dnEntry, listName, listAddress, listFirst, listLast, listDisplay, other_attrs );
/* Free up */
- ldapqry_free_lists( listName, listAddress, listFirst, listLast );
- listName = listAddress = listFirst = listLast = NULL;
+ ldapqry_free_lists( listName, listAddress, listFirst, listLast, listDisplay, other_attrs );
+ listName = listAddress = listFirst = listLast = listDisplay = other_attrs = NULL;
if( ber != NULL ) {
ber_free( ber, 0 );
*/
gboolean ldapqry_check_search( LdapQuery *qry ) {
LdapControl *ctl;
- qry->retVal = LDAPRC_CRITERIA;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_CRITERIA;
/* Test for control data */
ctl = qry->control;
}
/* Test for search value */
- if( qry->searchValue == NULL ) {
+ if( ADDRQUERY_SEARCHVALUE(qry) == NULL ) {
return FALSE;
}
- if( strlen( qry->searchValue ) < 1 ) {
+ if( strlen( ADDRQUERY_SEARCHVALUE(qry) ) < 1 ) {
return FALSE;
}
-
- qry->retVal = LDAPRC_SUCCESS;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
return TRUE;
}
qry->agedFlag = FALSE;
}
+/**
+ * Connect to LDAP server.
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_connect( LdapQuery *qry ) {
+ LdapControl *ctl;
+ LDAP *ld = NULL;
+ gint rc;
+ gint version;
+ gchar *uri = NULL;
+
+ /* Initialize connection */
+ if (debug_get_mode()) {
+ debug_print("===ldapqry_connect===\n");
+ /*ldapqry_print(qry, stdout);*/
+ }
+ ctl = qry->control;
+ /*if (debug_get_mode()) {
+ ldapctl_print(ctl, stdout);
+ debug_print("======\n");
+ }*/
+ ldapqry_touch( qry );
+ qry->startTime = qry->touchTime;
+ qry->elapsedTime = -1;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_INIT;
+
+ ldapsrv_set_options (ctl->timeOut, NULL);
+
+ uri = g_strdup_printf("ldap%s://%s:%d",
+ ctl->enableSSL?"s":"",
+ ctl->hostName, ctl->port);
+ ldap_initialize(&ld, uri);
+ g_free(uri);
+
+ if (ld == NULL)
+ return ADDRQUERY_RETVAL(qry);
+
+ qry->ldap = ld;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
+ if( ldapqry_get_stop_flag( qry ) ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ldapqry_touch( qry );
+
+ debug_print("connected to LDAP host %s on port %d\n",
+ ctl->hostName?ctl->hostName:"null", ctl->port);
+
+#ifdef USE_LDAP_TLS
+ /* Handle TLS */
+ version = LDAP_VERSION3;
+ rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
+ if( rc == LDAP_OPT_SUCCESS ) {
+ ctl->version = LDAP_VERSION3;
+ }
+
+ if( ctl->version == LDAP_VERSION3 ) {
+ if( ctl->enableTLS && !ctl->enableSSL ) {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_TLS;
+ rc = ldap_start_tls_s( ld, NULL, NULL );
+
+ debug_print("rc=%d\n", rc);
+ debug_print("LDAP Status: set_option: %s\n", ldap_err2string(rc));
+
+ if( rc != LDAP_SUCCESS ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+ }
+ }
+#endif
+
+ /* Bind to the server, if required */
+ ADDRQUERY_RETVAL(qry) = LDAPRC_BIND;
+ if( ctl->bindDN ) {
+ if( * ctl->bindDN != '\0' ) {
+ debug_print("binding...\n");
+ rc = claws_ldap_simple_bind_s( ld, ctl->bindDN, ctl->bindPass );
+ debug_print("rc=%d\n", rc);
+ if( rc != LDAP_SUCCESS ) {
+ debug_print("LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string(rc));
+ return ADDRQUERY_RETVAL(qry);
+ }
+ }
+ }
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
+ if( ldapqry_get_stop_flag( qry ) ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ldapqry_touch( qry );
+
+ ADDRQUERY_RETVAL(qry) = LDAP_SUCCESS;
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Connect to LDAP server.
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_disconnect( LdapQuery *qry ) {
+ /* Disconnect */
+ if( qry->ldap ) ldap_unbind_ext( qry->ldap, NULL, NULL );
+ qry->ldap = NULL;
+
+ ldapqry_touch( qry );
+ qry->elapsedTime = qry->touchTime - qry->startTime;
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
/**
* Perform the LDAP search, reading LDAP entries into cache.
* Note that one LDAP entry can have multiple values for many of its
* \param qry Query object to process.
* \return Error/status code.
*/
-static gint ldapqry_perform_search( LdapQuery *qry ) {
+static gint ldapqry_search_retrieve( LdapQuery *qry ) {
LdapControl *ctl;
LDAP *ld;
- LDAPMessage *result, *e;
+ LDAPMessage *result, *e = NULL;
char **attribs;
gchar *criteria;
+ gboolean searchFlag;
gboolean entriesFound;
gboolean first;
struct timeval timeout;
gint rc;
- time_t tstart, tend;
AddressCache *cache;
GList *listEMail;
/* Initialize some variables */
+ ld = qry->ldap;
ctl = qry->control;
cache = qry->server->addressCache;
timeout.tv_sec = ctl->timeOut;
timeout.tv_usec = 0L;
entriesFound = FALSE;
- qry->elapsedTime = -1;
- qry->retVal = LDAPRC_SUCCESS;
-
- /* Check search criteria */
- if( ! ldapqry_check_search( qry ) ) {
- return qry->retVal;
- }
-
- /* Initialize connection */
- ldapqry_touch( qry );
- tstart = qry->touchTime;
- tend = tstart - 1;
- if( ( ld = ldap_init( ctl->hostName, ctl->port ) ) == NULL ) {
- qry->retVal = LDAPRC_INIT;
- return qry->retVal;
- }
- if( ldapqry_get_stop_flag( qry ) ) {
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
- }
- ldapqry_touch( qry );
-
- /*
- printf( "connected to LDAP host %s on port %d\n", ctl->hostName, ctl->port );
- */
-
- /* Bind to the server, if required */
- if( ctl->bindDN ) {
- if( * ctl->bindDN != '\0' ) {
- /* printf( "binding...\n" ); */
- rc = ldap_simple_bind_s( ld, ctl->bindDN, ctl->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 );
- qry->retVal = LDAPRC_BIND;
- return qry->retVal;
- }
- }
- }
- if( ldapqry_get_stop_flag( qry ) ) {
- ldap_unbind( ld );
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
- }
- ldapqry_touch( qry );
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
/* Define all attributes we are interested in. */
- attribs = ldapctl_attribute_array( ctl );
+ attribs = ldapctl_full_attribute_array( ctl );
/* Create LDAP search string */
- criteria = ldapctl_format_criteria( ctl, qry->searchValue );
- /* printf( "Search criteria ::%s::\n", criteria ); */
+ criteria = ldapctl_format_criteria( ctl, ADDRQUERY_SEARCHVALUE(qry) );
+ debug_print("Search criteria ::%s::\n", criteria?criteria:"null");
/*
* Execute the search - this step may take some time to complete
* depending on network traffic and server response time.
*/
+ ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT;
rc = ldap_search_ext_s( ld, ctl->baseDN, LDAP_SCOPE_SUBTREE, criteria,
attribs, 0, NULL, NULL, &timeout, 0, &result );
+ debug_print("LDAP Error: ldap_search_st: %d\n", rc);
+ debug_print("LDAP Error: ldap_search_st: %s\n", ldap_err2string(rc));
ldapctl_free_attribute_array( attribs );
g_free( criteria );
criteria = NULL;
if( rc == LDAP_TIMEOUT ) {
- ldap_unbind( ld );
- qry->retVal = LDAPRC_TIMEOUT;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
- if( rc != LDAP_SUCCESS ) {
- /*
- printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
- */
- ldap_unbind( ld );
- qry->retVal = LDAPRC_SEARCH;
- return qry->retVal;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
+
+ /* Test valid returns */
+ searchFlag = FALSE;
+ if( rc == LDAP_ADMINLIMIT_EXCEEDED ) {
+ searchFlag = TRUE;
}
- if( ldapqry_get_stop_flag( qry ) ) {
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
+ else if( rc == LDAP_SUCCESS ) {
+ searchFlag = TRUE;
}
- ldapqry_touch( qry );
-
- /*
- printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
- */
-
- if( ldapqry_get_stop_flag( qry ) ) {
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
+ else if( rc == LDAP_PARTIAL_RESULTS ) {
+ searchFlag = TRUE;
}
+ else {
+ debug_print("LDAP Error: ldap_search_st: %d\n", rc);
+ debug_print("LDAP Error: ldap_search_st: %s\n", ldap_err2string(rc));
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
+
+ debug_print("Total results are: %d\n", ldap_count_entries(ld, result));
/* Process results */
first = TRUE;
- while( TRUE ) {
+ while( searchFlag ) {
ldapqry_touch( qry );
if( qry->entriesRead >= ctl->maxEntries ) break;
e = ldap_next_entry( ld, e );
}
if( e == NULL ) break;
-
entriesFound = TRUE;
/* Setup a critical section here */
/* Process callback */
if( qry->callBackEntry ) {
- qry->callBackEntry( qry, listEMail );
+ qry->callBackEntry( qry, ADDRQUERY_ID(qry), listEMail, qry->data );
}
else {
+ /*if (debug_get_mode()) {
+ GList *node = listEMail;
+ while (node) {
+ addritem_print_item_email(node->data, stdout);
+ node = g_list_next(node);
+ }
+ }*/
g_list_free( listEMail );
}
-
pthread_mutex_unlock( qry->mutexEntry );
}
/* Free up and disconnect */
ldap_msgfree( result );
- ldap_unbind( ld );
- ldapqry_touch( qry );
- tend = qry->touchTime;
- qry->elapsedTime = tend - tstart;
- if( entriesFound ) {
- qry->retVal = LDAPRC_SUCCESS;
+ if( searchFlag ) {
+ if( entriesFound ) {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
+ }
+ else {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
+ }
}
- else {
- qry->retVal = LDAPRC_NOENTRIES;
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Connection, perform search and disconnect.
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_perform_search( LdapQuery *qry ) {
+ /* Check search criteria */
+ if( ! ldapqry_check_search( qry ) ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+
+ /* Connect */
+ qry->ldap = NULL;
+ ldapqry_connect( qry );
+ if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
+ /* Perform search */
+ ldapqry_search_retrieve( qry );
}
+ /* Disconnect */
+ ldapqry_disconnect( qry );
+ qry->ldap = NULL;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
+static gint ldapqry_perform_locate( LdapQuery *qry );
+
/**
* Wrapper around search.
* \param qry Query object to process.
* \return Error/status code.
*/
-gint ldapqry_search( LdapQuery *qry ) {
+static gint ldapqry_search( LdapQuery *qry ) {
gint retVal;
g_return_val_if_fail( qry != NULL, -1 );
ldapqry_touch( qry );
qry->completed = FALSE;
- /* Process callback */
- if( qry->callBackStart ) {
- qry->callBackStart( qry );
- }
-
/* Setup pointer to thread specific area */
pthread_setspecific( _queryThreadKey_, qry );
/* Now perform the search */
qry->entriesRead = 0;
- qry->retVal = LDAPRC_SUCCESS;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
ldapqry_set_busy_flag( qry, TRUE );
ldapqry_set_stop_flag( qry, FALSE );
- retVal = ldapqry_perform_search( qry );
+ if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_LOCATE ) {
+ retVal = ldapqry_perform_locate( qry );
+ }
+ else {
+ retVal = ldapqry_perform_search( qry );
+ }
if( retVal == LDAPRC_SUCCESS ) {
qry->server->addressCache->dataRead = TRUE;
qry->server->addressCache->accessFlag = FALSE;
if( ldapqry_get_stop_flag( qry ) ) {
- /*
- printf( "Search was terminated prematurely\n" );
- */
+ debug_print("Search was terminated prematurely\n");
}
else {
ldapqry_touch( qry );
qry->completed = TRUE;
- /*
- printf( "Search ran to completion\n" );
- */
+ debug_print("Search ran to completion\n");
}
}
ldapqry_set_stop_flag( qry, TRUE );
/* Process callback */
if( qry->callBackEnd ) {
- qry->callBackEnd( qry );
+ g_timeout_add(0, callbackend, qry);
}
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
/**
ldapqry_set_stop_flag( qry, FALSE );
ldapqry_touch( qry );
if( ldapqry_check_search( qry ) ) {
- if( qry->retVal == LDAPRC_SUCCESS ) {
- /*
- printf( "Starting LDAP search thread\n");
- */
+ if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
+ debug_print("Starting LDAP search thread\n");
ldapqry_set_busy_flag( qry, TRUE );
qry->thread = g_malloc0( sizeof( pthread_t ) );
(void *) ldapqry_search, (void *) qry );
}
}
- return qry->retVal;
-}
-
-/**
- * Join the thread associated with the query. This should probably be removed
- * to prevent joining threads.
- * \param qry Query object to process.
- */
-void ldapqry_join_threadX( LdapQuery *qry ) {
- g_return_if_fail( qry != NULL );
-
- /* Wait for thread */
- /* printf( "ldapqry_join_thread::Joining thread...\n" ); */
- pthread_join( * qry->thread, NULL );
- /* printf( "ldapqry_join_thread::Thread terminated\n" ); */
+ return ADDRQUERY_RETVAL(qry);
}
/**
LdapQuery *qry;
qry = ( LdapQuery * ) ptr;
- /*
- printf( "ldapqry_destroyer::%d::%s\n", (int) pthread_self(), qry->queryName );
- */
+ g_return_if_fail( qry != NULL );
+
+ debug_print("ldapqry_destroyer::%d::%s\n", (int) pthread_self(),
+ ADDRQUERY_NAME(qry)?ADDRQUERY_NAME(qry):"null");
/* Perform any destruction here */
if( qry->control != NULL ) {
qry->control = NULL;
qry->thread = NULL;
ldapqry_set_busy_flag( qry, FALSE );
- /*
- printf( "...destroy exiting\n" );
- */
}
/**
void ldapqry_cancel( LdapQuery *qry ) {
g_return_if_fail( qry != NULL );
- /*
- printf( "cancelling::%d::%s\n", (int) pthread_self(), qry->queryName );
- */
+ debug_print("cancelling::%d::%s\n", (int) pthread_self(),
+ ADDRQUERY_NAME(qry)?ADDRQUERY_NAME(qry):"null");
if( ldapqry_get_busy_flag( qry ) ) {
if( qry->thread ) {
+ debug_print("calling pthread_cancel\n");
pthread_cancel( * qry->thread );
}
}
* any LDAP queries to initialize thread specific data.
*/
void ldapqry_initialize( void ) {
- /* printf( "ldapqry_initialize...\n" ); */
+ debug_print("ldapqry_initialize...\n");
if( ! _queryThreadInit_ ) {
- /*
- printf( "ldapqry_initialize::creating thread specific area\n" );
- */
+ debug_print("ldapqry_initialize::creating thread specific area\n");
pthread_key_create( &_queryThreadKey_, ldapqry_destroyer );
_queryThreadInit_ = TRUE;
}
- /* printf( "ldapqry_initialize... done!\n" ); */
+ debug_print("ldapqry_initialize... done!\n");
}
/**
g_return_if_fail( qry != NULL );
- folder = qry->folder;
+ folder = ADDRQUERY_FOLDER(qry);
if( folder ) {
cache = qry->server->addressCache;
folder = addrcache_remove_folder_delete( cache, folder );
if( folder ) {
addritem_free_item_folder( folder );
}
- qry->folder = NULL;
+ ADDRQUERY_FOLDER(qry) = NULL;
+ }
+}
+
+/**
+ * Create a name/value pair object.
+ * \param n Name.
+ * \param v Value.
+ * \return Initialized object.
+ */
+static NameValuePair *ldapqry_create_name_value( const gchar *n, const gchar *v ) {
+ NameValuePair *nvp = g_new0( NameValuePair, 1 );
+
+ nvp->name = g_strdup( n );
+ nvp->value = g_strdup( v );
+ return nvp;
+}
+
+/**
+ * Free up name/value pair object.
+ * \param nvp Name/value object.
+ */
+void ldapqry_free_name_value( NameValuePair *nvp ) {
+ if( nvp ) {
+ g_free( nvp->name );
+ g_free( nvp->value );
+ nvp->name = nvp->value = NULL;
+ g_free( nvp );
}
}
+/**
+ * Free up a list name/value pair objects.
+ * \param list List of name/value objects.
+ */
+void ldapqry_free_list_name_value( GList *list ) {
+ GList *node;
+
+ node = list;
+ while( node ) {
+ NameValuePair *nvp = ( NameValuePair * ) node->data;
+ ldapqry_free_name_value( nvp );
+ node->data = NULL;
+ node = g_list_next( node );
+ }
+ g_list_free( list );
+}
+
+/**
+ * Load a list of name/value pairs from LDAP attributes.
+ * \param ld LDAP handle.
+ * \param e LDAP message.
+ * \param attr Attribute name.
+ * \param listValues List to populate.
+ * \return List of attribute name/value pairs.
+ */
+static GList *ldapqry_load_attrib_values(
+ LDAP *ld, LDAPMessage *entry, char *attr,
+ GList *listValues )
+{
+ GList *list = NULL;
+ gint i;
+ struct berval **vals;
+ NameValuePair *nvp;
+
+ list = listValues;
+ if( ( vals = ldap_get_values_len( ld, entry, attr ) ) != NULL ) {
+ for( i = 0; vals[i] != NULL; i++ ) {
+ gchar *tmp = g_strndup( vals[i]->bv_val, vals[i]->bv_len);
+ nvp = ldapqry_create_name_value( attr, tmp );
+ g_free(tmp);
+ list = g_list_append( list, nvp );
+ }
+ }
+ ldap_value_free_len( vals );
+ return list;
+}
+
+/**
+ * Fetch a list of all attributes.
+ * \param ld LDAP handle.
+ * \param e LDAP message.
+ * \return List of attribute name/value pairs.
+ */
+static GList *ldapqry_fetch_attribs( LDAP *ld, LDAPMessage *e )
+{
+ char *attribute;
+ BerElement *ber;
+ GList *listValues = NULL;
+
+ /* Process all attributes */
+ for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
+ attribute = ldap_next_attribute( ld, e, ber ) ) {
+ listValues = ldapqry_load_attrib_values( ld, e, attribute, listValues );
+ ldap_memfree( attribute );
+ }
+
+ /* Free up */
+ if( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ return listValues;
+}
+
+#define CRITERIA_SINGLE "(objectclass=*)"
+
+/**
+ * Perform the data retrieval for a specific LDAP record.
+ *
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_locate_retrieve( LdapQuery *qry ) {
+ LdapControl *ctl;
+ LDAP *ld;
+ LDAPMessage *result, *e = NULL;
+ gboolean entriesFound;
+ gboolean first;
+ struct timeval timeout;
+ gint rc;
+ gchar *dn;
+ GList *listValues;
+
+ /* Initialize some variables */
+ ld = qry->ldap;
+ ctl = qry->control;
+ dn = ADDRQUERY_SEARCHVALUE(qry);
+ timeout.tv_sec = ctl->timeOut;
+ timeout.tv_usec = 0L;
+ entriesFound = FALSE;
+
+ /*
+ * Execute the search - this step may take some time to complete
+ * depending on network traffic and server response time.
+ */
+ ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT;
+ rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_BASE, CRITERIA_SINGLE,
+ NULL, 0, NULL, NULL, &timeout, 0, &result );
+ if( rc == LDAP_TIMEOUT ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
+ if( rc != LDAP_SUCCESS ) {
+ debug_print("LDAP Error: ldap_search_st: %s\n", ldap_err2string(rc));
+ return ADDRQUERY_RETVAL(qry);
+ }
+
+ debug_print("Total results are: %d\n", ldap_count_entries(ld, result));
+
+ /* Process results */
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
+ first = TRUE;
+ while( TRUE ) {
+ ldapqry_touch( qry );
+ if( qry->entriesRead >= ctl->maxEntries ) break;
+
+ /* Test for stop */
+ if( ldapqry_get_stop_flag( qry ) ) {
+ break;
+ }
+
+ /* Retrieve entry */
+ if( first ) {
+ first = FALSE;
+ e = ldap_first_entry( ld, result );
+ }
+ else {
+ e = ldap_next_entry( ld, e );
+ }
+ if( e == NULL ) break;
+
+ entriesFound = TRUE;
+
+ /* Setup a critical section here */
+ pthread_mutex_lock( qry->mutexEntry );
+
+ /* Process entry */
+ listValues = ldapqry_fetch_attribs( ld, e );
+
+ /* Process callback */
+ if( qry->callBackEntry ) {
+ qry->callBackEntry( qry, ADDRQUERY_ID(qry), listValues, qry->data );
+ }
+ ldapqry_free_list_name_value( listValues );
+ listValues = NULL;
+
+ pthread_mutex_unlock( qry->mutexEntry );
+ }
+
+ /* Free up and disconnect */
+ ldap_msgfree( result );
+
+ if( entriesFound ) {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
+ }
+ else {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
+ }
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Perform the search to locate a specific LDAP record identified by
+ * distinguished name (dn).
+ *
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_perform_locate( LdapQuery *qry ) {
+ /* Connect */
+ qry->ldap = NULL;
+ ldapqry_connect( qry );
+ if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
+ /* Perform search */
+ ldapqry_locate_retrieve( qry );
+ }
+ /* Disconnect */
+ ldapqry_disconnect( qry );
+ qry->ldap = NULL;
+
+ /* Process callback */
+ if( qry->callBackEnd ) {
+ g_timeout_add(0, callbackend, qry);
+ }
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Remove results (folder and data) for specified LDAP query.
+ * \param qry Query object to process.
+ * \return TRUE if folder deleted successfully.
+ */
+gboolean ldapquery_remove_results( LdapQuery *qry ) {
+ gboolean retVal = FALSE;
+
+ ldapqry_set_aged_flag( qry, TRUE );
+
+ if( ldapqry_get_busy_flag( qry ) ) {
+ ldapqry_set_stop_flag( qry, TRUE );
+ }
+ else {
+ LdapServer *server = qry->server;
+ server->listQuery = g_list_remove(server->listQuery, qry);
+
+ retVal = TRUE;
+ }
+ return retVal;
+}
+
+void ldapqry_print(LdapQuery *qry, FILE *stream) {
+ g_return_if_fail( qry != NULL );
+
+ ldapsvr_print_data(qry->server, stream);
+ ldapctl_print(qry->control, stream);
+ fprintf(stream, "entriesRead: %d\n", qry->entriesRead);
+ fprintf(stream, "elapsedTime: %d\n", qry->elapsedTime);
+ fprintf(stream, "stopFlag: %d\n", qry->stopFlag);
+ fprintf(stream, "busyFlag: %d\n", qry->busyFlag);
+ fprintf(stream, "agedFlag: %d\n", qry->agedFlag);
+ fprintf(stream, "completed: %d\n", qry->completed);
+ fprintf(stream, "startTime: %d\n", (int) qry->startTime);
+ fprintf(stream, "touchTime: %d\n", (int) qry->touchTime);
+ fprintf(stream, "data: %s\n", qry->data?(gchar *)qry->data:"null");
+}
+
#endif /* USE_LDAP */
/*