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