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"
102 #define ELTAG_LDAP_ATTR_SRCH "attribute"
103 #define ATTAG_LDAP_ATTR_NAME "name"
105 /* Attribute values */
106 #define ATVAL_BOOLEAN_YES "yes"
107 #define ATVAL_BOOLEAN_NO "no"
108 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
109 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
112 #define ATTAG_LDAP_DEFAULT "default"
114 #define DISP_NEW_COMMON _("Common addresses")
115 #define DISP_NEW_PERSONAL _("Personal addresses")
117 /* Old address book */
118 #define TAG_IF_OLD_COMMON "common_address"
119 #define TAG_IF_OLD_PERSONAL "personal_address"
121 #define DISP_OLD_COMMON _("Common address")
122 #define DISP_OLD_PERSONAL _("Personal address")
127 static AddressIndex *_addressIndex_ = NULL;
130 * Define attribute name-value pair.
132 typedef struct _AddressIfAttr AddressIfAttrib;
133 struct _AddressIfAttr {
139 * Define DOM fragment.
141 typedef struct _AddressIfFrag AddressIfFragment;
142 struct _AddressIfFrag {
149 * Build interface with default values.
151 * \param type Interface type.
152 * \param name Interface name.
153 * \param tagIf XML tag name for interface in address index file.
154 * \param tagDS XML tag name for datasource in address index file.
155 * \return Address interface object.
157 static AddressInterface *addrindex_create_interface(
158 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
160 AddressInterface *iface = g_new0( AddressInterface, 1 );
162 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
163 ADDRITEM_ID(iface) = NULL;
164 ADDRITEM_NAME(iface) = g_strdup( name );
165 ADDRITEM_PARENT(iface) = NULL;
166 ADDRITEM_SUBTYPE(iface) = type;
168 iface->name = g_strdup( name );
169 iface->listTag = g_strdup( tagIf );
170 iface->itemTag = g_strdup( tagDS );
171 iface->legacyFlag = FALSE;
172 iface->haveLibrary = TRUE;
173 iface->useInterface = TRUE;
174 iface->readOnly = TRUE;
176 /* Set callbacks to NULL values - override for each interface */
177 iface->getAccessFlag = NULL;
178 iface->getModifyFlag = NULL;
179 iface->getReadFlag = NULL;
180 iface->getStatusCode = NULL;
181 iface->getReadData = NULL;
182 iface->getRootFolder = NULL;
183 iface->getListFolder = NULL;
184 iface->getListPerson = NULL;
185 iface->getAllPersons = NULL;
186 iface->getAllGroups = NULL;
187 iface->getName = NULL;
188 iface->listSource = NULL;
191 iface->externalQuery = FALSE;
192 iface->searchOrder = 0; /* Ignored */
193 iface->startSearch = NULL;
194 iface->stopSearch = NULL;
200 * Build table of of all address book interfaces.
201 * \param addrIndex Address index object.
203 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
204 AddressInterface *iface;
206 /* Create intrinsic XML address book interface */
207 iface = addrindex_create_interface(
208 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
209 TAG_DS_ADDRESS_BOOK );
210 iface->readOnly = FALSE;
211 iface->getModifyFlag = ( void * ) addrbook_get_modified;
212 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
213 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
214 iface->getStatusCode = ( void * ) addrbook_get_status;
215 iface->getReadData = ( void * ) addrbook_read_data;
216 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
217 iface->getListFolder = ( void * ) addrbook_get_list_folder;
218 iface->getListPerson = ( void * ) addrbook_get_list_person;
219 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
220 iface->getName = ( void * ) addrbook_get_name;
221 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
222 iface->searchOrder = 0;
224 /* Add to list of interfaces in address book */
225 addrIndex->interfaceList =
226 g_list_append( addrIndex->interfaceList, iface );
227 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
229 /* Create vCard interface */
230 iface = addrindex_create_interface(
231 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
232 iface->getModifyFlag = ( void * ) vcard_get_modified;
233 iface->getAccessFlag = ( void * ) vcard_get_accessed;
234 iface->getReadFlag = ( void * ) vcard_get_read_flag;
235 iface->getStatusCode = ( void * ) vcard_get_status;
236 iface->getReadData = ( void * ) vcard_read_data;
237 iface->getRootFolder = ( void * ) vcard_get_root_folder;
238 iface->getListFolder = ( void * ) vcard_get_list_folder;
239 iface->getListPerson = ( void * ) vcard_get_list_person;
240 iface->getAllPersons = ( void * ) vcard_get_all_persons;
241 iface->getName = ( void * ) vcard_get_name;
242 iface->setAccessFlag = ( void * ) vcard_set_accessed;
243 iface->searchOrder = 0;
244 addrIndex->interfaceList =
245 g_list_append( addrIndex->interfaceList, iface );
246 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
248 /* Create JPilot interface */
249 iface = addrindex_create_interface(
250 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
253 iface->haveLibrary = jpilot_test_pilot_lib();
254 iface->useInterface = iface->haveLibrary;
255 iface->getModifyFlag = ( void * ) jpilot_get_modified;
256 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
257 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
258 iface->getStatusCode = ( void * ) jpilot_get_status;
259 iface->getReadData = ( void * ) jpilot_read_data;
260 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
261 iface->getListFolder = ( void * ) jpilot_get_list_folder;
262 iface->getListPerson = ( void * ) jpilot_get_list_person;
263 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
264 iface->getName = ( void * ) jpilot_get_name;
265 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
266 iface->searchOrder = 0;
268 iface->useInterface = FALSE;
269 iface->haveLibrary = FALSE;
271 addrIndex->interfaceList =
272 g_list_append( addrIndex->interfaceList, iface );
273 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
275 /* Create LDAP interface */
276 iface = addrindex_create_interface(
277 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
279 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
280 iface->haveLibrary = ldaputil_test_ldap_lib();
281 iface->useInterface = iface->haveLibrary;
282 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
283 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
284 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
285 iface->getStatusCode = ( void * ) ldapsvr_get_status;
286 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
287 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
288 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
289 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
290 iface->getName = ( void * ) ldapsvr_get_name;
291 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
292 iface->externalQuery = TRUE;
293 iface->searchOrder = 1;
295 iface->useInterface = FALSE;
296 iface->haveLibrary = FALSE;
298 addrIndex->interfaceList =
299 g_list_append( addrIndex->interfaceList, iface );
300 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
302 /* Two old legacy data sources (pre 0.7.0) */
303 iface = addrindex_create_interface(
304 ADDR_IF_COMMON, "Old Address - common",
305 TAG_IF_OLD_COMMON, NULL );
306 iface->legacyFlag = TRUE;
307 addrIndex->interfaceList =
308 g_list_append( addrIndex->interfaceList, iface );
309 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
311 iface = addrindex_create_interface(
312 ADDR_IF_COMMON, "Old Address - personal",
313 TAG_IF_OLD_PERSONAL, NULL );
314 iface->legacyFlag = TRUE;
315 addrIndex->interfaceList =
316 g_list_append( addrIndex->interfaceList, iface );
317 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
323 * \param fragment Fragment to free.
325 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
329 node = fragment->children;
331 AddressIfFragment *child = node->data;
332 addrindex_free_fragment( child );
334 node = g_list_next( node );
336 g_list_free( fragment->children );
338 /* Free attributes */
339 node = fragment->attributes;
341 AddressIfAttrib *nv = node->data;
346 node = g_list_next( node );
348 g_list_free( fragment->attributes );
350 g_free( fragment->name );
351 fragment->name = NULL;
352 fragment->attributes = NULL;
353 fragment->children = NULL;
359 * Create a new data source.
360 * \param ifType Interface type to create.
361 * \return Initialized data source.
363 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
364 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
366 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
367 ADDRITEM_ID(ds) = NULL;
368 ADDRITEM_NAME(ds) = NULL;
369 ADDRITEM_PARENT(ds) = NULL;
370 ADDRITEM_SUBTYPE(ds) = 0;
372 ds->rawDataSource = NULL;
373 ds->interface = NULL;
378 * Free up data source.
379 * \param ds Data source to free.
381 void addrindex_free_datasource( AddressDataSource *ds ) {
382 AddressInterface *iface;
384 g_return_if_fail( ds != NULL );
386 iface = ds->interface;
387 if( ds->rawDataSource != NULL ) {
388 if( iface != NULL ) {
389 if( iface->useInterface ) {
390 if( iface->type == ADDR_IF_BOOK ) {
391 AddressBookFile *abf = ds->rawDataSource;
392 addrbook_free_book( abf );
394 else if( iface->type == ADDR_IF_VCARD ) {
395 VCardFile *vcf = ds->rawDataSource;
399 else if( iface->type == ADDR_IF_JPILOT ) {
400 JPilotFile *jpf = ds->rawDataSource;
405 else if( iface->type == ADDR_IF_LDAP ) {
406 LdapServer *server = ds->rawDataSource;
407 ldapsvr_free( server );
414 AddressIfFragment *fragment = ds->rawDataSource;
415 addrindex_free_fragment( fragment );
420 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
421 ADDRITEM_ID(ds) = NULL;
422 ADDRITEM_NAME(ds) = NULL;
423 ADDRITEM_PARENT(ds) = NULL;
424 ADDRITEM_SUBTYPE(ds) = 0;
425 ds->type = ADDR_IF_NONE;
426 ds->interface = NULL;
427 ds->rawDataSource = NULL;
433 * Free up all data sources for specified interface.
434 * \param iface Address interface to process.
436 static void addrindex_free_all_datasources( AddressInterface *iface ) {
437 GList *node = iface->listSource;
439 AddressDataSource *ds = node->data;
440 addrindex_free_datasource( ds );
442 node = g_list_next( node );
447 * Free up specified interface.
448 * \param iface Interface to process.
450 static void addrindex_free_interface( AddressInterface *iface ) {
451 /* Free up data sources */
452 addrindex_free_all_datasources( iface );
453 g_list_free( iface->listSource );
455 /* Free internal storage */
456 g_free( ADDRITEM_ID(iface) );
457 g_free( ADDRITEM_NAME(iface) );
458 g_free( iface->name );
459 g_free( iface->listTag );
460 g_free( iface->itemTag );
462 /* Clear all pointers */
463 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
464 ADDRITEM_ID(iface) = NULL;
465 ADDRITEM_NAME(iface) = NULL;
466 ADDRITEM_PARENT(iface) = NULL;
467 ADDRITEM_SUBTYPE(iface) = 0;
468 iface->type = ADDR_IF_NONE;
470 iface->listTag = NULL;
471 iface->itemTag = NULL;
472 iface->legacyFlag = FALSE;
473 iface->useInterface = FALSE;
474 iface->haveLibrary = FALSE;
475 iface->listSource = NULL;
478 iface->searchOrder = 0;
479 iface->startSearch = NULL;
480 iface->stopSearch = NULL;
486 * Return cache ID for specified data source.
488 * \param addrIndex Address index.
489 * \param ds Data source.
490 * \return ID or NULL if not found. This should be <code>g_free()</code>
493 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
494 gchar *cacheID = NULL;
495 AddrBookBase *adbase;
498 g_return_val_if_fail( addrIndex != NULL, NULL );
499 g_return_val_if_fail( ds != NULL, NULL );
501 adbase = ( AddrBookBase * ) ds->rawDataSource;
503 cache = adbase->addressCache;
505 cacheID = g_strdup( cache->cacheID );
513 * Return reference to data source for specified cacheID.
514 * \param addrIndex Address index.
516 * \return Data source, or NULL if not found.
518 AddressDataSource *addrindex_get_datasource(
519 AddressIndex *addrIndex, const gchar *cacheID )
521 g_return_val_if_fail( addrIndex != NULL, NULL );
522 g_return_val_if_fail( cacheID != NULL, NULL );
523 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
527 * Return reference to address cache for specified cacheID.
528 * \param addrIndex Address index.
530 * \return Address cache, or NULL if not found.
532 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
533 AddressDataSource *ds;
534 AddrBookBase *adbase;
537 g_return_val_if_fail( addrIndex != NULL, NULL );
538 g_return_val_if_fail( cacheID != NULL, NULL );
541 ds = addrindex_get_datasource( addrIndex, cacheID );
543 adbase = ( AddrBookBase * ) ds->rawDataSource;
544 cache = adbase->addressCache;
550 * Add data source into hash table.
551 * \param addrIndex Address index.
552 * \param ds Data source.
554 static void addrindex_hash_add_cache(
555 AddressIndex *addrIndex, AddressDataSource *ds )
559 cacheID = addrindex_get_cache_id( addrIndex, ds );
561 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
566 * Free hash table callback function.
568 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
576 * Free hash table of address cache items.
578 static void addrindex_free_cache_hash( GHashTable *table ) {
579 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
580 g_hash_table_destroy( table );
584 * Remove data source from internal hashtable.
585 * \param addrIndex Address index.
586 * \param ds Data source to remove.
588 static void addrindex_hash_remove_cache(
589 AddressIndex *addrIndex, AddressDataSource *ds )
593 cacheID = addrindex_get_cache_id( addrIndex, ds );
595 g_hash_table_remove( addrIndex->hashCache, cacheID );
602 * Create a new address index. This is created as a singleton object.
603 * \return Initialized address index object.
605 AddressIndex *addrindex_create_index( void ) {
608 if( _addressIndex_ == NULL ) {
609 index = g_new0( AddressIndex, 1 );
610 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
611 ADDRITEM_ID(index) = NULL;
612 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
613 ADDRITEM_PARENT(index) = NULL;
614 ADDRITEM_SUBTYPE(index) = 0;
615 index->filePath = NULL;
616 index->fileName = NULL;
617 index->retVal = MGU_SUCCESS;
618 index->needsConversion = FALSE;
619 index->wasConverted = FALSE;
620 index->conversionError = FALSE;
621 index->interfaceList = NULL;
622 index->lastType = ADDR_IF_NONE;
623 index->dirtyFlag = FALSE;
624 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
625 index->loadedFlag = FALSE;
626 index->searchOrder = NULL;
627 addrindex_build_if_list( index );
628 _addressIndex_ = index;
630 return _addressIndex_;
634 * Return reference to address index.
635 * \return Address index object.
637 AddressIndex *addrindex_get_object( void ) {
638 return _addressIndex_;
642 * Property - Specify file path to address index file.
643 * \param addrIndex Address index.
644 * \param value Path to index file.
646 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
647 g_return_if_fail( addrIndex != NULL );
648 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
652 * Property - Specify file name to address index file.
653 * \param addrIndex Address index.
654 * \param value File name.
656 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
657 g_return_if_fail( addrIndex != NULL );
658 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
662 * Property - Specify file path to be used.
663 * \param addrIndex Address index.
664 * \param value Path to JPilot file.
666 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
667 g_return_if_fail( addrIndex != NULL );
668 addrIndex->dirtyFlag = value;
672 * Property - get loaded flag. Note that this flag is set after reading data
673 * from the address books.
674 * \param addrIndex Address index.
675 * \return <i>TRUE</i> if address index data was loaded.
677 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
678 g_return_val_if_fail( addrIndex != NULL, FALSE );
679 return addrIndex->loadedFlag;
683 * Return list of address interfaces.
684 * \param addrIndex Address index.
685 * \return List of address interfaces.
687 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
688 g_return_val_if_fail( addrIndex != NULL, NULL );
689 return addrIndex->interfaceList;
693 * Perform any other initialization of address index.
695 void addrindex_initialize( void ) {
697 addrcompl_initialize();
701 * Perform any other teardown of address index.
703 void addrindex_teardown( void ) {
704 addrcompl_teardown();
709 * Free up address index.
710 * \param addrIndex Address index.
712 void addrindex_free_index( AddressIndex *addrIndex ) {
715 g_return_if_fail( addrIndex != NULL );
718 g_list_free( addrIndex->searchOrder );
719 addrIndex->searchOrder = NULL;
721 /* Free internal storage */
722 g_free( ADDRITEM_ID(addrIndex) );
723 g_free( ADDRITEM_NAME(addrIndex) );
724 g_free( addrIndex->filePath );
725 g_free( addrIndex->fileName );
728 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
729 ADDRITEM_ID(addrIndex) = NULL;
730 ADDRITEM_NAME(addrIndex) = NULL;
731 ADDRITEM_PARENT(addrIndex) = NULL;
732 ADDRITEM_SUBTYPE(addrIndex) = 0;
733 addrIndex->filePath = NULL;
734 addrIndex->fileName = NULL;
735 addrIndex->retVal = MGU_SUCCESS;
736 addrIndex->needsConversion = FALSE;
737 addrIndex->wasConverted = FALSE;
738 addrIndex->conversionError = FALSE;
739 addrIndex->lastType = ADDR_IF_NONE;
740 addrIndex->dirtyFlag = FALSE;
742 /* Free up interfaces */
743 node = addrIndex->interfaceList;
745 AddressInterface *iface = node->data;
746 addrindex_free_interface( iface );
747 node = g_list_next( node );
749 g_list_free( addrIndex->interfaceList );
750 addrIndex->interfaceList = NULL;
752 /* Free up hash cache */
753 addrindex_free_cache_hash( addrIndex->hashCache );
754 addrIndex->hashCache = NULL;
756 addrIndex->loadedFlag = FALSE;
760 _addressIndex_ = NULL;
764 * Print address index.
765 * \param addrIndex Address index.
766 * \parem stream Stream to print.
768 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
769 g_return_if_fail( addrIndex != NULL );
770 fprintf( stream, "AddressIndex:\n" );
771 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
772 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
773 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
774 fprintf( stream, "\tconverted: '%s'\n",
775 addrIndex->wasConverted ? "yes" : "no" );
776 fprintf( stream, "\tcvt error: '%s'\n",
777 addrIndex->conversionError ? "yes" : "no" );
778 fprintf( stream, "\t---\n" );
782 * Retrieve reference to address interface for specified interface type.
783 * \param addrIndex Address index.
784 * \param ifType Interface type.
785 * \return Address interface, or NULL if not found.
787 AddressInterface *addrindex_get_interface(
788 AddressIndex *addrIndex, AddressIfType ifType )
790 AddressInterface *retVal = NULL;
793 g_return_val_if_fail( addrIndex != NULL, NULL );
795 node = addrIndex->interfaceList;
797 AddressInterface *iface = node->data;
798 node = g_list_next( node );
799 if( iface->type == ifType ) {
808 * Add raw data source to index. The raw data object (an AddressBookFile or
809 * VCardFile object, for example) should be supplied as the raw dataSource
812 * \param addrIndex Address index.
813 * \param ifType Interface type to add.
814 * \param dataSource Actual raw data source to add.
815 * \return Data source added, or NULL if invalid interface type.
817 AddressDataSource *addrindex_index_add_datasource(
818 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
820 AddressInterface *iface;
821 AddressDataSource *ds = NULL;
823 g_return_val_if_fail( addrIndex != NULL, NULL );
824 g_return_val_if_fail( dataSource != NULL, NULL );
826 iface = addrindex_get_interface( addrIndex, ifType );
828 ds = addrindex_create_datasource( ifType );
829 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
831 ds->rawDataSource = dataSource;
832 ds->interface = iface;
833 iface->listSource = g_list_append( iface->listSource, ds );
834 addrIndex->dirtyFlag = TRUE;
836 addrindex_hash_add_cache( addrIndex, ds );
842 * Remove specified data source from index.
843 * \param addrIndex Address index.
844 * \param dataSource Data source to add.
845 * \return Reference to data source if removed, or NULL if data source was not
846 * found in index. Note the this object must still be freed.
848 AddressDataSource *addrindex_index_remove_datasource(
849 AddressIndex *addrIndex, AddressDataSource *dataSource )
851 AddressDataSource *retVal = FALSE;
852 AddressInterface *iface;
854 g_return_val_if_fail( addrIndex != NULL, NULL );
855 g_return_val_if_fail( dataSource != NULL, NULL );
857 iface = addrindex_get_interface( addrIndex, dataSource->type );
859 iface->listSource = g_list_remove( iface->listSource, dataSource );
860 addrIndex->dirtyFlag = TRUE;
861 dataSource->interface = NULL;
863 /* Remove cache from hash table */
864 addrindex_hash_remove_cache( addrIndex, dataSource );
872 * Retrieve a reference to address interface for specified interface type and
873 * XML interface tag name.
874 * \param addrIndex Address index.
875 * \param tag XML interface tag name to match.
876 * \param ifType Interface type to match.
877 * \return Reference to address index, or NULL if not found in index.
879 static AddressInterface *addrindex_tag_get_interface(
880 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
882 AddressInterface *retVal = NULL;
883 GList *node = addrIndex->interfaceList;
886 AddressInterface *iface = node->data;
887 node = g_list_next( node );
889 if( strcmp( iface->listTag, tag ) == 0 ) {
895 if( iface->type == ifType ) {
905 * Retrieve a reference to address interface for specified interface type and
906 * XML datasource tag name.
907 * \param addrIndex Address index.
908 * \param ifType Interface type to match.
909 * \param tag XML datasource tag name to match.
910 * \return Reference to address index, or NULL if not found in index.
912 static AddressInterface *addrindex_tag_get_datasource(
913 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
915 AddressInterface *retVal = NULL;
916 GList *node = addrIndex->interfaceList;
919 AddressInterface *iface = node->data;
920 node = g_list_next( node );
921 if( iface->type == ifType && iface->itemTag ) {
922 if( strcmp( iface->itemTag, tag ) == 0 ) {
931 /* **********************************************************************
932 * Interface XML parsing functions.
933 * ***********************************************************************
937 * Write start of XML element to file.
939 * \param lvl Indentation level.
940 * \param name Element name.
942 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
944 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
950 * Write end of XML element to file.
952 * \param lvl Indentation level.
953 * \param name Element name.
955 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
957 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
964 * Write XML attribute to file.
966 * \param name Attribute name.
967 * \param value Attribute value.
969 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
973 xml_file_put_escape_str( fp, value );
978 * Return DOM fragment for current XML tag from file.
979 * \param file XML file being processed.
980 * \return Fragment representing DOM fragment for configuration element.
982 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
983 AddressIfFragment *fragment;
984 AddressIfFragment *child;
994 /* printf( "addrindex_read_fragment\n" ); */
996 prevLevel = file->level;
998 /* Get current tag name */
999 xtag = xml_get_current_tag( file );
1001 /* Create new fragment */
1002 fragment = g_new0( AddressIfFragment, 1 );
1003 fragment->name = g_strdup( xtag->tag );
1004 fragment->children = NULL;
1005 fragment->attributes = NULL;
1007 /* Read attributes */
1009 attr = xml_get_current_tag_attr( file );
1011 name = ((XMLAttr *)attr->data)->name;
1012 value = ((XMLAttr *)attr->data)->value;
1013 nv = g_new0( AddressIfAttrib, 1 );
1014 nv->name = g_strdup( name );
1015 nv->value = g_strdup( value );
1016 list = g_list_append( list, nv );
1017 attr = g_list_next( attr );
1019 fragment->attributes = list;
1021 /* Now read the children */
1023 rc = xml_parse_next_tag( file );
1028 if( file->level < prevLevel ) {
1029 /* We must be above level we start at */
1032 child = addrindex_read_fragment( file );
1033 fragment->children = g_list_append( fragment->children, child );
1040 * Write DOM fragment to file.
1041 * \param fp File to write.
1042 * \param fragment DOM fragment for configuration element.
1043 * \param lvl Indent level.
1045 static void addrindex_write_fragment(
1046 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1051 addrindex_write_elem_s( fp, lvl, fragment->name );
1052 node = fragment->attributes;
1054 AddressIfAttrib *nv = node->data;
1055 addrindex_write_attr( fp, nv->name, nv->value );
1056 node = g_list_next( node );
1058 if( fragment->children ) {
1061 /* Output children */
1062 node = fragment->children;
1064 AddressIfFragment *child = node->data;
1065 addrindex_write_fragment( fp, child, 1+lvl );
1066 node = g_list_next( node );
1069 /* Output closing tag */
1070 addrindex_write_elem_e( fp, lvl, fragment->name );
1079 * Read/parse address index file, creating a data source for a regular
1080 * intrinsic XML addressbook.
1081 * \param file Address index file.
1082 * \return Data source.
1084 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1085 AddressDataSource *ds;
1086 AddressBookFile *abf;
1089 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1090 abf = addrbook_create_book();
1091 attr = xml_get_current_tag_attr( file );
1093 gchar *name = ((XMLAttr *)attr->data)->name;
1094 gchar *value = ((XMLAttr *)attr->data)->value;
1095 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1096 addrbook_set_name( abf, value );
1098 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1099 addrbook_set_file( abf, value );
1101 attr = g_list_next( attr );
1103 ds->rawDataSource = abf;
1107 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1108 AddressBookFile *abf = ds->rawDataSource;
1110 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1111 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1112 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1113 fputs( " />\n", fp );
1117 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1118 AddressDataSource *ds;
1122 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1123 vcf = vcard_create();
1124 attr = xml_get_current_tag_attr( file );
1126 gchar *name = ((XMLAttr *)attr->data)->name;
1127 gchar *value = ((XMLAttr *)attr->data)->value;
1128 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1129 vcard_set_name( vcf, value );
1131 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1132 vcard_set_file( vcf, value );
1134 attr = g_list_next( attr );
1136 ds->rawDataSource = vcf;
1140 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1141 VCardFile *vcf = ds->rawDataSource;
1143 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1144 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1145 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1146 fputs( " />\n", fp );
1151 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1152 AddressDataSource *ds;
1156 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1157 jpf = jpilot_create();
1158 attr = xml_get_current_tag_attr( file );
1160 gchar *name = ((XMLAttr *)attr->data)->name;
1161 gchar *value = ((XMLAttr *)attr->data)->value;
1162 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1163 jpilot_set_name( jpf, value );
1165 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1166 jpilot_set_file( jpf, value );
1168 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1169 jpilot_add_custom_label( jpf, value );
1171 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1172 jpilot_add_custom_label( jpf, value );
1174 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1175 jpilot_add_custom_label( jpf, value );
1177 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1178 jpilot_add_custom_label( jpf, value );
1180 attr = g_list_next( attr );
1182 ds->rawDataSource = jpf;
1186 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1187 JPilotFile *jpf = ds->rawDataSource;
1191 GList *customLbl = jpilot_get_custom_labels( jpf );
1192 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1193 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1194 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1199 g_snprintf( name, sizeof(name), "%s%d",
1200 ATTAG_JPILOT_CUSTOM, ind );
1201 addrindex_write_attr( fp, name, node->data );
1203 node = g_list_next( node );
1205 fputs( " />\n", fp );
1211 * Just read/write DOM fragments (preserve data found in file).
1213 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1214 AddressDataSource *ds;
1216 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1217 ds->rawDataSource = addrindex_read_fragment( file );
1221 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1222 AddressIfFragment *fragment = ds->rawDataSource;
1224 addrindex_write_fragment( fp, fragment, lvl );
1231 * Parse LDAP criteria attribute data from XML file.
1232 * \param file Index file.
1233 * \param ctl LDAP control object to populate.
1235 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1244 if( file == NULL ) {
1249 prevLevel = file->level;
1250 xtagPrev = xml_get_current_tag( file );
1252 rc = xml_parse_next_tag( file );
1254 /* Terminate prematurely */
1255 mgu_free_dlist( list );
1259 if( file->level < prevLevel ) {
1260 /* We must be above level we start at */
1264 /* Get a tag (element) */
1265 xtag = xml_get_current_tag( file );
1266 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1267 /* LDAP criteria attribute */
1268 attr = xml_get_current_tag_attr( file );
1270 gchar *name = ((XMLAttr *)attr->data)->name;
1271 gchar *value = ((XMLAttr *)attr->data)->value;
1272 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1273 if( value && strlen( value ) > 0 ) {
1274 list = g_list_append(
1275 list, g_strdup( value ) );
1278 attr = g_list_next( attr );
1282 if( xtag != xtagPrev ) {
1283 /* Found a new tag */
1290 /* Build list of search attributes */
1291 ldapctl_criteria_list_clear( ctl );
1294 ldapctl_criteria_list_add( ctl, node->data );
1295 g_free( node->data );
1297 node = g_list_next( node );
1299 g_list_free( list );
1304 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1306 * Parse LDAP control data from XML file.
1307 * \param file Index file.
1308 * \return Initialized data soruce object.
1310 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1311 AddressDataSource *ds;
1315 gchar *serverName = NULL;
1316 gchar *criteria = NULL;
1317 gboolean bDynSearch;
1321 /* printf( "addrindex_parse_ldap\n" ); */
1322 /* Set up some defaults */
1325 iMatch = LDAPCTL_MATCH_BEGINWITH;
1327 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1328 ctl = ldapctl_create();
1329 attr = xml_get_current_tag_attr( file );
1331 gchar *name = ((XMLAttr *)attr->data)->name;
1332 gchar *value = ((XMLAttr *)attr->data)->value;
1333 gint ivalue = atoi( value );
1335 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1336 if( serverName ) g_free( serverName );
1337 serverName = g_strdup( value );
1339 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1340 ldapctl_set_host( ctl, value );
1342 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1343 ldapctl_set_port( ctl, ivalue );
1345 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1346 ldapctl_set_base_dn( ctl, value );
1348 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1349 ldapctl_set_bind_dn( ctl, value );
1351 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1352 ldapctl_set_bind_password( ctl, value );
1354 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1355 if( criteria ) g_free( criteria );
1356 criteria = g_strdup( value );
1358 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1359 ldapctl_set_max_entries( ctl, ivalue );
1361 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1362 ldapctl_set_timeout( ctl, ivalue );
1364 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1365 ldapctl_set_max_query_age( ctl, ivalue );
1367 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1369 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1373 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1374 iMatch = LDAPCTL_MATCH_BEGINWITH;
1375 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1376 iMatch = LDAPCTL_MATCH_CONTAINS;
1379 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1381 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1385 attr = g_list_next( attr );
1388 server = ldapsvr_create_noctl();
1389 ldapsvr_set_name( server, serverName );
1390 ldapsvr_set_search_flag( server, bDynSearch );
1391 ldapctl_set_matching_option( ctl, iMatch );
1392 ldapctl_set_tls( ctl, bTLS );
1393 g_free( serverName );
1394 ldapsvr_set_control( server, ctl );
1395 ds->rawDataSource = server;
1397 addrindex_parse_ldap_attrlist( file, ctl );
1399 * If criteria have been specified and no attributes were listed, then
1400 * convert old style criteria into an attribute list. Any criteria will
1401 * be dropped when saving data.
1404 if( ! ldapctl_get_criteria_list( ctl ) ) {
1405 ldapctl_parse_ldap_search( ctl, criteria );
1409 /* ldapsvr_print_data( server, stdout ); */
1414 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1415 LdapServer *server = ds->rawDataSource;
1416 LdapControl *ctl = NULL;
1421 ctl = server->control;
1423 if( ctl == NULL ) return;
1425 /* Output start element with attributes */
1426 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1427 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1428 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1430 sprintf( value, "%d", ctl->port );
1431 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1433 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1434 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1435 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1437 sprintf( value, "%d", ctl->maxEntries );
1438 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1439 sprintf( value, "%d", ctl->timeOut );
1440 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1441 sprintf( value, "%d", ctl->maxQueryAge );
1442 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1444 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1445 server->searchFlag ?
1446 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1448 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1449 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1450 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1452 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1454 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1458 /* Output attributes */
1459 node = ldapctl_get_criteria_list( ctl );
1461 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1462 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1464 node = g_list_next( node );
1467 /* End of element */
1468 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1473 * Just read/write DOM fragments (preserve data found in file).
1475 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1476 AddressDataSource *ds;
1478 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1479 ds->rawDataSource = addrindex_read_fragment( file );
1483 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1484 AddressIfFragment *fragment = ds->rawDataSource;
1486 addrindex_write_fragment( fp, fragment, lvl );
1491 /* **********************************************************************
1492 * Address index I/O functions.
1493 * ***********************************************************************
1496 * Read address index file, creating appropriate data sources for each address
1499 * \param addrIndex Address index.
1500 * \param file Address index file.
1502 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1505 AddressInterface *iface = NULL, *dsIFace = NULL;
1506 AddressDataSource *ds;
1509 addrIndex->loadedFlag = FALSE;
1511 prev_level = file->level;
1512 rc = xml_parse_next_tag( file );
1513 if( file->level == 0 ) return;
1515 xtag = xml_get_current_tag( file );
1517 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1519 addrIndex->lastType = iface->type;
1520 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1523 dsIFace = addrindex_tag_get_datasource(
1524 addrIndex, addrIndex->lastType, xtag->tag );
1526 /* Add data source to list */
1528 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1529 ds = addrindex_parse_book( file );
1530 if( ds->rawDataSource ) {
1531 addrbook_set_path( ds->rawDataSource,
1532 addrIndex->filePath );
1535 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1536 ds = addrindex_parse_vcard( file );
1538 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1539 ds = addrindex_parse_jpilot( file );
1541 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1542 ds = addrindex_parse_ldap( file );
1545 ds->interface = dsIFace;
1546 addrindex_hash_add_cache( addrIndex, ds );
1547 dsIFace->listSource =
1548 g_list_append( dsIFace->listSource, ds );
1556 * Search order sorting comparison function for building search order list.
1558 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1559 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1560 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1562 return ifaceA->searchOrder - ifaceB->searchOrder;
1566 * Build list of data sources to process.
1567 * \param addrIndex Address index object.
1569 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1572 /* Clear existing list */
1573 g_list_free( addrIndex->searchOrder );
1574 addrIndex->searchOrder = NULL;
1576 /* Build new list */
1577 nodeIf = addrIndex->interfaceList;
1579 AddressInterface *iface = nodeIf->data;
1580 if( iface->useInterface ) {
1581 if( iface->searchOrder > 0 ) {
1582 /* Add to search order list */
1583 addrIndex->searchOrder = g_list_insert_sorted(
1584 addrIndex->searchOrder, iface,
1585 addrindex_search_order_compare );
1588 nodeIf = g_list_next( nodeIf );
1592 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1593 XMLFile *file = NULL;
1594 gchar *fileSpec = NULL;
1596 g_return_val_if_fail( addrIndex != NULL, -1 );
1598 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1599 addrIndex->retVal = MGU_NO_FILE;
1600 file = xml_open_file( fileSpec );
1603 if( file == NULL ) {
1605 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1607 return addrIndex->retVal;
1610 addrIndex->retVal = MGU_BAD_FORMAT;
1611 if( xml_get_dtd( file ) == 0 ) {
1612 if( xml_parse_next_tag( file ) == 0 ) {
1613 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1614 addrindex_read_index( addrIndex, file );
1615 addrIndex->retVal = MGU_SUCCESS;
1619 xml_close_file( file );
1621 addrindex_build_search_order( addrIndex );
1623 return addrIndex->retVal;
1626 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1627 GList *nodeIF, *nodeDS;
1629 gint lvlItem = 1 + lvlList;
1631 nodeIF = addrIndex->interfaceList;
1633 AddressInterface *iface = nodeIF->data;
1634 if( ! iface->legacyFlag ) {
1635 nodeDS = iface->listSource;
1636 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1639 AddressDataSource *ds = nodeDS->data;
1641 if( iface->type == ADDR_IF_BOOK ) {
1642 addrindex_write_book( fp, ds, lvlItem );
1644 if( iface->type == ADDR_IF_VCARD ) {
1645 addrindex_write_vcard( fp, ds, lvlItem );
1647 if( iface->type == ADDR_IF_JPILOT ) {
1648 addrindex_write_jpilot( fp, ds, lvlItem );
1650 if( iface->type == ADDR_IF_LDAP ) {
1651 addrindex_write_ldap( fp, ds, lvlItem );
1654 nodeDS = g_list_next( nodeDS );
1656 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1658 nodeIF = g_list_next( nodeIF );
1663 * Write data to specified file.
1664 * Enter: addrIndex Address index object.
1665 * newFile New file name.
1666 * return: Status code, from addrIndex->retVal.
1667 * Note: File will be created in directory specified by addrIndex.
1669 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1672 #ifndef DEV_STANDALONE
1676 g_return_val_if_fail( addrIndex != NULL, -1 );
1678 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1679 addrIndex->retVal = MGU_OPEN_FILE;
1680 #ifdef DEV_STANDALONE
1681 fp = g_fopen( fileSpec, "wb" );
1684 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1686 pfile = prefs_write_open( fileSpec );
1690 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1692 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1695 addrindex_write_index( addrIndex, fp );
1696 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1698 addrIndex->retVal = MGU_SUCCESS;
1699 #ifdef DEV_STANDALONE
1702 if( prefs_file_close( pfile ) < 0 ) {
1703 addrIndex->retVal = MGU_ERROR_WRITE;
1709 return addrIndex->retVal;
1713 * Save address index data to original file.
1714 * return: Status code, from addrIndex->retVal.
1716 gint addrindex_save_data( AddressIndex *addrIndex ) {
1717 g_return_val_if_fail( addrIndex != NULL, -1 );
1719 addrIndex->retVal = MGU_NO_FILE;
1720 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1721 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1723 addrindex_write_to( addrIndex, addrIndex->fileName );
1724 if( addrIndex->retVal == MGU_SUCCESS ) {
1725 addrIndex->dirtyFlag = FALSE;
1727 return addrIndex->retVal;
1731 * Save all address book files which may have changed.
1732 * Return: Status code, set if there was a problem saving data.
1734 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1735 gint retVal = MGU_SUCCESS;
1736 GList *nodeIf, *nodeDS;
1738 nodeIf = addrIndex->interfaceList;
1740 AddressInterface *iface = nodeIf->data;
1741 if( iface->type == ADDR_IF_BOOK ) {
1742 nodeDS = iface->listSource;
1744 AddressDataSource *ds = nodeDS->data;
1745 AddressBookFile *abf = ds->rawDataSource;
1746 if( addrbook_get_dirty( abf ) ) {
1747 if( addrbook_get_read_flag( abf ) ) {
1748 addrbook_save_data( abf );
1749 if( abf->retVal != MGU_SUCCESS ) {
1750 retVal = abf->retVal;
1754 nodeDS = g_list_next( nodeDS );
1758 nodeIf = g_list_next( nodeIf );
1764 /* **********************************************************************
1765 * Address book conversion to new format.
1766 * ***********************************************************************
1769 #define ELTAG_IF_OLD_FOLDER "folder"
1770 #define ELTAG_IF_OLD_GROUP "group"
1771 #define ELTAG_IF_OLD_ITEM "item"
1772 #define ELTAG_IF_OLD_NAME "name"
1773 #define ELTAG_IF_OLD_ADDRESS "address"
1774 #define ELTAG_IF_OLD_REMARKS "remarks"
1775 #define ATTAG_IF_OLD_NAME "name"
1777 #define TEMPNODE_ROOT 0
1778 #define TEMPNODE_FOLDER 1
1779 #define TEMPNODE_GROUP 2
1780 #define TEMPNODE_ADDRESS 3
1782 typedef struct _AddressCvt_Node AddressCvtNode;
1783 struct _AddressCvt_Node {
1792 * Parse current address item.
1794 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1799 nn = g_new0( AddressCvtNode, 1 );
1800 nn->type = TEMPNODE_ADDRESS;
1803 level = file->level;
1806 xml_parse_next_tag(file);
1807 if (file->level < level) return nn;
1809 element = xml_get_element( file );
1810 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1811 nn->name = g_strdup( element );
1813 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1814 nn->address = g_strdup( element );
1816 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1817 nn->remarks = g_strdup( element );
1820 xml_parse_next_tag(file);
1825 * Create a temporary node below specified node.
1827 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1829 nn = g_new0( AddressCvtNode, 1 );
1831 nn->name = g_strdup( name );
1832 nn->remarks = g_strdup( rem );
1833 node->list = g_list_append( node->list, nn );
1838 * Process current temporary node.
1840 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1843 AddressCvtNode *newNode = NULL;
1848 prev_level = file->level;
1849 xml_parse_next_tag( file );
1850 if (file->level < prev_level) return;
1854 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1855 attr = xml_get_current_tag_attr(file);
1857 name = ((XMLAttr *)attr->data)->name;
1858 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1859 value = ((XMLAttr *)attr->data)->value;
1862 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1863 addrindex_add_obj( file, newNode );
1866 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1867 attr = xml_get_current_tag_attr(file);
1869 name = ((XMLAttr *)attr->data)->name;
1870 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1871 value = ((XMLAttr *)attr->data)->value;
1874 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1875 addrindex_add_obj( file, newNode );
1877 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1878 newNode = addrindex_parse_item( file );
1879 node->list = g_list_append( node->list, newNode );
1882 /* printf( "invalid: !!! \n" ); */
1883 attr = xml_get_current_tag_attr( file );
1889 * Consume all nodes below current tag.
1891 static void addrindex_consume_tree( XMLFile *file ) {
1898 prev_level = file->level;
1899 xml_parse_next_tag( file );
1900 if (file->level < prev_level) return;
1902 xtag = xml_get_current_tag( file );
1903 /* printf( "tag : %s\n", xtag->tag ); */
1904 element = xml_get_element( file );
1905 attr = xml_get_current_tag_attr( file );
1906 /* show_attribs( attr ); */
1907 /* printf( "\ttag value : %s :\n", element ); */
1908 addrindex_consume_tree( file );
1913 * Print temporary tree.
1915 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1918 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1919 fprintf( stream, "\tname :%s:\n", node->name );
1920 fprintf( stream, "\taddr :%s:\n", node->address );
1921 fprintf( stream, "\trems :%s:\n", node->remarks );
1923 fprintf( stream, "\t--list----\n" );
1927 AddressCvtNode *lNode = list->data;
1928 list = g_list_next( list );
1929 addrindex_print_node( lNode, stream );
1931 fprintf( stream, "\t==list-%d==\n", node->type );
1935 * Free up temporary tree.
1937 static void addrindex_free_node( AddressCvtNode *node ) {
1938 GList *list = node->list;
1941 AddressCvtNode *lNode = list->data;
1942 list = g_list_next( list );
1943 addrindex_free_node( lNode );
1945 node->type = TEMPNODE_ROOT;
1946 g_free( node->name );
1947 g_free( node->address );
1948 g_free( node->remarks );
1949 g_list_free( node->list );
1954 * Process address book for specified node.
1956 static void addrindex_process_node(
1957 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1958 ItemGroup *parentGrp, ItemFolder *folderGrp )
1961 ItemFolder *itemFolder = NULL;
1962 ItemGroup *itemGParent = parentGrp;
1963 ItemFolder *itemGFolder = folderGrp;
1964 AddressCache *cache = abf->addressCache;
1966 if( node->type == TEMPNODE_ROOT ) {
1967 itemFolder = parent;
1969 else if( node->type == TEMPNODE_FOLDER ) {
1970 itemFolder = addritem_create_item_folder();
1971 addritem_folder_set_name( itemFolder, node->name );
1972 addrcache_id_folder( cache, itemFolder );
1973 addrcache_folder_add_folder( cache, parent, itemFolder );
1976 else if( node->type == TEMPNODE_GROUP ) {
1977 ItemGroup *itemGroup;
1980 /* Create a folder for group */
1981 fName = g_strdup_printf( "Cvt - %s", node->name );
1982 itemGFolder = addritem_create_item_folder();
1983 addritem_folder_set_name( itemGFolder, fName );
1984 addrcache_id_folder( cache, itemGFolder );
1985 addrcache_folder_add_folder( cache, parent, itemGFolder );
1988 /* Add group into folder */
1989 itemGroup = addritem_create_item_group();
1990 addritem_group_set_name( itemGroup, node->name );
1991 addrcache_id_group( cache, itemGroup );
1992 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1993 itemGParent = itemGroup;
1995 else if( node->type == TEMPNODE_ADDRESS ) {
1996 ItemPerson *itemPerson;
1997 ItemEMail *itemEMail;
1999 /* Create person and email objects */
2000 itemPerson = addritem_create_item_person();
2001 addritem_person_set_common_name( itemPerson, node->name );
2002 addrcache_id_person( cache, itemPerson );
2003 itemEMail = addritem_create_item_email();
2004 addritem_email_set_address( itemEMail, node->address );
2005 addritem_email_set_remarks( itemEMail, node->remarks );
2006 addrcache_id_email( cache, itemEMail );
2007 addrcache_person_add_email( cache, itemPerson, itemEMail );
2009 /* Add person into appropriate folder */
2011 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2014 addrcache_folder_add_person( cache, parent, itemPerson );
2017 /* Add email address only into group */
2019 addrcache_group_add_email( cache, parentGrp, itemEMail );
2025 AddressCvtNode *lNode = list->data;
2026 list = g_list_next( list );
2027 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2032 * Process address book to specified file number.
2034 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2035 gboolean retVal = FALSE;
2036 AddressBookFile *abf = NULL;
2037 AddressCvtNode *rootNode = NULL;
2038 gchar *newFile = NULL;
2039 GList *fileList = NULL;
2042 /* Setup root node */
2043 rootNode = g_new0( AddressCvtNode, 1 );
2044 rootNode->type = TEMPNODE_ROOT;
2045 rootNode->name = g_strdup( "root" );
2046 rootNode->list = NULL;
2047 addrindex_add_obj( file, rootNode );
2048 /* addrindex_print_node( rootNode, stdout ); */
2050 /* Create new address book */
2051 abf = addrbook_create_book();
2052 addrbook_set_name( abf, displayName );
2053 addrbook_set_path( abf, addrIndex->filePath );
2055 /* Determine next available file number */
2056 fileList = addrbook_get_bookfile_list( abf );
2058 fileNum = 1 + abf->maxValue;
2060 g_list_free( fileList );
2063 newFile = addrbook_gen_new_file_name( fileNum );
2065 addrbook_set_file( abf, newFile );
2068 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2070 /* addrbook_dump_book( abf, stdout ); */
2071 addrbook_save_data( abf );
2072 addrIndex->retVal = abf->retVal;
2073 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2075 addrbook_free_book( abf );
2077 addrindex_free_node( rootNode );
2080 /* Create entries in address index */
2082 abf = addrbook_create_book();
2083 addrbook_set_name( abf, displayName );
2084 addrbook_set_path( abf, addrIndex->filePath );
2085 addrbook_set_file( abf, newFile );
2086 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2093 * Process tree converting data.
2095 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2103 prev_level = file->level;
2104 xml_parse_next_tag( file );
2105 if (file->level < prev_level) return;
2107 xtag = xml_get_current_tag( file );
2108 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2109 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2110 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2111 addrIndex->needsConversion = FALSE;
2112 addrIndex->wasConverted = TRUE;
2117 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2118 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2119 addrIndex->needsConversion = FALSE;
2120 addrIndex->wasConverted = TRUE;
2125 element = xml_get_element( file );
2126 attr = xml_get_current_tag_attr( file );
2127 /* show_attribs( attr ); */
2128 /* printf( "\ttag value : %s :\n", element ); */
2129 addrindex_consume_tree( file );
2133 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2134 XMLFile *file = NULL;
2137 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2138 addrIndex->retVal = MGU_NO_FILE;
2139 file = xml_open_file( fileSpec );
2142 if( file == NULL ) {
2143 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2144 return addrIndex->retVal;
2147 addrIndex->retVal = MGU_BAD_FORMAT;
2148 if( xml_get_dtd( file ) == 0 ) {
2149 if( xml_parse_next_tag( file ) == 0 ) {
2150 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2151 addrindex_convert_tree( addrIndex, file );
2155 xml_close_file( file );
2156 return addrIndex->retVal;
2160 * Create a new address book file.
2162 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2163 gboolean retVal = FALSE;
2164 AddressBookFile *abf = NULL;
2165 gchar *newFile = NULL;
2166 GList *fileList = NULL;
2169 /* Create new address book */
2170 abf = addrbook_create_book();
2171 addrbook_set_name( abf, displayName );
2172 addrbook_set_path( abf, addrIndex->filePath );
2174 /* Determine next available file number */
2175 fileList = addrbook_get_bookfile_list( abf );
2177 fileNum = 1 + abf->maxValue;
2179 g_list_free( fileList );
2182 newFile = addrbook_gen_new_file_name( fileNum );
2184 addrbook_set_file( abf, newFile );
2187 addrbook_save_data( abf );
2188 addrIndex->retVal = abf->retVal;
2189 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2190 addrbook_free_book( abf );
2193 /* Create entries in address index */
2195 abf = addrbook_create_book();
2196 addrbook_set_name( abf, displayName );
2197 addrbook_set_path( abf, addrIndex->filePath );
2198 addrbook_set_file( abf, newFile );
2199 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2206 * Read data for address index performing a conversion if necesary.
2207 * Enter: addrIndex Address index object.
2208 * return: Status code, from addrIndex->retVal.
2209 * Note: New address book files will be created in directory specified by
2210 * addrIndex. Three files will be created, for the following:
2211 * "Common addresses"
2212 * "Personal addresses"
2213 * "Gathered addresses" - a new address book.
2215 gint addrindex_read_data( AddressIndex *addrIndex ) {
2216 g_return_val_if_fail( addrIndex != NULL, -1 );
2218 addrIndex->conversionError = FALSE;
2219 addrindex_read_file( addrIndex );
2220 if( addrIndex->retVal == MGU_SUCCESS ) {
2221 if( addrIndex->needsConversion ) {
2222 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2223 addrIndex->conversionError = TRUE;
2226 addrIndex->conversionError = TRUE;
2229 addrIndex->dirtyFlag = TRUE;
2231 return addrIndex->retVal;
2235 * Create new address books for a new address index.
2236 * Enter: addrIndex Address index object.
2237 * return: Status code, from addrIndex->retVal.
2238 * Note: New address book files will be created in directory specified by
2239 * addrIndex. Three files will be created, for the following:
2240 * "Common addresses"
2241 * "Personal addresses"
2242 * "Gathered addresses" - a new address book.
2244 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2247 g_return_val_if_fail( addrIndex != NULL, -1 );
2249 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2251 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2252 addrIndex->dirtyFlag = TRUE;
2254 return addrIndex->retVal;
2257 /* **********************************************************************
2258 * New interface stuff.
2259 * ***********************************************************************
2263 * Return modified flag for specified data source.
2265 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2266 gboolean retVal = FALSE;
2267 AddressInterface *iface;
2269 if( ds == NULL ) return retVal;
2270 iface = ds->interface;
2271 if( iface == NULL ) return retVal;
2272 if( iface->getModifyFlag ) {
2273 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2279 * Return accessed flag for specified data source.
2281 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2282 gboolean retVal = FALSE;
2283 AddressInterface *iface;
2285 if( ds == NULL ) return retVal;
2286 iface = ds->interface;
2287 if( iface == NULL ) return retVal;
2288 if( iface->getAccessFlag ) {
2289 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2295 * Return data read flag for specified data source.
2297 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2298 gboolean retVal = TRUE;
2299 AddressInterface *iface;
2301 if( ds == NULL ) return retVal;
2302 iface = ds->interface;
2303 if( iface == NULL ) return retVal;
2304 if( iface->getReadFlag ) {
2305 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2311 * Return status code for specified data source.
2313 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2314 gint retVal = MGU_SUCCESS;
2315 AddressInterface *iface;
2317 if( ds == NULL ) return retVal;
2318 iface = ds->interface;
2319 if( iface == NULL ) return retVal;
2320 if( iface->getStatusCode ) {
2321 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2327 * Return data read flag for specified data source.
2329 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2330 gint retVal = MGU_SUCCESS;
2331 AddressInterface *iface;
2333 if( ds == NULL ) return retVal;
2334 iface = ds->interface;
2335 if( iface == NULL ) return retVal;
2336 if( iface->getReadData ) {
2338 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2339 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2341 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2347 * Return data read flag for specified data source.
2349 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2350 ItemFolder *retVal = NULL;
2351 AddressInterface *iface;
2353 if( ds == NULL ) return retVal;
2354 iface = ds->interface;
2355 if( iface == NULL ) return retVal;
2356 if( iface->getRootFolder ) {
2357 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2363 * Return list of folders for specified data source.
2365 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2366 GList *retVal = FALSE;
2367 AddressInterface *iface;
2369 if( ds == NULL ) return retVal;
2370 iface = ds->interface;
2371 if( iface == NULL ) return retVal;
2372 if( iface->getListFolder ) {
2373 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2379 * Return list of persons in root folder for specified data source.
2381 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2382 GList *retVal = FALSE;
2383 AddressInterface *iface;
2385 if( ds == NULL ) return retVal;
2386 iface = ds->interface;
2387 if( iface == NULL ) return retVal;
2388 if( iface->getListPerson ) {
2389 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2395 * Return name for specified data source.
2397 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2398 gchar *retVal = FALSE;
2399 AddressInterface *iface;
2401 if( ds == NULL ) return retVal;
2402 iface = ds->interface;
2403 if( iface == NULL ) return retVal;
2404 if( iface->getName ) {
2405 retVal = ( iface->getName ) ( ds->rawDataSource );
2411 * Set the access flag inside the data source.
2413 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2414 AddressInterface *iface;
2416 if( ds == NULL ) return;
2417 iface = ds->interface;
2418 if( iface == NULL ) return;
2419 if( iface->setAccessFlag ) {
2420 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2425 * Return read only flag for specified data source.
2427 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2428 AddressInterface *iface;
2429 if( ds == NULL ) return TRUE;
2430 iface = ds->interface;
2431 if( iface == NULL ) return TRUE;
2432 return iface->readOnly;
2436 * Return list of all persons for specified data source.
2438 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2439 GList *retVal = NULL;
2440 AddressInterface *iface;
2442 if( ds == NULL ) return retVal;
2443 iface = ds->interface;
2444 if( iface == NULL ) return retVal;
2445 if( iface->getAllPersons ) {
2446 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2452 * Return list of all groups for specified data source.
2454 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2455 GList *retVal = NULL;
2456 AddressInterface *iface;
2458 if( ds == NULL ) return retVal;
2459 iface = ds->interface;
2460 if( iface == NULL ) return retVal;
2461 if( iface->getAllGroups ) {
2462 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2467 /* **********************************************************************
2468 * Address search stuff.
2469 * ***********************************************************************
2473 * Setup or register the dynamic search that will be performed. The search
2474 * is registered with the query manager.
2476 * \param searchTerm Search term. A private copy will be made.
2477 * \param callBackEntry Callback function that should be called when
2478 * each entry is received.
2479 * \param callBackEnd Callback function that should be called when
2480 * search has finished running.
2481 * \return ID allocated to query that will be executed.
2483 gint addrindex_setup_search(
2484 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2489 /* Set up a dynamic address query */
2490 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2491 queryID = req->queryID;
2492 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2494 /* printf( "***> query ID ::%d::\n", queryID ); */
2501 * Function prototypes (not in header file or circular reference errors are
2504 LdapQuery *ldapsvr_new_dynamic_search(
2505 LdapServer *server, QueryRequest *req );
2506 LdapQuery *ldapsvr_new_explicit_search(
2507 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2508 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2513 * Execute the previously registered dynamic search.
2515 * \param req Address query object to execute.
2516 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2519 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2520 AddressInterface *iface;
2521 AddressDataSource *ds;
2526 /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2527 nodeIf = _addressIndex_->searchOrder;
2529 iface = nodeIf->data;
2530 nodeIf = g_list_next( nodeIf );
2532 if( ! iface->useInterface ) {
2535 if( ! iface->externalQuery ) {
2540 nodeDS = iface->listSource;
2543 nodeDS = g_list_next( nodeDS );
2545 if( type == ADDR_IF_LDAP ) {
2549 server = ds->rawDataSource;
2550 if( ! server->searchFlag ) {
2553 if( ldapsvr_reuse_previous( server, req ) ) {
2557 /* Start a new dynamic search */
2558 qry = ldapsvr_new_dynamic_search( server, req );
2560 ldapsvr_execute_query( server, qry );
2570 * Stop the previously registered search.
2572 * \param queryID ID of search query to stop.
2574 void addrindex_stop_search( const gint queryID ){
2576 AddrQueryObject *aqo;
2579 /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
2580 /* If query ID does not match, search has not been setup */
2581 req = qrymgr_find_request( queryID );
2586 /* Stop all queries that were associated with request */
2587 node = req->queryList;
2591 if( aqo->queryType == ADDRQUERY_LDAP ) {
2592 LdapQuery *qry = ( LdapQuery * ) aqo;
2593 ldapqry_set_stop_flag( qry, TRUE );
2597 node = g_list_next( node );
2600 /* Delete query request */
2601 qrymgr_delete_request( queryID );
2605 * Setup or register the explicit search that will be performed. The search is
2606 * registered with the query manager.
2608 * \param ds Data source to search.
2609 * \param searchTerm Search term to locate.
2610 * \param folder Folder to receive search results; may be NULL.
2611 * \param callbackEnd Function to call when search has terminated.
2612 * \param callbackEntry Function to called for each entry processed.
2613 * \return ID allocated to query that will be executed.
2615 gint addrindex_setup_explicit_search(
2616 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2617 void *callBackEnd, void *callBackEntry )
2624 /* Name the query */
2625 name = g_strdup_printf( "Search '%s'", searchTerm );
2627 /* Set up query request */
2628 if (!strcmp(searchTerm, "*"))
2629 mySearch = g_strdup("*@");
2631 mySearch = g_strdup(searchTerm);
2633 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2637 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2638 queryID = req->queryID;
2640 if( ds->type == ADDR_IF_LDAP ) {
2644 server = ds->rawDataSource;
2645 ldapsvr_new_explicit_search( server, req, folder );
2649 qrymgr_delete_request( queryID );
2658 * Execute the previously registered explicit search.
2660 * \param req Address query request object to execute.
2661 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2664 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2666 AddrQueryObject *aqo;
2670 /* Note: there should only be one query in the list. */
2671 aqo = req->queryList->data;
2673 if( aqo->queryType == ADDRQUERY_LDAP ) {
2677 qry = ( LdapQuery * ) aqo;
2678 server = qry->server;
2680 /* Start the search */
2682 ldapsvr_execute_query( server, qry );
2689 * Start the previously registered search.
2691 * \param queryID ID of search query to be executed.
2692 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2695 gboolean addrindex_start_search( const gint queryID ) {
2698 AddrSearchType searchType;
2701 /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
2702 req = qrymgr_find_request( queryID );
2707 searchType = req->searchType;
2708 if( searchType == ADDRSEARCH_DYNAMIC ) {
2709 retVal = addrindex_start_dynamic( req );
2711 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2712 retVal = addrindex_start_explicit( req );
2719 * Remove results (folder and data) for specified data source and folder.
2720 * \param ds Data source to process.
2721 * \param folder Results folder to remove.
2723 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2724 AddrBookBase *adbase;
2725 AddressCache *cache;
2728 /* printf( "addrindex_remove_results/start\n" ); */
2730 /* Test for folder */
2731 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2732 /* printf( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2733 adbase = ( AddrBookBase * ) ds->rawDataSource;
2734 if( adbase == NULL ) return;
2735 cache = adbase->addressCache;
2737 /* Hide folder to prevent re-display */
2738 addritem_folder_set_hidden( folder, TRUE );
2740 if( ds->type == ADDR_IF_LDAP ) {
2745 qry = ( LdapQuery * ) folder->folderData;
2746 queryID = ADDRQUERY_ID(qry);
2747 /* printf( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2748 delFlag = ldapquery_remove_results( qry );
2750 ldapqry_free( qry );
2752 /* printf( "calling ldapquery_remove_results...done\n" ); */
2755 printf( "delFlag IS-TRUE\n" );
2758 printf( "delFlag IS-FALSE\n" );
2759 addressbook_clear_idler( queryID );
2764 /* printf( "addrindex_remove_results/end\n" ); */
2766 /* Delete query request */
2768 qrymgr_delete_request( queryID );
2772 /* **********************************************************************
2773 * Address completion stuff.
2774 * ***********************************************************************
2778 * This function is used by the address completion function to load
2779 * addresses for all non-external address book interfaces.
2781 * \param callBackFunc Function to be called when an address is
2783 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2785 gboolean addrindex_load_completion(
2786 gint (*callBackFunc) ( const gchar *, const gchar *,
2787 const gchar *, const gchar * ) )
2789 AddressDataSource *ds;
2790 GList *nodeIf, *nodeDS;
2791 GList *listP, *nodeP;
2795 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2797 AddressInterface *iface = nodeIf->data;
2799 nodeIf = g_list_next( nodeIf );
2800 if( ! iface->useInterface ) {
2803 if( iface->externalQuery ) {
2806 nodeDS = iface->listSource;
2810 /* Read address book */
2811 if( addrindex_ds_get_modify_flag( ds ) ) {
2812 addrindex_ds_read_data( ds );
2815 if( ! addrindex_ds_get_read_flag( ds ) ) {
2816 addrindex_ds_read_data( ds );
2819 /* Get all persons */
2820 listP = addrindex_ds_get_all_persons( ds );
2823 ItemPerson *person = nodeP->data;
2824 nodeM = person->listEMail;
2826 /* Figure out name to use */
2827 sName = ADDRITEM_NAME(person);
2828 if( sName == NULL || *sName == '\0' ) {
2829 sName = person->nickName;
2832 /* Process each E-Mail address */
2834 ItemEMail *email = nodeM->data;
2836 callBackFunc( sName, email->address, person->nickName,
2837 ADDRITEM_NAME(email) );
2839 nodeM = g_list_next( nodeM );
2841 nodeP = g_list_next( nodeP );
2843 /* Free up the list */
2844 g_list_free( listP );
2846 nodeDS = g_list_next( nodeDS );
2854 * This function can be used to collect information about
2855 * addressbook entries that contain a specific attribute.
2857 * \param attr Name of attribute to look for
2858 * \param callBackFunc Function to be called when a matching attribute was found
2859 * \return <i>TRUE</i>
2861 gboolean addrindex_load_person_attribute(
2863 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2865 AddressDataSource *ds;
2866 GList *nodeIf, *nodeDS;
2867 GList *listP, *nodeP;
2870 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2873 AddressInterface *iface = nodeIf->data;
2875 nodeIf = g_list_next( nodeIf );
2876 if( ! iface->useInterface ) {
2879 if( iface->externalQuery ) {
2882 nodeDS = iface->listSource;
2886 /* Read address book */
2887 if( addrindex_ds_get_modify_flag( ds ) ) {
2888 addrindex_ds_read_data( ds );
2891 if( ! addrindex_ds_get_read_flag( ds ) ) {
2892 addrindex_ds_read_data( ds );
2895 /* Check addressbook name */
2896 cur_bname = addrindex_ds_get_name( ds );
2898 /* Get all persons */
2899 listP = addrindex_ds_get_all_persons( ds );
2902 ItemPerson *person = nodeP->data;
2904 /* Return all ItemPerson's if attr is NULL */
2905 if( attr == NULL ) {
2906 callBackFunc(person, cur_bname);
2909 /* Return ItemPerson's with specific attribute */
2911 nodeA = person->listAttrib;
2912 /* Process each User Attribute */
2914 UserAttribute *attrib = nodeA->data;
2916 !strcmp( attrib->name,attr ) ) {
2917 callBackFunc(person, cur_bname);
2919 nodeA = g_list_next( nodeA );
2922 nodeP = g_list_next( nodeP );
2924 /* Free up the list */
2925 g_list_free( listP );
2927 nodeDS = g_list_next( nodeDS );