sync with 0.7.4cvs51
[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         g_free( key );
444         key = NULL;
445         value = NULL;
446         return TRUE;
447 }
448
449 /*
450 * Free hash table of address cache items.
451 */
452 static void addrindex_free_cache_hash( GHashTable *table ) {
453         g_hash_table_freeze( table );
454         g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
455         g_hash_table_thaw( table );
456         g_hash_table_destroy( table );
457 }
458
459 /*
460 * Remove address cache for specified data source from internal hashtable.
461 */
462 static void addrindex_hash_remove_cache( AddressIndex *addrIndex, AddressDataSource *ds ) {
463         gchar *cacheID;
464
465         cacheID = addrindex_get_cache_id( addrIndex, ds );
466         if( cacheID ) {
467                 g_hash_table_remove( addrIndex->hashCache, cacheID );
468                 g_free( cacheID );
469                 cacheID = NULL;
470         }
471 }
472
473 /*
474 * Create new object.
475 */
476 AddressIndex *addrindex_create_index( void ) {
477         AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
478
479         ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
480         ADDRITEM_ID(addrIndex) = NULL;
481         ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
482         ADDRITEM_PARENT(addrIndex) = NULL;
483         ADDRITEM_SUBTYPE(addrIndex) = 0;
484         addrIndex->filePath = NULL;
485         addrIndex->fileName = NULL;
486         addrIndex->retVal = MGU_SUCCESS;
487         addrIndex->needsConversion = FALSE;
488         addrIndex->wasConverted = FALSE;
489         addrIndex->conversionError = FALSE;
490         addrIndex->interfaceList = NULL;
491         addrIndex->lastType = ADDR_IF_NONE;
492         addrIndex->dirtyFlag = FALSE;
493         addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
494         addrindex_build_if_list( addrIndex );
495         return addrIndex;
496 }
497
498 /*
499 * Specify file to be used.
500 */
501 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
502         g_return_if_fail( addrIndex != NULL );
503         addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
504 }
505 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
506         g_return_if_fail( addrIndex != NULL );
507         addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
508 }
509 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
510         g_return_if_fail( addrIndex != NULL );
511         addrIndex->dirtyFlag = value;
512 }
513
514 /*
515 * Return list of interfaces.
516 */
517 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
518         g_return_val_if_fail( addrIndex != NULL, NULL );
519         return addrIndex->interfaceList;
520 }
521
522 /*
523 * Free up object.
524 */
525 void addrindex_free_index( AddressIndex *addrIndex ) {
526         GList *node;
527
528         g_return_if_fail( addrIndex != NULL );
529
530         g_free( ADDRITEM_ID(addrIndex) );
531         g_free( ADDRITEM_NAME(addrIndex) );
532         g_free( addrIndex->filePath );
533         g_free( addrIndex->fileName );
534         ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
535         ADDRITEM_ID(addrIndex) = NULL;
536         ADDRITEM_NAME(addrIndex) = NULL;
537         ADDRITEM_PARENT(addrIndex) = NULL;
538         ADDRITEM_SUBTYPE(addrIndex) = 0;
539         addrIndex->filePath = NULL;
540         addrIndex->fileName = NULL;
541         addrIndex->retVal = MGU_SUCCESS;
542         addrIndex->needsConversion = FALSE;
543         addrIndex->wasConverted = FALSE;
544         addrIndex->conversionError = FALSE;
545         addrIndex->lastType = ADDR_IF_NONE;
546         addrIndex->dirtyFlag = FALSE;
547         node = addrIndex->interfaceList;
548         while( node ) {
549                 AddressInterface *iface = node->data;
550                 addrindex_free_interface( iface );
551                 node = g_list_next( node );
552         }
553         g_list_free( addrIndex->interfaceList );
554         addrIndex->interfaceList = NULL;
555         addrindex_free_cache_hash( addrIndex->hashCache );
556         addrIndex->hashCache = NULL;
557         g_free( addrIndex );
558 }
559
560 /*
561 * Print address index.
562 */
563 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
564         g_return_if_fail( addrIndex != NULL );
565         fprintf( stream, "AddressIndex:\n" );
566         fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
567         fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
568         fprintf( stream, "\t   status: %d : '%s'\n", addrIndex->retVal, mgu_error2string( addrIndex->retVal ) );
569         fprintf( stream, "\tconverted: '%s'\n", addrIndex->wasConverted ? "yes" : "no" );
570         fprintf( stream, "\tcvt error: '%s'\n", addrIndex->conversionError ? "yes" : "no" );
571         fprintf( stream, "\t---\n" );
572 }
573
574 /*
575 * Retrieve specified interface from index.
576 */
577 AddressInterface *addrindex_get_interface(
578         AddressIndex *addrIndex, AddressIfType ifType )
579 {
580         AddressInterface *retVal = NULL;
581         GList *node;
582
583         g_return_val_if_fail( addrIndex != NULL, NULL );
584
585         node = addrIndex->interfaceList;
586         while( node ) {
587                 AddressInterface *iface = node->data;
588                 node = g_list_next( node );
589                 if( iface->type == ifType ) {
590                         retVal = iface;
591                         break;
592                 }
593         }
594         return retVal;
595 }
596
597 /*
598 * Add data source to index.
599 * Enter: addrIndex  Address index object.
600 *        ifType     Interface type to add.
601 *        dataSource Actual data source to add.
602 * Return: TRUE if data source was added.
603 * Note: The raw data object (for example, AddressBookFile or VCardFile object) should be
604 * supplied as the dataSource argument.
605 */
606 AddressDataSource *addrindex_index_add_datasource(
607         AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
608 {
609         AddressInterface *iface;
610         AddressDataSource *ds = NULL;
611
612         g_return_val_if_fail( addrIndex != NULL, NULL );
613         g_return_val_if_fail( dataSource != NULL, NULL );
614
615         iface = addrindex_get_interface( addrIndex, ifType );
616         if( iface ) {
617                 ds = addrindex_create_datasource( ifType );
618                 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
619                 ds->type = ifType;
620                 ds->rawDataSource = dataSource;
621                 ds->interface = iface;
622                 iface->listSource = g_list_append( iface->listSource, ds );
623                 addrIndex->dirtyFlag = TRUE;
624
625                 addrindex_hash_add_cache( addrIndex, ds );
626         }
627         return ds;
628 }
629
630 /*
631 * Remove data source from index.
632 * Enter: addrIndex  Address index object.
633 *        dataSource Data source to remove.
634 * Return: Data source if removed, or NULL if data source was not found in
635 * index. Note the this object must still be freed.
636 */
637 AddressDataSource *addrindex_index_remove_datasource(
638         AddressIndex *addrIndex, AddressDataSource *dataSource )
639 {
640         AddressDataSource *retVal = FALSE;
641         AddressInterface *iface;
642
643         g_return_val_if_fail( addrIndex != NULL, NULL );
644         g_return_val_if_fail( dataSource != NULL, NULL );
645
646         iface = addrindex_get_interface( addrIndex, dataSource->type );
647         if( iface ) {
648                 iface->listSource = g_list_remove( iface->listSource, dataSource );
649                 addrIndex->dirtyFlag = TRUE;
650                 dataSource->interface = NULL;
651
652                 /* Remove cache from hash table */
653                 addrindex_hash_remove_cache( addrIndex, dataSource );
654
655                 retVal = dataSource;
656         }
657         return retVal;
658 }
659
660 static AddressInterface *addrindex_tag_get_interface(
661         AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
662 {
663         AddressInterface *retVal = NULL;
664         GList *node = addrIndex->interfaceList;
665
666         while( node ) {
667                 AddressInterface *iface = node->data;
668                 node = g_list_next( node );
669                 if( tag ) {
670                         if( strcmp( iface->listTag, tag ) == 0 ) {
671                                 retVal = iface;
672                                 break;
673                         }
674                 }
675                 else {
676                         if( iface->type == ifType ) {
677                                 retVal = iface;
678                                 break;
679                         }
680                 }
681         }
682         return retVal;
683 }
684
685 static AddressInterface *addrindex_tag_get_datasource(
686         AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
687 {
688         AddressInterface *retVal = NULL;
689         GList *node = addrIndex->interfaceList;
690
691         while( node ) {
692                 AddressInterface *iface = node->data;
693                 node = g_list_next( node );
694                 if( iface->type == ifType && iface->itemTag ) {
695                         if( strcmp( iface->itemTag, tag ) == 0 ) {
696                                 retVal = iface;
697                                 break;
698                         }
699                 }
700         }
701         return retVal;
702 }
703
704 /* **********************************************************************
705 * Interface XML parsing functions.
706 * ***********************************************************************
707 */
708 /*
709 static void show_attribs( GList *attr ) {
710         while( attr ) {
711                 gchar *name = ((XMLAttr *)attr->data)->name;
712                 gchar *value = ((XMLAttr *)attr->data)->value;
713                 printf( "\tattr value : %s :%s:\n", name, value );
714                 attr = g_list_next( attr );
715         }
716         printf( "\t---\n" );
717 }
718 */
719
720 static void addrindex_write_elem_s( FILE *fp, gint lvl, gchar *name ) {
721         gint i;
722         for( i = 0; i < lvl; i++ ) fputs( "  ", fp );
723         fputs( "<", fp );
724         fputs( name, fp );
725 }
726
727 static void addrindex_write_elem_e( FILE *fp, gint lvl, gchar *name ) {
728         gint i;
729         for( i = 0; i < lvl; i++ ) fputs( "  ", fp );
730         fputs( "</", fp );
731         fputs( name, fp );
732         fputs( ">\n", fp );
733 }
734
735 static void addrindex_write_attr( FILE *fp, gchar *name, gchar *value ) {
736         fputs( " ", fp );
737         fputs( name, fp );
738         fputs( "=\"", fp );
739         xml_file_put_escape_str( fp, value );
740         fputs( "\"", fp );
741 }
742
743 /*
744 * Return list of name-value pairs.
745 */
746 static GList *addrindex_read_attributes( XMLFile *file ) {
747         GList *list = NULL;
748         AddressIfAttrib *nv;
749         GList *attr;
750         gchar *name;
751         gchar *value;
752
753         attr = xml_get_current_tag_attr( file );
754         while( attr ) {
755                 name = ((XMLAttr *)attr->data)->name;
756                 value = ((XMLAttr *)attr->data)->value;
757                 nv = g_new0( AddressIfAttrib, 1 );
758                 nv->name = g_strdup( name );
759                 nv->value = g_strdup( value );
760                 list = g_list_append( list, nv );
761                 attr = g_list_next( attr );
762         }
763         return list;
764 }
765
766 /*
767 * Output name-value pairs.
768 */
769 static void addrindex_write_attributes( FILE *fp, gchar *tag, GList *list, gint lvl ) {
770         GList *node;
771         AddressIfAttrib *nv;
772         if( list ) {
773                 addrindex_write_elem_s( fp, lvl, tag );
774                 node = list;
775                 while( node ) {
776                         nv = node->data;
777                         addrindex_write_attr( fp, nv->name, nv->value );
778                         node = g_list_next( node );
779                 }
780                 fputs(" />\n", fp);
781         }
782 }
783
784 /*
785 static void addrindex_print_attributes( GList *list, FILE *stream ) {
786         GList *node = list;
787         while( node ) {
788                 AddressIfAttrib *nv = node->data;
789                 fprintf( stream, "%s : %s\n", nv->name, nv->value );
790                 node = g_list_next( node );
791         }
792 }
793 */
794
795 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
796         AddressDataSource *ds;
797         AddressBookFile *abf;
798         GList *attr;
799
800         ds = addrindex_create_datasource( ADDR_IF_BOOK );
801         abf = addrbook_create_book();
802         attr = xml_get_current_tag_attr( file );
803         while( attr ) {
804                 gchar *name = ((XMLAttr *)attr->data)->name;
805                 gchar *value = ((XMLAttr *)attr->data)->value;
806                 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
807                         addrbook_set_name( abf, value );
808                 }
809                 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
810                         addrbook_set_file( abf, value );
811                 }
812                 attr = g_list_next( attr );
813         }
814         ds->rawDataSource = abf;
815         return ds;
816 }
817
818 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
819         AddressBookFile *abf = ds->rawDataSource;
820         if( abf ) {
821                 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
822                 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
823                 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
824                 fputs( " />\n", fp );
825         }
826 }
827
828 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
829         AddressDataSource *ds;
830         VCardFile *vcf;
831         GList *attr;
832
833         ds = addrindex_create_datasource( ADDR_IF_VCARD );
834         vcf = vcard_create();
835         attr = xml_get_current_tag_attr( file );
836         while( attr ) {
837                 gchar *name = ((XMLAttr *)attr->data)->name;
838                 gchar *value = ((XMLAttr *)attr->data)->value;
839                 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
840                         vcard_set_name( vcf, value );
841                 }
842                 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
843                         vcard_set_file( vcf, value );
844                 }
845                 attr = g_list_next( attr );
846         }
847         ds->rawDataSource = vcf;
848         return ds;
849 }
850
851 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
852         VCardFile *vcf = ds->rawDataSource;
853         if( vcf ) {
854                 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
855                 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
856                 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
857                 fputs( " />\n", fp );
858         }
859 }
860
861 #ifdef USE_JPILOT
862 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
863         AddressDataSource *ds;
864         JPilotFile *jpf;
865         GList *attr;
866
867         ds = addrindex_create_datasource( ADDR_IF_JPILOT );
868         jpf = jpilot_create();
869         attr = xml_get_current_tag_attr( file );
870         while( attr ) {
871                 gchar *name = ((XMLAttr *)attr->data)->name;
872                 gchar *value = ((XMLAttr *)attr->data)->value;
873                 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
874                         jpilot_set_name( jpf, value );
875                 }
876                 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
877                         jpilot_set_file( jpf, value );
878                 }
879                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
880                         jpilot_add_custom_label( jpf, value );
881                 }
882                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
883                         jpilot_add_custom_label( jpf, value );
884                 }
885                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
886                         jpilot_add_custom_label( jpf, value );
887                 }
888                 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
889                         jpilot_add_custom_label( jpf, value );
890                 }
891                 attr = g_list_next( attr );
892         }
893         ds->rawDataSource = jpf;
894         return ds;
895 }
896
897 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
898         JPilotFile *jpf = ds->rawDataSource;
899         if( jpf ) {
900                 gint ind;
901                 GList *node;
902                 GList *customLbl = jpilot_get_custom_labels( jpf );
903                 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
904                 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
905                 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
906                 node = customLbl;
907                 ind = 1;
908                 while( node ) {
909                         gchar name[256];
910                         sprintf( name, "%s%d", ATTAG_JPILOT_CUSTOM, ind );
911                         addrindex_write_attr( fp, name, node->data );
912                         ind++;
913                         node = g_list_next( node );
914                 }
915                 fputs( " />\n", fp );
916         }
917 }
918 #else
919 /* Just read/write name-value pairs (preserve data found in file)  */
920 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
921         AddressDataSource *ds;
922
923         ds = addrindex_create_datasource( ADDR_IF_JPILOT );
924         ds->rawDataSource = addrindex_read_attributes( file );
925         return ds;
926 }
927
928 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
929         GList *list = ds->rawDataSource;
930         if( list ) {
931                 addrindex_write_attributes( fp, TAG_DS_JPILOT, list, lvl );
932         }
933 }
934 #endif
935
936 #ifdef USE_LDAP
937 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
938         AddressDataSource *ds;
939         SyldapServer *server;
940         GList *attr;
941
942         ds = addrindex_create_datasource( ADDR_IF_LDAP );
943         server = syldap_create();
944         attr = xml_get_current_tag_attr( file );
945         while( attr ) {
946                 gchar *name = ((XMLAttr *)attr->data)->name;
947                 gchar *value = ((XMLAttr *)attr->data)->value;
948                 gint ivalue = atoi( value );
949                 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
950                         syldap_set_name( server, value );
951                 }
952                 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
953                         syldap_set_host( server, value );
954                 }
955                 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
956                         syldap_set_port( server, ivalue );
957                 }
958                 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
959                         syldap_set_base_dn( server, value );
960                 }
961                 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
962                         syldap_set_bind_dn( server, value );
963                 }
964                 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
965                         syldap_set_bind_password( server, value );
966                 }
967                 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
968                         syldap_set_search_criteria( server, value );
969                 }
970                 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
971                         syldap_set_max_entries( server, ivalue );
972                 }
973                 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
974                         syldap_set_timeout( server, ivalue );
975                 }
976                 attr = g_list_next( attr );
977         }
978
979         ds->rawDataSource = server;
980         return ds;
981 }
982
983 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
984         SyldapServer *server = ds->rawDataSource;
985         if( server ) {
986                 gchar value[256];
987
988                 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
989                 addrindex_write_attr( fp, ATTAG_LDAP_NAME, syldap_get_name( server ) );
990                 addrindex_write_attr( fp, ATTAG_LDAP_HOST, server->hostName );
991
992                 sprintf( value, "%d", server->port );   
993                 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
994
995                 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, server->baseDN );
996                 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, server->bindDN );
997                 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, server->bindPass );
998                 addrindex_write_attr( fp, ATTAG_LDAP_CRITERIA, server->searchCriteria );
999
1000                 sprintf( value, "%d", server->maxEntries );
1001                 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1002                 sprintf( value, "%d", server->timeOut );
1003                 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1004
1005                 fputs(" />\n", fp);
1006         }
1007 }
1008 #else
1009 /* Just read/write name-value pairs (preserve data found in file)  */
1010 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1011         AddressDataSource *ds;
1012
1013         ds = addrindex_create_datasource( ADDR_IF_LDAP );
1014         ds->rawDataSource = addrindex_read_attributes( file );
1015         return ds;
1016 }
1017
1018 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1019         GList *list = ds->rawDataSource;
1020         if( list ) {
1021                 addrindex_write_attributes( fp, TAG_DS_LDAP, list, lvl );
1022         }
1023 }
1024 #endif
1025
1026 /* **********************************************************************
1027 * Address index I/O functions.
1028 * ***********************************************************************
1029 */
1030 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1031         guint prev_level;
1032         XMLTag *xtag;
1033         AddressInterface *iface = NULL, *dsIFace = NULL;
1034         AddressDataSource *ds;
1035
1036         for (;;) {
1037                 prev_level = file->level;
1038                 xml_parse_next_tag( file );
1039                 if( file->level < prev_level ) return;
1040
1041                 xtag = xml_get_current_tag( file );
1042
1043                 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1044                 if( iface ) {
1045                         addrIndex->lastType = iface->type;
1046                         if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1047                 }
1048                 else {
1049                         dsIFace = addrindex_tag_get_datasource(
1050                                         addrIndex, addrIndex->lastType, xtag->tag );
1051                         if( dsIFace ) {
1052                                 /* Add data source to list */
1053                                 ds = NULL;
1054                                 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1055                                         ds = addrindex_parse_book( file );
1056                                         if( ds->rawDataSource ) {
1057                                                 addrbook_set_path( ds->rawDataSource,
1058                                                         addrIndex->filePath );
1059                                         }
1060                                 }
1061                                 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1062                                         ds = addrindex_parse_vcard( file );
1063                                 }
1064                                 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1065                                         ds = addrindex_parse_jpilot( file );
1066                                 }
1067                                 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1068                                         ds = addrindex_parse_ldap( file );
1069                                 }
1070                                 if( ds ) {
1071                                         ds->interface = dsIFace;
1072                                         addrindex_hash_add_cache( addrIndex, ds );
1073                                         dsIFace->listSource =
1074                                                 g_list_append( dsIFace->listSource, ds );
1075                                 }
1076                         }
1077                 }
1078                 addrindex_read_index( addrIndex, file );
1079         }
1080 }
1081
1082 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1083         XMLFile *file = NULL;
1084         gchar *fileSpec = NULL;
1085
1086         g_return_val_if_fail( addrIndex != NULL, -1 );
1087
1088         fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1089         addrIndex->retVal = MGU_NO_FILE;
1090         file = xml_open_file( fileSpec );
1091         g_free( fileSpec );
1092
1093         if( file == NULL ) {
1094                 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
1095                 return addrIndex->retVal;
1096         }
1097
1098         addrIndex->retVal = MGU_BAD_FORMAT;
1099         if( xml_get_dtd( file ) == 0 ) {
1100                 if( xml_parse_next_tag( file ) == 0 ) {
1101                         if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1102                                 addrindex_read_index( addrIndex, file );
1103                                 addrIndex->retVal = MGU_SUCCESS;
1104                         }
1105                 }
1106         }
1107         xml_close_file( file );
1108
1109         return addrIndex->retVal;
1110 }
1111
1112 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1113         GList *nodeIF, *nodeDS;
1114         gint lvlList = 1;
1115         gint lvlItem = 1 + lvlList;
1116
1117         nodeIF = addrIndex->interfaceList;
1118         while( nodeIF ) {
1119                 AddressInterface *iface = nodeIF->data;
1120                 if( ! iface->legacyFlag ) {
1121                         nodeDS = iface->listSource;
1122                         addrindex_write_elem_s( fp, lvlList, iface->listTag );
1123                         fputs( ">\n", fp );
1124                         while( nodeDS ) {
1125                                 AddressDataSource *ds = nodeDS->data;
1126                                 if( ds ) {
1127                                         if( iface->type == ADDR_IF_BOOK ) {
1128                                                 addrindex_write_book( fp, ds, lvlItem );
1129                                         }
1130                                         if( iface->type == ADDR_IF_VCARD ) {
1131                                                 addrindex_write_vcard( fp, ds, lvlItem );
1132                                         }
1133                                         if( iface->type == ADDR_IF_JPILOT ) {
1134                                                 addrindex_write_jpilot( fp, ds, lvlItem );
1135                                         }
1136                                         if( iface->type == ADDR_IF_LDAP ) {
1137                                                 addrindex_write_ldap( fp, ds, lvlItem );
1138                                         }
1139                                 }
1140                                 nodeDS = g_list_next( nodeDS );
1141                         }
1142                         addrindex_write_elem_e( fp, lvlList, iface->listTag );
1143                 }
1144                 nodeIF = g_list_next( nodeIF );
1145         }
1146 }
1147
1148 /*
1149 * Write data to specified file.
1150 * Enter: addrIndex Address index object.
1151 *        newFile   New file name.
1152 * return: Status code, from addrIndex->retVal.
1153 * Note: File will be created in directory specified by addrIndex.
1154 */
1155 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1156         FILE *fp;
1157         gchar *fileSpec;
1158 #ifndef DEV_STANDALONE
1159         PrefFile *pfile;
1160 #endif
1161
1162         g_return_val_if_fail( addrIndex != NULL, -1 );
1163
1164         fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1165         addrIndex->retVal = MGU_OPEN_FILE;
1166 #ifdef DEV_STANDALONE
1167         fp = fopen( fileSpec, "wb" );
1168         g_free( fileSpec );
1169         if( fp ) {
1170                 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1171 #else
1172         pfile = prefs_write_open( fileSpec );
1173         g_free( fileSpec );
1174         if( pfile ) {
1175                 fp = pfile->fp;
1176                 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
1177                                 conv_get_current_charset_str() );
1178 #endif
1179                 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1180                 fputs( ">\n", fp );
1181
1182                 addrindex_write_index( addrIndex, fp );
1183                 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1184
1185                 addrIndex->retVal = MGU_SUCCESS;
1186 #ifdef DEV_STANDALONE
1187                 fclose( fp );
1188 #else
1189                 if( prefs_write_close( pfile ) < 0 ) {
1190                         addrIndex->retVal = MGU_ERROR_WRITE;
1191                 }
1192 #endif
1193         }
1194
1195         fileSpec = NULL;
1196         return addrIndex->retVal;
1197 }
1198
1199 /*
1200 * Save address index data to original file.
1201 * return: Status code, from addrIndex->retVal.
1202 */
1203 gint addrindex_save_data( AddressIndex *addrIndex ) {
1204         g_return_val_if_fail( addrIndex != NULL, -1 );
1205
1206         addrIndex->retVal = MGU_NO_FILE;
1207         if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1208         if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1209
1210         addrindex_write_to( addrIndex, addrIndex->fileName );
1211         if( addrIndex->retVal == MGU_SUCCESS ) {
1212                 addrIndex->dirtyFlag = FALSE;
1213         }
1214         return addrIndex->retVal;
1215 }
1216
1217 /*
1218 * Save all address book files which may have changed.
1219 * Return: Status code, set if there was a problem saving data.
1220 */
1221 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1222         gint retVal = MGU_SUCCESS;
1223         GList *nodeIf, *nodeDS;
1224
1225         nodeIf = addrIndex->interfaceList;
1226         while( nodeIf ) {
1227                 AddressInterface *iface = nodeIf->data;
1228                 if( iface->type == ADDR_IF_BOOK ) {
1229                         nodeDS = iface->listSource;
1230                         while( nodeDS ) {
1231                                 AddressDataSource *ds = nodeDS->data;
1232                                 AddressBookFile *abf = ds->rawDataSource;
1233                                 if( addrbook_get_dirty( abf ) ) {
1234                                         if( addrbook_get_read_flag( abf ) ) {
1235                                                 addrbook_save_data( abf );
1236                                                 if( abf->retVal != MGU_SUCCESS ) {
1237                                                         retVal = abf->retVal;
1238                                                 }
1239                                         }
1240                                 }
1241                                 nodeDS = g_list_next( nodeDS );
1242                         }
1243                         break;
1244                 }
1245                 nodeIf = g_list_next( nodeIf );
1246         }
1247         return retVal;
1248 }
1249
1250
1251 /* **********************************************************************
1252 * Address book conversion to new format.
1253 * ***********************************************************************
1254 */
1255
1256 #define ELTAG_IF_OLD_FOLDER   "folder"
1257 #define ELTAG_IF_OLD_GROUP    "group"
1258 #define ELTAG_IF_OLD_ITEM     "item"
1259 #define ELTAG_IF_OLD_NAME     "name"
1260 #define ELTAG_IF_OLD_ADDRESS  "address"
1261 #define ELTAG_IF_OLD_REMARKS  "remarks"
1262 #define ATTAG_IF_OLD_NAME     "name"
1263
1264 #define TEMPNODE_ROOT         0
1265 #define TEMPNODE_FOLDER       1
1266 #define TEMPNODE_GROUP        2
1267 #define TEMPNODE_ADDRESS      3
1268
1269 typedef struct _AddressCvt_Node AddressCvtNode;
1270 struct _AddressCvt_Node {
1271         gint  type;
1272         gchar *name;
1273         gchar *address;
1274         gchar *remarks;
1275         GList *list;
1276 };
1277
1278 /*
1279 * Parse current address item.
1280 */
1281 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1282         gchar *element;
1283         guint level;
1284         AddressCvtNode *nn;
1285
1286         nn = g_new0( AddressCvtNode, 1 );
1287         nn->type = TEMPNODE_ADDRESS;
1288         nn->list = NULL;
1289
1290         level = file->level;
1291
1292         for (;;) {
1293                 xml_parse_next_tag(file);
1294                 if (file->level < level) return nn;
1295
1296                 element = xml_get_element( file );
1297                 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1298                         nn->name = g_strdup( element );
1299                 }
1300                 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1301                         nn->address = g_strdup( element );
1302                 }
1303                 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1304                         nn->remarks = g_strdup( element );
1305                 }
1306                 xml_parse_next_tag(file);
1307         }
1308 }
1309
1310 /*
1311 * Create a temporary node below specified node.
1312 */
1313 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1314         AddressCvtNode *nn;
1315         nn = g_new0( AddressCvtNode, 1 );
1316         nn->type = type;
1317         nn->name = g_strdup( name );
1318         nn->remarks = g_strdup( rem );
1319         node->list = g_list_append( node->list, nn );
1320         return nn;
1321 }
1322
1323 /*
1324 * Process current temporary node.
1325 */
1326 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1327         GList *attr;
1328         guint prev_level;
1329         AddressCvtNode *newNode = NULL;
1330         gchar *name;
1331         gchar *value;
1332
1333         for (;;) {
1334                 prev_level = file->level;
1335                 xml_parse_next_tag( file );
1336                 if (file->level < prev_level) return;
1337                 name = NULL;
1338                 value = NULL;
1339
1340                 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1341                         attr = xml_get_current_tag_attr(file);
1342                         if (attr) {
1343                                 name = ((XMLAttr *)attr->data)->name;
1344                                 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1345                                         value = ((XMLAttr *)attr->data)->value;
1346                                 }
1347                         }
1348                         newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1349                         addrindex_add_obj( file, newNode );
1350
1351                 }
1352                 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1353                         attr = xml_get_current_tag_attr(file);
1354                         if (attr) {
1355                                 name = ((XMLAttr *)attr->data)->name;
1356                                 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1357                                         value = ((XMLAttr *)attr->data)->value;
1358                                 }
1359                         }
1360                         newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1361                         addrindex_add_obj( file, newNode );
1362                 }
1363                 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1364                         newNode = addrindex_parse_item( file );
1365                         node->list = g_list_append( node->list, newNode );
1366                 }
1367                 else {
1368                         /* printf( "invalid: !!! \n" ); */
1369                         attr = xml_get_current_tag_attr( file );
1370                 }
1371         }
1372 }
1373
1374 /*
1375 * Consume all nodes below current tag.
1376 */
1377 static void addrindex_consume_tree( XMLFile *file ) {
1378         guint prev_level;
1379         gchar *element;
1380         GList *attr;
1381         XMLTag *xtag;
1382
1383         for (;;) {
1384                 prev_level = file->level;
1385                 xml_parse_next_tag( file );
1386                 if (file->level < prev_level) return;
1387
1388                 xtag = xml_get_current_tag( file );
1389                 /* printf( "tag : %s\n", xtag->tag ); */
1390                 element = xml_get_element( file );
1391                 attr = xml_get_current_tag_attr( file );
1392                 /* show_attribs( attr ); */
1393                 /* printf( "\ttag  value : %s :\n", element ); */
1394                 addrindex_consume_tree( file );
1395         }
1396 }
1397
1398 /*
1399 * Print temporary tree.
1400 */
1401 static void addrindex_print_node( AddressCvtNode *node, FILE *stream  ) {
1402         GList *list;
1403
1404         fprintf( stream, "Node:\ttype :%d:\n", node->type );
1405         fprintf( stream, "\tname :%s:\n", node->name );
1406         fprintf( stream, "\taddr :%s:\n", node->address );
1407         fprintf( stream, "\trems :%s:\n", node->remarks );
1408         if( node->list ) {
1409                 fprintf( stream, "\t--list----\n" );
1410         }
1411         list = node->list;
1412         while( list ) {
1413                 AddressCvtNode *lNode = list->data;
1414                 list = g_list_next( list );
1415                 addrindex_print_node( lNode, stream );
1416         }
1417         fprintf( stream, "\t==list-%d==\n", node->type );
1418 }
1419
1420 /*
1421 * Free up temporary tree.
1422 */
1423 static void addrindex_free_node( AddressCvtNode *node ) {
1424         GList *list = node->list;
1425
1426         while( list ) {
1427                 AddressCvtNode *lNode = list->data;
1428                 list = g_list_next( list );
1429                 addrindex_free_node( lNode );
1430         }
1431         node->type = TEMPNODE_ROOT;
1432         g_free( node->name );
1433         g_free( node->address );
1434         g_free( node->remarks );
1435         g_list_free( node->list );
1436         g_free( node );
1437 }
1438
1439 /*
1440 * Process address book for specified node.
1441 */
1442 static void addrindex_process_node(
1443                 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1444                 ItemGroup *parentGrp, ItemFolder *folderGrp )
1445 {
1446         GList *list;
1447         ItemFolder *itemFolder = NULL;
1448         ItemGroup *itemGParent = parentGrp;
1449         ItemFolder *itemGFolder = folderGrp;
1450         AddressCache *cache = abf->addressCache;
1451
1452         if( node->type == TEMPNODE_ROOT ) {
1453                 itemFolder = parent;
1454         }
1455         else if( node->type == TEMPNODE_FOLDER ) {
1456                 itemFolder = addritem_create_item_folder();
1457                 addritem_folder_set_name( itemFolder, node->name );
1458                 addrcache_id_folder( cache, itemFolder );
1459                 addrcache_folder_add_folder( cache, parent, itemFolder );
1460                 itemGFolder = NULL;
1461         }
1462         else if( node->type == TEMPNODE_GROUP ) {
1463                 ItemGroup *itemGroup;
1464                 gchar *fName;
1465
1466                 /* Create a folder for group */
1467                 fName = g_strdup_printf( "Cvt - %s", node->name );
1468                 itemGFolder = addritem_create_item_folder();
1469                 addritem_folder_set_name( itemGFolder, fName );
1470                 addrcache_id_folder( cache, itemGFolder );
1471                 addrcache_folder_add_folder( cache, parent, itemGFolder );
1472                 g_free( fName );
1473
1474                 /* Add group into folder */
1475                 itemGroup = addritem_create_item_group();
1476                 addritem_group_set_name( itemGroup, node->name );
1477                 addrcache_id_group( cache, itemGroup );
1478                 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1479                 itemGParent = itemGroup;
1480         }
1481         else if( node->type == TEMPNODE_ADDRESS ) {
1482                 ItemPerson *itemPerson;
1483                 ItemEMail *itemEMail;
1484
1485                 /* Create person and email objects */
1486                 itemPerson = addritem_create_item_person();
1487                 addritem_person_set_common_name( itemPerson, node->name );
1488                 addrcache_id_person( cache, itemPerson );
1489                 itemEMail = addritem_create_item_email();
1490                 addritem_email_set_address( itemEMail, node->address );
1491                 addritem_email_set_remarks( itemEMail, node->remarks );
1492                 addrcache_id_email( cache, itemEMail );
1493                 addrcache_person_add_email( cache, itemPerson, itemEMail );
1494
1495                 /* Add person into appropriate folder */
1496                 if( itemGFolder ) {
1497                         addrcache_folder_add_person( cache, itemGFolder, itemPerson );
1498                 }
1499                 else {
1500                         addrcache_folder_add_person( cache, parent, itemPerson );
1501                 }
1502
1503                 /* Add email address only into group */
1504                 if( parentGrp ) {
1505                         addrcache_group_add_email( cache, parentGrp, itemEMail );
1506                 }
1507         }
1508
1509         list = node->list;
1510         while( list ) {
1511                 AddressCvtNode *lNode = list->data;
1512                 list = g_list_next( list );
1513                 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
1514         }
1515 }
1516
1517 /*
1518 * Process address book to specified file number.
1519 */
1520 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
1521         gboolean retVal = FALSE;
1522         AddressBookFile *abf = NULL;
1523         AddressCvtNode *rootNode = NULL;
1524         gchar *newFile = NULL;
1525         GList *fileList = NULL;
1526         gint fileNum  = 0;
1527
1528         /* Setup root node */
1529         rootNode = g_new0( AddressCvtNode, 1 );
1530         rootNode->type = TEMPNODE_ROOT;
1531         rootNode->name = g_strdup( "root" );
1532         rootNode->list = NULL;
1533         addrindex_add_obj( file, rootNode );
1534         /* addrindex_print_node( rootNode, stdout ); */
1535
1536         /* Create new address book */
1537         abf = addrbook_create_book();
1538         addrbook_set_name( abf, displayName );
1539         addrbook_set_path( abf, addrIndex->filePath );
1540
1541         /* Determine next available file number */
1542         fileList = addrbook_get_bookfile_list( abf );
1543         if( fileList ) {
1544                 fileNum = 1 + abf->maxValue;
1545         }
1546         g_list_free( fileList );
1547         fileList = NULL;
1548
1549         newFile = addrbook_gen_new_file_name( fileNum );
1550         if( newFile ) {
1551                 addrbook_set_file( abf, newFile );
1552         }
1553
1554         addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
1555
1556         /* addrbook_dump_book( abf, stdout ); */
1557         addrbook_save_data( abf );
1558         addrIndex->retVal = abf->retVal;
1559         if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
1560
1561         addrbook_free_book( abf );
1562         abf = NULL;
1563         addrindex_free_node( rootNode );
1564         rootNode = NULL;
1565
1566         /* Create entries in address index */
1567         if( retVal ) {
1568                 abf = addrbook_create_book();
1569                 addrbook_set_name( abf, displayName );
1570                 addrbook_set_path( abf, addrIndex->filePath );
1571                 addrbook_set_file( abf, newFile );
1572                 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
1573         }
1574
1575         return retVal;
1576 }
1577
1578 /*
1579 * Process tree converting data.
1580 */
1581 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
1582         guint prev_level;
1583         gchar *element;
1584         GList *attr;
1585         XMLTag *xtag;
1586
1587         /* Process file */
1588         for (;;) {
1589                 prev_level = file->level;
1590                 xml_parse_next_tag( file );
1591                 if (file->level < prev_level) return;
1592
1593                 xtag = xml_get_current_tag( file );
1594                 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
1595                 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
1596                         if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
1597                                 addrIndex->needsConversion = FALSE;
1598                                 addrIndex->wasConverted = TRUE;
1599                                 continue;
1600                         }
1601                         return;
1602                 }
1603                 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
1604                         if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
1605                                 addrIndex->needsConversion = FALSE;
1606                                 addrIndex->wasConverted = TRUE;
1607                                 continue;
1608                         }
1609                         return;
1610                 }
1611                 element = xml_get_element( file );
1612                 attr = xml_get_current_tag_attr( file );
1613                 /* show_attribs( attr ); */
1614                 /* printf( "\ttag  value : %s :\n", element ); */
1615                 addrindex_consume_tree( file );
1616         }
1617 }
1618
1619 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
1620         XMLFile *file = NULL;
1621         gchar *fileSpec;
1622
1623         fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1624         addrIndex->retVal = MGU_NO_FILE;
1625         file = xml_open_file( fileSpec );
1626         g_free( fileSpec );
1627
1628         if( file == NULL ) {
1629                 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
1630                 return addrIndex->retVal;
1631         }
1632
1633         addrIndex->retVal = MGU_BAD_FORMAT;
1634         if( xml_get_dtd( file ) == 0 ) {
1635                 if( xml_parse_next_tag( file ) == 0 ) {
1636                         if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1637                                 addrindex_convert_tree( addrIndex, file );
1638                         }
1639                 }
1640         }
1641         xml_close_file( file );
1642         return addrIndex->retVal;
1643 }
1644
1645 /*
1646 * Create a new address book file.
1647 */
1648 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
1649         gboolean retVal = FALSE;
1650         AddressBookFile *abf = NULL;
1651         gchar *newFile = NULL;
1652         GList *fileList = NULL;
1653         gint fileNum = 0;
1654
1655         /* Create new address book */
1656         abf = addrbook_create_book();
1657         addrbook_set_name( abf, displayName );
1658         addrbook_set_path( abf, addrIndex->filePath );
1659
1660         /* Determine next available file number */
1661         fileList = addrbook_get_bookfile_list( abf );
1662         if( fileList ) {
1663                 fileNum = 1 + abf->maxValue;
1664         }
1665         g_list_free( fileList );
1666         fileList = NULL;
1667
1668         newFile = addrbook_gen_new_file_name( fileNum );
1669         if( newFile ) {
1670                 addrbook_set_file( abf, newFile );
1671         }
1672
1673         addrbook_save_data( abf );
1674         addrIndex->retVal = abf->retVal;
1675         if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
1676         addrbook_free_book( abf );
1677         abf = NULL;
1678
1679         /* Create entries in address index */
1680         if( retVal ) {
1681                 abf = addrbook_create_book();
1682                 addrbook_set_name( abf, displayName );
1683                 addrbook_set_path( abf, addrIndex->filePath );
1684                 addrbook_set_file( abf, newFile );
1685                 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
1686         }
1687
1688         return retVal;
1689 }
1690
1691 /*
1692 * Read data for address index performing a conversion if necesary.
1693 * Enter: addrIndex Address index object.
1694 * return: Status code, from addrIndex->retVal.
1695 * Note: New address book files will be created in directory specified by
1696 * addrIndex. Three files will be created, for the following:
1697 *       "Common addresses"
1698 *       "Personal addresses"
1699 *       "Gathered addresses" - a new address book.
1700 */
1701 gint addrindex_read_data( AddressIndex *addrIndex ) {
1702         g_return_val_if_fail( addrIndex != NULL, -1 );
1703
1704         addrIndex->conversionError = FALSE;
1705         addrindex_read_file( addrIndex );
1706         if( addrIndex->retVal == MGU_SUCCESS ) {
1707                 if( addrIndex->needsConversion ) {
1708                         if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
1709                                 addrIndex->conversionError = TRUE;
1710                         }
1711                         else {
1712                                 addrIndex->conversionError = TRUE;
1713                         }
1714                 }
1715                 addrIndex->dirtyFlag = TRUE;
1716         }
1717         return addrIndex->retVal;
1718 }
1719
1720 /*
1721 * Create new address books for a new address index.
1722 * Enter: addrIndex Address index object.
1723 * return: Status code, from addrIndex->retVal.
1724 * Note: New address book files will be created in directory specified by
1725 * addrIndex. Three files will be created, for the following:
1726 *       "Common addresses"
1727 *       "Personal addresses"
1728 *       "Gathered addresses" - a new address book.
1729 */
1730 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
1731         gboolean flg;
1732
1733         g_return_val_if_fail( addrIndex != NULL, -1 );
1734
1735         flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
1736         if( flg ) {
1737                 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
1738                 addrIndex->dirtyFlag = TRUE;
1739         }
1740         return addrIndex->retVal;
1741 }
1742
1743 /* **********************************************************************
1744 * New interface stuff.
1745 * ***********************************************************************
1746 */
1747
1748 /*
1749  * Return modified flag for specified data source.
1750  */
1751 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
1752         gboolean retVal = FALSE;
1753         AddressInterface *iface;
1754
1755         if( ds == NULL ) return retVal;
1756         iface = ds->interface;
1757         if( iface == NULL ) return retVal;
1758         if( iface->getModifyFlag ) {
1759                 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
1760         }
1761         return retVal;
1762 }
1763
1764 /*
1765  * Return accessed flag for specified data source.
1766  */
1767 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
1768         gboolean retVal = FALSE;
1769         AddressInterface *iface;
1770
1771         if( ds == NULL ) return retVal;
1772         iface = ds->interface;
1773         if( iface == NULL ) return retVal;
1774         if( iface->getAccessFlag ) {
1775                 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
1776         }
1777         return retVal;
1778 }
1779
1780 /*
1781  * Return data read flag for specified data source.
1782  */
1783 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
1784         gboolean retVal = TRUE;
1785         AddressInterface *iface;
1786
1787         if( ds == NULL ) return retVal;
1788         iface = ds->interface;
1789         if( iface == NULL ) return retVal;
1790         if( iface->getReadFlag ) {
1791                 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
1792         }
1793         return retVal;
1794 }
1795
1796 /*
1797  * Return status code for specified data source.
1798  */
1799 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
1800         gint retVal = MGU_SUCCESS;
1801         AddressInterface *iface;
1802
1803         if( ds == NULL ) return retVal;
1804         iface = ds->interface;
1805         if( iface == NULL ) return retVal;
1806         if( iface->getStatusCode ) {
1807                 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
1808         }
1809         return retVal;
1810 }
1811
1812 /*
1813  * Return data read flag for specified data source.
1814  */
1815 gint addrindex_ds_read_data( AddressDataSource *ds ) {
1816         gint retVal = MGU_SUCCESS;
1817         AddressInterface *iface;
1818
1819         if( ds == NULL ) return retVal;
1820         iface = ds->interface;
1821         if( iface == NULL ) return retVal;
1822         if( iface->getReadData ) {
1823                 retVal = ( iface->getReadData ) ( ds->rawDataSource );
1824         }
1825         return retVal;
1826 }
1827
1828 /*
1829  * Return data read flag for specified data source.
1830  */
1831 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
1832         ItemFolder *retVal = NULL;
1833         AddressInterface *iface;
1834
1835         if( ds == NULL ) return retVal;
1836         iface = ds->interface;
1837         if( iface == NULL ) return retVal;
1838         if( iface->getRootFolder ) {
1839                 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
1840         }
1841         return retVal;
1842 }
1843
1844 /*
1845  * Return list of folders for specified data source.
1846  */
1847 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
1848         GList *retVal = FALSE;
1849         AddressInterface *iface;
1850
1851         if( ds == NULL ) return retVal;
1852         iface = ds->interface;
1853         if( iface == NULL ) return retVal;
1854         if( iface->getListFolder ) {
1855                 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
1856         }
1857         return retVal;
1858 }
1859
1860 /*
1861  * Return list of persons in root folder for specified data source.
1862  */
1863 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
1864         GList *retVal = FALSE;
1865         AddressInterface *iface;
1866
1867         if( ds == NULL ) return retVal;
1868         iface = ds->interface;
1869         if( iface == NULL ) return retVal;
1870         if( iface->getListPerson ) {
1871                 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
1872         }
1873         return retVal;
1874 }
1875
1876 /*
1877  * Return name for specified data source.
1878  */
1879 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
1880         gchar *retVal = FALSE;
1881         AddressInterface *iface;
1882
1883         if( ds == NULL ) return retVal;
1884         iface = ds->interface;
1885         if( iface == NULL ) return retVal;
1886         if( iface->getName ) {
1887                 retVal = ( iface->getName ) ( ds->rawDataSource );
1888         }
1889         return retVal;
1890 }
1891
1892 /*
1893  * Set the access flag inside the data source.
1894  */
1895 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
1896         AddressInterface *iface;
1897
1898         if( ds == NULL ) return;
1899         iface = ds->interface;
1900         if( iface == NULL ) return;
1901         if( iface->setAccessFlag ) {
1902                 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
1903         }
1904 }
1905
1906 /*
1907  * Return read only flag for specified data source.
1908  */
1909 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
1910         AddressInterface *iface;
1911         if( ds == NULL ) return TRUE;
1912         iface = ds->interface;
1913         if( iface == NULL ) return TRUE;
1914         return iface->readOnly;
1915 }
1916
1917 /*
1918  * Return list of all persons for specified data source.
1919  */
1920 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
1921         GList *retVal = NULL;
1922         AddressInterface *iface;
1923
1924         if( ds == NULL ) return retVal;
1925         iface = ds->interface;
1926         if( iface == NULL ) return retVal;
1927         if( iface->getAllPersons ) {
1928                 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
1929         }
1930         return retVal;
1931 }
1932
1933 /*
1934  * Return list of all groups for specified data source.
1935  */
1936 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
1937         GList *retVal = NULL;
1938         AddressInterface *iface;
1939
1940         if( ds == NULL ) return retVal;
1941         iface = ds->interface;
1942         if( iface == NULL ) return retVal;
1943         if( iface->getAllGroups ) {
1944                 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
1945         }
1946         return retVal;
1947 }
1948
1949 /*
1950 * End of Source.
1951 */