we're loading functions explicitly from dynamically loaded so's, so remove explicit...
[claws.git] / src / addrindex.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2001-2002 Match Grun
4  *
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.
9  *
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.
14  *
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.
18  */
19
20 /*
21  * General functions for accessing address index file.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "defs.h"
29
30 #include <glib.h>
31
32 #include "intl.h"
33 #include "mgutils.h"
34 #include "addritem.h"
35 #include "addrcache.h"
36 #include "addrbook.h"
37 #include "addrindex.h"
38 #include "xml.h"
39
40 #ifndef DEV_STANDALONE
41 #include "prefs.h"
42 #include "codeconv.h"
43 #endif
44
45 #include "vcard.h"
46
47 #ifdef USE_JPILOT
48 #include "jpilot.h"
49 #endif
50
51 #ifdef USE_LDAP
52 #include "syldap.h"
53 #endif
54
55 #define TAG_ADDRESS_INDEX    "addressbook"
56
57 #define TAG_IF_ADDRESS_BOOK  "book_list"
58 #define TAG_IF_VCARD         "vcard_list"
59 #define TAG_IF_JPILOT        "jpilot_list"
60 #define TAG_IF_LDAP          "ldap_list"
61
62 #define TAG_DS_ADDRESS_BOOK  "book"
63 #define TAG_DS_VCARD         "vcard"
64 #define TAG_DS_JPILOT        "jpilot"
65 #define TAG_DS_LDAP          "server"
66
67 /* XML Attribute names */
68 #define ATTAG_BOOK_NAME       "name"
69 #define ATTAG_BOOK_FILE       "file"
70
71 #define ATTAG_VCARD_NAME      "name"
72 #define ATTAG_VCARD_FILE      "file"
73
74 #define ATTAG_JPILOT_NAME     "name"
75 #define ATTAG_JPILOT_FILE     "file"
76 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
77 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
78 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
79 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
80 #define ATTAG_JPILOT_CUSTOM   "custom-"
81
82 #define ATTAG_LDAP_NAME       "name"
83 #define ATTAG_LDAP_HOST       "host"
84 #define ATTAG_LDAP_PORT       "port"
85 #define ATTAG_LDAP_BASE_DN    "base-dn"
86 #define ATTAG_LDAP_BIND_DN    "bind-dn"
87 #define ATTAG_LDAP_BIND_PASS  "bind-pass"
88 #define ATTAG_LDAP_CRITERIA   "criteria"
89 #define ATTAG_LDAP_MAX_ENTRY  "max-entry"
90 #define ATTAG_LDAP_TIMEOUT    "timeout"
91
92 #if 0
93 N_("Common address")
94 N_("Personal address")
95 #endif
96
97 #define DISP_NEW_COMMON       _("Common address")
98 #define DISP_NEW_PERSONAL     _("Personal address")
99
100 /* Old address book */
101 #define TAG_IF_OLD_COMMON     "common_address"
102 #define TAG_IF_OLD_PERSONAL   "personal_address"
103
104 #define DISP_OLD_COMMON       _("Common address")
105 #define DISP_OLD_PERSONAL     _("Personal address")
106
107 typedef struct _AddressIfAttr AddressIfAttrib;
108 struct _AddressIfAttr {
109         gchar *name;
110         gchar *value;
111 };
112
113 /*
114 * Build interface with default values.
115 */
116 static AddressInterface *addrindex_create_interface( gint type, gchar *name, gchar *tagIf, gchar *tagDS ) {
117         AddressInterface *iface = g_new0( AddressInterface, 1 );
118         ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
119         ADDRITEM_ID(iface) = NULL;
120         ADDRITEM_NAME(iface) = g_strdup( name );
121         ADDRITEM_PARENT(iface) = NULL;
122         ADDRITEM_SUBTYPE(iface) = type;
123         iface->type = type;
124         iface->name = g_strdup( name );
125         iface->listTag = g_strdup( tagIf );
126         iface->itemTag = g_strdup( tagDS );
127         iface->legacyFlag = FALSE;
128         iface->haveLibrary = TRUE;
129         iface->useInterface = TRUE;
130         iface->readOnly      = TRUE;
131         iface->getAccessFlag = NULL;
132         iface->getModifyFlag = NULL;
133         iface->getReadFlag   = NULL;
134         iface->getStatusCode = NULL;
135         iface->getReadData   = NULL;
136         iface->getRootFolder = NULL;
137         iface->getListFolder = NULL;
138         iface->getListPerson = NULL;
139         iface->getAllPersons = NULL;
140         iface->getAllGroups  = NULL;
141         iface->getName       = NULL;
142         iface->listSource = NULL;
143         return iface;
144 }
145
146 /*
147 * Build table of interfaces.
148 */
149 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
150         AddressInterface *iface;
151
152         iface = addrindex_create_interface( ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK, TAG_DS_ADDRESS_BOOK );
153         iface->readOnly      = FALSE;
154         iface->getModifyFlag = ( void * ) addrbook_get_modified;
155         iface->getAccessFlag = ( void * ) addrbook_get_accessed;
156         iface->getReadFlag   = ( void * ) addrbook_get_read_flag;
157         iface->getStatusCode = ( void * ) addrbook_get_status;
158         iface->getReadData   = ( void * ) addrbook_read_data;
159         iface->getRootFolder = ( void * ) addrbook_get_root_folder;
160         iface->getListFolder = ( void * ) addrbook_get_list_folder;
161         iface->getListPerson = ( void * ) addrbook_get_list_person;
162         iface->getAllPersons = ( void * ) addrbook_get_all_persons;
163         iface->getName       = ( void * ) addrbook_get_name;
164         iface->setAccessFlag = ( void * ) addrbook_set_accessed;
165         addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
166         ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
167
168         iface = addrindex_create_interface( ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
169         iface->getModifyFlag = ( void * ) vcard_get_modified;
170         iface->getAccessFlag = ( void * ) vcard_get_accessed;
171         iface->getReadFlag   = ( void * ) vcard_get_read_flag;
172         iface->getStatusCode = ( void * ) vcard_get_status;
173         iface->getReadData   = ( void * ) vcard_read_data;
174         iface->getRootFolder = ( void * ) vcard_get_root_folder;
175         iface->getListFolder = ( void * ) vcard_get_list_folder;
176         iface->getListPerson = ( void * ) vcard_get_list_person;
177         iface->getAllPersons = ( void * ) vcard_get_all_persons;
178         iface->getName       = ( void * ) vcard_get_name;
179         iface->setAccessFlag = ( void * ) vcard_set_accessed;
180         addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
181         ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
182
183         iface = addrindex_create_interface( ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT, TAG_DS_JPILOT );
184 #ifdef USE_JPILOT
185         iface->haveLibrary = jpilot_test_pilot_lib();
186         iface->useInterface = iface->haveLibrary;
187         iface->getModifyFlag = ( void * ) jpilot_get_modified;
188         iface->getAccessFlag = ( void * ) jpilot_get_accessed;
189         iface->getReadFlag   = ( void * ) jpilot_get_read_flag;
190         iface->getStatusCode = ( void * ) jpilot_get_status;
191         iface->getReadData   = ( void * ) jpilot_read_data;
192         iface->getRootFolder = ( void * ) jpilot_get_root_folder;
193         iface->getListFolder = ( void * ) jpilot_get_list_folder;
194         iface->getListPerson = ( void * ) jpilot_get_list_person;
195         iface->getAllPersons = ( void * ) jpilot_get_all_persons;
196         iface->getName       = ( void * ) jpilot_get_name;
197         iface->setAccessFlag = ( void * ) jpilot_set_accessed;
198 #else
199         iface->useInterface = FALSE;
200         iface->haveLibrary = FALSE;
201 #endif
202         addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
203         ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
204
205         iface = addrindex_create_interface( ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
206 #ifdef USE_LDAP
207         iface->haveLibrary = syldap_test_ldap_lib();
208         iface->useInterface = iface->haveLibrary;
209         iface->getAccessFlag = ( void * ) syldap_get_accessed;
210         /* iface->getModifyFlag = ( void * ) syldap_get_modified; */
211         /* iface->getReadFlag   = ( void * ) syldap_get_read_flag; */
212         iface->getStatusCode = ( void * ) syldap_get_status;
213         iface->getReadData   = ( void * ) syldap_read_data;
214         iface->getRootFolder = ( void * ) syldap_get_root_folder;
215         iface->getListFolder = ( void * ) syldap_get_list_folder;
216         iface->getListPerson = ( void * ) syldap_get_list_person;
217         iface->getName       = ( void * ) syldap_get_name;
218         iface->setAccessFlag = ( void * ) syldap_set_accessed;
219 #else
220         iface->useInterface = FALSE;
221         iface->haveLibrary = FALSE;
222 #endif
223         addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
224         ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
225
226         /* Two old legacy data sources */
227         iface = addrindex_create_interface(
228                         ADDR_IF_COMMON, "Old Address - common",
229                         TAG_IF_OLD_COMMON, NULL );
230         iface->legacyFlag = TRUE;
231         addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
232         ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
233
234         iface = addrindex_create_interface(
235                         ADDR_IF_COMMON, "Old Address - personal",
236                         TAG_IF_OLD_PERSONAL, NULL );
237         iface->legacyFlag = TRUE;
238         addrIndex->interfaceList = g_list_append( addrIndex->interfaceList, iface );
239         ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
240
241 }
242
243 /*
244 * Free name-value pairs.
245 */
246 static void addrindex_free_attributes( GList *list ) {
247         GList *node = list;
248         while( node ) {
249                 AddressIfAttrib *nv = node->data;
250                 g_free( nv->name ); nv->name = NULL;
251                 g_free( nv->value ); nv->value = NULL;
252                 g_free( nv );
253                 node->data = NULL;
254                 node = g_list_next( node );
255         }
256         g_list_free( list );
257 }
258
259 /*
260 * Create new data source.
261 * Enter: ifType Interface type to create.
262 * Return: Initialized data source.
263 */
264 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
265         AddressDataSource *ds = g_new0( AddressDataSource, 1 );
266
267         ds = g_new0( AddressDataSource, 1 );
268         ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
269         ADDRITEM_ID(ds) = NULL;
270         ADDRITEM_NAME(ds) = NULL;
271         ADDRITEM_PARENT(ds) = NULL;
272         ADDRITEM_SUBTYPE(ds) = 0;
273         ds->type = ifType;
274         ds->rawDataSource = NULL;
275         ds->interface = NULL;
276         return ds;
277 }
278
279 /*
280 * Free up data source.
281 */
282 void addrindex_free_datasource( AddressDataSource *ds ) {
283         AddressInterface *iface;
284
285         g_return_if_fail( ds != NULL );
286
287         iface = ds->interface;
288         if( iface == NULL ) return;
289         if( ds->rawDataSource != NULL ) {
290                 if( iface->useInterface ) {
291                         if( iface->type == ADDR_IF_BOOK ) {
292                                 AddressBookFile *abf = ds->rawDataSource;
293                                 addrbook_free_book( abf );
294                         }
295                         else if( iface->type == ADDR_IF_VCARD ) {
296                                 VCardFile *vcf = ds->rawDataSource;
297                                 vcard_free( vcf );
298                         }
299 #ifdef USE_JPILOT
300                         else if( iface->type == ADDR_IF_JPILOT ) {
301                                 JPilotFile *jpf = ds->rawDataSource;
302                                 jpilot_free( jpf );
303                         }
304 #endif
305 #ifdef USE_LDAP
306                         else if( iface->type == ADDR_IF_LDAP ) {
307                                 SyldapServer *server = ds->rawDataSource;
308                                 syldap_free( server );
309                         }
310 #endif
311                 }
312                 else {
313                         GList *list = ds->rawDataSource;
314                         addrindex_free_attributes( list );
315                 }
316         }
317
318         ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
319         ADDRITEM_ID(ds) = NULL;
320         ADDRITEM_NAME(ds) = NULL;
321         ADDRITEM_PARENT(ds) = NULL;
322         ADDRITEM_SUBTYPE(ds) = 0;
323         ds->type = ADDR_IF_NONE;
324         ds->interface = NULL;
325         ds->rawDataSource = NULL;
326         g_free( ds );
327 }
328
329 static void addrindex_free_all_datasources( AddressInterface *iface ) {
330         GList *node = iface->listSource;
331         while( node ) {
332                 AddressDataSource *ds = node->data;
333                 addrindex_free_datasource( ds );
334                 node->data = NULL;
335                 node = g_list_next( node );
336         }
337 }
338
339 static void addrindex_free_interface( AddressInterface *iface ) {
340         addrindex_free_all_datasources( iface );
341
342         g_free( ADDRITEM_ID(iface) );
343         g_free( ADDRITEM_NAME(iface) );
344         g_free( iface->name );
345         g_free( iface->listTag );
346         g_free( iface->itemTag );
347
348         ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
349         ADDRITEM_ID(iface) = NULL;
350         ADDRITEM_NAME(iface) = NULL;
351         ADDRITEM_PARENT(iface) = NULL;
352         ADDRITEM_SUBTYPE(iface) = 0;
353         iface->type = ADDR_IF_NONE;
354         iface->name = NULL;
355         iface->listTag = NULL;
356         iface->itemTag = NULL;
357         iface->legacyFlag = FALSE;
358         iface->useInterface = FALSE;
359         iface->haveLibrary = FALSE;
360
361         g_list_free( iface->listSource );
362         iface->listSource = NULL;
363 }
364
365 /*
366  * Return cache ID for specified data source.
367  * Enter: addrIndex Address index.
368  *        ds        Data source.
369  * Return: ID or NULL if not found. This can be g_free() when done.
370  */
371 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
372         gchar *cacheID = NULL;
373         AddrBookBase *adbase;
374         AddressCache *cache;
375
376         g_return_val_if_fail( addrIndex != NULL, NULL );
377         g_return_val_if_fail( ds != NULL, NULL );
378
379         adbase = ( AddrBookBase * ) ds->rawDataSource;
380         if( adbase ) {
381                 cache = adbase->addressCache;
382                 if( cache ) {
383                         cacheID = g_strdup( cache->cacheID );
384                 }
385         }
386
387         return cacheID;
388 }
389
390 /*
391  * Return data source for specified cacheID.
392  * Enter: addrIndex Address index.
393  *        cacheID   ID.
394  * Return: Data source, or NULL if not found.
395  */
396 AddressDataSource *addrindex_get_datasource( AddressIndex *addrIndex, const gchar *cacheID ) {
397         g_return_val_if_fail( addrIndex != NULL, NULL );
398         g_return_val_if_fail( cacheID != NULL, NULL );
399         return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
400 }
401
402 /*
403  * Return cache for specified cacheID.
404  * Enter: addrIndex Address index.
405  *        cacheID   ID.
406  * Return: Address cache, or NULL if not found.
407  */
408 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
409         AddressDataSource *ds;
410         AddrBookBase *adbase;
411         AddressCache *cache;
412
413         g_return_val_if_fail( addrIndex != NULL, NULL );
414         g_return_val_if_fail( cacheID != NULL, NULL );
415
416         cache = NULL;
417         ds = addrindex_get_datasource( addrIndex, cacheID );
418         if( ds ) {
419                 adbase = ( AddrBookBase * ) ds->rawDataSource;
420                 cache = adbase->addressCache;
421         }
422         return cache;
423 }
424
425 /*
426  * Add data source into hash.
427  * Enter: addrIndex Address index.
428  *        ds        Data source.
429  */
430 static addrindex_hash_add_cache( AddressIndex *addrIndex, AddressDataSource *ds ) {
431         gchar *cacheID;
432
433         cacheID = addrindex_get_cache_id( addrIndex, ds );
434         if( cacheID ) {
435                 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
436         }
437 }
438
439 /*
440 * Free hash table callback function.
441 */
442 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
443         printf( "free cache db: %s\n", key );
444         g_free( key );
445         key = NULL;
446         value = NULL;
447         return TRUE;
448 }
449
450 /*
451 * Free hash table of address cache items.
452 */
453 static void addrindex_free_cache_hash( GHashTable *table ) {
454         g_hash_table_freeze( table );
455         g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
456         g_hash_table_thaw( table );
457         g_hash_table_destroy( table );
458 }
459
460 /*
461 * Remove address cache for specified data source from internal hashtable.
462 */
463 static void addrindex_hash_remove_cache( AddressIndex *addrIndex, AddressDataSource *ds ) {
464         gchar *cacheID;
465
466         cacheID = addrindex_get_cache_id( addrIndex, ds );
467         if( cacheID ) {
468                 g_hash_table_remove( addrIndex->hashCache, cacheID );
469                 g_free( cacheID );
470                 cacheID = NULL;
471         }
472 }
473
474 /*
475 * Create new object.
476 */
477 AddressIndex *addrindex_create_index( void ) {
478         AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
479
480         ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
481         ADDRITEM_ID(addrIndex) = NULL;
482         ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
483         ADDRITEM_PARENT(addrIndex) = NULL;
484         ADDRITEM_SUBTYPE(addrIndex) = 0;
485         addrIndex->filePath = NULL;
486         addrIndex->fileName = NULL;
487         addrIndex->retVal = MGU_SUCCESS;
488         addrIndex->needsConversion = FALSE;
489         addrIndex->wasConverted = FALSE;
490         addrIndex->conversionError = FALSE;
491         addrIndex->interfaceList = NULL;
492         addrIndex->lastType = ADDR_IF_NONE;
493         addrIndex->dirtyFlag = FALSE;
494         addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
495         addrindex_build_if_list( addrIndex );
496         return addrIndex;
497 }
498
499 /*
500 * Specify file to be used.
501 */
502 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
503         g_return_if_fail( addrIndex != NULL );
504         addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
505 }
506 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
507         g_return_if_fail( addrIndex != NULL );
508         addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
509 }
510 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
511         g_return_if_fail( addrIndex != NULL );
512         addrIndex->dirtyFlag = value;
513 }
514
515 /*
516 * Return list of interfaces.
517 */
518 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
519         g_return_val_if_fail( addrIndex != NULL, NULL );
520         return addrIndex->interfaceList;
521 }
522
523 /*
524 * Free up object.
525 */
526 void addrindex_free_index( AddressIndex *addrIndex ) {
527         GList *node;
528
529         g_return_if_fail( addrIndex != NULL );
530
531         g_free( ADDRITEM_ID(addrIndex) );
532         g_free( ADDRITEM_NAME(addrIndex) );
533         g_free( addrIndex->filePath );
534         g_free( addrIndex->fileName );
535         ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
536         ADDRITEM_ID(addrIndex) = NULL;
537         ADDRITEM_NAME(addrIndex) = NULL;
538         ADDRITEM_PARENT(addrIndex) = NULL;
539         ADDRITEM_SUBTYPE(addrIndex) = 0;
540         addrIndex->filePath = NULL;
541         addrIndex->fileName = NULL;
542         addrIndex->retVal = MGU_SUCCESS;
543         addrIndex->needsConversion = FALSE;
544         addrIndex->wasConverted = FALSE;
545         addrIndex->conversionError = FALSE;
546         addrIndex->lastType = ADDR_IF_NONE;
547         addrIndex->dirtyFlag = FALSE;
548         node = addrIndex->interfaceList;
549         while( node ) {
550                 AddressInterface *iface = node->data;
551                 addrindex_free_interface( iface );
552                 node = g_list_next( node );
553         }
554         g_list_free( addrIndex->interfaceList );
555         addrIndex->interfaceList = NULL;
556         addrindex_free_cache_hash( addrIndex->hashCache );
557         addrIndex->hashCache = NULL;
558         g_free( addrIndex );
559 }
560
561 /*
562 * Print address index.
563 */
564 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
565         g_return_if_fail( addrIndex != NULL );
566         fprintf( stream, "AddressIndex:\n" );
567         fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
568         fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
569         fprintf( stream, "\t   status: %d : '%s'\n", addrIndex->retVal, mgu_error2string( addrIndex->retVal ) );
570         fprintf( stream, "\tconverted: '%s'\n", addrIndex->wasConverted ? "yes" : "no" );
571         fprintf( stream, "\tcvt error: '%s'\n", addrIndex->conversionError ? "yes" : "no" );
572         fprintf( stream, "\t---\n" );
573 }
574
575 /*
576 * Retrieve specified interface from index.
577 */
578 AddressInterface *addrindex_get_interface(
579         AddressIndex *addrIndex, AddressIfType ifType )
580 {
581         AddressInterface *retVal = NULL;
582         GList *node;
583
584         g_return_val_if_fail( addrIndex != NULL, NULL );
585
586         node = addrIndex->interfaceList;
587         while( node ) {
588                 AddressInterface *iface = node->data;
589                 node = g_list_next( node );
590                 if( iface->type == ifType ) {
591                         retVal = iface;
592                         break;
593                 }
594         }
595         return retVal;
596 }
597
598 /*
599 * Add data source to index.
600 * Enter: addrIndex  Address index object.
601 *        ifType     Interface type to add.
602 *        dataSource Actual data source to add.
603 * Return: TRUE if data source was added.
604 * Note: The raw data object (for example, AddressBookFile or VCardFile object) should be
605 * supplied as the dataSource argument.
606 */
607 AddressDataSource *addrindex_index_add_datasource(
608         AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
609 {
610         AddressInterface *iface;
611         AddressDataSource *ds = NULL;
612
613         g_return_val_if_fail( addrIndex != NULL, NULL );
614         g_return_val_if_fail( dataSource != NULL, NULL );
615
616         iface = addrindex_get_interface( addrIndex, ifType );
617         if( iface ) {
618                 ds = addrindex_create_datasource( ifType );
619                 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
620                 ds->type = ifType;
621                 ds->rawDataSource = dataSource;
622                 ds->interface = iface;
623                 iface->listSource = g_list_append( iface->listSource, ds );
624                 addrIndex->dirtyFlag = TRUE;
625
626                 addrindex_hash_add_cache( addrIndex, ds );
627         }
628         return ds;
629 }
630
631 /*
632 * Remove data source from index.
633 * Enter: addrIndex  Address index object.
634 *        dataSource Data source to remove.
635 * Return: Data source if removed, or NULL if data source was not found in
636 * index. Note the this object must still be freed.
637 */
638 AddressDataSource *addrindex_index_remove_datasource(
639         AddressIndex *addrIndex, AddressDataSource *dataSource )
640 {
641         AddressDataSource *retVal = FALSE;
642         AddressInterface *iface;
643
644         g_return_val_if_fail( addrIndex != NULL, NULL );
645         g_return_val_if_fail( dataSource != NULL, NULL );
646
647         iface = addrindex_get_interface( addrIndex, dataSource->type );
648         if( iface ) {
649                 iface->listSource = g_list_remove( iface->listSource, dataSource );
650                 addrIndex->dirtyFlag = TRUE;
651                 dataSource->interface = NULL;
652
653                 /* Remove cache from hash table */
654                 addrindex_hash_remove_cache( addrIndex, dataSource );
655
656                 retVal = dataSource;
657         }
658         return retVal;
659 }
660
661 static AddressInterface *addrindex_tag_get_interface(
662         AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
663 {
664         AddressInterface *retVal = NULL;
665         GList *node = addrIndex->interfaceList;
666
667         while( node ) {
668                 AddressInterface *iface = node->data;
669                 node = g_list_next( node );
670                 if( tag ) {
671                         if( strcmp( iface->listTag, tag ) == 0 ) {
672                                 retVal = iface;
673                                 break;
674                         }
675                 }
676                 else {
677                         if( iface->type == ifType ) {
678                                 retVal = iface;
679                                 break;
680                         }
681                 }
682         }
683         return retVal;
684 }
685
686 static AddressInterface *addrindex_tag_get_datasource(
687         AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
688 {
689         AddressInterface *retVal = NULL;
690         GList *node = addrIndex->interfaceList;
691
692         while( node ) {
693                 AddressInterface *iface = node->data;
694                 node = g_list_next( node );
695                 if( iface->type == ifType && iface->itemTag ) {
696                         if( strcmp( iface->itemTag, tag ) == 0 ) {
697                                 retVal = iface;
698                                 break;
699                         }
700                 }
701         }
702         return retVal;
703 }
704
705 /* **********************************************************************
706 * Interface XML parsing functions.
707 * ***********************************************************************
708 */
709 /*
710 static void show_attribs( GList *attr ) {
711         while( attr ) {
712                 gchar *name = ((XMLAttr *)attr->data)->name;
713                 gchar *value = ((XMLAttr *)attr->data)->value;
714                 printf( "\tattr value : %s :%s:\n", name, value );
715                 attr = g_list_next( attr );
716         }
717         printf( "\t---\n" );
718 }
719 */
720
721 static void addrindex_write_elem_s( FILE *fp, gint lvl, gchar *name ) {
722         gint i;
723         for( i = 0; i < lvl; i++ ) fputs( "  ", fp );
724         fputs( "<", fp );
725         fputs( name, fp );
726 }
727
728 static void addrindex_write_elem_e( FILE *fp, gint lvl, gchar *name ) {
729         gint i;
730         for( i = 0; i < lvl; i++ ) fputs( "  ", fp );
731         fputs( "</", fp );
732         fputs( name, fp );
733         fputs( ">\n", fp );
734 }
735
736 static void addrindex_write_attr( FILE *fp, gchar *name, gchar *value ) {
737         fputs( " ", fp );
738         fputs( name, fp );
739         fputs( "=\"", fp );
740         xml_file_put_escape_str( fp, value );
741         fputs( "\"", fp );
742 }
743
744 /*
745 * Return list of name-value pairs.
746 */
747 static GList *addrindex_read_attributes( XMLFile *file ) {
748         GList *list = NULL;
749         AddressIfAttrib *nv;
750         GList *attr;
751         gchar *name;
752         gchar *value;
753
754         attr = xml_get_current_tag_attr( file );
755         while( attr ) {
756                 name = ((XMLAttr *)attr->data)->name;
757                 value = ((XMLAttr *)attr->data)->value;
758                 nv = g_new0( AddressIfAttrib, 1 );
759                 nv->name = g_strdup( name );
760                 nv->value = g_strdup( value );
761                 list = g_list_append( list, nv );
762                 attr = g_list_next( attr );
763         }
764         return list;
765 }
766
767 /*
768 * Output name-value pairs.
769 */
770 static void addrindex_write_attributes( FILE *fp, gchar *tag, GList *list, gint lvl ) {
771         GList *node;
772         AddressIfAttrib *nv;
773         if( list ) {
774                 addrindex_write_elem_s( fp, lvl, tag );
775                 node = list;
776                 while( node ) {
777                         nv = node->data;
778                         addrindex_write_attr( fp, nv->name, nv->value );
779                         node = g_list_next( node );
780                 }
781                 fputs(" />\n", fp);
782         }
783 }
784
785 /*
786 static void addrindex_print_attributes( GList *list, FILE *stream ) {
787         GList *node = list;
788         while( node ) {
789                 AddressIfAttrib *nv = node->data;
790                 fprintf( stream, "%s : %s\n", nv->name, nv->value );
791                 node = g_list_next( node );
792         }
793 }
794 */
795
796 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
797         AddressDataSource *ds;
798         AddressBookFile *abf;
799         GList *attr;
800
801         ds = addrindex_create_datasource( ADDR_IF_BOOK );
802         abf = addrbook_create_book();
803         attr = xml_get_current_tag_attr( file );
804         while( attr ) {
805                 gchar *name = ((XMLAttr *)attr->data)->name;
806                 gchar *value = ((XMLAttr *)attr->data)->value;
807                 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
808                         addrbook_set_name( abf, value );
809                 }
810                 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
811                         addrbook_set_file( abf, value );
812                 }
813                 attr = g_list_next( attr );
814         }
815         ds->rawDataSource = abf;
816         return ds;
817 }
818
819 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
820         AddressBookFile *abf = ds->rawDataSource;
821         if( abf ) {
822                 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
823                 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
824                 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
825                 fputs( " />\n", fp );
826         }
827 }
828
829 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
830         AddressDataSource *ds;
831         VCardFile *vcf;
832         GList *attr;
833
834         ds = addrindex_create_datasource( ADDR_IF_VCARD );
835         vcf = vcard_create();
836         attr = xml_get_current_tag_attr( file );
837         while( attr ) {
838                 gchar *name = ((XMLAttr *)attr->data)->name;
839                 gchar *value = ((XMLAttr *)attr->data)->value;
840                 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
841                         vcard_set_name( vcf, value );
842                 }
843                 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
844                         vcard_set_file( vcf, value );
845                 }
846                 attr = g_list_next( attr );
847         }
848         ds->rawDataSource = vcf;
849         return ds;
850 }
851
852 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
853         VCardFile *vcf = ds->rawDataSource;
854         if( vcf ) {
855                 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
856                 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
857                 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
858                 fputs( " />\n", fp );
859         }
860 }
861
862 #ifdef USE_JPILOT
863 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
864         AddressDataSource *ds;
865         JPilotFile *jpf;
866         GList *attr;
867
868         ds = addrindex_create_datasource( ADDR_IF_JPILOT );
869         jpf = jpilot_create();
870         attr = xml_get_current_tag_attr( file );
871         while( attr ) {
872                 gchar *name = ((XMLAttr *)attr->data)->name;
873                 gchar *value = ((XMLAttr *)attr->data)->value;
874                 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
875                         jpilot_set_name( jpf, value );
876                 }
877                 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
878                         jpilot_set_file( jpf, value );
879                 }
880                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
881                         jpilot_add_custom_label( jpf, value );
882                 }
883                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
884                         jpilot_add_custom_label( jpf, value );
885                 }
886                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
887                         jpilot_add_custom_label( jpf, value );
888                 }
889                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
890                         jpilot_add_custom_label( jpf, value );
891                 }
892                 attr = g_list_next( attr );
893         }
894         ds->rawDataSource = jpf;
895         return ds;
896 }
897
898 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
899         JPilotFile *jpf = ds->rawDataSource;
900         if( jpf ) {
901                 gint ind;
902                 GList *node;
903                 GList *customLbl = jpilot_get_custom_labels( jpf );
904                 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
905                 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
906                 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
907                 node = customLbl;
908                 ind = 1;
909                 while( node ) {
910                         gchar name[256];
911                         sprintf( name, "%s%d", ATTAG_JPILOT_CUSTOM, ind );
912                         addrindex_write_attr( fp, name, node->data );
913                         ind++;
914                         node = g_list_next( node );
915                 }
916                 fputs( " />\n", fp );
917         }
918 }
919 #else
920 /* Just read/write name-value pairs (preserve data found in file)  */
921 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
922         AddressDataSource *ds;
923
924         ds = addrindex_create_datasource( ADDR_IF_JPILOT );
925         ds->rawDataSource = addrindex_read_attributes( file );
926         return ds;
927 }
928
929 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
930         GList *list = ds->rawDataSource;
931         if( list ) {
932                 addrindex_write_attributes( fp, TAG_DS_JPILOT, list, lvl );
933         }
934 }
935 #endif
936
937 #ifdef USE_LDAP
938 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
939         AddressDataSource *ds;
940         SyldapServer *server;
941         GList *attr;
942
943         ds = addrindex_create_datasource( ADDR_IF_LDAP );
944         server = syldap_create();
945         attr = xml_get_current_tag_attr( file );
946         while( attr ) {
947                 gchar *name = ((XMLAttr *)attr->data)->name;
948                 gchar *value = ((XMLAttr *)attr->data)->value;
949                 gint ivalue = atoi( value );
950                 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
951                         syldap_set_name( server, value );
952                 }
953                 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
954                         syldap_set_host( server, value );
955                 }
956                 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
957                         syldap_set_port( server, ivalue );
958                 }
959                 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
960                         syldap_set_base_dn( server, value );
961                 }
962                 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
963                         syldap_set_bind_dn( server, value );
964                 }
965                 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
966                         syldap_set_bind_password( server, value );
967                 }
968                 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
969                         syldap_set_search_criteria( server, value );
970                 }
971                 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
972                         syldap_set_max_entries( server, ivalue );
973                 }
974                 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
975                         syldap_set_timeout( server, ivalue );
976                 }
977                 attr = g_list_next( attr );
978         }
979
980         ds->rawDataSource = server;
981         return ds;
982 }
983
984 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
985         SyldapServer *server = ds->rawDataSource;
986         if( server ) {
987                 gchar value[256];
988
989                 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
990                 addrindex_write_attr( fp, ATTAG_LDAP_NAME, syldap_get_name( server ) );
991                 addrindex_write_attr( fp, ATTAG_LDAP_HOST, server->hostName );
992
993                 sprintf( value, "%d", server->port );   
994                 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
995
996                 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, server->baseDN );
997                 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, server->bindDN );
998                 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, server->bindPass );
999                 addrindex_write_attr( fp, ATTAG_LDAP_CRITERIA, server->searchCriteria );
1000
1001                 sprintf( value, "%d", server->maxEntries );
1002                 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1003                 sprintf( value, "%d", server->timeOut );
1004                 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1005
1006                 fputs(" />\n", fp);
1007         }
1008 }
1009 #else
1010 /* Just read/write name-value pairs (preserve data found in file)  */
1011 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1012         AddressDataSource *ds;
1013
1014         ds = addrindex_create_datasource( ADDR_IF_LDAP );
1015         ds->rawDataSource = addrindex_read_attributes( file );
1016         return ds;
1017 }
1018
1019 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1020         GList *list = ds->rawDataSource;
1021         if( list ) {
1022                 addrindex_write_attributes( fp, TAG_DS_LDAP, list, lvl );
1023         }
1024 }
1025 #endif
1026
1027 /* **********************************************************************
1028 * Address index I/O functions.
1029 * ***********************************************************************
1030 */
1031 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1032         guint prev_level;
1033         XMLTag *xtag;
1034         AddressInterface *iface = NULL, *dsIFace = NULL;
1035         AddressDataSource *ds;
1036
1037         for (;;) {
1038                 prev_level = file->level;
1039                 xml_parse_next_tag( file );
1040                 if( file->level < prev_level ) return;
1041
1042                 xtag = xml_get_current_tag( file );
1043
1044                 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1045                 if( iface ) {
1046                         addrIndex->lastType = iface->type;
1047                         if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1048                 }
1049                 else {
1050                         dsIFace = addrindex_tag_get_datasource(
1051                                         addrIndex, addrIndex->lastType, xtag->tag );
1052                         if( dsIFace ) {
1053                                 /* Add data source to list */
1054                                 ds = NULL;
1055                                 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1056                                         ds = addrindex_parse_book( file );
1057                                         if( ds->rawDataSource ) {
1058                                                 addrbook_set_path( ds->rawDataSource,
1059                                                         addrIndex->filePath );
1060                                         }
1061                                 }
1062                                 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1063                                         ds = addrindex_parse_vcard( file );
1064                                 }
1065                                 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1066                                         ds = addrindex_parse_jpilot( file );
1067                                 }
1068                                 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1069                                         ds = addrindex_parse_ldap( file );
1070                                 }
1071                                 if( ds ) {
1072                                         ds->interface = dsIFace;
1073                                         addrindex_hash_add_cache( addrIndex, ds );
1074                                         dsIFace->listSource =
1075                                                 g_list_append( dsIFace->listSource, ds );
1076                                 }
1077                         }
1078                 }
1079                 addrindex_read_index( addrIndex, file );
1080         }
1081 }
1082
1083 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1084         XMLFile *file = NULL;
1085         gchar *fileSpec = NULL;
1086
1087         g_return_val_if_fail( addrIndex != NULL, -1 );
1088
1089         fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1090         addrIndex->retVal = MGU_NO_FILE;
1091         file = xml_open_file( fileSpec );
1092         g_free( fileSpec );
1093
1094         if( file == NULL ) {
1095                 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
1096                 return addrIndex->retVal;
1097         }
1098
1099         addrIndex->retVal = MGU_BAD_FORMAT;
1100         if( xml_get_dtd( file ) == 0 ) {
1101                 if( xml_parse_next_tag( file ) == 0 ) {
1102                         if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1103                                 addrindex_read_index( addrIndex, file );
1104                                 addrIndex->retVal = MGU_SUCCESS;
1105                         }
1106                 }
1107         }
1108         xml_close_file( file );
1109
1110         return addrIndex->retVal;
1111 }
1112
1113 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1114         GList *nodeIF, *nodeDS;
1115         gint lvlList = 1;
1116         gint lvlItem = 1 + lvlList;
1117
1118         nodeIF = addrIndex->interfaceList;
1119         while( nodeIF ) {
1120                 AddressInterface *iface = nodeIF->data;
1121                 if( ! iface->legacyFlag ) {
1122                         nodeDS = iface->listSource;
1123                         addrindex_write_elem_s( fp, lvlList, iface->listTag );
1124                         fputs( ">\n", fp );
1125                         while( nodeDS ) {
1126                                 AddressDataSource *ds = nodeDS->data;
1127                                 if( ds ) {
1128                                         if( iface->type == ADDR_IF_BOOK ) {
1129                                                 addrindex_write_book( fp, ds, lvlItem );
1130                                         }
1131                                         if( iface->type == ADDR_IF_VCARD ) {
1132                                                 addrindex_write_vcard( fp, ds, lvlItem );
1133                                         }
1134                                         if( iface->type == ADDR_IF_JPILOT ) {
1135                                                 addrindex_write_jpilot( fp, ds, lvlItem );
1136                                         }
1137                                         if( iface->type == ADDR_IF_LDAP ) {
1138                                                 addrindex_write_ldap( fp, ds, lvlItem );
1139                                         }
1140                                 }
1141                                 nodeDS = g_list_next( nodeDS );
1142                         }
1143                         addrindex_write_elem_e( fp, lvlList, iface->listTag );
1144                 }
1145                 nodeIF = g_list_next( nodeIF );
1146         }
1147 }
1148
1149 /*
1150 * Write data to specified file.
1151 * Enter: addrIndex Address index object.
1152 *        newFile   New file name.
1153 * return: Status code, from addrIndex->retVal.
1154 * Note: File will be created in directory specified by addrIndex.
1155 */
1156 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1157         FILE *fp;
1158         gchar *fileSpec;
1159 #ifndef DEV_STANDALONE
1160         PrefFile *pfile;
1161 #endif
1162
1163         g_return_val_if_fail( addrIndex != NULL, -1 );
1164
1165         fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1166         addrIndex->retVal = MGU_OPEN_FILE;
1167 #ifdef DEV_STANDALONE
1168         fp = fopen( fileSpec, "w" );
1169         g_free( fileSpec );
1170         if( fp ) {
1171                 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1172 #else
1173         pfile = prefs_write_open( fileSpec );
1174         g_free( fileSpec );
1175         if( pfile ) {
1176                 fp = pfile->fp;
1177                 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
1178                                 conv_get_current_charset_str() );
1179 #endif
1180                 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1181                 fputs( ">\n", fp );
1182
1183                 addrindex_write_index( addrIndex, fp );
1184                 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1185
1186                 addrIndex->retVal = MGU_SUCCESS;
1187 #ifdef DEV_STANDALONE
1188                 fclose( fp );
1189 #else
1190                 if( prefs_write_close( pfile ) < 0 ) {
1191                         addrIndex->retVal = MGU_ERROR_WRITE;
1192                 }
1193 #endif
1194         }
1195
1196         fileSpec = NULL;
1197         return addrIndex->retVal;
1198 }
1199
1200 /*
1201 * Save address index data to original file.
1202 * return: Status code, from addrIndex->retVal.
1203 */
1204 gint addrindex_save_data( AddressIndex *addrIndex ) {
1205         g_return_val_if_fail( addrIndex != NULL, -1 );
1206
1207         addrIndex->retVal = MGU_NO_FILE;
1208         if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1209         if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1210
1211         addrindex_write_to( addrIndex, addrIndex->fileName );
1212         if( addrIndex->retVal == MGU_SUCCESS ) {
1213                 addrIndex->dirtyFlag = FALSE;
1214         }
1215         return addrIndex->retVal;
1216 }
1217
1218 /*
1219 * Save all address book files which may have changed.
1220 * Return: Status code, set if there was a problem saving data.
1221 */
1222 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1223         gint retVal = MGU_SUCCESS;
1224         GList *nodeIf, *nodeDS;
1225
1226         nodeIf = addrIndex->interfaceList;
1227         while( nodeIf ) {
1228                 AddressInterface *iface = nodeIf->data;
1229                 if( iface->type == ADDR_IF_BOOK ) {
1230                         nodeDS = iface->listSource;
1231                         while( nodeDS ) {
1232                                 AddressDataSource *ds = nodeDS->data;
1233                                 AddressBookFile *abf = ds->rawDataSource;
1234                                 if( addrbook_get_dirty( abf ) ) {
1235                                         if( abf->readFlag ) {
1236                                                 addrbook_save_data( abf );
1237                                                 if( abf->retVal != MGU_SUCCESS ) {
1238                                                         retVal = abf->retVal;
1239                                                 }
1240                                         }
1241                                 }
1242                                 nodeDS = g_list_next( nodeDS );
1243                         }
1244                         break;
1245                 }
1246                 nodeIf = g_list_next( nodeIf );
1247         }
1248         return retVal;
1249 }
1250
1251
1252 /* **********************************************************************
1253 * Address book conversion to new format.
1254 * ***********************************************************************
1255 */
1256
1257 #define ELTAG_IF_OLD_FOLDER   "folder"
1258 #define ELTAG_IF_OLD_GROUP    "group"
1259 #define ELTAG_IF_OLD_ITEM     "item"
1260 #define ELTAG_IF_OLD_NAME     "name"
1261 #define ELTAG_IF_OLD_ADDRESS  "address"
1262 #define ELTAG_IF_OLD_REMARKS  "remarks"
1263 #define ATTAG_IF_OLD_NAME     "name"
1264
1265 #define TEMPNODE_ROOT         0
1266 #define TEMPNODE_FOLDER       1
1267 #define TEMPNODE_GROUP        2
1268 #define TEMPNODE_ADDRESS      3
1269
1270 typedef struct _AddressCvt_Node AddressCvtNode;
1271 struct _AddressCvt_Node {
1272         gint  type;
1273         gchar *name;
1274         gchar *address;
1275         gchar *remarks;
1276         GList *list;
1277 };
1278
1279 /*
1280 * Parse current address item.
1281 */
1282 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1283         gchar *element;
1284         guint level;
1285         AddressCvtNode *nn;
1286
1287         nn = g_new0( AddressCvtNode, 1 );
1288         nn->type = TEMPNODE_ADDRESS;
1289         nn->list = NULL;
1290
1291         level = file->level;
1292
1293         for (;;) {
1294                 xml_parse_next_tag(file);
1295                 if (file->level < level) return nn;
1296
1297                 element = xml_get_element( file );
1298                 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1299                         nn->name = g_strdup( element );
1300                 }
1301                 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1302                         nn->address = g_strdup( element );
1303                 }
1304                 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1305                         nn->remarks = g_strdup( element );
1306                 }
1307                 xml_parse_next_tag(file);
1308         }
1309 }
1310
1311 /*
1312 * Create a temporary node below specified node.
1313 */
1314 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1315         AddressCvtNode *nn;
1316         nn = g_new0( AddressCvtNode, 1 );
1317         nn->type = type;
1318         nn->name = g_strdup( name );
1319         nn->remarks = g_strdup( rem );
1320         node->list = g_list_append( node->list, nn );
1321         return nn;
1322 }
1323
1324 /*
1325 * Process current temporary node.
1326 */
1327 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1328         GList *attr;
1329         guint prev_level;
1330         AddressCvtNode *newNode = NULL;
1331         gchar *name;
1332         gchar *value;
1333
1334         for (;;) {
1335                 prev_level = file->level;
1336                 xml_parse_next_tag( file );
1337                 if (file->level < prev_level) return;
1338                 name = NULL;
1339                 value = NULL;
1340
1341                 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1342                         attr = xml_get_current_tag_attr(file);
1343                         if (attr) {
1344                                 name = ((XMLAttr *)attr->data)->name;
1345                                 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1346                                         value = ((XMLAttr *)attr->data)->value;
1347                                 }
1348                         }
1349                         newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1350                         addrindex_add_obj( file, newNode );
1351
1352                 }
1353                 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1354                         attr = xml_get_current_tag_attr(file);
1355                         if (attr) {
1356                                 name = ((XMLAttr *)attr->data)->name;
1357                                 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1358                                         value = ((XMLAttr *)attr->data)->value;
1359                                 }
1360                         }
1361                         newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1362                         addrindex_add_obj( file, newNode );
1363                 }
1364                 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1365                         newNode = addrindex_parse_item( file );
1366                         node->list = g_list_append( node->list, newNode );
1367                 }
1368                 else {
1369                         /* printf( "invalid: !!! \n" ); */
1370                         attr = xml_get_current_tag_attr( file );
1371                 }
1372         }
1373 }
1374
1375 /*
1376 * Consume all nodes below current tag.
1377 */
1378 static void addrindex_consume_tree( XMLFile *file ) {
1379         guint prev_level;
1380         gchar *element;
1381         GList *attr;
1382         XMLTag *xtag;
1383
1384         for (;;) {
1385                 prev_level = file->level;
1386                 xml_parse_next_tag( file );
1387                 if (file->level < prev_level) return;
1388
1389                 xtag = xml_get_current_tag( file );
1390                 /* printf( "tag : %s\n", xtag->tag ); */
1391                 element = xml_get_element( file );
1392                 attr = xml_get_current_tag_attr( file );
1393                 /* show_attribs( attr ); */
1394                 /* printf( "\ttag  value : %s :\n", element ); */
1395                 addrindex_consume_tree( file );
1396         }
1397 }
1398
1399 /*
1400 * Print temporary tree.
1401 */
1402 static void addrindex_print_node( AddressCvtNode *node, FILE *stream  ) {
1403         GList *list;
1404
1405         fprintf( stream, "Node:\ttype :%d:\n", node->type );
1406         fprintf( stream, "\tname :%s:\n", node->name );
1407         fprintf( stream, "\taddr :%s:\n", node->address );
1408         fprintf( stream, "\trems :%s:\n", node->remarks );
1409         if( node->list ) {
1410                 fprintf( stream, "\t--list----\n" );
1411         }
1412         list = node->list;
1413         while( list ) {
1414                 AddressCvtNode *lNode = list->data;
1415                 list = g_list_next( list );
1416                 addrindex_print_node( lNode, stream );
1417         }
1418         fprintf( stream, "\t==list-%d==\n", node->type );
1419 }
1420
1421 /*
1422 * Free up temporary tree.
1423 */
1424 static void addrindex_free_node( AddressCvtNode *node ) {
1425         GList *list = node->list;
1426
1427         while( list ) {
1428                 AddressCvtNode *lNode = list->data;
1429                 list = g_list_next( list );
1430                 addrindex_free_node( lNode );
1431         }
1432         node->type = TEMPNODE_ROOT;
1433         g_free( node->name );
1434         g_free( node->address );
1435         g_free( node->remarks );
1436         g_list_free( node->list );
1437         g_free( node );
1438 }
1439
1440 /*
1441 * Process address book for specified node.
1442 */
1443 static void addrindex_process_node(
1444                 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1445                 ItemGroup *parentGrp, ItemFolder *folderGrp )
1446 {
1447         GList *list;
1448         ItemFolder *itemFolder = NULL;
1449         ItemGroup *itemGParent = parentGrp;
1450         ItemFolder *itemGFolder = folderGrp;
1451         AddressCache *cache = abf->addressCache;
1452
1453         if( node->type == TEMPNODE_ROOT ) {
1454                 itemFolder = parent;
1455         }
1456         else if( node->type == TEMPNODE_FOLDER ) {
1457                 itemFolder = addritem_create_item_folder();
1458                 addritem_folder_set_name( itemFolder, node->name );
1459                 addrcache_id_folder( cache, itemFolder );
1460                 addrcache_folder_add_folder( cache, parent, itemFolder );
1461                 itemGFolder = NULL;
1462         }
1463         else if( node->type == TEMPNODE_GROUP ) {
1464                 ItemGroup *itemGroup;
1465                 gchar *fName;
1466
1467                 /* Create a folder for group */
1468                 fName = g_strdup_printf( "Cvt - %s", node->name );
1469                 itemGFolder = addritem_create_item_folder();
1470                 addritem_folder_set_name( itemGFolder, fName );
1471                 addrcache_id_folder( cache, itemGFolder );
1472                 addrcache_folder_add_folder( cache, parent, itemGFolder );
1473                 g_free( fName );
1474
1475                 /* Add group into folder */
1476                 itemGroup = addritem_create_item_group();
1477                 addritem_group_set_name( itemGroup, node->name );
1478                 addrcache_id_group( cache, itemGroup );
1479                 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1480                 itemGParent = itemGroup;
1481         }
1482         else if( node->type == TEMPNODE_ADDRESS ) {
1483                 ItemPerson *itemPerson;
1484                 ItemEMail *itemEMail;
1485
1486                 /* Create person and email objects */
1487                 itemPerson = addritem_create_item_person();
1488                 addritem_person_set_common_name( itemPerson, node->name );
1489                 addrcache_id_person( cache, itemPerson );
1490                 itemEMail = addritem_create_item_email();
1491                 addritem_email_set_address( itemEMail, node->address );
1492                 addritem_email_set_remarks( itemEMail, node->remarks );
1493                 addrcache_id_email( cache, itemEMail );
1494                 addrcache_person_add_email( cache, itemPerson, itemEMail );
1495
1496                 /* Add person into appropriate folder */
1497                 if( itemGFolder ) {
1498                         addrcache_folder_add_person( cache, itemGFolder, itemPerson );
1499                 }
1500                 else {
1501                         addrcache_folder_add_person( cache, parent, itemPerson );
1502                 }
1503
1504                 /* Add email address only into group */
1505                 if( parentGrp ) {
1506                         addrcache_group_add_email( cache, parentGrp, itemEMail );
1507                 }
1508         }
1509
1510         list = node->list;
1511         while( list ) {
1512                 AddressCvtNode *lNode = list->data;
1513                 list = g_list_next( list );
1514                 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
1515         }
1516 }
1517
1518 /*
1519 * Process address book to specified file number.
1520 */
1521 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
1522         gboolean retVal = FALSE;
1523         AddressBookFile *abf = NULL;
1524         AddressCvtNode *rootNode = NULL;
1525         gchar *newFile = NULL;
1526         GList *fileList = NULL;
1527         gint fileNum  = 0;
1528
1529         /* Setup root node */
1530         rootNode = g_new0( AddressCvtNode, 1 );
1531         rootNode->type = TEMPNODE_ROOT;
1532         rootNode->name = g_strdup( "root" );
1533         rootNode->list = NULL;
1534         addrindex_add_obj( file, rootNode );
1535         /* addrindex_print_node( rootNode, stdout ); */
1536
1537         /* Create new address book */
1538         abf = addrbook_create_book();
1539         addrbook_set_name( abf, displayName );
1540         addrbook_set_path( abf, addrIndex->filePath );
1541
1542         /* Determine next available file number */
1543         fileList = addrbook_get_bookfile_list( abf );
1544         if( fileList ) {
1545                 fileNum = 1 + abf->maxValue;
1546         }
1547         g_list_free( fileList );
1548         fileList = NULL;
1549
1550         newFile = addrbook_gen_new_file_name( fileNum );
1551         if( newFile ) {
1552                 addrbook_set_file( abf, newFile );
1553         }
1554
1555         addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
1556
1557         /* addrbook_dump_book( abf, stdout ); */
1558         addrbook_save_data( abf );
1559         addrIndex->retVal = abf->retVal;
1560         if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
1561
1562         addrbook_free_book( abf );
1563         abf = NULL;
1564         addrindex_free_node( rootNode );
1565         rootNode = NULL;
1566
1567         /* Create entries in address index */
1568         if( retVal ) {
1569                 abf = addrbook_create_book();
1570                 addrbook_set_name( abf, displayName );
1571                 addrbook_set_path( abf, addrIndex->filePath );
1572                 addrbook_set_file( abf, newFile );
1573                 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
1574         }
1575
1576         return retVal;
1577 }
1578
1579 /*
1580 * Process tree converting data.
1581 */
1582 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
1583         guint prev_level;
1584         gchar *element;
1585         GList *attr;
1586         XMLTag *xtag;
1587
1588         /* Process file */
1589         for (;;) {
1590                 prev_level = file->level;
1591                 xml_parse_next_tag( file );
1592                 if (file->level < prev_level) return;
1593
1594                 xtag = xml_get_current_tag( file );
1595                 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
1596                 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
1597                         if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
1598                                 addrIndex->needsConversion = FALSE;
1599                                 addrIndex->wasConverted = TRUE;
1600                                 continue;
1601                         }
1602                         return;
1603                 }
1604                 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
1605                         if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
1606                                 addrIndex->needsConversion = FALSE;
1607                                 addrIndex->wasConverted = TRUE;
1608                                 continue;
1609                         }
1610                         return;
1611                 }
1612                 element = xml_get_element( file );
1613                 attr = xml_get_current_tag_attr( file );
1614                 /* show_attribs( attr ); */
1615                 /* printf( "\ttag  value : %s :\n", element ); */
1616                 addrindex_consume_tree( file );
1617         }
1618 }
1619
1620 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
1621         XMLFile *file = NULL;
1622         gchar *fileSpec;
1623
1624         fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1625         addrIndex->retVal = MGU_NO_FILE;
1626         file = xml_open_file( fileSpec );
1627         g_free( fileSpec );
1628
1629         if( file == NULL ) {
1630                 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
1631                 return addrIndex->retVal;
1632         }
1633
1634         addrIndex->retVal = MGU_BAD_FORMAT;
1635         if( xml_get_dtd( file ) == 0 ) {
1636                 if( xml_parse_next_tag( file ) == 0 ) {
1637                         if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1638                                 addrindex_convert_tree( addrIndex, file );
1639                         }
1640                 }
1641         }
1642         xml_close_file( file );
1643         return addrIndex->retVal;
1644 }
1645
1646 /*
1647 * Create a new address book file.
1648 */
1649 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
1650         gboolean retVal = FALSE;
1651         AddressBookFile *abf = NULL;
1652         gchar *newFile = NULL;
1653         GList *fileList = NULL;
1654         gint fileNum = 0;
1655
1656         /* Create new address book */
1657         abf = addrbook_create_book();
1658         addrbook_set_name( abf, displayName );
1659         addrbook_set_path( abf, addrIndex->filePath );
1660
1661         /* Determine next available file number */
1662         fileList = addrbook_get_bookfile_list( abf );
1663         if( fileList ) {
1664                 fileNum = 1 + abf->maxValue;
1665         }
1666         g_list_free( fileList );
1667         fileList = NULL;
1668
1669         newFile = addrbook_gen_new_file_name( fileNum );
1670         if( newFile ) {
1671                 addrbook_set_file( abf, newFile );
1672         }
1673
1674         addrbook_save_data( abf );
1675         addrIndex->retVal = abf->retVal;
1676         if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
1677         addrbook_free_book( abf );
1678         abf = NULL;
1679
1680         /* Create entries in address index */
1681         if( retVal ) {
1682                 abf = addrbook_create_book();
1683                 addrbook_set_name( abf, displayName );
1684                 addrbook_set_path( abf, addrIndex->filePath );
1685                 addrbook_set_file( abf, newFile );
1686                 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
1687         }
1688
1689         return retVal;
1690 }
1691
1692 /*
1693 * Read data for address index performing a conversion if necesary.
1694 * Enter: addrIndex Address index object.
1695 * return: Status code, from addrIndex->retVal.
1696 * Note: New address book files will be created in directory specified by
1697 * addrIndex. Three files will be created, for the following:
1698 *       "Common addresses"
1699 *       "Personal addresses"
1700 *       "Gathered addresses" - a new address book.
1701 */
1702 gint addrindex_read_data( AddressIndex *addrIndex ) {
1703         g_return_val_if_fail( addrIndex != NULL, -1 );
1704
1705         addrIndex->conversionError = FALSE;
1706         addrindex_read_file( addrIndex );
1707         if( addrIndex->retVal == MGU_SUCCESS ) {
1708                 if( addrIndex->needsConversion ) {
1709                         if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
1710                                 addrIndex->conversionError = TRUE;
1711                         }
1712                         else {
1713                                 addrIndex->conversionError = TRUE;
1714                         }
1715                 }
1716                 addrIndex->dirtyFlag = TRUE;
1717         }
1718         return addrIndex->retVal;
1719 }
1720
1721 /*
1722 * Create new address books for a new address index.
1723 * Enter: addrIndex Address index object.
1724 * return: Status code, from addrIndex->retVal.
1725 * Note: New address book files will be created in directory specified by
1726 * addrIndex. Three files will be created, for the following:
1727 *       "Common addresses"
1728 *       "Personal addresses"
1729 *       "Gathered addresses" - a new address book.
1730 */
1731 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
1732         gboolean flg;
1733
1734         g_return_val_if_fail( addrIndex != NULL, -1 );
1735
1736         flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
1737         if( flg ) {
1738                 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
1739                 addrIndex->dirtyFlag = TRUE;
1740         }
1741         return addrIndex->retVal;
1742 }
1743
1744 /* **********************************************************************
1745 * New interface stuff.
1746 * ***********************************************************************
1747 */
1748
1749 /*
1750  * Return modified flag for specified data source.
1751  */
1752 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
1753         gboolean retVal = FALSE;
1754         AddressInterface *iface;
1755
1756         if( ds == NULL ) return retVal;
1757         iface = ds->interface;
1758         if( iface == NULL ) return retVal;
1759         if( iface->getModifyFlag ) {
1760                 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
1761         }
1762         return retVal;
1763 }
1764
1765 /*
1766  * Return accessed flag for specified data source.
1767  */
1768 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
1769         gboolean retVal = FALSE;
1770         AddressInterface *iface;
1771
1772         if( ds == NULL ) return retVal;
1773         iface = ds->interface;
1774         if( iface == NULL ) return retVal;
1775         if( iface->getAccessFlag ) {
1776                 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
1777         }
1778         return retVal;
1779 }
1780
1781 /*
1782  * Return data read flag for specified data source.
1783  */
1784 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
1785         gboolean retVal = TRUE;
1786         AddressInterface *iface;
1787
1788         if( ds == NULL ) return retVal;
1789         iface = ds->interface;
1790         if( iface == NULL ) return retVal;
1791         if( iface->getReadFlag ) {
1792                 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
1793         }
1794         return retVal;
1795 }
1796
1797 /*
1798  * Return status code for specified data source.
1799  */
1800 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
1801         gint retVal = MGU_SUCCESS;
1802         AddressInterface *iface;
1803
1804         if( ds == NULL ) return retVal;
1805         iface = ds->interface;
1806         if( iface == NULL ) return retVal;
1807         if( iface->getStatusCode ) {
1808                 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
1809         }
1810         return retVal;
1811 }
1812
1813 /*
1814  * Return data read flag for specified data source.
1815  */
1816 gint addrindex_ds_read_data( AddressDataSource *ds ) {
1817         gint retVal = MGU_SUCCESS;
1818         AddressInterface *iface;
1819
1820         if( ds == NULL ) return retVal;
1821         iface = ds->interface;
1822         if( iface == NULL ) return retVal;
1823         if( iface->getReadData ) {
1824                 retVal = ( iface->getReadData ) ( ds->rawDataSource );
1825         }
1826         return retVal;
1827 }
1828
1829 /*
1830  * Return data read flag for specified data source.
1831  */
1832 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
1833         ItemFolder *retVal = NULL;
1834         AddressInterface *iface;
1835
1836         if( ds == NULL ) return retVal;
1837         iface = ds->interface;
1838         if( iface == NULL ) return retVal;
1839         if( iface->getRootFolder ) {
1840                 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
1841         }
1842         return retVal;
1843 }
1844
1845 /*
1846  * Return list of folders for specified data source.
1847  */
1848 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
1849         GList *retVal = FALSE;
1850         AddressInterface *iface;
1851
1852         if( ds == NULL ) return retVal;
1853         iface = ds->interface;
1854         if( iface == NULL ) return retVal;
1855         if( iface->getListFolder ) {
1856                 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
1857         }
1858         return retVal;
1859 }
1860
1861 /*
1862  * Return list of persons in root folder for specified data source.
1863  */
1864 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
1865         GList *retVal = FALSE;
1866         AddressInterface *iface;
1867
1868         if( ds == NULL ) return retVal;
1869         iface = ds->interface;
1870         if( iface == NULL ) return retVal;
1871         if( iface->getListPerson ) {
1872                 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
1873         }
1874         return retVal;
1875 }
1876
1877 /*
1878  * Return name for specified data source.
1879  */
1880 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
1881         gchar *retVal = FALSE;
1882         AddressInterface *iface;
1883
1884         if( ds == NULL ) return retVal;
1885         iface = ds->interface;
1886         if( iface == NULL ) return retVal;
1887         if( iface->getName ) {
1888                 retVal = ( iface->getName ) ( ds->rawDataSource );
1889         }
1890         return retVal;
1891 }
1892
1893 /*
1894  * Set the access flag inside the data source.
1895  */
1896 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
1897         AddressInterface *iface;
1898
1899         if( ds == NULL ) return;
1900         iface = ds->interface;
1901         if( iface == NULL ) return;
1902         if( iface->setAccessFlag ) {
1903                 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
1904         }
1905 }
1906
1907 /*
1908  * Return read only flag for specified data source.
1909  */
1910 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
1911         AddressInterface *iface;
1912         if( ds == NULL ) return TRUE;
1913         iface = ds->interface;
1914         if( iface == NULL ) return TRUE;
1915         return iface->readOnly;
1916 }
1917
1918 /*
1919  * Return list of all persons for specified data source.
1920  */
1921 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
1922         GList *retVal = NULL;
1923         AddressInterface *iface;
1924
1925         if( ds == NULL ) return retVal;
1926         iface = ds->interface;
1927         if( iface == NULL ) return retVal;
1928         if( iface->getAllPersons ) {
1929                 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
1930         }
1931         return retVal;
1932 }
1933
1934 /*
1935  * Return list of all groups for specified data source.
1936  */
1937 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
1938         GList *retVal = NULL;
1939         AddressInterface *iface;
1940
1941         if( ds == NULL ) return retVal;
1942         iface = ds->interface;
1943         if( iface == NULL ) return retVal;
1944         if( iface->getAllGroups ) {
1945                 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
1946         }
1947         return retVal;
1948 }
1949
1950 /*
1951 * End of Source.
1952 */