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., 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"
116 N_("Personal address")
119 #define DISP_NEW_COMMON _("Common addresses")
120 #define DISP_NEW_PERSONAL _("Personal addresses")
122 /* Old address book */
123 #define TAG_IF_OLD_COMMON "common_address"
124 #define TAG_IF_OLD_PERSONAL "personal_address"
126 #define DISP_OLD_COMMON _("Common address")
127 #define DISP_OLD_PERSONAL _("Personal address")
132 static AddressIndex *_addressIndex_ = NULL;
135 * Define attribute name-value pair.
137 typedef struct _AddressIfAttr AddressIfAttrib;
138 struct _AddressIfAttr {
144 * Define DOM fragment.
146 typedef struct _AddressIfFrag AddressIfFragment;
147 struct _AddressIfFrag {
154 * Build interface with default values.
156 * \param type Interface type.
157 * \param name Interface name.
158 * \param tagIf XML tag name for interface in address index file.
159 * \param tagDS XML tag name for datasource in address index file.
160 * \return Address interface object.
162 static AddressInterface *addrindex_create_interface(
163 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
165 AddressInterface *iface = g_new0( AddressInterface, 1 );
167 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
168 ADDRITEM_ID(iface) = NULL;
169 ADDRITEM_NAME(iface) = g_strdup( name );
170 ADDRITEM_PARENT(iface) = NULL;
171 ADDRITEM_SUBTYPE(iface) = type;
173 iface->name = g_strdup( name );
174 iface->listTag = g_strdup( tagIf );
175 iface->itemTag = g_strdup( tagDS );
176 iface->legacyFlag = FALSE;
177 iface->haveLibrary = TRUE;
178 iface->useInterface = TRUE;
179 iface->readOnly = TRUE;
181 /* Set callbacks to NULL values - override for each interface */
182 iface->getAccessFlag = NULL;
183 iface->getModifyFlag = NULL;
184 iface->getReadFlag = NULL;
185 iface->getStatusCode = NULL;
186 iface->getReadData = NULL;
187 iface->getRootFolder = NULL;
188 iface->getListFolder = NULL;
189 iface->getListPerson = NULL;
190 iface->getAllPersons = NULL;
191 iface->getAllGroups = NULL;
192 iface->getName = NULL;
193 iface->listSource = NULL;
196 iface->externalQuery = FALSE;
197 iface->searchOrder = 0; /* Ignored */
198 iface->startSearch = NULL;
199 iface->stopSearch = NULL;
205 * Build table of of all address book interfaces.
206 * \param addrIndex Address index object.
208 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
209 AddressInterface *iface;
211 /* Create intrinsic XML address book interface */
212 iface = addrindex_create_interface(
213 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
214 TAG_DS_ADDRESS_BOOK );
215 iface->readOnly = FALSE;
216 iface->getModifyFlag = ( void * ) addrbook_get_modified;
217 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
218 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
219 iface->getStatusCode = ( void * ) addrbook_get_status;
220 iface->getReadData = ( void * ) addrbook_read_data;
221 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
222 iface->getListFolder = ( void * ) addrbook_get_list_folder;
223 iface->getListPerson = ( void * ) addrbook_get_list_person;
224 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
225 iface->getName = ( void * ) addrbook_get_name;
226 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
227 iface->searchOrder = 0;
229 /* Add to list of interfaces in address book */
230 addrIndex->interfaceList =
231 g_list_append( addrIndex->interfaceList, iface );
232 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
234 /* Create vCard interface */
235 iface = addrindex_create_interface(
236 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
237 iface->getModifyFlag = ( void * ) vcard_get_modified;
238 iface->getAccessFlag = ( void * ) vcard_get_accessed;
239 iface->getReadFlag = ( void * ) vcard_get_read_flag;
240 iface->getStatusCode = ( void * ) vcard_get_status;
241 iface->getReadData = ( void * ) vcard_read_data;
242 iface->getRootFolder = ( void * ) vcard_get_root_folder;
243 iface->getListFolder = ( void * ) vcard_get_list_folder;
244 iface->getListPerson = ( void * ) vcard_get_list_person;
245 iface->getAllPersons = ( void * ) vcard_get_all_persons;
246 iface->getName = ( void * ) vcard_get_name;
247 iface->setAccessFlag = ( void * ) vcard_set_accessed;
248 iface->searchOrder = 0;
249 addrIndex->interfaceList =
250 g_list_append( addrIndex->interfaceList, iface );
251 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
253 /* Create JPilot interface */
254 iface = addrindex_create_interface(
255 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
258 iface->haveLibrary = jpilot_test_pilot_lib();
259 iface->useInterface = iface->haveLibrary;
260 iface->getModifyFlag = ( void * ) jpilot_get_modified;
261 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
262 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
263 iface->getStatusCode = ( void * ) jpilot_get_status;
264 iface->getReadData = ( void * ) jpilot_read_data;
265 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
266 iface->getListFolder = ( void * ) jpilot_get_list_folder;
267 iface->getListPerson = ( void * ) jpilot_get_list_person;
268 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
269 iface->getName = ( void * ) jpilot_get_name;
270 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
271 iface->searchOrder = 0;
273 iface->useInterface = FALSE;
274 iface->haveLibrary = FALSE;
276 addrIndex->interfaceList =
277 g_list_append( addrIndex->interfaceList, iface );
278 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
280 /* Create LDAP interface */
281 iface = addrindex_create_interface(
282 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
284 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
285 iface->haveLibrary = ldaputil_test_ldap_lib();
286 iface->useInterface = iface->haveLibrary;
287 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
288 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
289 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
290 iface->getStatusCode = ( void * ) ldapsvr_get_status;
291 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
292 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
293 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
294 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
295 iface->getName = ( void * ) ldapsvr_get_name;
296 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
297 iface->externalQuery = TRUE;
298 iface->searchOrder = 1;
300 iface->useInterface = FALSE;
301 iface->haveLibrary = FALSE;
303 addrIndex->interfaceList =
304 g_list_append( addrIndex->interfaceList, iface );
305 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
307 /* Two old legacy data sources (pre 0.7.0) */
308 iface = addrindex_create_interface(
309 ADDR_IF_COMMON, "Old Address - common",
310 TAG_IF_OLD_COMMON, NULL );
311 iface->legacyFlag = TRUE;
312 addrIndex->interfaceList =
313 g_list_append( addrIndex->interfaceList, iface );
314 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
316 iface = addrindex_create_interface(
317 ADDR_IF_COMMON, "Old Address - personal",
318 TAG_IF_OLD_PERSONAL, NULL );
319 iface->legacyFlag = TRUE;
320 addrIndex->interfaceList =
321 g_list_append( addrIndex->interfaceList, iface );
322 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
328 * \param fragment Fragment to free.
330 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
334 node = fragment->children;
336 AddressIfFragment *child = node->data;
337 addrindex_free_fragment( child );
339 node = g_list_next( node );
341 g_list_free( fragment->children );
343 /* Free attributes */
344 node = fragment->attributes;
346 AddressIfAttrib *nv = node->data;
351 node = g_list_next( node );
353 g_list_free( fragment->attributes );
355 g_free( fragment->name );
356 fragment->name = NULL;
357 fragment->attributes = NULL;
358 fragment->children = NULL;
364 * Create a new data source.
365 * \param ifType Interface type to create.
366 * \return Initialized data source.
368 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
369 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
371 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
372 ADDRITEM_ID(ds) = NULL;
373 ADDRITEM_NAME(ds) = NULL;
374 ADDRITEM_PARENT(ds) = NULL;
375 ADDRITEM_SUBTYPE(ds) = 0;
377 ds->rawDataSource = NULL;
378 ds->interface = NULL;
383 * Free up data source.
384 * \param ds Data source to free.
386 void addrindex_free_datasource( AddressDataSource *ds ) {
387 AddressInterface *iface;
389 g_return_if_fail( ds != NULL );
391 iface = ds->interface;
392 if( ds->rawDataSource != NULL ) {
393 if( iface != NULL ) {
394 if( iface->useInterface ) {
395 if( iface->type == ADDR_IF_BOOK ) {
396 AddressBookFile *abf = ds->rawDataSource;
397 addrbook_free_book( abf );
399 else if( iface->type == ADDR_IF_VCARD ) {
400 VCardFile *vcf = ds->rawDataSource;
404 else if( iface->type == ADDR_IF_JPILOT ) {
405 JPilotFile *jpf = ds->rawDataSource;
410 else if( iface->type == ADDR_IF_LDAP ) {
411 LdapServer *server = ds->rawDataSource;
412 ldapsvr_free( server );
419 AddressIfFragment *fragment = ds->rawDataSource;
420 addrindex_free_fragment( fragment );
425 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
426 ADDRITEM_ID(ds) = NULL;
427 ADDRITEM_NAME(ds) = NULL;
428 ADDRITEM_PARENT(ds) = NULL;
429 ADDRITEM_SUBTYPE(ds) = 0;
430 ds->type = ADDR_IF_NONE;
431 ds->interface = NULL;
432 ds->rawDataSource = NULL;
438 * Free up all data sources for specified interface.
439 * \param iface Address interface to process.
441 static void addrindex_free_all_datasources( AddressInterface *iface ) {
442 GList *node = iface->listSource;
444 AddressDataSource *ds = node->data;
445 addrindex_free_datasource( ds );
447 node = g_list_next( node );
452 * Free up specified interface.
453 * \param iface Interface to process.
455 static void addrindex_free_interface( AddressInterface *iface ) {
456 /* Free up data sources */
457 addrindex_free_all_datasources( iface );
458 g_list_free( iface->listSource );
460 /* Free internal storage */
461 g_free( ADDRITEM_ID(iface) );
462 g_free( ADDRITEM_NAME(iface) );
463 g_free( iface->name );
464 g_free( iface->listTag );
465 g_free( iface->itemTag );
467 /* Clear all pointers */
468 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
469 ADDRITEM_ID(iface) = NULL;
470 ADDRITEM_NAME(iface) = NULL;
471 ADDRITEM_PARENT(iface) = NULL;
472 ADDRITEM_SUBTYPE(iface) = 0;
473 iface->type = ADDR_IF_NONE;
475 iface->listTag = NULL;
476 iface->itemTag = NULL;
477 iface->legacyFlag = FALSE;
478 iface->useInterface = FALSE;
479 iface->haveLibrary = FALSE;
480 iface->listSource = NULL;
483 iface->searchOrder = 0;
484 iface->startSearch = NULL;
485 iface->stopSearch = NULL;
491 * Return cache ID for specified data source.
493 * \param addrIndex Address index.
494 * \param ds Data source.
495 * \return ID or NULL if not found. This should be <code>g_free()</code>
498 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
499 gchar *cacheID = NULL;
500 AddrBookBase *adbase;
503 g_return_val_if_fail( addrIndex != NULL, NULL );
504 g_return_val_if_fail( ds != NULL, NULL );
506 adbase = ( AddrBookBase * ) ds->rawDataSource;
508 cache = adbase->addressCache;
510 cacheID = g_strdup( cache->cacheID );
518 * Return reference to data source for specified cacheID.
519 * \param addrIndex Address index.
521 * \return Data source, or NULL if not found.
523 AddressDataSource *addrindex_get_datasource(
524 AddressIndex *addrIndex, const gchar *cacheID )
526 g_return_val_if_fail( addrIndex != NULL, NULL );
527 g_return_val_if_fail( cacheID != NULL, NULL );
528 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
532 * Return reference to address cache for specified cacheID.
533 * \param addrIndex Address index.
535 * \return Address cache, or NULL if not found.
537 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
538 AddressDataSource *ds;
539 AddrBookBase *adbase;
542 g_return_val_if_fail( addrIndex != NULL, NULL );
543 g_return_val_if_fail( cacheID != NULL, NULL );
546 ds = addrindex_get_datasource( addrIndex, cacheID );
548 adbase = ( AddrBookBase * ) ds->rawDataSource;
549 cache = adbase->addressCache;
555 * Add data source into hash table.
556 * \param addrIndex Address index.
557 * \param ds Data source.
559 static void addrindex_hash_add_cache(
560 AddressIndex *addrIndex, AddressDataSource *ds )
564 cacheID = addrindex_get_cache_id( addrIndex, ds );
566 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
571 * Free hash table callback function.
573 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
581 * Free hash table of address cache items.
583 static void addrindex_free_cache_hash( GHashTable *table ) {
584 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
585 g_hash_table_destroy( table );
589 * Remove data source from internal hashtable.
590 * \param addrIndex Address index.
591 * \param ds Data source to remove.
593 static void addrindex_hash_remove_cache(
594 AddressIndex *addrIndex, AddressDataSource *ds )
598 cacheID = addrindex_get_cache_id( addrIndex, ds );
600 g_hash_table_remove( addrIndex->hashCache, cacheID );
607 * Create a new address index. This is created as a singleton object.
608 * \return Initialized address index object.
610 AddressIndex *addrindex_create_index( void ) {
613 if( _addressIndex_ == NULL ) {
614 index = g_new0( AddressIndex, 1 );
615 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
616 ADDRITEM_ID(index) = NULL;
617 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
618 ADDRITEM_PARENT(index) = NULL;
619 ADDRITEM_SUBTYPE(index) = 0;
620 index->filePath = NULL;
621 index->fileName = NULL;
622 index->retVal = MGU_SUCCESS;
623 index->needsConversion = FALSE;
624 index->wasConverted = FALSE;
625 index->conversionError = FALSE;
626 index->interfaceList = NULL;
627 index->lastType = ADDR_IF_NONE;
628 index->dirtyFlag = FALSE;
629 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
630 index->loadedFlag = FALSE;
631 index->searchOrder = NULL;
632 addrindex_build_if_list( index );
633 _addressIndex_ = index;
635 return _addressIndex_;
639 * Return reference to address index.
640 * \return Address index object.
642 AddressIndex *addrindex_get_object( void ) {
643 return _addressIndex_;
647 * Property - Specify file path to address index file.
648 * \param addrIndex Address index.
649 * \param value Path to index file.
651 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
652 g_return_if_fail( addrIndex != NULL );
653 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
657 * Property - Specify file name to address index file.
658 * \param addrIndex Address index.
659 * \param value File name.
661 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
662 g_return_if_fail( addrIndex != NULL );
663 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
667 * Property - Specify file path to be used.
668 * \param addrIndex Address index.
669 * \param value Path to JPilot file.
671 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
672 g_return_if_fail( addrIndex != NULL );
673 addrIndex->dirtyFlag = value;
677 * Property - get loaded flag. Note that this flag is set after reading data
678 * from the address books.
679 * \param addrIndex Address index.
680 * \return <i>TRUE</i> if address index data was loaded.
682 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
683 g_return_val_if_fail( addrIndex != NULL, FALSE );
684 return addrIndex->loadedFlag;
688 * Return list of address interfaces.
689 * \param addrIndex Address index.
690 * \return List of address interfaces.
692 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
693 g_return_val_if_fail( addrIndex != NULL, NULL );
694 return addrIndex->interfaceList;
698 * Perform any other initialization of address index.
700 void addrindex_initialize( void ) {
702 addrcompl_initialize();
706 * Perform any other teardown of address index.
708 void addrindex_teardown( void ) {
709 addrcompl_teardown();
714 * Free up address index.
715 * \param addrIndex Address index.
717 void addrindex_free_index( AddressIndex *addrIndex ) {
720 g_return_if_fail( addrIndex != NULL );
723 g_list_free( addrIndex->searchOrder );
724 addrIndex->searchOrder = NULL;
726 /* Free internal storage */
727 g_free( ADDRITEM_ID(addrIndex) );
728 g_free( ADDRITEM_NAME(addrIndex) );
729 g_free( addrIndex->filePath );
730 g_free( addrIndex->fileName );
733 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
734 ADDRITEM_ID(addrIndex) = NULL;
735 ADDRITEM_NAME(addrIndex) = NULL;
736 ADDRITEM_PARENT(addrIndex) = NULL;
737 ADDRITEM_SUBTYPE(addrIndex) = 0;
738 addrIndex->filePath = NULL;
739 addrIndex->fileName = NULL;
740 addrIndex->retVal = MGU_SUCCESS;
741 addrIndex->needsConversion = FALSE;
742 addrIndex->wasConverted = FALSE;
743 addrIndex->conversionError = FALSE;
744 addrIndex->lastType = ADDR_IF_NONE;
745 addrIndex->dirtyFlag = FALSE;
747 /* Free up interfaces */
748 node = addrIndex->interfaceList;
750 AddressInterface *iface = node->data;
751 addrindex_free_interface( iface );
752 node = g_list_next( node );
754 g_list_free( addrIndex->interfaceList );
755 addrIndex->interfaceList = NULL;
757 /* Free up hash cache */
758 addrindex_free_cache_hash( addrIndex->hashCache );
759 addrIndex->hashCache = NULL;
761 addrIndex->loadedFlag = FALSE;
765 _addressIndex_ = NULL;
769 * Print address index.
770 * \param addrIndex Address index.
771 * \parem stream Stream to print.
773 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
774 g_return_if_fail( addrIndex != NULL );
775 fprintf( stream, "AddressIndex:\n" );
776 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
777 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
778 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
779 fprintf( stream, "\tconverted: '%s'\n",
780 addrIndex->wasConverted ? "yes" : "no" );
781 fprintf( stream, "\tcvt error: '%s'\n",
782 addrIndex->conversionError ? "yes" : "no" );
783 fprintf( stream, "\t---\n" );
787 * Retrieve reference to address interface for specified interface type.
788 * \param addrIndex Address index.
789 * \param ifType Interface type.
790 * \return Address interface, or NULL if not found.
792 AddressInterface *addrindex_get_interface(
793 AddressIndex *addrIndex, AddressIfType ifType )
795 AddressInterface *retVal = NULL;
798 g_return_val_if_fail( addrIndex != NULL, NULL );
800 node = addrIndex->interfaceList;
802 AddressInterface *iface = node->data;
803 node = g_list_next( node );
804 if( iface->type == ifType ) {
813 * Add raw data source to index. The raw data object (an AddressBookFile or
814 * VCardFile object, for example) should be supplied as the raw dataSource
817 * \param addrIndex Address index.
818 * \param ifType Interface type to add.
819 * \param dataSource Actual raw data source to add.
820 * \return Data source added, or NULL if invalid interface type.
822 AddressDataSource *addrindex_index_add_datasource(
823 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
825 AddressInterface *iface;
826 AddressDataSource *ds = NULL;
828 g_return_val_if_fail( addrIndex != NULL, NULL );
829 g_return_val_if_fail( dataSource != NULL, NULL );
831 iface = addrindex_get_interface( addrIndex, ifType );
833 ds = addrindex_create_datasource( ifType );
834 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
836 ds->rawDataSource = dataSource;
837 ds->interface = iface;
838 iface->listSource = g_list_append( iface->listSource, ds );
839 addrIndex->dirtyFlag = TRUE;
841 addrindex_hash_add_cache( addrIndex, ds );
847 * Remove specified data source from index.
848 * \param addrIndex Address index.
849 * \param dataSource Data source to add.
850 * \return Reference to data source if removed, or NULL if data source was not
851 * found in index. Note the this object must still be freed.
853 AddressDataSource *addrindex_index_remove_datasource(
854 AddressIndex *addrIndex, AddressDataSource *dataSource )
856 AddressDataSource *retVal = FALSE;
857 AddressInterface *iface;
859 g_return_val_if_fail( addrIndex != NULL, NULL );
860 g_return_val_if_fail( dataSource != NULL, NULL );
862 iface = addrindex_get_interface( addrIndex, dataSource->type );
864 iface->listSource = g_list_remove( iface->listSource, dataSource );
865 addrIndex->dirtyFlag = TRUE;
866 dataSource->interface = NULL;
868 /* Remove cache from hash table */
869 addrindex_hash_remove_cache( addrIndex, dataSource );
877 * Retrieve a reference to address interface for specified interface type and
878 * XML interface tag name.
879 * \param addrIndex Address index.
880 * \param tag XML interface tag name to match.
881 * \param ifType Interface type to match.
882 * \return Reference to address index, or NULL if not found in index.
884 static AddressInterface *addrindex_tag_get_interface(
885 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
887 AddressInterface *retVal = NULL;
888 GList *node = addrIndex->interfaceList;
891 AddressInterface *iface = node->data;
892 node = g_list_next( node );
894 if( strcmp( iface->listTag, tag ) == 0 ) {
900 if( iface->type == ifType ) {
910 * Retrieve a reference to address interface for specified interface type and
911 * XML datasource tag name.
912 * \param addrIndex Address index.
913 * \param ifType Interface type to match.
914 * \param tag XML datasource tag name to match.
915 * \return Reference to address index, or NULL if not found in index.
917 static AddressInterface *addrindex_tag_get_datasource(
918 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
920 AddressInterface *retVal = NULL;
921 GList *node = addrIndex->interfaceList;
924 AddressInterface *iface = node->data;
925 node = g_list_next( node );
926 if( iface->type == ifType && iface->itemTag ) {
927 if( strcmp( iface->itemTag, tag ) == 0 ) {
936 /* **********************************************************************
937 * Interface XML parsing functions.
938 * ***********************************************************************
942 * Write start of XML element to file.
944 * \param lvl Indentation level.
945 * \param name Element name.
947 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
949 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
955 * Write end of XML element to file.
957 * \param lvl Indentation level.
958 * \param name Element name.
960 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
962 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
969 * Write XML attribute to file.
971 * \param name Attribute name.
972 * \param value Attribute value.
974 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
978 xml_file_put_escape_str( fp, value );
983 * Return DOM fragment for current XML tag from file.
984 * \param file XML file being processed.
985 * \return Fragment representing DOM fragment for configuration element.
987 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
988 AddressIfFragment *fragment;
989 AddressIfFragment *child;
999 /* printf( "addrindex_read_fragment\n" ); */
1001 prevLevel = file->level;
1003 /* Get current tag name */
1004 xtag = xml_get_current_tag( file );
1006 /* Create new fragment */
1007 fragment = g_new0( AddressIfFragment, 1 );
1008 fragment->name = g_strdup( xtag->tag );
1009 fragment->children = NULL;
1010 fragment->attributes = NULL;
1012 /* Read attributes */
1014 attr = xml_get_current_tag_attr( file );
1016 name = ((XMLAttr *)attr->data)->name;
1017 value = ((XMLAttr *)attr->data)->value;
1018 nv = g_new0( AddressIfAttrib, 1 );
1019 nv->name = g_strdup( name );
1020 nv->value = g_strdup( value );
1021 list = g_list_append( list, nv );
1022 attr = g_list_next( attr );
1024 fragment->attributes = list;
1026 /* Now read the children */
1028 rc = xml_parse_next_tag( file );
1033 if( file->level < prevLevel ) {
1034 /* We must be above level we start at */
1037 child = addrindex_read_fragment( file );
1038 fragment->children = g_list_append( fragment->children, child );
1045 * Write DOM fragment to file.
1046 * \param fp File to write.
1047 * \param fragment DOM fragment for configuration element.
1048 * \param lvl Indent level.
1050 static void addrindex_write_fragment(
1051 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1056 addrindex_write_elem_s( fp, lvl, fragment->name );
1057 node = fragment->attributes;
1059 AddressIfAttrib *nv = node->data;
1060 addrindex_write_attr( fp, nv->name, nv->value );
1061 node = g_list_next( node );
1063 if( fragment->children ) {
1066 /* Output children */
1067 node = fragment->children;
1069 AddressIfFragment *child = node->data;
1070 addrindex_write_fragment( fp, child, 1+lvl );
1071 node = g_list_next( node );
1074 /* Output closing tag */
1075 addrindex_write_elem_e( fp, lvl, fragment->name );
1084 static void addrindex_print_fragment_r(
1085 const AddressIfFragment *fragment, FILE *stream, gint lvl )
1090 for( i = 0; i < lvl; i++ )
1091 fprintf( stream, " " );
1092 fprintf( stream, "Element:%s:\n", fragment->name );
1093 node = fragment->attributes;
1095 AddressIfAttrib *nv = node->data;
1096 for( i = 0; i < lvl; i++ )
1097 fprintf( stream, " " );
1098 fprintf( stream, " %s : %s\n", nv->name, nv->value );
1099 node = g_list_next( node );
1101 node = fragment->children;
1103 AddressIfFragment *child = node->data;
1104 addrindex_print_fragment_r( child, stream, 1+lvl );
1105 node = g_list_next( node );
1109 static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
1110 addrindex_print_fragment_r( fragment, stream, 0 );
1115 * Read/parse address index file, creating a data source for a regular
1116 * intrinsic XML addressbook.
1117 * \param file Address index file.
1118 * \return Data source.
1120 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1121 AddressDataSource *ds;
1122 AddressBookFile *abf;
1125 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1126 abf = addrbook_create_book();
1127 attr = xml_get_current_tag_attr( file );
1129 gchar *name = ((XMLAttr *)attr->data)->name;
1130 gchar *value = ((XMLAttr *)attr->data)->value;
1131 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1132 addrbook_set_name( abf, value );
1134 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1135 addrbook_set_file( abf, value );
1137 attr = g_list_next( attr );
1139 ds->rawDataSource = abf;
1143 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1144 AddressBookFile *abf = ds->rawDataSource;
1146 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1147 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1148 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1149 fputs( " />\n", fp );
1153 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1154 AddressDataSource *ds;
1158 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1159 vcf = vcard_create();
1160 attr = xml_get_current_tag_attr( file );
1162 gchar *name = ((XMLAttr *)attr->data)->name;
1163 gchar *value = ((XMLAttr *)attr->data)->value;
1164 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1165 vcard_set_name( vcf, value );
1167 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1168 vcard_set_file( vcf, value );
1170 attr = g_list_next( attr );
1172 ds->rawDataSource = vcf;
1176 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1177 VCardFile *vcf = ds->rawDataSource;
1179 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1180 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1181 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1182 fputs( " />\n", fp );
1187 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1188 AddressDataSource *ds;
1192 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1193 jpf = jpilot_create();
1194 attr = xml_get_current_tag_attr( file );
1196 gchar *name = ((XMLAttr *)attr->data)->name;
1197 gchar *value = ((XMLAttr *)attr->data)->value;
1198 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1199 jpilot_set_name( jpf, value );
1201 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1202 jpilot_set_file( jpf, value );
1204 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1205 jpilot_add_custom_label( jpf, value );
1207 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1208 jpilot_add_custom_label( jpf, value );
1210 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1211 jpilot_add_custom_label( jpf, value );
1213 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1214 jpilot_add_custom_label( jpf, value );
1216 attr = g_list_next( attr );
1218 ds->rawDataSource = jpf;
1222 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1223 JPilotFile *jpf = ds->rawDataSource;
1227 GList *customLbl = jpilot_get_custom_labels( jpf );
1228 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1229 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1230 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1235 g_snprintf( name, sizeof(name), "%s%d",
1236 ATTAG_JPILOT_CUSTOM, ind );
1237 addrindex_write_attr( fp, name, node->data );
1239 node = g_list_next( node );
1241 fputs( " />\n", fp );
1247 * Just read/write DOM fragments (preserve data found in file).
1249 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1250 AddressDataSource *ds;
1252 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1253 ds->rawDataSource = addrindex_read_fragment( file );
1257 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1258 AddressIfFragment *fragment = ds->rawDataSource;
1260 addrindex_write_fragment( fp, fragment, lvl );
1267 * Parse LDAP criteria attribute data from XML file.
1268 * \param file Index file.
1269 * \param ctl LDAP control object to populate.
1271 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1280 if( file == NULL ) {
1285 prevLevel = file->level;
1286 xtagPrev = xml_get_current_tag( file );
1288 rc = xml_parse_next_tag( file );
1290 /* Terminate prematurely */
1291 mgu_free_dlist( list );
1295 if( file->level < prevLevel ) {
1296 /* We must be above level we start at */
1300 /* Get a tag (element) */
1301 xtag = xml_get_current_tag( file );
1302 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1303 /* LDAP criteria attribute */
1304 attr = xml_get_current_tag_attr( file );
1306 gchar *name = ((XMLAttr *)attr->data)->name;
1307 gchar *value = ((XMLAttr *)attr->data)->value;
1308 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1309 if( value && strlen( value ) > 0 ) {
1310 list = g_list_append(
1311 list, g_strdup( value ) );
1314 attr = g_list_next( attr );
1318 if( xtag != xtagPrev ) {
1319 /* Found a new tag */
1326 /* Build list of search attributes */
1327 ldapctl_criteria_list_clear( ctl );
1330 ldapctl_criteria_list_add( ctl, node->data );
1331 g_free( node->data );
1333 node = g_list_next( node );
1335 g_list_free( list );
1340 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1342 * Parse LDAP control data from XML file.
1343 * \param file Index file.
1344 * \return Initialized data soruce object.
1346 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1347 AddressDataSource *ds;
1351 gchar *serverName = NULL;
1352 gchar *criteria = NULL;
1353 gboolean bDynSearch;
1357 /* printf( "addrindex_parse_ldap\n" ); */
1358 /* Set up some defaults */
1361 iMatch = LDAPCTL_MATCH_BEGINWITH;
1363 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1364 ctl = ldapctl_create();
1365 attr = xml_get_current_tag_attr( file );
1367 gchar *name = ((XMLAttr *)attr->data)->name;
1368 gchar *value = ((XMLAttr *)attr->data)->value;
1369 gint ivalue = atoi( value );
1371 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1372 if( serverName ) g_free( serverName );
1373 serverName = g_strdup( value );
1375 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1376 ldapctl_set_host( ctl, value );
1378 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1379 ldapctl_set_port( ctl, ivalue );
1381 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1382 ldapctl_set_base_dn( ctl, value );
1384 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1385 ldapctl_set_bind_dn( ctl, value );
1387 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1388 ldapctl_set_bind_password( ctl, value );
1390 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1391 if( criteria ) g_free( criteria );
1392 criteria = g_strdup( value );
1394 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1395 ldapctl_set_max_entries( ctl, ivalue );
1397 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1398 ldapctl_set_timeout( ctl, ivalue );
1400 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1401 ldapctl_set_max_query_age( ctl, ivalue );
1403 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1405 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1409 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1410 iMatch = LDAPCTL_MATCH_BEGINWITH;
1411 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1412 iMatch = LDAPCTL_MATCH_CONTAINS;
1415 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1417 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1421 attr = g_list_next( attr );
1424 server = ldapsvr_create_noctl();
1425 ldapsvr_set_name( server, serverName );
1426 ldapsvr_set_search_flag( server, bDynSearch );
1427 ldapctl_set_matching_option( ctl, iMatch );
1428 ldapctl_set_tls( ctl, bTLS );
1429 g_free( serverName );
1430 ldapsvr_set_control( server, ctl );
1431 ds->rawDataSource = server;
1433 addrindex_parse_ldap_attrlist( file, ctl );
1435 * If criteria have been specified and no attributes were listed, then
1436 * convert old style criteria into an attribute list. Any criteria will
1437 * be dropped when saving data.
1440 if( ! ldapctl_get_criteria_list( ctl ) ) {
1441 ldapctl_parse_ldap_search( ctl, criteria );
1445 /* ldapsvr_print_data( server, stdout ); */
1450 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1451 LdapServer *server = ds->rawDataSource;
1452 LdapControl *ctl = NULL;
1457 ctl = server->control;
1459 if( ctl == NULL ) return;
1461 /* Output start element with attributes */
1462 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1463 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1464 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1466 sprintf( value, "%d", ctl->port );
1467 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1469 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1470 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1471 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1473 sprintf( value, "%d", ctl->maxEntries );
1474 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1475 sprintf( value, "%d", ctl->timeOut );
1476 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1477 sprintf( value, "%d", ctl->maxQueryAge );
1478 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1480 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1481 server->searchFlag ?
1482 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1484 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1485 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1486 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1488 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1490 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1494 /* Output attributes */
1495 node = ldapctl_get_criteria_list( ctl );
1497 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1498 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1500 node = g_list_next( node );
1503 /* End of element */
1504 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1509 * Just read/write DOM fragments (preserve data found in file).
1511 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1512 AddressDataSource *ds;
1514 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1515 ds->rawDataSource = addrindex_read_fragment( file );
1519 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1520 AddressIfFragment *fragment = ds->rawDataSource;
1522 addrindex_write_fragment( fp, fragment, lvl );
1527 /* **********************************************************************
1528 * Address index I/O functions.
1529 * ***********************************************************************
1532 * Read address index file, creating appropriate data sources for each address
1535 * \param addrIndex Address index.
1536 * \param file Address index file.
1538 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1541 AddressInterface *iface = NULL, *dsIFace = NULL;
1542 AddressDataSource *ds;
1545 addrIndex->loadedFlag = FALSE;
1547 prev_level = file->level;
1548 rc = xml_parse_next_tag( file );
1549 if( file->level == 0 ) return;
1551 xtag = xml_get_current_tag( file );
1553 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1555 addrIndex->lastType = iface->type;
1556 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1559 dsIFace = addrindex_tag_get_datasource(
1560 addrIndex, addrIndex->lastType, xtag->tag );
1562 /* Add data source to list */
1564 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1565 ds = addrindex_parse_book( file );
1566 if( ds->rawDataSource ) {
1567 addrbook_set_path( ds->rawDataSource,
1568 addrIndex->filePath );
1571 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1572 ds = addrindex_parse_vcard( file );
1574 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1575 ds = addrindex_parse_jpilot( file );
1577 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1578 ds = addrindex_parse_ldap( file );
1581 ds->interface = dsIFace;
1582 addrindex_hash_add_cache( addrIndex, ds );
1583 dsIFace->listSource =
1584 g_list_append( dsIFace->listSource, ds );
1592 * Search order sorting comparison function for building search order list.
1594 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1595 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1596 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1598 return ifaceA->searchOrder - ifaceB->searchOrder;
1602 * Build list of data sources to process.
1603 * \param addrIndex Address index object.
1605 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1608 /* Clear existing list */
1609 g_list_free( addrIndex->searchOrder );
1610 addrIndex->searchOrder = NULL;
1612 /* Build new list */
1613 nodeIf = addrIndex->interfaceList;
1615 AddressInterface *iface = nodeIf->data;
1616 if( iface->useInterface ) {
1617 if( iface->searchOrder > 0 ) {
1618 /* Add to search order list */
1619 addrIndex->searchOrder = g_list_insert_sorted(
1620 addrIndex->searchOrder, iface,
1621 addrindex_search_order_compare );
1624 nodeIf = g_list_next( nodeIf );
1628 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1629 XMLFile *file = NULL;
1630 gchar *fileSpec = NULL;
1632 g_return_val_if_fail( addrIndex != NULL, -1 );
1634 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1635 addrIndex->retVal = MGU_NO_FILE;
1636 file = xml_open_file( fileSpec );
1639 if( file == NULL ) {
1641 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1643 return addrIndex->retVal;
1646 addrIndex->retVal = MGU_BAD_FORMAT;
1647 if( xml_get_dtd( file ) == 0 ) {
1648 if( xml_parse_next_tag( file ) == 0 ) {
1649 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1650 addrindex_read_index( addrIndex, file );
1651 addrIndex->retVal = MGU_SUCCESS;
1655 xml_close_file( file );
1657 addrindex_build_search_order( addrIndex );
1659 return addrIndex->retVal;
1662 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1663 GList *nodeIF, *nodeDS;
1665 gint lvlItem = 1 + lvlList;
1667 nodeIF = addrIndex->interfaceList;
1669 AddressInterface *iface = nodeIF->data;
1670 if( ! iface->legacyFlag ) {
1671 nodeDS = iface->listSource;
1672 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1675 AddressDataSource *ds = nodeDS->data;
1677 if( iface->type == ADDR_IF_BOOK ) {
1678 addrindex_write_book( fp, ds, lvlItem );
1680 if( iface->type == ADDR_IF_VCARD ) {
1681 addrindex_write_vcard( fp, ds, lvlItem );
1683 if( iface->type == ADDR_IF_JPILOT ) {
1684 addrindex_write_jpilot( fp, ds, lvlItem );
1686 if( iface->type == ADDR_IF_LDAP ) {
1687 addrindex_write_ldap( fp, ds, lvlItem );
1690 nodeDS = g_list_next( nodeDS );
1692 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1694 nodeIF = g_list_next( nodeIF );
1699 * Write data to specified file.
1700 * Enter: addrIndex Address index object.
1701 * newFile New file name.
1702 * return: Status code, from addrIndex->retVal.
1703 * Note: File will be created in directory specified by addrIndex.
1705 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1708 #ifndef DEV_STANDALONE
1712 g_return_val_if_fail( addrIndex != NULL, -1 );
1714 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1715 addrIndex->retVal = MGU_OPEN_FILE;
1716 #ifdef DEV_STANDALONE
1717 fp = g_fopen( fileSpec, "wb" );
1720 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1722 pfile = prefs_write_open( fileSpec );
1726 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1728 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1731 addrindex_write_index( addrIndex, fp );
1732 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1734 addrIndex->retVal = MGU_SUCCESS;
1735 #ifdef DEV_STANDALONE
1738 if( prefs_file_close( pfile ) < 0 ) {
1739 addrIndex->retVal = MGU_ERROR_WRITE;
1745 return addrIndex->retVal;
1749 * Save address index data to original file.
1750 * return: Status code, from addrIndex->retVal.
1752 gint addrindex_save_data( AddressIndex *addrIndex ) {
1753 g_return_val_if_fail( addrIndex != NULL, -1 );
1755 addrIndex->retVal = MGU_NO_FILE;
1756 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1757 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1759 addrindex_write_to( addrIndex, addrIndex->fileName );
1760 if( addrIndex->retVal == MGU_SUCCESS ) {
1761 addrIndex->dirtyFlag = FALSE;
1763 return addrIndex->retVal;
1767 * Save all address book files which may have changed.
1768 * Return: Status code, set if there was a problem saving data.
1770 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1771 gint retVal = MGU_SUCCESS;
1772 GList *nodeIf, *nodeDS;
1774 nodeIf = addrIndex->interfaceList;
1776 AddressInterface *iface = nodeIf->data;
1777 if( iface->type == ADDR_IF_BOOK ) {
1778 nodeDS = iface->listSource;
1780 AddressDataSource *ds = nodeDS->data;
1781 AddressBookFile *abf = ds->rawDataSource;
1782 if( addrbook_get_dirty( abf ) ) {
1783 if( addrbook_get_read_flag( abf ) ) {
1784 addrbook_save_data( abf );
1785 if( abf->retVal != MGU_SUCCESS ) {
1786 retVal = abf->retVal;
1790 nodeDS = g_list_next( nodeDS );
1794 nodeIf = g_list_next( nodeIf );
1800 /* **********************************************************************
1801 * Address book conversion to new format.
1802 * ***********************************************************************
1805 #define ELTAG_IF_OLD_FOLDER "folder"
1806 #define ELTAG_IF_OLD_GROUP "group"
1807 #define ELTAG_IF_OLD_ITEM "item"
1808 #define ELTAG_IF_OLD_NAME "name"
1809 #define ELTAG_IF_OLD_ADDRESS "address"
1810 #define ELTAG_IF_OLD_REMARKS "remarks"
1811 #define ATTAG_IF_OLD_NAME "name"
1813 #define TEMPNODE_ROOT 0
1814 #define TEMPNODE_FOLDER 1
1815 #define TEMPNODE_GROUP 2
1816 #define TEMPNODE_ADDRESS 3
1818 typedef struct _AddressCvt_Node AddressCvtNode;
1819 struct _AddressCvt_Node {
1828 * Parse current address item.
1830 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1835 nn = g_new0( AddressCvtNode, 1 );
1836 nn->type = TEMPNODE_ADDRESS;
1839 level = file->level;
1842 xml_parse_next_tag(file);
1843 if (file->level < level) return nn;
1845 element = xml_get_element( file );
1846 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1847 nn->name = g_strdup( element );
1849 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1850 nn->address = g_strdup( element );
1852 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1853 nn->remarks = g_strdup( element );
1856 xml_parse_next_tag(file);
1861 * Create a temporary node below specified node.
1863 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1865 nn = g_new0( AddressCvtNode, 1 );
1867 nn->name = g_strdup( name );
1868 nn->remarks = g_strdup( rem );
1869 node->list = g_list_append( node->list, nn );
1874 * Process current temporary node.
1876 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1879 AddressCvtNode *newNode = NULL;
1884 prev_level = file->level;
1885 xml_parse_next_tag( file );
1886 if (file->level < prev_level) return;
1890 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1891 attr = xml_get_current_tag_attr(file);
1893 name = ((XMLAttr *)attr->data)->name;
1894 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1895 value = ((XMLAttr *)attr->data)->value;
1898 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1899 addrindex_add_obj( file, newNode );
1902 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1903 attr = xml_get_current_tag_attr(file);
1905 name = ((XMLAttr *)attr->data)->name;
1906 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1907 value = ((XMLAttr *)attr->data)->value;
1910 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1911 addrindex_add_obj( file, newNode );
1913 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1914 newNode = addrindex_parse_item( file );
1915 node->list = g_list_append( node->list, newNode );
1918 /* printf( "invalid: !!! \n" ); */
1919 attr = xml_get_current_tag_attr( file );
1925 * Consume all nodes below current tag.
1927 static void addrindex_consume_tree( XMLFile *file ) {
1934 prev_level = file->level;
1935 xml_parse_next_tag( file );
1936 if (file->level < prev_level) return;
1938 xtag = xml_get_current_tag( file );
1939 /* printf( "tag : %s\n", xtag->tag ); */
1940 element = xml_get_element( file );
1941 attr = xml_get_current_tag_attr( file );
1942 /* show_attribs( attr ); */
1943 /* printf( "\ttag value : %s :\n", element ); */
1944 addrindex_consume_tree( file );
1949 * Print temporary tree.
1951 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1954 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1955 fprintf( stream, "\tname :%s:\n", node->name );
1956 fprintf( stream, "\taddr :%s:\n", node->address );
1957 fprintf( stream, "\trems :%s:\n", node->remarks );
1959 fprintf( stream, "\t--list----\n" );
1963 AddressCvtNode *lNode = list->data;
1964 list = g_list_next( list );
1965 addrindex_print_node( lNode, stream );
1967 fprintf( stream, "\t==list-%d==\n", node->type );
1971 * Free up temporary tree.
1973 static void addrindex_free_node( AddressCvtNode *node ) {
1974 GList *list = node->list;
1977 AddressCvtNode *lNode = list->data;
1978 list = g_list_next( list );
1979 addrindex_free_node( lNode );
1981 node->type = TEMPNODE_ROOT;
1982 g_free( node->name );
1983 g_free( node->address );
1984 g_free( node->remarks );
1985 g_list_free( node->list );
1990 * Process address book for specified node.
1992 static void addrindex_process_node(
1993 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1994 ItemGroup *parentGrp, ItemFolder *folderGrp )
1997 ItemFolder *itemFolder = NULL;
1998 ItemGroup *itemGParent = parentGrp;
1999 ItemFolder *itemGFolder = folderGrp;
2000 AddressCache *cache = abf->addressCache;
2002 if( node->type == TEMPNODE_ROOT ) {
2003 itemFolder = parent;
2005 else if( node->type == TEMPNODE_FOLDER ) {
2006 itemFolder = addritem_create_item_folder();
2007 addritem_folder_set_name( itemFolder, node->name );
2008 addrcache_id_folder( cache, itemFolder );
2009 addrcache_folder_add_folder( cache, parent, itemFolder );
2012 else if( node->type == TEMPNODE_GROUP ) {
2013 ItemGroup *itemGroup;
2016 /* Create a folder for group */
2017 fName = g_strdup_printf( "Cvt - %s", node->name );
2018 itemGFolder = addritem_create_item_folder();
2019 addritem_folder_set_name( itemGFolder, fName );
2020 addrcache_id_folder( cache, itemGFolder );
2021 addrcache_folder_add_folder( cache, parent, itemGFolder );
2024 /* Add group into folder */
2025 itemGroup = addritem_create_item_group();
2026 addritem_group_set_name( itemGroup, node->name );
2027 addrcache_id_group( cache, itemGroup );
2028 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2029 itemGParent = itemGroup;
2031 else if( node->type == TEMPNODE_ADDRESS ) {
2032 ItemPerson *itemPerson;
2033 ItemEMail *itemEMail;
2035 /* Create person and email objects */
2036 itemPerson = addritem_create_item_person();
2037 addritem_person_set_common_name( itemPerson, node->name );
2038 addrcache_id_person( cache, itemPerson );
2039 itemEMail = addritem_create_item_email();
2040 addritem_email_set_address( itemEMail, node->address );
2041 addritem_email_set_remarks( itemEMail, node->remarks );
2042 addrcache_id_email( cache, itemEMail );
2043 addrcache_person_add_email( cache, itemPerson, itemEMail );
2045 /* Add person into appropriate folder */
2047 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2050 addrcache_folder_add_person( cache, parent, itemPerson );
2053 /* Add email address only into group */
2055 addrcache_group_add_email( cache, parentGrp, itemEMail );
2061 AddressCvtNode *lNode = list->data;
2062 list = g_list_next( list );
2063 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2068 * Process address book to specified file number.
2070 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2071 gboolean retVal = FALSE;
2072 AddressBookFile *abf = NULL;
2073 AddressCvtNode *rootNode = NULL;
2074 gchar *newFile = NULL;
2075 GList *fileList = NULL;
2078 /* Setup root node */
2079 rootNode = g_new0( AddressCvtNode, 1 );
2080 rootNode->type = TEMPNODE_ROOT;
2081 rootNode->name = g_strdup( "root" );
2082 rootNode->list = NULL;
2083 addrindex_add_obj( file, rootNode );
2084 /* addrindex_print_node( rootNode, stdout ); */
2086 /* Create new address book */
2087 abf = addrbook_create_book();
2088 addrbook_set_name( abf, displayName );
2089 addrbook_set_path( abf, addrIndex->filePath );
2091 /* Determine next available file number */
2092 fileList = addrbook_get_bookfile_list( abf );
2094 fileNum = 1 + abf->maxValue;
2096 g_list_free( fileList );
2099 newFile = addrbook_gen_new_file_name( fileNum );
2101 addrbook_set_file( abf, newFile );
2104 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2106 /* addrbook_dump_book( abf, stdout ); */
2107 addrbook_save_data( abf );
2108 addrIndex->retVal = abf->retVal;
2109 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2111 addrbook_free_book( abf );
2113 addrindex_free_node( rootNode );
2116 /* Create entries in address index */
2118 abf = addrbook_create_book();
2119 addrbook_set_name( abf, displayName );
2120 addrbook_set_path( abf, addrIndex->filePath );
2121 addrbook_set_file( abf, newFile );
2122 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2129 * Process tree converting data.
2131 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2139 prev_level = file->level;
2140 xml_parse_next_tag( file );
2141 if (file->level < prev_level) return;
2143 xtag = xml_get_current_tag( file );
2144 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2145 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2146 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2147 addrIndex->needsConversion = FALSE;
2148 addrIndex->wasConverted = TRUE;
2153 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2154 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2155 addrIndex->needsConversion = FALSE;
2156 addrIndex->wasConverted = TRUE;
2161 element = xml_get_element( file );
2162 attr = xml_get_current_tag_attr( file );
2163 /* show_attribs( attr ); */
2164 /* printf( "\ttag value : %s :\n", element ); */
2165 addrindex_consume_tree( file );
2169 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2170 XMLFile *file = NULL;
2173 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2174 addrIndex->retVal = MGU_NO_FILE;
2175 file = xml_open_file( fileSpec );
2178 if( file == NULL ) {
2179 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2180 return addrIndex->retVal;
2183 addrIndex->retVal = MGU_BAD_FORMAT;
2184 if( xml_get_dtd( file ) == 0 ) {
2185 if( xml_parse_next_tag( file ) == 0 ) {
2186 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2187 addrindex_convert_tree( addrIndex, file );
2191 xml_close_file( file );
2192 return addrIndex->retVal;
2196 * Create a new address book file.
2198 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2199 gboolean retVal = FALSE;
2200 AddressBookFile *abf = NULL;
2201 gchar *newFile = NULL;
2202 GList *fileList = NULL;
2205 /* Create new address book */
2206 abf = addrbook_create_book();
2207 addrbook_set_name( abf, displayName );
2208 addrbook_set_path( abf, addrIndex->filePath );
2210 /* Determine next available file number */
2211 fileList = addrbook_get_bookfile_list( abf );
2213 fileNum = 1 + abf->maxValue;
2215 g_list_free( fileList );
2218 newFile = addrbook_gen_new_file_name( fileNum );
2220 addrbook_set_file( abf, newFile );
2223 addrbook_save_data( abf );
2224 addrIndex->retVal = abf->retVal;
2225 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2226 addrbook_free_book( abf );
2229 /* Create entries in address index */
2231 abf = addrbook_create_book();
2232 addrbook_set_name( abf, displayName );
2233 addrbook_set_path( abf, addrIndex->filePath );
2234 addrbook_set_file( abf, newFile );
2235 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2242 * Read data for address index performing a conversion if necesary.
2243 * Enter: addrIndex Address index object.
2244 * return: Status code, from addrIndex->retVal.
2245 * Note: New address book files will be created in directory specified by
2246 * addrIndex. Three files will be created, for the following:
2247 * "Common addresses"
2248 * "Personal addresses"
2249 * "Gathered addresses" - a new address book.
2251 gint addrindex_read_data( AddressIndex *addrIndex ) {
2252 g_return_val_if_fail( addrIndex != NULL, -1 );
2254 addrIndex->conversionError = FALSE;
2255 addrindex_read_file( addrIndex );
2256 if( addrIndex->retVal == MGU_SUCCESS ) {
2257 if( addrIndex->needsConversion ) {
2258 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2259 addrIndex->conversionError = TRUE;
2262 addrIndex->conversionError = TRUE;
2265 addrIndex->dirtyFlag = TRUE;
2267 return addrIndex->retVal;
2271 * Create new address books for a new address index.
2272 * Enter: addrIndex Address index object.
2273 * return: Status code, from addrIndex->retVal.
2274 * Note: New address book files will be created in directory specified by
2275 * addrIndex. Three files will be created, for the following:
2276 * "Common addresses"
2277 * "Personal addresses"
2278 * "Gathered addresses" - a new address book.
2280 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2283 g_return_val_if_fail( addrIndex != NULL, -1 );
2285 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2287 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2288 addrIndex->dirtyFlag = TRUE;
2290 return addrIndex->retVal;
2293 /* **********************************************************************
2294 * New interface stuff.
2295 * ***********************************************************************
2299 * Return modified flag for specified data source.
2301 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2302 gboolean retVal = FALSE;
2303 AddressInterface *iface;
2305 if( ds == NULL ) return retVal;
2306 iface = ds->interface;
2307 if( iface == NULL ) return retVal;
2308 if( iface->getModifyFlag ) {
2309 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2315 * Return accessed flag for specified data source.
2317 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2318 gboolean retVal = FALSE;
2319 AddressInterface *iface;
2321 if( ds == NULL ) return retVal;
2322 iface = ds->interface;
2323 if( iface == NULL ) return retVal;
2324 if( iface->getAccessFlag ) {
2325 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2331 * Return data read flag for specified data source.
2333 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2334 gboolean retVal = TRUE;
2335 AddressInterface *iface;
2337 if( ds == NULL ) return retVal;
2338 iface = ds->interface;
2339 if( iface == NULL ) return retVal;
2340 if( iface->getReadFlag ) {
2341 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2347 * Return status code for specified data source.
2349 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2350 gint retVal = MGU_SUCCESS;
2351 AddressInterface *iface;
2353 if( ds == NULL ) return retVal;
2354 iface = ds->interface;
2355 if( iface == NULL ) return retVal;
2356 if( iface->getStatusCode ) {
2357 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2363 * Return data read flag for specified data source.
2365 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2366 gint retVal = MGU_SUCCESS;
2367 AddressInterface *iface;
2369 if( ds == NULL ) return retVal;
2370 iface = ds->interface;
2371 if( iface == NULL ) return retVal;
2372 if( iface->getReadData ) {
2374 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2375 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2377 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2383 * Return data read flag for specified data source.
2385 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2386 ItemFolder *retVal = NULL;
2387 AddressInterface *iface;
2389 if( ds == NULL ) return retVal;
2390 iface = ds->interface;
2391 if( iface == NULL ) return retVal;
2392 if( iface->getRootFolder ) {
2393 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2399 * Return list of folders for specified data source.
2401 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2402 GList *retVal = FALSE;
2403 AddressInterface *iface;
2405 if( ds == NULL ) return retVal;
2406 iface = ds->interface;
2407 if( iface == NULL ) return retVal;
2408 if( iface->getListFolder ) {
2409 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2415 * Return list of persons in root folder for specified data source.
2417 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2418 GList *retVal = FALSE;
2419 AddressInterface *iface;
2421 if( ds == NULL ) return retVal;
2422 iface = ds->interface;
2423 if( iface == NULL ) return retVal;
2424 if( iface->getListPerson ) {
2425 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2431 * Return name for specified data source.
2433 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2434 gchar *retVal = FALSE;
2435 AddressInterface *iface;
2437 if( ds == NULL ) return retVal;
2438 iface = ds->interface;
2439 if( iface == NULL ) return retVal;
2440 if( iface->getName ) {
2441 retVal = ( iface->getName ) ( ds->rawDataSource );
2447 * Set the access flag inside the data source.
2449 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2450 AddressInterface *iface;
2452 if( ds == NULL ) return;
2453 iface = ds->interface;
2454 if( iface == NULL ) return;
2455 if( iface->setAccessFlag ) {
2456 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2461 * Return read only flag for specified data source.
2463 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2464 AddressInterface *iface;
2465 if( ds == NULL ) return TRUE;
2466 iface = ds->interface;
2467 if( iface == NULL ) return TRUE;
2468 return iface->readOnly;
2472 * Return list of all persons for specified data source.
2474 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2475 GList *retVal = NULL;
2476 AddressInterface *iface;
2478 if( ds == NULL ) return retVal;
2479 iface = ds->interface;
2480 if( iface == NULL ) return retVal;
2481 if( iface->getAllPersons ) {
2482 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2488 * Return list of all groups for specified data source.
2490 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2491 GList *retVal = NULL;
2492 AddressInterface *iface;
2494 if( ds == NULL ) return retVal;
2495 iface = ds->interface;
2496 if( iface == NULL ) return retVal;
2497 if( iface->getAllGroups ) {
2498 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2503 /* **********************************************************************
2504 * Address search stuff.
2505 * ***********************************************************************
2509 * Setup or register the dynamic search that will be performed. The search
2510 * is registered with the query manager.
2512 * \param searchTerm Search term. A private copy will be made.
2513 * \param callBackEntry Callback function that should be called when
2514 * each entry is received.
2515 * \param callBackEnd Callback function that should be called when
2516 * search has finished running.
2517 * \return ID allocated to query that will be executed.
2519 gint addrindex_setup_search(
2520 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2525 /* Set up a dynamic address query */
2526 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2527 queryID = req->queryID;
2528 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2530 /* printf( "***> query ID ::%d::\n", queryID ); */
2537 * Function prototypes (not in header file or circular reference errors are
2540 LdapQuery *ldapsvr_new_dynamic_search(
2541 LdapServer *server, QueryRequest *req );
2542 LdapQuery *ldapsvr_new_explicit_search(
2543 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2544 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2549 * Execute the previously registered dynamic search.
2551 * \param req Address query object to execute.
2552 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2555 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2556 AddressInterface *iface;
2557 AddressDataSource *ds;
2562 /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2563 nodeIf = _addressIndex_->searchOrder;
2565 iface = nodeIf->data;
2566 nodeIf = g_list_next( nodeIf );
2568 if( ! iface->useInterface ) {
2571 if( ! iface->externalQuery ) {
2576 nodeDS = iface->listSource;
2579 nodeDS = g_list_next( nodeDS );
2581 if( type == ADDR_IF_LDAP ) {
2585 server = ds->rawDataSource;
2586 if( ! server->searchFlag ) {
2589 if( ldapsvr_reuse_previous( server, req ) ) {
2593 /* Start a new dynamic search */
2594 qry = ldapsvr_new_dynamic_search( server, req );
2596 ldapsvr_execute_query( server, qry );
2606 * Stop the previously registered search.
2608 * \param queryID ID of search query to stop.
2610 void addrindex_stop_search( const gint queryID ){
2612 AddrQueryObject *aqo;
2615 /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
2616 /* If query ID does not match, search has not been setup */
2617 req = qrymgr_find_request( queryID );
2622 /* Stop all queries that were associated with request */
2623 node = req->queryList;
2627 if( aqo->queryType == ADDRQUERY_LDAP ) {
2628 LdapQuery *qry = ( LdapQuery * ) aqo;
2629 ldapqry_set_stop_flag( qry, TRUE );
2633 node = g_list_next( node );
2636 /* Delete query request */
2637 qrymgr_delete_request( queryID );
2641 * Setup or register the explicit search that will be performed. The search is
2642 * registered with the query manager.
2644 * \param ds Data source to search.
2645 * \param searchTerm Search term to locate.
2646 * \param folder Folder to receive search results; may be NULL.
2647 * \param callbackEnd Function to call when search has terminated.
2648 * \param callbackEntry Function to called for each entry processed.
2649 * \return ID allocated to query that will be executed.
2651 gint addrindex_setup_explicit_search(
2652 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2653 void *callBackEnd, void *callBackEntry )
2660 /* Name the query */
2661 name = g_strdup_printf( "Search '%s'", searchTerm );
2663 /* Set up query request */
2664 if (!strcmp(searchTerm, "*"))
2665 mySearch = g_strdup("*@");
2667 mySearch = g_strdup(searchTerm);
2669 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2673 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2674 queryID = req->queryID;
2676 if( ds->type == ADDR_IF_LDAP ) {
2680 server = ds->rawDataSource;
2681 ldapsvr_new_explicit_search( server, req, folder );
2685 qrymgr_delete_request( queryID );
2694 * Execute the previously registered explicit search.
2696 * \param req Address query request object to execute.
2697 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2700 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2702 AddrQueryObject *aqo;
2706 /* Note: there should only be one query in the list. */
2707 aqo = req->queryList->data;
2709 if( aqo->queryType == ADDRQUERY_LDAP ) {
2713 qry = ( LdapQuery * ) aqo;
2714 server = qry->server;
2716 /* Start the search */
2718 ldapsvr_execute_query( server, qry );
2725 * Start the previously registered search.
2727 * \param queryID ID of search query to be executed.
2728 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2731 gboolean addrindex_start_search( const gint queryID ) {
2734 AddrSearchType searchType;
2737 /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
2738 req = qrymgr_find_request( queryID );
2743 searchType = req->searchType;
2744 if( searchType == ADDRSEARCH_DYNAMIC ) {
2745 retVal = addrindex_start_dynamic( req );
2747 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2748 retVal = addrindex_start_explicit( req );
2755 * Remove results (folder and data) for specified data source and folder.
2756 * \param ds Data source to process.
2757 * \param folder Results folder to remove.
2759 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2760 AddrBookBase *adbase;
2761 AddressCache *cache;
2764 /* printf( "addrindex_remove_results/start\n" ); */
2766 /* Test for folder */
2767 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2768 /* printf( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2769 adbase = ( AddrBookBase * ) ds->rawDataSource;
2770 if( adbase == NULL ) return;
2771 cache = adbase->addressCache;
2773 /* Hide folder to prevent re-display */
2774 addritem_folder_set_hidden( folder, TRUE );
2776 if( ds->type == ADDR_IF_LDAP ) {
2781 qry = ( LdapQuery * ) folder->folderData;
2782 queryID = ADDRQUERY_ID(qry);
2783 /* printf( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2784 delFlag = ldapquery_remove_results( qry );
2786 ldapqry_free( qry );
2788 /* printf( "calling ldapquery_remove_results...done\n" ); */
2791 printf( "delFlag IS-TRUE\n" );
2794 printf( "delFlag IS-FALSE\n" );
2795 addressbook_clear_idler( queryID );
2800 /* printf( "addrindex_remove_results/end\n" ); */
2802 /* Delete query request */
2804 qrymgr_delete_request( queryID );
2808 /* **********************************************************************
2809 * Address completion stuff.
2810 * ***********************************************************************
2814 * This function is used by the address completion function to load
2815 * addresses for all non-external address book interfaces.
2817 * \param callBackFunc Function to be called when an address is
2819 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2821 gboolean addrindex_load_completion(
2822 gint (*callBackFunc) ( const gchar *, const gchar *,
2823 const gchar *, const gchar * ) )
2825 AddressDataSource *ds;
2826 GList *nodeIf, *nodeDS;
2827 GList *listP, *nodeP;
2831 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2833 AddressInterface *iface = nodeIf->data;
2835 nodeIf = g_list_next( nodeIf );
2836 if( ! iface->useInterface ) {
2839 if( iface->externalQuery ) {
2842 nodeDS = iface->listSource;
2846 /* Read address book */
2847 if( addrindex_ds_get_modify_flag( ds ) ) {
2848 addrindex_ds_read_data( ds );
2851 if( ! addrindex_ds_get_read_flag( ds ) ) {
2852 addrindex_ds_read_data( ds );
2855 /* Get all persons */
2856 listP = addrindex_ds_get_all_persons( ds );
2859 ItemPerson *person = nodeP->data;
2860 nodeM = person->listEMail;
2862 /* Figure out name to use */
2863 sName = ADDRITEM_NAME(person);
2864 if( sName == NULL || *sName == '\0' ) {
2865 sName = person->nickName;
2868 /* Process each E-Mail address */
2870 ItemEMail *email = nodeM->data;
2872 callBackFunc( sName, email->address, person->nickName,
2873 ADDRITEM_NAME(email) );
2875 nodeM = g_list_next( nodeM );
2877 nodeP = g_list_next( nodeP );
2879 /* Free up the list */
2880 g_list_free( listP );
2882 nodeDS = g_list_next( nodeDS );
2890 * This function can be used to collect information about
2891 * addressbook entries that contain a specific attribute.
2893 * \param attr Name of attribute to look for
2894 * \param callBackFunc Function to be called when a matching attribute was found
2895 * \return <i>TRUE</i>
2897 gboolean addrindex_load_person_attribute(
2899 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2901 AddressDataSource *ds;
2902 GList *nodeIf, *nodeDS;
2903 GList *listP, *nodeP;
2906 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2909 AddressInterface *iface = nodeIf->data;
2911 nodeIf = g_list_next( nodeIf );
2912 if( ! iface->useInterface ) {
2915 if( iface->externalQuery ) {
2918 nodeDS = iface->listSource;
2922 /* Read address book */
2923 if( addrindex_ds_get_modify_flag( ds ) ) {
2924 addrindex_ds_read_data( ds );
2927 if( ! addrindex_ds_get_read_flag( ds ) ) {
2928 addrindex_ds_read_data( ds );
2931 /* Check addressbook name */
2932 cur_bname = addrindex_ds_get_name( ds );
2934 /* Get all persons */
2935 listP = addrindex_ds_get_all_persons( ds );
2938 ItemPerson *person = nodeP->data;
2940 /* Return all ItemPerson's if attr is NULL */
2941 if( attr == NULL ) {
2942 callBackFunc(person, cur_bname);
2945 /* Return ItemPerson's with specific attribute */
2947 nodeA = person->listAttrib;
2948 /* Process each User Attribute */
2950 UserAttribute *attrib = nodeA->data;
2952 !strcmp( attrib->name,attr ) ) {
2953 callBackFunc(person, cur_bname);
2955 nodeA = g_list_next( nodeA );
2958 nodeP = g_list_next( nodeP );
2960 /* Free up the list */
2961 g_list_free( listP );
2963 nodeDS = g_list_next( nodeDS );