2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2004 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * 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"
60 #define TAG_ADDRESS_INDEX "addressbook"
62 #define TAG_IF_ADDRESS_BOOK "book_list"
63 #define TAG_IF_VCARD "vcard_list"
64 #define TAG_IF_JPILOT "jpilot_list"
65 #define TAG_IF_LDAP "ldap_list"
67 #define TAG_DS_ADDRESS_BOOK "book"
68 #define TAG_DS_VCARD "vcard"
69 #define TAG_DS_JPILOT "jpilot"
70 #define TAG_DS_LDAP "server"
72 /* XML Attribute names */
73 #define ATTAG_BOOK_NAME "name"
74 #define ATTAG_BOOK_FILE "file"
76 #define ATTAG_VCARD_NAME "name"
77 #define ATTAG_VCARD_FILE "file"
79 #define ATTAG_JPILOT_NAME "name"
80 #define ATTAG_JPILOT_FILE "file"
81 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
82 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
83 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
84 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
85 #define ATTAG_JPILOT_CUSTOM "custom-"
87 #define ATTAG_LDAP_NAME "name"
88 #define ATTAG_LDAP_HOST "host"
89 #define ATTAG_LDAP_PORT "port"
90 #define ATTAG_LDAP_BASE_DN "base-dn"
91 #define ATTAG_LDAP_BIND_DN "bind-dn"
92 #define ATTAG_LDAP_BIND_PASS "bind-pass"
93 #define ATTAG_LDAP_CRITERIA "criteria"
94 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
95 #define ATTAG_LDAP_TIMEOUT "timeout"
96 #define ATTAG_LDAP_MAX_AGE "max-age"
97 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
98 #define ATTAG_LDAP_MATCH_OPT "match-opt"
99 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
101 #define ELTAG_LDAP_ATTR_SRCH "attribute"
102 #define ATTAG_LDAP_ATTR_NAME "name"
104 /* Attribute values */
105 #define ATVAL_BOOLEAN_YES "yes"
106 #define ATVAL_BOOLEAN_NO "no"
107 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
108 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
111 #define ATTAG_LDAP_DEFAULT "default"
115 N_("Personal address")
118 #define DISP_NEW_COMMON _("Common address")
119 #define DISP_NEW_PERSONAL _("Personal address")
121 /* Old address book */
122 #define TAG_IF_OLD_COMMON "common_address"
123 #define TAG_IF_OLD_PERSONAL "personal_address"
125 #define DISP_OLD_COMMON _("Common address")
126 #define DISP_OLD_PERSONAL _("Personal address")
131 static AddressIndex *_addressIndex_ = NULL;
134 * Define attribute name-value pair.
136 typedef struct _AddressIfAttr AddressIfAttrib;
137 struct _AddressIfAttr {
143 * Define DOM fragment.
145 typedef struct _AddressIfFrag AddressIfFragment;
146 struct _AddressIfFrag {
153 * Build interface with default values.
155 * \param type Interface type.
156 * \param name Interface name.
157 * \param tagIf XML tag name for interface in address index file.
158 * \param tagDS XML tag name for datasource in address index file.
159 * \return Address interface object.
161 static AddressInterface *addrindex_create_interface(
162 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
164 AddressInterface *iface = g_new0( AddressInterface, 1 );
166 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
167 ADDRITEM_ID(iface) = NULL;
168 ADDRITEM_NAME(iface) = g_strdup( name );
169 ADDRITEM_PARENT(iface) = NULL;
170 ADDRITEM_SUBTYPE(iface) = type;
172 iface->name = g_strdup( name );
173 iface->listTag = g_strdup( tagIf );
174 iface->itemTag = g_strdup( tagDS );
175 iface->legacyFlag = FALSE;
176 iface->haveLibrary = TRUE;
177 iface->useInterface = TRUE;
178 iface->readOnly = TRUE;
180 /* Set callbacks to NULL values - override for each interface */
181 iface->getAccessFlag = NULL;
182 iface->getModifyFlag = NULL;
183 iface->getReadFlag = NULL;
184 iface->getStatusCode = NULL;
185 iface->getReadData = NULL;
186 iface->getRootFolder = NULL;
187 iface->getListFolder = NULL;
188 iface->getListPerson = NULL;
189 iface->getAllPersons = NULL;
190 iface->getAllGroups = NULL;
191 iface->getName = NULL;
192 iface->listSource = NULL;
195 iface->externalQuery = FALSE;
196 iface->searchOrder = 0; /* Ignored */
197 iface->startSearch = NULL;
198 iface->stopSearch = NULL;
204 * Build table of of all address book interfaces.
205 * \param addrIndex Address index object.
207 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
208 AddressInterface *iface;
210 /* Create intrinsic XML address book interface */
211 iface = addrindex_create_interface(
212 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
213 TAG_DS_ADDRESS_BOOK );
214 iface->readOnly = FALSE;
215 iface->getModifyFlag = ( void * ) addrbook_get_modified;
216 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
217 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
218 iface->getStatusCode = ( void * ) addrbook_get_status;
219 iface->getReadData = ( void * ) addrbook_read_data;
220 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
221 iface->getListFolder = ( void * ) addrbook_get_list_folder;
222 iface->getListPerson = ( void * ) addrbook_get_list_person;
223 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
224 iface->getName = ( void * ) addrbook_get_name;
225 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
226 iface->searchOrder = 0;
228 /* Add to list of interfaces in address book */
229 addrIndex->interfaceList =
230 g_list_append( addrIndex->interfaceList, iface );
231 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
233 /* Create vCard interface */
234 iface = addrindex_create_interface(
235 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
236 iface->getModifyFlag = ( void * ) vcard_get_modified;
237 iface->getAccessFlag = ( void * ) vcard_get_accessed;
238 iface->getReadFlag = ( void * ) vcard_get_read_flag;
239 iface->getStatusCode = ( void * ) vcard_get_status;
240 iface->getReadData = ( void * ) vcard_read_data;
241 iface->getRootFolder = ( void * ) vcard_get_root_folder;
242 iface->getListFolder = ( void * ) vcard_get_list_folder;
243 iface->getListPerson = ( void * ) vcard_get_list_person;
244 iface->getAllPersons = ( void * ) vcard_get_all_persons;
245 iface->getName = ( void * ) vcard_get_name;
246 iface->setAccessFlag = ( void * ) vcard_set_accessed;
247 iface->searchOrder = 0;
248 addrIndex->interfaceList =
249 g_list_append( addrIndex->interfaceList, iface );
250 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
252 /* Create JPilot interface */
253 iface = addrindex_create_interface(
254 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
257 iface->haveLibrary = jpilot_test_pilot_lib();
258 iface->useInterface = iface->haveLibrary;
259 iface->getModifyFlag = ( void * ) jpilot_get_modified;
260 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
261 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
262 iface->getStatusCode = ( void * ) jpilot_get_status;
263 iface->getReadData = ( void * ) jpilot_read_data;
264 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
265 iface->getListFolder = ( void * ) jpilot_get_list_folder;
266 iface->getListPerson = ( void * ) jpilot_get_list_person;
267 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
268 iface->getName = ( void * ) jpilot_get_name;
269 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
270 iface->searchOrder = 0;
272 iface->useInterface = FALSE;
273 iface->haveLibrary = FALSE;
275 addrIndex->interfaceList =
276 g_list_append( addrIndex->interfaceList, iface );
277 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
279 /* Create LDAP interface */
280 iface = addrindex_create_interface(
281 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
283 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
284 iface->haveLibrary = ldaputil_test_ldap_lib();
285 iface->useInterface = iface->haveLibrary;
286 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
287 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
288 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
289 iface->getStatusCode = ( void * ) ldapsvr_get_status;
290 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
291 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
292 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
293 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
294 iface->getName = ( void * ) ldapsvr_get_name;
295 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
296 iface->externalQuery = TRUE;
297 iface->searchOrder = 1;
299 iface->useInterface = FALSE;
300 iface->haveLibrary = FALSE;
302 addrIndex->interfaceList =
303 g_list_append( addrIndex->interfaceList, iface );
304 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
306 /* Two old legacy data sources (pre 0.7.0) */
307 iface = addrindex_create_interface(
308 ADDR_IF_COMMON, "Old Address - common",
309 TAG_IF_OLD_COMMON, NULL );
310 iface->legacyFlag = TRUE;
311 addrIndex->interfaceList =
312 g_list_append( addrIndex->interfaceList, iface );
313 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
315 iface = addrindex_create_interface(
316 ADDR_IF_COMMON, "Old Address - personal",
317 TAG_IF_OLD_PERSONAL, NULL );
318 iface->legacyFlag = TRUE;
319 addrIndex->interfaceList =
320 g_list_append( addrIndex->interfaceList, iface );
321 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
327 * \param fragment Fragment to free.
329 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
333 node = fragment->children;
335 AddressIfFragment *child = node->data;
336 addrindex_free_fragment( child );
338 node = g_list_next( node );
340 g_list_free( fragment->children );
342 /* Free attributes */
343 node = fragment->attributes;
345 AddressIfAttrib *nv = node->data;
350 node = g_list_next( node );
352 g_list_free( fragment->attributes );
354 g_free( fragment->name );
355 fragment->name = NULL;
356 fragment->attributes = NULL;
357 fragment->children = NULL;
363 * Create a new data source.
364 * \param ifType Interface type to create.
365 * \return Initialized data source.
367 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
368 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
370 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
371 ADDRITEM_ID(ds) = NULL;
372 ADDRITEM_NAME(ds) = NULL;
373 ADDRITEM_PARENT(ds) = NULL;
374 ADDRITEM_SUBTYPE(ds) = 0;
376 ds->rawDataSource = NULL;
377 ds->interface = NULL;
382 * Free up data source.
383 * \param ds Data source to free.
385 void addrindex_free_datasource( AddressDataSource *ds ) {
386 AddressInterface *iface;
388 g_return_if_fail( ds != NULL );
390 iface = ds->interface;
391 if( ds->rawDataSource != NULL ) {
392 if( iface != NULL ) {
393 if( iface->useInterface ) {
394 if( iface->type == ADDR_IF_BOOK ) {
395 AddressBookFile *abf = ds->rawDataSource;
396 addrbook_free_book( abf );
398 else if( iface->type == ADDR_IF_VCARD ) {
399 VCardFile *vcf = ds->rawDataSource;
403 else if( iface->type == ADDR_IF_JPILOT ) {
404 JPilotFile *jpf = ds->rawDataSource;
409 else if( iface->type == ADDR_IF_LDAP ) {
410 LdapServer *server = ds->rawDataSource;
411 ldapsvr_free( server );
418 AddressIfFragment *fragment = ds->rawDataSource;
419 addrindex_free_fragment( fragment );
424 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
425 ADDRITEM_ID(ds) = NULL;
426 ADDRITEM_NAME(ds) = NULL;
427 ADDRITEM_PARENT(ds) = NULL;
428 ADDRITEM_SUBTYPE(ds) = 0;
429 ds->type = ADDR_IF_NONE;
430 ds->interface = NULL;
431 ds->rawDataSource = NULL;
437 * Free up all data sources for specified interface.
438 * \param iface Address interface to process.
440 static void addrindex_free_all_datasources( AddressInterface *iface ) {
441 GList *node = iface->listSource;
443 AddressDataSource *ds = node->data;
444 addrindex_free_datasource( ds );
446 node = g_list_next( node );
451 * Free up specified interface.
452 * \param iface Interface to process.
454 static void addrindex_free_interface( AddressInterface *iface ) {
455 /* Free up data sources */
456 addrindex_free_all_datasources( iface );
457 g_list_free( iface->listSource );
459 /* Free internal storage */
460 g_free( ADDRITEM_ID(iface) );
461 g_free( ADDRITEM_NAME(iface) );
462 g_free( iface->name );
463 g_free( iface->listTag );
464 g_free( iface->itemTag );
466 /* Clear all pointers */
467 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
468 ADDRITEM_ID(iface) = NULL;
469 ADDRITEM_NAME(iface) = NULL;
470 ADDRITEM_PARENT(iface) = NULL;
471 ADDRITEM_SUBTYPE(iface) = 0;
472 iface->type = ADDR_IF_NONE;
474 iface->listTag = NULL;
475 iface->itemTag = NULL;
476 iface->legacyFlag = FALSE;
477 iface->useInterface = FALSE;
478 iface->haveLibrary = FALSE;
479 iface->listSource = NULL;
482 iface->searchOrder = 0;
483 iface->startSearch = NULL;
484 iface->stopSearch = NULL;
490 * Return cache ID for specified data source.
492 * \param addrIndex Address index.
493 * \param ds Data source.
494 * \return ID or NULL if not found. This should be <code>g_free()</code>
497 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
498 gchar *cacheID = NULL;
499 AddrBookBase *adbase;
502 g_return_val_if_fail( addrIndex != NULL, NULL );
503 g_return_val_if_fail( ds != NULL, NULL );
505 adbase = ( AddrBookBase * ) ds->rawDataSource;
507 cache = adbase->addressCache;
509 cacheID = g_strdup( cache->cacheID );
517 * Return reference to data source for specified cacheID.
518 * \param addrIndex Address index.
520 * \return Data source, or NULL if not found.
522 AddressDataSource *addrindex_get_datasource(
523 AddressIndex *addrIndex, const gchar *cacheID )
525 g_return_val_if_fail( addrIndex != NULL, NULL );
526 g_return_val_if_fail( cacheID != NULL, NULL );
527 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
531 * Return reference to address cache for specified cacheID.
532 * \param addrIndex Address index.
534 * \return Address cache, or NULL if not found.
536 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
537 AddressDataSource *ds;
538 AddrBookBase *adbase;
541 g_return_val_if_fail( addrIndex != NULL, NULL );
542 g_return_val_if_fail( cacheID != NULL, NULL );
545 ds = addrindex_get_datasource( addrIndex, cacheID );
547 adbase = ( AddrBookBase * ) ds->rawDataSource;
548 cache = adbase->addressCache;
554 * Add data source into hash table.
555 * \param addrIndex Address index.
556 * \param ds Data source.
558 static void addrindex_hash_add_cache(
559 AddressIndex *addrIndex, AddressDataSource *ds )
563 cacheID = addrindex_get_cache_id( addrIndex, ds );
565 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
570 * Free hash table callback function.
572 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
580 * Free hash table of address cache items.
582 static void addrindex_free_cache_hash( GHashTable *table ) {
583 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
584 g_hash_table_destroy( table );
588 * Remove data source from internal hashtable.
589 * \param addrIndex Address index.
590 * \param ds Data source to remove.
592 static void addrindex_hash_remove_cache(
593 AddressIndex *addrIndex, AddressDataSource *ds )
597 cacheID = addrindex_get_cache_id( addrIndex, ds );
599 g_hash_table_remove( addrIndex->hashCache, cacheID );
606 * Create a new address index. This is created as a singleton object.
607 * \return Initialized address index object.
609 AddressIndex *addrindex_create_index( void ) {
612 if( _addressIndex_ == NULL ) {
613 index = g_new0( AddressIndex, 1 );
614 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
615 ADDRITEM_ID(index) = NULL;
616 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
617 ADDRITEM_PARENT(index) = NULL;
618 ADDRITEM_SUBTYPE(index) = 0;
619 index->filePath = NULL;
620 index->fileName = NULL;
621 index->retVal = MGU_SUCCESS;
622 index->needsConversion = FALSE;
623 index->wasConverted = FALSE;
624 index->conversionError = FALSE;
625 index->interfaceList = NULL;
626 index->lastType = ADDR_IF_NONE;
627 index->dirtyFlag = FALSE;
628 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
629 index->loadedFlag = FALSE;
630 index->searchOrder = NULL;
631 addrindex_build_if_list( index );
632 _addressIndex_ = index;
634 return _addressIndex_;
638 * Return reference to address index.
639 * \return Address index object.
641 AddressIndex *addrindex_get_object( void ) {
642 return _addressIndex_;
646 * Property - Specify file path to address index file.
647 * \param addrIndex Address index.
648 * \param value Path to index file.
650 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
651 g_return_if_fail( addrIndex != NULL );
652 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
656 * Property - Specify file name to address index file.
657 * \param addrIndex Address index.
658 * \param value File name.
660 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
661 g_return_if_fail( addrIndex != NULL );
662 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
666 * Property - Specify file path to be used.
667 * \param addrIndex Address index.
668 * \param value Path to JPilot file.
670 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
671 g_return_if_fail( addrIndex != NULL );
672 addrIndex->dirtyFlag = value;
676 * Property - get loaded flag. Note that this flag is set after reading data
677 * from the address books.
678 * \param addrIndex Address index.
679 * \return <i>TRUE</i> if address index data was loaded.
681 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
682 g_return_val_if_fail( addrIndex != NULL, FALSE );
683 return addrIndex->loadedFlag;
687 * Return list of address interfaces.
688 * \param addrIndex Address index.
689 * \return List of address interfaces.
691 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
692 g_return_val_if_fail( addrIndex != NULL, NULL );
693 return addrIndex->interfaceList;
697 * Perform any other initialization of address index.
699 void addrindex_initialize( void ) {
701 addrcompl_initialize();
705 * Perform any other teardown of address index.
707 void addrindex_teardown( void ) {
708 addrcompl_teardown();
713 * Free up address index.
714 * \param addrIndex Address index.
716 void addrindex_free_index( AddressIndex *addrIndex ) {
719 g_return_if_fail( addrIndex != NULL );
722 g_list_free( addrIndex->searchOrder );
723 addrIndex->searchOrder = NULL;
725 /* Free internal storage */
726 g_free( ADDRITEM_ID(addrIndex) );
727 g_free( ADDRITEM_NAME(addrIndex) );
728 g_free( addrIndex->filePath );
729 g_free( addrIndex->fileName );
732 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
733 ADDRITEM_ID(addrIndex) = NULL;
734 ADDRITEM_NAME(addrIndex) = NULL;
735 ADDRITEM_PARENT(addrIndex) = NULL;
736 ADDRITEM_SUBTYPE(addrIndex) = 0;
737 addrIndex->filePath = NULL;
738 addrIndex->fileName = NULL;
739 addrIndex->retVal = MGU_SUCCESS;
740 addrIndex->needsConversion = FALSE;
741 addrIndex->wasConverted = FALSE;
742 addrIndex->conversionError = FALSE;
743 addrIndex->lastType = ADDR_IF_NONE;
744 addrIndex->dirtyFlag = FALSE;
746 /* Free up interfaces */
747 node = addrIndex->interfaceList;
749 AddressInterface *iface = node->data;
750 addrindex_free_interface( iface );
751 node = g_list_next( node );
753 g_list_free( addrIndex->interfaceList );
754 addrIndex->interfaceList = NULL;
756 /* Free up hash cache */
757 addrindex_free_cache_hash( addrIndex->hashCache );
758 addrIndex->hashCache = NULL;
760 addrIndex->loadedFlag = FALSE;
764 _addressIndex_ = NULL;
768 * Print address index.
769 * \param addrIndex Address index.
770 * \parem stream Stream to print.
772 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
773 g_return_if_fail( addrIndex != NULL );
774 fprintf( stream, "AddressIndex:\n" );
775 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
776 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
777 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
778 fprintf( stream, "\tconverted: '%s'\n",
779 addrIndex->wasConverted ? "yes" : "no" );
780 fprintf( stream, "\tcvt error: '%s'\n",
781 addrIndex->conversionError ? "yes" : "no" );
782 fprintf( stream, "\t---\n" );
786 * Retrieve reference to address interface for specified interface type.
787 * \param addrIndex Address index.
788 * \param ifType Interface type.
789 * \return Address interface, or NULL if not found.
791 AddressInterface *addrindex_get_interface(
792 AddressIndex *addrIndex, AddressIfType ifType )
794 AddressInterface *retVal = NULL;
797 g_return_val_if_fail( addrIndex != NULL, NULL );
799 node = addrIndex->interfaceList;
801 AddressInterface *iface = node->data;
802 node = g_list_next( node );
803 if( iface->type == ifType ) {
812 * Add raw data source to index. The raw data object (an AddressBookFile or
813 * VCardFile object, for example) should be supplied as the raw dataSource
816 * \param addrIndex Address index.
817 * \param ifType Interface type to add.
818 * \param dataSource Actual raw data source to add.
819 * \return Data source added, or NULL if invalid interface type.
821 AddressDataSource *addrindex_index_add_datasource(
822 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
824 AddressInterface *iface;
825 AddressDataSource *ds = NULL;
827 g_return_val_if_fail( addrIndex != NULL, NULL );
828 g_return_val_if_fail( dataSource != NULL, NULL );
830 iface = addrindex_get_interface( addrIndex, ifType );
832 ds = addrindex_create_datasource( ifType );
833 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
835 ds->rawDataSource = dataSource;
836 ds->interface = iface;
837 iface->listSource = g_list_append( iface->listSource, ds );
838 addrIndex->dirtyFlag = TRUE;
840 addrindex_hash_add_cache( addrIndex, ds );
846 * Remove specified data source from index.
847 * \param addrIndex Address index.
848 * \param dataSource Data source to add.
849 * \return Reference to data source if removed, or NULL if data source was not
850 * found in index. Note the this object must still be freed.
852 AddressDataSource *addrindex_index_remove_datasource(
853 AddressIndex *addrIndex, AddressDataSource *dataSource )
855 AddressDataSource *retVal = FALSE;
856 AddressInterface *iface;
858 g_return_val_if_fail( addrIndex != NULL, NULL );
859 g_return_val_if_fail( dataSource != NULL, NULL );
861 iface = addrindex_get_interface( addrIndex, dataSource->type );
863 iface->listSource = g_list_remove( iface->listSource, dataSource );
864 addrIndex->dirtyFlag = TRUE;
865 dataSource->interface = NULL;
867 /* Remove cache from hash table */
868 addrindex_hash_remove_cache( addrIndex, dataSource );
876 * Retrieve a reference to address interface for specified interface type and
877 * XML interface tag name.
878 * \param addrIndex Address index.
879 * \param tag XML interface tag name to match.
880 * \param ifType Interface type to match.
881 * \return Reference to address index, or NULL if not found in index.
883 static AddressInterface *addrindex_tag_get_interface(
884 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
886 AddressInterface *retVal = NULL;
887 GList *node = addrIndex->interfaceList;
890 AddressInterface *iface = node->data;
891 node = g_list_next( node );
893 if( strcmp( iface->listTag, tag ) == 0 ) {
899 if( iface->type == ifType ) {
909 * Retrieve a reference to address interface for specified interface type and
910 * XML datasource tag name.
911 * \param addrIndex Address index.
912 * \param ifType Interface type to match.
913 * \param tag XML datasource tag name to match.
914 * \return Reference to address index, or NULL if not found in index.
916 static AddressInterface *addrindex_tag_get_datasource(
917 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
919 AddressInterface *retVal = NULL;
920 GList *node = addrIndex->interfaceList;
923 AddressInterface *iface = node->data;
924 node = g_list_next( node );
925 if( iface->type == ifType && iface->itemTag ) {
926 if( strcmp( iface->itemTag, tag ) == 0 ) {
935 /* **********************************************************************
936 * Interface XML parsing functions.
937 * ***********************************************************************
941 * Write start of XML element to file.
943 * \param lvl Indentation level.
944 * \param name Element name.
946 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
948 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
954 * Write end of XML element to file.
956 * \param lvl Indentation level.
957 * \param name Element name.
959 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
961 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
968 * Write XML attribute to file.
970 * \param name Attribute name.
971 * \param value Attribute value.
973 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
977 xml_file_put_escape_str( fp, value );
982 * Return DOM fragment for current XML tag from file.
983 * \param file XML file being processed.
984 * \return Fragment representing DOM fragment for configuration element.
986 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
987 AddressIfFragment *fragment;
988 AddressIfFragment *child;
998 /* printf( "addrindex_read_fragment\n" ); */
1000 prevLevel = file->level;
1002 /* Get current tag name */
1003 xtag = xml_get_current_tag( file );
1005 /* Create new fragment */
1006 fragment = g_new0( AddressIfFragment, 1 );
1007 fragment->name = g_strdup( xtag->tag );
1008 fragment->children = NULL;
1009 fragment->attributes = NULL;
1011 /* Read attributes */
1013 attr = xml_get_current_tag_attr( file );
1015 name = ((XMLAttr *)attr->data)->name;
1016 value = ((XMLAttr *)attr->data)->value;
1017 nv = g_new0( AddressIfAttrib, 1 );
1018 nv->name = g_strdup( name );
1019 nv->value = g_strdup( value );
1020 list = g_list_append( list, nv );
1021 attr = g_list_next( attr );
1023 fragment->attributes = list;
1025 /* Now read the children */
1027 rc = xml_parse_next_tag( file );
1032 if( file->level < prevLevel ) {
1033 /* We must be above level we start at */
1036 child = addrindex_read_fragment( file );
1037 fragment->children = g_list_append( fragment->children, child );
1044 * Write DOM fragment to file.
1045 * \param fp File to write.
1046 * \param fragment DOM fragment for configuration element.
1047 * \param lvl Indent level.
1049 static void addrindex_write_fragment(
1050 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1055 addrindex_write_elem_s( fp, lvl, fragment->name );
1056 node = fragment->attributes;
1058 AddressIfAttrib *nv = node->data;
1059 addrindex_write_attr( fp, nv->name, nv->value );
1060 node = g_list_next( node );
1062 if( fragment->children ) {
1065 /* Output children */
1066 node = fragment->children;
1068 AddressIfFragment *child = node->data;
1069 addrindex_write_fragment( fp, child, 1+lvl );
1070 node = g_list_next( node );
1073 /* Output closing tag */
1074 addrindex_write_elem_e( fp, lvl, fragment->name );
1083 static void addrindex_print_fragment_r(
1084 const AddressIfFragment *fragment, FILE *stream, gint lvl )
1089 for( i = 0; i < lvl; i++ )
1090 fprintf( stream, " " );
1091 fprintf( stream, "Element:%s:\n", fragment->name );
1092 node = fragment->attributes;
1094 AddressIfAttrib *nv = node->data;
1095 for( i = 0; i < lvl; i++ )
1096 fprintf( stream, " " );
1097 fprintf( stream, " %s : %s\n", nv->name, nv->value );
1098 node = g_list_next( node );
1100 node = fragment->children;
1102 AddressIfFragment *child = node->data;
1103 addrindex_print_fragment_r( child, stream, 1+lvl );
1104 node = g_list_next( node );
1108 static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
1109 addrindex_print_fragment_r( fragment, stream, 0 );
1114 * Read/parse address index file, creating a data source for a regular
1115 * intrinsic XML addressbook.
1116 * \param file Address index file.
1117 * \return Data source.
1119 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1120 AddressDataSource *ds;
1121 AddressBookFile *abf;
1124 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1125 abf = addrbook_create_book();
1126 attr = xml_get_current_tag_attr( file );
1128 gchar *name = ((XMLAttr *)attr->data)->name;
1129 gchar *value = ((XMLAttr *)attr->data)->value;
1130 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1131 addrbook_set_name( abf, value );
1133 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1134 addrbook_set_file( abf, value );
1136 attr = g_list_next( attr );
1138 ds->rawDataSource = abf;
1142 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1143 AddressBookFile *abf = ds->rawDataSource;
1145 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1146 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1147 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1148 fputs( " />\n", fp );
1152 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1153 AddressDataSource *ds;
1157 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1158 vcf = vcard_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_VCARD_NAME ) == 0 ) {
1164 vcard_set_name( vcf, value );
1166 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1167 vcard_set_file( vcf, value );
1169 attr = g_list_next( attr );
1171 ds->rawDataSource = vcf;
1175 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1176 VCardFile *vcf = ds->rawDataSource;
1178 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1179 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1180 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1181 fputs( " />\n", fp );
1186 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1187 AddressDataSource *ds;
1191 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1192 jpf = jpilot_create();
1193 attr = xml_get_current_tag_attr( file );
1195 gchar *name = ((XMLAttr *)attr->data)->name;
1196 gchar *value = ((XMLAttr *)attr->data)->value;
1197 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1198 jpilot_set_name( jpf, value );
1200 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1201 jpilot_set_file( jpf, value );
1203 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1204 jpilot_add_custom_label( jpf, value );
1206 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1207 jpilot_add_custom_label( jpf, value );
1209 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1210 jpilot_add_custom_label( jpf, value );
1212 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1213 jpilot_add_custom_label( jpf, value );
1215 attr = g_list_next( attr );
1217 ds->rawDataSource = jpf;
1221 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1222 JPilotFile *jpf = ds->rawDataSource;
1226 GList *customLbl = jpilot_get_custom_labels( jpf );
1227 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1228 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1229 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1234 g_snprintf( name, sizeof(name), "%s%d",
1235 ATTAG_JPILOT_CUSTOM, ind );
1236 addrindex_write_attr( fp, name, node->data );
1238 node = g_list_next( node );
1240 fputs( " />\n", fp );
1246 * Just read/write DOM fragments (preserve data found in file).
1248 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1249 AddressDataSource *ds;
1251 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1252 ds->rawDataSource = addrindex_read_fragment( file );
1256 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1257 AddressIfFragment *fragment = ds->rawDataSource;
1259 addrindex_write_fragment( fp, fragment, lvl );
1266 * Parse LDAP criteria attribute data from XML file.
1267 * \param file Index file.
1268 * \param ctl LDAP control object to populate.
1270 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1279 if( file == NULL ) {
1284 prevLevel = file->level;
1285 xtagPrev = xml_get_current_tag( file );
1287 rc = xml_parse_next_tag( file );
1289 /* Terminate prematurely */
1290 mgu_free_dlist( list );
1294 if( file->level < prevLevel ) {
1295 /* We must be above level we start at */
1299 /* Get a tag (element) */
1300 xtag = xml_get_current_tag( file );
1301 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1302 /* LDAP criteria attribute */
1303 attr = xml_get_current_tag_attr( file );
1305 gchar *name = ((XMLAttr *)attr->data)->name;
1306 gchar *value = ((XMLAttr *)attr->data)->value;
1307 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1308 if( value && strlen( value ) > 0 ) {
1309 list = g_list_append(
1310 list, g_strdup( value ) );
1313 attr = g_list_next( attr );
1317 if( xtag != xtagPrev ) {
1318 /* Found a new tag */
1325 /* Build list of search attributes */
1326 ldapctl_criteria_list_clear( ctl );
1329 ldapctl_criteria_list_add( ctl, node->data );
1330 g_free( node->data );
1332 node = g_list_next( node );
1334 g_list_free( list );
1340 * Parse LDAP control data from XML file.
1341 * \param file Index file.
1342 * \return Initialized data soruce object.
1344 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1345 AddressDataSource *ds;
1349 gchar *serverName = NULL;
1350 gchar *criteria = NULL;
1351 gboolean bDynSearch;
1355 /* printf( "addrindex_parse_ldap\n" ); */
1356 /* Set up some defaults */
1359 iMatch = LDAPCTL_MATCH_BEGINWITH;
1361 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1362 ctl = ldapctl_create();
1363 attr = xml_get_current_tag_attr( file );
1365 gchar *name = ((XMLAttr *)attr->data)->name;
1366 gchar *value = ((XMLAttr *)attr->data)->value;
1367 gint ivalue = atoi( value );
1369 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1370 if( serverName ) g_free( serverName );
1371 serverName = g_strdup( value );
1373 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1374 ldapctl_set_host( ctl, value );
1376 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1377 ldapctl_set_port( ctl, ivalue );
1379 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1380 ldapctl_set_base_dn( ctl, value );
1382 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1383 ldapctl_set_bind_dn( ctl, value );
1385 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1386 ldapctl_set_bind_password( ctl, value );
1388 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1389 if( criteria ) g_free( criteria );
1390 criteria = g_strdup( value );
1392 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1393 ldapctl_set_max_entries( ctl, ivalue );
1395 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1396 ldapctl_set_timeout( ctl, ivalue );
1398 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1399 ldapctl_set_max_query_age( ctl, ivalue );
1401 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1403 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1407 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1408 iMatch = LDAPCTL_MATCH_BEGINWITH;
1409 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1410 iMatch = LDAPCTL_MATCH_CONTAINS;
1413 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1415 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1419 attr = g_list_next( attr );
1422 server = ldapsvr_create_noctl();
1423 ldapsvr_set_name( server, serverName );
1424 ldapsvr_set_search_flag( server, bDynSearch );
1425 ldapctl_set_matching_option( ctl, iMatch );
1426 ldapctl_set_tls( ctl, bTLS );
1427 g_free( serverName );
1428 ldapsvr_set_control( server, ctl );
1429 ds->rawDataSource = server;
1431 addrindex_parse_ldap_attrlist( file, ctl );
1433 * If criteria have been specified and no attributes were listed, then
1434 * convert old style criteria into an attribute list. Any criteria will
1435 * be dropped when saving data.
1438 if( ! ldapctl_get_criteria_list( ctl ) ) {
1439 ldapctl_parse_ldap_search( ctl, criteria );
1443 /* ldapsvr_print_data( server, stdout ); */
1448 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1449 LdapServer *server = ds->rawDataSource;
1450 LdapControl *ctl = NULL;
1455 ctl = server->control;
1457 if( ctl == NULL ) return;
1459 /* Output start element with attributes */
1460 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1461 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1462 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1464 sprintf( value, "%d", ctl->port );
1465 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1467 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1468 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1469 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1471 sprintf( value, "%d", ctl->maxEntries );
1472 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1473 sprintf( value, "%d", ctl->timeOut );
1474 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1475 sprintf( value, "%d", ctl->maxQueryAge );
1476 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1478 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1479 server->searchFlag ?
1480 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1482 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1483 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1484 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1486 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1488 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1492 /* Output attributes */
1493 node = ldapctl_get_criteria_list( ctl );
1495 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1496 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1498 node = g_list_next( node );
1501 /* End of element */
1502 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1507 * Just read/write DOM fragments (preserve data found in file).
1509 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1510 AddressDataSource *ds;
1512 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1513 ds->rawDataSource = addrindex_read_fragment( file );
1517 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1518 AddressIfFragment *fragment = ds->rawDataSource;
1520 addrindex_write_fragment( fp, fragment, lvl );
1525 /* **********************************************************************
1526 * Address index I/O functions.
1527 * ***********************************************************************
1530 * Read address index file, creating appropriate data sources for each address
1533 * \param addrIndex Address index.
1534 * \param file Address index file.
1536 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1539 AddressInterface *iface = NULL, *dsIFace = NULL;
1540 AddressDataSource *ds;
1543 addrIndex->loadedFlag = FALSE;
1545 prev_level = file->level;
1546 rc = xml_parse_next_tag( file );
1547 if( file->level == 0 ) return;
1549 xtag = xml_get_current_tag( file );
1551 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1553 addrIndex->lastType = iface->type;
1554 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1557 dsIFace = addrindex_tag_get_datasource(
1558 addrIndex, addrIndex->lastType, xtag->tag );
1560 /* Add data source to list */
1562 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1563 ds = addrindex_parse_book( file );
1564 if( ds->rawDataSource ) {
1565 addrbook_set_path( ds->rawDataSource,
1566 addrIndex->filePath );
1569 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1570 ds = addrindex_parse_vcard( file );
1572 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1573 ds = addrindex_parse_jpilot( file );
1575 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1576 ds = addrindex_parse_ldap( file );
1579 ds->interface = dsIFace;
1580 addrindex_hash_add_cache( addrIndex, ds );
1581 dsIFace->listSource =
1582 g_list_append( dsIFace->listSource, ds );
1590 * Search order sorting comparison function for building search order list.
1592 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1593 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1594 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1596 return ifaceA->searchOrder - ifaceB->searchOrder;
1600 * Build list of data sources to process.
1601 * \param addrIndex Address index object.
1603 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1606 /* Clear existing list */
1607 g_list_free( addrIndex->searchOrder );
1608 addrIndex->searchOrder = NULL;
1610 /* Build new list */
1611 nodeIf = addrIndex->interfaceList;
1613 AddressInterface *iface = nodeIf->data;
1614 if( iface->useInterface ) {
1615 if( iface->searchOrder > 0 ) {
1616 /* Add to search order list */
1617 addrIndex->searchOrder = g_list_insert_sorted(
1618 addrIndex->searchOrder, iface,
1619 addrindex_search_order_compare );
1622 nodeIf = g_list_next( nodeIf );
1626 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1627 XMLFile *file = NULL;
1628 gchar *fileSpec = NULL;
1630 g_return_val_if_fail( addrIndex != NULL, -1 );
1632 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1633 addrIndex->retVal = MGU_NO_FILE;
1634 file = xml_open_file( fileSpec );
1637 if( file == NULL ) {
1639 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1641 return addrIndex->retVal;
1644 addrIndex->retVal = MGU_BAD_FORMAT;
1645 if( xml_get_dtd( file ) == 0 ) {
1646 if( xml_parse_next_tag( file ) == 0 ) {
1647 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1648 addrindex_read_index( addrIndex, file );
1649 addrIndex->retVal = MGU_SUCCESS;
1653 xml_close_file( file );
1655 addrindex_build_search_order( addrIndex );
1657 return addrIndex->retVal;
1660 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1661 GList *nodeIF, *nodeDS;
1663 gint lvlItem = 1 + lvlList;
1665 nodeIF = addrIndex->interfaceList;
1667 AddressInterface *iface = nodeIF->data;
1668 if( ! iface->legacyFlag ) {
1669 nodeDS = iface->listSource;
1670 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1673 AddressDataSource *ds = nodeDS->data;
1675 if( iface->type == ADDR_IF_BOOK ) {
1676 addrindex_write_book( fp, ds, lvlItem );
1678 if( iface->type == ADDR_IF_VCARD ) {
1679 addrindex_write_vcard( fp, ds, lvlItem );
1681 if( iface->type == ADDR_IF_JPILOT ) {
1682 addrindex_write_jpilot( fp, ds, lvlItem );
1684 if( iface->type == ADDR_IF_LDAP ) {
1685 addrindex_write_ldap( fp, ds, lvlItem );
1688 nodeDS = g_list_next( nodeDS );
1690 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1692 nodeIF = g_list_next( nodeIF );
1697 * Write data to specified file.
1698 * Enter: addrIndex Address index object.
1699 * newFile New file name.
1700 * return: Status code, from addrIndex->retVal.
1701 * Note: File will be created in directory specified by addrIndex.
1703 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1706 #ifndef DEV_STANDALONE
1710 g_return_val_if_fail( addrIndex != NULL, -1 );
1712 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1713 addrIndex->retVal = MGU_OPEN_FILE;
1714 #ifdef DEV_STANDALONE
1715 fp = g_fopen( fileSpec, "wb" );
1718 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1720 pfile = prefs_write_open( fileSpec );
1724 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1726 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1729 addrindex_write_index( addrIndex, fp );
1730 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1732 addrIndex->retVal = MGU_SUCCESS;
1733 #ifdef DEV_STANDALONE
1736 if( prefs_file_close( pfile ) < 0 ) {
1737 addrIndex->retVal = MGU_ERROR_WRITE;
1743 return addrIndex->retVal;
1747 * Save address index data to original file.
1748 * return: Status code, from addrIndex->retVal.
1750 gint addrindex_save_data( AddressIndex *addrIndex ) {
1751 g_return_val_if_fail( addrIndex != NULL, -1 );
1753 addrIndex->retVal = MGU_NO_FILE;
1754 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1755 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1757 addrindex_write_to( addrIndex, addrIndex->fileName );
1758 if( addrIndex->retVal == MGU_SUCCESS ) {
1759 addrIndex->dirtyFlag = FALSE;
1761 return addrIndex->retVal;
1765 * Save all address book files which may have changed.
1766 * Return: Status code, set if there was a problem saving data.
1768 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1769 gint retVal = MGU_SUCCESS;
1770 GList *nodeIf, *nodeDS;
1772 nodeIf = addrIndex->interfaceList;
1774 AddressInterface *iface = nodeIf->data;
1775 if( iface->type == ADDR_IF_BOOK ) {
1776 nodeDS = iface->listSource;
1778 AddressDataSource *ds = nodeDS->data;
1779 AddressBookFile *abf = ds->rawDataSource;
1780 if( addrbook_get_dirty( abf ) ) {
1781 if( addrbook_get_read_flag( abf ) ) {
1782 addrbook_save_data( abf );
1783 if( abf->retVal != MGU_SUCCESS ) {
1784 retVal = abf->retVal;
1788 nodeDS = g_list_next( nodeDS );
1792 nodeIf = g_list_next( nodeIf );
1798 /* **********************************************************************
1799 * Address book conversion to new format.
1800 * ***********************************************************************
1803 #define ELTAG_IF_OLD_FOLDER "folder"
1804 #define ELTAG_IF_OLD_GROUP "group"
1805 #define ELTAG_IF_OLD_ITEM "item"
1806 #define ELTAG_IF_OLD_NAME "name"
1807 #define ELTAG_IF_OLD_ADDRESS "address"
1808 #define ELTAG_IF_OLD_REMARKS "remarks"
1809 #define ATTAG_IF_OLD_NAME "name"
1811 #define TEMPNODE_ROOT 0
1812 #define TEMPNODE_FOLDER 1
1813 #define TEMPNODE_GROUP 2
1814 #define TEMPNODE_ADDRESS 3
1816 typedef struct _AddressCvt_Node AddressCvtNode;
1817 struct _AddressCvt_Node {
1826 * Parse current address item.
1828 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1833 nn = g_new0( AddressCvtNode, 1 );
1834 nn->type = TEMPNODE_ADDRESS;
1837 level = file->level;
1840 xml_parse_next_tag(file);
1841 if (file->level < level) return nn;
1843 element = xml_get_element( file );
1844 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1845 nn->name = g_strdup( element );
1847 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1848 nn->address = g_strdup( element );
1850 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1851 nn->remarks = g_strdup( element );
1853 xml_parse_next_tag(file);
1858 * Create a temporary node below specified node.
1860 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1862 nn = g_new0( AddressCvtNode, 1 );
1864 nn->name = g_strdup( name );
1865 nn->remarks = g_strdup( rem );
1866 node->list = g_list_append( node->list, nn );
1871 * Process current temporary node.
1873 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1876 AddressCvtNode *newNode = NULL;
1881 prev_level = file->level;
1882 xml_parse_next_tag( file );
1883 if (file->level < prev_level) return;
1887 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1888 attr = xml_get_current_tag_attr(file);
1890 name = ((XMLAttr *)attr->data)->name;
1891 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1892 value = ((XMLAttr *)attr->data)->value;
1895 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1896 addrindex_add_obj( file, newNode );
1899 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1900 attr = xml_get_current_tag_attr(file);
1902 name = ((XMLAttr *)attr->data)->name;
1903 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1904 value = ((XMLAttr *)attr->data)->value;
1907 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1908 addrindex_add_obj( file, newNode );
1910 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1911 newNode = addrindex_parse_item( file );
1912 node->list = g_list_append( node->list, newNode );
1915 /* printf( "invalid: !!! \n" ); */
1916 attr = xml_get_current_tag_attr( file );
1922 * Consume all nodes below current tag.
1924 static void addrindex_consume_tree( XMLFile *file ) {
1931 prev_level = file->level;
1932 xml_parse_next_tag( file );
1933 if (file->level < prev_level) return;
1935 xtag = xml_get_current_tag( file );
1936 /* printf( "tag : %s\n", xtag->tag ); */
1937 element = xml_get_element( file );
1938 attr = xml_get_current_tag_attr( file );
1939 /* show_attribs( attr ); */
1940 /* printf( "\ttag value : %s :\n", element ); */
1941 addrindex_consume_tree( file );
1946 * Print temporary tree.
1948 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1951 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1952 fprintf( stream, "\tname :%s:\n", node->name );
1953 fprintf( stream, "\taddr :%s:\n", node->address );
1954 fprintf( stream, "\trems :%s:\n", node->remarks );
1956 fprintf( stream, "\t--list----\n" );
1960 AddressCvtNode *lNode = list->data;
1961 list = g_list_next( list );
1962 addrindex_print_node( lNode, stream );
1964 fprintf( stream, "\t==list-%d==\n", node->type );
1968 * Free up temporary tree.
1970 static void addrindex_free_node( AddressCvtNode *node ) {
1971 GList *list = node->list;
1974 AddressCvtNode *lNode = list->data;
1975 list = g_list_next( list );
1976 addrindex_free_node( lNode );
1978 node->type = TEMPNODE_ROOT;
1979 g_free( node->name );
1980 g_free( node->address );
1981 g_free( node->remarks );
1982 g_list_free( node->list );
1987 * Process address book for specified node.
1989 static void addrindex_process_node(
1990 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1991 ItemGroup *parentGrp, ItemFolder *folderGrp )
1994 ItemFolder *itemFolder = NULL;
1995 ItemGroup *itemGParent = parentGrp;
1996 ItemFolder *itemGFolder = folderGrp;
1997 AddressCache *cache = abf->addressCache;
1999 if( node->type == TEMPNODE_ROOT ) {
2000 itemFolder = parent;
2002 else if( node->type == TEMPNODE_FOLDER ) {
2003 itemFolder = addritem_create_item_folder();
2004 addritem_folder_set_name( itemFolder, node->name );
2005 addrcache_id_folder( cache, itemFolder );
2006 addrcache_folder_add_folder( cache, parent, itemFolder );
2009 else if( node->type == TEMPNODE_GROUP ) {
2010 ItemGroup *itemGroup;
2013 /* Create a folder for group */
2014 fName = g_strdup_printf( "Cvt - %s", node->name );
2015 itemGFolder = addritem_create_item_folder();
2016 addritem_folder_set_name( itemGFolder, fName );
2017 addrcache_id_folder( cache, itemGFolder );
2018 addrcache_folder_add_folder( cache, parent, itemGFolder );
2021 /* Add group into folder */
2022 itemGroup = addritem_create_item_group();
2023 addritem_group_set_name( itemGroup, node->name );
2024 addrcache_id_group( cache, itemGroup );
2025 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2026 itemGParent = itemGroup;
2028 else if( node->type == TEMPNODE_ADDRESS ) {
2029 ItemPerson *itemPerson;
2030 ItemEMail *itemEMail;
2032 /* Create person and email objects */
2033 itemPerson = addritem_create_item_person();
2034 addritem_person_set_common_name( itemPerson, node->name );
2035 addrcache_id_person( cache, itemPerson );
2036 itemEMail = addritem_create_item_email();
2037 addritem_email_set_address( itemEMail, node->address );
2038 addritem_email_set_remarks( itemEMail, node->remarks );
2039 addrcache_id_email( cache, itemEMail );
2040 addrcache_person_add_email( cache, itemPerson, itemEMail );
2042 /* Add person into appropriate folder */
2044 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2047 addrcache_folder_add_person( cache, parent, itemPerson );
2050 /* Add email address only into group */
2052 addrcache_group_add_email( cache, parentGrp, itemEMail );
2058 AddressCvtNode *lNode = list->data;
2059 list = g_list_next( list );
2060 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2065 * Process address book to specified file number.
2067 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2068 gboolean retVal = FALSE;
2069 AddressBookFile *abf = NULL;
2070 AddressCvtNode *rootNode = NULL;
2071 gchar *newFile = NULL;
2072 GList *fileList = NULL;
2075 /* Setup root node */
2076 rootNode = g_new0( AddressCvtNode, 1 );
2077 rootNode->type = TEMPNODE_ROOT;
2078 rootNode->name = g_strdup( "root" );
2079 rootNode->list = NULL;
2080 addrindex_add_obj( file, rootNode );
2081 /* addrindex_print_node( rootNode, stdout ); */
2083 /* Create new address book */
2084 abf = addrbook_create_book();
2085 addrbook_set_name( abf, displayName );
2086 addrbook_set_path( abf, addrIndex->filePath );
2088 /* Determine next available file number */
2089 fileList = addrbook_get_bookfile_list( abf );
2091 fileNum = 1 + abf->maxValue;
2093 g_list_free( fileList );
2096 newFile = addrbook_gen_new_file_name( fileNum );
2098 addrbook_set_file( abf, newFile );
2101 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2103 /* addrbook_dump_book( abf, stdout ); */
2104 addrbook_save_data( abf );
2105 addrIndex->retVal = abf->retVal;
2106 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2108 addrbook_free_book( abf );
2110 addrindex_free_node( rootNode );
2113 /* Create entries in address index */
2115 abf = addrbook_create_book();
2116 addrbook_set_name( abf, displayName );
2117 addrbook_set_path( abf, addrIndex->filePath );
2118 addrbook_set_file( abf, newFile );
2119 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2126 * Process tree converting data.
2128 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2136 prev_level = file->level;
2137 xml_parse_next_tag( file );
2138 if (file->level < prev_level) return;
2140 xtag = xml_get_current_tag( file );
2141 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2142 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2143 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2144 addrIndex->needsConversion = FALSE;
2145 addrIndex->wasConverted = TRUE;
2150 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2151 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2152 addrIndex->needsConversion = FALSE;
2153 addrIndex->wasConverted = TRUE;
2158 element = xml_get_element( file );
2159 attr = xml_get_current_tag_attr( file );
2160 /* show_attribs( attr ); */
2161 /* printf( "\ttag value : %s :\n", element ); */
2162 addrindex_consume_tree( file );
2166 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2167 XMLFile *file = NULL;
2170 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2171 addrIndex->retVal = MGU_NO_FILE;
2172 file = xml_open_file( fileSpec );
2175 if( file == NULL ) {
2176 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2177 return addrIndex->retVal;
2180 addrIndex->retVal = MGU_BAD_FORMAT;
2181 if( xml_get_dtd( file ) == 0 ) {
2182 if( xml_parse_next_tag( file ) == 0 ) {
2183 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2184 addrindex_convert_tree( addrIndex, file );
2188 xml_close_file( file );
2189 return addrIndex->retVal;
2193 * Create a new address book file.
2195 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2196 gboolean retVal = FALSE;
2197 AddressBookFile *abf = NULL;
2198 gchar *newFile = NULL;
2199 GList *fileList = NULL;
2202 /* Create new address book */
2203 abf = addrbook_create_book();
2204 addrbook_set_name( abf, displayName );
2205 addrbook_set_path( abf, addrIndex->filePath );
2207 /* Determine next available file number */
2208 fileList = addrbook_get_bookfile_list( abf );
2210 fileNum = 1 + abf->maxValue;
2212 g_list_free( fileList );
2215 newFile = addrbook_gen_new_file_name( fileNum );
2217 addrbook_set_file( abf, newFile );
2220 addrbook_save_data( abf );
2221 addrIndex->retVal = abf->retVal;
2222 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2223 addrbook_free_book( abf );
2226 /* Create entries in address index */
2228 abf = addrbook_create_book();
2229 addrbook_set_name( abf, displayName );
2230 addrbook_set_path( abf, addrIndex->filePath );
2231 addrbook_set_file( abf, newFile );
2232 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2239 * Read data for address index performing a conversion if necesary.
2240 * Enter: addrIndex Address index object.
2241 * return: Status code, from addrIndex->retVal.
2242 * Note: New address book files will be created in directory specified by
2243 * addrIndex. Three files will be created, for the following:
2244 * "Common addresses"
2245 * "Personal addresses"
2246 * "Gathered addresses" - a new address book.
2248 gint addrindex_read_data( AddressIndex *addrIndex ) {
2249 g_return_val_if_fail( addrIndex != NULL, -1 );
2251 addrIndex->conversionError = FALSE;
2252 addrindex_read_file( addrIndex );
2253 if( addrIndex->retVal == MGU_SUCCESS ) {
2254 if( addrIndex->needsConversion ) {
2255 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2256 addrIndex->conversionError = TRUE;
2259 addrIndex->conversionError = TRUE;
2262 addrIndex->dirtyFlag = TRUE;
2264 return addrIndex->retVal;
2268 * Create new address books for a new address index.
2269 * Enter: addrIndex Address index object.
2270 * return: Status code, from addrIndex->retVal.
2271 * Note: New address book files will be created in directory specified by
2272 * addrIndex. Three files will be created, for the following:
2273 * "Common addresses"
2274 * "Personal addresses"
2275 * "Gathered addresses" - a new address book.
2277 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2280 g_return_val_if_fail( addrIndex != NULL, -1 );
2282 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2284 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2285 addrIndex->dirtyFlag = TRUE;
2287 return addrIndex->retVal;
2290 /* **********************************************************************
2291 * New interface stuff.
2292 * ***********************************************************************
2296 * Return modified flag for specified data source.
2298 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2299 gboolean retVal = FALSE;
2300 AddressInterface *iface;
2302 if( ds == NULL ) return retVal;
2303 iface = ds->interface;
2304 if( iface == NULL ) return retVal;
2305 if( iface->getModifyFlag ) {
2306 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2312 * Return accessed flag for specified data source.
2314 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2315 gboolean retVal = FALSE;
2316 AddressInterface *iface;
2318 if( ds == NULL ) return retVal;
2319 iface = ds->interface;
2320 if( iface == NULL ) return retVal;
2321 if( iface->getAccessFlag ) {
2322 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2328 * Return data read flag for specified data source.
2330 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2331 gboolean retVal = TRUE;
2332 AddressInterface *iface;
2334 if( ds == NULL ) return retVal;
2335 iface = ds->interface;
2336 if( iface == NULL ) return retVal;
2337 if( iface->getReadFlag ) {
2338 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2344 * Return status code for specified data source.
2346 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2347 gint retVal = MGU_SUCCESS;
2348 AddressInterface *iface;
2350 if( ds == NULL ) return retVal;
2351 iface = ds->interface;
2352 if( iface == NULL ) return retVal;
2353 if( iface->getStatusCode ) {
2354 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2360 * Return data read flag for specified data source.
2362 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2363 gint retVal = MGU_SUCCESS;
2364 AddressInterface *iface;
2366 if( ds == NULL ) return retVal;
2367 iface = ds->interface;
2368 if( iface == NULL ) return retVal;
2369 if( iface->getReadData ) {
2371 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2372 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2374 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2380 * Return data read flag for specified data source.
2382 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2383 ItemFolder *retVal = NULL;
2384 AddressInterface *iface;
2386 if( ds == NULL ) return retVal;
2387 iface = ds->interface;
2388 if( iface == NULL ) return retVal;
2389 if( iface->getRootFolder ) {
2390 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2396 * Return list of folders for specified data source.
2398 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2399 GList *retVal = FALSE;
2400 AddressInterface *iface;
2402 if( ds == NULL ) return retVal;
2403 iface = ds->interface;
2404 if( iface == NULL ) return retVal;
2405 if( iface->getListFolder ) {
2406 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2412 * Return list of persons in root folder for specified data source.
2414 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2415 GList *retVal = FALSE;
2416 AddressInterface *iface;
2418 if( ds == NULL ) return retVal;
2419 iface = ds->interface;
2420 if( iface == NULL ) return retVal;
2421 if( iface->getListPerson ) {
2422 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2428 * Return name for specified data source.
2430 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2431 gchar *retVal = FALSE;
2432 AddressInterface *iface;
2434 if( ds == NULL ) return retVal;
2435 iface = ds->interface;
2436 if( iface == NULL ) return retVal;
2437 if( iface->getName ) {
2438 retVal = ( iface->getName ) ( ds->rawDataSource );
2444 * Set the access flag inside the data source.
2446 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2447 AddressInterface *iface;
2449 if( ds == NULL ) return;
2450 iface = ds->interface;
2451 if( iface == NULL ) return;
2452 if( iface->setAccessFlag ) {
2453 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2458 * Return read only flag for specified data source.
2460 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2461 AddressInterface *iface;
2462 if( ds == NULL ) return TRUE;
2463 iface = ds->interface;
2464 if( iface == NULL ) return TRUE;
2465 return iface->readOnly;
2469 * Return list of all persons for specified data source.
2471 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2472 GList *retVal = NULL;
2473 AddressInterface *iface;
2475 if( ds == NULL ) return retVal;
2476 iface = ds->interface;
2477 if( iface == NULL ) return retVal;
2478 if( iface->getAllPersons ) {
2479 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2485 * Return list of all groups for specified data source.
2487 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2488 GList *retVal = NULL;
2489 AddressInterface *iface;
2491 if( ds == NULL ) return retVal;
2492 iface = ds->interface;
2493 if( iface == NULL ) return retVal;
2494 if( iface->getAllGroups ) {
2495 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2500 /* **********************************************************************
2501 * Address search stuff.
2502 * ***********************************************************************
2506 * Setup or register the dynamic search that will be performed. The search
2507 * is registered with the query manager.
2509 * \param searchTerm Search term. A private copy will be made.
2510 * \param callBackEntry Callback function that should be called when
2511 * each entry is received.
2512 * \param callBackEnd Callback function that should be called when
2513 * search has finished running.
2514 * \return ID allocated to query that will be executed.
2516 gint addrindex_setup_search(
2517 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2522 /* Set up a dynamic address query */
2523 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2524 queryID = req->queryID;
2525 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2527 /* printf( "***> query ID ::%d::\n", queryID ); */
2534 * Function prototypes (not in header file or circular reference errors are
2537 LdapQuery *ldapsvr_new_dynamic_search(
2538 LdapServer *server, QueryRequest *req );
2539 LdapQuery *ldapsvr_new_explicit_search(
2540 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2545 * Execute the previously registered dynamic search.
2547 * \param req Address query object to execute.
2548 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2551 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2552 AddressInterface *iface;
2553 AddressDataSource *ds;
2558 /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2559 nodeIf = _addressIndex_->searchOrder;
2561 iface = nodeIf->data;
2562 nodeIf = g_list_next( nodeIf );
2564 if( ! iface->useInterface ) {
2567 if( ! iface->externalQuery ) {
2572 nodeDS = iface->listSource;
2575 nodeDS = g_list_next( nodeDS );
2577 if( type == ADDR_IF_LDAP ) {
2581 server = ds->rawDataSource;
2582 if( ! server->searchFlag ) {
2585 if( ldapsvr_reuse_previous( server, req ) ) {
2589 /* Start a new dynamic search */
2590 qry = ldapsvr_new_dynamic_search( server, req );
2592 ldapsvr_execute_query( server, qry );
2602 * Stop the previously registered search.
2604 * \param queryID ID of search query to stop.
2606 void addrindex_stop_search( const gint queryID ){
2608 AddrQueryObject *aqo;
2611 /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
2612 /* If query ID does not match, search has not been setup */
2613 req = qrymgr_find_request( queryID );
2618 /* Stop all queries that were associated with request */
2619 node = req->queryList;
2623 if( aqo->queryType == ADDRQUERY_LDAP ) {
2624 LdapQuery *qry = ( LdapQuery * ) aqo;
2625 ldapqry_set_stop_flag( qry, TRUE );
2629 node = g_list_next( node );
2632 /* Delete query request */
2633 qrymgr_delete_request( queryID );
2637 * Setup or register the explicit search that will be performed. The search is
2638 * registered with the query manager.
2640 * \param ds Data source to search.
2641 * \param searchTerm Search term to locate.
2642 * \param folder Folder to receive search results; may be NULL.
2643 * \param callbackEnd Function to call when search has terminated.
2644 * \param callbackEntry Function to called for each entry processed.
2645 * \return ID allocated to query that will be executed.
2647 gint addrindex_setup_explicit_search(
2648 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2649 void *callBackEnd, void *callBackEntry )
2655 /* Name the query */
2656 name = g_strdup_printf( "Search '%s'", searchTerm );
2658 /* Set up query request */
2659 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2660 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2661 queryID = req->queryID;
2663 if( ds->type == ADDR_IF_LDAP ) {
2667 server = ds->rawDataSource;
2668 ldapsvr_new_explicit_search( server, req, folder );
2672 qrymgr_delete_request( queryID );
2681 * Execute the previously registered explicit search.
2683 * \param req Address query request object to execute.
2684 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2687 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2689 AddrQueryObject *aqo;
2693 /* Note: there should only be one query in the list. */
2694 aqo = req->queryList->data;
2696 if( aqo->queryType == ADDRQUERY_LDAP ) {
2700 qry = ( LdapQuery * ) aqo;
2701 server = qry->server;
2703 /* Start the search */
2705 ldapsvr_execute_query( server, qry );
2712 * Start the previously registered search.
2714 * \param queryID ID of search query to be executed.
2715 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2718 gboolean addrindex_start_search( const gint queryID ) {
2721 AddrSearchType searchType;
2724 /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
2725 req = qrymgr_find_request( queryID );
2730 searchType = req->searchType;
2731 if( searchType == ADDRSEARCH_DYNAMIC ) {
2732 retVal = addrindex_start_dynamic( req );
2734 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2735 retVal = addrindex_start_explicit( req );
2742 * Remove results (folder and data) for specified data source and folder.
2743 * \param ds Data source to process.
2744 * \param folder Results folder to remove.
2746 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2747 AddrBookBase *adbase;
2748 AddressCache *cache;
2751 /* printf( "addrindex_remove_results/start\n" ); */
2753 /* Test for folder */
2754 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2755 /* printf( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2756 adbase = ( AddrBookBase * ) ds->rawDataSource;
2757 if( adbase == NULL ) return;
2758 cache = adbase->addressCache;
2760 /* Hide folder to prevent re-display */
2761 addritem_folder_set_hidden( folder, TRUE );
2763 if( ds->type == ADDR_IF_LDAP ) {
2768 qry = ( LdapQuery * ) folder->folderData;
2769 queryID = ADDRQUERY_ID(qry);
2770 /* printf( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2771 delFlag = ldapquery_remove_results( qry );
2773 ldapqry_free( qry );
2775 /* printf( "calling ldapquery_remove_results...done\n" ); */
2778 printf( "delFlag IS-TRUE\n" );
2781 printf( "delFlag IS-FALSE\n" );
2782 addressbook_clear_idler( queryID );
2787 /* printf( "addrindex_remove_results/end\n" ); */
2789 /* Delete query request */
2791 qrymgr_delete_request( queryID );
2795 /* **********************************************************************
2796 * Address completion stuff.
2797 * ***********************************************************************
2801 * This function is used by the address completion function to load
2802 * addresses for all non-external address book interfaces.
2804 * \param callBackFunc Function to be called when an address is
2806 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2808 gboolean addrindex_load_completion(
2809 gint (*callBackFunc) ( const gchar *, const gchar *,
2810 const gchar *, const gchar * ) )
2812 AddressDataSource *ds;
2813 GList *nodeIf, *nodeDS;
2814 GList *listP, *nodeP;
2818 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2820 AddressInterface *iface = nodeIf->data;
2822 nodeIf = g_list_next( nodeIf );
2823 if( ! iface->useInterface ) {
2826 if( iface->externalQuery ) {
2829 nodeDS = iface->listSource;
2833 /* Read address book */
2834 if( addrindex_ds_get_modify_flag( ds ) ) {
2835 addrindex_ds_read_data( ds );
2838 if( ! addrindex_ds_get_read_flag( ds ) ) {
2839 addrindex_ds_read_data( ds );
2842 /* Get all persons */
2843 listP = addrindex_ds_get_all_persons( ds );
2846 ItemPerson *person = nodeP->data;
2847 nodeM = person->listEMail;
2849 /* Figure out name to use */
2850 sName = ADDRITEM_NAME(person);
2851 if( sName == NULL || *sName == '\0' ) {
2852 sName = person->nickName;
2855 /* Process each E-Mail address */
2857 ItemEMail *email = nodeM->data;
2859 callBackFunc( sName, email->address, person->nickName,
2860 ADDRITEM_NAME(email) );
2862 nodeM = g_list_next( nodeM );
2864 nodeP = g_list_next( nodeP );
2866 /* Free up the list */
2867 g_list_free( listP );
2869 nodeDS = g_list_next( nodeDS );
2877 * This function can be used to collect information about
2878 * addressbook entries that contain a specific attribute.
2880 * \param attr Name of attribute to look for
2881 * \param callBackFunc Function to be called when a matching attribute was found
2882 * \return <i>TRUE</i>
2884 gboolean addrindex_load_person_attribute(
2886 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2888 AddressDataSource *ds;
2889 GList *nodeIf, *nodeDS;
2890 GList *listP, *nodeP;
2893 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2896 AddressInterface *iface = nodeIf->data;
2898 nodeIf = g_list_next( nodeIf );
2899 if( ! iface->useInterface ) {
2902 if( iface->externalQuery ) {
2905 nodeDS = iface->listSource;
2909 /* Read address book */
2910 if( addrindex_ds_get_modify_flag( ds ) ) {
2911 addrindex_ds_read_data( ds );
2914 if( ! addrindex_ds_get_read_flag( ds ) ) {
2915 addrindex_ds_read_data( ds );
2918 /* Check addressbook name */
2919 cur_bname = addrindex_ds_get_name( ds );
2921 /* Get all persons */
2922 listP = addrindex_ds_get_all_persons( ds );
2925 ItemPerson *person = nodeP->data;
2927 /* Return all ItemPerson's if attr is NULL */
2928 if( attr == NULL ) {
2929 callBackFunc(person, cur_bname);
2932 /* Return ItemPerson's with specific attribute */
2934 nodeA = person->listAttrib;
2935 /* Process each User Attribute */
2937 UserAttribute *attrib = nodeA->data;
2939 !strcmp( attrib->name,attr ) ) {
2940 callBackFunc(person, cur_bname);
2942 nodeA = g_list_next( nodeA );
2945 nodeP = g_list_next( nodeP );
2947 /* Free up the list */
2948 g_list_free( listP );
2950 nodeDS = g_list_next( nodeDS );