2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2006 Match Grun and the Sylpheed-Claws team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * General functions for accessing address index file.
31 #include <glib/gi18n.h>
35 #include "addrcache.h"
37 #include "addrindex.h"
39 #include "addrquery.h"
40 #include "addr_compl.h"
43 #ifndef DEV_STANDALONE
44 #include "prefs_gtk.h"
55 #include "ldapserver.h"
57 #include "ldapquery.h"
61 #define TAG_ADDRESS_INDEX "addressbook"
63 #define TAG_IF_ADDRESS_BOOK "book_list"
64 #define TAG_IF_VCARD "vcard_list"
65 #define TAG_IF_JPILOT "jpilot_list"
66 #define TAG_IF_LDAP "ldap_list"
68 #define TAG_DS_ADDRESS_BOOK "book"
69 #define TAG_DS_VCARD "vcard"
70 #define TAG_DS_JPILOT "jpilot"
71 #define TAG_DS_LDAP "server"
73 /* XML Attribute names */
74 #define ATTAG_BOOK_NAME "name"
75 #define ATTAG_BOOK_FILE "file"
77 #define ATTAG_VCARD_NAME "name"
78 #define ATTAG_VCARD_FILE "file"
80 #define ATTAG_JPILOT_NAME "name"
81 #define ATTAG_JPILOT_FILE "file"
82 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
83 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
84 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
85 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
86 #define ATTAG_JPILOT_CUSTOM "custom-"
88 #define ATTAG_LDAP_NAME "name"
89 #define ATTAG_LDAP_HOST "host"
90 #define ATTAG_LDAP_PORT "port"
91 #define ATTAG_LDAP_BASE_DN "base-dn"
92 #define ATTAG_LDAP_BIND_DN "bind-dn"
93 #define ATTAG_LDAP_BIND_PASS "bind-pass"
94 #define ATTAG_LDAP_CRITERIA "criteria"
95 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
96 #define ATTAG_LDAP_TIMEOUT "timeout"
97 #define ATTAG_LDAP_MAX_AGE "max-age"
98 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
99 #define ATTAG_LDAP_MATCH_OPT "match-opt"
100 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
101 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
103 #define ELTAG_LDAP_ATTR_SRCH "attribute"
104 #define ATTAG_LDAP_ATTR_NAME "name"
106 /* Attribute values */
107 #define ATVAL_BOOLEAN_YES "yes"
108 #define ATVAL_BOOLEAN_NO "no"
109 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
110 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
113 #define ATTAG_LDAP_DEFAULT "default"
115 #define DISP_NEW_COMMON _("Common addresses")
116 #define DISP_NEW_PERSONAL _("Personal addresses")
118 /* Old address book */
119 #define TAG_IF_OLD_COMMON "common_address"
120 #define TAG_IF_OLD_PERSONAL "personal_address"
122 #define DISP_OLD_COMMON _("Common address")
123 #define DISP_OLD_PERSONAL _("Personal address")
128 static AddressIndex *_addressIndex_ = NULL;
131 * Define attribute name-value pair.
133 typedef struct _AddressIfAttr AddressIfAttrib;
134 struct _AddressIfAttr {
140 * Define DOM fragment.
142 typedef struct _AddressIfFrag AddressIfFragment;
143 struct _AddressIfFrag {
150 * Build interface with default values.
152 * \param type Interface type.
153 * \param name Interface name.
154 * \param tagIf XML tag name for interface in address index file.
155 * \param tagDS XML tag name for datasource in address index file.
156 * \return Address interface object.
158 static AddressInterface *addrindex_create_interface(
159 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
161 AddressInterface *iface = g_new0( AddressInterface, 1 );
163 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
164 ADDRITEM_ID(iface) = NULL;
165 ADDRITEM_NAME(iface) = g_strdup( name );
166 ADDRITEM_PARENT(iface) = NULL;
167 ADDRITEM_SUBTYPE(iface) = type;
169 iface->name = g_strdup( name );
170 iface->listTag = g_strdup( tagIf );
171 iface->itemTag = g_strdup( tagDS );
172 iface->legacyFlag = FALSE;
173 iface->haveLibrary = TRUE;
174 iface->useInterface = TRUE;
175 iface->readOnly = TRUE;
177 /* Set callbacks to NULL values - override for each interface */
178 iface->getAccessFlag = NULL;
179 iface->getModifyFlag = NULL;
180 iface->getReadFlag = NULL;
181 iface->getStatusCode = NULL;
182 iface->getReadData = NULL;
183 iface->getRootFolder = NULL;
184 iface->getListFolder = NULL;
185 iface->getListPerson = NULL;
186 iface->getAllPersons = NULL;
187 iface->getAllGroups = NULL;
188 iface->getName = NULL;
189 iface->listSource = NULL;
192 iface->externalQuery = FALSE;
193 iface->searchOrder = 0; /* Ignored */
194 iface->startSearch = NULL;
195 iface->stopSearch = NULL;
201 * Build table of of all address book interfaces.
202 * \param addrIndex Address index object.
204 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
205 AddressInterface *iface;
207 /* Create intrinsic XML address book interface */
208 iface = addrindex_create_interface(
209 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
210 TAG_DS_ADDRESS_BOOK );
211 iface->readOnly = FALSE;
212 iface->getModifyFlag = ( void * ) addrbook_get_modified;
213 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
214 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
215 iface->getStatusCode = ( void * ) addrbook_get_status;
216 iface->getReadData = ( void * ) addrbook_read_data;
217 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
218 iface->getListFolder = ( void * ) addrbook_get_list_folder;
219 iface->getListPerson = ( void * ) addrbook_get_list_person;
220 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
221 iface->getName = ( void * ) addrbook_get_name;
222 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
223 iface->searchOrder = 0;
225 /* Add to list of interfaces in address book */
226 addrIndex->interfaceList =
227 g_list_append( addrIndex->interfaceList, iface );
228 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
230 /* Create vCard interface */
231 iface = addrindex_create_interface(
232 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
233 iface->getModifyFlag = ( void * ) vcard_get_modified;
234 iface->getAccessFlag = ( void * ) vcard_get_accessed;
235 iface->getReadFlag = ( void * ) vcard_get_read_flag;
236 iface->getStatusCode = ( void * ) vcard_get_status;
237 iface->getReadData = ( void * ) vcard_read_data;
238 iface->getRootFolder = ( void * ) vcard_get_root_folder;
239 iface->getListFolder = ( void * ) vcard_get_list_folder;
240 iface->getListPerson = ( void * ) vcard_get_list_person;
241 iface->getAllPersons = ( void * ) vcard_get_all_persons;
242 iface->getName = ( void * ) vcard_get_name;
243 iface->setAccessFlag = ( void * ) vcard_set_accessed;
244 iface->searchOrder = 0;
245 addrIndex->interfaceList =
246 g_list_append( addrIndex->interfaceList, iface );
247 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
249 /* Create JPilot interface */
250 iface = addrindex_create_interface(
251 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
254 iface->haveLibrary = jpilot_test_pilot_lib();
255 iface->useInterface = iface->haveLibrary;
256 iface->getModifyFlag = ( void * ) jpilot_get_modified;
257 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
258 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
259 iface->getStatusCode = ( void * ) jpilot_get_status;
260 iface->getReadData = ( void * ) jpilot_read_data;
261 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
262 iface->getListFolder = ( void * ) jpilot_get_list_folder;
263 iface->getListPerson = ( void * ) jpilot_get_list_person;
264 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
265 iface->getName = ( void * ) jpilot_get_name;
266 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
267 iface->searchOrder = 0;
269 iface->useInterface = FALSE;
270 iface->haveLibrary = FALSE;
272 addrIndex->interfaceList =
273 g_list_append( addrIndex->interfaceList, iface );
274 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
276 /* Create LDAP interface */
277 iface = addrindex_create_interface(
278 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
280 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
281 iface->haveLibrary = ldaputil_test_ldap_lib();
282 iface->useInterface = iface->haveLibrary;
283 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
284 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
285 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
286 iface->getStatusCode = ( void * ) ldapsvr_get_status;
287 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
288 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
289 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
290 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
291 iface->getName = ( void * ) ldapsvr_get_name;
292 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
293 iface->externalQuery = TRUE;
294 iface->searchOrder = 1;
296 iface->useInterface = FALSE;
297 iface->haveLibrary = FALSE;
299 addrIndex->interfaceList =
300 g_list_append( addrIndex->interfaceList, iface );
301 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
303 /* Two old legacy data sources (pre 0.7.0) */
304 iface = addrindex_create_interface(
305 ADDR_IF_COMMON, "Old Address - common",
306 TAG_IF_OLD_COMMON, NULL );
307 iface->legacyFlag = TRUE;
308 addrIndex->interfaceList =
309 g_list_append( addrIndex->interfaceList, iface );
310 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
312 iface = addrindex_create_interface(
313 ADDR_IF_COMMON, "Old Address - personal",
314 TAG_IF_OLD_PERSONAL, NULL );
315 iface->legacyFlag = TRUE;
316 addrIndex->interfaceList =
317 g_list_append( addrIndex->interfaceList, iface );
318 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
324 * \param fragment Fragment to free.
326 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
330 node = fragment->children;
332 AddressIfFragment *child = node->data;
333 addrindex_free_fragment( child );
335 node = g_list_next( node );
337 g_list_free( fragment->children );
339 /* Free attributes */
340 node = fragment->attributes;
342 AddressIfAttrib *nv = node->data;
347 node = g_list_next( node );
349 g_list_free( fragment->attributes );
351 g_free( fragment->name );
352 fragment->name = NULL;
353 fragment->attributes = NULL;
354 fragment->children = NULL;
360 * Create a new data source.
361 * \param ifType Interface type to create.
362 * \return Initialized data source.
364 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
365 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
367 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
368 ADDRITEM_ID(ds) = NULL;
369 ADDRITEM_NAME(ds) = NULL;
370 ADDRITEM_PARENT(ds) = NULL;
371 ADDRITEM_SUBTYPE(ds) = 0;
373 ds->rawDataSource = NULL;
374 ds->interface = NULL;
379 * Free up data source.
380 * \param ds Data source to free.
382 void addrindex_free_datasource( AddressDataSource *ds ) {
383 AddressInterface *iface;
385 g_return_if_fail( ds != NULL );
387 iface = ds->interface;
388 if( ds->rawDataSource != NULL ) {
389 if( iface != NULL ) {
390 if( iface->useInterface ) {
391 if( iface->type == ADDR_IF_BOOK ) {
392 AddressBookFile *abf = ds->rawDataSource;
393 addrbook_free_book( abf );
395 else if( iface->type == ADDR_IF_VCARD ) {
396 VCardFile *vcf = ds->rawDataSource;
400 else if( iface->type == ADDR_IF_JPILOT ) {
401 JPilotFile *jpf = ds->rawDataSource;
406 else if( iface->type == ADDR_IF_LDAP ) {
407 LdapServer *server = ds->rawDataSource;
408 ldapsvr_free( server );
415 AddressIfFragment *fragment = ds->rawDataSource;
416 addrindex_free_fragment( fragment );
421 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
422 ADDRITEM_ID(ds) = NULL;
423 ADDRITEM_NAME(ds) = NULL;
424 ADDRITEM_PARENT(ds) = NULL;
425 ADDRITEM_SUBTYPE(ds) = 0;
426 ds->type = ADDR_IF_NONE;
427 ds->interface = NULL;
428 ds->rawDataSource = NULL;
434 * Free up all data sources for specified interface.
435 * \param iface Address interface to process.
437 static void addrindex_free_all_datasources( AddressInterface *iface ) {
438 GList *node = iface->listSource;
440 AddressDataSource *ds = node->data;
441 addrindex_free_datasource( ds );
443 node = g_list_next( node );
448 * Free up specified interface.
449 * \param iface Interface to process.
451 static void addrindex_free_interface( AddressInterface *iface ) {
452 /* Free up data sources */
453 addrindex_free_all_datasources( iface );
454 g_list_free( iface->listSource );
456 /* Free internal storage */
457 g_free( ADDRITEM_ID(iface) );
458 g_free( ADDRITEM_NAME(iface) );
459 g_free( iface->name );
460 g_free( iface->listTag );
461 g_free( iface->itemTag );
463 /* Clear all pointers */
464 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
465 ADDRITEM_ID(iface) = NULL;
466 ADDRITEM_NAME(iface) = NULL;
467 ADDRITEM_PARENT(iface) = NULL;
468 ADDRITEM_SUBTYPE(iface) = 0;
469 iface->type = ADDR_IF_NONE;
471 iface->listTag = NULL;
472 iface->itemTag = NULL;
473 iface->legacyFlag = FALSE;
474 iface->useInterface = FALSE;
475 iface->haveLibrary = FALSE;
476 iface->listSource = NULL;
479 iface->searchOrder = 0;
480 iface->startSearch = NULL;
481 iface->stopSearch = NULL;
487 * Return cache ID for specified data source.
489 * \param addrIndex Address index.
490 * \param ds Data source.
491 * \return ID or NULL if not found. This should be <code>g_free()</code>
494 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
495 gchar *cacheID = NULL;
496 AddrBookBase *adbase;
499 g_return_val_if_fail( addrIndex != NULL, NULL );
500 g_return_val_if_fail( ds != NULL, NULL );
502 adbase = ( AddrBookBase * ) ds->rawDataSource;
504 cache = adbase->addressCache;
506 cacheID = g_strdup( cache->cacheID );
514 * Return reference to data source for specified cacheID.
515 * \param addrIndex Address index.
517 * \return Data source, or NULL if not found.
519 AddressDataSource *addrindex_get_datasource(
520 AddressIndex *addrIndex, const gchar *cacheID )
522 g_return_val_if_fail( addrIndex != NULL, NULL );
523 g_return_val_if_fail( cacheID != NULL, NULL );
524 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
528 * Return reference to address cache for specified cacheID.
529 * \param addrIndex Address index.
531 * \return Address cache, or NULL if not found.
533 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
534 AddressDataSource *ds;
535 AddrBookBase *adbase;
538 g_return_val_if_fail( addrIndex != NULL, NULL );
539 g_return_val_if_fail( cacheID != NULL, NULL );
542 ds = addrindex_get_datasource( addrIndex, cacheID );
544 adbase = ( AddrBookBase * ) ds->rawDataSource;
545 cache = adbase->addressCache;
551 * Add data source into hash table.
552 * \param addrIndex Address index.
553 * \param ds Data source.
555 static void addrindex_hash_add_cache(
556 AddressIndex *addrIndex, AddressDataSource *ds )
560 cacheID = addrindex_get_cache_id( addrIndex, ds );
562 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
567 * Free hash table callback function.
569 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
577 * Free hash table of address cache items.
579 static void addrindex_free_cache_hash( GHashTable *table ) {
580 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
581 g_hash_table_destroy( table );
585 * Remove data source from internal hashtable.
586 * \param addrIndex Address index.
587 * \param ds Data source to remove.
589 static void addrindex_hash_remove_cache(
590 AddressIndex *addrIndex, AddressDataSource *ds )
594 cacheID = addrindex_get_cache_id( addrIndex, ds );
596 g_hash_table_remove( addrIndex->hashCache, cacheID );
603 * Create a new address index. This is created as a singleton object.
604 * \return Initialized address index object.
606 AddressIndex *addrindex_create_index( void ) {
609 if( _addressIndex_ == NULL ) {
610 index = g_new0( AddressIndex, 1 );
611 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
612 ADDRITEM_ID(index) = NULL;
613 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
614 ADDRITEM_PARENT(index) = NULL;
615 ADDRITEM_SUBTYPE(index) = 0;
616 index->filePath = NULL;
617 index->fileName = NULL;
618 index->retVal = MGU_SUCCESS;
619 index->needsConversion = FALSE;
620 index->wasConverted = FALSE;
621 index->conversionError = FALSE;
622 index->interfaceList = NULL;
623 index->lastType = ADDR_IF_NONE;
624 index->dirtyFlag = FALSE;
625 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
626 index->loadedFlag = FALSE;
627 index->searchOrder = NULL;
628 addrindex_build_if_list( index );
629 _addressIndex_ = index;
631 return _addressIndex_;
635 * Return reference to address index.
636 * \return Address index object.
638 AddressIndex *addrindex_get_object( void ) {
639 return _addressIndex_;
643 * Property - Specify file path to address index file.
644 * \param addrIndex Address index.
645 * \param value Path to index file.
647 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
648 g_return_if_fail( addrIndex != NULL );
649 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
653 * Property - Specify file name to address index file.
654 * \param addrIndex Address index.
655 * \param value File name.
657 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
658 g_return_if_fail( addrIndex != NULL );
659 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
663 * Property - Specify file path to be used.
664 * \param addrIndex Address index.
665 * \param value Path to JPilot file.
667 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
668 g_return_if_fail( addrIndex != NULL );
669 addrIndex->dirtyFlag = value;
673 * Property - get loaded flag. Note that this flag is set after reading data
674 * from the address books.
675 * \param addrIndex Address index.
676 * \return <i>TRUE</i> if address index data was loaded.
678 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
679 g_return_val_if_fail( addrIndex != NULL, FALSE );
680 return addrIndex->loadedFlag;
684 * Return list of address interfaces.
685 * \param addrIndex Address index.
686 * \return List of address interfaces.
688 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
689 g_return_val_if_fail( addrIndex != NULL, NULL );
690 return addrIndex->interfaceList;
694 * Perform any other initialization of address index.
696 void addrindex_initialize( void ) {
698 addrcompl_initialize();
702 * Perform any other teardown of address index.
704 void addrindex_teardown( void ) {
705 addrcompl_teardown();
710 * Free up address index.
711 * \param addrIndex Address index.
713 void addrindex_free_index( AddressIndex *addrIndex ) {
716 g_return_if_fail( addrIndex != NULL );
719 g_list_free( addrIndex->searchOrder );
720 addrIndex->searchOrder = NULL;
722 /* Free internal storage */
723 g_free( ADDRITEM_ID(addrIndex) );
724 g_free( ADDRITEM_NAME(addrIndex) );
725 g_free( addrIndex->filePath );
726 g_free( addrIndex->fileName );
729 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
730 ADDRITEM_ID(addrIndex) = NULL;
731 ADDRITEM_NAME(addrIndex) = NULL;
732 ADDRITEM_PARENT(addrIndex) = NULL;
733 ADDRITEM_SUBTYPE(addrIndex) = 0;
734 addrIndex->filePath = NULL;
735 addrIndex->fileName = NULL;
736 addrIndex->retVal = MGU_SUCCESS;
737 addrIndex->needsConversion = FALSE;
738 addrIndex->wasConverted = FALSE;
739 addrIndex->conversionError = FALSE;
740 addrIndex->lastType = ADDR_IF_NONE;
741 addrIndex->dirtyFlag = FALSE;
743 /* Free up interfaces */
744 node = addrIndex->interfaceList;
746 AddressInterface *iface = node->data;
747 addrindex_free_interface( iface );
748 node = g_list_next( node );
750 g_list_free( addrIndex->interfaceList );
751 addrIndex->interfaceList = NULL;
753 /* Free up hash cache */
754 addrindex_free_cache_hash( addrIndex->hashCache );
755 addrIndex->hashCache = NULL;
757 addrIndex->loadedFlag = FALSE;
761 _addressIndex_ = NULL;
765 * Print address index.
766 * \param addrIndex Address index.
767 * \parem stream Stream to print.
769 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
770 g_return_if_fail( addrIndex != NULL );
771 fprintf( stream, "AddressIndex:\n" );
772 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
773 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
774 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
775 fprintf( stream, "\tconverted: '%s'\n",
776 addrIndex->wasConverted ? "yes" : "no" );
777 fprintf( stream, "\tcvt error: '%s'\n",
778 addrIndex->conversionError ? "yes" : "no" );
779 fprintf( stream, "\t---\n" );
783 * Retrieve reference to address interface for specified interface type.
784 * \param addrIndex Address index.
785 * \param ifType Interface type.
786 * \return Address interface, or NULL if not found.
788 AddressInterface *addrindex_get_interface(
789 AddressIndex *addrIndex, AddressIfType ifType )
791 AddressInterface *retVal = NULL;
794 g_return_val_if_fail( addrIndex != NULL, NULL );
796 node = addrIndex->interfaceList;
798 AddressInterface *iface = node->data;
799 node = g_list_next( node );
800 if( iface->type == ifType ) {
809 * Add raw data source to index. The raw data object (an AddressBookFile or
810 * VCardFile object, for example) should be supplied as the raw dataSource
813 * \param addrIndex Address index.
814 * \param ifType Interface type to add.
815 * \param dataSource Actual raw data source to add.
816 * \return Data source added, or NULL if invalid interface type.
818 AddressDataSource *addrindex_index_add_datasource(
819 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
821 AddressInterface *iface;
822 AddressDataSource *ds = NULL;
824 g_return_val_if_fail( addrIndex != NULL, NULL );
825 g_return_val_if_fail( dataSource != NULL, NULL );
827 iface = addrindex_get_interface( addrIndex, ifType );
829 ds = addrindex_create_datasource( ifType );
830 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
832 ds->rawDataSource = dataSource;
833 ds->interface = iface;
834 iface->listSource = g_list_append( iface->listSource, ds );
835 addrIndex->dirtyFlag = TRUE;
837 addrindex_hash_add_cache( addrIndex, ds );
843 * Remove specified data source from index.
844 * \param addrIndex Address index.
845 * \param dataSource Data source to add.
846 * \return Reference to data source if removed, or NULL if data source was not
847 * found in index. Note the this object must still be freed.
849 AddressDataSource *addrindex_index_remove_datasource(
850 AddressIndex *addrIndex, AddressDataSource *dataSource )
852 AddressDataSource *retVal = FALSE;
853 AddressInterface *iface;
855 g_return_val_if_fail( addrIndex != NULL, NULL );
856 g_return_val_if_fail( dataSource != NULL, NULL );
858 iface = addrindex_get_interface( addrIndex, dataSource->type );
860 iface->listSource = g_list_remove( iface->listSource, dataSource );
861 addrIndex->dirtyFlag = TRUE;
862 dataSource->interface = NULL;
864 /* Remove cache from hash table */
865 addrindex_hash_remove_cache( addrIndex, dataSource );
873 * Retrieve a reference to address interface for specified interface type and
874 * XML interface tag name.
875 * \param addrIndex Address index.
876 * \param tag XML interface tag name to match.
877 * \param ifType Interface type to match.
878 * \return Reference to address index, or NULL if not found in index.
880 static AddressInterface *addrindex_tag_get_interface(
881 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
883 AddressInterface *retVal = NULL;
884 GList *node = addrIndex->interfaceList;
887 AddressInterface *iface = node->data;
888 node = g_list_next( node );
890 if( strcmp( iface->listTag, tag ) == 0 ) {
896 if( iface->type == ifType ) {
906 * Retrieve a reference to address interface for specified interface type and
907 * XML datasource tag name.
908 * \param addrIndex Address index.
909 * \param ifType Interface type to match.
910 * \param tag XML datasource tag name to match.
911 * \return Reference to address index, or NULL if not found in index.
913 static AddressInterface *addrindex_tag_get_datasource(
914 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
916 AddressInterface *retVal = NULL;
917 GList *node = addrIndex->interfaceList;
920 AddressInterface *iface = node->data;
921 node = g_list_next( node );
922 if( iface->type == ifType && iface->itemTag ) {
923 if( strcmp( iface->itemTag, tag ) == 0 ) {
932 /* **********************************************************************
933 * Interface XML parsing functions.
934 * ***********************************************************************
938 * Write start of XML element to file.
940 * \param lvl Indentation level.
941 * \param name Element name.
943 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
945 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
951 * Write end of XML element to file.
953 * \param lvl Indentation level.
954 * \param name Element name.
956 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
958 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
965 * Write XML attribute to file.
967 * \param name Attribute name.
968 * \param value Attribute value.
970 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
974 xml_file_put_escape_str( fp, value );
979 * Return DOM fragment for current XML tag from file.
980 * \param file XML file being processed.
981 * \return Fragment representing DOM fragment for configuration element.
983 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
984 AddressIfFragment *fragment;
985 AddressIfFragment *child;
995 /* printf( "addrindex_read_fragment\n" ); */
997 prevLevel = file->level;
999 /* Get current tag name */
1000 xtag = xml_get_current_tag( file );
1002 /* Create new fragment */
1003 fragment = g_new0( AddressIfFragment, 1 );
1004 fragment->name = g_strdup( xtag->tag );
1005 fragment->children = NULL;
1006 fragment->attributes = NULL;
1008 /* Read attributes */
1010 attr = xml_get_current_tag_attr( file );
1012 name = ((XMLAttr *)attr->data)->name;
1013 value = ((XMLAttr *)attr->data)->value;
1014 nv = g_new0( AddressIfAttrib, 1 );
1015 nv->name = g_strdup( name );
1016 nv->value = g_strdup( value );
1017 list = g_list_append( list, nv );
1018 attr = g_list_next( attr );
1020 fragment->attributes = list;
1022 /* Now read the children */
1024 rc = xml_parse_next_tag( file );
1029 if( file->level < prevLevel ) {
1030 /* We must be above level we start at */
1033 child = addrindex_read_fragment( file );
1034 fragment->children = g_list_append( fragment->children, child );
1041 * Write DOM fragment to file.
1042 * \param fp File to write.
1043 * \param fragment DOM fragment for configuration element.
1044 * \param lvl Indent level.
1046 static void addrindex_write_fragment(
1047 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1052 addrindex_write_elem_s( fp, lvl, fragment->name );
1053 node = fragment->attributes;
1055 AddressIfAttrib *nv = node->data;
1056 addrindex_write_attr( fp, nv->name, nv->value );
1057 node = g_list_next( node );
1059 if( fragment->children ) {
1062 /* Output children */
1063 node = fragment->children;
1065 AddressIfFragment *child = node->data;
1066 addrindex_write_fragment( fp, child, 1+lvl );
1067 node = g_list_next( node );
1070 /* Output closing tag */
1071 addrindex_write_elem_e( fp, lvl, fragment->name );
1080 * Read/parse address index file, creating a data source for a regular
1081 * intrinsic XML addressbook.
1082 * \param file Address index file.
1083 * \return Data source.
1085 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1086 AddressDataSource *ds;
1087 AddressBookFile *abf;
1090 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1091 abf = addrbook_create_book();
1092 attr = xml_get_current_tag_attr( file );
1094 gchar *name = ((XMLAttr *)attr->data)->name;
1095 gchar *value = ((XMLAttr *)attr->data)->value;
1096 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1097 addrbook_set_name( abf, value );
1099 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1100 addrbook_set_file( abf, value );
1102 attr = g_list_next( attr );
1104 ds->rawDataSource = abf;
1108 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1109 AddressBookFile *abf = ds->rawDataSource;
1111 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1112 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1113 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1114 fputs( " />\n", fp );
1118 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1119 AddressDataSource *ds;
1123 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1124 vcf = vcard_create();
1125 attr = xml_get_current_tag_attr( file );
1127 gchar *name = ((XMLAttr *)attr->data)->name;
1128 gchar *value = ((XMLAttr *)attr->data)->value;
1129 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1130 vcard_set_name( vcf, value );
1132 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1133 vcard_set_file( vcf, value );
1135 attr = g_list_next( attr );
1137 ds->rawDataSource = vcf;
1141 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1142 VCardFile *vcf = ds->rawDataSource;
1144 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1145 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1146 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1147 fputs( " />\n", fp );
1152 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1153 AddressDataSource *ds;
1157 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1158 jpf = jpilot_create();
1159 attr = xml_get_current_tag_attr( file );
1161 gchar *name = ((XMLAttr *)attr->data)->name;
1162 gchar *value = ((XMLAttr *)attr->data)->value;
1163 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1164 jpilot_set_name( jpf, value );
1166 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1167 jpilot_set_file( jpf, value );
1169 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1170 jpilot_add_custom_label( jpf, value );
1172 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1173 jpilot_add_custom_label( jpf, value );
1175 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1176 jpilot_add_custom_label( jpf, value );
1178 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1179 jpilot_add_custom_label( jpf, value );
1181 attr = g_list_next( attr );
1183 ds->rawDataSource = jpf;
1187 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1188 JPilotFile *jpf = ds->rawDataSource;
1192 GList *customLbl = jpilot_get_custom_labels( jpf );
1193 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1194 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1195 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1200 g_snprintf( name, sizeof(name), "%s%d",
1201 ATTAG_JPILOT_CUSTOM, ind );
1202 addrindex_write_attr( fp, name, node->data );
1204 node = g_list_next( node );
1206 fputs( " />\n", fp );
1212 * Just read/write DOM fragments (preserve data found in file).
1214 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1215 AddressDataSource *ds;
1217 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1218 ds->rawDataSource = addrindex_read_fragment( file );
1222 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1223 AddressIfFragment *fragment = ds->rawDataSource;
1225 addrindex_write_fragment( fp, fragment, lvl );
1232 * Parse LDAP criteria attribute data from XML file.
1233 * \param file Index file.
1234 * \param ctl LDAP control object to populate.
1236 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1245 if( file == NULL ) {
1250 prevLevel = file->level;
1251 xtagPrev = xml_get_current_tag( file );
1253 rc = xml_parse_next_tag( file );
1255 /* Terminate prematurely */
1256 mgu_free_dlist( list );
1260 if( file->level < prevLevel ) {
1261 /* We must be above level we start at */
1265 /* Get a tag (element) */
1266 xtag = xml_get_current_tag( file );
1267 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1268 /* LDAP criteria attribute */
1269 attr = xml_get_current_tag_attr( file );
1271 gchar *name = ((XMLAttr *)attr->data)->name;
1272 gchar *value = ((XMLAttr *)attr->data)->value;
1273 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1274 if( value && strlen( value ) > 0 ) {
1275 list = g_list_append(
1276 list, g_strdup( value ) );
1279 attr = g_list_next( attr );
1283 if( xtag != xtagPrev ) {
1284 /* Found a new tag */
1291 /* Build list of search attributes */
1292 ldapctl_criteria_list_clear( ctl );
1295 ldapctl_criteria_list_add( ctl, node->data );
1296 g_free( node->data );
1298 node = g_list_next( node );
1300 g_list_free( list );
1305 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1307 * Parse LDAP control data from XML file.
1308 * \param file Index file.
1309 * \return Initialized data soruce object.
1311 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1312 AddressDataSource *ds;
1316 gchar *serverName = NULL;
1317 gchar *criteria = NULL;
1318 gboolean bDynSearch;
1319 gboolean bTLS, bSSL;
1322 /* printf( "addrindex_parse_ldap\n" ); */
1323 /* Set up some defaults */
1327 iMatch = LDAPCTL_MATCH_BEGINWITH;
1329 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1330 ctl = ldapctl_create();
1331 attr = xml_get_current_tag_attr( file );
1333 gchar *name = ((XMLAttr *)attr->data)->name;
1334 gchar *value = ((XMLAttr *)attr->data)->value;
1335 gint ivalue = atoi( value );
1337 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1338 g_free( serverName );
1339 serverName = g_strdup( value );
1341 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1342 ldapctl_set_host( ctl, value );
1344 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1345 ldapctl_set_port( ctl, ivalue );
1347 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1348 ldapctl_set_base_dn( ctl, value );
1350 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1351 ldapctl_set_bind_dn( ctl, value );
1353 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1354 ldapctl_set_bind_password( ctl, value );
1356 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1358 criteria = g_strdup( value );
1360 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1361 ldapctl_set_max_entries( ctl, ivalue );
1363 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1364 ldapctl_set_timeout( ctl, ivalue );
1366 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1367 ldapctl_set_max_query_age( ctl, ivalue );
1369 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1371 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1375 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1376 iMatch = LDAPCTL_MATCH_BEGINWITH;
1377 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1378 iMatch = LDAPCTL_MATCH_CONTAINS;
1381 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1383 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1387 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1389 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1393 attr = g_list_next( attr );
1396 server = ldapsvr_create_noctl();
1397 ldapsvr_set_name( server, serverName );
1398 ldapsvr_set_search_flag( server, bDynSearch );
1399 ldapctl_set_matching_option( ctl, iMatch );
1401 ldapctl_set_tls( ctl, bTLS );
1402 ldapctl_set_ssl( ctl, bSSL );
1404 g_free( serverName );
1405 ldapsvr_set_control( server, ctl );
1406 ds->rawDataSource = server;
1408 addrindex_parse_ldap_attrlist( file, ctl );
1410 * If criteria have been specified and no attributes were listed, then
1411 * convert old style criteria into an attribute list. Any criteria will
1412 * be dropped when saving data.
1415 if( ! ldapctl_get_criteria_list( ctl ) ) {
1416 ldapctl_parse_ldap_search( ctl, criteria );
1420 /* ldapsvr_print_data( server, stdout ); */
1425 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1426 LdapServer *server = ds->rawDataSource;
1427 LdapControl *ctl = NULL;
1432 ctl = server->control;
1434 if( ctl == NULL ) return;
1436 /* Output start element with attributes */
1437 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1438 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1439 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1441 sprintf( value, "%d", ctl->port );
1442 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1444 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1445 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1446 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1448 sprintf( value, "%d", ctl->maxEntries );
1449 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1450 sprintf( value, "%d", ctl->timeOut );
1451 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1452 sprintf( value, "%d", ctl->maxQueryAge );
1453 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1455 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1456 server->searchFlag ?
1457 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1459 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1460 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1461 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1463 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1465 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1466 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1468 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1472 /* Output attributes */
1473 node = ldapctl_get_criteria_list( ctl );
1475 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1476 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1478 node = g_list_next( node );
1481 /* End of element */
1482 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1487 * Just read/write DOM fragments (preserve data found in file).
1489 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1490 AddressDataSource *ds;
1492 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1493 ds->rawDataSource = addrindex_read_fragment( file );
1497 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1498 AddressIfFragment *fragment = ds->rawDataSource;
1500 addrindex_write_fragment( fp, fragment, lvl );
1505 /* **********************************************************************
1506 * Address index I/O functions.
1507 * ***********************************************************************
1510 * Read address index file, creating appropriate data sources for each address
1513 * \param addrIndex Address index.
1514 * \param file Address index file.
1516 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1519 AddressInterface *iface = NULL, *dsIFace = NULL;
1520 AddressDataSource *ds;
1523 addrIndex->loadedFlag = FALSE;
1525 prev_level = file->level;
1526 rc = xml_parse_next_tag( file );
1527 if( file->level == 0 ) return;
1529 xtag = xml_get_current_tag( file );
1531 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1533 addrIndex->lastType = iface->type;
1534 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1537 dsIFace = addrindex_tag_get_datasource(
1538 addrIndex, addrIndex->lastType, xtag->tag );
1540 /* Add data source to list */
1542 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1543 ds = addrindex_parse_book( file );
1544 if( ds->rawDataSource ) {
1545 addrbook_set_path( ds->rawDataSource,
1546 addrIndex->filePath );
1549 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1550 ds = addrindex_parse_vcard( file );
1552 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1553 ds = addrindex_parse_jpilot( file );
1555 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1556 ds = addrindex_parse_ldap( file );
1559 ds->interface = dsIFace;
1560 addrindex_hash_add_cache( addrIndex, ds );
1561 dsIFace->listSource =
1562 g_list_append( dsIFace->listSource, ds );
1570 * Search order sorting comparison function for building search order list.
1572 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1573 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1574 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1576 return ifaceA->searchOrder - ifaceB->searchOrder;
1580 * Build list of data sources to process.
1581 * \param addrIndex Address index object.
1583 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1586 /* Clear existing list */
1587 g_list_free( addrIndex->searchOrder );
1588 addrIndex->searchOrder = NULL;
1590 /* Build new list */
1591 nodeIf = addrIndex->interfaceList;
1593 AddressInterface *iface = nodeIf->data;
1594 if( iface->useInterface ) {
1595 if( iface->searchOrder > 0 ) {
1596 /* Add to search order list */
1597 addrIndex->searchOrder = g_list_insert_sorted(
1598 addrIndex->searchOrder, iface,
1599 addrindex_search_order_compare );
1602 nodeIf = g_list_next( nodeIf );
1606 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1607 XMLFile *file = NULL;
1608 gchar *fileSpec = NULL;
1610 g_return_val_if_fail( addrIndex != NULL, -1 );
1612 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1613 addrIndex->retVal = MGU_NO_FILE;
1614 file = xml_open_file( fileSpec );
1617 if( file == NULL ) {
1619 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1621 return addrIndex->retVal;
1624 addrIndex->retVal = MGU_BAD_FORMAT;
1625 if( xml_get_dtd( file ) == 0 ) {
1626 if( xml_parse_next_tag( file ) == 0 ) {
1627 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1628 addrindex_read_index( addrIndex, file );
1629 addrIndex->retVal = MGU_SUCCESS;
1633 xml_close_file( file );
1635 addrindex_build_search_order( addrIndex );
1637 return addrIndex->retVal;
1640 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1641 GList *nodeIF, *nodeDS;
1643 gint lvlItem = 1 + lvlList;
1645 nodeIF = addrIndex->interfaceList;
1647 AddressInterface *iface = nodeIF->data;
1648 if( ! iface->legacyFlag ) {
1649 nodeDS = iface->listSource;
1650 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1653 AddressDataSource *ds = nodeDS->data;
1655 if( iface->type == ADDR_IF_BOOK ) {
1656 addrindex_write_book( fp, ds, lvlItem );
1658 if( iface->type == ADDR_IF_VCARD ) {
1659 addrindex_write_vcard( fp, ds, lvlItem );
1661 if( iface->type == ADDR_IF_JPILOT ) {
1662 addrindex_write_jpilot( fp, ds, lvlItem );
1664 if( iface->type == ADDR_IF_LDAP ) {
1665 addrindex_write_ldap( fp, ds, lvlItem );
1668 nodeDS = g_list_next( nodeDS );
1670 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1672 nodeIF = g_list_next( nodeIF );
1677 * Write data to specified file.
1678 * Enter: addrIndex Address index object.
1679 * newFile New file name.
1680 * return: Status code, from addrIndex->retVal.
1681 * Note: File will be created in directory specified by addrIndex.
1683 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1686 #ifndef DEV_STANDALONE
1690 g_return_val_if_fail( addrIndex != NULL, -1 );
1692 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1693 addrIndex->retVal = MGU_OPEN_FILE;
1694 #ifdef DEV_STANDALONE
1695 fp = g_fopen( fileSpec, "wb" );
1698 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1700 pfile = prefs_write_open( fileSpec );
1704 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1706 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1709 addrindex_write_index( addrIndex, fp );
1710 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1712 addrIndex->retVal = MGU_SUCCESS;
1713 #ifdef DEV_STANDALONE
1716 if( prefs_file_close( pfile ) < 0 ) {
1717 addrIndex->retVal = MGU_ERROR_WRITE;
1723 return addrIndex->retVal;
1727 * Save address index data to original file.
1728 * return: Status code, from addrIndex->retVal.
1730 gint addrindex_save_data( AddressIndex *addrIndex ) {
1731 g_return_val_if_fail( addrIndex != NULL, -1 );
1733 addrIndex->retVal = MGU_NO_FILE;
1734 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1735 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1737 addrindex_write_to( addrIndex, addrIndex->fileName );
1738 if( addrIndex->retVal == MGU_SUCCESS ) {
1739 addrIndex->dirtyFlag = FALSE;
1741 return addrIndex->retVal;
1745 * Save all address book files which may have changed.
1746 * Return: Status code, set if there was a problem saving data.
1748 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1749 gint retVal = MGU_SUCCESS;
1750 GList *nodeIf, *nodeDS;
1752 nodeIf = addrIndex->interfaceList;
1754 AddressInterface *iface = nodeIf->data;
1755 if( iface->type == ADDR_IF_BOOK ) {
1756 nodeDS = iface->listSource;
1758 AddressDataSource *ds = nodeDS->data;
1759 AddressBookFile *abf = ds->rawDataSource;
1760 if( addrbook_get_dirty( abf ) ) {
1761 if( addrbook_get_read_flag( abf ) ) {
1762 addrbook_save_data( abf );
1763 if( abf->retVal != MGU_SUCCESS ) {
1764 retVal = abf->retVal;
1768 nodeDS = g_list_next( nodeDS );
1772 nodeIf = g_list_next( nodeIf );
1778 /* **********************************************************************
1779 * Address book conversion to new format.
1780 * ***********************************************************************
1783 #define ELTAG_IF_OLD_FOLDER "folder"
1784 #define ELTAG_IF_OLD_GROUP "group"
1785 #define ELTAG_IF_OLD_ITEM "item"
1786 #define ELTAG_IF_OLD_NAME "name"
1787 #define ELTAG_IF_OLD_ADDRESS "address"
1788 #define ELTAG_IF_OLD_REMARKS "remarks"
1789 #define ATTAG_IF_OLD_NAME "name"
1791 #define TEMPNODE_ROOT 0
1792 #define TEMPNODE_FOLDER 1
1793 #define TEMPNODE_GROUP 2
1794 #define TEMPNODE_ADDRESS 3
1796 typedef struct _AddressCvt_Node AddressCvtNode;
1797 struct _AddressCvt_Node {
1806 * Parse current address item.
1808 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1813 nn = g_new0( AddressCvtNode, 1 );
1814 nn->type = TEMPNODE_ADDRESS;
1817 level = file->level;
1820 xml_parse_next_tag(file);
1821 if (file->level < level) return nn;
1823 element = xml_get_element( file );
1824 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1825 nn->name = g_strdup( element );
1827 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1828 nn->address = g_strdup( element );
1830 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1831 nn->remarks = g_strdup( element );
1834 xml_parse_next_tag(file);
1839 * Create a temporary node below specified node.
1841 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1843 nn = g_new0( AddressCvtNode, 1 );
1845 nn->name = g_strdup( name );
1846 nn->remarks = g_strdup( rem );
1847 node->list = g_list_append( node->list, nn );
1852 * Process current temporary node.
1854 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1857 AddressCvtNode *newNode = NULL;
1862 prev_level = file->level;
1863 xml_parse_next_tag( file );
1864 if (file->level < prev_level) return;
1868 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1869 attr = xml_get_current_tag_attr(file);
1871 name = ((XMLAttr *)attr->data)->name;
1872 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1873 value = ((XMLAttr *)attr->data)->value;
1876 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1877 addrindex_add_obj( file, newNode );
1880 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1881 attr = xml_get_current_tag_attr(file);
1883 name = ((XMLAttr *)attr->data)->name;
1884 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1885 value = ((XMLAttr *)attr->data)->value;
1888 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1889 addrindex_add_obj( file, newNode );
1891 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1892 newNode = addrindex_parse_item( file );
1893 node->list = g_list_append( node->list, newNode );
1896 /* printf( "invalid: !!! \n" ); */
1897 attr = xml_get_current_tag_attr( file );
1903 * Consume all nodes below current tag.
1905 static void addrindex_consume_tree( XMLFile *file ) {
1912 prev_level = file->level;
1913 xml_parse_next_tag( file );
1914 if (file->level < prev_level) return;
1916 xtag = xml_get_current_tag( file );
1917 /* printf( "tag : %s\n", xtag->tag ); */
1918 element = xml_get_element( file );
1919 attr = xml_get_current_tag_attr( file );
1920 /* show_attribs( attr ); */
1921 /* printf( "\ttag value : %s :\n", element ); */
1922 addrindex_consume_tree( file );
1927 * Print temporary tree.
1929 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1932 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1933 fprintf( stream, "\tname :%s:\n", node->name );
1934 fprintf( stream, "\taddr :%s:\n", node->address );
1935 fprintf( stream, "\trems :%s:\n", node->remarks );
1937 fprintf( stream, "\t--list----\n" );
1941 AddressCvtNode *lNode = list->data;
1942 list = g_list_next( list );
1943 addrindex_print_node( lNode, stream );
1945 fprintf( stream, "\t==list-%d==\n", node->type );
1949 * Free up temporary tree.
1951 static void addrindex_free_node( AddressCvtNode *node ) {
1952 GList *list = node->list;
1955 AddressCvtNode *lNode = list->data;
1956 list = g_list_next( list );
1957 addrindex_free_node( lNode );
1959 node->type = TEMPNODE_ROOT;
1960 g_free( node->name );
1961 g_free( node->address );
1962 g_free( node->remarks );
1963 g_list_free( node->list );
1968 * Process address book for specified node.
1970 static void addrindex_process_node(
1971 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1972 ItemGroup *parentGrp, ItemFolder *folderGrp )
1975 ItemFolder *itemFolder = NULL;
1976 ItemGroup *itemGParent = parentGrp;
1977 ItemFolder *itemGFolder = folderGrp;
1978 AddressCache *cache = abf->addressCache;
1980 if( node->type == TEMPNODE_ROOT ) {
1981 itemFolder = parent;
1983 else if( node->type == TEMPNODE_FOLDER ) {
1984 itemFolder = addritem_create_item_folder();
1985 addritem_folder_set_name( itemFolder, node->name );
1986 addrcache_id_folder( cache, itemFolder );
1987 addrcache_folder_add_folder( cache, parent, itemFolder );
1990 else if( node->type == TEMPNODE_GROUP ) {
1991 ItemGroup *itemGroup;
1994 /* Create a folder for group */
1995 fName = g_strdup_printf( "Cvt - %s", node->name );
1996 itemGFolder = addritem_create_item_folder();
1997 addritem_folder_set_name( itemGFolder, fName );
1998 addrcache_id_folder( cache, itemGFolder );
1999 addrcache_folder_add_folder( cache, parent, itemGFolder );
2002 /* Add group into folder */
2003 itemGroup = addritem_create_item_group();
2004 addritem_group_set_name( itemGroup, node->name );
2005 addrcache_id_group( cache, itemGroup );
2006 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2007 itemGParent = itemGroup;
2009 else if( node->type == TEMPNODE_ADDRESS ) {
2010 ItemPerson *itemPerson;
2011 ItemEMail *itemEMail;
2013 /* Create person and email objects */
2014 itemPerson = addritem_create_item_person();
2015 addritem_person_set_common_name( itemPerson, node->name );
2016 addrcache_id_person( cache, itemPerson );
2017 itemEMail = addritem_create_item_email();
2018 addritem_email_set_address( itemEMail, node->address );
2019 addritem_email_set_remarks( itemEMail, node->remarks );
2020 addrcache_id_email( cache, itemEMail );
2021 addrcache_person_add_email( cache, itemPerson, itemEMail );
2023 /* Add person into appropriate folder */
2025 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2028 addrcache_folder_add_person( cache, parent, itemPerson );
2031 /* Add email address only into group */
2033 addrcache_group_add_email( cache, parentGrp, itemEMail );
2039 AddressCvtNode *lNode = list->data;
2040 list = g_list_next( list );
2041 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2046 * Process address book to specified file number.
2048 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2049 gboolean retVal = FALSE;
2050 AddressBookFile *abf = NULL;
2051 AddressCvtNode *rootNode = NULL;
2052 gchar *newFile = NULL;
2053 GList *fileList = NULL;
2056 /* Setup root node */
2057 rootNode = g_new0( AddressCvtNode, 1 );
2058 rootNode->type = TEMPNODE_ROOT;
2059 rootNode->name = g_strdup( "root" );
2060 rootNode->list = NULL;
2061 addrindex_add_obj( file, rootNode );
2062 /* addrindex_print_node( rootNode, stdout ); */
2064 /* Create new address book */
2065 abf = addrbook_create_book();
2066 addrbook_set_name( abf, displayName );
2067 addrbook_set_path( abf, addrIndex->filePath );
2069 /* Determine next available file number */
2070 fileList = addrbook_get_bookfile_list( abf );
2072 fileNum = 1 + abf->maxValue;
2074 g_list_free( fileList );
2077 newFile = addrbook_gen_new_file_name( fileNum );
2079 addrbook_set_file( abf, newFile );
2082 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2084 /* addrbook_dump_book( abf, stdout ); */
2085 addrbook_save_data( abf );
2086 addrIndex->retVal = abf->retVal;
2087 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2089 addrbook_free_book( abf );
2091 addrindex_free_node( rootNode );
2094 /* Create entries in address index */
2096 abf = addrbook_create_book();
2097 addrbook_set_name( abf, displayName );
2098 addrbook_set_path( abf, addrIndex->filePath );
2099 addrbook_set_file( abf, newFile );
2100 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2107 * Process tree converting data.
2109 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2117 prev_level = file->level;
2118 xml_parse_next_tag( file );
2119 if (file->level < prev_level) return;
2121 xtag = xml_get_current_tag( file );
2122 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2123 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2124 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2125 addrIndex->needsConversion = FALSE;
2126 addrIndex->wasConverted = TRUE;
2131 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2132 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2133 addrIndex->needsConversion = FALSE;
2134 addrIndex->wasConverted = TRUE;
2139 element = xml_get_element( file );
2140 attr = xml_get_current_tag_attr( file );
2141 /* show_attribs( attr ); */
2142 /* printf( "\ttag value : %s :\n", element ); */
2143 addrindex_consume_tree( file );
2147 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2148 XMLFile *file = NULL;
2151 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2152 addrIndex->retVal = MGU_NO_FILE;
2153 file = xml_open_file( fileSpec );
2156 if( file == NULL ) {
2157 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2158 return addrIndex->retVal;
2161 addrIndex->retVal = MGU_BAD_FORMAT;
2162 if( xml_get_dtd( file ) == 0 ) {
2163 if( xml_parse_next_tag( file ) == 0 ) {
2164 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2165 addrindex_convert_tree( addrIndex, file );
2169 xml_close_file( file );
2170 return addrIndex->retVal;
2174 * Create a new address book file.
2176 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2177 gboolean retVal = FALSE;
2178 AddressBookFile *abf = NULL;
2179 gchar *newFile = NULL;
2180 GList *fileList = NULL;
2183 /* Create new address book */
2184 abf = addrbook_create_book();
2185 addrbook_set_name( abf, displayName );
2186 addrbook_set_path( abf, addrIndex->filePath );
2188 /* Determine next available file number */
2189 fileList = addrbook_get_bookfile_list( abf );
2191 fileNum = 1 + abf->maxValue;
2193 g_list_free( fileList );
2196 newFile = addrbook_gen_new_file_name( fileNum );
2198 addrbook_set_file( abf, newFile );
2201 addrbook_save_data( abf );
2202 addrIndex->retVal = abf->retVal;
2203 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2204 addrbook_free_book( abf );
2207 /* Create entries in address index */
2209 abf = addrbook_create_book();
2210 addrbook_set_name( abf, displayName );
2211 addrbook_set_path( abf, addrIndex->filePath );
2212 addrbook_set_file( abf, newFile );
2213 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2220 * Read data for address index performing a conversion if necesary.
2221 * Enter: addrIndex Address index object.
2222 * return: Status code, from addrIndex->retVal.
2223 * Note: New address book files will be created in directory specified by
2224 * addrIndex. Three files will be created, for the following:
2225 * "Common addresses"
2226 * "Personal addresses"
2227 * "Gathered addresses" - a new address book.
2229 gint addrindex_read_data( AddressIndex *addrIndex ) {
2230 g_return_val_if_fail( addrIndex != NULL, -1 );
2232 addrIndex->conversionError = FALSE;
2233 addrindex_read_file( addrIndex );
2234 if( addrIndex->retVal == MGU_SUCCESS ) {
2235 if( addrIndex->needsConversion ) {
2236 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2237 addrIndex->conversionError = TRUE;
2240 addrIndex->conversionError = TRUE;
2243 addrIndex->dirtyFlag = TRUE;
2245 return addrIndex->retVal;
2249 * Create new address books for a new address index.
2250 * Enter: addrIndex Address index object.
2251 * return: Status code, from addrIndex->retVal.
2252 * Note: New address book files will be created in directory specified by
2253 * addrIndex. Three files will be created, for the following:
2254 * "Common addresses"
2255 * "Personal addresses"
2256 * "Gathered addresses" - a new address book.
2258 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2261 g_return_val_if_fail( addrIndex != NULL, -1 );
2263 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2265 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2266 addrIndex->dirtyFlag = TRUE;
2268 return addrIndex->retVal;
2271 /* **********************************************************************
2272 * New interface stuff.
2273 * ***********************************************************************
2277 * Return modified flag for specified data source.
2279 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2280 gboolean retVal = FALSE;
2281 AddressInterface *iface;
2283 if( ds == NULL ) return retVal;
2284 iface = ds->interface;
2285 if( iface == NULL ) return retVal;
2286 if( iface->getModifyFlag ) {
2287 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2293 * Return accessed flag for specified data source.
2295 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2296 gboolean retVal = FALSE;
2297 AddressInterface *iface;
2299 if( ds == NULL ) return retVal;
2300 iface = ds->interface;
2301 if( iface == NULL ) return retVal;
2302 if( iface->getAccessFlag ) {
2303 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2309 * Return data read flag for specified data source.
2311 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2312 gboolean retVal = TRUE;
2313 AddressInterface *iface;
2315 if( ds == NULL ) return retVal;
2316 iface = ds->interface;
2317 if( iface == NULL ) return retVal;
2318 if( iface->getReadFlag ) {
2319 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2325 * Return status code for specified data source.
2327 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2328 gint retVal = MGU_SUCCESS;
2329 AddressInterface *iface;
2331 if( ds == NULL ) return retVal;
2332 iface = ds->interface;
2333 if( iface == NULL ) return retVal;
2334 if( iface->getStatusCode ) {
2335 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2341 * Return data read flag for specified data source.
2343 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2344 gint retVal = MGU_SUCCESS;
2345 AddressInterface *iface;
2347 if( ds == NULL ) return retVal;
2348 iface = ds->interface;
2349 if( iface == NULL ) return retVal;
2350 if( iface->getReadData ) {
2352 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2353 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2355 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2361 * Return data read flag for specified data source.
2363 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2364 ItemFolder *retVal = NULL;
2365 AddressInterface *iface;
2367 if( ds == NULL ) return retVal;
2368 iface = ds->interface;
2369 if( iface == NULL ) return retVal;
2370 if( iface->getRootFolder ) {
2371 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2377 * Return list of folders for specified data source.
2379 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2380 GList *retVal = FALSE;
2381 AddressInterface *iface;
2383 if( ds == NULL ) return retVal;
2384 iface = ds->interface;
2385 if( iface == NULL ) return retVal;
2386 if( iface->getListFolder ) {
2387 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2393 * Return list of persons in root folder for specified data source.
2395 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2396 GList *retVal = FALSE;
2397 AddressInterface *iface;
2399 if( ds == NULL ) return retVal;
2400 iface = ds->interface;
2401 if( iface == NULL ) return retVal;
2402 if( iface->getListPerson ) {
2403 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2409 * Return name for specified data source.
2411 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2412 gchar *retVal = FALSE;
2413 AddressInterface *iface;
2415 if( ds == NULL ) return retVal;
2416 iface = ds->interface;
2417 if( iface == NULL ) return retVal;
2418 if( iface->getName ) {
2419 retVal = ( iface->getName ) ( ds->rawDataSource );
2425 * Set the access flag inside the data source.
2427 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2428 AddressInterface *iface;
2430 if( ds == NULL ) return;
2431 iface = ds->interface;
2432 if( iface == NULL ) return;
2433 if( iface->setAccessFlag ) {
2434 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2439 * Return read only flag for specified data source.
2441 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2442 AddressInterface *iface;
2443 if( ds == NULL ) return TRUE;
2444 iface = ds->interface;
2445 if( iface == NULL ) return TRUE;
2446 return iface->readOnly;
2450 * Return list of all persons for specified data source.
2452 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2453 GList *retVal = NULL;
2454 AddressInterface *iface;
2456 if( ds == NULL ) return retVal;
2457 iface = ds->interface;
2458 if( iface == NULL ) return retVal;
2459 if( iface->getAllPersons ) {
2460 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2466 * Return list of all groups for specified data source.
2468 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2469 GList *retVal = NULL;
2470 AddressInterface *iface;
2472 if( ds == NULL ) return retVal;
2473 iface = ds->interface;
2474 if( iface == NULL ) return retVal;
2475 if( iface->getAllGroups ) {
2476 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2481 /* **********************************************************************
2482 * Address search stuff.
2483 * ***********************************************************************
2487 * Setup or register the dynamic search that will be performed. The search
2488 * is registered with the query manager.
2490 * \param searchTerm Search term. A private copy will be made.
2491 * \param callBackEntry Callback function that should be called when
2492 * each entry is received.
2493 * \param callBackEnd Callback function that should be called when
2494 * search has finished running.
2495 * \return ID allocated to query that will be executed.
2497 gint addrindex_setup_search(
2498 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2503 /* Set up a dynamic address query */
2504 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2505 queryID = req->queryID;
2506 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2508 /* printf( "***> query ID ::%d::\n", queryID ); */
2515 * Function prototypes (not in header file or circular reference errors are
2518 LdapQuery *ldapsvr_new_dynamic_search(
2519 LdapServer *server, QueryRequest *req );
2520 LdapQuery *ldapsvr_new_explicit_search(
2521 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2522 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2527 * Execute the previously registered dynamic search.
2529 * \param req Address query object to execute.
2530 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2533 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2534 AddressInterface *iface;
2535 AddressDataSource *ds;
2540 /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2541 nodeIf = _addressIndex_->searchOrder;
2543 iface = nodeIf->data;
2544 nodeIf = g_list_next( nodeIf );
2546 if( ! iface->useInterface ) {
2549 if( ! iface->externalQuery ) {
2554 nodeDS = iface->listSource;
2557 nodeDS = g_list_next( nodeDS );
2559 if( type == ADDR_IF_LDAP ) {
2563 server = ds->rawDataSource;
2564 if( ! server->searchFlag ) {
2567 if( ldapsvr_reuse_previous( server, req ) ) {
2571 /* Start a new dynamic search */
2572 qry = ldapsvr_new_dynamic_search( server, req );
2574 ldapsvr_execute_query( server, qry );
2584 * Stop the previously registered search.
2586 * \param queryID ID of search query to stop.
2588 void addrindex_stop_search( const gint queryID ){
2590 AddrQueryObject *aqo;
2593 /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
2594 /* If query ID does not match, search has not been setup */
2595 req = qrymgr_find_request( queryID );
2600 /* Stop all queries that were associated with request */
2601 node = req->queryList;
2605 if( aqo->queryType == ADDRQUERY_LDAP ) {
2606 LdapQuery *qry = ( LdapQuery * ) aqo;
2607 ldapqry_set_stop_flag( qry, TRUE );
2611 node = g_list_next( node );
2614 /* Delete query request */
2615 qrymgr_delete_request( queryID );
2619 * Setup or register the explicit search that will be performed. The search is
2620 * registered with the query manager.
2622 * \param ds Data source to search.
2623 * \param searchTerm Search term to locate.
2624 * \param folder Folder to receive search results; may be NULL.
2625 * \param callbackEnd Function to call when search has terminated.
2626 * \param callbackEntry Function to called for each entry processed.
2627 * \return ID allocated to query that will be executed.
2629 gint addrindex_setup_explicit_search(
2630 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2631 void *callBackEnd, void *callBackEntry )
2638 /* Name the query */
2639 name = g_strdup_printf( "Search '%s'", searchTerm );
2641 /* Set up query request */
2642 if (!strcmp(searchTerm, "*"))
2643 mySearch = g_strdup("*@");
2645 mySearch = g_strdup(searchTerm);
2647 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2651 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2652 queryID = req->queryID;
2654 if( ds->type == ADDR_IF_LDAP ) {
2658 server = ds->rawDataSource;
2659 ldapsvr_new_explicit_search( server, req, folder );
2663 qrymgr_delete_request( queryID );
2672 * Execute the previously registered explicit search.
2674 * \param req Address query request object to execute.
2675 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2678 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2680 AddrQueryObject *aqo;
2684 /* Note: there should only be one query in the list. */
2685 aqo = req->queryList->data;
2687 if( aqo->queryType == ADDRQUERY_LDAP ) {
2691 qry = ( LdapQuery * ) aqo;
2692 server = qry->server;
2694 /* Start the search */
2696 ldapsvr_execute_query( server, qry );
2703 * Start the previously registered search.
2705 * \param queryID ID of search query to be executed.
2706 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2709 gboolean addrindex_start_search( const gint queryID ) {
2712 AddrSearchType searchType;
2715 /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
2716 req = qrymgr_find_request( queryID );
2721 searchType = req->searchType;
2722 if( searchType == ADDRSEARCH_DYNAMIC ) {
2723 retVal = addrindex_start_dynamic( req );
2725 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2726 retVal = addrindex_start_explicit( req );
2733 * Remove results (folder and data) for specified data source and folder.
2734 * \param ds Data source to process.
2735 * \param folder Results folder to remove.
2737 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2738 AddrBookBase *adbase;
2739 AddressCache *cache;
2742 /* printf( "addrindex_remove_results/start\n" ); */
2744 /* Test for folder */
2745 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2746 /* printf( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2747 adbase = ( AddrBookBase * ) ds->rawDataSource;
2748 if( adbase == NULL ) return;
2749 cache = adbase->addressCache;
2751 /* Hide folder to prevent re-display */
2752 addritem_folder_set_hidden( folder, TRUE );
2754 if( ds->type == ADDR_IF_LDAP ) {
2759 qry = ( LdapQuery * ) folder->folderData;
2760 queryID = ADDRQUERY_ID(qry);
2761 /* printf( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2762 delFlag = ldapquery_remove_results( qry );
2764 ldapqry_free( qry );
2766 /* printf( "calling ldapquery_remove_results...done\n" ); */
2769 printf( "delFlag IS-TRUE\n" );
2772 printf( "delFlag IS-FALSE\n" );
2773 addressbook_clear_idler( queryID );
2778 /* printf( "addrindex_remove_results/end\n" ); */
2780 /* Delete query request */
2782 qrymgr_delete_request( queryID );
2786 /* **********************************************************************
2787 * Address completion stuff.
2788 * ***********************************************************************
2792 * This function is used by the address completion function to load
2793 * addresses for all non-external address book interfaces.
2795 * \param callBackFunc Function to be called when an address is
2797 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2799 gboolean addrindex_load_completion(
2800 gint (*callBackFunc) ( const gchar *, const gchar *,
2801 const gchar *, const gchar * ) )
2803 AddressDataSource *ds;
2804 GList *nodeIf, *nodeDS;
2805 GList *listP, *nodeP;
2809 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2811 AddressInterface *iface = nodeIf->data;
2813 nodeIf = g_list_next( nodeIf );
2814 if( ! iface->useInterface ) {
2817 if( iface->externalQuery ) {
2820 nodeDS = iface->listSource;
2824 /* Read address book */
2825 if( addrindex_ds_get_modify_flag( ds ) ) {
2826 addrindex_ds_read_data( ds );
2829 if( ! addrindex_ds_get_read_flag( ds ) ) {
2830 addrindex_ds_read_data( ds );
2833 /* Get all persons */
2834 listP = addrindex_ds_get_all_persons( ds );
2837 ItemPerson *person = nodeP->data;
2838 nodeM = person->listEMail;
2840 /* Figure out name to use */
2841 sName = ADDRITEM_NAME(person);
2842 if( sName == NULL || *sName == '\0' ) {
2843 sName = person->nickName;
2846 /* Process each E-Mail address */
2848 ItemEMail *email = nodeM->data;
2850 callBackFunc( sName, email->address, person->nickName,
2851 ADDRITEM_NAME(email) );
2853 nodeM = g_list_next( nodeM );
2855 nodeP = g_list_next( nodeP );
2857 /* Free up the list */
2858 g_list_free( listP );
2860 nodeDS = g_list_next( nodeDS );
2868 * This function can be used to collect information about
2869 * addressbook entries that contain a specific attribute.
2871 * \param attr Name of attribute to look for
2872 * \param callBackFunc Function to be called when a matching attribute was found
2873 * \return <i>TRUE</i>
2875 gboolean addrindex_load_person_attribute(
2877 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2879 AddressDataSource *ds;
2880 GList *nodeIf, *nodeDS;
2881 GList *listP, *nodeP;
2884 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2887 AddressInterface *iface = nodeIf->data;
2889 nodeIf = g_list_next( nodeIf );
2890 if( ! iface->useInterface ) {
2893 if( iface->externalQuery ) {
2896 nodeDS = iface->listSource;
2900 /* Read address book */
2901 if( addrindex_ds_get_modify_flag( ds ) ) {
2902 addrindex_ds_read_data( ds );
2905 if( ! addrindex_ds_get_read_flag( ds ) ) {
2906 addrindex_ds_read_data( ds );
2909 /* Check addressbook name */
2910 cur_bname = addrindex_ds_get_name( ds );
2912 /* Get all persons */
2913 listP = addrindex_ds_get_all_persons( ds );
2916 ItemPerson *person = nodeP->data;
2918 /* Return all ItemPerson's if attr is NULL */
2919 if( attr == NULL ) {
2920 callBackFunc(person, cur_bname);
2923 /* Return ItemPerson's with specific attribute */
2925 nodeA = person->listAttrib;
2926 /* Process each User Attribute */
2928 UserAttribute *attrib = nodeA->data;
2930 !strcmp( attrib->name,attr ) ) {
2931 callBackFunc(person, cur_bname);
2933 nodeA = g_list_next( nodeA );
2936 nodeP = g_list_next( nodeP );
2938 /* Free up the list */
2939 g_list_free( listP );
2941 nodeDS = g_list_next( nodeDS );