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