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