2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2006 Match Grun and the Claws Mail 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 "addressbook.h"
38 #include "addrindex.h"
40 #include "addrquery.h"
41 #include "addr_compl.h"
44 #ifndef DEV_STANDALONE
45 #include "prefs_gtk.h"
56 #include "ldapserver.h"
58 #include "ldapquery.h"
62 #define TAG_ADDRESS_INDEX "addressbook"
64 #define TAG_IF_ADDRESS_BOOK "book_list"
65 #define TAG_IF_VCARD "vcard_list"
66 #define TAG_IF_JPILOT "jpilot_list"
67 #define TAG_IF_LDAP "ldap_list"
69 #define TAG_DS_ADDRESS_BOOK "book"
70 #define TAG_DS_VCARD "vcard"
71 #define TAG_DS_JPILOT "jpilot"
72 #define TAG_DS_LDAP "server"
74 /* XML Attribute names */
75 #define ATTAG_BOOK_NAME "name"
76 #define ATTAG_BOOK_FILE "file"
78 #define ATTAG_VCARD_NAME "name"
79 #define ATTAG_VCARD_FILE "file"
81 #define ATTAG_JPILOT_NAME "name"
82 #define ATTAG_JPILOT_FILE "file"
83 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
84 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
85 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
86 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
87 #define ATTAG_JPILOT_CUSTOM "custom-"
89 #define ATTAG_LDAP_NAME "name"
90 #define ATTAG_LDAP_HOST "host"
91 #define ATTAG_LDAP_PORT "port"
92 #define ATTAG_LDAP_BASE_DN "base-dn"
93 #define ATTAG_LDAP_BIND_DN "bind-dn"
94 #define ATTAG_LDAP_BIND_PASS "bind-pass"
95 #define ATTAG_LDAP_CRITERIA "criteria"
96 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
97 #define ATTAG_LDAP_TIMEOUT "timeout"
98 #define ATTAG_LDAP_MAX_AGE "max-age"
99 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
100 #define ATTAG_LDAP_MATCH_OPT "match-opt"
101 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
102 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
104 #define ELTAG_LDAP_ATTR_SRCH "attribute"
105 #define ATTAG_LDAP_ATTR_NAME "name"
107 /* Attribute values */
108 #define ATVAL_BOOLEAN_YES "yes"
109 #define ATVAL_BOOLEAN_NO "no"
110 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
111 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
114 #define ATTAG_LDAP_DEFAULT "default"
116 #define DISP_NEW_COMMON _("Common addresses")
117 #define DISP_NEW_PERSONAL _("Personal addresses")
119 /* Old address book */
120 #define TAG_IF_OLD_COMMON "common_address"
121 #define TAG_IF_OLD_PERSONAL "personal_address"
123 #define DISP_OLD_COMMON _("Common address")
124 #define DISP_OLD_PERSONAL _("Personal address")
129 static AddressIndex *_addressIndex_ = NULL;
132 * Define attribute name-value pair.
134 typedef struct _AddressIfAttr AddressIfAttrib;
135 struct _AddressIfAttr {
141 * Define DOM fragment.
143 typedef struct _AddressIfFrag AddressIfFragment;
144 struct _AddressIfFrag {
151 * Build interface with default values.
153 * \param type Interface type.
154 * \param name Interface name.
155 * \param tagIf XML tag name for interface in address index file.
156 * \param tagDS XML tag name for datasource in address index file.
157 * \return Address interface object.
159 static AddressInterface *addrindex_create_interface(
160 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
162 AddressInterface *iface = g_new0( AddressInterface, 1 );
164 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
165 ADDRITEM_ID(iface) = NULL;
166 ADDRITEM_NAME(iface) = g_strdup( name );
167 ADDRITEM_PARENT(iface) = NULL;
168 ADDRITEM_SUBTYPE(iface) = type;
170 iface->name = g_strdup( name );
171 iface->listTag = g_strdup( tagIf );
172 iface->itemTag = g_strdup( tagDS );
173 iface->legacyFlag = FALSE;
174 iface->haveLibrary = TRUE;
175 iface->useInterface = TRUE;
176 iface->readOnly = TRUE;
178 /* Set callbacks to NULL values - override for each interface */
179 iface->getAccessFlag = NULL;
180 iface->getModifyFlag = NULL;
181 iface->getReadFlag = NULL;
182 iface->getStatusCode = NULL;
183 iface->getReadData = NULL;
184 iface->getRootFolder = NULL;
185 iface->getListFolder = NULL;
186 iface->getListPerson = NULL;
187 iface->getAllPersons = NULL;
188 iface->getAllGroups = NULL;
189 iface->getName = NULL;
190 iface->listSource = NULL;
193 iface->externalQuery = FALSE;
194 iface->searchOrder = 0; /* Ignored */
195 iface->startSearch = NULL;
196 iface->stopSearch = NULL;
202 * Build table of of all address book interfaces.
203 * \param addrIndex Address index object.
205 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
206 AddressInterface *iface;
208 /* Create intrinsic XML address book interface */
209 iface = addrindex_create_interface(
210 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
211 TAG_DS_ADDRESS_BOOK );
212 iface->readOnly = FALSE;
213 iface->getModifyFlag = ( void * ) addrbook_get_modified;
214 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
215 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
216 iface->getStatusCode = ( void * ) addrbook_get_status;
217 iface->getReadData = ( void * ) addrbook_read_data;
218 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
219 iface->getListFolder = ( void * ) addrbook_get_list_folder;
220 iface->getListPerson = ( void * ) addrbook_get_list_person;
221 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
222 iface->getAllGroups = ( void * ) addrbook_get_all_groups;
223 iface->getName = ( void * ) addrbook_get_name;
224 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
225 iface->searchOrder = 0;
227 /* Add to list of interfaces in address book */
228 addrIndex->interfaceList =
229 g_list_append( addrIndex->interfaceList, iface );
230 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
232 /* Create vCard interface */
233 iface = addrindex_create_interface(
234 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
235 iface->getModifyFlag = ( void * ) vcard_get_modified;
236 iface->getAccessFlag = ( void * ) vcard_get_accessed;
237 iface->getReadFlag = ( void * ) vcard_get_read_flag;
238 iface->getStatusCode = ( void * ) vcard_get_status;
239 iface->getReadData = ( void * ) vcard_read_data;
240 iface->getRootFolder = ( void * ) vcard_get_root_folder;
241 iface->getListFolder = ( void * ) vcard_get_list_folder;
242 iface->getListPerson = ( void * ) vcard_get_list_person;
243 iface->getAllPersons = ( void * ) vcard_get_all_persons;
244 iface->getName = ( void * ) vcard_get_name;
245 iface->setAccessFlag = ( void * ) vcard_set_accessed;
246 iface->searchOrder = 0;
247 addrIndex->interfaceList =
248 g_list_append( addrIndex->interfaceList, iface );
249 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
251 /* Create JPilot interface */
252 iface = addrindex_create_interface(
253 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
256 iface->haveLibrary = jpilot_test_pilot_lib();
257 iface->useInterface = iface->haveLibrary;
258 iface->getModifyFlag = ( void * ) jpilot_get_modified;
259 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
260 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
261 iface->getStatusCode = ( void * ) jpilot_get_status;
262 iface->getReadData = ( void * ) jpilot_read_data;
263 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
264 iface->getListFolder = ( void * ) jpilot_get_list_folder;
265 iface->getListPerson = ( void * ) jpilot_get_list_person;
266 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
267 iface->getName = ( void * ) jpilot_get_name;
268 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
269 iface->searchOrder = 0;
271 iface->useInterface = FALSE;
272 iface->haveLibrary = FALSE;
274 addrIndex->interfaceList =
275 g_list_append( addrIndex->interfaceList, iface );
276 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
278 /* Create LDAP interface */
279 iface = addrindex_create_interface(
280 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
282 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
283 iface->haveLibrary = ldaputil_test_ldap_lib();
284 iface->useInterface = iface->haveLibrary;
285 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
286 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
287 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
288 iface->getStatusCode = ( void * ) ldapsvr_get_status;
289 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
290 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
291 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
292 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
293 iface->getName = ( void * ) ldapsvr_get_name;
294 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
295 iface->externalQuery = TRUE;
296 iface->searchOrder = 1;
298 iface->useInterface = FALSE;
299 iface->haveLibrary = FALSE;
301 addrIndex->interfaceList =
302 g_list_append( addrIndex->interfaceList, iface );
303 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
305 /* Two old legacy data sources (pre 0.7.0) */
306 iface = addrindex_create_interface(
307 ADDR_IF_COMMON, "Old Address - common",
308 TAG_IF_OLD_COMMON, NULL );
309 iface->legacyFlag = TRUE;
310 addrIndex->interfaceList =
311 g_list_append( addrIndex->interfaceList, iface );
312 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
314 iface = addrindex_create_interface(
315 ADDR_IF_COMMON, "Old Address - personal",
316 TAG_IF_OLD_PERSONAL, NULL );
317 iface->legacyFlag = TRUE;
318 addrIndex->interfaceList =
319 g_list_append( addrIndex->interfaceList, iface );
320 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
326 * \param fragment Fragment to free.
328 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
332 node = fragment->children;
334 AddressIfFragment *child = node->data;
335 addrindex_free_fragment( child );
337 node = g_list_next( node );
339 g_list_free( fragment->children );
341 /* Free attributes */
342 node = fragment->attributes;
344 AddressIfAttrib *nv = node->data;
349 node = g_list_next( node );
351 g_list_free( fragment->attributes );
353 g_free( fragment->name );
354 fragment->name = NULL;
355 fragment->attributes = NULL;
356 fragment->children = NULL;
362 * Create a new data source.
363 * \param ifType Interface type to create.
364 * \return Initialized data source.
366 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
367 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
369 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
370 ADDRITEM_ID(ds) = NULL;
371 ADDRITEM_NAME(ds) = NULL;
372 ADDRITEM_PARENT(ds) = NULL;
373 ADDRITEM_SUBTYPE(ds) = 0;
375 ds->rawDataSource = NULL;
376 ds->interface = NULL;
381 * Free up data source.
382 * \param ds Data source to free.
384 void addrindex_free_datasource( AddressDataSource *ds ) {
385 AddressInterface *iface;
387 g_return_if_fail( ds != NULL );
389 iface = ds->interface;
390 if( ds->rawDataSource != NULL ) {
391 if( iface != NULL ) {
392 if( iface->useInterface ) {
393 if( iface->type == ADDR_IF_BOOK ) {
394 AddressBookFile *abf = ds->rawDataSource;
395 addrbook_free_book( abf );
397 else if( iface->type == ADDR_IF_VCARD ) {
398 VCardFile *vcf = ds->rawDataSource;
402 else if( iface->type == ADDR_IF_JPILOT ) {
403 JPilotFile *jpf = ds->rawDataSource;
408 else if( iface->type == ADDR_IF_LDAP ) {
409 LdapServer *server = ds->rawDataSource;
410 ldapsvr_free( server );
417 AddressIfFragment *fragment = ds->rawDataSource;
418 addrindex_free_fragment( fragment );
423 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
424 ADDRITEM_ID(ds) = NULL;
425 ADDRITEM_NAME(ds) = NULL;
426 ADDRITEM_PARENT(ds) = NULL;
427 ADDRITEM_SUBTYPE(ds) = 0;
428 ds->type = ADDR_IF_NONE;
429 ds->interface = NULL;
430 ds->rawDataSource = NULL;
436 * Free up all data sources for specified interface.
437 * \param iface Address interface to process.
439 static void addrindex_free_all_datasources( AddressInterface *iface ) {
440 GList *node = iface->listSource;
442 AddressDataSource *ds = node->data;
443 addrindex_free_datasource( ds );
445 node = g_list_next( node );
450 * Free up specified interface.
451 * \param iface Interface to process.
453 static void addrindex_free_interface( AddressInterface *iface ) {
454 /* Free up data sources */
455 addrindex_free_all_datasources( iface );
456 g_list_free( iface->listSource );
458 /* Free internal storage */
459 g_free( ADDRITEM_ID(iface) );
460 g_free( ADDRITEM_NAME(iface) );
461 g_free( iface->name );
462 g_free( iface->listTag );
463 g_free( iface->itemTag );
465 /* Clear all pointers */
466 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
467 ADDRITEM_ID(iface) = NULL;
468 ADDRITEM_NAME(iface) = NULL;
469 ADDRITEM_PARENT(iface) = NULL;
470 ADDRITEM_SUBTYPE(iface) = 0;
471 iface->type = ADDR_IF_NONE;
473 iface->listTag = NULL;
474 iface->itemTag = NULL;
475 iface->legacyFlag = FALSE;
476 iface->useInterface = FALSE;
477 iface->haveLibrary = FALSE;
478 iface->listSource = NULL;
481 iface->searchOrder = 0;
482 iface->startSearch = NULL;
483 iface->stopSearch = NULL;
489 * Return cache ID for specified data source.
491 * \param addrIndex Address index.
492 * \param ds Data source.
493 * \return ID or NULL if not found. This should be <code>g_free()</code>
496 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
497 gchar *cacheID = NULL;
498 AddrBookBase *adbase;
501 g_return_val_if_fail( addrIndex != NULL, NULL );
502 g_return_val_if_fail( ds != NULL, NULL );
504 adbase = ( AddrBookBase * ) ds->rawDataSource;
506 cache = adbase->addressCache;
508 cacheID = g_strdup( cache->cacheID );
516 * Return reference to data source for specified cacheID.
517 * \param addrIndex Address index.
519 * \return Data source, or NULL if not found.
521 AddressDataSource *addrindex_get_datasource(
522 AddressIndex *addrIndex, const gchar *cacheID )
524 g_return_val_if_fail( addrIndex != NULL, NULL );
525 g_return_val_if_fail( cacheID != NULL, NULL );
526 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
530 * Return reference to address cache for specified cacheID.
531 * \param addrIndex Address index.
533 * \return Address cache, or NULL if not found.
535 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
536 AddressDataSource *ds;
537 AddrBookBase *adbase;
540 g_return_val_if_fail( addrIndex != NULL, NULL );
541 g_return_val_if_fail( cacheID != NULL, NULL );
544 ds = addrindex_get_datasource( addrIndex, cacheID );
546 adbase = ( AddrBookBase * ) ds->rawDataSource;
547 cache = adbase->addressCache;
553 * Add data source into hash table.
554 * \param addrIndex Address index.
555 * \param ds Data source.
557 static void addrindex_hash_add_cache(
558 AddressIndex *addrIndex, AddressDataSource *ds )
562 cacheID = addrindex_get_cache_id( addrIndex, ds );
564 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
569 * Free hash table callback function.
571 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
579 * Free hash table of address cache items.
581 static void addrindex_free_cache_hash( GHashTable *table ) {
582 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
583 g_hash_table_destroy( table );
587 * Remove data source from internal hashtable.
588 * \param addrIndex Address index.
589 * \param ds Data source to remove.
591 static void addrindex_hash_remove_cache(
592 AddressIndex *addrIndex, AddressDataSource *ds )
596 cacheID = addrindex_get_cache_id( addrIndex, ds );
598 g_hash_table_remove( addrIndex->hashCache, cacheID );
605 * Create a new address index. This is created as a singleton object.
606 * \return Initialized address index object.
608 AddressIndex *addrindex_create_index( void ) {
611 if( _addressIndex_ == NULL ) {
612 index = g_new0( AddressIndex, 1 );
613 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
614 ADDRITEM_ID(index) = NULL;
615 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
616 ADDRITEM_PARENT(index) = NULL;
617 ADDRITEM_SUBTYPE(index) = 0;
618 index->filePath = NULL;
619 index->fileName = NULL;
620 index->retVal = MGU_SUCCESS;
621 index->needsConversion = FALSE;
622 index->wasConverted = FALSE;
623 index->conversionError = FALSE;
624 index->interfaceList = NULL;
625 index->lastType = ADDR_IF_NONE;
626 index->dirtyFlag = FALSE;
627 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
628 index->loadedFlag = FALSE;
629 index->searchOrder = NULL;
630 addrindex_build_if_list( index );
631 _addressIndex_ = index;
633 return _addressIndex_;
637 * Return reference to address index.
638 * \return Address index object.
640 AddressIndex *addrindex_get_object( void ) {
641 return _addressIndex_;
645 * Property - Specify file path to address index file.
646 * \param addrIndex Address index.
647 * \param value Path to index file.
649 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
650 g_return_if_fail( addrIndex != NULL );
651 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
655 * Property - Specify file name to address index file.
656 * \param addrIndex Address index.
657 * \param value File name.
659 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
660 g_return_if_fail( addrIndex != NULL );
661 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
665 * Property - Specify file path to be used.
666 * \param addrIndex Address index.
667 * \param value Path to JPilot file.
669 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
670 g_return_if_fail( addrIndex != NULL );
671 addrIndex->dirtyFlag = value;
675 * Property - get loaded flag. Note that this flag is set after reading data
676 * from the address books.
677 * \param addrIndex Address index.
678 * \return <i>TRUE</i> if address index data was loaded.
680 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
681 g_return_val_if_fail( addrIndex != NULL, FALSE );
682 return addrIndex->loadedFlag;
686 * Return list of address interfaces.
687 * \param addrIndex Address index.
688 * \return List of address interfaces.
690 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
691 g_return_val_if_fail( addrIndex != NULL, NULL );
692 return addrIndex->interfaceList;
696 * Perform any other initialization of address index.
698 void addrindex_initialize( void ) {
700 addrcompl_initialize();
704 * Perform any other teardown of address index.
706 void addrindex_teardown( void ) {
707 addrcompl_teardown();
712 * Free up address index.
713 * \param addrIndex Address index.
715 void addrindex_free_index( AddressIndex *addrIndex ) {
718 g_return_if_fail( addrIndex != NULL );
721 g_list_free( addrIndex->searchOrder );
722 addrIndex->searchOrder = NULL;
724 /* Free internal storage */
725 g_free( ADDRITEM_ID(addrIndex) );
726 g_free( ADDRITEM_NAME(addrIndex) );
727 g_free( addrIndex->filePath );
728 g_free( addrIndex->fileName );
731 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
732 ADDRITEM_ID(addrIndex) = NULL;
733 ADDRITEM_NAME(addrIndex) = NULL;
734 ADDRITEM_PARENT(addrIndex) = NULL;
735 ADDRITEM_SUBTYPE(addrIndex) = 0;
736 addrIndex->filePath = NULL;
737 addrIndex->fileName = NULL;
738 addrIndex->retVal = MGU_SUCCESS;
739 addrIndex->needsConversion = FALSE;
740 addrIndex->wasConverted = FALSE;
741 addrIndex->conversionError = FALSE;
742 addrIndex->lastType = ADDR_IF_NONE;
743 addrIndex->dirtyFlag = FALSE;
745 /* Free up interfaces */
746 node = addrIndex->interfaceList;
748 AddressInterface *iface = node->data;
749 addrindex_free_interface( iface );
750 node = g_list_next( node );
752 g_list_free( addrIndex->interfaceList );
753 addrIndex->interfaceList = NULL;
755 /* Free up hash cache */
756 addrindex_free_cache_hash( addrIndex->hashCache );
757 addrIndex->hashCache = NULL;
759 addrIndex->loadedFlag = FALSE;
763 _addressIndex_ = NULL;
767 * Print address index.
768 * \param addrIndex Address index.
769 * \parem stream Stream to print.
771 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
772 g_return_if_fail( addrIndex != NULL );
773 fprintf( stream, "AddressIndex:\n" );
774 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
775 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
776 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
777 fprintf( stream, "\tconverted: '%s'\n",
778 addrIndex->wasConverted ? "yes" : "no" );
779 fprintf( stream, "\tcvt error: '%s'\n",
780 addrIndex->conversionError ? "yes" : "no" );
781 fprintf( stream, "\t---\n" );
785 * Retrieve reference to address interface for specified interface type.
786 * \param addrIndex Address index.
787 * \param ifType Interface type.
788 * \return Address interface, or NULL if not found.
790 AddressInterface *addrindex_get_interface(
791 AddressIndex *addrIndex, AddressIfType ifType )
793 AddressInterface *retVal = NULL;
796 g_return_val_if_fail( addrIndex != NULL, NULL );
798 node = addrIndex->interfaceList;
800 AddressInterface *iface = node->data;
801 node = g_list_next( node );
802 if( iface->type == ifType ) {
811 * Add raw data source to index. The raw data object (an AddressBookFile or
812 * VCardFile object, for example) should be supplied as the raw dataSource
815 * \param addrIndex Address index.
816 * \param ifType Interface type to add.
817 * \param dataSource Actual raw data source to add.
818 * \return Data source added, or NULL if invalid interface type.
820 AddressDataSource *addrindex_index_add_datasource(
821 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
823 AddressInterface *iface;
824 AddressDataSource *ds = NULL;
826 g_return_val_if_fail( addrIndex != NULL, NULL );
827 g_return_val_if_fail( dataSource != NULL, NULL );
829 iface = addrindex_get_interface( addrIndex, ifType );
831 ds = addrindex_create_datasource( ifType );
832 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
834 ds->rawDataSource = dataSource;
835 ds->interface = iface;
836 iface->listSource = g_list_append( iface->listSource, ds );
837 addrIndex->dirtyFlag = TRUE;
839 addrindex_hash_add_cache( addrIndex, ds );
845 * Remove specified data source from index.
846 * \param addrIndex Address index.
847 * \param dataSource Data source to add.
848 * \return Reference to data source if removed, or NULL if data source was not
849 * found in index. Note the this object must still be freed.
851 AddressDataSource *addrindex_index_remove_datasource(
852 AddressIndex *addrIndex, AddressDataSource *dataSource )
854 AddressDataSource *retVal = FALSE;
855 AddressInterface *iface;
857 g_return_val_if_fail( addrIndex != NULL, NULL );
858 g_return_val_if_fail( dataSource != NULL, NULL );
860 iface = addrindex_get_interface( addrIndex, dataSource->type );
862 iface->listSource = g_list_remove( iface->listSource, dataSource );
863 addrIndex->dirtyFlag = TRUE;
864 dataSource->interface = NULL;
866 /* Remove cache from hash table */
867 addrindex_hash_remove_cache( addrIndex, dataSource );
875 * Retrieve a reference to address interface for specified interface type and
876 * XML interface tag name.
877 * \param addrIndex Address index.
878 * \param tag XML interface tag name to match.
879 * \param ifType Interface type to match.
880 * \return Reference to address index, or NULL if not found in index.
882 static AddressInterface *addrindex_tag_get_interface(
883 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
885 AddressInterface *retVal = NULL;
886 GList *node = addrIndex->interfaceList;
889 AddressInterface *iface = node->data;
890 node = g_list_next( node );
892 if( strcmp( iface->listTag, tag ) == 0 ) {
898 if( iface->type == ifType ) {
908 * Retrieve a reference to address interface for specified interface type and
909 * XML datasource tag name.
910 * \param addrIndex Address index.
911 * \param ifType Interface type to match.
912 * \param tag XML datasource tag name to match.
913 * \return Reference to address index, or NULL if not found in index.
915 static AddressInterface *addrindex_tag_get_datasource(
916 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
918 AddressInterface *retVal = NULL;
919 GList *node = addrIndex->interfaceList;
922 AddressInterface *iface = node->data;
923 node = g_list_next( node );
924 if( iface->type == ifType && iface->itemTag ) {
925 if( strcmp( iface->itemTag, tag ) == 0 ) {
934 /* **********************************************************************
935 * Interface XML parsing functions.
936 * ***********************************************************************
940 * Write start of XML element to file.
942 * \param lvl Indentation level.
943 * \param name Element name.
945 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
947 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
953 * Write end of XML element to file.
955 * \param lvl Indentation level.
956 * \param name Element name.
958 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
960 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
967 * Write XML attribute to file.
969 * \param name Attribute name.
970 * \param value Attribute value.
972 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
976 xml_file_put_escape_str( fp, value );
981 * Return DOM fragment for current XML tag from file.
982 * \param file XML file being processed.
983 * \return Fragment representing DOM fragment for configuration element.
985 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
986 AddressIfFragment *fragment;
987 AddressIfFragment *child;
997 /* printf( "addrindex_read_fragment\n" ); */
999 prevLevel = file->level;
1001 /* Get current tag name */
1002 xtag = xml_get_current_tag( file );
1004 /* Create new fragment */
1005 fragment = g_new0( AddressIfFragment, 1 );
1006 fragment->name = g_strdup( xtag->tag );
1007 fragment->children = NULL;
1008 fragment->attributes = NULL;
1010 /* Read attributes */
1012 attr = xml_get_current_tag_attr( file );
1014 name = ((XMLAttr *)attr->data)->name;
1015 value = ((XMLAttr *)attr->data)->value;
1016 nv = g_new0( AddressIfAttrib, 1 );
1017 nv->name = g_strdup( name );
1018 nv->value = g_strdup( value );
1019 list = g_list_append( list, nv );
1020 attr = g_list_next( attr );
1022 fragment->attributes = list;
1024 /* Now read the children */
1026 rc = xml_parse_next_tag( file );
1031 if( file->level < prevLevel ) {
1032 /* We must be above level we start at */
1035 child = addrindex_read_fragment( file );
1036 fragment->children = g_list_append( fragment->children, child );
1043 * Write DOM fragment to file.
1044 * \param fp File to write.
1045 * \param fragment DOM fragment for configuration element.
1046 * \param lvl Indent level.
1048 static void addrindex_write_fragment(
1049 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1054 addrindex_write_elem_s( fp, lvl, fragment->name );
1055 node = fragment->attributes;
1057 AddressIfAttrib *nv = node->data;
1058 addrindex_write_attr( fp, nv->name, nv->value );
1059 node = g_list_next( node );
1061 if( fragment->children ) {
1064 /* Output children */
1065 node = fragment->children;
1067 AddressIfFragment *child = node->data;
1068 addrindex_write_fragment( fp, child, 1+lvl );
1069 node = g_list_next( node );
1072 /* Output closing tag */
1073 addrindex_write_elem_e( fp, lvl, fragment->name );
1082 * Read/parse address index file, creating a data source for a regular
1083 * intrinsic XML addressbook.
1084 * \param file Address index file.
1085 * \return Data source.
1087 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1088 AddressDataSource *ds;
1089 AddressBookFile *abf;
1092 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1093 abf = addrbook_create_book();
1094 attr = xml_get_current_tag_attr( file );
1096 gchar *name = ((XMLAttr *)attr->data)->name;
1097 gchar *value = ((XMLAttr *)attr->data)->value;
1098 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1099 addrbook_set_name( abf, value );
1101 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1102 addrbook_set_file( abf, value );
1104 attr = g_list_next( attr );
1106 ds->rawDataSource = abf;
1110 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1111 AddressBookFile *abf = ds->rawDataSource;
1113 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1114 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1115 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1116 fputs( " />\n", fp );
1120 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1121 AddressDataSource *ds;
1125 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1126 vcf = vcard_create();
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_VCARD_NAME ) == 0 ) {
1132 vcard_set_name( vcf, value );
1134 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1135 vcard_set_file( vcf, value );
1137 attr = g_list_next( attr );
1139 ds->rawDataSource = vcf;
1143 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1144 VCardFile *vcf = ds->rawDataSource;
1146 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1147 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1148 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1149 fputs( " />\n", fp );
1154 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1155 AddressDataSource *ds;
1159 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1160 jpf = jpilot_create();
1161 attr = xml_get_current_tag_attr( file );
1163 gchar *name = ((XMLAttr *)attr->data)->name;
1164 gchar *value = ((XMLAttr *)attr->data)->value;
1165 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1166 jpilot_set_name( jpf, value );
1168 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1169 jpilot_set_file( jpf, value );
1171 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1172 jpilot_add_custom_label( jpf, value );
1174 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1175 jpilot_add_custom_label( jpf, value );
1177 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1178 jpilot_add_custom_label( jpf, value );
1180 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1181 jpilot_add_custom_label( jpf, value );
1183 attr = g_list_next( attr );
1185 ds->rawDataSource = jpf;
1189 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1190 JPilotFile *jpf = ds->rawDataSource;
1194 GList *customLbl = jpilot_get_custom_labels( jpf );
1195 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1196 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1197 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1202 g_snprintf( name, sizeof(name), "%s%d",
1203 ATTAG_JPILOT_CUSTOM, ind );
1204 addrindex_write_attr( fp, name, node->data );
1206 node = g_list_next( node );
1208 fputs( " />\n", fp );
1214 * Just read/write DOM fragments (preserve data found in file).
1216 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1217 AddressDataSource *ds;
1219 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1220 ds->rawDataSource = addrindex_read_fragment( file );
1224 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1225 AddressIfFragment *fragment = ds->rawDataSource;
1227 addrindex_write_fragment( fp, fragment, lvl );
1234 * Parse LDAP criteria attribute data from XML file.
1235 * \param file Index file.
1236 * \param ctl LDAP control object to populate.
1238 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1247 if( file == NULL ) {
1252 prevLevel = file->level;
1253 xtagPrev = xml_get_current_tag( file );
1255 rc = xml_parse_next_tag( file );
1257 /* Terminate prematurely */
1258 mgu_free_dlist( list );
1262 if( file->level < prevLevel ) {
1263 /* We must be above level we start at */
1267 /* Get a tag (element) */
1268 xtag = xml_get_current_tag( file );
1269 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1270 /* LDAP criteria attribute */
1271 attr = xml_get_current_tag_attr( file );
1273 gchar *name = ((XMLAttr *)attr->data)->name;
1274 gchar *value = ((XMLAttr *)attr->data)->value;
1275 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1276 if( value && strlen( value ) > 0 ) {
1277 list = g_list_append(
1278 list, g_strdup( value ) );
1281 attr = g_list_next( attr );
1285 if( xtag != xtagPrev ) {
1286 /* Found a new tag */
1293 /* Build list of search attributes */
1294 ldapctl_criteria_list_clear( ctl );
1297 ldapctl_criteria_list_add( ctl, node->data );
1298 g_free( node->data );
1300 node = g_list_next( node );
1302 g_list_free( list );
1307 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1309 * Parse LDAP control data from XML file.
1310 * \param file Index file.
1311 * \return Initialized data soruce object.
1313 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1314 AddressDataSource *ds;
1318 gchar *serverName = NULL;
1319 gchar *criteria = NULL;
1320 gboolean bDynSearch;
1321 gboolean bTLS, bSSL;
1324 /* printf( "addrindex_parse_ldap\n" ); */
1325 /* Set up some defaults */
1329 iMatch = LDAPCTL_MATCH_BEGINWITH;
1331 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1332 ctl = ldapctl_create();
1333 attr = xml_get_current_tag_attr( file );
1335 gchar *name = ((XMLAttr *)attr->data)->name;
1336 gchar *value = ((XMLAttr *)attr->data)->value;
1337 gint ivalue = atoi( value );
1339 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1340 g_free( serverName );
1341 serverName = g_strdup( value );
1343 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1344 ldapctl_set_host( ctl, value );
1346 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1347 ldapctl_set_port( ctl, ivalue );
1349 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1350 ldapctl_set_base_dn( ctl, value );
1352 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1353 ldapctl_set_bind_dn( ctl, value );
1355 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1356 ldapctl_set_bind_password( ctl, value );
1358 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1360 criteria = g_strdup( value );
1362 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1363 ldapctl_set_max_entries( ctl, ivalue );
1365 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1366 ldapctl_set_timeout( ctl, ivalue );
1368 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1369 ldapctl_set_max_query_age( ctl, ivalue );
1371 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1373 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1377 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1378 iMatch = LDAPCTL_MATCH_BEGINWITH;
1379 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1380 iMatch = LDAPCTL_MATCH_CONTAINS;
1383 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1385 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1389 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1391 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1395 attr = g_list_next( attr );
1398 server = ldapsvr_create_noctl();
1399 ldapsvr_set_name( server, serverName );
1400 ldapsvr_set_search_flag( server, bDynSearch );
1401 ldapctl_set_matching_option( ctl, iMatch );
1403 ldapctl_set_tls( ctl, bTLS );
1404 ldapctl_set_ssl( ctl, bSSL );
1406 g_free( serverName );
1407 ldapsvr_set_control( server, ctl );
1408 ds->rawDataSource = server;
1410 addrindex_parse_ldap_attrlist( file, ctl );
1412 * If criteria have been specified and no attributes were listed, then
1413 * convert old style criteria into an attribute list. Any criteria will
1414 * be dropped when saving data.
1417 if( ! ldapctl_get_criteria_list( ctl ) ) {
1418 ldapctl_parse_ldap_search( ctl, criteria );
1422 /* ldapsvr_print_data( server, stdout ); */
1427 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1428 LdapServer *server = ds->rawDataSource;
1429 LdapControl *ctl = NULL;
1434 ctl = server->control;
1436 if( ctl == NULL ) return;
1438 /* Output start element with attributes */
1439 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1440 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1441 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1443 sprintf( value, "%d", ctl->port );
1444 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1446 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1447 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1448 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1450 sprintf( value, "%d", ctl->maxEntries );
1451 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1452 sprintf( value, "%d", ctl->timeOut );
1453 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1454 sprintf( value, "%d", ctl->maxQueryAge );
1455 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1457 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1458 server->searchFlag ?
1459 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1461 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1462 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1463 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1465 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1467 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1468 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1470 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1474 /* Output attributes */
1475 node = ldapctl_get_criteria_list( ctl );
1477 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1478 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1480 node = g_list_next( node );
1483 /* End of element */
1484 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1489 * Just read/write DOM fragments (preserve data found in file).
1491 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1492 AddressDataSource *ds;
1494 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1495 ds->rawDataSource = addrindex_read_fragment( file );
1499 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1500 AddressIfFragment *fragment = ds->rawDataSource;
1502 addrindex_write_fragment( fp, fragment, lvl );
1507 /* **********************************************************************
1508 * Address index I/O functions.
1509 * ***********************************************************************
1512 * Read address index file, creating appropriate data sources for each address
1515 * \param addrIndex Address index.
1516 * \param file Address index file.
1518 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1521 AddressInterface *iface = NULL, *dsIFace = NULL;
1522 AddressDataSource *ds;
1525 addrIndex->loadedFlag = FALSE;
1527 prev_level = file->level;
1528 rc = xml_parse_next_tag( file );
1529 if( file->level == 0 ) return;
1531 xtag = xml_get_current_tag( file );
1533 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1535 addrIndex->lastType = iface->type;
1536 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1539 dsIFace = addrindex_tag_get_datasource(
1540 addrIndex, addrIndex->lastType, xtag->tag );
1542 /* Add data source to list */
1544 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1545 ds = addrindex_parse_book( file );
1546 if( ds->rawDataSource ) {
1547 addrbook_set_path( ds->rawDataSource,
1548 addrIndex->filePath );
1551 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1552 ds = addrindex_parse_vcard( file );
1554 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1555 ds = addrindex_parse_jpilot( file );
1557 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1558 ds = addrindex_parse_ldap( file );
1561 ds->interface = dsIFace;
1562 addrindex_hash_add_cache( addrIndex, ds );
1563 dsIFace->listSource =
1564 g_list_append( dsIFace->listSource, ds );
1572 * Search order sorting comparison function for building search order list.
1574 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1575 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1576 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1578 return ifaceA->searchOrder - ifaceB->searchOrder;
1582 * Build list of data sources to process.
1583 * \param addrIndex Address index object.
1585 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1588 /* Clear existing list */
1589 g_list_free( addrIndex->searchOrder );
1590 addrIndex->searchOrder = NULL;
1592 /* Build new list */
1593 nodeIf = addrIndex->interfaceList;
1595 AddressInterface *iface = nodeIf->data;
1596 if( iface->useInterface ) {
1597 if( iface->searchOrder > 0 ) {
1598 /* Add to search order list */
1599 addrIndex->searchOrder = g_list_insert_sorted(
1600 addrIndex->searchOrder, iface,
1601 addrindex_search_order_compare );
1604 nodeIf = g_list_next( nodeIf );
1608 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1609 XMLFile *file = NULL;
1610 gchar *fileSpec = NULL;
1612 g_return_val_if_fail( addrIndex != NULL, -1 );
1614 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1615 addrIndex->retVal = MGU_NO_FILE;
1616 file = xml_open_file( fileSpec );
1619 if( file == NULL ) {
1621 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1623 return addrIndex->retVal;
1626 addrIndex->retVal = MGU_BAD_FORMAT;
1627 if( xml_get_dtd( file ) == 0 ) {
1628 if( xml_parse_next_tag( file ) == 0 ) {
1629 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1630 addrindex_read_index( addrIndex, file );
1631 addrIndex->retVal = MGU_SUCCESS;
1635 xml_close_file( file );
1637 addrindex_build_search_order( addrIndex );
1639 return addrIndex->retVal;
1642 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1643 GList *nodeIF, *nodeDS;
1645 gint lvlItem = 1 + lvlList;
1647 nodeIF = addrIndex->interfaceList;
1649 AddressInterface *iface = nodeIF->data;
1650 if( ! iface->legacyFlag ) {
1651 nodeDS = iface->listSource;
1652 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1655 AddressDataSource *ds = nodeDS->data;
1657 if( iface->type == ADDR_IF_BOOK ) {
1658 addrindex_write_book( fp, ds, lvlItem );
1660 if( iface->type == ADDR_IF_VCARD ) {
1661 addrindex_write_vcard( fp, ds, lvlItem );
1663 if( iface->type == ADDR_IF_JPILOT ) {
1664 addrindex_write_jpilot( fp, ds, lvlItem );
1666 if( iface->type == ADDR_IF_LDAP ) {
1667 addrindex_write_ldap( fp, ds, lvlItem );
1670 nodeDS = g_list_next( nodeDS );
1672 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1674 nodeIF = g_list_next( nodeIF );
1679 * Write data to specified file.
1680 * Enter: addrIndex Address index object.
1681 * newFile New file name.
1682 * return: Status code, from addrIndex->retVal.
1683 * Note: File will be created in directory specified by addrIndex.
1685 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1688 #ifndef DEV_STANDALONE
1692 g_return_val_if_fail( addrIndex != NULL, -1 );
1694 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1695 addrIndex->retVal = MGU_OPEN_FILE;
1696 #ifdef DEV_STANDALONE
1697 fp = g_fopen( fileSpec, "wb" );
1700 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1702 pfile = prefs_write_open( fileSpec );
1706 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1708 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1711 addrindex_write_index( addrIndex, fp );
1712 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1714 addrIndex->retVal = MGU_SUCCESS;
1715 #ifdef DEV_STANDALONE
1718 if( prefs_file_close( pfile ) < 0 ) {
1719 addrIndex->retVal = MGU_ERROR_WRITE;
1725 return addrIndex->retVal;
1729 * Save address index data to original file.
1730 * return: Status code, from addrIndex->retVal.
1732 gint addrindex_save_data( AddressIndex *addrIndex ) {
1733 g_return_val_if_fail( addrIndex != NULL, -1 );
1735 addrIndex->retVal = MGU_NO_FILE;
1736 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1737 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1739 addrindex_write_to( addrIndex, addrIndex->fileName );
1740 if( addrIndex->retVal == MGU_SUCCESS ) {
1741 addrIndex->dirtyFlag = FALSE;
1743 return addrIndex->retVal;
1747 * Save all address book files which may have changed.
1748 * Return: Status code, set if there was a problem saving data.
1750 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1751 gint retVal = MGU_SUCCESS;
1752 GList *nodeIf, *nodeDS;
1754 nodeIf = addrIndex->interfaceList;
1756 AddressInterface *iface = nodeIf->data;
1757 if( iface->type == ADDR_IF_BOOK ) {
1758 nodeDS = iface->listSource;
1760 AddressDataSource *ds = nodeDS->data;
1761 AddressBookFile *abf = ds->rawDataSource;
1762 if( addrbook_get_dirty( abf ) ) {
1763 if( addrbook_get_read_flag( abf ) ) {
1764 addrbook_save_data( abf );
1765 if( abf->retVal != MGU_SUCCESS ) {
1766 retVal = abf->retVal;
1770 nodeDS = g_list_next( nodeDS );
1774 nodeIf = g_list_next( nodeIf );
1780 /* **********************************************************************
1781 * Address book conversion to new format.
1782 * ***********************************************************************
1785 #define ELTAG_IF_OLD_FOLDER "folder"
1786 #define ELTAG_IF_OLD_GROUP "group"
1787 #define ELTAG_IF_OLD_ITEM "item"
1788 #define ELTAG_IF_OLD_NAME "name"
1789 #define ELTAG_IF_OLD_ADDRESS "address"
1790 #define ELTAG_IF_OLD_REMARKS "remarks"
1791 #define ATTAG_IF_OLD_NAME "name"
1793 #define TEMPNODE_ROOT 0
1794 #define TEMPNODE_FOLDER 1
1795 #define TEMPNODE_GROUP 2
1796 #define TEMPNODE_ADDRESS 3
1798 typedef struct _AddressCvt_Node AddressCvtNode;
1799 struct _AddressCvt_Node {
1808 * Parse current address item.
1810 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1815 nn = g_new0( AddressCvtNode, 1 );
1816 nn->type = TEMPNODE_ADDRESS;
1819 level = file->level;
1822 xml_parse_next_tag(file);
1823 if (file->level < level) return nn;
1825 element = xml_get_element( file );
1826 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1827 nn->name = g_strdup( element );
1829 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1830 nn->address = g_strdup( element );
1832 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1833 nn->remarks = g_strdup( element );
1836 xml_parse_next_tag(file);
1841 * Create a temporary node below specified node.
1843 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1845 nn = g_new0( AddressCvtNode, 1 );
1847 nn->name = g_strdup( name );
1848 nn->remarks = g_strdup( rem );
1849 node->list = g_list_append( node->list, nn );
1854 * Process current temporary node.
1856 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1859 AddressCvtNode *newNode = NULL;
1864 prev_level = file->level;
1865 xml_parse_next_tag( file );
1866 if (file->level < prev_level) return;
1870 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1871 attr = xml_get_current_tag_attr(file);
1873 name = ((XMLAttr *)attr->data)->name;
1874 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1875 value = ((XMLAttr *)attr->data)->value;
1878 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1879 addrindex_add_obj( file, newNode );
1882 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1883 attr = xml_get_current_tag_attr(file);
1885 name = ((XMLAttr *)attr->data)->name;
1886 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1887 value = ((XMLAttr *)attr->data)->value;
1890 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1891 addrindex_add_obj( file, newNode );
1893 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1894 newNode = addrindex_parse_item( file );
1895 node->list = g_list_append( node->list, newNode );
1898 /* printf( "invalid: !!! \n" ); */
1899 attr = xml_get_current_tag_attr( file );
1905 * Consume all nodes below current tag.
1907 static void addrindex_consume_tree( XMLFile *file ) {
1914 prev_level = file->level;
1915 xml_parse_next_tag( file );
1916 if (file->level < prev_level) return;
1918 xtag = xml_get_current_tag( file );
1919 /* printf( "tag : %s\n", xtag->tag ); */
1920 element = xml_get_element( file );
1921 attr = xml_get_current_tag_attr( file );
1922 /* show_attribs( attr ); */
1923 /* printf( "\ttag value : %s :\n", element ); */
1924 addrindex_consume_tree( file );
1929 * Print temporary tree.
1931 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1934 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1935 fprintf( stream, "\tname :%s:\n", node->name );
1936 fprintf( stream, "\taddr :%s:\n", node->address );
1937 fprintf( stream, "\trems :%s:\n", node->remarks );
1939 fprintf( stream, "\t--list----\n" );
1943 AddressCvtNode *lNode = list->data;
1944 list = g_list_next( list );
1945 addrindex_print_node( lNode, stream );
1947 fprintf( stream, "\t==list-%d==\n", node->type );
1951 * Free up temporary tree.
1953 static void addrindex_free_node( AddressCvtNode *node ) {
1954 GList *list = node->list;
1957 AddressCvtNode *lNode = list->data;
1958 list = g_list_next( list );
1959 addrindex_free_node( lNode );
1961 node->type = TEMPNODE_ROOT;
1962 g_free( node->name );
1963 g_free( node->address );
1964 g_free( node->remarks );
1965 g_list_free( node->list );
1970 * Process address book for specified node.
1972 static void addrindex_process_node(
1973 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1974 ItemGroup *parentGrp, ItemFolder *folderGrp )
1977 ItemFolder *itemFolder = NULL;
1978 ItemGroup *itemGParent = parentGrp;
1979 ItemFolder *itemGFolder = folderGrp;
1980 AddressCache *cache = abf->addressCache;
1982 if( node->type == TEMPNODE_ROOT ) {
1983 itemFolder = parent;
1985 else if( node->type == TEMPNODE_FOLDER ) {
1986 itemFolder = addritem_create_item_folder();
1987 addritem_folder_set_name( itemFolder, node->name );
1988 addrcache_id_folder( cache, itemFolder );
1989 addrcache_folder_add_folder( cache, parent, itemFolder );
1992 else if( node->type == TEMPNODE_GROUP ) {
1993 ItemGroup *itemGroup;
1996 /* Create a folder for group */
1997 fName = g_strdup_printf( "Cvt - %s", node->name );
1998 itemGFolder = addritem_create_item_folder();
1999 addritem_folder_set_name( itemGFolder, fName );
2000 addrcache_id_folder( cache, itemGFolder );
2001 addrcache_folder_add_folder( cache, parent, itemGFolder );
2004 /* Add group into folder */
2005 itemGroup = addritem_create_item_group();
2006 addritem_group_set_name( itemGroup, node->name );
2007 addrcache_id_group( cache, itemGroup );
2008 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2009 itemGParent = itemGroup;
2011 else if( node->type == TEMPNODE_ADDRESS ) {
2012 ItemPerson *itemPerson;
2013 ItemEMail *itemEMail;
2015 /* Create person and email objects */
2016 itemPerson = addritem_create_item_person();
2017 addritem_person_set_common_name( itemPerson, node->name );
2018 addrcache_id_person( cache, itemPerson );
2019 itemEMail = addritem_create_item_email();
2020 addritem_email_set_address( itemEMail, node->address );
2021 addritem_email_set_remarks( itemEMail, node->remarks );
2022 addrcache_id_email( cache, itemEMail );
2023 addrcache_person_add_email( cache, itemPerson, itemEMail );
2025 /* Add person into appropriate folder */
2027 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2030 addrcache_folder_add_person( cache, parent, itemPerson );
2033 /* Add email address only into group */
2035 addrcache_group_add_email( cache, parentGrp, itemEMail );
2041 AddressCvtNode *lNode = list->data;
2042 list = g_list_next( list );
2043 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2048 * Process address book to specified file number.
2050 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2051 gboolean retVal = FALSE;
2052 AddressBookFile *abf = NULL;
2053 AddressCvtNode *rootNode = NULL;
2054 gchar *newFile = NULL;
2055 GList *fileList = NULL;
2058 /* Setup root node */
2059 rootNode = g_new0( AddressCvtNode, 1 );
2060 rootNode->type = TEMPNODE_ROOT;
2061 rootNode->name = g_strdup( "root" );
2062 rootNode->list = NULL;
2063 addrindex_add_obj( file, rootNode );
2064 /* addrindex_print_node( rootNode, stdout ); */
2066 /* Create new address book */
2067 abf = addrbook_create_book();
2068 addrbook_set_name( abf, displayName );
2069 addrbook_set_path( abf, addrIndex->filePath );
2071 /* Determine next available file number */
2072 fileList = addrbook_get_bookfile_list( abf );
2074 fileNum = 1 + abf->maxValue;
2076 g_list_free( fileList );
2079 newFile = addrbook_gen_new_file_name( fileNum );
2081 addrbook_set_file( abf, newFile );
2084 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2086 /* addrbook_dump_book( abf, stdout ); */
2087 addrbook_save_data( abf );
2088 addrIndex->retVal = abf->retVal;
2089 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2091 addrbook_free_book( abf );
2093 addrindex_free_node( rootNode );
2096 /* Create entries in address index */
2098 abf = addrbook_create_book();
2099 addrbook_set_name( abf, displayName );
2100 addrbook_set_path( abf, addrIndex->filePath );
2101 addrbook_set_file( abf, newFile );
2102 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2109 * Process tree converting data.
2111 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2119 prev_level = file->level;
2120 xml_parse_next_tag( file );
2121 if (file->level < prev_level) return;
2123 xtag = xml_get_current_tag( file );
2124 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2125 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2126 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2127 addrIndex->needsConversion = FALSE;
2128 addrIndex->wasConverted = TRUE;
2133 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2134 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2135 addrIndex->needsConversion = FALSE;
2136 addrIndex->wasConverted = TRUE;
2141 element = xml_get_element( file );
2142 attr = xml_get_current_tag_attr( file );
2143 /* show_attribs( attr ); */
2144 /* printf( "\ttag value : %s :\n", element ); */
2145 addrindex_consume_tree( file );
2149 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2150 XMLFile *file = NULL;
2153 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2154 addrIndex->retVal = MGU_NO_FILE;
2155 file = xml_open_file( fileSpec );
2158 if( file == NULL ) {
2159 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2160 return addrIndex->retVal;
2163 addrIndex->retVal = MGU_BAD_FORMAT;
2164 if( xml_get_dtd( file ) == 0 ) {
2165 if( xml_parse_next_tag( file ) == 0 ) {
2166 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2167 addrindex_convert_tree( addrIndex, file );
2171 xml_close_file( file );
2172 return addrIndex->retVal;
2176 * Create a new address book file.
2178 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2179 gboolean retVal = FALSE;
2180 AddressBookFile *abf = NULL;
2181 gchar *newFile = NULL;
2182 GList *fileList = NULL;
2185 /* Create new address book */
2186 abf = addrbook_create_book();
2187 addrbook_set_name( abf, displayName );
2188 addrbook_set_path( abf, addrIndex->filePath );
2190 /* Determine next available file number */
2191 fileList = addrbook_get_bookfile_list( abf );
2193 fileNum = 1 + abf->maxValue;
2195 g_list_free( fileList );
2198 newFile = addrbook_gen_new_file_name( fileNum );
2200 addrbook_set_file( abf, newFile );
2203 addrbook_save_data( abf );
2204 addrIndex->retVal = abf->retVal;
2205 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2206 addrbook_free_book( abf );
2209 /* Create entries in address index */
2211 abf = addrbook_create_book();
2212 addrbook_set_name( abf, displayName );
2213 addrbook_set_path( abf, addrIndex->filePath );
2214 addrbook_set_file( abf, newFile );
2215 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2222 * Read data for address index performing a conversion if necesary.
2223 * Enter: addrIndex Address index object.
2224 * return: Status code, from addrIndex->retVal.
2225 * Note: New address book files will be created in directory specified by
2226 * addrIndex. Three files will be created, for the following:
2227 * "Common addresses"
2228 * "Personal addresses"
2229 * "Gathered addresses" - a new address book.
2231 gint addrindex_read_data( AddressIndex *addrIndex ) {
2232 g_return_val_if_fail( addrIndex != NULL, -1 );
2234 addrIndex->conversionError = FALSE;
2235 addrindex_read_file( addrIndex );
2236 if( addrIndex->retVal == MGU_SUCCESS ) {
2237 if( addrIndex->needsConversion ) {
2238 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2239 addrIndex->conversionError = TRUE;
2242 addrIndex->conversionError = TRUE;
2245 addrIndex->dirtyFlag = TRUE;
2247 return addrIndex->retVal;
2251 * Create new address books for a new address index.
2252 * Enter: addrIndex Address index object.
2253 * return: Status code, from addrIndex->retVal.
2254 * Note: New address book files will be created in directory specified by
2255 * addrIndex. Three files will be created, for the following:
2256 * "Common addresses"
2257 * "Personal addresses"
2258 * "Gathered addresses" - a new address book.
2260 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2263 g_return_val_if_fail( addrIndex != NULL, -1 );
2265 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2267 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2268 addrIndex->dirtyFlag = TRUE;
2270 return addrIndex->retVal;
2273 /* **********************************************************************
2274 * New interface stuff.
2275 * ***********************************************************************
2279 * Return modified flag for specified data source.
2281 gboolean addrindex_ds_get_modify_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->getModifyFlag ) {
2289 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2295 * Return accessed flag for specified data source.
2297 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2298 gboolean retVal = FALSE;
2299 AddressInterface *iface;
2301 if( ds == NULL ) return retVal;
2302 iface = ds->interface;
2303 if( iface == NULL ) return retVal;
2304 if( iface->getAccessFlag ) {
2305 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2311 * Return data read flag for specified data source.
2313 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2314 gboolean retVal = TRUE;
2315 AddressInterface *iface;
2317 if( ds == NULL ) return retVal;
2318 iface = ds->interface;
2319 if( iface == NULL ) return retVal;
2320 if( iface->getReadFlag ) {
2321 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2327 * Return status code for specified data source.
2329 gint addrindex_ds_get_status_code( 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->getStatusCode ) {
2337 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2343 * Return data read flag for specified data source.
2345 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2346 gint retVal = MGU_SUCCESS;
2347 AddressInterface *iface;
2349 if( ds == NULL ) return retVal;
2350 iface = ds->interface;
2351 if( iface == NULL ) return retVal;
2352 if( iface->getReadData ) {
2354 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2355 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2357 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2363 * Return data read flag for specified data source.
2365 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2366 ItemFolder *retVal = NULL;
2367 AddressInterface *iface;
2369 if( ds == NULL ) return retVal;
2370 iface = ds->interface;
2371 if( iface == NULL ) return retVal;
2372 if( iface->getRootFolder ) {
2373 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2379 * Return list of folders for specified data source.
2381 GList *addrindex_ds_get_list_folder( 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->getListFolder ) {
2389 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2395 * Return list of persons in root folder for specified data source.
2397 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2398 GList *retVal = FALSE;
2399 AddressInterface *iface;
2401 if( ds == NULL ) return retVal;
2402 iface = ds->interface;
2403 if( iface == NULL ) return retVal;
2404 if( iface->getListPerson ) {
2405 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2411 * Return name for specified data source.
2413 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2414 gchar *retVal = FALSE;
2415 AddressInterface *iface;
2417 if( ds == NULL ) return retVal;
2418 iface = ds->interface;
2419 if( iface == NULL ) return retVal;
2420 if( iface->getName ) {
2421 retVal = ( iface->getName ) ( ds->rawDataSource );
2427 * Set the access flag inside the data source.
2429 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2430 AddressInterface *iface;
2432 if( ds == NULL ) return;
2433 iface = ds->interface;
2434 if( iface == NULL ) return;
2435 if( iface->setAccessFlag ) {
2436 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2441 * Return read only flag for specified data source.
2443 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2444 AddressInterface *iface;
2445 if( ds == NULL ) return TRUE;
2446 iface = ds->interface;
2447 if( iface == NULL ) return TRUE;
2448 return iface->readOnly;
2452 * Return list of all persons for specified data source.
2454 GList *addrindex_ds_get_all_persons( 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->getAllPersons ) {
2462 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2468 * Return list of all groups for specified data source.
2470 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2471 GList *retVal = NULL;
2472 AddressInterface *iface;
2474 if( ds == NULL ) return retVal;
2475 iface = ds->interface;
2476 if( iface == NULL ) return retVal;
2477 if( iface->getAllGroups ) {
2478 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2483 /* **********************************************************************
2484 * Address search stuff.
2485 * ***********************************************************************
2489 * Setup or register the dynamic search that will be performed. The search
2490 * is registered with the query manager.
2492 * \param searchTerm Search term. A private copy will be made.
2493 * \param callBackEntry Callback function that should be called when
2494 * each entry is received.
2495 * \param callBackEnd Callback function that should be called when
2496 * search has finished running.
2497 * \return ID allocated to query that will be executed.
2499 gint addrindex_setup_search(
2500 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2505 /* Set up a dynamic address query */
2506 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2507 queryID = req->queryID;
2508 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2510 /* printf( "***> query ID ::%d::\n", queryID ); */
2517 * Function prototypes (not in header file or circular reference errors are
2520 LdapQuery *ldapsvr_new_dynamic_search(
2521 LdapServer *server, QueryRequest *req );
2522 LdapQuery *ldapsvr_new_explicit_search(
2523 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2524 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2529 * Execute the previously registered dynamic search.
2531 * \param req Address query object to execute.
2532 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2535 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2536 AddressInterface *iface;
2537 AddressDataSource *ds;
2542 /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2543 nodeIf = _addressIndex_->searchOrder;
2545 iface = nodeIf->data;
2546 nodeIf = g_list_next( nodeIf );
2548 if( ! iface->useInterface ) {
2551 if( ! iface->externalQuery ) {
2556 nodeDS = iface->listSource;
2559 nodeDS = g_list_next( nodeDS );
2561 if( type == ADDR_IF_LDAP ) {
2565 server = ds->rawDataSource;
2566 if( ! server->searchFlag ) {
2569 if( ldapsvr_reuse_previous( server, req ) ) {
2573 /* Start a new dynamic search */
2574 qry = ldapsvr_new_dynamic_search( server, req );
2576 ldapsvr_execute_query( server, qry );
2586 * Stop the previously registered search.
2588 * \param queryID ID of search query to stop.
2590 void addrindex_stop_search( const gint queryID ){
2592 AddrQueryObject *aqo;
2595 /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
2596 /* If query ID does not match, search has not been setup */
2597 req = qrymgr_find_request( queryID );
2602 /* Stop all queries that were associated with request */
2603 node = req->queryList;
2607 if( aqo->queryType == ADDRQUERY_LDAP ) {
2608 LdapQuery *qry = ( LdapQuery * ) aqo;
2609 ldapqry_set_stop_flag( qry, TRUE );
2613 node = g_list_next( node );
2616 /* Delete query request */
2617 qrymgr_delete_request( queryID );
2621 * Setup or register the explicit search that will be performed. The search is
2622 * registered with the query manager.
2624 * \param ds Data source to search.
2625 * \param searchTerm Search term to locate.
2626 * \param folder Folder to receive search results; may be NULL.
2627 * \param callbackEnd Function to call when search has terminated.
2628 * \param callbackEntry Function to called for each entry processed.
2629 * \return ID allocated to query that will be executed.
2631 gint addrindex_setup_explicit_search(
2632 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2633 void *callBackEnd, void *callBackEntry )
2640 /* Name the query */
2641 name = g_strdup_printf( "Search '%s'", searchTerm );
2643 /* Set up query request */
2644 if (!strcmp(searchTerm, "*"))
2645 mySearch = g_strdup("*@");
2647 mySearch = g_strdup(searchTerm);
2649 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2653 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2654 queryID = req->queryID;
2656 if( ds->type == ADDR_IF_LDAP ) {
2660 server = ds->rawDataSource;
2661 ldapsvr_new_explicit_search( server, req, folder );
2665 qrymgr_delete_request( queryID );
2674 * Execute the previously registered explicit search.
2676 * \param req Address query request object to execute.
2677 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2680 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2682 AddrQueryObject *aqo;
2686 /* Note: there should only be one query in the list. */
2687 aqo = req->queryList->data;
2689 if( aqo->queryType == ADDRQUERY_LDAP ) {
2693 qry = ( LdapQuery * ) aqo;
2694 server = qry->server;
2696 /* Start the search */
2698 ldapsvr_execute_query( server, qry );
2705 * Start the previously registered search.
2707 * \param queryID ID of search query to be executed.
2708 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2711 gboolean addrindex_start_search( const gint queryID ) {
2714 AddrSearchType searchType;
2717 /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
2718 req = qrymgr_find_request( queryID );
2723 searchType = req->searchType;
2724 if( searchType == ADDRSEARCH_DYNAMIC ) {
2725 retVal = addrindex_start_dynamic( req );
2727 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2728 retVal = addrindex_start_explicit( req );
2735 * Remove results (folder and data) for specified data source and folder.
2736 * \param ds Data source to process.
2737 * \param folder Results folder to remove.
2739 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2740 AddrBookBase *adbase;
2741 AddressCache *cache;
2744 /* printf( "addrindex_remove_results/start\n" ); */
2746 /* Test for folder */
2747 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2748 /* printf( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2749 adbase = ( AddrBookBase * ) ds->rawDataSource;
2750 if( adbase == NULL ) return;
2751 cache = adbase->addressCache;
2753 /* Hide folder to prevent re-display */
2754 addritem_folder_set_hidden( folder, TRUE );
2756 if( ds->type == ADDR_IF_LDAP ) {
2761 qry = ( LdapQuery * ) folder->folderData;
2762 queryID = ADDRQUERY_ID(qry);
2763 /* printf( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2764 delFlag = ldapquery_remove_results( qry );
2766 ldapqry_free( qry );
2768 /* printf( "calling ldapquery_remove_results...done\n" ); */
2771 printf( "delFlag IS-TRUE\n" );
2774 printf( "delFlag IS-FALSE\n" );
2775 addressbook_clear_idler( queryID );
2780 /* printf( "addrindex_remove_results/end\n" ); */
2782 /* Delete query request */
2784 qrymgr_delete_request( queryID );
2788 /* **********************************************************************
2789 * Address completion stuff.
2790 * ***********************************************************************
2793 static void addrindex_load_completion_load_persons(
2794 gint (*callBackFunc) ( const gchar *, const gchar *,
2795 const gchar *, const gchar *, GList * ),
2796 AddressDataSource *ds)
2798 GList *listP, *nodeP;
2802 /* Read address book */
2803 if( addrindex_ds_get_modify_flag( ds ) ) {
2804 addrindex_ds_read_data( ds );
2807 if( ! addrindex_ds_get_read_flag( ds ) ) {
2808 addrindex_ds_read_data( ds );
2811 /* Get all groups */
2812 listP = addrindex_ds_get_all_groups( ds );
2815 ItemGroup *group = nodeP->data;
2816 GList *emails = NULL;
2817 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2818 ItemEMail *email = nodeM->data;
2820 emails = g_list_append(emails, email);
2822 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2823 NULL, NULL, emails );
2824 nodeP = g_list_next( nodeP );
2827 /* Free up the list */
2828 g_list_free( listP );
2829 /* Get all persons */
2830 listP = addrindex_ds_get_all_persons( ds );
2833 ItemPerson *person = nodeP->data;
2834 nodeM = person->listEMail;
2836 /* Figure out name to use */
2837 sName = ADDRITEM_NAME(person);
2838 if( sName == NULL || *sName == '\0' ) {
2839 sName = person->nickName;
2842 /* Process each E-Mail address */
2844 ItemEMail *email = nodeM->data;
2846 callBackFunc( sName, email->address, person->nickName,
2847 ADDRITEM_NAME(email), NULL );
2849 nodeM = g_list_next( nodeM );
2851 nodeP = g_list_next( nodeP );
2854 /* Free up the list */
2855 g_list_free( listP );
2859 * This function is used by the address completion function to load
2860 * addresses for all non-external address book interfaces.
2862 * \param callBackFunc Function to be called when an address is
2864 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2865 * or "Any", assume the whole addressbook
2866 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2869 gboolean addrindex_load_completion(
2870 gint (*callBackFunc) ( const gchar *, const gchar *,
2871 const gchar *, const gchar *, GList * ),
2874 GList *nodeIf, *nodeDS;
2876 if( folderpath != NULL ) {
2877 AddressDataSource *book;
2880 /* split the folder path we've received, we'll try to match this path, subpath by
2881 subpath against the book/folder structure in order and restrict loading of
2882 addresses to that subpart (if matches). book/folder path must exist and
2883 folderpath must not be empty or NULL */
2885 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2886 g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath);
2890 if( book != NULL ) {
2891 AddressBookFile *abf = book->rawDataSource;
2893 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf->fileName);
2895 addrindex_load_completion_load_persons( callBackFunc, book );
2901 if( folder != NULL ) {
2907 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2909 /* Load email addresses */
2910 items = addritem_folder_get_person_list( folder );
2911 for( ; items != NULL; items = g_list_next( items ) ) {
2912 person = items->data;
2913 nodeM = person->listEMail;
2915 /* Figure out name to use */
2916 sName = ADDRITEM_NAME(person);
2917 if( sName == NULL || *sName == '\0' ) {
2918 sName = person->nickName;
2921 /* Process each E-Mail address */
2923 ItemEMail *email = nodeM->data;
2925 callBackFunc( sName, email->address, person->nickName,
2926 ADDRITEM_NAME(email), NULL );
2928 nodeM = g_list_next( nodeM );
2931 /* Free up the list */
2932 mgu_clear_list( items );
2933 g_list_free( items );
2938 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
2945 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2947 AddressInterface *iface = nodeIf->data;
2949 nodeIf = g_list_next( nodeIf );
2951 if( ! iface->useInterface || iface->externalQuery )
2954 nodeDS = iface->listSource;
2956 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
2957 nodeDS = g_list_next( nodeDS );
2966 * This function can be used to collect information about
2967 * addressbook entries that contain a specific attribute.
2969 * \param attr Name of attribute to look for
2970 * \param callBackFunc Function to be called when a matching attribute was found
2971 * \return <i>TRUE</i>
2973 gboolean addrindex_load_person_attribute(
2975 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2977 AddressDataSource *ds;
2978 GList *nodeIf, *nodeDS;
2979 GList *listP, *nodeP;
2982 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2985 AddressInterface *iface = nodeIf->data;
2987 nodeIf = g_list_next( nodeIf );
2989 if( ! iface->useInterface || iface->externalQuery )
2992 nodeDS = iface->listSource;
2996 /* Read address book */
2997 if( addrindex_ds_get_modify_flag( ds ) ) {
2998 addrindex_ds_read_data( ds );
3001 if( ! addrindex_ds_get_read_flag( ds ) ) {
3002 addrindex_ds_read_data( ds );
3005 /* Check addressbook name */
3006 cur_bname = addrindex_ds_get_name( ds );
3008 /* Get all persons */
3009 listP = addrindex_ds_get_all_persons( ds );
3012 ItemPerson *person = nodeP->data;
3014 /* Return all ItemPerson's if attr is NULL */
3015 if( attr == NULL ) {
3016 callBackFunc(person, cur_bname);
3019 /* Return ItemPerson's with specific attribute */
3021 nodeA = person->listAttrib;
3022 /* Process each User Attribute */
3024 UserAttribute *attrib = nodeA->data;
3026 !strcmp( attrib->name,attr ) ) {
3027 callBackFunc(person, cur_bname);
3029 nodeA = g_list_next( nodeA );
3032 nodeP = g_list_next( nodeP );
3034 /* Free up the list */
3035 g_list_free( listP );
3037 nodeDS = g_list_next( nodeDS );