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