2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2003 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * General functions for accessing address index file.
35 #include "addrcache.h"
37 #include "addrindex.h"
39 #include "addrquery.h"
41 #ifndef DEV_STANDALONE
42 #include "prefs_gtk.h"
53 #include "ldapserver.h"
55 #include "ldapquery.h"
58 #define TAG_ADDRESS_INDEX "addressbook"
60 #define TAG_IF_ADDRESS_BOOK "book_list"
61 #define TAG_IF_VCARD "vcard_list"
62 #define TAG_IF_JPILOT "jpilot_list"
63 #define TAG_IF_LDAP "ldap_list"
65 #define TAG_DS_ADDRESS_BOOK "book"
66 #define TAG_DS_VCARD "vcard"
67 #define TAG_DS_JPILOT "jpilot"
68 #define TAG_DS_LDAP "server"
70 /* XML Attribute names */
71 #define ATTAG_BOOK_NAME "name"
72 #define ATTAG_BOOK_FILE "file"
74 #define ATTAG_VCARD_NAME "name"
75 #define ATTAG_VCARD_FILE "file"
77 #define ATTAG_JPILOT_NAME "name"
78 #define ATTAG_JPILOT_FILE "file"
79 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
80 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
81 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
82 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
83 #define ATTAG_JPILOT_CUSTOM "custom-"
85 #define ATTAG_LDAP_NAME "name"
86 #define ATTAG_LDAP_HOST "host"
87 #define ATTAG_LDAP_PORT "port"
88 #define ATTAG_LDAP_BASE_DN "base-dn"
89 #define ATTAG_LDAP_BIND_DN "bind-dn"
90 #define ATTAG_LDAP_BIND_PASS "bind-pass"
91 #define ATTAG_LDAP_CRITERIA "criteria"
92 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
93 #define ATTAG_LDAP_TIMEOUT "timeout"
94 #define ATTAG_LDAP_MAX_AGE "max-age"
95 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
97 #define ELTAG_LDAP_ATTR_SRCH "attribute"
98 #define ATTAG_LDAP_ATTR_NAME "name"
101 #define ATTAG_LDAP_DEFAULT "default"
105 N_("Personal address")
108 #define DISP_NEW_COMMON _("Common address")
109 #define DISP_NEW_PERSONAL _("Personal address")
111 /* Old address book */
112 #define TAG_IF_OLD_COMMON "common_address"
113 #define TAG_IF_OLD_PERSONAL "personal_address"
115 #define DISP_OLD_COMMON _("Common address")
116 #define DISP_OLD_PERSONAL _("Personal address")
119 * Define attribute name-value pair.
121 typedef struct _AddressIfAttr AddressIfAttrib;
122 struct _AddressIfAttr {
128 * Define DOM fragment.
130 typedef struct _AddressIfFrag AddressIfFragment;
131 struct _AddressIfFrag {
138 * Build interface with default values.
140 * \param type Interface type.
141 * \param name Interface name.
142 * \param tagIf XML tag name for interface in address index file.
143 * \param tagDS XML tag name for datasource in address index file.
144 * \return Address interface object.
146 static AddressInterface *addrindex_create_interface(
147 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
149 AddressInterface *iface = g_new0( AddressInterface, 1 );
151 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
152 ADDRITEM_ID(iface) = NULL;
153 ADDRITEM_NAME(iface) = g_strdup( name );
154 ADDRITEM_PARENT(iface) = NULL;
155 ADDRITEM_SUBTYPE(iface) = type;
157 iface->name = g_strdup( name );
158 iface->listTag = g_strdup( tagIf );
159 iface->itemTag = g_strdup( tagDS );
160 iface->legacyFlag = FALSE;
161 iface->haveLibrary = TRUE;
162 iface->useInterface = TRUE;
163 iface->readOnly = TRUE;
165 /* Set callbacks to NULL values - override for each interface */
166 iface->getAccessFlag = NULL;
167 iface->getModifyFlag = NULL;
168 iface->getReadFlag = NULL;
169 iface->getStatusCode = NULL;
170 iface->getReadData = NULL;
171 iface->getRootFolder = NULL;
172 iface->getListFolder = NULL;
173 iface->getListPerson = NULL;
174 iface->getAllPersons = NULL;
175 iface->getAllGroups = NULL;
176 iface->getName = NULL;
177 iface->listSource = NULL;
180 iface->externalQuery = FALSE;
181 iface->searchOrder = 0; /* Ignored */
182 iface->startSearch = NULL;
183 iface->stopSearch = NULL;
189 * Build table of of all address book interfaces.
190 * \param addrIndex Address index object.
192 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
193 AddressInterface *iface;
195 /* Create intrinsic XML address book interface */
196 iface = addrindex_create_interface(
197 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
198 TAG_DS_ADDRESS_BOOK );
199 iface->readOnly = FALSE;
200 iface->getModifyFlag = ( void * ) addrbook_get_modified;
201 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
202 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
203 iface->getStatusCode = ( void * ) addrbook_get_status;
204 iface->getReadData = ( void * ) addrbook_read_data;
205 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
206 iface->getListFolder = ( void * ) addrbook_get_list_folder;
207 iface->getListPerson = ( void * ) addrbook_get_list_person;
208 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
209 iface->getName = ( void * ) addrbook_get_name;
210 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
211 iface->searchOrder = 2;
213 /* Add to list of interfaces in address book */
214 addrIndex->interfaceList =
215 g_list_append( addrIndex->interfaceList, iface );
216 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
218 /* Create vCard interface */
219 iface = addrindex_create_interface(
220 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
221 iface->getModifyFlag = ( void * ) vcard_get_modified;
222 iface->getAccessFlag = ( void * ) vcard_get_accessed;
223 iface->getReadFlag = ( void * ) vcard_get_read_flag;
224 iface->getStatusCode = ( void * ) vcard_get_status;
225 iface->getReadData = ( void * ) vcard_read_data;
226 iface->getRootFolder = ( void * ) vcard_get_root_folder;
227 iface->getListFolder = ( void * ) vcard_get_list_folder;
228 iface->getListPerson = ( void * ) vcard_get_list_person;
229 iface->getAllPersons = ( void * ) vcard_get_all_persons;
230 iface->getName = ( void * ) vcard_get_name;
231 iface->setAccessFlag = ( void * ) vcard_set_accessed;
232 iface->searchOrder = 3;
233 addrIndex->interfaceList =
234 g_list_append( addrIndex->interfaceList, iface );
235 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
237 /* Create JPilot interface */
238 iface = addrindex_create_interface(
239 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
242 iface->haveLibrary = jpilot_test_pilot_lib();
243 iface->useInterface = iface->haveLibrary;
244 iface->getModifyFlag = ( void * ) jpilot_get_modified;
245 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
246 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
247 iface->getStatusCode = ( void * ) jpilot_get_status;
248 iface->getReadData = ( void * ) jpilot_read_data;
249 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
250 iface->getListFolder = ( void * ) jpilot_get_list_folder;
251 iface->getListPerson = ( void * ) jpilot_get_list_person;
252 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
253 iface->getName = ( void * ) jpilot_get_name;
254 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
255 iface->searchOrder = 3;
257 iface->useInterface = FALSE;
258 iface->haveLibrary = FALSE;
260 addrIndex->interfaceList =
261 g_list_append( addrIndex->interfaceList, iface );
262 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
264 /* Create LDAP interface */
265 iface = addrindex_create_interface(
266 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
268 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
269 iface->haveLibrary = ldaputil_test_ldap_lib();
270 iface->useInterface = iface->haveLibrary;
271 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
272 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
273 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
274 iface->getStatusCode = ( void * ) ldapsvr_get_status;
275 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
276 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
277 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
278 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
279 iface->getName = ( void * ) ldapsvr_get_name;
280 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
281 iface->externalQuery = TRUE;
282 iface->searchOrder = 1;
284 iface->useInterface = FALSE;
285 iface->haveLibrary = FALSE;
287 addrIndex->interfaceList =
288 g_list_append( addrIndex->interfaceList, iface );
289 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
291 /* Two old legacy data sources (pre 0.7.0) */
292 iface = addrindex_create_interface(
293 ADDR_IF_COMMON, "Old Address - common",
294 TAG_IF_OLD_COMMON, NULL );
295 iface->legacyFlag = TRUE;
296 addrIndex->interfaceList =
297 g_list_append( addrIndex->interfaceList, iface );
298 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
300 iface = addrindex_create_interface(
301 ADDR_IF_COMMON, "Old Address - personal",
302 TAG_IF_OLD_PERSONAL, NULL );
303 iface->legacyFlag = TRUE;
304 addrIndex->interfaceList =
305 g_list_append( addrIndex->interfaceList, iface );
306 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
312 * \param fragment Fragment to free.
314 static addrindex_free_fragment( AddressIfFragment *fragment ) {
318 node = fragment->children;
320 AddressIfFragment *child = node->data;
321 addrindex_free_fragment( child );
323 node = g_list_next( node );
325 g_list_free( fragment->children );
327 /* Free attributes */
328 node = fragment->attributes;
330 AddressIfAttrib *nv = node->data;
335 node = g_list_next( node );
337 g_list_free( fragment->attributes );
339 g_free( fragment->name );
340 fragment->name = NULL;
341 fragment->attributes = NULL;
342 fragment->children = NULL;
348 * Create a new data source.
349 * \param ifType Interface type to create.
350 * \return Initialized data source.
352 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
353 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
355 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
356 ADDRITEM_ID(ds) = NULL;
357 ADDRITEM_NAME(ds) = NULL;
358 ADDRITEM_PARENT(ds) = NULL;
359 ADDRITEM_SUBTYPE(ds) = 0;
361 ds->rawDataSource = NULL;
362 ds->interface = NULL;
367 * Free up data source.
368 * \param ds Data source to free.
370 void addrindex_free_datasource( AddressDataSource *ds ) {
371 AddressInterface *iface;
374 g_return_if_fail( ds != NULL );
376 iface = ds->interface;
377 if( ds->rawDataSource != NULL ) {
378 if( iface != NULL ) {
379 if( iface->useInterface ) {
380 if( iface->type == ADDR_IF_BOOK ) {
381 AddressBookFile *abf = ds->rawDataSource;
382 addrbook_free_book( abf );
384 else if( iface->type == ADDR_IF_VCARD ) {
385 VCardFile *vcf = ds->rawDataSource;
389 else if( iface->type == ADDR_IF_JPILOT ) {
390 JPilotFile *jpf = ds->rawDataSource;
395 else if( iface->type == ADDR_IF_LDAP ) {
396 LdapServer *server = ds->rawDataSource;
397 cache = server->addressCache;
398 addrcache_use_index( cache, FALSE );
399 ldapsvr_free( server );
406 AddressIfFragment *fragment = ds->rawDataSource;
407 addrindex_free_fragment( fragment );
412 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
413 ADDRITEM_ID(ds) = NULL;
414 ADDRITEM_NAME(ds) = NULL;
415 ADDRITEM_PARENT(ds) = NULL;
416 ADDRITEM_SUBTYPE(ds) = 0;
417 ds->type = ADDR_IF_NONE;
418 ds->interface = NULL;
419 ds->rawDataSource = NULL;
425 * Free up all data sources for specified interface.
426 * \param iface Address interface to process.
428 static void addrindex_free_all_datasources( AddressInterface *iface ) {
429 GList *node = iface->listSource;
431 AddressDataSource *ds = node->data;
432 addrindex_free_datasource( ds );
434 node = g_list_next( node );
439 * Free up specified interface.
440 * \param iface Interface to process.
442 static void addrindex_free_interface( AddressInterface *iface ) {
443 /* Free up data sources */
444 addrindex_free_all_datasources( iface );
445 g_list_free( iface->listSource );
447 /* Free internal storage */
448 g_free( ADDRITEM_ID(iface) );
449 g_free( ADDRITEM_NAME(iface) );
450 g_free( iface->name );
451 g_free( iface->listTag );
452 g_free( iface->itemTag );
454 /* Clear all pointers */
455 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
456 ADDRITEM_ID(iface) = NULL;
457 ADDRITEM_NAME(iface) = NULL;
458 ADDRITEM_PARENT(iface) = NULL;
459 ADDRITEM_SUBTYPE(iface) = 0;
460 iface->type = ADDR_IF_NONE;
462 iface->listTag = NULL;
463 iface->itemTag = NULL;
464 iface->legacyFlag = FALSE;
465 iface->useInterface = FALSE;
466 iface->haveLibrary = FALSE;
467 iface->listSource = NULL;
470 iface->searchOrder = 0;
471 iface->startSearch = NULL;
472 iface->stopSearch = NULL;
478 * Return cache ID for specified data source.
480 * \param addrIndex Address index.
481 * \param ds Data source.
482 * \return ID or NULL if not found. This should be <code>g_free()</code>
485 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
486 gchar *cacheID = NULL;
487 AddrBookBase *adbase;
490 g_return_val_if_fail( addrIndex != NULL, NULL );
491 g_return_val_if_fail( ds != NULL, NULL );
493 adbase = ( AddrBookBase * ) ds->rawDataSource;
495 cache = adbase->addressCache;
497 cacheID = g_strdup( cache->cacheID );
505 * Return reference to data source for specified cacheID.
506 * \param addrIndex Address index.
508 * \return Data source, or NULL if not found.
510 AddressDataSource *addrindex_get_datasource(
511 AddressIndex *addrIndex, const gchar *cacheID )
513 g_return_val_if_fail( addrIndex != NULL, NULL );
514 g_return_val_if_fail( cacheID != NULL, NULL );
515 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
519 * Return reference to address cache for specified cacheID.
520 * \param addrIndex Address index.
522 * \return Address cache, or NULL if not found.
524 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
525 AddressDataSource *ds;
526 AddrBookBase *adbase;
529 g_return_val_if_fail( addrIndex != NULL, NULL );
530 g_return_val_if_fail( cacheID != NULL, NULL );
533 ds = addrindex_get_datasource( addrIndex, cacheID );
535 adbase = ( AddrBookBase * ) ds->rawDataSource;
536 cache = adbase->addressCache;
542 * Add data source into hash table.
543 * \param addrIndex Address index.
544 * \param ds Data source.
546 static void addrindex_hash_add_cache(
547 AddressIndex *addrIndex, AddressDataSource *ds )
551 cacheID = addrindex_get_cache_id( addrIndex, ds );
553 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
558 * Free hash table callback function.
560 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
568 * Free hash table of address cache items.
570 static void addrindex_free_cache_hash( GHashTable *table ) {
571 g_hash_table_freeze( table );
572 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
573 g_hash_table_thaw( table );
574 g_hash_table_destroy( table );
578 * Remove data source from internal hashtable.
579 * \param addrIndex Address index.
580 * \param ds Data source to remove.
582 static void addrindex_hash_remove_cache(
583 AddressIndex *addrIndex, AddressDataSource *ds )
587 cacheID = addrindex_get_cache_id( addrIndex, ds );
589 g_hash_table_remove( addrIndex->hashCache, cacheID );
596 * Create a new address index.
597 * \return Initialized address index object.
599 AddressIndex *addrindex_create_index( void ) {
600 AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
602 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
603 ADDRITEM_ID(addrIndex) = NULL;
604 ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
605 ADDRITEM_PARENT(addrIndex) = NULL;
606 ADDRITEM_SUBTYPE(addrIndex) = 0;
607 addrIndex->filePath = NULL;
608 addrIndex->fileName = NULL;
609 addrIndex->retVal = MGU_SUCCESS;
610 addrIndex->needsConversion = FALSE;
611 addrIndex->wasConverted = FALSE;
612 addrIndex->conversionError = FALSE;
613 addrIndex->interfaceList = NULL;
614 addrIndex->lastType = ADDR_IF_NONE;
615 addrIndex->dirtyFlag = FALSE;
616 addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
617 addrIndex->loadedFlag = FALSE;
618 addrIndex->searchOrder = NULL;
619 addrindex_build_if_list( addrIndex );
624 * Property - Specify file path to address index file.
625 * \param addrIndex Address index.
626 * \param value Path to index file.
628 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
629 g_return_if_fail( addrIndex != NULL );
630 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
634 * Property - Specify file name to address index file.
635 * \param addrIndex Address index.
636 * \param value File name.
638 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
639 g_return_if_fail( addrIndex != NULL );
640 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
644 * Property - Specify file path to be used.
645 * \param addrIndex Address index.
646 * \param value Path to JPilot file.
648 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
649 g_return_if_fail( addrIndex != NULL );
650 addrIndex->dirtyFlag = value;
654 * Property - get loaded flag. Note that this flag is set after reading data
655 * from the address books.
656 * \param addrIndex Address index.
657 * \return <i>TRUE</i> if address index data was loaded.
659 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
660 g_return_val_if_fail( addrIndex != NULL, FALSE );
661 return addrIndex->loadedFlag;
665 * Return list of address interfaces.
666 * \param addrIndex Address index.
667 * \return List of address interfaces.
669 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
670 g_return_val_if_fail( addrIndex != NULL, NULL );
671 return addrIndex->interfaceList;
675 * Free up address index.
676 * \param addrIndex Address index.
678 void addrindex_free_index( AddressIndex *addrIndex ) {
681 g_return_if_fail( addrIndex != NULL );
684 g_list_free( addrIndex->searchOrder );
685 addrIndex->searchOrder = NULL;
687 /* Free internal storage */
688 g_free( ADDRITEM_ID(addrIndex) );
689 g_free( ADDRITEM_NAME(addrIndex) );
690 g_free( addrIndex->filePath );
691 g_free( addrIndex->fileName );
694 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
695 ADDRITEM_ID(addrIndex) = NULL;
696 ADDRITEM_NAME(addrIndex) = NULL;
697 ADDRITEM_PARENT(addrIndex) = NULL;
698 ADDRITEM_SUBTYPE(addrIndex) = 0;
699 addrIndex->filePath = NULL;
700 addrIndex->fileName = NULL;
701 addrIndex->retVal = MGU_SUCCESS;
702 addrIndex->needsConversion = FALSE;
703 addrIndex->wasConverted = FALSE;
704 addrIndex->conversionError = FALSE;
705 addrIndex->lastType = ADDR_IF_NONE;
706 addrIndex->dirtyFlag = FALSE;
708 /* Free up interfaces */
709 node = addrIndex->interfaceList;
711 AddressInterface *iface = node->data;
712 addrindex_free_interface( iface );
713 node = g_list_next( node );
715 g_list_free( addrIndex->interfaceList );
716 addrIndex->interfaceList = NULL;
718 /* Free up hash cache */
719 addrindex_free_cache_hash( addrIndex->hashCache );
720 addrIndex->hashCache = NULL;
722 addrIndex->loadedFlag = FALSE;
728 * Print address index.
729 * \param addrIndex Address index.
730 * \parem stream Stream to print.
732 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
733 g_return_if_fail( addrIndex != NULL );
734 fprintf( stream, "AddressIndex:\n" );
735 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
736 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
737 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
738 fprintf( stream, "\tconverted: '%s'\n",
739 addrIndex->wasConverted ? "yes" : "no" );
740 fprintf( stream, "\tcvt error: '%s'\n",
741 addrIndex->conversionError ? "yes" : "no" );
742 fprintf( stream, "\t---\n" );
746 * Retrieve reference to address interface for specified interface type.
747 * \param addrIndex Address index.
748 * \param ifType Interface type.
749 * \return Address interface, or NULL if not found.
751 AddressInterface *addrindex_get_interface(
752 AddressIndex *addrIndex, AddressIfType ifType )
754 AddressInterface *retVal = NULL;
757 g_return_val_if_fail( addrIndex != NULL, NULL );
759 node = addrIndex->interfaceList;
761 AddressInterface *iface = node->data;
762 node = g_list_next( node );
763 if( iface->type == ifType ) {
772 * Add raw data source to index. The raw data object (an AddressBookFile or
773 * VCardFile object, for example) should be supplied as the raw dataSource
776 * \param addrIndex Address index.
777 * \param ifType Interface type to add.
778 * \param dataSource Actual raw data source to add.
779 * \return Data source added, or NULL if invalid interface type.
781 AddressDataSource *addrindex_index_add_datasource(
782 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
784 AddressInterface *iface;
785 AddressDataSource *ds = NULL;
787 g_return_val_if_fail( addrIndex != NULL, NULL );
788 g_return_val_if_fail( dataSource != NULL, NULL );
790 iface = addrindex_get_interface( addrIndex, ifType );
792 ds = addrindex_create_datasource( ifType );
793 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
795 ds->rawDataSource = dataSource;
796 ds->interface = iface;
797 iface->listSource = g_list_append( iface->listSource, ds );
798 addrIndex->dirtyFlag = TRUE;
800 addrindex_hash_add_cache( addrIndex, ds );
806 * Remove specified data source from index.
807 * \param addrIndex Address index.
808 * \param dataSource Data source to add.
809 * \return Reference to data source if removed, or NULL if data source was not
810 * found in index. Note the this object must still be freed.
812 AddressDataSource *addrindex_index_remove_datasource(
813 AddressIndex *addrIndex, AddressDataSource *dataSource )
815 AddressDataSource *retVal = FALSE;
816 AddressInterface *iface;
818 g_return_val_if_fail( addrIndex != NULL, NULL );
819 g_return_val_if_fail( dataSource != NULL, NULL );
821 iface = addrindex_get_interface( addrIndex, dataSource->type );
823 iface->listSource = g_list_remove( iface->listSource, dataSource );
824 addrIndex->dirtyFlag = TRUE;
825 dataSource->interface = NULL;
827 /* Remove cache from hash table */
828 addrindex_hash_remove_cache( addrIndex, dataSource );
836 * Retrieve a reference to address interface for specified interface type and
837 * XML interface tag name.
838 * \param addrIndex Address index.
839 * \param tag XML interface tag name to match.
840 * \param ifType Interface type to match.
841 * \return Reference to address index, or NULL if not found in index.
843 static AddressInterface *addrindex_tag_get_interface(
844 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
846 AddressInterface *retVal = NULL;
847 GList *node = addrIndex->interfaceList;
850 AddressInterface *iface = node->data;
851 node = g_list_next( node );
853 if( strcmp( iface->listTag, tag ) == 0 ) {
859 if( iface->type == ifType ) {
869 * Retrieve a reference to address interface for specified interface type and
870 * XML datasource tag name.
871 * \param addrIndex Address index.
872 * \param ifType Interface type to match.
873 * \param tag XML datasource tag name to match.
874 * \return Reference to address index, or NULL if not found in index.
876 static AddressInterface *addrindex_tag_get_datasource(
877 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
879 AddressInterface *retVal = NULL;
880 GList *node = addrIndex->interfaceList;
883 AddressInterface *iface = node->data;
884 node = g_list_next( node );
885 if( iface->type == ifType && iface->itemTag ) {
886 if( strcmp( iface->itemTag, tag ) == 0 ) {
895 /* **********************************************************************
896 * Interface XML parsing functions.
897 * ***********************************************************************
901 * Write start of XML element to file.
903 * \param lvl Indentation level.
904 * \param name Element name.
906 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
908 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
914 * Write end of XML element to file.
916 * \param lvl Indentation level.
917 * \param name Element name.
919 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
921 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
928 * Write XML attribute to file.
930 * \param name Attribute name.
931 * \param value Attribute value.
933 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
937 xml_file_put_escape_str( fp, value );
942 * Return DOM fragment for current XML tag from file.
943 * \param file XML file being processed.
944 * \return Fragment representing DOM fragment for configuration element.
946 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
947 AddressIfFragment *fragment;
948 AddressIfFragment *child;
958 prevLevel = file->level;
960 /* Get current tag name */
961 xtag = xml_get_current_tag( file );
963 /* Create new fragment */
964 fragment = g_new0( AddressIfFragment, 1 );
965 fragment->name = g_strdup( xtag->tag );
966 fragment->children = NULL;
967 fragment->attributes = NULL;
969 /* Read attributes */
971 attr = xml_get_current_tag_attr( file );
973 name = ((XMLAttr *)attr->data)->name;
974 value = ((XMLAttr *)attr->data)->value;
975 nv = g_new0( AddressIfAttrib, 1 );
976 nv->name = g_strdup( name );
977 nv->value = g_strdup( value );
978 list = g_list_append( list, nv );
979 attr = g_list_next( attr );
981 fragment->attributes = list;
983 /* Now read the children */
985 rc = xml_parse_next_tag( file );
990 if( file->level < prevLevel ) {
991 /* We must be above level we start at */
994 child = addrindex_read_fragment( file );
995 fragment->children = g_list_append( fragment->children, child );
1002 * Write DOM fragment to file.
1003 * \param fp File to write.
1004 * \param fragment DOM fragment for configuration element.
1005 * \param lvl Indent level.
1007 static void addrindex_write_fragment(
1008 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1013 addrindex_write_elem_s( fp, lvl, fragment->name );
1014 node = fragment->attributes;
1016 AddressIfAttrib *nv = node->data;
1017 addrindex_write_attr( fp, nv->name, nv->value );
1018 node = g_list_next( node );
1020 if( fragment->children ) {
1023 /* Output children */
1024 node = fragment->children;
1026 AddressIfFragment *child = node->data;
1027 addrindex_write_fragment( fp, child, 1+lvl );
1028 node = g_list_next( node );
1031 /* Output closing tag */
1032 addrindex_write_elem_e( fp, lvl, fragment->name );
1041 static void addrindex_print_fragment_r(
1042 const AddressIfFragment *fragment, FILE *stream, gint lvl )
1047 for( i = 0; i < lvl; i++ )
1048 fprintf( stream, " " );
1049 fprintf( stream, "Element:%s:\n", fragment->name );
1050 node = fragment->attributes;
1052 AddressIfAttrib *nv = node->data;
1053 for( i = 0; i < lvl; i++ )
1054 fprintf( stream, " " );
1055 fprintf( stream, " %s : %s\n", nv->name, nv->value );
1056 node = g_list_next( node );
1058 node = fragment->children;
1060 AddressIfFragment *child = node->data;
1061 addrindex_print_fragment_r( child, stream, 1+lvl );
1062 node = g_list_next( node );
1066 static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
1067 addrindex_print_fragment_r( fragment, stream, 0 );
1072 * Read/parse address index file, creating a data source for a regular
1073 * intrinsic XML addressbook.
1074 * \param file Address index file.
1075 * \return Data source.
1077 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1078 AddressDataSource *ds;
1079 AddressBookFile *abf;
1082 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1083 abf = addrbook_create_book();
1084 attr = xml_get_current_tag_attr( file );
1086 gchar *name = ((XMLAttr *)attr->data)->name;
1087 gchar *value = ((XMLAttr *)attr->data)->value;
1088 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1089 addrbook_set_name( abf, value );
1091 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1092 addrbook_set_file( abf, value );
1094 attr = g_list_next( attr );
1096 ds->rawDataSource = abf;
1100 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1101 AddressBookFile *abf = ds->rawDataSource;
1103 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1104 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1105 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1106 fputs( " />\n", fp );
1110 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1111 AddressDataSource *ds;
1115 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1116 vcf = vcard_create();
1117 attr = xml_get_current_tag_attr( file );
1119 gchar *name = ((XMLAttr *)attr->data)->name;
1120 gchar *value = ((XMLAttr *)attr->data)->value;
1121 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1122 vcard_set_name( vcf, value );
1124 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1125 vcard_set_file( vcf, value );
1127 attr = g_list_next( attr );
1129 ds->rawDataSource = vcf;
1133 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1134 VCardFile *vcf = ds->rawDataSource;
1136 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1137 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1138 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1139 fputs( " />\n", fp );
1144 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1145 AddressDataSource *ds;
1149 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1150 jpf = jpilot_create();
1151 attr = xml_get_current_tag_attr( file );
1153 gchar *name = ((XMLAttr *)attr->data)->name;
1154 gchar *value = ((XMLAttr *)attr->data)->value;
1155 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1156 jpilot_set_name( jpf, value );
1158 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1159 jpilot_set_file( jpf, value );
1161 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1162 jpilot_add_custom_label( jpf, value );
1164 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1165 jpilot_add_custom_label( jpf, value );
1167 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1168 jpilot_add_custom_label( jpf, value );
1170 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1171 jpilot_add_custom_label( jpf, value );
1173 attr = g_list_next( attr );
1175 ds->rawDataSource = jpf;
1179 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1180 JPilotFile *jpf = ds->rawDataSource;
1184 GList *customLbl = jpilot_get_custom_labels( jpf );
1185 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1186 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1187 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1192 g_snprintf( name, sizeof(name), "%s%d",
1193 ATTAG_JPILOT_CUSTOM, ind );
1194 addrindex_write_attr( fp, name, node->data );
1196 node = g_list_next( node );
1198 fputs( " />\n", fp );
1204 * Just read/write DOM fragments (preserve data found in file).
1206 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1207 AddressDataSource *ds;
1209 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1210 ds->rawDataSource = addrindex_read_fragment( file );
1214 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1215 AddressIfFragment *fragment = ds->rawDataSource;
1217 addrindex_write_fragment( fp, fragment, lvl );
1224 * Parse LDAP criteria attribute data from XML file.
1225 * \param file Index file.
1226 * \param ctl LDAP control object to populate.
1228 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1237 if( file == NULL ) {
1242 prevLevel = file->level;
1243 xtagPrev = xml_get_current_tag( file );
1245 rc = xml_parse_next_tag( file );
1247 /* Terminate prematurely */
1248 mgu_free_dlist( list );
1252 if( file->level < prevLevel ) {
1253 /* We must be above level we start at */
1257 /* Get a tag (element) */
1258 xtag = xml_get_current_tag( file );
1259 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1260 /* LDAP criteria attribute */
1261 attr = xml_get_current_tag_attr( file );
1263 gchar *name = ((XMLAttr *)attr->data)->name;
1264 gchar *value = ((XMLAttr *)attr->data)->value;
1265 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1266 if( value && strlen( value ) > 0 ) {
1267 list = g_list_append(
1268 list, g_strdup( value ) );
1271 attr = g_list_next( attr );
1275 if( xtag != xtagPrev ) {
1276 /* Found a new tag */
1283 /* Build list of search attributes */
1284 ldapctl_criteria_list_clear( ctl );
1287 ldapctl_criteria_list_add( ctl, node->data );
1288 g_free( node->data );
1290 node = g_list_next( node );
1292 g_list_free( list );
1297 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1298 AddressDataSource *ds;
1302 gchar *serverName = NULL;
1303 gchar *criteria = NULL;
1304 gboolean bSearch = FALSE;
1305 gboolean cvtFlag = TRUE;
1307 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1308 ctl = ldapctl_create();
1309 attr = xml_get_current_tag_attr( file );
1311 gchar *name = ((XMLAttr *)attr->data)->name;
1312 gchar *value = ((XMLAttr *)attr->data)->value;
1313 gint ivalue = atoi( value );
1315 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1316 if( serverName ) g_free( serverName );
1317 serverName = g_strdup( value );
1319 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1320 ldapctl_set_host( ctl, value );
1322 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1323 ldapctl_set_port( ctl, ivalue );
1325 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1326 ldapctl_set_base_dn( ctl, value );
1328 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1329 ldapctl_set_bind_dn( ctl, value );
1331 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1332 ldapctl_set_bind_password( ctl, value );
1334 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1335 if( criteria ) g_free( criteria );
1336 criteria = g_strdup( value );
1338 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1339 ldapctl_set_max_entries( ctl, ivalue );
1341 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1342 ldapctl_set_timeout( ctl, ivalue );
1344 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1345 ldapctl_set_max_query_age( ctl, ivalue );
1347 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1350 if( strcmp( value, "yes" ) == 0 ) {
1354 attr = g_list_next( attr );
1357 server = ldapsvr_create();
1358 ldapsvr_set_name( server, serverName );
1359 ldapsvr_set_search_flag( server, bSearch );
1360 g_free( serverName );
1361 ldapsvr_set_control( server, ctl );
1362 ds->rawDataSource = server;
1364 addrindex_parse_ldap_attrlist( file, ctl );
1366 * If criteria have been specified and no attributes were listed, then
1367 * convert old style criteria into an attribute list. Any criteria will
1368 * be dropped when saving data.
1371 if( ! ldapctl_get_criteria_list( ctl ) ) {
1372 ldapctl_parse_ldap_search( ctl, criteria );
1377 * If no search flag was found, then we are converting from old format
1378 * server data to new format.
1381 ldapsvr_set_search_flag( server, TRUE );
1383 /* ldapsvr_print_data( server, stdout ); */
1388 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1389 LdapServer *server = ds->rawDataSource;
1390 LdapControl *ctl = NULL;
1395 ctl = server->control;
1397 if( ctl == NULL ) return;
1399 /* Output start element with attributes */
1400 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1401 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1402 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1404 sprintf( value, "%d", ctl->port );
1405 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1407 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1408 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1409 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1411 sprintf( value, "%d", ctl->maxEntries );
1412 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1413 sprintf( value, "%d", ctl->timeOut );
1414 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1415 sprintf( value, "%d", ctl->maxQueryAge );
1416 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1418 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1419 server->searchFlag ? "yes" : "no" );
1423 /* Output attributes */
1424 node = ldapctl_get_criteria_list( ctl );
1426 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1427 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1429 node = g_list_next( node );
1432 /* End of element */
1433 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1439 * Just read/write DOM fragments (preserve data found in file).
1441 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1442 AddressDataSource *ds;
1444 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1445 ds->rawDataSource = addrindex_read_fragment( file );
1449 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1450 AddressIfFragment *fragment = ds->rawDataSource;
1452 addrindex_write_fragment( fp, fragment, lvl );
1457 /* **********************************************************************
1458 * Address index I/O functions.
1459 * ***********************************************************************
1462 * Read address index file, creating appropriate data sources for each address
1465 * \param addrIndex Address index.
1466 * \param file Address index file.
1468 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1471 AddressInterface *iface = NULL, *dsIFace = NULL;
1472 AddressDataSource *ds;
1475 addrIndex->loadedFlag = FALSE;
1477 prev_level = file->level;
1478 rc = xml_parse_next_tag( file );
1479 if( file->level == 0 ) return;
1481 xtag = xml_get_current_tag( file );
1483 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1485 addrIndex->lastType = iface->type;
1486 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1489 dsIFace = addrindex_tag_get_datasource(
1490 addrIndex, addrIndex->lastType, xtag->tag );
1492 /* Add data source to list */
1494 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1495 ds = addrindex_parse_book( file );
1496 if( ds->rawDataSource ) {
1497 addrbook_set_path( ds->rawDataSource,
1498 addrIndex->filePath );
1501 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1502 ds = addrindex_parse_vcard( file );
1504 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1505 ds = addrindex_parse_jpilot( file );
1507 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1508 ds = addrindex_parse_ldap( file );
1511 ds->interface = dsIFace;
1512 addrindex_hash_add_cache( addrIndex, ds );
1513 dsIFace->listSource =
1514 g_list_append( dsIFace->listSource, ds );
1522 * Search order sorting comparison function for building search order list.
1524 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1525 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1526 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1528 return ifaceA->searchOrder - ifaceB->searchOrder;
1532 * Build list of data sources to process.
1533 * \param addrIndex Address index object.
1535 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1536 AddressInterface *iface;
1539 /* Clear existing list */
1540 g_list_free( addrIndex->searchOrder );
1541 addrIndex->searchOrder = NULL;
1543 /* Build new list */
1544 nodeIf = addrIndex->interfaceList;
1546 AddressInterface *iface = nodeIf->data;
1547 if( iface->searchOrder > 0 ) {
1548 /* Add to search order list */
1549 addrIndex->searchOrder = g_list_insert_sorted(
1550 addrIndex->searchOrder, iface,
1551 addrindex_search_order_compare );
1553 nodeIf = g_list_next( nodeIf );
1556 nodeIf = addrIndex->searchOrder;
1558 AddressInterface *iface = nodeIf->data;
1559 nodeIf = g_list_next( nodeIf );
1564 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1565 XMLFile *file = NULL;
1566 gchar *fileSpec = NULL;
1568 g_return_val_if_fail( addrIndex != NULL, -1 );
1570 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1571 addrIndex->retVal = MGU_NO_FILE;
1572 file = xml_open_file( fileSpec );
1575 if( file == NULL ) {
1577 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1579 return addrIndex->retVal;
1582 addrIndex->retVal = MGU_BAD_FORMAT;
1583 if( xml_get_dtd( file ) == 0 ) {
1584 if( xml_parse_next_tag( file ) == 0 ) {
1585 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1586 addrindex_read_index( addrIndex, file );
1587 addrIndex->retVal = MGU_SUCCESS;
1591 xml_close_file( file );
1593 addrindex_build_search_order( addrIndex );
1595 return addrIndex->retVal;
1598 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1599 GList *nodeIF, *nodeDS;
1601 gint lvlItem = 1 + lvlList;
1603 nodeIF = addrIndex->interfaceList;
1605 AddressInterface *iface = nodeIF->data;
1606 if( ! iface->legacyFlag ) {
1607 nodeDS = iface->listSource;
1608 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1611 AddressDataSource *ds = nodeDS->data;
1613 if( iface->type == ADDR_IF_BOOK ) {
1614 addrindex_write_book( fp, ds, lvlItem );
1616 if( iface->type == ADDR_IF_VCARD ) {
1617 addrindex_write_vcard( fp, ds, lvlItem );
1619 if( iface->type == ADDR_IF_JPILOT ) {
1620 addrindex_write_jpilot( fp, ds, lvlItem );
1622 if( iface->type == ADDR_IF_LDAP ) {
1623 addrindex_write_ldap( fp, ds, lvlItem );
1626 nodeDS = g_list_next( nodeDS );
1628 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1630 nodeIF = g_list_next( nodeIF );
1635 * Write data to specified file.
1636 * Enter: addrIndex Address index object.
1637 * newFile New file name.
1638 * return: Status code, from addrIndex->retVal.
1639 * Note: File will be created in directory specified by addrIndex.
1641 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1644 #ifndef DEV_STANDALONE
1648 g_return_val_if_fail( addrIndex != NULL, -1 );
1650 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1651 addrIndex->retVal = MGU_OPEN_FILE;
1652 #ifdef DEV_STANDALONE
1653 fp = fopen( fileSpec, "wb" );
1656 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1658 pfile = prefs_write_open( fileSpec );
1662 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
1663 conv_get_current_charset_str() );
1665 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1668 addrindex_write_index( addrIndex, fp );
1669 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1671 addrIndex->retVal = MGU_SUCCESS;
1672 #ifdef DEV_STANDALONE
1675 if( prefs_file_close( pfile ) < 0 ) {
1676 addrIndex->retVal = MGU_ERROR_WRITE;
1682 return addrIndex->retVal;
1686 * Save address index data to original file.
1687 * return: Status code, from addrIndex->retVal.
1689 gint addrindex_save_data( AddressIndex *addrIndex ) {
1690 g_return_val_if_fail( addrIndex != NULL, -1 );
1692 addrIndex->retVal = MGU_NO_FILE;
1693 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1694 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1696 addrindex_write_to( addrIndex, addrIndex->fileName );
1697 if( addrIndex->retVal == MGU_SUCCESS ) {
1698 addrIndex->dirtyFlag = FALSE;
1700 return addrIndex->retVal;
1704 * Save all address book files which may have changed.
1705 * Return: Status code, set if there was a problem saving data.
1707 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1708 gint retVal = MGU_SUCCESS;
1709 GList *nodeIf, *nodeDS;
1711 nodeIf = addrIndex->interfaceList;
1713 AddressInterface *iface = nodeIf->data;
1714 if( iface->type == ADDR_IF_BOOK ) {
1715 nodeDS = iface->listSource;
1717 AddressDataSource *ds = nodeDS->data;
1718 AddressBookFile *abf = ds->rawDataSource;
1719 if( addrbook_get_dirty( abf ) ) {
1720 if( addrbook_get_read_flag( abf ) ) {
1721 addrbook_save_data( abf );
1722 if( abf->retVal != MGU_SUCCESS ) {
1723 retVal = abf->retVal;
1727 nodeDS = g_list_next( nodeDS );
1731 nodeIf = g_list_next( nodeIf );
1737 /* **********************************************************************
1738 * Address book conversion to new format.
1739 * ***********************************************************************
1742 #define ELTAG_IF_OLD_FOLDER "folder"
1743 #define ELTAG_IF_OLD_GROUP "group"
1744 #define ELTAG_IF_OLD_ITEM "item"
1745 #define ELTAG_IF_OLD_NAME "name"
1746 #define ELTAG_IF_OLD_ADDRESS "address"
1747 #define ELTAG_IF_OLD_REMARKS "remarks"
1748 #define ATTAG_IF_OLD_NAME "name"
1750 #define TEMPNODE_ROOT 0
1751 #define TEMPNODE_FOLDER 1
1752 #define TEMPNODE_GROUP 2
1753 #define TEMPNODE_ADDRESS 3
1755 typedef struct _AddressCvt_Node AddressCvtNode;
1756 struct _AddressCvt_Node {
1765 * Parse current address item.
1767 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1772 nn = g_new0( AddressCvtNode, 1 );
1773 nn->type = TEMPNODE_ADDRESS;
1776 level = file->level;
1779 xml_parse_next_tag(file);
1780 if (file->level < level) return nn;
1782 element = xml_get_element( file );
1783 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1784 nn->name = g_strdup( element );
1786 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1787 nn->address = g_strdup( element );
1789 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1790 nn->remarks = g_strdup( element );
1792 xml_parse_next_tag(file);
1797 * Create a temporary node below specified node.
1799 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1801 nn = g_new0( AddressCvtNode, 1 );
1803 nn->name = g_strdup( name );
1804 nn->remarks = g_strdup( rem );
1805 node->list = g_list_append( node->list, nn );
1810 * Process current temporary node.
1812 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1815 AddressCvtNode *newNode = NULL;
1820 prev_level = file->level;
1821 xml_parse_next_tag( file );
1822 if (file->level < prev_level) return;
1826 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1827 attr = xml_get_current_tag_attr(file);
1829 name = ((XMLAttr *)attr->data)->name;
1830 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1831 value = ((XMLAttr *)attr->data)->value;
1834 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1835 addrindex_add_obj( file, newNode );
1838 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1839 attr = xml_get_current_tag_attr(file);
1841 name = ((XMLAttr *)attr->data)->name;
1842 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1843 value = ((XMLAttr *)attr->data)->value;
1846 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1847 addrindex_add_obj( file, newNode );
1849 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1850 newNode = addrindex_parse_item( file );
1851 node->list = g_list_append( node->list, newNode );
1854 /* printf( "invalid: !!! \n" ); */
1855 attr = xml_get_current_tag_attr( file );
1861 * Consume all nodes below current tag.
1863 static void addrindex_consume_tree( XMLFile *file ) {
1870 prev_level = file->level;
1871 xml_parse_next_tag( file );
1872 if (file->level < prev_level) return;
1874 xtag = xml_get_current_tag( file );
1875 /* printf( "tag : %s\n", xtag->tag ); */
1876 element = xml_get_element( file );
1877 attr = xml_get_current_tag_attr( file );
1878 /* show_attribs( attr ); */
1879 /* printf( "\ttag value : %s :\n", element ); */
1880 addrindex_consume_tree( file );
1885 * Print temporary tree.
1887 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1890 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1891 fprintf( stream, "\tname :%s:\n", node->name );
1892 fprintf( stream, "\taddr :%s:\n", node->address );
1893 fprintf( stream, "\trems :%s:\n", node->remarks );
1895 fprintf( stream, "\t--list----\n" );
1899 AddressCvtNode *lNode = list->data;
1900 list = g_list_next( list );
1901 addrindex_print_node( lNode, stream );
1903 fprintf( stream, "\t==list-%d==\n", node->type );
1907 * Free up temporary tree.
1909 static void addrindex_free_node( AddressCvtNode *node ) {
1910 GList *list = node->list;
1913 AddressCvtNode *lNode = list->data;
1914 list = g_list_next( list );
1915 addrindex_free_node( lNode );
1917 node->type = TEMPNODE_ROOT;
1918 g_free( node->name );
1919 g_free( node->address );
1920 g_free( node->remarks );
1921 g_list_free( node->list );
1926 * Process address book for specified node.
1928 static void addrindex_process_node(
1929 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1930 ItemGroup *parentGrp, ItemFolder *folderGrp )
1933 ItemFolder *itemFolder = NULL;
1934 ItemGroup *itemGParent = parentGrp;
1935 ItemFolder *itemGFolder = folderGrp;
1936 AddressCache *cache = abf->addressCache;
1938 if( node->type == TEMPNODE_ROOT ) {
1939 itemFolder = parent;
1941 else if( node->type == TEMPNODE_FOLDER ) {
1942 itemFolder = addritem_create_item_folder();
1943 addritem_folder_set_name( itemFolder, node->name );
1944 addrcache_id_folder( cache, itemFolder );
1945 addrcache_folder_add_folder( cache, parent, itemFolder );
1948 else if( node->type == TEMPNODE_GROUP ) {
1949 ItemGroup *itemGroup;
1952 /* Create a folder for group */
1953 fName = g_strdup_printf( "Cvt - %s", node->name );
1954 itemGFolder = addritem_create_item_folder();
1955 addritem_folder_set_name( itemGFolder, fName );
1956 addrcache_id_folder( cache, itemGFolder );
1957 addrcache_folder_add_folder( cache, parent, itemGFolder );
1960 /* Add group into folder */
1961 itemGroup = addritem_create_item_group();
1962 addritem_group_set_name( itemGroup, node->name );
1963 addrcache_id_group( cache, itemGroup );
1964 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1965 itemGParent = itemGroup;
1967 else if( node->type == TEMPNODE_ADDRESS ) {
1968 ItemPerson *itemPerson;
1969 ItemEMail *itemEMail;
1971 /* Create person and email objects */
1972 itemPerson = addritem_create_item_person();
1973 addritem_person_set_common_name( itemPerson, node->name );
1974 addrcache_id_person( cache, itemPerson );
1975 itemEMail = addritem_create_item_email();
1976 addritem_email_set_address( itemEMail, node->address );
1977 addritem_email_set_remarks( itemEMail, node->remarks );
1978 addrcache_id_email( cache, itemEMail );
1979 addrcache_person_add_email( cache, itemPerson, itemEMail );
1981 /* Add person into appropriate folder */
1983 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
1986 addrcache_folder_add_person( cache, parent, itemPerson );
1989 /* Add email address only into group */
1991 addrcache_group_add_email( cache, parentGrp, itemEMail );
1997 AddressCvtNode *lNode = list->data;
1998 list = g_list_next( list );
1999 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2004 * Process address book to specified file number.
2006 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2007 gboolean retVal = FALSE;
2008 AddressBookFile *abf = NULL;
2009 AddressCvtNode *rootNode = NULL;
2010 gchar *newFile = NULL;
2011 GList *fileList = NULL;
2014 /* Setup root node */
2015 rootNode = g_new0( AddressCvtNode, 1 );
2016 rootNode->type = TEMPNODE_ROOT;
2017 rootNode->name = g_strdup( "root" );
2018 rootNode->list = NULL;
2019 addrindex_add_obj( file, rootNode );
2020 /* addrindex_print_node( rootNode, stdout ); */
2022 /* Create new address book */
2023 abf = addrbook_create_book();
2024 addrbook_set_name( abf, displayName );
2025 addrbook_set_path( abf, addrIndex->filePath );
2027 /* Determine next available file number */
2028 fileList = addrbook_get_bookfile_list( abf );
2030 fileNum = 1 + abf->maxValue;
2032 g_list_free( fileList );
2035 newFile = addrbook_gen_new_file_name( fileNum );
2037 addrbook_set_file( abf, newFile );
2040 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2042 /* addrbook_dump_book( abf, stdout ); */
2043 addrbook_save_data( abf );
2044 addrIndex->retVal = abf->retVal;
2045 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2047 addrbook_free_book( abf );
2049 addrindex_free_node( rootNode );
2052 /* Create entries in address index */
2054 abf = addrbook_create_book();
2055 addrbook_set_name( abf, displayName );
2056 addrbook_set_path( abf, addrIndex->filePath );
2057 addrbook_set_file( abf, newFile );
2058 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2065 * Process tree converting data.
2067 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2075 prev_level = file->level;
2076 xml_parse_next_tag( file );
2077 if (file->level < prev_level) return;
2079 xtag = xml_get_current_tag( file );
2080 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2081 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2082 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2083 addrIndex->needsConversion = FALSE;
2084 addrIndex->wasConverted = TRUE;
2089 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2090 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2091 addrIndex->needsConversion = FALSE;
2092 addrIndex->wasConverted = TRUE;
2097 element = xml_get_element( file );
2098 attr = xml_get_current_tag_attr( file );
2099 /* show_attribs( attr ); */
2100 /* printf( "\ttag value : %s :\n", element ); */
2101 addrindex_consume_tree( file );
2105 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2106 XMLFile *file = NULL;
2109 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2110 addrIndex->retVal = MGU_NO_FILE;
2111 file = xml_open_file( fileSpec );
2114 if( file == NULL ) {
2115 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2116 return addrIndex->retVal;
2119 addrIndex->retVal = MGU_BAD_FORMAT;
2120 if( xml_get_dtd( file ) == 0 ) {
2121 if( xml_parse_next_tag( file ) == 0 ) {
2122 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2123 addrindex_convert_tree( addrIndex, file );
2127 xml_close_file( file );
2128 return addrIndex->retVal;
2132 * Create a new address book file.
2134 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2135 gboolean retVal = FALSE;
2136 AddressBookFile *abf = NULL;
2137 gchar *newFile = NULL;
2138 GList *fileList = NULL;
2141 /* Create new address book */
2142 abf = addrbook_create_book();
2143 addrbook_set_name( abf, displayName );
2144 addrbook_set_path( abf, addrIndex->filePath );
2146 /* Determine next available file number */
2147 fileList = addrbook_get_bookfile_list( abf );
2149 fileNum = 1 + abf->maxValue;
2151 g_list_free( fileList );
2154 newFile = addrbook_gen_new_file_name( fileNum );
2156 addrbook_set_file( abf, newFile );
2159 addrbook_save_data( abf );
2160 addrIndex->retVal = abf->retVal;
2161 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2162 addrbook_free_book( abf );
2165 /* Create entries in address index */
2167 abf = addrbook_create_book();
2168 addrbook_set_name( abf, displayName );
2169 addrbook_set_path( abf, addrIndex->filePath );
2170 addrbook_set_file( abf, newFile );
2171 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2178 * Read data for address index performing a conversion if necesary.
2179 * Enter: addrIndex Address index object.
2180 * return: Status code, from addrIndex->retVal.
2181 * Note: New address book files will be created in directory specified by
2182 * addrIndex. Three files will be created, for the following:
2183 * "Common addresses"
2184 * "Personal addresses"
2185 * "Gathered addresses" - a new address book.
2187 gint addrindex_read_data( AddressIndex *addrIndex ) {
2188 g_return_val_if_fail( addrIndex != NULL, -1 );
2190 addrIndex->conversionError = FALSE;
2191 addrindex_read_file( addrIndex );
2192 if( addrIndex->retVal == MGU_SUCCESS ) {
2193 if( addrIndex->needsConversion ) {
2194 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2195 addrIndex->conversionError = TRUE;
2198 addrIndex->conversionError = TRUE;
2201 addrIndex->dirtyFlag = TRUE;
2203 return addrIndex->retVal;
2207 * Create new address books for a new address index.
2208 * Enter: addrIndex Address index object.
2209 * return: Status code, from addrIndex->retVal.
2210 * Note: New address book files will be created in directory specified by
2211 * addrIndex. Three files will be created, for the following:
2212 * "Common addresses"
2213 * "Personal addresses"
2214 * "Gathered addresses" - a new address book.
2216 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2219 g_return_val_if_fail( addrIndex != NULL, -1 );
2221 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2223 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2224 addrIndex->dirtyFlag = TRUE;
2226 return addrIndex->retVal;
2229 /* **********************************************************************
2230 * New interface stuff.
2231 * ***********************************************************************
2235 * Return modified flag for specified data source.
2237 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2238 gboolean retVal = FALSE;
2239 AddressInterface *iface;
2241 if( ds == NULL ) return retVal;
2242 iface = ds->interface;
2243 if( iface == NULL ) return retVal;
2244 if( iface->getModifyFlag ) {
2245 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2251 * Return accessed flag for specified data source.
2253 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2254 gboolean retVal = FALSE;
2255 AddressInterface *iface;
2257 if( ds == NULL ) return retVal;
2258 iface = ds->interface;
2259 if( iface == NULL ) return retVal;
2260 if( iface->getAccessFlag ) {
2261 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2267 * Return data read flag for specified data source.
2269 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2270 gboolean retVal = TRUE;
2271 AddressInterface *iface;
2273 if( ds == NULL ) return retVal;
2274 iface = ds->interface;
2275 if( iface == NULL ) return retVal;
2276 if( iface->getReadFlag ) {
2277 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2283 * Return status code for specified data source.
2285 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2286 gint retVal = MGU_SUCCESS;
2287 AddressInterface *iface;
2289 if( ds == NULL ) return retVal;
2290 iface = ds->interface;
2291 if( iface == NULL ) return retVal;
2292 if( iface->getStatusCode ) {
2293 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2299 * Return data read flag for specified data source.
2301 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2302 gint retVal = MGU_SUCCESS;
2303 AddressInterface *iface;
2305 if( ds == NULL ) return retVal;
2306 iface = ds->interface;
2307 if( iface == NULL ) return retVal;
2308 if( iface->getReadData ) {
2309 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2315 * Return data read flag for specified data source.
2317 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2318 ItemFolder *retVal = NULL;
2319 AddressInterface *iface;
2321 if( ds == NULL ) return retVal;
2322 iface = ds->interface;
2323 if( iface == NULL ) return retVal;
2324 if( iface->getRootFolder ) {
2325 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2331 * Return list of folders for specified data source.
2333 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2334 GList *retVal = FALSE;
2335 AddressInterface *iface;
2337 if( ds == NULL ) return retVal;
2338 iface = ds->interface;
2339 if( iface == NULL ) return retVal;
2340 if( iface->getListFolder ) {
2341 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2347 * Return list of persons in root folder for specified data source.
2349 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2350 GList *retVal = FALSE;
2351 AddressInterface *iface;
2353 if( ds == NULL ) return retVal;
2354 iface = ds->interface;
2355 if( iface == NULL ) return retVal;
2356 if( iface->getListPerson ) {
2357 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2363 * Return name for specified data source.
2365 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2366 gchar *retVal = FALSE;
2367 AddressInterface *iface;
2369 if( ds == NULL ) return retVal;
2370 iface = ds->interface;
2371 if( iface == NULL ) return retVal;
2372 if( iface->getName ) {
2373 retVal = ( iface->getName ) ( ds->rawDataSource );
2379 * Set the access flag inside the data source.
2381 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2382 AddressInterface *iface;
2384 if( ds == NULL ) return;
2385 iface = ds->interface;
2386 if( iface == NULL ) return;
2387 if( iface->setAccessFlag ) {
2388 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2393 * Return read only flag for specified data source.
2395 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2396 AddressInterface *iface;
2397 if( ds == NULL ) return TRUE;
2398 iface = ds->interface;
2399 if( iface == NULL ) return TRUE;
2400 return iface->readOnly;
2404 * Return list of all persons for specified data source.
2406 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2407 GList *retVal = NULL;
2408 AddressInterface *iface;
2410 if( ds == NULL ) return retVal;
2411 iface = ds->interface;
2412 if( iface == NULL ) return retVal;
2413 if( iface->getAllPersons ) {
2414 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2420 * Return list of all groups for specified data source.
2422 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2423 GList *retVal = NULL;
2424 AddressInterface *iface;
2426 if( ds == NULL ) return retVal;
2427 iface = ds->interface;
2428 if( iface == NULL ) return retVal;
2429 if( iface->getAllGroups ) {
2430 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2435 /* **********************************************************************
2436 * Address search stuff.
2437 * ***********************************************************************
2441 * Current query ID. This is incremented for each query created.
2443 static gint _currentQueryID_ = 0;
2446 * Variables for the search that is being performed.
2448 static gchar *_searchTerm_ = NULL;
2449 static gpointer _searchTarget_ = NULL;
2450 static AddrSearchCallbackFunc *_searchCallback_ = NULL;
2453 * Setup or register the search that will be performed.
2454 * \param addrIndex Address index object.
2455 * \param searchTerm Search term. A private copy will be made.
2456 * \param target Target object that will receive data.
2457 * \param callBack Callback function.
2458 * \return ID allocated to query that will be executed.
2460 gint addrindex_setup_search(
2461 AddressIndex *addrIndex, const gchar *searchTerm,
2462 const gpointer target, AddrSearchCallbackFunc callBack )
2466 /* printf( "search term ::%s::\n", searchTerm ); */
2467 g_free( _searchTerm_ );
2468 _searchTerm_ = g_strdup( searchTerm );
2470 queryID = ++_currentQueryID_;
2471 _searchTarget_ = target;
2472 _searchCallback_ = callBack;
2473 /* printf( "query ID ::%d::\n", queryID ); */
2478 * Perform the search for specified address cache.
2479 * \param cache Cache to be searched.
2480 * \param queryID ID of search query to be executed.
2482 static void addrindex_search_cache( AddressCache *cache, const gint queryID ) {
2483 AddrCacheIndex *index;
2486 index = cache->searchIndex;
2487 if( index == NULL ) return;
2488 if( index->invalid ) {
2489 addrcache_build_index( cache );
2493 printf( "query ::%d:: searching index for ::%s::\n", queryID, _searchTerm_ );
2495 listEMail = addrcindex_search( index, _searchTerm_ );
2496 ( _searchCallback_ ) ( queryID, listEMail, _searchTarget_ );
2497 g_list_free( listEMail );
2499 /* printf( "searching index done\n" ); */
2504 * LDAP callback entry point for each address entry found.
2505 * \param qry LDAP query.
2506 * \param listEMail List of Item EMail objects found.
2508 static void addrindex_ldap_entry_cb( LdapQuery *qry, GList *listEMail ) {
2512 printf( "\naddrindex::addrindex_ldap_entry_cb ::%s::\n", qry->queryName );
2516 ItemEMail *email = node->data;
2517 /* printf( "\temail ::%s::\n", email->address ); */
2518 node = g_list_next( node );
2520 if( _searchCallback_ ) {
2521 ( _searchCallback_ ) ( qry->queryID, listEMail, _searchTarget_ );
2523 g_list_free( listEMail );
2527 * LDAP callback entry point for completion of search.
2528 * \param qry LDAP query.
2530 static void addrindex_ldap_end_cb( LdapQuery *qry ) {
2531 /* printf( "\naddrindex::addrindex_ldap_end_cb ::%s::\n", qry->queryName ); */
2535 * Return results of previous query.
2537 * \return List of ItemEMail objects.
2539 static void addrindex_ldap_use_previous( const ItemFolder *folder, const gint queryID )
2546 if( _searchCallback_ ) {
2547 node = folder->listPerson;
2549 AddrItemObject *aio = node->data;
2550 if( aio && aio->type == ITEMTYPE_PERSON ) {
2551 ItemPerson *person = node->data;
2552 nodeEM = person->listEMail;
2554 ItemEMail *email = nodeEM->data;
2555 nodeEM = g_list_next( nodeEM );
2556 listEMail = g_list_append( listEMail, email );
2559 node = g_list_next( node );
2561 ( _searchCallback_ ) ( queryID, listEMail, _searchTarget_ );
2562 g_list_free( listEMail );
2566 LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm );
2569 * Construct an LDAP query and initiate an LDAP search.
2570 * \param server LDAP server object.
2571 * \param queryID ID of search query to be executed.
2573 static void addrindex_search_ldap( LdapServer *server, const gint queryID ) {
2577 if( ! server->searchFlag ) return;
2578 printf( "Searching ::%s::\n", ldapsvr_get_name( server ) );
2580 /* Retire any aged queries */
2581 ldapsvr_retire_query( server );
2583 /* Test whether any queries for the same term exist */
2584 qry = ldapsvr_locate_query( server, _searchTerm_ );
2586 ItemFolder *folder = qry->folder;
2588 /* Touch query to ensure it hangs around for a bit longer */
2589 ldapqry_touch( qry );
2591 addrindex_ldap_use_previous( folder, queryID );
2596 /* Construct a query */
2597 qry = ldapqry_create();
2598 ldapqry_set_query_id( qry, queryID );
2599 ldapqry_set_search_value( qry, _searchTerm_ );
2600 ldapqry_set_query_type( qry, LDAPQUERY_DYNAMIC );
2601 ldapqry_set_callback_entry( qry, addrindex_ldap_entry_cb );
2602 ldapqry_set_callback_end( qry, addrindex_ldap_end_cb );
2604 /* Name the query */
2605 name = g_strdup_printf( "Search for '%s'", _searchTerm_ );
2606 ldapqry_set_name( qry, name );
2609 ldapsvr_add_query( server, qry );
2610 /* printf( "addrindex_search_ldap::executing dynamic search...\n" ); */
2611 ldapsvr_execute_query( server, qry );
2615 * Construct an LDAP query and initiate an LDAP search.
2616 * \param server LDAP server object to search.
2617 * \param searchTerm Search term to locate.
2618 * \param callbackEnd Function to call when search has terminated.
2621 void addrindex_search_ldap_noid(
2622 LdapServer *server, const gchar *searchTerm, void * callbackEnd )
2627 /* Construct a query */
2628 qry = ldapqry_create();
2629 ldapqry_set_search_value( qry, searchTerm );
2630 ldapqry_set_query_type( qry, LDAPQUERY_STATIC );
2631 ldapqry_set_callback_end( qry, callbackEnd );
2633 /* Name the query */
2634 name = g_strdup_printf( "Static Search for '%s'", searchTerm );
2635 ldapqry_set_name( qry, name );
2638 ldapsvr_add_query( server, qry );
2639 /* printf( "addrindex_search_ldap_noid::executing static search...\n" ); */
2640 ldapsvr_execute_query( server, qry );
2645 * Perform the previously registered search.
2646 * \param addrIndex Address index object.
2647 * \param queryID ID of search query to be executed.
2648 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2651 gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
2652 AddressInterface *iface;
2653 AddressDataSource *ds;
2654 AddressCache *cache;
2659 /* printf( "addrindex_start_search::%d::\n", queryID ); */
2660 nodeIf = addrIndex->searchOrder;
2662 iface = nodeIf->data;
2663 nodeIf = g_list_next( nodeIf );
2665 if( ! iface->useInterface ) {
2670 nodeDS = iface->listSource;
2673 nodeDS = g_list_next( nodeDS );
2676 if( type == ADDR_IF_BOOK ) {
2677 AddressBookFile *abf = ds->rawDataSource;
2678 cache = abf->addressCache;
2680 else if( type == ADDR_IF_VCARD ) {
2681 VCardFile *vcf = ds->rawDataSource;
2682 cache = vcf->addressCache;
2685 else if( type == ADDR_IF_JPILOT ) {
2686 JPilotFile *jpf = ds->rawDataSource;
2687 cache = jpf->addressCache;
2691 else if( type == ADDR_IF_LDAP ) {
2692 LdapServer *server = ds->rawDataSource;
2693 addrindex_search_ldap( server, queryID );
2697 addrindex_search_cache( cache, queryID );
2705 * Stop the previously registered search.
2706 * \param addrIndex Address index object.
2707 * \param queryID ID of search query to stop.
2709 void addrindex_stop_search( AddressIndex *addrIndex, const gint queryID ){
2711 AddressInterface *iface;
2712 AddressDataSource *ds;
2717 /* If query ID does not match, search has not been setup */
2718 /* if( queryID != _queryID_ ) return; */
2720 /* printf( "addrindex_stop_search::%d::\n", queryID ); */
2721 nodeIf = addrIndex->searchOrder;
2723 iface = nodeIf->data;
2724 nodeIf = g_list_next( nodeIf );
2726 if( ! iface->useInterface ) {
2731 nodeDS = iface->listSource;
2734 nodeDS = g_list_next( nodeDS );
2735 if( type == ADDR_IF_LDAP ) {
2736 LdapServer *server = ds->rawDataSource;
2737 ldapsvr_stop_all_query( server );
2745 * Read all address books that do not support dynamic queries.
2746 * \param addrIndex Address index object.
2748 void addrindex_read_all( AddressIndex *addrIndex ) {
2749 AddressInterface *iface;
2750 AddressDataSource *ds;
2754 nodeIf = addrIndex->searchOrder;
2756 iface = nodeIf->data;
2757 nodeIf = g_list_next( nodeIf );
2759 if( ! iface->useInterface ) {
2762 if( iface->externalQuery ) {
2765 nodeDS = iface->listSource;
2768 nodeDS = g_list_next( nodeDS );
2770 /* Read address book */
2771 if( addrindex_ds_get_modify_flag( ds ) ) {
2772 addrindex_ds_read_data( ds );
2776 if( ! addrindex_ds_get_read_flag( ds ) ) {
2777 addrindex_ds_read_data( ds );
2782 addrIndex->loadedFlag = TRUE;
2786 * Perform a simple search of all non-query type data sources for specified
2787 * search term. If several entries are found, only the first item is
2788 * returned. Interfaces that require a time-consuming "external query" are
2789 * ignored for this search.
2791 * \param addrIndex Address index object.
2792 * \param searchTerm Search term to find. Typically an email address.
2793 * \return List of references to zero or mail E-Mail object that was found in
2794 * the address books, or <i>NULL</i> if nothing found. This list
2795 * *SHOULD* be freed when done.
2797 GList *addrindex_quick_search_list(
2798 AddressIndex *addrIndex, const gchar *searchTerm )
2800 GList *listRet = NULL;
2802 AddressInterface *iface;
2803 AddressDataSource *ds;
2804 AddressCache *cache;
2805 AddrCacheIndex *index;
2812 nodeIf = addrIndex->searchOrder;
2814 iface = nodeIf->data;
2815 nodeIf = g_list_next( nodeIf );
2817 if( ! iface->useInterface ) {
2818 /* Ignore interfaces that don't have a library */
2821 if( iface->externalQuery ) {
2822 /* Ignore interfaces that require a "query" */
2827 nodeDS = iface->listSource;
2830 nodeDS = g_list_next( nodeDS );
2833 if( type == ADDR_IF_BOOK ) {
2834 AddressBookFile *abf = ds->rawDataSource;
2835 cache = abf->addressCache;
2837 else if( type == ADDR_IF_VCARD ) {
2838 VCardFile *vcf = ds->rawDataSource;
2839 cache = vcf->addressCache;
2842 else if( type == ADDR_IF_JPILOT ) {
2843 JPilotFile *jpf = ds->rawDataSource;
2844 cache = jpf->addressCache;
2848 index = cache->searchIndex;
2849 if( index == NULL ) {
2852 if( index->invalid ) {
2853 addrcache_build_index( cache );
2855 listEMail = addrcindex_search( index, searchTerm );
2858 email = listEMail->data;
2859 listRet = g_list_append( listRet, email );
2860 nodeEM = g_list_next( nodeEM );
2862 g_list_free( listEMail );
2870 * Perform a simple search of all non-query type data sources for specified
2871 * search term. If several entries are found, only the first item is
2872 * returned. Interfaces that require a time-consuming "external query" are
2873 * ignored for this search.
2875 * \param addrIndex Address index object.
2876 * \param searchTerm Search term to find. Typically an email address.
2877 * \return Reference to a single E-Mail object that was found in the address
2878 * book, or <i>NULL</i> if nothing found. This should *NOT* be freed
2881 ItemEMail *addrindex_quick_search_single(
2882 AddressIndex *addrIndex, const gchar *searchTerm )
2884 ItemEMail *email = NULL;
2885 AddressInterface *iface;
2886 AddressDataSource *ds;
2887 AddressCache *cache;
2888 AddrCacheIndex *index;
2894 /* printf( "addrindex_quick_search::%s::\n", searchTerm ); */
2895 nodeIf = addrIndex->searchOrder;
2897 iface = nodeIf->data;
2898 nodeIf = g_list_next( nodeIf );
2900 if( ! iface->useInterface ) {
2903 if( iface->externalQuery ) {
2908 nodeDS = iface->listSource;
2911 nodeDS = g_list_next( nodeDS );
2914 if( type == ADDR_IF_BOOK ) {
2915 AddressBookFile *abf = ds->rawDataSource;
2916 cache = abf->addressCache;
2918 else if( type == ADDR_IF_VCARD ) {
2919 VCardFile *vcf = ds->rawDataSource;
2920 cache = vcf->addressCache;
2923 else if( type == ADDR_IF_JPILOT ) {
2924 JPilotFile *jpf = ds->rawDataSource;
2925 cache = jpf->addressCache;
2929 index = cache->searchIndex;
2930 if( index == NULL ) {
2933 if( index->invalid ) {
2934 addrcache_build_index( cache );
2937 listEMail = addrcindex_search( index, searchTerm );
2939 email = listEMail->data;
2941 g_list_free( listEMail );