/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001-2002 Match Grun
+ * Copyright (C) 2001-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 "defs.h"
#include <glib.h>
+#include <glib/gi18n.h>
-#include "intl.h"
#include "mgutils.h"
#include "addritem.h"
#include "addrcache.h"
#include "addrbook.h"
+#include "addressbook.h"
#include "addrindex.h"
#include "xml.h"
+#include "addrquery.h"
+#include "addr_compl.h"
+#include "utils.h"
+#include "alertpanel.h"
#ifndef DEV_STANDALONE
-#include "prefs.h"
+#include "prefs_gtk.h"
#include "codeconv.h"
#endif
#endif
#ifdef USE_LDAP
-#include "syldap.h"
+#include "ldapserver.h"
+#include "ldapctrl.h"
+#include "ldapquery.h"
+#include "ldapupdate.h"
+#include "ldaputil.h"
#endif
#define TAG_ADDRESS_INDEX "addressbook"
#define ATTAG_LDAP_CRITERIA "criteria"
#define ATTAG_LDAP_MAX_ENTRY "max-entry"
#define ATTAG_LDAP_TIMEOUT "timeout"
+#define ATTAG_LDAP_MAX_AGE "max-age"
+#define ATTAG_LDAP_DYN_SEARCH "dyn-search"
+#define ATTAG_LDAP_MATCH_OPT "match-opt"
+#define ATTAG_LDAP_ENABLE_TLS "enable-tls"
+#define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
-#if 0
-N_("Common address")
-N_("Personal address")
-#endif
+#define ELTAG_LDAP_ATTR_SRCH "attribute"
+#define ATTAG_LDAP_ATTR_NAME "name"
+
+/* Attribute values */
+#define ATVAL_BOOLEAN_YES "yes"
+#define ATVAL_BOOLEAN_NO "no"
+#define ATVAL_LDAP_MATCH_BEGIN "begin-with"
+#define ATVAL_LDAP_MATCH_CONTAINS "contains"
+
+/* New attributes */
+#define ATTAG_LDAP_DEFAULT "default"
-#define DISP_NEW_COMMON _("Common address")
-#define DISP_NEW_PERSONAL _("Personal address")
+#define DISP_NEW_COMMON _("Common addresses")
+#define DISP_NEW_PERSONAL _("Personal addresses")
/* Old address book */
#define TAG_IF_OLD_COMMON "common_address"
#define DISP_OLD_COMMON _("Common address")
#define DISP_OLD_PERSONAL _("Personal address")
+/**
+ * Singleton object.
+ */
+static AddressIndex *_addressIndex_ = NULL;
+
+/*
+ * Define attribute name-value pair.
+ */
typedef struct _AddressIfAttr AddressIfAttrib;
struct _AddressIfAttr {
gchar *name;
gchar *value;
};
+static AddressDataSource *addrindex_create_datasource ( AddressIfType ifType );
+
+static GList *addrindex_ds_get_all_persons ( AddressDataSource *ds );
+static GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
+static AddressDataSource *addrindex_get_datasource ( AddressIndex *addrIndex,
+ const gchar *cacheID );
+static AddressInterface *addrindex_get_interface ( AddressIndex *addrIndex,
+ AddressIfType ifType );
+static gint addrindex_write_to ( AddressIndex *addrIndex,
+ const gchar *newFile );
+
/*
-* Build interface with default values.
+ * Define DOM fragment.
+ */
+typedef struct _AddressIfFrag AddressIfFragment;
+struct _AddressIfFrag {
+ gchar *name;
+ GList *children;
+ GList *attributes;
+};
+
+/**
+ * Build interface with default values.
+ *
+ * \param type Interface type.
+ * \param name Interface name.
+ * \param tagIf XML tag name for interface in address index file.
+ * \param tagDS XML tag name for datasource in address index file.
+ * \return Address interface object.
*/
-static AddressInterface *addrindex_create_interface( gint type, gchar *name, gchar *tagIf, gchar *tagDS ) {
+static AddressInterface *addrindex_create_interface(
+ gint type, gchar *name, gchar *tagIf, gchar *tagDS )
+{
AddressInterface *iface = g_new0( AddressInterface, 1 );
+
ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
ADDRITEM_ID(iface) = NULL;
ADDRITEM_NAME(iface) = g_strdup( name );
iface->haveLibrary = TRUE;
iface->useInterface = TRUE;
iface->readOnly = TRUE;
+
+ /* Set callbacks to NULL values - override for each interface */
iface->getAccessFlag = NULL;
iface->getModifyFlag = NULL;
iface->getReadFlag = NULL;
iface->getAllGroups = NULL;
iface->getName = NULL;
iface->listSource = NULL;
+
+ /* Search stuff */
+ iface->externalQuery = FALSE;
+ iface->searchOrder = 0; /* Ignored */
+ iface->startSearch = NULL;
+ iface->stopSearch = NULL;
+
return iface;
}
-/*
-* Build table of interfaces.
-*/
+/**
+ * Build table of of all address book interfaces.
+ * \param addrIndex Address index object.
+ */
static void addrindex_build_if_list( AddressIndex *addrIndex ) {
AddressInterface *iface;
- iface = addrindex_create_interface( ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK, TAG_DS_ADDRESS_BOOK );
+ /* Create intrinsic XML address book interface */
+ iface = addrindex_create_interface(
+ ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
+ TAG_DS_ADDRESS_BOOK );
iface->readOnly = FALSE;
iface->getModifyFlag = ( void * ) addrbook_get_modified;
iface->getAccessFlag = ( void * ) addrbook_get_accessed;
iface->getListFolder = ( void * ) addrbook_get_list_folder;
iface->getListPerson = ( void * ) addrbook_get_list_person;
iface->getAllPersons = ( void * ) addrbook_get_all_persons;
+ iface->getAllGroups = ( void * ) addrbook_get_all_groups;
iface->getName = ( void * ) addrbook_get_name;
iface->setAccessFlag = ( void * ) addrbook_set_accessed;
- addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
+ iface->searchOrder = 0;
+
+ /* Add to list of interfaces in address book */
+ addrIndex->interfaceList =
+ g_list_append( addrIndex->interfaceList, iface );
ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
- iface = addrindex_create_interface( ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
+ /* Create vCard interface */
+ iface = addrindex_create_interface(
+ ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
iface->getModifyFlag = ( void * ) vcard_get_modified;
iface->getAccessFlag = ( void * ) vcard_get_accessed;
iface->getReadFlag = ( void * ) vcard_get_read_flag;
iface->getAllPersons = ( void * ) vcard_get_all_persons;
iface->getName = ( void * ) vcard_get_name;
iface->setAccessFlag = ( void * ) vcard_set_accessed;
- addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
+ iface->searchOrder = 0;
+ addrIndex->interfaceList =
+ g_list_append( addrIndex->interfaceList, iface );
ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
- iface = addrindex_create_interface( ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT, TAG_DS_JPILOT );
+ /* Create JPilot interface */
+ iface = addrindex_create_interface(
+ ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
+ TAG_DS_JPILOT );
#ifdef USE_JPILOT
iface->haveLibrary = jpilot_test_pilot_lib();
iface->useInterface = iface->haveLibrary;
iface->getAllPersons = ( void * ) jpilot_get_all_persons;
iface->getName = ( void * ) jpilot_get_name;
iface->setAccessFlag = ( void * ) jpilot_set_accessed;
+ iface->searchOrder = 0;
#else
iface->useInterface = FALSE;
iface->haveLibrary = FALSE;
#endif
- addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
+ addrIndex->interfaceList =
+ g_list_append( addrIndex->interfaceList, iface );
ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
- iface = addrindex_create_interface( ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
+ /* Create LDAP interface */
+ iface = addrindex_create_interface(
+ ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
#ifdef USE_LDAP
- iface->haveLibrary = syldap_test_ldap_lib();
+ iface->readOnly = FALSE;
+ /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
+ iface->haveLibrary = ldaputil_test_ldap_lib();
iface->useInterface = iface->haveLibrary;
- iface->getAccessFlag = ( void * ) syldap_get_accessed;
- /* iface->getModifyFlag = ( void * ) syldap_get_modified; */
- /* iface->getReadFlag = ( void * ) syldap_get_read_flag; */
- iface->getStatusCode = ( void * ) syldap_get_status;
- iface->getReadData = ( void * ) syldap_read_data;
- iface->getRootFolder = ( void * ) syldap_get_root_folder;
- iface->getListFolder = ( void * ) syldap_get_list_folder;
- iface->getListPerson = ( void * ) syldap_get_list_person;
- iface->getName = ( void * ) syldap_get_name;
- iface->setAccessFlag = ( void * ) syldap_set_accessed;
+ iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
+ iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
+ iface->getReadFlag = ( void * ) ldapsvr_get_read_flag;
+ iface->getStatusCode = ( void * ) ldapsvr_get_status;
+ iface->getReadData = ( void * ) ldapsvr_read_data;
+ iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
+ iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
+ iface->getListPerson = ( void * ) ldapsvr_get_list_person;
+ iface->getName = ( void * ) ldapsvr_get_name;
+ iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
+ iface->externalQuery = TRUE;
+ iface->searchOrder = 1;
#else
iface->useInterface = FALSE;
iface->haveLibrary = FALSE;
#endif
- addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
+ addrIndex->interfaceList =
+ g_list_append( addrIndex->interfaceList, iface );
ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
- /* Two old legacy data sources */
+ /* Two old legacy data sources (pre 0.7.0) */
iface = addrindex_create_interface(
ADDR_IF_COMMON, "Old Address - common",
TAG_IF_OLD_COMMON, NULL );
iface->legacyFlag = TRUE;
- addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
+ addrIndex->interfaceList =
+ g_list_append( addrIndex->interfaceList, iface );
ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
iface = addrindex_create_interface(
ADDR_IF_COMMON, "Old Address - personal",
TAG_IF_OLD_PERSONAL, NULL );
iface->legacyFlag = TRUE;
- addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
+ addrIndex->interfaceList =
+ g_list_append( addrIndex->interfaceList, iface );
ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
}
-/*
-* Free name-value pairs.
-*/
-static void addrindex_free_attributes( GList *list ) {
- GList *node = list;
+/**
+ * Free DOM fragment.
+ * \param fragment Fragment to free.
+ */
+static void addrindex_free_fragment( AddressIfFragment *fragment ) {
+ GList *node;
+
+ /* Free children */
+ node = fragment->children;
+ while( node ) {
+ AddressIfFragment *child = node->data;
+ addrindex_free_fragment( child );
+ node->data = NULL;
+ node = g_list_next( node );
+ }
+ g_list_free( fragment->children );
+
+ /* Free attributes */
+ node = fragment->attributes;
while( node ) {
AddressIfAttrib *nv = node->data;
- g_free( nv->name ); nv->name = NULL;
- g_free( nv->value ); nv->value = NULL;
+ g_free( nv->name );
+ g_free( nv->value );
g_free( nv );
node->data = NULL;
node = g_list_next( node );
}
- g_list_free( list );
+ g_list_free( fragment->attributes );
+
+ g_free( fragment->name );
+ fragment->name = NULL;
+ fragment->attributes = NULL;
+ fragment->children = NULL;
+
+ g_free( fragment );
}
-/*
-* Create new data source.
-* Enter: ifType Interface type to create.
-* Return: Initialized data source.
-*/
+/**
+ * Create a new data source.
+ * \param ifType Interface type to create.
+ * \return Initialized data source.
+ */
AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
AddressDataSource *ds = g_new0( AddressDataSource, 1 );
- ds = g_new0( AddressDataSource, 1 );
ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
ADDRITEM_ID(ds) = NULL;
ADDRITEM_NAME(ds) = NULL;
return ds;
}
-/*
-* Free up data source.
-*/
+/**
+ * Free up data source.
+ * \param ds Data source to free.
+ */
void addrindex_free_datasource( AddressDataSource *ds ) {
AddressInterface *iface;
g_return_if_fail( ds != NULL );
iface = ds->interface;
- if( iface == NULL ) return;
if( ds->rawDataSource != NULL ) {
- if( iface->useInterface ) {
- if( iface->type == ADDR_IF_BOOK ) {
- AddressBookFile *abf = ds->rawDataSource;
- addrbook_free_book( abf );
- }
- else if( iface->type == ADDR_IF_VCARD ) {
- VCardFile *vcf = ds->rawDataSource;
- vcard_free( vcf );
- }
+ if( iface != NULL ) {
+ if( iface->useInterface ) {
+ if( iface->type == ADDR_IF_BOOK ) {
+ AddressBookFile *abf = ds->rawDataSource;
+ addrbook_free_book( abf );
+ }
+ else if( iface->type == ADDR_IF_VCARD ) {
+ VCardFile *vcf = ds->rawDataSource;
+ vcard_free( vcf );
+ }
#ifdef USE_JPILOT
- else if( iface->type == ADDR_IF_JPILOT ) {
- JPilotFile *jpf = ds->rawDataSource;
- jpilot_free( jpf );
- }
+ else if( iface->type == ADDR_IF_JPILOT ) {
+ JPilotFile *jpf = ds->rawDataSource;
+ jpilot_free( jpf );
+ }
#endif
#ifdef USE_LDAP
- else if( iface->type == ADDR_IF_LDAP ) {
- SyldapServer *server = ds->rawDataSource;
- syldap_free( server );
- }
+ else if( iface->type == ADDR_IF_LDAP ) {
+ LdapServer *server = ds->rawDataSource;
+ ldapsvr_free( server );
+ }
#endif
- }
- else {
- GList *list = ds->rawDataSource;
- addrindex_free_attributes( list );
+ else {
+ }
+ }
+ else {
+ AddressIfFragment *fragment = ds->rawDataSource;
+ addrindex_free_fragment( fragment );
+ }
}
}
ds->type = ADDR_IF_NONE;
ds->interface = NULL;
ds->rawDataSource = NULL;
+
g_free( ds );
}
+/**
+ * Free up all data sources for specified interface.
+ * \param iface Address interface to process.
+ */
static void addrindex_free_all_datasources( AddressInterface *iface ) {
GList *node = iface->listSource;
while( node ) {
}
}
+/**
+ * Free up specified interface.
+ * \param iface Interface to process.
+ */
static void addrindex_free_interface( AddressInterface *iface ) {
+ /* Free up data sources */
addrindex_free_all_datasources( iface );
+ g_list_free( iface->listSource );
+ /* Free internal storage */
g_free( ADDRITEM_ID(iface) );
g_free( ADDRITEM_NAME(iface) );
g_free( iface->name );
g_free( iface->listTag );
g_free( iface->itemTag );
+ /* Clear all pointers */
ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
ADDRITEM_ID(iface) = NULL;
ADDRITEM_NAME(iface) = NULL;
iface->legacyFlag = FALSE;
iface->useInterface = FALSE;
iface->haveLibrary = FALSE;
-
- g_list_free( iface->listSource );
iface->listSource = NULL;
+
+ /* Search stuff */
+ iface->searchOrder = 0;
+ iface->startSearch = NULL;
+ iface->stopSearch = NULL;
+
+ g_free( iface );
}
-/*
+/**
* Return cache ID for specified data source.
- * Enter: addrIndex Address index.
- * ds Data source.
- * Return: ID or NULL if not found. This can be g_free() when done.
+ *
+ * \param addrIndex Address index.
+ * \param ds Data source.
+ * \return ID or NULL if not found. This should be <code>g_free()</code>
+ * when done.
*/
gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
gchar *cacheID = NULL;
return cacheID;
}
-/*
- * Return data source for specified cacheID.
- * Enter: addrIndex Address index.
- * cacheID ID.
- * Return: Data source, or NULL if not found.
+/**
+ * Return reference to data source for specified cacheID.
+ * \param addrIndex Address index.
+ * \param cacheID ID.
+ * \return Data source, or NULL if not found.
*/
-AddressDataSource *addrindex_get_datasource( AddressIndex *addrIndex, const gchar *cacheID ) {
+static AddressDataSource *addrindex_get_datasource(
+ AddressIndex *addrIndex, const gchar *cacheID )
+{
g_return_val_if_fail( addrIndex != NULL, NULL );
g_return_val_if_fail( cacheID != NULL, NULL );
return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
}
-/*
- * Return cache for specified cacheID.
- * Enter: addrIndex Address index.
- * cacheID ID.
- * Return: Address cache, or NULL if not found.
+/**
+ * Return reference to address cache for specified cacheID.
+ * \param addrIndex Address index.
+ * \param cacheID ID.
+ * \return Address cache, or NULL if not found.
*/
AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
AddressDataSource *ds;
return cache;
}
-/*
- * Add data source into hash.
- * Enter: addrIndex Address index.
- * ds Data source.
+/**
+ * Add data source into hash table.
+ * \param addrIndex Address index.
+ * \param ds Data source.
*/
-static addrindex_hash_add_cache( AddressIndex *addrIndex, AddressDataSource *ds ) {
+static void addrindex_hash_add_cache(
+ AddressIndex *addrIndex, AddressDataSource *ds )
+{
gchar *cacheID;
cacheID = addrindex_get_cache_id( addrIndex, ds );
}
/*
-* Free hash table callback function.
-*/
+ * Free hash table callback function.
+ */
static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
- printf( "free cache db: %s\n", key );
g_free( key );
key = NULL;
value = NULL;
}
/*
-* Free hash table of address cache items.
-*/
+ * Free hash table of address cache items.
+ */
static void addrindex_free_cache_hash( GHashTable *table ) {
- g_hash_table_freeze( table );
g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
- g_hash_table_thaw( table );
g_hash_table_destroy( table );
}
-/*
-* Remove address cache for specified data source from internal hashtable.
-*/
-static void addrindex_hash_remove_cache( AddressIndex *addrIndex, AddressDataSource *ds ) {
+/**
+ * Remove data source from internal hashtable.
+ * \param addrIndex Address index.
+ * \param ds Data source to remove.
+ */
+static void addrindex_hash_remove_cache(
+ AddressIndex *addrIndex, AddressDataSource *ds )
+{
gchar *cacheID;
cacheID = addrindex_get_cache_id( addrIndex, ds );
}
}
-/*
-* Create new object.
-*/
+/**
+ * Create a new address index. This is created as a singleton object.
+ * \return Initialized address index object.
+ */
AddressIndex *addrindex_create_index( void ) {
- AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
-
- ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
- ADDRITEM_ID(addrIndex) = NULL;
- ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
- ADDRITEM_PARENT(addrIndex) = NULL;
- ADDRITEM_SUBTYPE(addrIndex) = 0;
- addrIndex->filePath = NULL;
- addrIndex->fileName = NULL;
- addrIndex->retVal = MGU_SUCCESS;
- addrIndex->needsConversion = FALSE;
- addrIndex->wasConverted = FALSE;
- addrIndex->conversionError = FALSE;
- addrIndex->interfaceList = NULL;
- addrIndex->lastType = ADDR_IF_NONE;
- addrIndex->dirtyFlag = FALSE;
- addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
- addrindex_build_if_list( addrIndex );
- return addrIndex;
-}
-
-/*
-* Specify file to be used.
-*/
+ AddressIndex *index;
+
+ if( _addressIndex_ == NULL ) {
+ index = g_new0( AddressIndex, 1 );
+ ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
+ ADDRITEM_ID(index) = NULL;
+ ADDRITEM_NAME(index) = g_strdup( "Address Index" );
+ ADDRITEM_PARENT(index) = NULL;
+ ADDRITEM_SUBTYPE(index) = 0;
+ index->filePath = NULL;
+ index->fileName = NULL;
+ index->retVal = MGU_SUCCESS;
+ index->needsConversion = FALSE;
+ index->wasConverted = FALSE;
+ index->conversionError = FALSE;
+ index->interfaceList = NULL;
+ index->lastType = ADDR_IF_NONE;
+ index->dirtyFlag = FALSE;
+ index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
+ index->loadedFlag = FALSE;
+ index->searchOrder = NULL;
+ addrindex_build_if_list( index );
+ _addressIndex_ = index;
+ }
+ return _addressIndex_;
+}
+
+/**
+ * Property - Specify file path to address index file.
+ * \param addrIndex Address index.
+ * \param value Path to index file.
+ */
void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
g_return_if_fail( addrIndex != NULL );
addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
}
+
+/**
+ * Property - Specify file name to address index file.
+ * \param addrIndex Address index.
+ * \param value File name.
+ */
void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
g_return_if_fail( addrIndex != NULL );
addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
}
-void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
- g_return_if_fail( addrIndex != NULL );
- addrIndex->dirtyFlag = value;
-}
-/*
-* Return list of interfaces.
-*/
+/**
+ * Return list of address interfaces.
+ * \param addrIndex Address index.
+ * \return List of address interfaces.
+ */
GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
g_return_val_if_fail( addrIndex != NULL, NULL );
return addrIndex->interfaceList;
}
-/*
-* Free up object.
-*/
+/**
+ * Perform any other initialization of address index.
+ */
+void addrindex_initialize( void ) {
+ qrymgr_initialize();
+ addrcompl_initialize();
+}
+
+/**
+ * Perform any other teardown of address index.
+ */
+void addrindex_teardown( void ) {
+ addrcompl_teardown();
+ qrymgr_teardown();
+}
+
+/**
+ * Free up address index.
+ * \param addrIndex Address index.
+ */
void addrindex_free_index( AddressIndex *addrIndex ) {
GList *node;
g_return_if_fail( addrIndex != NULL );
+ /* Search stuff */
+ g_list_free( addrIndex->searchOrder );
+ addrIndex->searchOrder = NULL;
+
+ /* Free internal storage */
g_free( ADDRITEM_ID(addrIndex) );
g_free( ADDRITEM_NAME(addrIndex) );
g_free( addrIndex->filePath );
g_free( addrIndex->fileName );
+
+ /* Clear pointers */
ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
ADDRITEM_ID(addrIndex) = NULL;
ADDRITEM_NAME(addrIndex) = NULL;
addrIndex->conversionError = FALSE;
addrIndex->lastType = ADDR_IF_NONE;
addrIndex->dirtyFlag = FALSE;
+
+ /* Free up interfaces */
node = addrIndex->interfaceList;
while( node ) {
AddressInterface *iface = node->data;
}
g_list_free( addrIndex->interfaceList );
addrIndex->interfaceList = NULL;
+
+ /* Free up hash cache */
addrindex_free_cache_hash( addrIndex->hashCache );
addrIndex->hashCache = NULL;
+
+ addrIndex->loadedFlag = FALSE;
+
g_free( addrIndex );
+ addrIndex = NULL;
+ _addressIndex_ = NULL;
}
-/*
-* Print address index.
+/**
+ * Print address index.
+ * \param addrIndex Address index.
+ * \parem stream Stream to print.
*/
void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
g_return_if_fail( addrIndex != NULL );
fprintf( stream, "AddressIndex:\n" );
fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
- fprintf( stream, "\t status: %d : '%s'\n", addrIndex->retVal, mgu_error2string( addrIndex->retVal ) );
- fprintf( stream, "\tconverted: '%s'\n", addrIndex->wasConverted ? "yes" : "no" );
- fprintf( stream, "\tcvt error: '%s'\n", addrIndex->conversionError ? "yes" : "no" );
+ fprintf( stream, "\t status: %d\n", addrIndex->retVal );
+ fprintf( stream, "\tconverted: '%s'\n",
+ addrIndex->wasConverted ? "yes" : "no" );
+ fprintf( stream, "\tcvt error: '%s'\n",
+ addrIndex->conversionError ? "yes" : "no" );
fprintf( stream, "\t---\n" );
}
-/*
-* Retrieve specified interface from index.
-*/
-AddressInterface *addrindex_get_interface(
+/**
+ * Retrieve reference to address interface for specified interface type.
+ * \param addrIndex Address index.
+ * \param ifType Interface type.
+ * \return Address interface, or NULL if not found.
+ */
+static AddressInterface *addrindex_get_interface(
AddressIndex *addrIndex, AddressIfType ifType )
{
AddressInterface *retVal = NULL;
return retVal;
}
-/*
-* Add data source to index.
-* Enter: addrIndex Address index object.
-* ifType Interface type to add.
-* dataSource Actual data source to add.
-* Return: TRUE if data source was added.
-* Note: The raw data object (for example, AddressBookFile or VCardFile object) should be
-* supplied as the dataSource argument.
-*/
+/**
+ * Add raw data source to index. The raw data object (an AddressBookFile or
+ * VCardFile object, for example) should be supplied as the raw dataSource
+ * argument.
+ *
+ * \param addrIndex Address index.
+ * \param ifType Interface type to add.
+ * \param dataSource Actual raw data source to add.
+ * \return Data source added, or NULL if invalid interface type.
+ */
AddressDataSource *addrindex_index_add_datasource(
AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
{
return ds;
}
-/*
-* Remove data source from index.
-* Enter: addrIndex Address index object.
-* dataSource Data source to remove.
-* Return: Data source if removed, or NULL if data source was not found in
-* index. Note the this object must still be freed.
-*/
+/**
+ * Remove specified data source from index.
+ * \param addrIndex Address index.
+ * \param dataSource Data source to add.
+ * \return Reference to data source if removed, or NULL if data source was not
+ * found in index. Note the this object must still be freed.
+ */
AddressDataSource *addrindex_index_remove_datasource(
AddressIndex *addrIndex, AddressDataSource *dataSource )
{
return retVal;
}
+/**
+ * Retrieve a reference to address interface for specified interface type and
+ * XML interface tag name.
+ * \param addrIndex Address index.
+ * \param tag XML interface tag name to match.
+ * \param ifType Interface type to match.
+ * \return Reference to address index, or NULL if not found in index.
+ */
static AddressInterface *addrindex_tag_get_interface(
AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
{
return retVal;
}
+/**
+ * Retrieve a reference to address interface for specified interface type and
+ * XML datasource tag name.
+ * \param addrIndex Address index.
+ * \param ifType Interface type to match.
+ * \param tag XML datasource tag name to match.
+ * \return Reference to address index, or NULL if not found in index.
+ */
static AddressInterface *addrindex_tag_get_datasource(
AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
{
* Interface XML parsing functions.
* ***********************************************************************
*/
-/*
-static void show_attribs( GList *attr ) {
- while( attr ) {
- gchar *name = ((XMLAttr *)attr->data)->name;
- gchar *value = ((XMLAttr *)attr->data)->value;
- printf( "\tattr value : %s :%s:\n", name, value );
- attr = g_list_next( attr );
- }
- printf( "\t---\n" );
-}
-*/
-static void addrindex_write_elem_s( FILE *fp, gint lvl, gchar *name ) {
+/**
+ * Write start of XML element to file.
+ * \param fp File.
+ * \param lvl Indentation level.
+ * \param name Element name.
+ */
+static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
gint i;
for( i = 0; i < lvl; i++ ) fputs( " ", fp );
fputs( "<", fp );
fputs( name, fp );
}
-static void addrindex_write_elem_e( FILE *fp, gint lvl, gchar *name ) {
+/**
+ * Write end of XML element to file.
+ * \param fp File.
+ * \param lvl Indentation level.
+ * \param name Element name.
+ */
+static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
gint i;
for( i = 0; i < lvl; i++ ) fputs( " ", fp );
fputs( "</", fp );
fputs( ">\n", fp );
}
-static void addrindex_write_attr( FILE *fp, gchar *name, gchar *value ) {
+/**
+ * Write XML attribute to file.
+ * \param fp File.
+ * \param name Attribute name.
+ * \param value Attribute value.
+ */
+static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
fputs( " ", fp );
fputs( name, fp );
fputs( "=\"", fp );
fputs( "\"", fp );
}
-/*
-* Return list of name-value pairs.
-*/
-static GList *addrindex_read_attributes( XMLFile *file ) {
- GList *list = NULL;
+/**
+ * Return DOM fragment for current XML tag from file.
+ * \param file XML file being processed.
+ * \return Fragment representing DOM fragment for configuration element.
+ */
+static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
+ AddressIfFragment *fragment;
+ AddressIfFragment *child;
AddressIfAttrib *nv;
+ XMLTag *xtag;
+ GList *list;
GList *attr;
gchar *name;
gchar *value;
+ guint prevLevel;
+ gint rc;
+
+ /* g_print( "addrindex_read_fragment\n" ); */
+
+ prevLevel = file->level;
+
+ /* Get current tag name */
+ xtag = xml_get_current_tag( file );
+ /* Create new fragment */
+ fragment = g_new0( AddressIfFragment, 1 );
+ fragment->name = g_strdup( xtag->tag );
+ fragment->children = NULL;
+ fragment->attributes = NULL;
+
+ /* Read attributes */
+ list = NULL;
attr = xml_get_current_tag_attr( file );
while( attr ) {
name = ((XMLAttr *)attr->data)->name;
list = g_list_append( list, nv );
attr = g_list_next( attr );
}
- return list;
+ fragment->attributes = list;
+
+ /* Now read the children */
+ while( TRUE ) {
+ rc = xml_parse_next_tag( file );
+ if( rc != 0 ) {
+ /* End of file? */
+ break;
+ }
+ if( file->level < prevLevel ) {
+ /* We must be above level we start at */
+ break;
+ }
+ child = addrindex_read_fragment( file );
+ fragment->children = g_list_append( fragment->children, child );
+ }
+
+ return fragment;
}
-/*
-* Output name-value pairs.
-*/
-static void addrindex_write_attributes( FILE *fp, gchar *tag, GList *list, gint lvl ) {
+/**
+ * Write DOM fragment to file.
+ * \param fp File to write.
+ * \param fragment DOM fragment for configuration element.
+ * \param lvl Indent level.
+ */
+static void addrindex_write_fragment(
+ FILE *fp, const AddressIfFragment *fragment, const gint lvl )
+{
GList *node;
- AddressIfAttrib *nv;
- if( list ) {
- addrindex_write_elem_s( fp, lvl, tag );
- node = list;
+
+ if( fragment ) {
+ addrindex_write_elem_s( fp, lvl, fragment->name );
+ node = fragment->attributes;
while( node ) {
- nv = node->data;
+ AddressIfAttrib *nv = node->data;
addrindex_write_attr( fp, nv->name, nv->value );
node = g_list_next( node );
}
- fputs(" />\n", fp);
- }
-}
+ if( fragment->children ) {
+ fputs(" >\n", fp);
+
+ /* Output children */
+ node = fragment->children;
+ while( node ) {
+ AddressIfFragment *child = node->data;
+ addrindex_write_fragment( fp, child, 1+lvl );
+ node = g_list_next( node );
+ }
-/*
-static void addrindex_print_attributes( GList *list, FILE *stream ) {
- GList *node = list;
- while( node ) {
- AddressIfAttrib *nv = node->data;
- fprintf( stream, "%s : %s\n", nv->name, nv->value );
- node = g_list_next( node );
+ /* Output closing tag */
+ addrindex_write_elem_e( fp, lvl, fragment->name );
+ }
+ else {
+ fputs(" />\n", fp);
+ }
}
}
-*/
+/**
+ * Read/parse address index file, creating a data source for a regular
+ * intrinsic XML addressbook.
+ * \param file Address index file.
+ * \return Data source.
+ */
static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
AddressDataSource *ds;
AddressBookFile *abf;
ind = 1;
while( node ) {
gchar name[256];
- sprintf( name, "%s%d", ATTAG_JPILOT_CUSTOM, ind );
+ g_snprintf( name, sizeof(name), "%s%d",
+ ATTAG_JPILOT_CUSTOM, ind );
addrindex_write_attr( fp, name, node->data );
ind++;
node = g_list_next( node );
fputs( " />\n", fp );
}
}
+
#else
-/* Just read/write name-value pairs (preserve data found in file) */
+/*
+ * Just read/write DOM fragments (preserve data found in file).
+ */
static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
AddressDataSource *ds;
ds = addrindex_create_datasource( ADDR_IF_JPILOT );
- ds->rawDataSource = addrindex_read_attributes( file );
+ ds->rawDataSource = addrindex_read_fragment( file );
return ds;
}
static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
- GList *list = ds->rawDataSource;
- if( list ) {
- addrindex_write_attributes( fp, TAG_DS_JPILOT, list, lvl );
+ AddressIfFragment *fragment = ds->rawDataSource;
+ if( fragment ) {
+ addrindex_write_fragment( fp, fragment, lvl );
}
}
#endif
#ifdef USE_LDAP
+/**
+ * Parse LDAP criteria attribute data from XML file.
+ * \param file Index file.
+ * \param ctl LDAP control object to populate.
+ */
+static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
+ guint prevLevel;
+ XMLTag *xtag;
+ XMLTag *xtagPrev;
+ gint rc;
+ GList *attr;
+ GList *list;
+ GList *node;
+
+ if( file == NULL ) {
+ return;
+ }
+
+ list = NULL;
+ prevLevel = file->level;
+ xtagPrev = xml_get_current_tag( file );
+ while( TRUE ) {
+ rc = xml_parse_next_tag( file );
+ if( rc != 0 ) {
+ /* Terminate prematurely */
+ mgu_free_dlist( list );
+ list = NULL;
+ return;
+ }
+ if( file->level < prevLevel ) {
+ /* We must be above level we start at */
+ break;
+ }
+
+ /* Get a tag (element) */
+ xtag = xml_get_current_tag( file );
+ if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
+ /* LDAP criteria attribute */
+ attr = xml_get_current_tag_attr( file );
+ while( attr ) {
+ gchar *name = ((XMLAttr *)attr->data)->name;
+ gchar *value = ((XMLAttr *)attr->data)->value;
+ if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
+ if( value && strlen( value ) > 0 ) {
+ list = g_list_append(
+ list, g_strdup( value ) );
+ }
+ }
+ attr = g_list_next( attr );
+ }
+ }
+ else {
+ if( xtag != xtagPrev ) {
+ /* Found a new tag */
+ break;
+ }
+ }
+ xtag = xtagPrev;
+ }
+
+ /* Build list of search attributes */
+ ldapctl_criteria_list_clear( ctl );
+ node = list;
+ while( node ) {
+ ldapctl_criteria_list_add( ctl, node->data );
+ g_free( node->data );
+ node->data = NULL;
+ node = g_list_next( node );
+ }
+ g_list_free( list );
+ list = NULL;
+
+}
+
+void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
+/**
+ * Parse LDAP control data from XML file.
+ * \param file Index file.
+ * \return Initialized data soruce object.
+ */
static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
AddressDataSource *ds;
- SyldapServer *server;
+ LdapServer *server;
+ LdapControl *ctl;
GList *attr;
+ gchar *serverName = NULL;
+ gchar *criteria = NULL;
+ gboolean bDynSearch;
+ gboolean bTLS, bSSL;
+ gint iMatch;
+
+ /* g_print( "addrindex_parse_ldap\n" ); */
+ /* Set up some defaults */
+ bDynSearch = FALSE;
+ bTLS = FALSE;
+ bSSL = FALSE;
+ iMatch = LDAPCTL_MATCH_BEGINWITH;
ds = addrindex_create_datasource( ADDR_IF_LDAP );
- server = syldap_create();
+ ctl = ldapctl_create();
attr = xml_get_current_tag_attr( file );
while( attr ) {
gchar *name = ((XMLAttr *)attr->data)->name;
gchar *value = ((XMLAttr *)attr->data)->value;
gint ivalue = atoi( value );
+
if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
- syldap_set_name( server, value );
+ g_free( serverName );
+ serverName = g_strdup( value );
}
else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
- syldap_set_host( server, value );
+ ldapctl_set_host( ctl, value );
}
else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
- syldap_set_port( server, ivalue );
+ ldapctl_set_port( ctl, ivalue );
}
else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
- syldap_set_base_dn( server, value );
+ ldapctl_set_base_dn( ctl, value );
}
else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
- syldap_set_bind_dn( server, value );
+ ldapctl_set_bind_dn( ctl, value );
}
else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
- syldap_set_bind_password( server, value );
+ ldapctl_set_bind_password( ctl, value );
}
else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
- syldap_set_search_criteria( server, value );
+ g_free( criteria );
+ criteria = g_strdup( value );
+ g_print("criteria %s\n", criteria);
}
else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
- syldap_set_max_entries( server, ivalue );
+ ldapctl_set_max_entries( ctl, ivalue );
}
else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
- syldap_set_timeout( server, ivalue );
+ ldapctl_set_timeout( ctl, ivalue );
+ }
+ else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
+ ldapctl_set_max_query_age( ctl, ivalue );
+ }
+ else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
+ bDynSearch = FALSE;
+ if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
+ bDynSearch = TRUE;
+ }
+ }
+ else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
+ iMatch = LDAPCTL_MATCH_BEGINWITH;
+ if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
+ iMatch = LDAPCTL_MATCH_CONTAINS;
+ }
+ }
+ else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
+ bTLS = FALSE;
+ if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
+ bTLS = TRUE;
+ }
+ }
+ else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
+ bSSL = FALSE;
+ if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
+ bSSL = TRUE;
+ }
}
attr = g_list_next( attr );
}
+ server = ldapsvr_create_noctl();
+ ldapsvr_set_name( server, serverName );
+ ldapsvr_set_search_flag( server, bDynSearch );
+ ldapctl_set_matching_option( ctl, iMatch );
+#ifdef USE_LDAP_TLS
+ ldapctl_set_tls( ctl, bTLS );
+ ldapctl_set_ssl( ctl, bSSL );
+#endif
+ g_free( serverName );
+ ldapsvr_set_control( server, ctl );
ds->rawDataSource = server;
+
+ addrindex_parse_ldap_attrlist( file, ctl );
+ /*
+ * If criteria have been specified and no attributes were listed, then
+ * convert old style criteria into an attribute list. Any criteria will
+ * be dropped when saving data.
+ */
+ if( criteria ) {
+ if( ! ldapctl_get_criteria_list( ctl ) ) {
+ ldapctl_parse_ldap_search( ctl, criteria );
+ }
+ g_free( criteria );
+ }
+ /* ldapsvr_print_data( server, stdout ); */
+
return ds;
}
static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
- SyldapServer *server = ds->rawDataSource;
+ LdapServer *server = ds->rawDataSource;
+ LdapControl *ctl = NULL;
+ GList *node;
+ gchar value[256];
+
if( server ) {
- gchar value[256];
+ ctl = server->control;
+ }
+ if( ctl == NULL ) return;
+
+ /* Output start element with attributes */
+ addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
+ addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
+ addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
+
+ sprintf( value, "%d", ctl->port );
+ addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
+
+ addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
+ addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
+ addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
- addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
- addrindex_write_attr( fp, ATTAG_LDAP_NAME, syldap_get_name( server ) );
- addrindex_write_attr( fp, ATTAG_LDAP_HOST, server->hostName );
+ sprintf( value, "%d", ctl->maxEntries );
+ addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
+ sprintf( value, "%d", ctl->timeOut );
+ addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
+ sprintf( value, "%d", ctl->maxQueryAge );
+ addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
- sprintf( value, "%d", server->port );
- addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
+ addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
+ server->searchFlag ?
+ ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
- addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, server->baseDN );
- addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, server->bindDN );
- addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, server->bindPass );
- addrindex_write_attr( fp, ATTAG_LDAP_CRITERIA, server->searchCriteria );
+ addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
+ ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
+ ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
- sprintf( value, "%d", server->maxEntries );
- addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
- sprintf( value, "%d", server->timeOut );
- addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
+ addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
+ ctl->enableTLS ?
+ ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
+ addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
+ ctl->enableSSL ?
+ ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
+ fputs(" >\n", fp);
+
+ /* Output attributes */
+ node = ldapctl_get_criteria_list( ctl );
+ while( node ) {
+ addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
+ addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
fputs(" />\n", fp);
+ node = g_list_next( node );
}
+
+ /* End of element */
+ addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
}
+
#else
-/* Just read/write name-value pairs (preserve data found in file) */
+/*
+ * Just read/write DOM fragments (preserve data found in file).
+ */
static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
AddressDataSource *ds;
ds = addrindex_create_datasource( ADDR_IF_LDAP );
- ds->rawDataSource = addrindex_read_attributes( file );
+ ds->rawDataSource = addrindex_read_fragment( file );
return ds;
}
static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
- GList *list = ds->rawDataSource;
- if( list ) {
- addrindex_write_attributes( fp, TAG_DS_LDAP, list, lvl );
+ AddressIfFragment *fragment = ds->rawDataSource;
+ if( fragment ) {
+ addrindex_write_fragment( fp, fragment, lvl );
}
}
#endif
* Address index I/O functions.
* ***********************************************************************
*/
+/**
+ * Read address index file, creating appropriate data sources for each address
+ * index file entry.
+ *
+ * \param addrIndex Address index.
+ * \param file Address index file.
+ */
static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
guint prev_level;
XMLTag *xtag;
AddressInterface *iface = NULL, *dsIFace = NULL;
AddressDataSource *ds;
+ gint rc;
+ addrIndex->loadedFlag = FALSE;
for (;;) {
prev_level = file->level;
- xml_parse_next_tag( file );
- if( file->level < prev_level ) return;
+ rc = xml_parse_next_tag( file );
+ if( file->level == 0 ) return;
xtag = xml_get_current_tag( file );
}
}
}
- addrindex_read_index( addrIndex, file );
+ }
+}
+
+/*
+ * Search order sorting comparison function for building search order list.
+ */
+static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
+ AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
+ AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
+
+ return ifaceA->searchOrder - ifaceB->searchOrder;
+}
+
+/**
+ * Build list of data sources to process.
+ * \param addrIndex Address index object.
+ */
+static void addrindex_build_search_order( AddressIndex *addrIndex ) {
+ GList *nodeIf;
+
+ /* Clear existing list */
+ g_list_free( addrIndex->searchOrder );
+ addrIndex->searchOrder = NULL;
+
+ /* Build new list */
+ nodeIf = addrIndex->interfaceList;
+ while( nodeIf ) {
+ AddressInterface *iface = nodeIf->data;
+ if( iface->useInterface ) {
+ if( iface->searchOrder > 0 ) {
+ /* Add to search order list */
+ addrIndex->searchOrder = g_list_insert_sorted(
+ addrIndex->searchOrder, iface,
+ addrindex_search_order_compare );
+ }
+ }
+ nodeIf = g_list_next( nodeIf );
}
}
g_free( fileSpec );
if( file == NULL ) {
- /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
+ /*
+ g_print( " file '%s' does not exist.\n", addrIndex->fileName );
+ */
return addrIndex->retVal;
}
}
xml_close_file( file );
+ addrindex_build_search_order( addrIndex );
+
return addrIndex->retVal;
}
* return: Status code, from addrIndex->retVal.
* Note: File will be created in directory specified by addrIndex.
*/
-gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
+static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
FILE *fp;
gchar *fileSpec;
#ifndef DEV_STANDALONE
fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
addrIndex->retVal = MGU_OPEN_FILE;
#ifdef DEV_STANDALONE
- fp = fopen( fileSpec, "w" );
+ fp = g_fopen( fileSpec, "wb" );
g_free( fileSpec );
if( fp ) {
fputs( "<?xml version=\"1.0\" ?>\n", fp );
g_free( fileSpec );
if( pfile ) {
fp = pfile->fp;
- fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
- conv_get_current_charset_str() );
+ fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
#endif
addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
fputs( ">\n", fp );
#ifdef DEV_STANDALONE
fclose( fp );
#else
- if( prefs_write_close( pfile ) < 0 ) {
+ if( prefs_file_close( pfile ) < 0 ) {
addrIndex->retVal = MGU_ERROR_WRITE;
}
#endif
* return: Status code, from addrIndex->retVal.
*/
gint addrindex_save_data( AddressIndex *addrIndex ) {
+#ifdef USE_LDAP
+ GList *nodeIf;
+ GList *nodeDS;
+#endif
+
g_return_val_if_fail( addrIndex != NULL, -1 );
+#ifdef USE_LDAP
+ nodeIf = addrIndex->interfaceList;
+ /* save LDAP interfaces */
+ while ( nodeIf ) {
+ AddressInterface *iface = nodeIf->data;
+ if( iface->type == ADDR_IF_LDAP ) {
+ nodeDS = iface->listSource;
+ while( nodeDS ) {
+ AddressDataSource *ds = nodeDS->data;
+ LdapServer *abf = ds->rawDataSource;
+ if( ldapsvr_get_read_flag( abf ) ) {
+ if( ldapsvr_get_modified( abf ) ) {
+ ldapsvr_update_book( abf, NULL );
+ if( abf->retVal != LDAPRC_SUCCESS ) {
+ alertpanel( _("Address(es) update"),
+ _("Update failed. Changes not written to Directory."),
+ GTK_STOCK_CLOSE, NULL, NULL );
+ }
+ else {
+ abf->retVal = MGU_SUCCESS;
+ ldapsvr_set_modified( abf, FALSE );
+ }
+ }
+ }
+ nodeDS = g_list_next( nodeDS );
+ }
+ break;
+ }
+ nodeIf = g_list_next( nodeIf );
+ }
+#endif
addrIndex->retVal = MGU_NO_FILE;
if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
AddressDataSource *ds = nodeDS->data;
AddressBookFile *abf = ds->rawDataSource;
if( addrbook_get_dirty( abf ) ) {
- if( abf->readFlag ) {
+ if( addrbook_get_read_flag( abf ) ) {
addrbook_save_data( abf );
if( abf->retVal != MGU_SUCCESS ) {
retVal = abf->retVal;
if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
nn->remarks = g_strdup( element );
}
+ g_free(element);
xml_parse_next_tag(file);
}
}
node->list = g_list_append( node->list, newNode );
}
else {
- /* printf( "invalid: !!! \n" ); */
+ /* g_print( "invalid: !!! \n" ); */
attr = xml_get_current_tag_attr( file );
}
}
if (file->level < prev_level) return;
xtag = xml_get_current_tag( file );
- /* printf( "tag : %s\n", xtag->tag ); */
+ /* g_print( "tag : %s\n", xtag->tag ); */
element = xml_get_element( file );
attr = xml_get_current_tag_attr( file );
/* show_attribs( attr ); */
- /* printf( "\ttag value : %s :\n", element ); */
+ /* g_print( "\ttag value : %s :\n", element ); */
addrindex_consume_tree( file );
}
}
if (file->level < prev_level) return;
xtag = xml_get_current_tag( file );
- /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
+ /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
addrIndex->needsConversion = FALSE;
element = xml_get_element( file );
attr = xml_get_current_tag_attr( file );
/* show_attribs( attr ); */
- /* printf( "\ttag value : %s :\n", element ); */
+ /* g_print( "\ttag value : %s :\n", element ); */
addrindex_consume_tree( file );
}
}
g_free( fileSpec );
if( file == NULL ) {
- /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
+ /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
return addrIndex->retVal;
}
iface = ds->interface;
if( iface == NULL ) return retVal;
if( iface->getReadData ) {
+ /*
+ gchar *name = ( iface->getName ) ( ds->rawDataSource );
+ g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
+ */
retVal = ( iface->getReadData ) ( ds->rawDataSource );
}
return retVal;
return retVal;
}
-/*
- * Return list of folders for specified data source.
- */
-GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
- GList *retVal = FALSE;
- AddressInterface *iface;
-
- if( ds == NULL ) return retVal;
- iface = ds->interface;
- if( iface == NULL ) return retVal;
- if( iface->getListFolder ) {
- retVal = ( iface->getListFolder ) ( ds->rawDataSource );
- }
- return retVal;
-}
-
-/*
- * Return list of persons in root folder for specified data source.
- */
-GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
- GList *retVal = FALSE;
- AddressInterface *iface;
-
- if( ds == NULL ) return retVal;
- iface = ds->interface;
- if( iface == NULL ) return retVal;
- if( iface->getListPerson ) {
- retVal = ( iface->getListPerson ) ( ds->rawDataSource );
- }
- return retVal;
-}
-
/*
* Return name for specified data source.
*/
/*
* Return list of all persons for specified data source.
*/
-GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
+static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
GList *retVal = NULL;
AddressInterface *iface;
/*
* Return list of all groups for specified data source.
*/
-GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
+static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
GList *retVal = NULL;
AddressInterface *iface;
return retVal;
}
+/* **********************************************************************
+* Address search stuff.
+* ***********************************************************************
+*/
+
+/**
+ * Setup or register the dynamic search that will be performed. The search
+ * is registered with the query manager.
+ *
+ * \param searchTerm Search term. A private copy will be made.
+ * \param callBackEntry Callback function that should be called when
+ * each entry is received.
+ * \param callBackEnd Callback function that should be called when
+ * search has finished running.
+ * \return ID allocated to query that will be executed.
+ */
+gint addrindex_setup_search(
+ const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
+{
+ QueryRequest *req;
+ gint queryID;
+
+ /* Set up a dynamic address query */
+ req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
+ queryID = req->queryID;
+ qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
+
+ /* g_print( "***> query ID ::%d::\n", queryID ); */
+ return queryID;
+}
+
+#ifdef USE_LDAP
+
/*
-* End of Source.
+ * Function prototypes (not in header file or circular reference errors are
+ * encountered!)
+ */
+LdapQuery *ldapsvr_new_dynamic_search(
+ LdapServer *server, QueryRequest *req );
+LdapQuery *ldapsvr_new_explicit_search(
+ LdapServer *server, QueryRequest *req, ItemFolder *folder );
+void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
+
+#endif
+
+/**
+ * Execute the previously registered dynamic search.
+ *
+ * \param req Address query object to execute.
+ * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
+ * failed.
+ */
+static gboolean addrindex_start_dynamic( QueryRequest *req ) {
+ AddressInterface *iface;
+ AddressDataSource *ds;
+ GList *nodeIf;
+ GList *nodeDS;
+ gint type;
+
+ /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
+ nodeIf = _addressIndex_->searchOrder;
+ while( nodeIf ) {
+ iface = nodeIf->data;
+ nodeIf = g_list_next( nodeIf );
+
+ if( ! iface->useInterface ) {
+ continue;
+ }
+ if( ! iface->externalQuery ) {
+ continue;
+ }
+
+ type = iface->type;
+ nodeDS = iface->listSource;
+ while( nodeDS ) {
+ ds = nodeDS->data;
+ nodeDS = g_list_next( nodeDS );
+#ifdef USE_LDAP
+ if( type == ADDR_IF_LDAP ) {
+ LdapServer *server;
+ LdapQuery *qry;
+
+ server = ds->rawDataSource;
+ if( ! server->searchFlag ) {
+ continue;
+ }
+ if( ldapsvr_reuse_previous( server, req ) ) {
+ continue;
+ }
+
+ /* Start a new dynamic search */
+ qry = ldapsvr_new_dynamic_search( server, req );
+ if( qry ) {
+ ldapsvr_execute_query( server, qry );
+ }
+ }
+#endif
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Stop the previously registered search.
+ *
+ * \param queryID ID of search query to stop.
+ */
+void addrindex_stop_search( const gint queryID ){
+ QueryRequest *req;
+ AddrQueryObject *aqo;
+ GList *node;
+
+ /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
+ /* If query ID does not match, search has not been setup */
+ req = qrymgr_find_request( queryID );
+ if( req == NULL ) {
+ return;
+ }
+
+ /* Stop all queries that were associated with request */
+ node = req->queryList;
+ while( node ) {
+ aqo = node->data;
+#ifdef USE_LDAP
+ if( aqo->queryType == ADDRQUERY_LDAP ) {
+ LdapQuery *qry = ( LdapQuery * ) aqo;
+ ldapqry_set_stop_flag( qry, TRUE );
+ }
+#endif
+ node->data = NULL;
+ node = g_list_next( node );
+ }
+
+ /* Delete query request */
+ qrymgr_delete_request( queryID );
+}
+
+/**
+ * Setup or register the explicit search that will be performed. The search is
+ * registered with the query manager.
+ *
+ * \param ds Data source to search.
+ * \param searchTerm Search term to locate.
+ * \param folder Folder to receive search results; may be NULL.
+ * \param callbackEnd Function to call when search has terminated.
+ * \param callbackEntry Function to called for each entry processed.
+ * \return ID allocated to query that will be executed.
+ */
+gint addrindex_setup_explicit_search(
+ AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
+ void *callBackEnd, void *callBackEntry )
+{
+ QueryRequest *req;
+ gint queryID;
+ gchar *name;
+ gchar *mySearch;
+
+ /* Name the query */
+ name = g_strdup_printf( "Search '%s'", searchTerm );
+
+ /* Set up query request */
+ if (!strcmp(searchTerm, "*"))
+ mySearch = g_strdup("*@");
+ else
+ mySearch = g_strdup(searchTerm);
+
+ req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
+
+ g_free(mySearch);
+
+ qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
+ queryID = req->queryID;
+
+ if( ds->type == ADDR_IF_LDAP ) {
+#ifdef USE_LDAP
+ LdapServer *server;
+
+ server = ds->rawDataSource;
+ ldapsvr_new_explicit_search( server, req, folder );
+#endif
+ }
+ else {
+ qrymgr_delete_request( queryID );
+ queryID = 0;
+ }
+ g_free( name );
+
+ return queryID;
+}
+
+/**
+ * Execute the previously registered explicit search.
+ *
+ * \param req Address query request object to execute.
+ * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
+ * failed.
+ */
+static gboolean addrindex_start_explicit( QueryRequest *req ) {
+ gboolean retVal;
+ AddrQueryObject *aqo;
+
+ retVal = FALSE;
+
+ /* Note: there should only be one query in the list. */
+ aqo = req->queryList->data;
+#ifdef USE_LDAP
+ if( aqo->queryType == ADDRQUERY_LDAP ) {
+ LdapServer *server;
+ LdapQuery *qry;
+
+ qry = ( LdapQuery * ) aqo;
+ server = qry->server;
+
+ /* Start the search */
+ retVal = TRUE;
+ ldapsvr_execute_query( server, qry );
+ }
+#endif
+ return retVal;
+}
+
+/**
+ * Start the previously registered search.
+ *
+ * \param queryID ID of search query to be executed.
+ * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
+ * failed.
+ */
+gboolean addrindex_start_search( const gint queryID ) {
+ gboolean retVal;
+ QueryRequest *req;
+ AddrSearchType searchType;
+
+ retVal = FALSE;
+ /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
+ req = qrymgr_find_request( queryID );
+ if( req == NULL ) {
+ return retVal;
+ }
+
+ searchType = req->searchType;
+ if( searchType == ADDRSEARCH_DYNAMIC ) {
+ retVal = addrindex_start_dynamic( req );
+ }
+ else if( searchType == ADDRSEARCH_EXPLICIT ) {
+ retVal = addrindex_start_explicit( req );
+ }
+
+ return retVal;
+}
+
+/**
+ * Remove results (folder and data) for specified data source and folder.
+ * \param ds Data source to process.
+ * \param folder Results folder to remove.
+ */
+void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
+ AddrBookBase *adbase;
+ AddressCache *cache;
+ gint queryID = 0;
+
+ /* g_print( "addrindex_remove_results/start\n" ); */
+
+ /* Test for folder */
+ if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
+ /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
+ adbase = ( AddrBookBase * ) ds->rawDataSource;
+ if( adbase == NULL ) return;
+ cache = adbase->addressCache;
+
+ /* Hide folder to prevent re-display */
+ addritem_folder_set_hidden( folder, TRUE );
+
+ if( ds->type == ADDR_IF_LDAP ) {
+#ifdef USE_LDAP
+ LdapQuery *qry;
+ gboolean delFlag;
+
+ qry = ( LdapQuery * ) folder->folderData;
+ queryID = ADDRQUERY_ID(qry);
+ /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
+ delFlag = ldapquery_remove_results( qry );
+ if (delFlag) {
+ ldapqry_free( qry );
+ }
+ /* g_print( "calling ldapquery_remove_results...done\n" ); */
+ /*
+ if( delFlag ) {
+ g_print( "delFlag IS-TRUE\n" );
+ }
+ else {
+ g_print( "delFlag IS-FALSE\n" );
+ }
+ */
+#endif
+ }
+ /* g_print( "addrindex_remove_results/end\n" ); */
+
+ /* Delete query request */
+ if( queryID > 0 ) {
+ qrymgr_delete_request( queryID );
+ }
+}
+
+/* **********************************************************************
+* Address completion stuff.
+* ***********************************************************************
*/
+
+static void addrindex_load_completion_load_persons(
+ gint (*callBackFunc) ( const gchar *, const gchar *,
+ const gchar *, const gchar *, GList * ),
+ AddressDataSource *ds)
+{
+ GList *listP, *nodeP;
+ GList *nodeM;
+ gchar *sName;
+
+ /* Read address book */
+ if( addrindex_ds_get_modify_flag( ds ) ) {
+ addrindex_ds_read_data( ds );
+ }
+
+ if( ! addrindex_ds_get_read_flag( ds ) ) {
+ addrindex_ds_read_data( ds );
+ }
+
+ /* Get all groups */
+ listP = addrindex_ds_get_all_groups( ds );
+ nodeP = listP;
+ while( nodeP ) {
+ ItemGroup *group = nodeP->data;
+ GList *emails = NULL;
+ for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
+ ItemEMail *email = nodeM->data;
+ if (email->address)
+ emails = g_list_append(emails, email);
+ }
+ callBackFunc( ((AddrItemObject *)group)->name, NULL,
+ NULL, NULL, emails );
+ nodeP = g_list_next( nodeP );
+ }
+
+ /* Free up the list */
+ g_list_free( listP );
+ /* Get all persons */
+ listP = addrindex_ds_get_all_persons( ds );
+ nodeP = listP;
+ while( nodeP ) {
+ ItemPerson *person = nodeP->data;
+ nodeM = person->listEMail;
+
+ /* Figure out name to use */
+ sName = ADDRITEM_NAME(person);
+ if( sName == NULL || *sName == '\0' ) {
+ sName = person->nickName;
+ }
+
+ /* Process each E-Mail address */
+ while( nodeM ) {
+ ItemEMail *email = nodeM->data;
+
+ callBackFunc( sName, email->address, person->nickName,
+ ADDRITEM_NAME(email), NULL );
+
+ nodeM = g_list_next( nodeM );
+ }
+ nodeP = g_list_next( nodeP );
+ }
+
+ /* Free up the list */
+ g_list_free( listP );
+}
+
+/**
+ * This function is used by the address completion function to load
+ * addresses for all non-external address book interfaces.
+ *
+ * \param callBackFunc Function to be called when an address is
+ * to be loaded.
+ * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
+ * or "Any", assume the whole addressbook
+ * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
+ */
+
+gboolean addrindex_load_completion(
+ gint (*callBackFunc) ( const gchar *, const gchar *,
+ const gchar *, const gchar *, GList * ),
+ gchar *folderpath )
+{
+ GList *nodeIf, *nodeDS;
+
+ if( folderpath != NULL ) {
+ AddressDataSource *book;
+ ItemFolder* folder;
+
+ /* split the folder path we've received, we'll try to match this path, subpath by
+ subpath against the book/folder structure in order and restrict loading of
+ addresses to that subpart (if matches). book/folder path must exist and
+ folderpath must not be empty or NULL */
+
+ if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
+ g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath);
+ return FALSE;
+ }
+
+ if( folder != NULL ) {
+
+ GList *items;
+ GList *nodeM;
+ gchar *sName;
+ ItemPerson *person;
+
+ debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
+
+ /* Load email addresses */
+ items = addritem_folder_get_person_list( folder );
+ for( ; items != NULL; items = g_list_next( items ) ) {
+ person = items->data;
+ nodeM = person->listEMail;
+
+ /* Figure out name to use */
+ sName = ADDRITEM_NAME(person);
+ if( sName == NULL || *sName == '\0' ) {
+ sName = person->nickName;
+ }
+
+ /* Process each E-Mail address */
+ while( nodeM ) {
+ ItemEMail *email = nodeM->data;
+
+ callBackFunc( sName, email->address, person->nickName,
+ ADDRITEM_NAME(email), NULL );
+
+ nodeM = g_list_next( nodeM );
+ }
+ }
+ /* Free up the list */
+ mgu_clear_list( items );
+ g_list_free( items );
+
+ return TRUE;
+
+ } else {
+
+ if( book != NULL ) {
+
+ AddressBookFile *abf = book->rawDataSource;
+
+ debug_print("addrindex_load_completion: book %p '%s'\n", book, abf?abf->fileName:"(null)");
+
+ addrindex_load_completion_load_persons( callBackFunc, book );
+
+ return TRUE;
+
+ } else {
+ g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
+ }
+ }
+ return FALSE;
+
+ } else {
+
+ nodeIf = addrindex_get_interface_list( _addressIndex_ );
+ while( nodeIf ) {
+ AddressInterface *iface = nodeIf->data;
+
+ nodeIf = g_list_next( nodeIf );
+
+ if( ! iface->useInterface || iface->externalQuery )
+ continue;
+
+ nodeDS = iface->listSource;
+ while( nodeDS ) {
+ addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
+ nodeDS = g_list_next( nodeDS );
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * This function can be used to collect information about
+ * addressbook entries that contain a specific attribute.
+ *
+ * \param attr Name of attribute to look for
+ * \param callBackFunc Function to be called when a matching attribute was found
+ * \return <i>TRUE</i>
+ */
+gboolean addrindex_load_person_attribute(
+ const gchar *attr,
+ gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
+{
+ AddressDataSource *ds;
+ GList *nodeIf, *nodeDS;
+ GList *listP, *nodeP;
+ GList *nodeA;
+
+ nodeIf = addrindex_get_interface_list( _addressIndex_ );
+ while( nodeIf ) {
+ gchar *cur_bname;
+ AddressInterface *iface = nodeIf->data;
+
+ nodeIf = g_list_next( nodeIf );
+
+ if( ! iface->useInterface || iface->externalQuery )
+ continue;
+
+ nodeDS = iface->listSource;
+ while( nodeDS ) {
+ ds = nodeDS->data;
+
+ /* Read address book */
+ if( addrindex_ds_get_modify_flag( ds ) ) {
+ addrindex_ds_read_data( ds );
+ }
+
+ if( ! addrindex_ds_get_read_flag( ds ) ) {
+ addrindex_ds_read_data( ds );
+ }
+
+ /* Check addressbook name */
+ cur_bname = addrindex_ds_get_name( ds );
+
+ /* Get all persons */
+ listP = addrindex_ds_get_all_persons( ds );
+ nodeP = listP;
+ while( nodeP ) {
+ ItemPerson *person = nodeP->data;
+
+ /* Return all ItemPerson's if attr is NULL */
+ if( attr == NULL ) {
+ callBackFunc(person, cur_bname);
+ }
+
+ /* Return ItemPerson's with specific attribute */
+ else {
+ nodeA = person->listAttrib;
+ /* Process each User Attribute */
+ while( nodeA ) {
+ UserAttribute *attrib = nodeA->data;
+ if( attrib->name &&
+ !strcmp( attrib->name,attr ) ) {
+ callBackFunc(person, cur_bname);
+ }
+ nodeA = g_list_next( nodeA );
+ }
+ }
+ nodeP = g_list_next( nodeP );
+ }
+ /* Free up the list */
+ g_list_free( listP );
+
+ nodeDS = g_list_next( nodeDS );
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * End of Source.
+ */