2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2007 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 {
140 static AddressDataSource *addrindex_create_datasource ( AddressIfType ifType );
142 static GList *addrindex_ds_get_all_persons ( AddressDataSource *ds );
143 static GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
144 static AddressDataSource *addrindex_get_datasource ( AddressIndex *addrIndex,
145 const gchar *cacheID );
146 static AddressInterface *addrindex_get_interface ( AddressIndex *addrIndex,
147 AddressIfType ifType );
148 static gint addrindex_write_to ( AddressIndex *addrIndex,
149 const gchar *newFile );
152 * Define DOM fragment.
154 typedef struct _AddressIfFrag AddressIfFragment;
155 struct _AddressIfFrag {
162 * Build interface with default values.
164 * \param type Interface type.
165 * \param name Interface name.
166 * \param tagIf XML tag name for interface in address index file.
167 * \param tagDS XML tag name for datasource in address index file.
168 * \return Address interface object.
170 static AddressInterface *addrindex_create_interface(
171 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
173 AddressInterface *iface = g_new0( AddressInterface, 1 );
175 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
176 ADDRITEM_ID(iface) = NULL;
177 ADDRITEM_NAME(iface) = g_strdup( name );
178 ADDRITEM_PARENT(iface) = NULL;
179 ADDRITEM_SUBTYPE(iface) = type;
181 iface->name = g_strdup( name );
182 iface->listTag = g_strdup( tagIf );
183 iface->itemTag = g_strdup( tagDS );
184 iface->legacyFlag = FALSE;
185 iface->haveLibrary = TRUE;
186 iface->useInterface = TRUE;
187 iface->readOnly = TRUE;
189 /* Set callbacks to NULL values - override for each interface */
190 iface->getAccessFlag = NULL;
191 iface->getModifyFlag = NULL;
192 iface->getReadFlag = NULL;
193 iface->getStatusCode = NULL;
194 iface->getReadData = NULL;
195 iface->getRootFolder = NULL;
196 iface->getListFolder = NULL;
197 iface->getListPerson = NULL;
198 iface->getAllPersons = NULL;
199 iface->getAllGroups = NULL;
200 iface->getName = NULL;
201 iface->listSource = NULL;
204 iface->externalQuery = FALSE;
205 iface->searchOrder = 0; /* Ignored */
206 iface->startSearch = NULL;
207 iface->stopSearch = NULL;
213 * Build table of of all address book interfaces.
214 * \param addrIndex Address index object.
216 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
217 AddressInterface *iface;
219 /* Create intrinsic XML address book interface */
220 iface = addrindex_create_interface(
221 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
222 TAG_DS_ADDRESS_BOOK );
223 iface->readOnly = FALSE;
224 iface->getModifyFlag = ( void * ) addrbook_get_modified;
225 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
226 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
227 iface->getStatusCode = ( void * ) addrbook_get_status;
228 iface->getReadData = ( void * ) addrbook_read_data;
229 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
230 iface->getListFolder = ( void * ) addrbook_get_list_folder;
231 iface->getListPerson = ( void * ) addrbook_get_list_person;
232 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
233 iface->getAllGroups = ( void * ) addrbook_get_all_groups;
234 iface->getName = ( void * ) addrbook_get_name;
235 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
236 iface->searchOrder = 0;
238 /* Add to list of interfaces in address book */
239 addrIndex->interfaceList =
240 g_list_append( addrIndex->interfaceList, iface );
241 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
243 /* Create vCard interface */
244 iface = addrindex_create_interface(
245 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
246 iface->getModifyFlag = ( void * ) vcard_get_modified;
247 iface->getAccessFlag = ( void * ) vcard_get_accessed;
248 iface->getReadFlag = ( void * ) vcard_get_read_flag;
249 iface->getStatusCode = ( void * ) vcard_get_status;
250 iface->getReadData = ( void * ) vcard_read_data;
251 iface->getRootFolder = ( void * ) vcard_get_root_folder;
252 iface->getListFolder = ( void * ) vcard_get_list_folder;
253 iface->getListPerson = ( void * ) vcard_get_list_person;
254 iface->getAllPersons = ( void * ) vcard_get_all_persons;
255 iface->getName = ( void * ) vcard_get_name;
256 iface->setAccessFlag = ( void * ) vcard_set_accessed;
257 iface->searchOrder = 0;
258 addrIndex->interfaceList =
259 g_list_append( addrIndex->interfaceList, iface );
260 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
262 /* Create JPilot interface */
263 iface = addrindex_create_interface(
264 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
267 iface->haveLibrary = jpilot_test_pilot_lib();
268 iface->useInterface = iface->haveLibrary;
269 iface->getModifyFlag = ( void * ) jpilot_get_modified;
270 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
271 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
272 iface->getStatusCode = ( void * ) jpilot_get_status;
273 iface->getReadData = ( void * ) jpilot_read_data;
274 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
275 iface->getListFolder = ( void * ) jpilot_get_list_folder;
276 iface->getListPerson = ( void * ) jpilot_get_list_person;
277 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
278 iface->getName = ( void * ) jpilot_get_name;
279 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
280 iface->searchOrder = 0;
282 iface->useInterface = FALSE;
283 iface->haveLibrary = FALSE;
285 addrIndex->interfaceList =
286 g_list_append( addrIndex->interfaceList, iface );
287 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
289 /* Create LDAP interface */
290 iface = addrindex_create_interface(
291 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
293 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
294 iface->haveLibrary = ldaputil_test_ldap_lib();
295 iface->useInterface = iface->haveLibrary;
296 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
297 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
298 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
299 iface->getStatusCode = ( void * ) ldapsvr_get_status;
300 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
301 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
302 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
303 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
304 iface->getName = ( void * ) ldapsvr_get_name;
305 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
306 iface->externalQuery = TRUE;
307 iface->searchOrder = 1;
309 iface->useInterface = FALSE;
310 iface->haveLibrary = FALSE;
312 addrIndex->interfaceList =
313 g_list_append( addrIndex->interfaceList, iface );
314 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
316 /* Two old legacy data sources (pre 0.7.0) */
317 iface = addrindex_create_interface(
318 ADDR_IF_COMMON, "Old Address - common",
319 TAG_IF_OLD_COMMON, NULL );
320 iface->legacyFlag = TRUE;
321 addrIndex->interfaceList =
322 g_list_append( addrIndex->interfaceList, iface );
323 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
325 iface = addrindex_create_interface(
326 ADDR_IF_COMMON, "Old Address - personal",
327 TAG_IF_OLD_PERSONAL, NULL );
328 iface->legacyFlag = TRUE;
329 addrIndex->interfaceList =
330 g_list_append( addrIndex->interfaceList, iface );
331 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
337 * \param fragment Fragment to free.
339 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
343 node = fragment->children;
345 AddressIfFragment *child = node->data;
346 addrindex_free_fragment( child );
348 node = g_list_next( node );
350 g_list_free( fragment->children );
352 /* Free attributes */
353 node = fragment->attributes;
355 AddressIfAttrib *nv = node->data;
360 node = g_list_next( node );
362 g_list_free( fragment->attributes );
364 g_free( fragment->name );
365 fragment->name = NULL;
366 fragment->attributes = NULL;
367 fragment->children = NULL;
373 * Create a new data source.
374 * \param ifType Interface type to create.
375 * \return Initialized data source.
377 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
378 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
380 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
381 ADDRITEM_ID(ds) = NULL;
382 ADDRITEM_NAME(ds) = NULL;
383 ADDRITEM_PARENT(ds) = NULL;
384 ADDRITEM_SUBTYPE(ds) = 0;
386 ds->rawDataSource = NULL;
387 ds->interface = NULL;
392 * Free up data source.
393 * \param ds Data source to free.
395 void addrindex_free_datasource( AddressDataSource *ds ) {
396 AddressInterface *iface;
398 g_return_if_fail( ds != NULL );
400 iface = ds->interface;
401 if( ds->rawDataSource != NULL ) {
402 if( iface != NULL ) {
403 if( iface->useInterface ) {
404 if( iface->type == ADDR_IF_BOOK ) {
405 AddressBookFile *abf = ds->rawDataSource;
406 addrbook_free_book( abf );
408 else if( iface->type == ADDR_IF_VCARD ) {
409 VCardFile *vcf = ds->rawDataSource;
413 else if( iface->type == ADDR_IF_JPILOT ) {
414 JPilotFile *jpf = ds->rawDataSource;
419 else if( iface->type == ADDR_IF_LDAP ) {
420 LdapServer *server = ds->rawDataSource;
421 ldapsvr_free( server );
428 AddressIfFragment *fragment = ds->rawDataSource;
429 addrindex_free_fragment( fragment );
434 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
435 ADDRITEM_ID(ds) = NULL;
436 ADDRITEM_NAME(ds) = NULL;
437 ADDRITEM_PARENT(ds) = NULL;
438 ADDRITEM_SUBTYPE(ds) = 0;
439 ds->type = ADDR_IF_NONE;
440 ds->interface = NULL;
441 ds->rawDataSource = NULL;
447 * Free up all data sources for specified interface.
448 * \param iface Address interface to process.
450 static void addrindex_free_all_datasources( AddressInterface *iface ) {
451 GList *node = iface->listSource;
453 AddressDataSource *ds = node->data;
454 addrindex_free_datasource( ds );
456 node = g_list_next( node );
461 * Free up specified interface.
462 * \param iface Interface to process.
464 static void addrindex_free_interface( AddressInterface *iface ) {
465 /* Free up data sources */
466 addrindex_free_all_datasources( iface );
467 g_list_free( iface->listSource );
469 /* Free internal storage */
470 g_free( ADDRITEM_ID(iface) );
471 g_free( ADDRITEM_NAME(iface) );
472 g_free( iface->name );
473 g_free( iface->listTag );
474 g_free( iface->itemTag );
476 /* Clear all pointers */
477 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
478 ADDRITEM_ID(iface) = NULL;
479 ADDRITEM_NAME(iface) = NULL;
480 ADDRITEM_PARENT(iface) = NULL;
481 ADDRITEM_SUBTYPE(iface) = 0;
482 iface->type = ADDR_IF_NONE;
484 iface->listTag = NULL;
485 iface->itemTag = NULL;
486 iface->legacyFlag = FALSE;
487 iface->useInterface = FALSE;
488 iface->haveLibrary = FALSE;
489 iface->listSource = NULL;
492 iface->searchOrder = 0;
493 iface->startSearch = NULL;
494 iface->stopSearch = NULL;
500 * Return cache ID for specified data source.
502 * \param addrIndex Address index.
503 * \param ds Data source.
504 * \return ID or NULL if not found. This should be <code>g_free()</code>
507 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
508 gchar *cacheID = NULL;
509 AddrBookBase *adbase;
512 g_return_val_if_fail( addrIndex != NULL, NULL );
513 g_return_val_if_fail( ds != NULL, NULL );
515 adbase = ( AddrBookBase * ) ds->rawDataSource;
517 cache = adbase->addressCache;
519 cacheID = g_strdup( cache->cacheID );
527 * Return reference to data source for specified cacheID.
528 * \param addrIndex Address index.
530 * \return Data source, or NULL if not found.
532 static AddressDataSource *addrindex_get_datasource(
533 AddressIndex *addrIndex, const gchar *cacheID )
535 g_return_val_if_fail( addrIndex != NULL, NULL );
536 g_return_val_if_fail( cacheID != NULL, NULL );
537 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
541 * Return reference to address cache for specified cacheID.
542 * \param addrIndex Address index.
544 * \return Address cache, or NULL if not found.
546 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
547 AddressDataSource *ds;
548 AddrBookBase *adbase;
551 g_return_val_if_fail( addrIndex != NULL, NULL );
552 g_return_val_if_fail( cacheID != NULL, NULL );
555 ds = addrindex_get_datasource( addrIndex, cacheID );
557 adbase = ( AddrBookBase * ) ds->rawDataSource;
558 cache = adbase->addressCache;
564 * Add data source into hash table.
565 * \param addrIndex Address index.
566 * \param ds Data source.
568 static void addrindex_hash_add_cache(
569 AddressIndex *addrIndex, AddressDataSource *ds )
573 cacheID = addrindex_get_cache_id( addrIndex, ds );
575 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
580 * Free hash table callback function.
582 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
590 * Free hash table of address cache items.
592 static void addrindex_free_cache_hash( GHashTable *table ) {
593 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
594 g_hash_table_destroy( table );
598 * Remove data source from internal hashtable.
599 * \param addrIndex Address index.
600 * \param ds Data source to remove.
602 static void addrindex_hash_remove_cache(
603 AddressIndex *addrIndex, AddressDataSource *ds )
607 cacheID = addrindex_get_cache_id( addrIndex, ds );
609 g_hash_table_remove( addrIndex->hashCache, cacheID );
616 * Create a new address index. This is created as a singleton object.
617 * \return Initialized address index object.
619 AddressIndex *addrindex_create_index( void ) {
622 if( _addressIndex_ == NULL ) {
623 index = g_new0( AddressIndex, 1 );
624 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
625 ADDRITEM_ID(index) = NULL;
626 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
627 ADDRITEM_PARENT(index) = NULL;
628 ADDRITEM_SUBTYPE(index) = 0;
629 index->filePath = NULL;
630 index->fileName = NULL;
631 index->retVal = MGU_SUCCESS;
632 index->needsConversion = FALSE;
633 index->wasConverted = FALSE;
634 index->conversionError = FALSE;
635 index->interfaceList = NULL;
636 index->lastType = ADDR_IF_NONE;
637 index->dirtyFlag = FALSE;
638 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
639 index->loadedFlag = FALSE;
640 index->searchOrder = NULL;
641 addrindex_build_if_list( index );
642 _addressIndex_ = index;
644 return _addressIndex_;
648 * Property - Specify file path to address index file.
649 * \param addrIndex Address index.
650 * \param value Path to index file.
652 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
653 g_return_if_fail( addrIndex != NULL );
654 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
658 * Property - Specify file name to address index file.
659 * \param addrIndex Address index.
660 * \param value File name.
662 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
663 g_return_if_fail( addrIndex != NULL );
664 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
668 * Return list of address interfaces.
669 * \param addrIndex Address index.
670 * \return List of address interfaces.
672 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
673 g_return_val_if_fail( addrIndex != NULL, NULL );
674 return addrIndex->interfaceList;
678 * Perform any other initialization of address index.
680 void addrindex_initialize( void ) {
682 addrcompl_initialize();
686 * Perform any other teardown of address index.
688 void addrindex_teardown( void ) {
689 addrcompl_teardown();
694 * Free up address index.
695 * \param addrIndex Address index.
697 void addrindex_free_index( AddressIndex *addrIndex ) {
700 g_return_if_fail( addrIndex != NULL );
703 g_list_free( addrIndex->searchOrder );
704 addrIndex->searchOrder = NULL;
706 /* Free internal storage */
707 g_free( ADDRITEM_ID(addrIndex) );
708 g_free( ADDRITEM_NAME(addrIndex) );
709 g_free( addrIndex->filePath );
710 g_free( addrIndex->fileName );
713 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
714 ADDRITEM_ID(addrIndex) = NULL;
715 ADDRITEM_NAME(addrIndex) = NULL;
716 ADDRITEM_PARENT(addrIndex) = NULL;
717 ADDRITEM_SUBTYPE(addrIndex) = 0;
718 addrIndex->filePath = NULL;
719 addrIndex->fileName = NULL;
720 addrIndex->retVal = MGU_SUCCESS;
721 addrIndex->needsConversion = FALSE;
722 addrIndex->wasConverted = FALSE;
723 addrIndex->conversionError = FALSE;
724 addrIndex->lastType = ADDR_IF_NONE;
725 addrIndex->dirtyFlag = FALSE;
727 /* Free up interfaces */
728 node = addrIndex->interfaceList;
730 AddressInterface *iface = node->data;
731 addrindex_free_interface( iface );
732 node = g_list_next( node );
734 g_list_free( addrIndex->interfaceList );
735 addrIndex->interfaceList = NULL;
737 /* Free up hash cache */
738 addrindex_free_cache_hash( addrIndex->hashCache );
739 addrIndex->hashCache = NULL;
741 addrIndex->loadedFlag = FALSE;
745 _addressIndex_ = NULL;
749 * Print address index.
750 * \param addrIndex Address index.
751 * \parem stream Stream to print.
753 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
754 g_return_if_fail( addrIndex != NULL );
755 fprintf( stream, "AddressIndex:\n" );
756 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
757 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
758 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
759 fprintf( stream, "\tconverted: '%s'\n",
760 addrIndex->wasConverted ? "yes" : "no" );
761 fprintf( stream, "\tcvt error: '%s'\n",
762 addrIndex->conversionError ? "yes" : "no" );
763 fprintf( stream, "\t---\n" );
767 * Retrieve reference to address interface for specified interface type.
768 * \param addrIndex Address index.
769 * \param ifType Interface type.
770 * \return Address interface, or NULL if not found.
772 static AddressInterface *addrindex_get_interface(
773 AddressIndex *addrIndex, AddressIfType ifType )
775 AddressInterface *retVal = NULL;
778 g_return_val_if_fail( addrIndex != NULL, NULL );
780 node = addrIndex->interfaceList;
782 AddressInterface *iface = node->data;
783 node = g_list_next( node );
784 if( iface->type == ifType ) {
793 * Add raw data source to index. The raw data object (an AddressBookFile or
794 * VCardFile object, for example) should be supplied as the raw dataSource
797 * \param addrIndex Address index.
798 * \param ifType Interface type to add.
799 * \param dataSource Actual raw data source to add.
800 * \return Data source added, or NULL if invalid interface type.
802 AddressDataSource *addrindex_index_add_datasource(
803 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
805 AddressInterface *iface;
806 AddressDataSource *ds = NULL;
808 g_return_val_if_fail( addrIndex != NULL, NULL );
809 g_return_val_if_fail( dataSource != NULL, NULL );
811 iface = addrindex_get_interface( addrIndex, ifType );
813 ds = addrindex_create_datasource( ifType );
814 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
816 ds->rawDataSource = dataSource;
817 ds->interface = iface;
818 iface->listSource = g_list_append( iface->listSource, ds );
819 addrIndex->dirtyFlag = TRUE;
821 addrindex_hash_add_cache( addrIndex, ds );
827 * Remove specified data source from index.
828 * \param addrIndex Address index.
829 * \param dataSource Data source to add.
830 * \return Reference to data source if removed, or NULL if data source was not
831 * found in index. Note the this object must still be freed.
833 AddressDataSource *addrindex_index_remove_datasource(
834 AddressIndex *addrIndex, AddressDataSource *dataSource )
836 AddressDataSource *retVal = FALSE;
837 AddressInterface *iface;
839 g_return_val_if_fail( addrIndex != NULL, NULL );
840 g_return_val_if_fail( dataSource != NULL, NULL );
842 iface = addrindex_get_interface( addrIndex, dataSource->type );
844 iface->listSource = g_list_remove( iface->listSource, dataSource );
845 addrIndex->dirtyFlag = TRUE;
846 dataSource->interface = NULL;
848 /* Remove cache from hash table */
849 addrindex_hash_remove_cache( addrIndex, dataSource );
857 * Retrieve a reference to address interface for specified interface type and
858 * XML interface tag name.
859 * \param addrIndex Address index.
860 * \param tag XML interface tag name to match.
861 * \param ifType Interface type to match.
862 * \return Reference to address index, or NULL if not found in index.
864 static AddressInterface *addrindex_tag_get_interface(
865 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
867 AddressInterface *retVal = NULL;
868 GList *node = addrIndex->interfaceList;
871 AddressInterface *iface = node->data;
872 node = g_list_next( node );
874 if( strcmp( iface->listTag, tag ) == 0 ) {
880 if( iface->type == ifType ) {
890 * Retrieve a reference to address interface for specified interface type and
891 * XML datasource tag name.
892 * \param addrIndex Address index.
893 * \param ifType Interface type to match.
894 * \param tag XML datasource tag name to match.
895 * \return Reference to address index, or NULL if not found in index.
897 static AddressInterface *addrindex_tag_get_datasource(
898 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
900 AddressInterface *retVal = NULL;
901 GList *node = addrIndex->interfaceList;
904 AddressInterface *iface = node->data;
905 node = g_list_next( node );
906 if( iface->type == ifType && iface->itemTag ) {
907 if( strcmp( iface->itemTag, tag ) == 0 ) {
916 /* **********************************************************************
917 * Interface XML parsing functions.
918 * ***********************************************************************
922 * Write start of XML element to file.
924 * \param lvl Indentation level.
925 * \param name Element name.
927 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
929 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
935 * Write end of XML element to file.
937 * \param lvl Indentation level.
938 * \param name Element name.
940 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
942 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
949 * Write XML attribute to file.
951 * \param name Attribute name.
952 * \param value Attribute value.
954 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
958 xml_file_put_escape_str( fp, value );
963 * Return DOM fragment for current XML tag from file.
964 * \param file XML file being processed.
965 * \return Fragment representing DOM fragment for configuration element.
967 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
968 AddressIfFragment *fragment;
969 AddressIfFragment *child;
979 /* printf( "addrindex_read_fragment\n" ); */
981 prevLevel = file->level;
983 /* Get current tag name */
984 xtag = xml_get_current_tag( file );
986 /* Create new fragment */
987 fragment = g_new0( AddressIfFragment, 1 );
988 fragment->name = g_strdup( xtag->tag );
989 fragment->children = NULL;
990 fragment->attributes = NULL;
992 /* Read attributes */
994 attr = xml_get_current_tag_attr( file );
996 name = ((XMLAttr *)attr->data)->name;
997 value = ((XMLAttr *)attr->data)->value;
998 nv = g_new0( AddressIfAttrib, 1 );
999 nv->name = g_strdup( name );
1000 nv->value = g_strdup( value );
1001 list = g_list_append( list, nv );
1002 attr = g_list_next( attr );
1004 fragment->attributes = list;
1006 /* Now read the children */
1008 rc = xml_parse_next_tag( file );
1013 if( file->level < prevLevel ) {
1014 /* We must be above level we start at */
1017 child = addrindex_read_fragment( file );
1018 fragment->children = g_list_append( fragment->children, child );
1025 * Write DOM fragment to file.
1026 * \param fp File to write.
1027 * \param fragment DOM fragment for configuration element.
1028 * \param lvl Indent level.
1030 static void addrindex_write_fragment(
1031 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1036 addrindex_write_elem_s( fp, lvl, fragment->name );
1037 node = fragment->attributes;
1039 AddressIfAttrib *nv = node->data;
1040 addrindex_write_attr( fp, nv->name, nv->value );
1041 node = g_list_next( node );
1043 if( fragment->children ) {
1046 /* Output children */
1047 node = fragment->children;
1049 AddressIfFragment *child = node->data;
1050 addrindex_write_fragment( fp, child, 1+lvl );
1051 node = g_list_next( node );
1054 /* Output closing tag */
1055 addrindex_write_elem_e( fp, lvl, fragment->name );
1064 * Read/parse address index file, creating a data source for a regular
1065 * intrinsic XML addressbook.
1066 * \param file Address index file.
1067 * \return Data source.
1069 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1070 AddressDataSource *ds;
1071 AddressBookFile *abf;
1074 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1075 abf = addrbook_create_book();
1076 attr = xml_get_current_tag_attr( file );
1078 gchar *name = ((XMLAttr *)attr->data)->name;
1079 gchar *value = ((XMLAttr *)attr->data)->value;
1080 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1081 addrbook_set_name( abf, value );
1083 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1084 addrbook_set_file( abf, value );
1086 attr = g_list_next( attr );
1088 ds->rawDataSource = abf;
1092 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1093 AddressBookFile *abf = ds->rawDataSource;
1095 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1096 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1097 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1098 fputs( " />\n", fp );
1102 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1103 AddressDataSource *ds;
1107 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1108 vcf = vcard_create();
1109 attr = xml_get_current_tag_attr( file );
1111 gchar *name = ((XMLAttr *)attr->data)->name;
1112 gchar *value = ((XMLAttr *)attr->data)->value;
1113 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1114 vcard_set_name( vcf, value );
1116 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1117 vcard_set_file( vcf, value );
1119 attr = g_list_next( attr );
1121 ds->rawDataSource = vcf;
1125 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1126 VCardFile *vcf = ds->rawDataSource;
1128 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1129 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1130 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1131 fputs( " />\n", fp );
1136 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1137 AddressDataSource *ds;
1141 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1142 jpf = jpilot_create();
1143 attr = xml_get_current_tag_attr( file );
1145 gchar *name = ((XMLAttr *)attr->data)->name;
1146 gchar *value = ((XMLAttr *)attr->data)->value;
1147 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1148 jpilot_set_name( jpf, value );
1150 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1151 jpilot_set_file( jpf, value );
1153 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1154 jpilot_add_custom_label( jpf, value );
1156 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1157 jpilot_add_custom_label( jpf, value );
1159 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1160 jpilot_add_custom_label( jpf, value );
1162 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1163 jpilot_add_custom_label( jpf, value );
1165 attr = g_list_next( attr );
1167 ds->rawDataSource = jpf;
1171 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1172 JPilotFile *jpf = ds->rawDataSource;
1176 GList *customLbl = jpilot_get_custom_labels( jpf );
1177 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1178 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1179 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1184 g_snprintf( name, sizeof(name), "%s%d",
1185 ATTAG_JPILOT_CUSTOM, ind );
1186 addrindex_write_attr( fp, name, node->data );
1188 node = g_list_next( node );
1190 fputs( " />\n", fp );
1196 * Just read/write DOM fragments (preserve data found in file).
1198 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1199 AddressDataSource *ds;
1201 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1202 ds->rawDataSource = addrindex_read_fragment( file );
1206 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1207 AddressIfFragment *fragment = ds->rawDataSource;
1209 addrindex_write_fragment( fp, fragment, lvl );
1216 * Parse LDAP criteria attribute data from XML file.
1217 * \param file Index file.
1218 * \param ctl LDAP control object to populate.
1220 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1229 if( file == NULL ) {
1234 prevLevel = file->level;
1235 xtagPrev = xml_get_current_tag( file );
1237 rc = xml_parse_next_tag( file );
1239 /* Terminate prematurely */
1240 mgu_free_dlist( list );
1244 if( file->level < prevLevel ) {
1245 /* We must be above level we start at */
1249 /* Get a tag (element) */
1250 xtag = xml_get_current_tag( file );
1251 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1252 /* LDAP criteria attribute */
1253 attr = xml_get_current_tag_attr( file );
1255 gchar *name = ((XMLAttr *)attr->data)->name;
1256 gchar *value = ((XMLAttr *)attr->data)->value;
1257 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1258 if( value && strlen( value ) > 0 ) {
1259 list = g_list_append(
1260 list, g_strdup( value ) );
1263 attr = g_list_next( attr );
1267 if( xtag != xtagPrev ) {
1268 /* Found a new tag */
1275 /* Build list of search attributes */
1276 ldapctl_criteria_list_clear( ctl );
1279 ldapctl_criteria_list_add( ctl, node->data );
1280 g_free( node->data );
1282 node = g_list_next( node );
1284 g_list_free( list );
1289 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1291 * Parse LDAP control data from XML file.
1292 * \param file Index file.
1293 * \return Initialized data soruce object.
1295 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1296 AddressDataSource *ds;
1300 gchar *serverName = NULL;
1301 gchar *criteria = NULL;
1302 gboolean bDynSearch;
1303 gboolean bTLS, bSSL;
1306 /* printf( "addrindex_parse_ldap\n" ); */
1307 /* Set up some defaults */
1311 iMatch = LDAPCTL_MATCH_BEGINWITH;
1313 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1314 ctl = ldapctl_create();
1315 attr = xml_get_current_tag_attr( file );
1317 gchar *name = ((XMLAttr *)attr->data)->name;
1318 gchar *value = ((XMLAttr *)attr->data)->value;
1319 gint ivalue = atoi( value );
1321 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1322 g_free( serverName );
1323 serverName = g_strdup( value );
1325 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1326 ldapctl_set_host( ctl, value );
1328 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1329 ldapctl_set_port( ctl, ivalue );
1331 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1332 ldapctl_set_base_dn( ctl, value );
1334 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1335 ldapctl_set_bind_dn( ctl, value );
1337 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1338 ldapctl_set_bind_password( ctl, value );
1340 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1342 criteria = g_strdup( value );
1344 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1345 ldapctl_set_max_entries( ctl, ivalue );
1347 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1348 ldapctl_set_timeout( ctl, ivalue );
1350 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1351 ldapctl_set_max_query_age( ctl, ivalue );
1353 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1355 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1359 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1360 iMatch = LDAPCTL_MATCH_BEGINWITH;
1361 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1362 iMatch = LDAPCTL_MATCH_CONTAINS;
1365 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1367 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1371 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1373 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1377 attr = g_list_next( attr );
1380 server = ldapsvr_create_noctl();
1381 ldapsvr_set_name( server, serverName );
1382 ldapsvr_set_search_flag( server, bDynSearch );
1383 ldapctl_set_matching_option( ctl, iMatch );
1385 ldapctl_set_tls( ctl, bTLS );
1386 ldapctl_set_ssl( ctl, bSSL );
1388 g_free( serverName );
1389 ldapsvr_set_control( server, ctl );
1390 ds->rawDataSource = server;
1392 addrindex_parse_ldap_attrlist( file, ctl );
1394 * If criteria have been specified and no attributes were listed, then
1395 * convert old style criteria into an attribute list. Any criteria will
1396 * be dropped when saving data.
1399 if( ! ldapctl_get_criteria_list( ctl ) ) {
1400 ldapctl_parse_ldap_search( ctl, criteria );
1404 /* ldapsvr_print_data( server, stdout ); */
1409 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1410 LdapServer *server = ds->rawDataSource;
1411 LdapControl *ctl = NULL;
1416 ctl = server->control;
1418 if( ctl == NULL ) return;
1420 /* Output start element with attributes */
1421 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1422 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1423 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1425 sprintf( value, "%d", ctl->port );
1426 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1428 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1429 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1430 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1432 sprintf( value, "%d", ctl->maxEntries );
1433 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1434 sprintf( value, "%d", ctl->timeOut );
1435 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1436 sprintf( value, "%d", ctl->maxQueryAge );
1437 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1439 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1440 server->searchFlag ?
1441 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1443 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1444 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1445 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1447 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1449 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1450 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1452 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1456 /* Output attributes */
1457 node = ldapctl_get_criteria_list( ctl );
1459 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1460 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1462 node = g_list_next( node );
1465 /* End of element */
1466 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1471 * Just read/write DOM fragments (preserve data found in file).
1473 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1474 AddressDataSource *ds;
1476 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1477 ds->rawDataSource = addrindex_read_fragment( file );
1481 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1482 AddressIfFragment *fragment = ds->rawDataSource;
1484 addrindex_write_fragment( fp, fragment, lvl );
1489 /* **********************************************************************
1490 * Address index I/O functions.
1491 * ***********************************************************************
1494 * Read address index file, creating appropriate data sources for each address
1497 * \param addrIndex Address index.
1498 * \param file Address index file.
1500 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1503 AddressInterface *iface = NULL, *dsIFace = NULL;
1504 AddressDataSource *ds;
1507 addrIndex->loadedFlag = FALSE;
1509 prev_level = file->level;
1510 rc = xml_parse_next_tag( file );
1511 if( file->level == 0 ) return;
1513 xtag = xml_get_current_tag( file );
1515 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1517 addrIndex->lastType = iface->type;
1518 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1521 dsIFace = addrindex_tag_get_datasource(
1522 addrIndex, addrIndex->lastType, xtag->tag );
1524 /* Add data source to list */
1526 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1527 ds = addrindex_parse_book( file );
1528 if( ds->rawDataSource ) {
1529 addrbook_set_path( ds->rawDataSource,
1530 addrIndex->filePath );
1533 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1534 ds = addrindex_parse_vcard( file );
1536 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1537 ds = addrindex_parse_jpilot( file );
1539 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1540 ds = addrindex_parse_ldap( file );
1543 ds->interface = dsIFace;
1544 addrindex_hash_add_cache( addrIndex, ds );
1545 dsIFace->listSource =
1546 g_list_append( dsIFace->listSource, ds );
1554 * Search order sorting comparison function for building search order list.
1556 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1557 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1558 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1560 return ifaceA->searchOrder - ifaceB->searchOrder;
1564 * Build list of data sources to process.
1565 * \param addrIndex Address index object.
1567 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1570 /* Clear existing list */
1571 g_list_free( addrIndex->searchOrder );
1572 addrIndex->searchOrder = NULL;
1574 /* Build new list */
1575 nodeIf = addrIndex->interfaceList;
1577 AddressInterface *iface = nodeIf->data;
1578 if( iface->useInterface ) {
1579 if( iface->searchOrder > 0 ) {
1580 /* Add to search order list */
1581 addrIndex->searchOrder = g_list_insert_sorted(
1582 addrIndex->searchOrder, iface,
1583 addrindex_search_order_compare );
1586 nodeIf = g_list_next( nodeIf );
1590 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1591 XMLFile *file = NULL;
1592 gchar *fileSpec = NULL;
1594 g_return_val_if_fail( addrIndex != NULL, -1 );
1596 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1597 addrIndex->retVal = MGU_NO_FILE;
1598 file = xml_open_file( fileSpec );
1601 if( file == NULL ) {
1603 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1605 return addrIndex->retVal;
1608 addrIndex->retVal = MGU_BAD_FORMAT;
1609 if( xml_get_dtd( file ) == 0 ) {
1610 if( xml_parse_next_tag( file ) == 0 ) {
1611 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1612 addrindex_read_index( addrIndex, file );
1613 addrIndex->retVal = MGU_SUCCESS;
1617 xml_close_file( file );
1619 addrindex_build_search_order( addrIndex );
1621 return addrIndex->retVal;
1624 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1625 GList *nodeIF, *nodeDS;
1627 gint lvlItem = 1 + lvlList;
1629 nodeIF = addrIndex->interfaceList;
1631 AddressInterface *iface = nodeIF->data;
1632 if( ! iface->legacyFlag ) {
1633 nodeDS = iface->listSource;
1634 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1637 AddressDataSource *ds = nodeDS->data;
1639 if( iface->type == ADDR_IF_BOOK ) {
1640 addrindex_write_book( fp, ds, lvlItem );
1642 if( iface->type == ADDR_IF_VCARD ) {
1643 addrindex_write_vcard( fp, ds, lvlItem );
1645 if( iface->type == ADDR_IF_JPILOT ) {
1646 addrindex_write_jpilot( fp, ds, lvlItem );
1648 if( iface->type == ADDR_IF_LDAP ) {
1649 addrindex_write_ldap( fp, ds, lvlItem );
1652 nodeDS = g_list_next( nodeDS );
1654 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1656 nodeIF = g_list_next( nodeIF );
1661 * Write data to specified file.
1662 * Enter: addrIndex Address index object.
1663 * newFile New file name.
1664 * return: Status code, from addrIndex->retVal.
1665 * Note: File will be created in directory specified by addrIndex.
1667 static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1670 #ifndef DEV_STANDALONE
1674 g_return_val_if_fail( addrIndex != NULL, -1 );
1676 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1677 addrIndex->retVal = MGU_OPEN_FILE;
1678 #ifdef DEV_STANDALONE
1679 fp = g_fopen( fileSpec, "wb" );
1682 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1684 pfile = prefs_write_open( fileSpec );
1688 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1690 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1693 addrindex_write_index( addrIndex, fp );
1694 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1696 addrIndex->retVal = MGU_SUCCESS;
1697 #ifdef DEV_STANDALONE
1700 if( prefs_file_close( pfile ) < 0 ) {
1701 addrIndex->retVal = MGU_ERROR_WRITE;
1707 return addrIndex->retVal;
1711 * Save address index data to original file.
1712 * return: Status code, from addrIndex->retVal.
1714 gint addrindex_save_data( AddressIndex *addrIndex ) {
1715 g_return_val_if_fail( addrIndex != NULL, -1 );
1717 addrIndex->retVal = MGU_NO_FILE;
1718 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1719 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1721 addrindex_write_to( addrIndex, addrIndex->fileName );
1722 if( addrIndex->retVal == MGU_SUCCESS ) {
1723 addrIndex->dirtyFlag = FALSE;
1725 return addrIndex->retVal;
1729 * Save all address book files which may have changed.
1730 * Return: Status code, set if there was a problem saving data.
1732 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1733 gint retVal = MGU_SUCCESS;
1734 GList *nodeIf, *nodeDS;
1736 nodeIf = addrIndex->interfaceList;
1738 AddressInterface *iface = nodeIf->data;
1739 if( iface->type == ADDR_IF_BOOK ) {
1740 nodeDS = iface->listSource;
1742 AddressDataSource *ds = nodeDS->data;
1743 AddressBookFile *abf = ds->rawDataSource;
1744 if( addrbook_get_dirty( abf ) ) {
1745 if( addrbook_get_read_flag( abf ) ) {
1746 addrbook_save_data( abf );
1747 if( abf->retVal != MGU_SUCCESS ) {
1748 retVal = abf->retVal;
1752 nodeDS = g_list_next( nodeDS );
1756 nodeIf = g_list_next( nodeIf );
1762 /* **********************************************************************
1763 * Address book conversion to new format.
1764 * ***********************************************************************
1767 #define ELTAG_IF_OLD_FOLDER "folder"
1768 #define ELTAG_IF_OLD_GROUP "group"
1769 #define ELTAG_IF_OLD_ITEM "item"
1770 #define ELTAG_IF_OLD_NAME "name"
1771 #define ELTAG_IF_OLD_ADDRESS "address"
1772 #define ELTAG_IF_OLD_REMARKS "remarks"
1773 #define ATTAG_IF_OLD_NAME "name"
1775 #define TEMPNODE_ROOT 0
1776 #define TEMPNODE_FOLDER 1
1777 #define TEMPNODE_GROUP 2
1778 #define TEMPNODE_ADDRESS 3
1780 typedef struct _AddressCvt_Node AddressCvtNode;
1781 struct _AddressCvt_Node {
1790 * Parse current address item.
1792 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1797 nn = g_new0( AddressCvtNode, 1 );
1798 nn->type = TEMPNODE_ADDRESS;
1801 level = file->level;
1804 xml_parse_next_tag(file);
1805 if (file->level < level) return nn;
1807 element = xml_get_element( file );
1808 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1809 nn->name = g_strdup( element );
1811 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1812 nn->address = g_strdup( element );
1814 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1815 nn->remarks = g_strdup( element );
1818 xml_parse_next_tag(file);
1823 * Create a temporary node below specified node.
1825 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1827 nn = g_new0( AddressCvtNode, 1 );
1829 nn->name = g_strdup( name );
1830 nn->remarks = g_strdup( rem );
1831 node->list = g_list_append( node->list, nn );
1836 * Process current temporary node.
1838 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1841 AddressCvtNode *newNode = NULL;
1846 prev_level = file->level;
1847 xml_parse_next_tag( file );
1848 if (file->level < prev_level) return;
1852 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1853 attr = xml_get_current_tag_attr(file);
1855 name = ((XMLAttr *)attr->data)->name;
1856 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1857 value = ((XMLAttr *)attr->data)->value;
1860 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1861 addrindex_add_obj( file, newNode );
1864 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1865 attr = xml_get_current_tag_attr(file);
1867 name = ((XMLAttr *)attr->data)->name;
1868 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1869 value = ((XMLAttr *)attr->data)->value;
1872 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1873 addrindex_add_obj( file, newNode );
1875 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1876 newNode = addrindex_parse_item( file );
1877 node->list = g_list_append( node->list, newNode );
1880 /* printf( "invalid: !!! \n" ); */
1881 attr = xml_get_current_tag_attr( file );
1887 * Consume all nodes below current tag.
1889 static void addrindex_consume_tree( XMLFile *file ) {
1896 prev_level = file->level;
1897 xml_parse_next_tag( file );
1898 if (file->level < prev_level) return;
1900 xtag = xml_get_current_tag( file );
1901 /* printf( "tag : %s\n", xtag->tag ); */
1902 element = xml_get_element( file );
1903 attr = xml_get_current_tag_attr( file );
1904 /* show_attribs( attr ); */
1905 /* printf( "\ttag value : %s :\n", element ); */
1906 addrindex_consume_tree( file );
1911 * Print temporary tree.
1913 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1916 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1917 fprintf( stream, "\tname :%s:\n", node->name );
1918 fprintf( stream, "\taddr :%s:\n", node->address );
1919 fprintf( stream, "\trems :%s:\n", node->remarks );
1921 fprintf( stream, "\t--list----\n" );
1925 AddressCvtNode *lNode = list->data;
1926 list = g_list_next( list );
1927 addrindex_print_node( lNode, stream );
1929 fprintf( stream, "\t==list-%d==\n", node->type );
1933 * Free up temporary tree.
1935 static void addrindex_free_node( AddressCvtNode *node ) {
1936 GList *list = node->list;
1939 AddressCvtNode *lNode = list->data;
1940 list = g_list_next( list );
1941 addrindex_free_node( lNode );
1943 node->type = TEMPNODE_ROOT;
1944 g_free( node->name );
1945 g_free( node->address );
1946 g_free( node->remarks );
1947 g_list_free( node->list );
1952 * Process address book for specified node.
1954 static void addrindex_process_node(
1955 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1956 ItemGroup *parentGrp, ItemFolder *folderGrp )
1959 ItemFolder *itemFolder = NULL;
1960 ItemGroup *itemGParent = parentGrp;
1961 ItemFolder *itemGFolder = folderGrp;
1962 AddressCache *cache = abf->addressCache;
1964 if( node->type == TEMPNODE_ROOT ) {
1965 itemFolder = parent;
1967 else if( node->type == TEMPNODE_FOLDER ) {
1968 itemFolder = addritem_create_item_folder();
1969 addritem_folder_set_name( itemFolder, node->name );
1970 addrcache_id_folder( cache, itemFolder );
1971 addrcache_folder_add_folder( cache, parent, itemFolder );
1974 else if( node->type == TEMPNODE_GROUP ) {
1975 ItemGroup *itemGroup;
1978 /* Create a folder for group */
1979 fName = g_strdup_printf( "Cvt - %s", node->name );
1980 itemGFolder = addritem_create_item_folder();
1981 addritem_folder_set_name( itemGFolder, fName );
1982 addrcache_id_folder( cache, itemGFolder );
1983 addrcache_folder_add_folder( cache, parent, itemGFolder );
1986 /* Add group into folder */
1987 itemGroup = addritem_create_item_group();
1988 addritem_group_set_name( itemGroup, node->name );
1989 addrcache_id_group( cache, itemGroup );
1990 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1991 itemGParent = itemGroup;
1993 else if( node->type == TEMPNODE_ADDRESS ) {
1994 ItemPerson *itemPerson;
1995 ItemEMail *itemEMail;
1997 /* Create person and email objects */
1998 itemPerson = addritem_create_item_person();
1999 addritem_person_set_common_name( itemPerson, node->name );
2000 addrcache_id_person( cache, itemPerson );
2001 itemEMail = addritem_create_item_email();
2002 addritem_email_set_address( itemEMail, node->address );
2003 addritem_email_set_remarks( itemEMail, node->remarks );
2004 addrcache_id_email( cache, itemEMail );
2005 addrcache_person_add_email( cache, itemPerson, itemEMail );
2007 /* Add person into appropriate folder */
2009 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2012 addrcache_folder_add_person( cache, parent, itemPerson );
2015 /* Add email address only into group */
2017 addrcache_group_add_email( cache, parentGrp, itemEMail );
2023 AddressCvtNode *lNode = list->data;
2024 list = g_list_next( list );
2025 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2030 * Process address book to specified file number.
2032 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2033 gboolean retVal = FALSE;
2034 AddressBookFile *abf = NULL;
2035 AddressCvtNode *rootNode = NULL;
2036 gchar *newFile = NULL;
2037 GList *fileList = NULL;
2040 /* Setup root node */
2041 rootNode = g_new0( AddressCvtNode, 1 );
2042 rootNode->type = TEMPNODE_ROOT;
2043 rootNode->name = g_strdup( "root" );
2044 rootNode->list = NULL;
2045 addrindex_add_obj( file, rootNode );
2046 /* addrindex_print_node( rootNode, stdout ); */
2048 /* Create new address book */
2049 abf = addrbook_create_book();
2050 addrbook_set_name( abf, displayName );
2051 addrbook_set_path( abf, addrIndex->filePath );
2053 /* Determine next available file number */
2054 fileList = addrbook_get_bookfile_list( abf );
2056 fileNum = 1 + abf->maxValue;
2058 g_list_free( fileList );
2061 newFile = addrbook_gen_new_file_name( fileNum );
2063 addrbook_set_file( abf, newFile );
2066 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2068 /* addrbook_dump_book( abf, stdout ); */
2069 addrbook_save_data( abf );
2070 addrIndex->retVal = abf->retVal;
2071 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2073 addrbook_free_book( abf );
2075 addrindex_free_node( rootNode );
2078 /* Create entries in address index */
2080 abf = addrbook_create_book();
2081 addrbook_set_name( abf, displayName );
2082 addrbook_set_path( abf, addrIndex->filePath );
2083 addrbook_set_file( abf, newFile );
2084 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2091 * Process tree converting data.
2093 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2101 prev_level = file->level;
2102 xml_parse_next_tag( file );
2103 if (file->level < prev_level) return;
2105 xtag = xml_get_current_tag( file );
2106 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2107 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2108 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2109 addrIndex->needsConversion = FALSE;
2110 addrIndex->wasConverted = TRUE;
2115 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2116 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2117 addrIndex->needsConversion = FALSE;
2118 addrIndex->wasConverted = TRUE;
2123 element = xml_get_element( file );
2124 attr = xml_get_current_tag_attr( file );
2125 /* show_attribs( attr ); */
2126 /* printf( "\ttag value : %s :\n", element ); */
2127 addrindex_consume_tree( file );
2131 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2132 XMLFile *file = NULL;
2135 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2136 addrIndex->retVal = MGU_NO_FILE;
2137 file = xml_open_file( fileSpec );
2140 if( file == NULL ) {
2141 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2142 return addrIndex->retVal;
2145 addrIndex->retVal = MGU_BAD_FORMAT;
2146 if( xml_get_dtd( file ) == 0 ) {
2147 if( xml_parse_next_tag( file ) == 0 ) {
2148 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2149 addrindex_convert_tree( addrIndex, file );
2153 xml_close_file( file );
2154 return addrIndex->retVal;
2158 * Create a new address book file.
2160 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2161 gboolean retVal = FALSE;
2162 AddressBookFile *abf = NULL;
2163 gchar *newFile = NULL;
2164 GList *fileList = NULL;
2167 /* Create new address book */
2168 abf = addrbook_create_book();
2169 addrbook_set_name( abf, displayName );
2170 addrbook_set_path( abf, addrIndex->filePath );
2172 /* Determine next available file number */
2173 fileList = addrbook_get_bookfile_list( abf );
2175 fileNum = 1 + abf->maxValue;
2177 g_list_free( fileList );
2180 newFile = addrbook_gen_new_file_name( fileNum );
2182 addrbook_set_file( abf, newFile );
2185 addrbook_save_data( abf );
2186 addrIndex->retVal = abf->retVal;
2187 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2188 addrbook_free_book( abf );
2191 /* Create entries in address index */
2193 abf = addrbook_create_book();
2194 addrbook_set_name( abf, displayName );
2195 addrbook_set_path( abf, addrIndex->filePath );
2196 addrbook_set_file( abf, newFile );
2197 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2204 * Read data for address index performing a conversion if necesary.
2205 * Enter: addrIndex Address index object.
2206 * return: Status code, from addrIndex->retVal.
2207 * Note: New address book files will be created in directory specified by
2208 * addrIndex. Three files will be created, for the following:
2209 * "Common addresses"
2210 * "Personal addresses"
2211 * "Gathered addresses" - a new address book.
2213 gint addrindex_read_data( AddressIndex *addrIndex ) {
2214 g_return_val_if_fail( addrIndex != NULL, -1 );
2216 addrIndex->conversionError = FALSE;
2217 addrindex_read_file( addrIndex );
2218 if( addrIndex->retVal == MGU_SUCCESS ) {
2219 if( addrIndex->needsConversion ) {
2220 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2221 addrIndex->conversionError = TRUE;
2224 addrIndex->conversionError = TRUE;
2227 addrIndex->dirtyFlag = TRUE;
2229 return addrIndex->retVal;
2233 * Create new address books for a new address index.
2234 * Enter: addrIndex Address index object.
2235 * return: Status code, from addrIndex->retVal.
2236 * Note: New address book files will be created in directory specified by
2237 * addrIndex. Three files will be created, for the following:
2238 * "Common addresses"
2239 * "Personal addresses"
2240 * "Gathered addresses" - a new address book.
2242 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2245 g_return_val_if_fail( addrIndex != NULL, -1 );
2247 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2249 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2250 addrIndex->dirtyFlag = TRUE;
2252 return addrIndex->retVal;
2255 /* **********************************************************************
2256 * New interface stuff.
2257 * ***********************************************************************
2261 * Return modified flag for specified data source.
2263 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2264 gboolean retVal = FALSE;
2265 AddressInterface *iface;
2267 if( ds == NULL ) return retVal;
2268 iface = ds->interface;
2269 if( iface == NULL ) return retVal;
2270 if( iface->getModifyFlag ) {
2271 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2277 * Return accessed flag for specified data source.
2279 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2280 gboolean retVal = FALSE;
2281 AddressInterface *iface;
2283 if( ds == NULL ) return retVal;
2284 iface = ds->interface;
2285 if( iface == NULL ) return retVal;
2286 if( iface->getAccessFlag ) {
2287 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2293 * Return data read flag for specified data source.
2295 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2296 gboolean retVal = TRUE;
2297 AddressInterface *iface;
2299 if( ds == NULL ) return retVal;
2300 iface = ds->interface;
2301 if( iface == NULL ) return retVal;
2302 if( iface->getReadFlag ) {
2303 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2309 * Return status code for specified data source.
2311 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2312 gint retVal = MGU_SUCCESS;
2313 AddressInterface *iface;
2315 if( ds == NULL ) return retVal;
2316 iface = ds->interface;
2317 if( iface == NULL ) return retVal;
2318 if( iface->getStatusCode ) {
2319 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2325 * Return data read flag for specified data source.
2327 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2328 gint retVal = MGU_SUCCESS;
2329 AddressInterface *iface;
2331 if( ds == NULL ) return retVal;
2332 iface = ds->interface;
2333 if( iface == NULL ) return retVal;
2334 if( iface->getReadData ) {
2336 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2337 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2339 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2345 * Return data read flag for specified data source.
2347 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2348 ItemFolder *retVal = NULL;
2349 AddressInterface *iface;
2351 if( ds == NULL ) return retVal;
2352 iface = ds->interface;
2353 if( iface == NULL ) return retVal;
2354 if( iface->getRootFolder ) {
2355 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2361 * Return name for specified data source.
2363 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2364 gchar *retVal = FALSE;
2365 AddressInterface *iface;
2367 if( ds == NULL ) return retVal;
2368 iface = ds->interface;
2369 if( iface == NULL ) return retVal;
2370 if( iface->getName ) {
2371 retVal = ( iface->getName ) ( ds->rawDataSource );
2377 * Set the access flag inside the data source.
2379 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2380 AddressInterface *iface;
2382 if( ds == NULL ) return;
2383 iface = ds->interface;
2384 if( iface == NULL ) return;
2385 if( iface->setAccessFlag ) {
2386 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2391 * Return read only flag for specified data source.
2393 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2394 AddressInterface *iface;
2395 if( ds == NULL ) return TRUE;
2396 iface = ds->interface;
2397 if( iface == NULL ) return TRUE;
2398 return iface->readOnly;
2402 * Return list of all persons for specified data source.
2404 static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2405 GList *retVal = NULL;
2406 AddressInterface *iface;
2408 if( ds == NULL ) return retVal;
2409 iface = ds->interface;
2410 if( iface == NULL ) return retVal;
2411 if( iface->getAllPersons ) {
2412 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2418 * Return list of all groups for specified data source.
2420 static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2421 GList *retVal = NULL;
2422 AddressInterface *iface;
2424 if( ds == NULL ) return retVal;
2425 iface = ds->interface;
2426 if( iface == NULL ) return retVal;
2427 if( iface->getAllGroups ) {
2428 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2433 /* **********************************************************************
2434 * Address search stuff.
2435 * ***********************************************************************
2439 * Setup or register the dynamic search that will be performed. The search
2440 * is registered with the query manager.
2442 * \param searchTerm Search term. A private copy will be made.
2443 * \param callBackEntry Callback function that should be called when
2444 * each entry is received.
2445 * \param callBackEnd Callback function that should be called when
2446 * search has finished running.
2447 * \return ID allocated to query that will be executed.
2449 gint addrindex_setup_search(
2450 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2455 /* Set up a dynamic address query */
2456 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2457 queryID = req->queryID;
2458 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2460 /* printf( "***> query ID ::%d::\n", queryID ); */
2467 * Function prototypes (not in header file or circular reference errors are
2470 LdapQuery *ldapsvr_new_dynamic_search(
2471 LdapServer *server, QueryRequest *req );
2472 LdapQuery *ldapsvr_new_explicit_search(
2473 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2474 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2479 * Execute the previously registered dynamic search.
2481 * \param req Address query object to execute.
2482 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2485 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2486 AddressInterface *iface;
2487 AddressDataSource *ds;
2492 /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2493 nodeIf = _addressIndex_->searchOrder;
2495 iface = nodeIf->data;
2496 nodeIf = g_list_next( nodeIf );
2498 if( ! iface->useInterface ) {
2501 if( ! iface->externalQuery ) {
2506 nodeDS = iface->listSource;
2509 nodeDS = g_list_next( nodeDS );
2511 if( type == ADDR_IF_LDAP ) {
2515 server = ds->rawDataSource;
2516 if( ! server->searchFlag ) {
2519 if( ldapsvr_reuse_previous( server, req ) ) {
2523 /* Start a new dynamic search */
2524 qry = ldapsvr_new_dynamic_search( server, req );
2526 ldapsvr_execute_query( server, qry );
2536 * Stop the previously registered search.
2538 * \param queryID ID of search query to stop.
2540 void addrindex_stop_search( const gint queryID ){
2542 AddrQueryObject *aqo;
2545 /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
2546 /* If query ID does not match, search has not been setup */
2547 req = qrymgr_find_request( queryID );
2552 /* Stop all queries that were associated with request */
2553 node = req->queryList;
2557 if( aqo->queryType == ADDRQUERY_LDAP ) {
2558 LdapQuery *qry = ( LdapQuery * ) aqo;
2559 ldapqry_set_stop_flag( qry, TRUE );
2563 node = g_list_next( node );
2566 /* Delete query request */
2567 qrymgr_delete_request( queryID );
2571 * Setup or register the explicit search that will be performed. The search is
2572 * registered with the query manager.
2574 * \param ds Data source to search.
2575 * \param searchTerm Search term to locate.
2576 * \param folder Folder to receive search results; may be NULL.
2577 * \param callbackEnd Function to call when search has terminated.
2578 * \param callbackEntry Function to called for each entry processed.
2579 * \return ID allocated to query that will be executed.
2581 gint addrindex_setup_explicit_search(
2582 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2583 void *callBackEnd, void *callBackEntry )
2590 /* Name the query */
2591 name = g_strdup_printf( "Search '%s'", searchTerm );
2593 /* Set up query request */
2594 if (!strcmp(searchTerm, "*"))
2595 mySearch = g_strdup("*@");
2597 mySearch = g_strdup(searchTerm);
2599 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2603 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2604 queryID = req->queryID;
2606 if( ds->type == ADDR_IF_LDAP ) {
2610 server = ds->rawDataSource;
2611 ldapsvr_new_explicit_search( server, req, folder );
2615 qrymgr_delete_request( queryID );
2624 * Execute the previously registered explicit search.
2626 * \param req Address query request object to execute.
2627 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2630 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2632 AddrQueryObject *aqo;
2636 /* Note: there should only be one query in the list. */
2637 aqo = req->queryList->data;
2639 if( aqo->queryType == ADDRQUERY_LDAP ) {
2643 qry = ( LdapQuery * ) aqo;
2644 server = qry->server;
2646 /* Start the search */
2648 ldapsvr_execute_query( server, qry );
2655 * Start the previously registered search.
2657 * \param queryID ID of search query to be executed.
2658 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2661 gboolean addrindex_start_search( const gint queryID ) {
2664 AddrSearchType searchType;
2667 /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
2668 req = qrymgr_find_request( queryID );
2673 searchType = req->searchType;
2674 if( searchType == ADDRSEARCH_DYNAMIC ) {
2675 retVal = addrindex_start_dynamic( req );
2677 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2678 retVal = addrindex_start_explicit( req );
2685 * Remove results (folder and data) for specified data source and folder.
2686 * \param ds Data source to process.
2687 * \param folder Results folder to remove.
2689 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2690 AddrBookBase *adbase;
2691 AddressCache *cache;
2694 /* printf( "addrindex_remove_results/start\n" ); */
2696 /* Test for folder */
2697 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2698 /* printf( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2699 adbase = ( AddrBookBase * ) ds->rawDataSource;
2700 if( adbase == NULL ) return;
2701 cache = adbase->addressCache;
2703 /* Hide folder to prevent re-display */
2704 addritem_folder_set_hidden( folder, TRUE );
2706 if( ds->type == ADDR_IF_LDAP ) {
2711 qry = ( LdapQuery * ) folder->folderData;
2712 queryID = ADDRQUERY_ID(qry);
2713 /* printf( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2714 delFlag = ldapquery_remove_results( qry );
2716 ldapqry_free( qry );
2718 /* printf( "calling ldapquery_remove_results...done\n" ); */
2721 printf( "delFlag IS-TRUE\n" );
2724 printf( "delFlag IS-FALSE\n" );
2729 /* printf( "addrindex_remove_results/end\n" ); */
2731 /* Delete query request */
2733 qrymgr_delete_request( queryID );
2737 /* **********************************************************************
2738 * Address completion stuff.
2739 * ***********************************************************************
2742 static void addrindex_load_completion_load_persons(
2743 gint (*callBackFunc) ( const gchar *, const gchar *,
2744 const gchar *, const gchar *, GList * ),
2745 AddressDataSource *ds)
2747 GList *listP, *nodeP;
2751 /* Read address book */
2752 if( addrindex_ds_get_modify_flag( ds ) ) {
2753 addrindex_ds_read_data( ds );
2756 if( ! addrindex_ds_get_read_flag( ds ) ) {
2757 addrindex_ds_read_data( ds );
2760 /* Get all groups */
2761 listP = addrindex_ds_get_all_groups( ds );
2764 ItemGroup *group = nodeP->data;
2765 GList *emails = NULL;
2766 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2767 ItemEMail *email = nodeM->data;
2769 emails = g_list_append(emails, email);
2771 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2772 NULL, NULL, emails );
2773 nodeP = g_list_next( nodeP );
2776 /* Free up the list */
2777 g_list_free( listP );
2778 /* Get all persons */
2779 listP = addrindex_ds_get_all_persons( ds );
2782 ItemPerson *person = nodeP->data;
2783 nodeM = person->listEMail;
2785 /* Figure out name to use */
2786 sName = ADDRITEM_NAME(person);
2787 if( sName == NULL || *sName == '\0' ) {
2788 sName = person->nickName;
2791 /* Process each E-Mail address */
2793 ItemEMail *email = nodeM->data;
2795 callBackFunc( sName, email->address, person->nickName,
2796 ADDRITEM_NAME(email), NULL );
2798 nodeM = g_list_next( nodeM );
2800 nodeP = g_list_next( nodeP );
2803 /* Free up the list */
2804 g_list_free( listP );
2808 * This function is used by the address completion function to load
2809 * addresses for all non-external address book interfaces.
2811 * \param callBackFunc Function to be called when an address is
2813 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2814 * or "Any", assume the whole addressbook
2815 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2818 gboolean addrindex_load_completion(
2819 gint (*callBackFunc) ( const gchar *, const gchar *,
2820 const gchar *, const gchar *, GList * ),
2823 GList *nodeIf, *nodeDS;
2825 if( folderpath != NULL ) {
2826 AddressDataSource *book;
2829 /* split the folder path we've received, we'll try to match this path, subpath by
2830 subpath against the book/folder structure in order and restrict loading of
2831 addresses to that subpart (if matches). book/folder path must exist and
2832 folderpath must not be empty or NULL */
2834 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2835 g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath);
2839 if( folder != NULL ) {
2846 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2848 /* Load email addresses */
2849 items = addritem_folder_get_person_list( folder );
2850 for( ; items != NULL; items = g_list_next( items ) ) {
2851 person = items->data;
2852 nodeM = person->listEMail;
2854 /* Figure out name to use */
2855 sName = ADDRITEM_NAME(person);
2856 if( sName == NULL || *sName == '\0' ) {
2857 sName = person->nickName;
2860 /* Process each E-Mail address */
2862 ItemEMail *email = nodeM->data;
2864 callBackFunc( sName, email->address, person->nickName,
2865 ADDRITEM_NAME(email), NULL );
2867 nodeM = g_list_next( nodeM );
2870 /* Free up the list */
2871 mgu_clear_list( items );
2872 g_list_free( items );
2878 if( book != NULL ) {
2880 AddressBookFile *abf = book->rawDataSource;
2882 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf->fileName);
2884 addrindex_load_completion_load_persons( callBackFunc, book );
2889 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
2896 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2898 AddressInterface *iface = nodeIf->data;
2900 nodeIf = g_list_next( nodeIf );
2902 if( ! iface->useInterface || iface->externalQuery )
2905 nodeDS = iface->listSource;
2907 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
2908 nodeDS = g_list_next( nodeDS );
2917 * This function can be used to collect information about
2918 * addressbook entries that contain a specific attribute.
2920 * \param attr Name of attribute to look for
2921 * \param callBackFunc Function to be called when a matching attribute was found
2922 * \return <i>TRUE</i>
2924 gboolean addrindex_load_person_attribute(
2926 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2928 AddressDataSource *ds;
2929 GList *nodeIf, *nodeDS;
2930 GList *listP, *nodeP;
2933 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2936 AddressInterface *iface = nodeIf->data;
2938 nodeIf = g_list_next( nodeIf );
2940 if( ! iface->useInterface || iface->externalQuery )
2943 nodeDS = iface->listSource;
2947 /* Read address book */
2948 if( addrindex_ds_get_modify_flag( ds ) ) {
2949 addrindex_ds_read_data( ds );
2952 if( ! addrindex_ds_get_read_flag( ds ) ) {
2953 addrindex_ds_read_data( ds );
2956 /* Check addressbook name */
2957 cur_bname = addrindex_ds_get_name( ds );
2959 /* Get all persons */
2960 listP = addrindex_ds_get_all_persons( ds );
2963 ItemPerson *person = nodeP->data;
2965 /* Return all ItemPerson's if attr is NULL */
2966 if( attr == NULL ) {
2967 callBackFunc(person, cur_bname);
2970 /* Return ItemPerson's with specific attribute */
2972 nodeA = person->listAttrib;
2973 /* Process each User Attribute */
2975 UserAttribute *attrib = nodeA->data;
2977 !strcmp( attrib->name,attr ) ) {
2978 callBackFunc(person, cur_bname);
2980 nodeA = g_list_next( nodeA );
2983 nodeP = g_list_next( nodeP );
2985 /* Free up the list */
2986 g_list_free( listP );
2988 nodeDS = g_list_next( nodeDS );