2007-08-27 [colin] 2.10.0cvs179
[claws.git] / src / addrindex.c
blob6885b5644dffd58dbebe6a87c4b721a666ff5c1e
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2007 Match Grun and the Claws Mail team
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 3 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * General functions for accessing address index file.
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include "defs.h"
30 #include <glib.h>
31 #include <glib/gi18n.h>
33 #include "mgutils.h"
34 #include "addritem.h"
35 #include "addrcache.h"
36 #include "addrbook.h"
37 #include "addressbook.h"
38 #include "addrindex.h"
39 #include "xml.h"
40 #include "addrquery.h"
41 #include "addr_compl.h"
42 #include "utils.h"
43 #include "alertpanel.h"
45 #ifndef DEV_STANDALONE
46 #include "prefs_gtk.h"
47 #include "codeconv.h"
48 #endif
50 #include "vcard.h"
52 #ifdef USE_JPILOT
53 #include "jpilot.h"
54 #endif
56 #ifdef USE_LDAP
57 #include "ldapserver.h"
58 #include "ldapctrl.h"
59 #include "ldapquery.h"
60 #include "ldapupdate.h"
61 #include "ldaputil.h"
62 #endif
64 #define TAG_ADDRESS_INDEX "addressbook"
66 #define TAG_IF_ADDRESS_BOOK "book_list"
67 #define TAG_IF_VCARD "vcard_list"
68 #define TAG_IF_JPILOT "jpilot_list"
69 #define TAG_IF_LDAP "ldap_list"
71 #define TAG_DS_ADDRESS_BOOK "book"
72 #define TAG_DS_VCARD "vcard"
73 #define TAG_DS_JPILOT "jpilot"
74 #define TAG_DS_LDAP "server"
76 /* XML Attribute names */
77 #define ATTAG_BOOK_NAME "name"
78 #define ATTAG_BOOK_FILE "file"
80 #define ATTAG_VCARD_NAME "name"
81 #define ATTAG_VCARD_FILE "file"
83 #define ATTAG_JPILOT_NAME "name"
84 #define ATTAG_JPILOT_FILE "file"
85 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
86 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
87 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
88 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
89 #define ATTAG_JPILOT_CUSTOM "custom-"
91 #define ATTAG_LDAP_NAME "name"
92 #define ATTAG_LDAP_HOST "host"
93 #define ATTAG_LDAP_PORT "port"
94 #define ATTAG_LDAP_BASE_DN "base-dn"
95 #define ATTAG_LDAP_BIND_DN "bind-dn"
96 #define ATTAG_LDAP_BIND_PASS "bind-pass"
97 #define ATTAG_LDAP_CRITERIA "criteria"
98 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
99 #define ATTAG_LDAP_TIMEOUT "timeout"
100 #define ATTAG_LDAP_MAX_AGE "max-age"
101 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
102 #define ATTAG_LDAP_MATCH_OPT "match-opt"
103 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
104 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
106 #define ELTAG_LDAP_ATTR_SRCH "attribute"
107 #define ATTAG_LDAP_ATTR_NAME "name"
109 /* Attribute values */
110 #define ATVAL_BOOLEAN_YES "yes"
111 #define ATVAL_BOOLEAN_NO "no"
112 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
113 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
115 /* New attributes */
116 #define ATTAG_LDAP_DEFAULT "default"
118 #define DISP_NEW_COMMON _("Common addresses")
119 #define DISP_NEW_PERSONAL _("Personal addresses")
121 /* Old address book */
122 #define TAG_IF_OLD_COMMON "common_address"
123 #define TAG_IF_OLD_PERSONAL "personal_address"
125 #define DISP_OLD_COMMON _("Common address")
126 #define DISP_OLD_PERSONAL _("Personal address")
129 * Singleton object.
131 static AddressIndex *_addressIndex_ = NULL;
134 * Define attribute name-value pair.
136 typedef struct _AddressIfAttr AddressIfAttrib;
137 struct _AddressIfAttr {
138 gchar *name;
139 gchar *value;
142 static AddressDataSource *addrindex_create_datasource ( AddressIfType ifType );
144 static GList *addrindex_ds_get_all_persons ( AddressDataSource *ds );
145 static GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
146 static AddressDataSource *addrindex_get_datasource ( AddressIndex *addrIndex,
147 const gchar *cacheID );
148 static AddressInterface *addrindex_get_interface ( AddressIndex *addrIndex,
149 AddressIfType ifType );
150 static gint addrindex_write_to ( AddressIndex *addrIndex,
151 const gchar *newFile );
154 * Define DOM fragment.
156 typedef struct _AddressIfFrag AddressIfFragment;
157 struct _AddressIfFrag {
158 gchar *name;
159 GList *children;
160 GList *attributes;
164 * Build interface with default values.
166 * \param type Interface type.
167 * \param name Interface name.
168 * \param tagIf XML tag name for interface in address index file.
169 * \param tagDS XML tag name for datasource in address index file.
170 * \return Address interface object.
172 static AddressInterface *addrindex_create_interface(
173 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
175 AddressInterface *iface = g_new0( AddressInterface, 1 );
177 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
178 ADDRITEM_ID(iface) = NULL;
179 ADDRITEM_NAME(iface) = g_strdup( name );
180 ADDRITEM_PARENT(iface) = NULL;
181 ADDRITEM_SUBTYPE(iface) = type;
182 iface->type = type;
183 iface->name = g_strdup( name );
184 iface->listTag = g_strdup( tagIf );
185 iface->itemTag = g_strdup( tagDS );
186 iface->legacyFlag = FALSE;
187 iface->haveLibrary = TRUE;
188 iface->useInterface = TRUE;
189 iface->readOnly = TRUE;
191 /* Set callbacks to NULL values - override for each interface */
192 iface->getAccessFlag = NULL;
193 iface->getModifyFlag = NULL;
194 iface->getReadFlag = NULL;
195 iface->getStatusCode = NULL;
196 iface->getReadData = NULL;
197 iface->getRootFolder = NULL;
198 iface->getListFolder = NULL;
199 iface->getListPerson = NULL;
200 iface->getAllPersons = NULL;
201 iface->getAllGroups = NULL;
202 iface->getName = NULL;
203 iface->listSource = NULL;
205 /* Search stuff */
206 iface->externalQuery = FALSE;
207 iface->searchOrder = 0; /* Ignored */
208 iface->startSearch = NULL;
209 iface->stopSearch = NULL;
211 return iface;
215 * Build table of of all address book interfaces.
216 * \param addrIndex Address index object.
218 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
219 AddressInterface *iface;
221 /* Create intrinsic XML address book interface */
222 iface = addrindex_create_interface(
223 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
224 TAG_DS_ADDRESS_BOOK );
225 iface->readOnly = FALSE;
226 iface->getModifyFlag = ( void * ) addrbook_get_modified;
227 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
228 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
229 iface->getStatusCode = ( void * ) addrbook_get_status;
230 iface->getReadData = ( void * ) addrbook_read_data;
231 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
232 iface->getListFolder = ( void * ) addrbook_get_list_folder;
233 iface->getListPerson = ( void * ) addrbook_get_list_person;
234 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
235 iface->getAllGroups = ( void * ) addrbook_get_all_groups;
236 iface->getName = ( void * ) addrbook_get_name;
237 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
238 iface->searchOrder = 0;
240 /* Add to list of interfaces in address book */
241 addrIndex->interfaceList =
242 g_list_append( addrIndex->interfaceList, iface );
243 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
245 /* Create vCard interface */
246 iface = addrindex_create_interface(
247 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
248 iface->getModifyFlag = ( void * ) vcard_get_modified;
249 iface->getAccessFlag = ( void * ) vcard_get_accessed;
250 iface->getReadFlag = ( void * ) vcard_get_read_flag;
251 iface->getStatusCode = ( void * ) vcard_get_status;
252 iface->getReadData = ( void * ) vcard_read_data;
253 iface->getRootFolder = ( void * ) vcard_get_root_folder;
254 iface->getListFolder = ( void * ) vcard_get_list_folder;
255 iface->getListPerson = ( void * ) vcard_get_list_person;
256 iface->getAllPersons = ( void * ) vcard_get_all_persons;
257 iface->getName = ( void * ) vcard_get_name;
258 iface->setAccessFlag = ( void * ) vcard_set_accessed;
259 iface->searchOrder = 0;
260 addrIndex->interfaceList =
261 g_list_append( addrIndex->interfaceList, iface );
262 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
264 /* Create JPilot interface */
265 iface = addrindex_create_interface(
266 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
267 TAG_DS_JPILOT );
268 #ifdef USE_JPILOT
269 iface->haveLibrary = jpilot_test_pilot_lib();
270 iface->useInterface = iface->haveLibrary;
271 iface->getModifyFlag = ( void * ) jpilot_get_modified;
272 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
273 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
274 iface->getStatusCode = ( void * ) jpilot_get_status;
275 iface->getReadData = ( void * ) jpilot_read_data;
276 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
277 iface->getListFolder = ( void * ) jpilot_get_list_folder;
278 iface->getListPerson = ( void * ) jpilot_get_list_person;
279 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
280 iface->getName = ( void * ) jpilot_get_name;
281 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
282 iface->searchOrder = 0;
283 #else
284 iface->useInterface = FALSE;
285 iface->haveLibrary = FALSE;
286 #endif
287 addrIndex->interfaceList =
288 g_list_append( addrIndex->interfaceList, iface );
289 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
291 /* Create LDAP interface */
292 iface = addrindex_create_interface(
293 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
294 #ifdef USE_LDAP
295 iface->readOnly = FALSE;
296 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
297 iface->haveLibrary = ldaputil_test_ldap_lib();
298 iface->useInterface = iface->haveLibrary;
299 iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
300 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
301 iface->getReadFlag = ( void * ) ldapsvr_get_read_flag;
302 iface->getStatusCode = ( void * ) ldapsvr_get_status;
303 iface->getReadData = ( void * ) ldapsvr_read_data;
304 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
305 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
306 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
307 iface->getName = ( void * ) ldapsvr_get_name;
308 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
309 iface->externalQuery = TRUE;
310 iface->searchOrder = 1;
311 #else
312 iface->useInterface = FALSE;
313 iface->haveLibrary = FALSE;
314 #endif
315 addrIndex->interfaceList =
316 g_list_append( addrIndex->interfaceList, iface );
317 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
319 /* Two old legacy data sources (pre 0.7.0) */
320 iface = addrindex_create_interface(
321 ADDR_IF_COMMON, "Old Address - common",
322 TAG_IF_OLD_COMMON, NULL );
323 iface->legacyFlag = TRUE;
324 addrIndex->interfaceList =
325 g_list_append( addrIndex->interfaceList, iface );
326 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
328 iface = addrindex_create_interface(
329 ADDR_IF_COMMON, "Old Address - personal",
330 TAG_IF_OLD_PERSONAL, NULL );
331 iface->legacyFlag = TRUE;
332 addrIndex->interfaceList =
333 g_list_append( addrIndex->interfaceList, iface );
334 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
339 * Free DOM fragment.
340 * \param fragment Fragment to free.
342 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
343 GList *node;
345 /* Free children */
346 node = fragment->children;
347 while( node ) {
348 AddressIfFragment *child = node->data;
349 addrindex_free_fragment( child );
350 node->data = NULL;
351 node = g_list_next( node );
353 g_list_free( fragment->children );
355 /* Free attributes */
356 node = fragment->attributes;
357 while( node ) {
358 AddressIfAttrib *nv = node->data;
359 g_free( nv->name );
360 g_free( nv->value );
361 g_free( nv );
362 node->data = NULL;
363 node = g_list_next( node );
365 g_list_free( fragment->attributes );
367 g_free( fragment->name );
368 fragment->name = NULL;
369 fragment->attributes = NULL;
370 fragment->children = NULL;
372 g_free( fragment );
376 * Create a new data source.
377 * \param ifType Interface type to create.
378 * \return Initialized data source.
380 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
381 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
383 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
384 ADDRITEM_ID(ds) = NULL;
385 ADDRITEM_NAME(ds) = NULL;
386 ADDRITEM_PARENT(ds) = NULL;
387 ADDRITEM_SUBTYPE(ds) = 0;
388 ds->type = ifType;
389 ds->rawDataSource = NULL;
390 ds->interface = NULL;
391 return ds;
395 * Free up data source.
396 * \param ds Data source to free.
398 void addrindex_free_datasource( AddressDataSource *ds ) {
399 AddressInterface *iface;
401 g_return_if_fail( ds != NULL );
403 iface = ds->interface;
404 if( ds->rawDataSource != NULL ) {
405 if( iface != NULL ) {
406 if( iface->useInterface ) {
407 if( iface->type == ADDR_IF_BOOK ) {
408 AddressBookFile *abf = ds->rawDataSource;
409 addrbook_free_book( abf );
411 else if( iface->type == ADDR_IF_VCARD ) {
412 VCardFile *vcf = ds->rawDataSource;
413 vcard_free( vcf );
415 #ifdef USE_JPILOT
416 else if( iface->type == ADDR_IF_JPILOT ) {
417 JPilotFile *jpf = ds->rawDataSource;
418 jpilot_free( jpf );
420 #endif
421 #ifdef USE_LDAP
422 else if( iface->type == ADDR_IF_LDAP ) {
423 LdapServer *server = ds->rawDataSource;
424 ldapsvr_free( server );
426 #endif
427 else {
430 else {
431 AddressIfFragment *fragment = ds->rawDataSource;
432 addrindex_free_fragment( fragment );
437 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
438 ADDRITEM_ID(ds) = NULL;
439 ADDRITEM_NAME(ds) = NULL;
440 ADDRITEM_PARENT(ds) = NULL;
441 ADDRITEM_SUBTYPE(ds) = 0;
442 ds->type = ADDR_IF_NONE;
443 ds->interface = NULL;
444 ds->rawDataSource = NULL;
446 g_free( ds );
450 * Free up all data sources for specified interface.
451 * \param iface Address interface to process.
453 static void addrindex_free_all_datasources( AddressInterface *iface ) {
454 GList *node = iface->listSource;
455 while( node ) {
456 AddressDataSource *ds = node->data;
457 addrindex_free_datasource( ds );
458 node->data = NULL;
459 node = g_list_next( node );
464 * Free up specified interface.
465 * \param iface Interface to process.
467 static void addrindex_free_interface( AddressInterface *iface ) {
468 /* Free up data sources */
469 addrindex_free_all_datasources( iface );
470 g_list_free( iface->listSource );
472 /* Free internal storage */
473 g_free( ADDRITEM_ID(iface) );
474 g_free( ADDRITEM_NAME(iface) );
475 g_free( iface->name );
476 g_free( iface->listTag );
477 g_free( iface->itemTag );
479 /* Clear all pointers */
480 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
481 ADDRITEM_ID(iface) = NULL;
482 ADDRITEM_NAME(iface) = NULL;
483 ADDRITEM_PARENT(iface) = NULL;
484 ADDRITEM_SUBTYPE(iface) = 0;
485 iface->type = ADDR_IF_NONE;
486 iface->name = NULL;
487 iface->listTag = NULL;
488 iface->itemTag = NULL;
489 iface->legacyFlag = FALSE;
490 iface->useInterface = FALSE;
491 iface->haveLibrary = FALSE;
492 iface->listSource = NULL;
494 /* Search stuff */
495 iface->searchOrder = 0;
496 iface->startSearch = NULL;
497 iface->stopSearch = NULL;
499 g_free( iface );
503 * Return cache ID for specified data source.
505 * \param addrIndex Address index.
506 * \param ds Data source.
507 * \return ID or NULL if not found. This should be <code>g_free()</code>
508 * when done.
510 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
511 gchar *cacheID = NULL;
512 AddrBookBase *adbase;
513 AddressCache *cache;
515 g_return_val_if_fail( addrIndex != NULL, NULL );
516 g_return_val_if_fail( ds != NULL, NULL );
518 adbase = ( AddrBookBase * ) ds->rawDataSource;
519 if( adbase ) {
520 cache = adbase->addressCache;
521 if( cache ) {
522 cacheID = g_strdup( cache->cacheID );
526 return cacheID;
530 * Return reference to data source for specified cacheID.
531 * \param addrIndex Address index.
532 * \param cacheID ID.
533 * \return Data source, or NULL if not found.
535 static AddressDataSource *addrindex_get_datasource(
536 AddressIndex *addrIndex, const gchar *cacheID )
538 g_return_val_if_fail( addrIndex != NULL, NULL );
539 g_return_val_if_fail( cacheID != NULL, NULL );
540 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
544 * Return reference to address cache for specified cacheID.
545 * \param addrIndex Address index.
546 * \param cacheID ID.
547 * \return Address cache, or NULL if not found.
549 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
550 AddressDataSource *ds;
551 AddrBookBase *adbase;
552 AddressCache *cache;
554 g_return_val_if_fail( addrIndex != NULL, NULL );
555 g_return_val_if_fail( cacheID != NULL, NULL );
557 cache = NULL;
558 ds = addrindex_get_datasource( addrIndex, cacheID );
559 if( ds ) {
560 adbase = ( AddrBookBase * ) ds->rawDataSource;
561 cache = adbase->addressCache;
563 return cache;
567 * Add data source into hash table.
568 * \param addrIndex Address index.
569 * \param ds Data source.
571 static void addrindex_hash_add_cache(
572 AddressIndex *addrIndex, AddressDataSource *ds )
574 gchar *cacheID;
576 cacheID = addrindex_get_cache_id( addrIndex, ds );
577 if( cacheID ) {
578 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
583 * Free hash table callback function.
585 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
586 g_free( key );
587 key = NULL;
588 value = NULL;
589 return TRUE;
593 * Free hash table of address cache items.
595 static void addrindex_free_cache_hash( GHashTable *table ) {
596 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
597 g_hash_table_destroy( table );
601 * Remove data source from internal hashtable.
602 * \param addrIndex Address index.
603 * \param ds Data source to remove.
605 static void addrindex_hash_remove_cache(
606 AddressIndex *addrIndex, AddressDataSource *ds )
608 gchar *cacheID;
610 cacheID = addrindex_get_cache_id( addrIndex, ds );
611 if( cacheID ) {
612 g_hash_table_remove( addrIndex->hashCache, cacheID );
613 g_free( cacheID );
614 cacheID = NULL;
619 * Create a new address index. This is created as a singleton object.
620 * \return Initialized address index object.
622 AddressIndex *addrindex_create_index( void ) {
623 AddressIndex *index;
625 if( _addressIndex_ == NULL ) {
626 index = g_new0( AddressIndex, 1 );
627 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
628 ADDRITEM_ID(index) = NULL;
629 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
630 ADDRITEM_PARENT(index) = NULL;
631 ADDRITEM_SUBTYPE(index) = 0;
632 index->filePath = NULL;
633 index->fileName = NULL;
634 index->retVal = MGU_SUCCESS;
635 index->needsConversion = FALSE;
636 index->wasConverted = FALSE;
637 index->conversionError = FALSE;
638 index->interfaceList = NULL;
639 index->lastType = ADDR_IF_NONE;
640 index->dirtyFlag = FALSE;
641 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
642 index->loadedFlag = FALSE;
643 index->searchOrder = NULL;
644 addrindex_build_if_list( index );
645 _addressIndex_ = index;
647 return _addressIndex_;
651 * Property - Specify file path to address index file.
652 * \param addrIndex Address index.
653 * \param value Path to index file.
655 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
656 g_return_if_fail( addrIndex != NULL );
657 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
661 * Property - Specify file name to address index file.
662 * \param addrIndex Address index.
663 * \param value File name.
665 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
666 g_return_if_fail( addrIndex != NULL );
667 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
671 * Return list of address interfaces.
672 * \param addrIndex Address index.
673 * \return List of address interfaces.
675 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
676 g_return_val_if_fail( addrIndex != NULL, NULL );
677 return addrIndex->interfaceList;
681 * Perform any other initialization of address index.
683 void addrindex_initialize( void ) {
684 qrymgr_initialize();
685 addrcompl_initialize();
689 * Perform any other teardown of address index.
691 void addrindex_teardown( void ) {
692 addrcompl_teardown();
693 qrymgr_teardown();
697 * Free up address index.
698 * \param addrIndex Address index.
700 void addrindex_free_index( AddressIndex *addrIndex ) {
701 GList *node;
703 g_return_if_fail( addrIndex != NULL );
705 /* Search stuff */
706 g_list_free( addrIndex->searchOrder );
707 addrIndex->searchOrder = NULL;
709 /* Free internal storage */
710 g_free( ADDRITEM_ID(addrIndex) );
711 g_free( ADDRITEM_NAME(addrIndex) );
712 g_free( addrIndex->filePath );
713 g_free( addrIndex->fileName );
715 /* Clear pointers */
716 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
717 ADDRITEM_ID(addrIndex) = NULL;
718 ADDRITEM_NAME(addrIndex) = NULL;
719 ADDRITEM_PARENT(addrIndex) = NULL;
720 ADDRITEM_SUBTYPE(addrIndex) = 0;
721 addrIndex->filePath = NULL;
722 addrIndex->fileName = NULL;
723 addrIndex->retVal = MGU_SUCCESS;
724 addrIndex->needsConversion = FALSE;
725 addrIndex->wasConverted = FALSE;
726 addrIndex->conversionError = FALSE;
727 addrIndex->lastType = ADDR_IF_NONE;
728 addrIndex->dirtyFlag = FALSE;
730 /* Free up interfaces */
731 node = addrIndex->interfaceList;
732 while( node ) {
733 AddressInterface *iface = node->data;
734 addrindex_free_interface( iface );
735 node = g_list_next( node );
737 g_list_free( addrIndex->interfaceList );
738 addrIndex->interfaceList = NULL;
740 /* Free up hash cache */
741 addrindex_free_cache_hash( addrIndex->hashCache );
742 addrIndex->hashCache = NULL;
744 addrIndex->loadedFlag = FALSE;
746 g_free( addrIndex );
747 addrIndex = NULL;
748 _addressIndex_ = NULL;
752 * Print address index.
753 * \param addrIndex Address index.
754 * \parem stream Stream to print.
756 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
757 g_return_if_fail( addrIndex != NULL );
758 fprintf( stream, "AddressIndex:\n" );
759 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
760 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
761 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
762 fprintf( stream, "\tconverted: '%s'\n",
763 addrIndex->wasConverted ? "yes" : "no" );
764 fprintf( stream, "\tcvt error: '%s'\n",
765 addrIndex->conversionError ? "yes" : "no" );
766 fprintf( stream, "\t---\n" );
770 * Retrieve reference to address interface for specified interface type.
771 * \param addrIndex Address index.
772 * \param ifType Interface type.
773 * \return Address interface, or NULL if not found.
775 static AddressInterface *addrindex_get_interface(
776 AddressIndex *addrIndex, AddressIfType ifType )
778 AddressInterface *retVal = NULL;
779 GList *node;
781 g_return_val_if_fail( addrIndex != NULL, NULL );
783 node = addrIndex->interfaceList;
784 while( node ) {
785 AddressInterface *iface = node->data;
786 node = g_list_next( node );
787 if( iface->type == ifType ) {
788 retVal = iface;
789 break;
792 return retVal;
796 * Add raw data source to index. The raw data object (an AddressBookFile or
797 * VCardFile object, for example) should be supplied as the raw dataSource
798 * argument.
800 * \param addrIndex Address index.
801 * \param ifType Interface type to add.
802 * \param dataSource Actual raw data source to add.
803 * \return Data source added, or NULL if invalid interface type.
805 AddressDataSource *addrindex_index_add_datasource(
806 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
808 AddressInterface *iface;
809 AddressDataSource *ds = NULL;
811 g_return_val_if_fail( addrIndex != NULL, NULL );
812 g_return_val_if_fail( dataSource != NULL, NULL );
814 iface = addrindex_get_interface( addrIndex, ifType );
815 if( iface ) {
816 ds = addrindex_create_datasource( ifType );
817 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
818 ds->type = ifType;
819 ds->rawDataSource = dataSource;
820 ds->interface = iface;
821 iface->listSource = g_list_append( iface->listSource, ds );
822 addrIndex->dirtyFlag = TRUE;
824 addrindex_hash_add_cache( addrIndex, ds );
826 return ds;
830 * Remove specified data source from index.
831 * \param addrIndex Address index.
832 * \param dataSource Data source to add.
833 * \return Reference to data source if removed, or NULL if data source was not
834 * found in index. Note the this object must still be freed.
836 AddressDataSource *addrindex_index_remove_datasource(
837 AddressIndex *addrIndex, AddressDataSource *dataSource )
839 AddressDataSource *retVal = FALSE;
840 AddressInterface *iface;
842 g_return_val_if_fail( addrIndex != NULL, NULL );
843 g_return_val_if_fail( dataSource != NULL, NULL );
845 iface = addrindex_get_interface( addrIndex, dataSource->type );
846 if( iface ) {
847 iface->listSource = g_list_remove( iface->listSource, dataSource );
848 addrIndex->dirtyFlag = TRUE;
849 dataSource->interface = NULL;
851 /* Remove cache from hash table */
852 addrindex_hash_remove_cache( addrIndex, dataSource );
854 retVal = dataSource;
856 return retVal;
860 * Retrieve a reference to address interface for specified interface type and
861 * XML interface tag name.
862 * \param addrIndex Address index.
863 * \param tag XML interface tag name to match.
864 * \param ifType Interface type to match.
865 * \return Reference to address index, or NULL if not found in index.
867 static AddressInterface *addrindex_tag_get_interface(
868 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
870 AddressInterface *retVal = NULL;
871 GList *node = addrIndex->interfaceList;
873 while( node ) {
874 AddressInterface *iface = node->data;
875 node = g_list_next( node );
876 if( tag ) {
877 if( strcmp( iface->listTag, tag ) == 0 ) {
878 retVal = iface;
879 break;
882 else {
883 if( iface->type == ifType ) {
884 retVal = iface;
885 break;
889 return retVal;
893 * Retrieve a reference to address interface for specified interface type and
894 * XML datasource tag name.
895 * \param addrIndex Address index.
896 * \param ifType Interface type to match.
897 * \param tag XML datasource tag name to match.
898 * \return Reference to address index, or NULL if not found in index.
900 static AddressInterface *addrindex_tag_get_datasource(
901 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
903 AddressInterface *retVal = NULL;
904 GList *node = addrIndex->interfaceList;
906 while( node ) {
907 AddressInterface *iface = node->data;
908 node = g_list_next( node );
909 if( iface->type == ifType && iface->itemTag ) {
910 if( strcmp( iface->itemTag, tag ) == 0 ) {
911 retVal = iface;
912 break;
916 return retVal;
919 /* **********************************************************************
920 * Interface XML parsing functions.
921 * ***********************************************************************
925 * Write start of XML element to file.
926 * \param fp File.
927 * \param lvl Indentation level.
928 * \param name Element name.
930 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
931 gint i;
932 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
933 fputs( "<", fp );
934 fputs( name, fp );
938 * Write end of XML element to file.
939 * \param fp File.
940 * \param lvl Indentation level.
941 * \param name Element name.
943 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
944 gint i;
945 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
946 fputs( "</", fp );
947 fputs( name, fp );
948 fputs( ">\n", fp );
952 * Write XML attribute to file.
953 * \param fp File.
954 * \param name Attribute name.
955 * \param value Attribute value.
957 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
958 fputs( " ", fp );
959 fputs( name, fp );
960 fputs( "=\"", fp );
961 xml_file_put_escape_str( fp, value );
962 fputs( "\"", fp );
966 * Return DOM fragment for current XML tag from file.
967 * \param file XML file being processed.
968 * \return Fragment representing DOM fragment for configuration element.
970 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
971 AddressIfFragment *fragment;
972 AddressIfFragment *child;
973 AddressIfAttrib *nv;
974 XMLTag *xtag;
975 GList *list;
976 GList *attr;
977 gchar *name;
978 gchar *value;
979 guint prevLevel;
980 gint rc;
982 /* g_print( "addrindex_read_fragment\n" ); */
984 prevLevel = file->level;
986 /* Get current tag name */
987 xtag = xml_get_current_tag( file );
989 /* Create new fragment */
990 fragment = g_new0( AddressIfFragment, 1 );
991 fragment->name = g_strdup( xtag->tag );
992 fragment->children = NULL;
993 fragment->attributes = NULL;
995 /* Read attributes */
996 list = NULL;
997 attr = xml_get_current_tag_attr( file );
998 while( attr ) {
999 name = ((XMLAttr *)attr->data)->name;
1000 value = ((XMLAttr *)attr->data)->value;
1001 nv = g_new0( AddressIfAttrib, 1 );
1002 nv->name = g_strdup( name );
1003 nv->value = g_strdup( value );
1004 list = g_list_append( list, nv );
1005 attr = g_list_next( attr );
1007 fragment->attributes = list;
1009 /* Now read the children */
1010 while( TRUE ) {
1011 rc = xml_parse_next_tag( file );
1012 if( rc != 0 ) {
1013 /* End of file? */
1014 break;
1016 if( file->level < prevLevel ) {
1017 /* We must be above level we start at */
1018 break;
1020 child = addrindex_read_fragment( file );
1021 fragment->children = g_list_append( fragment->children, child );
1024 return fragment;
1028 * Write DOM fragment to file.
1029 * \param fp File to write.
1030 * \param fragment DOM fragment for configuration element.
1031 * \param lvl Indent level.
1033 static void addrindex_write_fragment(
1034 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1036 GList *node;
1038 if( fragment ) {
1039 addrindex_write_elem_s( fp, lvl, fragment->name );
1040 node = fragment->attributes;
1041 while( node ) {
1042 AddressIfAttrib *nv = node->data;
1043 addrindex_write_attr( fp, nv->name, nv->value );
1044 node = g_list_next( node );
1046 if( fragment->children ) {
1047 fputs(" >\n", fp);
1049 /* Output children */
1050 node = fragment->children;
1051 while( node ) {
1052 AddressIfFragment *child = node->data;
1053 addrindex_write_fragment( fp, child, 1+lvl );
1054 node = g_list_next( node );
1057 /* Output closing tag */
1058 addrindex_write_elem_e( fp, lvl, fragment->name );
1060 else {
1061 fputs(" />\n", fp);
1067 * Read/parse address index file, creating a data source for a regular
1068 * intrinsic XML addressbook.
1069 * \param file Address index file.
1070 * \return Data source.
1072 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1073 AddressDataSource *ds;
1074 AddressBookFile *abf;
1075 GList *attr;
1077 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1078 abf = addrbook_create_book();
1079 attr = xml_get_current_tag_attr( file );
1080 while( attr ) {
1081 gchar *name = ((XMLAttr *)attr->data)->name;
1082 gchar *value = ((XMLAttr *)attr->data)->value;
1083 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1084 addrbook_set_name( abf, value );
1086 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1087 addrbook_set_file( abf, value );
1089 attr = g_list_next( attr );
1091 ds->rawDataSource = abf;
1092 return ds;
1095 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1096 AddressBookFile *abf = ds->rawDataSource;
1097 if( abf ) {
1098 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1099 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1100 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1101 fputs( " />\n", fp );
1105 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1106 AddressDataSource *ds;
1107 VCardFile *vcf;
1108 GList *attr;
1110 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1111 vcf = vcard_create();
1112 attr = xml_get_current_tag_attr( file );
1113 while( attr ) {
1114 gchar *name = ((XMLAttr *)attr->data)->name;
1115 gchar *value = ((XMLAttr *)attr->data)->value;
1116 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1117 vcard_set_name( vcf, value );
1119 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1120 vcard_set_file( vcf, value );
1122 attr = g_list_next( attr );
1124 ds->rawDataSource = vcf;
1125 return ds;
1128 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1129 VCardFile *vcf = ds->rawDataSource;
1130 if( vcf ) {
1131 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1132 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1133 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1134 fputs( " />\n", fp );
1138 #ifdef USE_JPILOT
1139 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1140 AddressDataSource *ds;
1141 JPilotFile *jpf;
1142 GList *attr;
1144 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1145 jpf = jpilot_create();
1146 attr = xml_get_current_tag_attr( file );
1147 while( attr ) {
1148 gchar *name = ((XMLAttr *)attr->data)->name;
1149 gchar *value = ((XMLAttr *)attr->data)->value;
1150 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1151 jpilot_set_name( jpf, value );
1153 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1154 jpilot_set_file( jpf, value );
1156 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1157 jpilot_add_custom_label( jpf, value );
1159 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1160 jpilot_add_custom_label( jpf, value );
1162 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1163 jpilot_add_custom_label( jpf, value );
1165 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1166 jpilot_add_custom_label( jpf, value );
1168 attr = g_list_next( attr );
1170 ds->rawDataSource = jpf;
1171 return ds;
1174 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1175 JPilotFile *jpf = ds->rawDataSource;
1176 if( jpf ) {
1177 gint ind;
1178 GList *node;
1179 GList *customLbl = jpilot_get_custom_labels( jpf );
1180 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1181 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1182 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1183 node = customLbl;
1184 ind = 1;
1185 while( node ) {
1186 gchar name[256];
1187 g_snprintf( name, sizeof(name), "%s%d",
1188 ATTAG_JPILOT_CUSTOM, ind );
1189 addrindex_write_attr( fp, name, node->data );
1190 ind++;
1191 node = g_list_next( node );
1193 fputs( " />\n", fp );
1197 #else
1199 * Just read/write DOM fragments (preserve data found in file).
1201 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1202 AddressDataSource *ds;
1204 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1205 ds->rawDataSource = addrindex_read_fragment( file );
1206 return ds;
1209 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1210 AddressIfFragment *fragment = ds->rawDataSource;
1211 if( fragment ) {
1212 addrindex_write_fragment( fp, fragment, lvl );
1215 #endif
1217 #ifdef USE_LDAP
1219 * Parse LDAP criteria attribute data from XML file.
1220 * \param file Index file.
1221 * \param ctl LDAP control object to populate.
1223 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1224 guint prevLevel;
1225 XMLTag *xtag;
1226 XMLTag *xtagPrev;
1227 gint rc;
1228 GList *attr;
1229 GList *list;
1230 GList *node;
1232 if( file == NULL ) {
1233 return;
1236 list = NULL;
1237 prevLevel = file->level;
1238 xtagPrev = xml_get_current_tag( file );
1239 while( TRUE ) {
1240 rc = xml_parse_next_tag( file );
1241 if( rc != 0 ) {
1242 /* Terminate prematurely */
1243 mgu_free_dlist( list );
1244 list = NULL;
1245 return;
1247 if( file->level < prevLevel ) {
1248 /* We must be above level we start at */
1249 break;
1252 /* Get a tag (element) */
1253 xtag = xml_get_current_tag( file );
1254 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1255 /* LDAP criteria attribute */
1256 attr = xml_get_current_tag_attr( file );
1257 while( attr ) {
1258 gchar *name = ((XMLAttr *)attr->data)->name;
1259 gchar *value = ((XMLAttr *)attr->data)->value;
1260 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1261 if( value && strlen( value ) > 0 ) {
1262 list = g_list_append(
1263 list, g_strdup( value ) );
1266 attr = g_list_next( attr );
1269 else {
1270 if( xtag != xtagPrev ) {
1271 /* Found a new tag */
1272 break;
1275 xtag = xtagPrev;
1278 /* Build list of search attributes */
1279 ldapctl_criteria_list_clear( ctl );
1280 node = list;
1281 while( node ) {
1282 ldapctl_criteria_list_add( ctl, node->data );
1283 g_free( node->data );
1284 node->data = NULL;
1285 node = g_list_next( node );
1287 g_list_free( list );
1288 list = NULL;
1292 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1294 * Parse LDAP control data from XML file.
1295 * \param file Index file.
1296 * \return Initialized data soruce object.
1298 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1299 AddressDataSource *ds;
1300 LdapServer *server;
1301 LdapControl *ctl;
1302 GList *attr;
1303 gchar *serverName = NULL;
1304 gchar *criteria = NULL;
1305 gboolean bDynSearch;
1306 gboolean bTLS, bSSL;
1307 gint iMatch;
1309 /* g_print( "addrindex_parse_ldap\n" ); */
1310 /* Set up some defaults */
1311 bDynSearch = FALSE;
1312 bTLS = FALSE;
1313 bSSL = FALSE;
1314 iMatch = LDAPCTL_MATCH_BEGINWITH;
1316 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1317 ctl = ldapctl_create();
1318 attr = xml_get_current_tag_attr( file );
1319 while( attr ) {
1320 gchar *name = ((XMLAttr *)attr->data)->name;
1321 gchar *value = ((XMLAttr *)attr->data)->value;
1322 gint ivalue = atoi( value );
1324 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1325 g_free( serverName );
1326 serverName = g_strdup( value );
1328 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1329 ldapctl_set_host( ctl, value );
1331 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1332 ldapctl_set_port( ctl, ivalue );
1334 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1335 ldapctl_set_base_dn( ctl, value );
1337 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1338 ldapctl_set_bind_dn( ctl, value );
1340 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1341 ldapctl_set_bind_password( ctl, value );
1343 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1344 g_free( criteria );
1345 criteria = g_strdup( value );
1346 g_print("criteria %s\n", criteria);
1348 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1349 ldapctl_set_max_entries( ctl, ivalue );
1351 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1352 ldapctl_set_timeout( ctl, ivalue );
1354 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1355 ldapctl_set_max_query_age( ctl, ivalue );
1357 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1358 bDynSearch = FALSE;
1359 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1360 bDynSearch = TRUE;
1363 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1364 iMatch = LDAPCTL_MATCH_BEGINWITH;
1365 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1366 iMatch = LDAPCTL_MATCH_CONTAINS;
1369 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1370 bTLS = FALSE;
1371 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1372 bTLS = TRUE;
1375 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1376 bSSL = FALSE;
1377 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1378 bSSL = TRUE;
1381 attr = g_list_next( attr );
1384 server = ldapsvr_create_noctl();
1385 ldapsvr_set_name( server, serverName );
1386 ldapsvr_set_search_flag( server, bDynSearch );
1387 ldapctl_set_matching_option( ctl, iMatch );
1388 #ifdef USE_LDAP_TLS
1389 ldapctl_set_tls( ctl, bTLS );
1390 ldapctl_set_ssl( ctl, bSSL );
1391 #endif
1392 g_free( serverName );
1393 ldapsvr_set_control( server, ctl );
1394 ds->rawDataSource = server;
1396 addrindex_parse_ldap_attrlist( file, ctl );
1398 * If criteria have been specified and no attributes were listed, then
1399 * convert old style criteria into an attribute list. Any criteria will
1400 * be dropped when saving data.
1402 if( criteria ) {
1403 if( ! ldapctl_get_criteria_list( ctl ) ) {
1404 ldapctl_parse_ldap_search( ctl, criteria );
1406 g_free( criteria );
1408 /* ldapsvr_print_data( server, stdout ); */
1410 return ds;
1413 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1414 LdapServer *server = ds->rawDataSource;
1415 LdapControl *ctl = NULL;
1416 GList *node;
1417 gchar value[256];
1419 if( server ) {
1420 ctl = server->control;
1422 if( ctl == NULL ) return;
1424 /* Output start element with attributes */
1425 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1426 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1427 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1429 sprintf( value, "%d", ctl->port );
1430 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1432 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1433 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1434 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1436 sprintf( value, "%d", ctl->maxEntries );
1437 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1438 sprintf( value, "%d", ctl->timeOut );
1439 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1440 sprintf( value, "%d", ctl->maxQueryAge );
1441 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1443 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1444 server->searchFlag ?
1445 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1447 addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1448 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1449 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN );
1451 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1452 ctl->enableTLS ?
1453 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1454 addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1455 ctl->enableSSL ?
1456 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO );
1458 fputs(" >\n", fp);
1460 /* Output attributes */
1461 node = ldapctl_get_criteria_list( ctl );
1462 while( node ) {
1463 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1464 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1465 fputs(" />\n", fp);
1466 node = g_list_next( node );
1469 /* End of element */
1470 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1473 #else
1475 * Just read/write DOM fragments (preserve data found in file).
1477 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1478 AddressDataSource *ds;
1480 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1481 ds->rawDataSource = addrindex_read_fragment( file );
1482 return ds;
1485 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1486 AddressIfFragment *fragment = ds->rawDataSource;
1487 if( fragment ) {
1488 addrindex_write_fragment( fp, fragment, lvl );
1491 #endif
1493 /* **********************************************************************
1494 * Address index I/O functions.
1495 * ***********************************************************************
1498 * Read address index file, creating appropriate data sources for each address
1499 * index file entry.
1501 * \param addrIndex Address index.
1502 * \param file Address index file.
1504 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1505 guint prev_level;
1506 XMLTag *xtag;
1507 AddressInterface *iface = NULL, *dsIFace = NULL;
1508 AddressDataSource *ds;
1509 gint rc;
1511 addrIndex->loadedFlag = FALSE;
1512 for (;;) {
1513 prev_level = file->level;
1514 rc = xml_parse_next_tag( file );
1515 if( file->level == 0 ) return;
1517 xtag = xml_get_current_tag( file );
1519 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1520 if( iface ) {
1521 addrIndex->lastType = iface->type;
1522 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1524 else {
1525 dsIFace = addrindex_tag_get_datasource(
1526 addrIndex, addrIndex->lastType, xtag->tag );
1527 if( dsIFace ) {
1528 /* Add data source to list */
1529 ds = NULL;
1530 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1531 ds = addrindex_parse_book( file );
1532 if( ds->rawDataSource ) {
1533 addrbook_set_path( ds->rawDataSource,
1534 addrIndex->filePath );
1537 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1538 ds = addrindex_parse_vcard( file );
1540 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1541 ds = addrindex_parse_jpilot( file );
1543 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1544 ds = addrindex_parse_ldap( file );
1546 if( ds ) {
1547 ds->interface = dsIFace;
1548 addrindex_hash_add_cache( addrIndex, ds );
1549 dsIFace->listSource =
1550 g_list_append( dsIFace->listSource, ds );
1558 * Search order sorting comparison function for building search order list.
1560 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1561 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1562 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1564 return ifaceA->searchOrder - ifaceB->searchOrder;
1568 * Build list of data sources to process.
1569 * \param addrIndex Address index object.
1571 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1572 GList *nodeIf;
1574 /* Clear existing list */
1575 g_list_free( addrIndex->searchOrder );
1576 addrIndex->searchOrder = NULL;
1578 /* Build new list */
1579 nodeIf = addrIndex->interfaceList;
1580 while( nodeIf ) {
1581 AddressInterface *iface = nodeIf->data;
1582 if( iface->useInterface ) {
1583 if( iface->searchOrder > 0 ) {
1584 /* Add to search order list */
1585 addrIndex->searchOrder = g_list_insert_sorted(
1586 addrIndex->searchOrder, iface,
1587 addrindex_search_order_compare );
1590 nodeIf = g_list_next( nodeIf );
1594 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1595 XMLFile *file = NULL;
1596 gchar *fileSpec = NULL;
1598 g_return_val_if_fail( addrIndex != NULL, -1 );
1600 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1601 addrIndex->retVal = MGU_NO_FILE;
1602 file = xml_open_file( fileSpec );
1603 g_free( fileSpec );
1605 if( file == NULL ) {
1607 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1609 return addrIndex->retVal;
1612 addrIndex->retVal = MGU_BAD_FORMAT;
1613 if( xml_get_dtd( file ) == 0 ) {
1614 if( xml_parse_next_tag( file ) == 0 ) {
1615 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1616 addrindex_read_index( addrIndex, file );
1617 addrIndex->retVal = MGU_SUCCESS;
1621 xml_close_file( file );
1623 addrindex_build_search_order( addrIndex );
1625 return addrIndex->retVal;
1628 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1629 GList *nodeIF, *nodeDS;
1630 gint lvlList = 1;
1631 gint lvlItem = 1 + lvlList;
1633 nodeIF = addrIndex->interfaceList;
1634 while( nodeIF ) {
1635 AddressInterface *iface = nodeIF->data;
1636 if( ! iface->legacyFlag ) {
1637 nodeDS = iface->listSource;
1638 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1639 fputs( ">\n", fp );
1640 while( nodeDS ) {
1641 AddressDataSource *ds = nodeDS->data;
1642 if( ds ) {
1643 if( iface->type == ADDR_IF_BOOK ) {
1644 addrindex_write_book( fp, ds, lvlItem );
1646 if( iface->type == ADDR_IF_VCARD ) {
1647 addrindex_write_vcard( fp, ds, lvlItem );
1649 if( iface->type == ADDR_IF_JPILOT ) {
1650 addrindex_write_jpilot( fp, ds, lvlItem );
1652 if( iface->type == ADDR_IF_LDAP ) {
1653 addrindex_write_ldap( fp, ds, lvlItem );
1656 nodeDS = g_list_next( nodeDS );
1658 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1660 nodeIF = g_list_next( nodeIF );
1665 * Write data to specified file.
1666 * Enter: addrIndex Address index object.
1667 * newFile New file name.
1668 * return: Status code, from addrIndex->retVal.
1669 * Note: File will be created in directory specified by addrIndex.
1671 static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1672 FILE *fp;
1673 gchar *fileSpec;
1674 #ifndef DEV_STANDALONE
1675 PrefFile *pfile;
1676 #endif
1678 g_return_val_if_fail( addrIndex != NULL, -1 );
1680 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1681 addrIndex->retVal = MGU_OPEN_FILE;
1682 #ifdef DEV_STANDALONE
1683 fp = g_fopen( fileSpec, "wb" );
1684 g_free( fileSpec );
1685 if( fp ) {
1686 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1687 #else
1688 pfile = prefs_write_open( fileSpec );
1689 g_free( fileSpec );
1690 if( pfile ) {
1691 fp = pfile->fp;
1692 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1693 #endif
1694 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1695 fputs( ">\n", fp );
1697 addrindex_write_index( addrIndex, fp );
1698 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1700 addrIndex->retVal = MGU_SUCCESS;
1701 #ifdef DEV_STANDALONE
1702 fclose( fp );
1703 #else
1704 if( prefs_file_close( pfile ) < 0 ) {
1705 addrIndex->retVal = MGU_ERROR_WRITE;
1707 #endif
1710 fileSpec = NULL;
1711 return addrIndex->retVal;
1715 * Save address index data to original file.
1716 * return: Status code, from addrIndex->retVal.
1718 gint addrindex_save_data( AddressIndex *addrIndex ) {
1719 GList *nodeIf, *nodeDS;
1721 g_return_val_if_fail( addrIndex != NULL, -1 );
1722 nodeIf = addrIndex->interfaceList;
1724 #ifdef USE_LDAP
1725 /* save LDAP interfaces */
1726 while ( nodeIf ) {
1727 AddressInterface *iface = nodeIf->data;
1728 if( iface->type == ADDR_IF_LDAP ) {
1729 nodeDS = iface->listSource;
1730 while( nodeDS ) {
1731 AddressDataSource *ds = nodeDS->data;
1732 LdapServer *abf = ds->rawDataSource;
1733 if( ldapsvr_get_read_flag( abf ) ) {
1734 if( ldapsvr_get_modified( abf ) ) {
1735 ldapsvr_update_book( abf, NULL );
1736 if( abf->retVal != LDAPRC_SUCCESS ) {
1737 alertpanel( _("Address(es) update"),
1738 _("Update failed. Changes not written to Directory."),
1739 GTK_STOCK_CLOSE, NULL, NULL );
1741 else {
1742 abf->retVal = MGU_SUCCESS;
1743 ldapsvr_set_modified( abf, FALSE );
1747 nodeDS = g_list_next( nodeDS );
1749 break;
1751 nodeIf = g_list_next( nodeIf );
1753 #endif
1754 addrIndex->retVal = MGU_NO_FILE;
1755 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1756 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1758 addrindex_write_to( addrIndex, addrIndex->fileName );
1759 if( addrIndex->retVal == MGU_SUCCESS ) {
1760 addrIndex->dirtyFlag = FALSE;
1762 return addrIndex->retVal;
1766 * Save all address book files which may have changed.
1767 * Return: Status code, set if there was a problem saving data.
1769 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1770 gint retVal = MGU_SUCCESS;
1771 GList *nodeIf, *nodeDS;
1773 nodeIf = addrIndex->interfaceList;
1774 while( nodeIf ) {
1775 AddressInterface *iface = nodeIf->data;
1776 if( iface->type == ADDR_IF_BOOK ) {
1777 nodeDS = iface->listSource;
1778 while( nodeDS ) {
1779 AddressDataSource *ds = nodeDS->data;
1780 AddressBookFile *abf = ds->rawDataSource;
1781 if( addrbook_get_dirty( abf ) ) {
1782 if( addrbook_get_read_flag( abf ) ) {
1783 addrbook_save_data( abf );
1784 if( abf->retVal != MGU_SUCCESS ) {
1785 retVal = abf->retVal;
1789 nodeDS = g_list_next( nodeDS );
1791 break;
1793 nodeIf = g_list_next( nodeIf );
1795 return retVal;
1799 /* **********************************************************************
1800 * Address book conversion to new format.
1801 * ***********************************************************************
1804 #define ELTAG_IF_OLD_FOLDER "folder"
1805 #define ELTAG_IF_OLD_GROUP "group"
1806 #define ELTAG_IF_OLD_ITEM "item"
1807 #define ELTAG_IF_OLD_NAME "name"
1808 #define ELTAG_IF_OLD_ADDRESS "address"
1809 #define ELTAG_IF_OLD_REMARKS "remarks"
1810 #define ATTAG_IF_OLD_NAME "name"
1812 #define TEMPNODE_ROOT 0
1813 #define TEMPNODE_FOLDER 1
1814 #define TEMPNODE_GROUP 2
1815 #define TEMPNODE_ADDRESS 3
1817 typedef struct _AddressCvt_Node AddressCvtNode;
1818 struct _AddressCvt_Node {
1819 gint type;
1820 gchar *name;
1821 gchar *address;
1822 gchar *remarks;
1823 GList *list;
1827 * Parse current address item.
1829 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1830 gchar *element;
1831 guint level;
1832 AddressCvtNode *nn;
1834 nn = g_new0( AddressCvtNode, 1 );
1835 nn->type = TEMPNODE_ADDRESS;
1836 nn->list = NULL;
1838 level = file->level;
1840 for (;;) {
1841 xml_parse_next_tag(file);
1842 if (file->level < level) return nn;
1844 element = xml_get_element( file );
1845 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1846 nn->name = g_strdup( element );
1848 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1849 nn->address = g_strdup( element );
1851 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1852 nn->remarks = g_strdup( element );
1854 g_free(element);
1855 xml_parse_next_tag(file);
1860 * Create a temporary node below specified node.
1862 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1863 AddressCvtNode *nn;
1864 nn = g_new0( AddressCvtNode, 1 );
1865 nn->type = type;
1866 nn->name = g_strdup( name );
1867 nn->remarks = g_strdup( rem );
1868 node->list = g_list_append( node->list, nn );
1869 return nn;
1873 * Process current temporary node.
1875 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1876 GList *attr;
1877 guint prev_level;
1878 AddressCvtNode *newNode = NULL;
1879 gchar *name;
1880 gchar *value;
1882 for (;;) {
1883 prev_level = file->level;
1884 xml_parse_next_tag( file );
1885 if (file->level < prev_level) return;
1886 name = NULL;
1887 value = NULL;
1889 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1890 attr = xml_get_current_tag_attr(file);
1891 if (attr) {
1892 name = ((XMLAttr *)attr->data)->name;
1893 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1894 value = ((XMLAttr *)attr->data)->value;
1897 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1898 addrindex_add_obj( file, newNode );
1901 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1902 attr = xml_get_current_tag_attr(file);
1903 if (attr) {
1904 name = ((XMLAttr *)attr->data)->name;
1905 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1906 value = ((XMLAttr *)attr->data)->value;
1909 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1910 addrindex_add_obj( file, newNode );
1912 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1913 newNode = addrindex_parse_item( file );
1914 node->list = g_list_append( node->list, newNode );
1916 else {
1917 /* g_print( "invalid: !!! \n" ); */
1918 attr = xml_get_current_tag_attr( file );
1924 * Consume all nodes below current tag.
1926 static void addrindex_consume_tree( XMLFile *file ) {
1927 guint prev_level;
1928 gchar *element;
1929 GList *attr;
1930 XMLTag *xtag;
1932 for (;;) {
1933 prev_level = file->level;
1934 xml_parse_next_tag( file );
1935 if (file->level < prev_level) return;
1937 xtag = xml_get_current_tag( file );
1938 /* g_print( "tag : %s\n", xtag->tag ); */
1939 element = xml_get_element( file );
1940 attr = xml_get_current_tag_attr( file );
1941 /* show_attribs( attr ); */
1942 /* g_print( "\ttag value : %s :\n", element ); */
1943 addrindex_consume_tree( file );
1948 * Print temporary tree.
1950 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1951 GList *list;
1953 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1954 fprintf( stream, "\tname :%s:\n", node->name );
1955 fprintf( stream, "\taddr :%s:\n", node->address );
1956 fprintf( stream, "\trems :%s:\n", node->remarks );
1957 if( node->list ) {
1958 fprintf( stream, "\t--list----\n" );
1960 list = node->list;
1961 while( list ) {
1962 AddressCvtNode *lNode = list->data;
1963 list = g_list_next( list );
1964 addrindex_print_node( lNode, stream );
1966 fprintf( stream, "\t==list-%d==\n", node->type );
1970 * Free up temporary tree.
1972 static void addrindex_free_node( AddressCvtNode *node ) {
1973 GList *list = node->list;
1975 while( list ) {
1976 AddressCvtNode *lNode = list->data;
1977 list = g_list_next( list );
1978 addrindex_free_node( lNode );
1980 node->type = TEMPNODE_ROOT;
1981 g_free( node->name );
1982 g_free( node->address );
1983 g_free( node->remarks );
1984 g_list_free( node->list );
1985 g_free( node );
1989 * Process address book for specified node.
1991 static void addrindex_process_node(
1992 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1993 ItemGroup *parentGrp, ItemFolder *folderGrp )
1995 GList *list;
1996 ItemFolder *itemFolder = NULL;
1997 ItemGroup *itemGParent = parentGrp;
1998 ItemFolder *itemGFolder = folderGrp;
1999 AddressCache *cache = abf->addressCache;
2001 if( node->type == TEMPNODE_ROOT ) {
2002 itemFolder = parent;
2004 else if( node->type == TEMPNODE_FOLDER ) {
2005 itemFolder = addritem_create_item_folder();
2006 addritem_folder_set_name( itemFolder, node->name );
2007 addrcache_id_folder( cache, itemFolder );
2008 addrcache_folder_add_folder( cache, parent, itemFolder );
2009 itemGFolder = NULL;
2011 else if( node->type == TEMPNODE_GROUP ) {
2012 ItemGroup *itemGroup;
2013 gchar *fName;
2015 /* Create a folder for group */
2016 fName = g_strdup_printf( "Cvt - %s", node->name );
2017 itemGFolder = addritem_create_item_folder();
2018 addritem_folder_set_name( itemGFolder, fName );
2019 addrcache_id_folder( cache, itemGFolder );
2020 addrcache_folder_add_folder( cache, parent, itemGFolder );
2021 g_free( fName );
2023 /* Add group into folder */
2024 itemGroup = addritem_create_item_group();
2025 addritem_group_set_name( itemGroup, node->name );
2026 addrcache_id_group( cache, itemGroup );
2027 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2028 itemGParent = itemGroup;
2030 else if( node->type == TEMPNODE_ADDRESS ) {
2031 ItemPerson *itemPerson;
2032 ItemEMail *itemEMail;
2034 /* Create person and email objects */
2035 itemPerson = addritem_create_item_person();
2036 addritem_person_set_common_name( itemPerson, node->name );
2037 addrcache_id_person( cache, itemPerson );
2038 itemEMail = addritem_create_item_email();
2039 addritem_email_set_address( itemEMail, node->address );
2040 addritem_email_set_remarks( itemEMail, node->remarks );
2041 addrcache_id_email( cache, itemEMail );
2042 addrcache_person_add_email( cache, itemPerson, itemEMail );
2044 /* Add person into appropriate folder */
2045 if( itemGFolder ) {
2046 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2048 else {
2049 addrcache_folder_add_person( cache, parent, itemPerson );
2052 /* Add email address only into group */
2053 if( parentGrp ) {
2054 addrcache_group_add_email( cache, parentGrp, itemEMail );
2058 list = node->list;
2059 while( list ) {
2060 AddressCvtNode *lNode = list->data;
2061 list = g_list_next( list );
2062 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2067 * Process address book to specified file number.
2069 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2070 gboolean retVal = FALSE;
2071 AddressBookFile *abf = NULL;
2072 AddressCvtNode *rootNode = NULL;
2073 gchar *newFile = NULL;
2074 GList *fileList = NULL;
2075 gint fileNum = 0;
2077 /* Setup root node */
2078 rootNode = g_new0( AddressCvtNode, 1 );
2079 rootNode->type = TEMPNODE_ROOT;
2080 rootNode->name = g_strdup( "root" );
2081 rootNode->list = NULL;
2082 addrindex_add_obj( file, rootNode );
2083 /* addrindex_print_node( rootNode, stdout ); */
2085 /* Create new address book */
2086 abf = addrbook_create_book();
2087 addrbook_set_name( abf, displayName );
2088 addrbook_set_path( abf, addrIndex->filePath );
2090 /* Determine next available file number */
2091 fileList = addrbook_get_bookfile_list( abf );
2092 if( fileList ) {
2093 fileNum = 1 + abf->maxValue;
2095 g_list_free( fileList );
2096 fileList = NULL;
2098 newFile = addrbook_gen_new_file_name( fileNum );
2099 if( newFile ) {
2100 addrbook_set_file( abf, newFile );
2103 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2105 /* addrbook_dump_book( abf, stdout ); */
2106 addrbook_save_data( abf );
2107 addrIndex->retVal = abf->retVal;
2108 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2110 addrbook_free_book( abf );
2111 abf = NULL;
2112 addrindex_free_node( rootNode );
2113 rootNode = NULL;
2115 /* Create entries in address index */
2116 if( retVal ) {
2117 abf = addrbook_create_book();
2118 addrbook_set_name( abf, displayName );
2119 addrbook_set_path( abf, addrIndex->filePath );
2120 addrbook_set_file( abf, newFile );
2121 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2124 return retVal;
2128 * Process tree converting data.
2130 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2131 guint prev_level;
2132 gchar *element;
2133 GList *attr;
2134 XMLTag *xtag;
2136 /* Process file */
2137 for (;;) {
2138 prev_level = file->level;
2139 xml_parse_next_tag( file );
2140 if (file->level < prev_level) return;
2142 xtag = xml_get_current_tag( file );
2143 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2144 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2145 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2146 addrIndex->needsConversion = FALSE;
2147 addrIndex->wasConverted = TRUE;
2148 continue;
2150 return;
2152 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2153 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2154 addrIndex->needsConversion = FALSE;
2155 addrIndex->wasConverted = TRUE;
2156 continue;
2158 return;
2160 element = xml_get_element( file );
2161 attr = xml_get_current_tag_attr( file );
2162 /* show_attribs( attr ); */
2163 /* g_print( "\ttag value : %s :\n", element ); */
2164 addrindex_consume_tree( file );
2168 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2169 XMLFile *file = NULL;
2170 gchar *fileSpec;
2172 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2173 addrIndex->retVal = MGU_NO_FILE;
2174 file = xml_open_file( fileSpec );
2175 g_free( fileSpec );
2177 if( file == NULL ) {
2178 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2179 return addrIndex->retVal;
2182 addrIndex->retVal = MGU_BAD_FORMAT;
2183 if( xml_get_dtd( file ) == 0 ) {
2184 if( xml_parse_next_tag( file ) == 0 ) {
2185 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2186 addrindex_convert_tree( addrIndex, file );
2190 xml_close_file( file );
2191 return addrIndex->retVal;
2195 * Create a new address book file.
2197 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2198 gboolean retVal = FALSE;
2199 AddressBookFile *abf = NULL;
2200 gchar *newFile = NULL;
2201 GList *fileList = NULL;
2202 gint fileNum = 0;
2204 /* Create new address book */
2205 abf = addrbook_create_book();
2206 addrbook_set_name( abf, displayName );
2207 addrbook_set_path( abf, addrIndex->filePath );
2209 /* Determine next available file number */
2210 fileList = addrbook_get_bookfile_list( abf );
2211 if( fileList ) {
2212 fileNum = 1 + abf->maxValue;
2214 g_list_free( fileList );
2215 fileList = NULL;
2217 newFile = addrbook_gen_new_file_name( fileNum );
2218 if( newFile ) {
2219 addrbook_set_file( abf, newFile );
2222 addrbook_save_data( abf );
2223 addrIndex->retVal = abf->retVal;
2224 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2225 addrbook_free_book( abf );
2226 abf = NULL;
2228 /* Create entries in address index */
2229 if( retVal ) {
2230 abf = addrbook_create_book();
2231 addrbook_set_name( abf, displayName );
2232 addrbook_set_path( abf, addrIndex->filePath );
2233 addrbook_set_file( abf, newFile );
2234 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2237 return retVal;
2241 * Read data for address index performing a conversion if necesary.
2242 * Enter: addrIndex Address index object.
2243 * return: Status code, from addrIndex->retVal.
2244 * Note: New address book files will be created in directory specified by
2245 * addrIndex. Three files will be created, for the following:
2246 * "Common addresses"
2247 * "Personal addresses"
2248 * "Gathered addresses" - a new address book.
2250 gint addrindex_read_data( AddressIndex *addrIndex ) {
2251 g_return_val_if_fail( addrIndex != NULL, -1 );
2253 addrIndex->conversionError = FALSE;
2254 addrindex_read_file( addrIndex );
2255 if( addrIndex->retVal == MGU_SUCCESS ) {
2256 if( addrIndex->needsConversion ) {
2257 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2258 addrIndex->conversionError = TRUE;
2260 else {
2261 addrIndex->conversionError = TRUE;
2264 addrIndex->dirtyFlag = TRUE;
2266 return addrIndex->retVal;
2270 * Create new address books for a new address index.
2271 * Enter: addrIndex Address index object.
2272 * return: Status code, from addrIndex->retVal.
2273 * Note: New address book files will be created in directory specified by
2274 * addrIndex. Three files will be created, for the following:
2275 * "Common addresses"
2276 * "Personal addresses"
2277 * "Gathered addresses" - a new address book.
2279 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2280 gboolean flg;
2282 g_return_val_if_fail( addrIndex != NULL, -1 );
2284 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2285 if( flg ) {
2286 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2287 addrIndex->dirtyFlag = TRUE;
2289 return addrIndex->retVal;
2292 /* **********************************************************************
2293 * New interface stuff.
2294 * ***********************************************************************
2298 * Return modified flag for specified data source.
2300 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2301 gboolean retVal = FALSE;
2302 AddressInterface *iface;
2304 if( ds == NULL ) return retVal;
2305 iface = ds->interface;
2306 if( iface == NULL ) return retVal;
2307 if( iface->getModifyFlag ) {
2308 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2310 return retVal;
2314 * Return accessed flag for specified data source.
2316 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2317 gboolean retVal = FALSE;
2318 AddressInterface *iface;
2320 if( ds == NULL ) return retVal;
2321 iface = ds->interface;
2322 if( iface == NULL ) return retVal;
2323 if( iface->getAccessFlag ) {
2324 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2326 return retVal;
2330 * Return data read flag for specified data source.
2332 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2333 gboolean retVal = TRUE;
2334 AddressInterface *iface;
2336 if( ds == NULL ) return retVal;
2337 iface = ds->interface;
2338 if( iface == NULL ) return retVal;
2339 if( iface->getReadFlag ) {
2340 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2342 return retVal;
2346 * Return status code for specified data source.
2348 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2349 gint retVal = MGU_SUCCESS;
2350 AddressInterface *iface;
2352 if( ds == NULL ) return retVal;
2353 iface = ds->interface;
2354 if( iface == NULL ) return retVal;
2355 if( iface->getStatusCode ) {
2356 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2358 return retVal;
2362 * Return data read flag for specified data source.
2364 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2365 gint retVal = MGU_SUCCESS;
2366 AddressInterface *iface;
2368 if( ds == NULL ) return retVal;
2369 iface = ds->interface;
2370 if( iface == NULL ) return retVal;
2371 if( iface->getReadData ) {
2373 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2374 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2376 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2378 return retVal;
2382 * Return data read flag for specified data source.
2384 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2385 ItemFolder *retVal = NULL;
2386 AddressInterface *iface;
2388 if( ds == NULL ) return retVal;
2389 iface = ds->interface;
2390 if( iface == NULL ) return retVal;
2391 if( iface->getRootFolder ) {
2392 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2394 return retVal;
2398 * Return name for specified data source.
2400 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2401 gchar *retVal = FALSE;
2402 AddressInterface *iface;
2404 if( ds == NULL ) return retVal;
2405 iface = ds->interface;
2406 if( iface == NULL ) return retVal;
2407 if( iface->getName ) {
2408 retVal = ( iface->getName ) ( ds->rawDataSource );
2410 return retVal;
2414 * Set the access flag inside the data source.
2416 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2417 AddressInterface *iface;
2419 if( ds == NULL ) return;
2420 iface = ds->interface;
2421 if( iface == NULL ) return;
2422 if( iface->setAccessFlag ) {
2423 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2428 * Return read only flag for specified data source.
2430 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2431 AddressInterface *iface;
2432 if( ds == NULL ) return TRUE;
2433 iface = ds->interface;
2434 if( iface == NULL ) return TRUE;
2435 return iface->readOnly;
2439 * Return list of all persons for specified data source.
2441 static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2442 GList *retVal = NULL;
2443 AddressInterface *iface;
2445 if( ds == NULL ) return retVal;
2446 iface = ds->interface;
2447 if( iface == NULL ) return retVal;
2448 if( iface->getAllPersons ) {
2449 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2451 return retVal;
2455 * Return list of all groups for specified data source.
2457 static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2458 GList *retVal = NULL;
2459 AddressInterface *iface;
2461 if( ds == NULL ) return retVal;
2462 iface = ds->interface;
2463 if( iface == NULL ) return retVal;
2464 if( iface->getAllGroups ) {
2465 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2467 return retVal;
2470 /* **********************************************************************
2471 * Address search stuff.
2472 * ***********************************************************************
2476 * Setup or register the dynamic search that will be performed. The search
2477 * is registered with the query manager.
2479 * \param searchTerm Search term. A private copy will be made.
2480 * \param callBackEntry Callback function that should be called when
2481 * each entry is received.
2482 * \param callBackEnd Callback function that should be called when
2483 * search has finished running.
2484 * \return ID allocated to query that will be executed.
2486 gint addrindex_setup_search(
2487 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2489 QueryRequest *req;
2490 gint queryID;
2492 /* Set up a dynamic address query */
2493 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2494 queryID = req->queryID;
2495 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2497 /* g_print( "***> query ID ::%d::\n", queryID ); */
2498 return queryID;
2501 #ifdef USE_LDAP
2504 * Function prototypes (not in header file or circular reference errors are
2505 * encountered!)
2507 LdapQuery *ldapsvr_new_dynamic_search(
2508 LdapServer *server, QueryRequest *req );
2509 LdapQuery *ldapsvr_new_explicit_search(
2510 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2511 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2513 #endif
2516 * Execute the previously registered dynamic search.
2518 * \param req Address query object to execute.
2519 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2520 * failed.
2522 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2523 AddressInterface *iface;
2524 AddressDataSource *ds;
2525 GList *nodeIf;
2526 GList *nodeDS;
2527 gint type;
2529 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2530 nodeIf = _addressIndex_->searchOrder;
2531 while( nodeIf ) {
2532 iface = nodeIf->data;
2533 nodeIf = g_list_next( nodeIf );
2535 if( ! iface->useInterface ) {
2536 continue;
2538 if( ! iface->externalQuery ) {
2539 continue;
2542 type = iface->type;
2543 nodeDS = iface->listSource;
2544 while( nodeDS ) {
2545 ds = nodeDS->data;
2546 nodeDS = g_list_next( nodeDS );
2547 #ifdef USE_LDAP
2548 if( type == ADDR_IF_LDAP ) {
2549 LdapServer *server;
2550 LdapQuery *qry;
2552 server = ds->rawDataSource;
2553 if( ! server->searchFlag ) {
2554 continue;
2556 if( ldapsvr_reuse_previous( server, req ) ) {
2557 continue;
2560 /* Start a new dynamic search */
2561 qry = ldapsvr_new_dynamic_search( server, req );
2562 if( qry ) {
2563 ldapsvr_execute_query( server, qry );
2566 #endif
2569 return TRUE;
2573 * Stop the previously registered search.
2575 * \param queryID ID of search query to stop.
2577 void addrindex_stop_search( const gint queryID ){
2578 QueryRequest *req;
2579 AddrQueryObject *aqo;
2580 GList *node;
2582 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2583 /* If query ID does not match, search has not been setup */
2584 req = qrymgr_find_request( queryID );
2585 if( req == NULL ) {
2586 return;
2589 /* Stop all queries that were associated with request */
2590 node = req->queryList;
2591 while( node ) {
2592 aqo = node->data;
2593 #ifdef USE_LDAP
2594 if( aqo->queryType == ADDRQUERY_LDAP ) {
2595 LdapQuery *qry = ( LdapQuery * ) aqo;
2596 ldapqry_set_stop_flag( qry, TRUE );
2598 #endif
2599 node->data = NULL;
2600 node = g_list_next( node );
2603 /* Delete query request */
2604 qrymgr_delete_request( queryID );
2608 * Setup or register the explicit search that will be performed. The search is
2609 * registered with the query manager.
2611 * \param ds Data source to search.
2612 * \param searchTerm Search term to locate.
2613 * \param folder Folder to receive search results; may be NULL.
2614 * \param callbackEnd Function to call when search has terminated.
2615 * \param callbackEntry Function to called for each entry processed.
2616 * \return ID allocated to query that will be executed.
2618 gint addrindex_setup_explicit_search(
2619 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2620 void *callBackEnd, void *callBackEntry )
2622 QueryRequest *req;
2623 gint queryID;
2624 gchar *name;
2625 gchar *mySearch;
2627 /* Name the query */
2628 name = g_strdup_printf( "Search '%s'", searchTerm );
2630 /* Set up query request */
2631 if (!strcmp(searchTerm, "*"))
2632 mySearch = g_strdup("*@");
2633 else
2634 mySearch = g_strdup(searchTerm);
2636 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2638 g_free(mySearch);
2640 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2641 queryID = req->queryID;
2643 if( ds->type == ADDR_IF_LDAP ) {
2644 #ifdef USE_LDAP
2645 LdapServer *server;
2647 server = ds->rawDataSource;
2648 ldapsvr_new_explicit_search( server, req, folder );
2649 #endif
2651 else {
2652 qrymgr_delete_request( queryID );
2653 queryID = 0;
2655 g_free( name );
2657 return queryID;
2661 * Execute the previously registered explicit search.
2663 * \param req Address query request object to execute.
2664 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2665 * failed.
2667 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2668 gboolean retVal;
2669 AddrQueryObject *aqo;
2671 retVal = FALSE;
2673 /* Note: there should only be one query in the list. */
2674 aqo = req->queryList->data;
2675 #ifdef USE_LDAP
2676 if( aqo->queryType == ADDRQUERY_LDAP ) {
2677 LdapServer *server;
2678 LdapQuery *qry;
2680 qry = ( LdapQuery * ) aqo;
2681 server = qry->server;
2683 /* Start the search */
2684 retVal = TRUE;
2685 ldapsvr_execute_query( server, qry );
2687 #endif
2688 return retVal;
2692 * Start the previously registered search.
2694 * \param queryID ID of search query to be executed.
2695 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2696 * failed.
2698 gboolean addrindex_start_search( const gint queryID ) {
2699 gboolean retVal;
2700 QueryRequest *req;
2701 AddrSearchType searchType;
2703 retVal = FALSE;
2704 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2705 req = qrymgr_find_request( queryID );
2706 if( req == NULL ) {
2707 return retVal;
2710 searchType = req->searchType;
2711 if( searchType == ADDRSEARCH_DYNAMIC ) {
2712 retVal = addrindex_start_dynamic( req );
2714 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2715 retVal = addrindex_start_explicit( req );
2718 return retVal;
2722 * Remove results (folder and data) for specified data source and folder.
2723 * \param ds Data source to process.
2724 * \param folder Results folder to remove.
2726 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2727 AddrBookBase *adbase;
2728 AddressCache *cache;
2729 gint queryID = 0;
2731 /* g_print( "addrindex_remove_results/start\n" ); */
2733 /* Test for folder */
2734 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2735 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2736 adbase = ( AddrBookBase * ) ds->rawDataSource;
2737 if( adbase == NULL ) return;
2738 cache = adbase->addressCache;
2740 /* Hide folder to prevent re-display */
2741 addritem_folder_set_hidden( folder, TRUE );
2743 if( ds->type == ADDR_IF_LDAP ) {
2744 #ifdef USE_LDAP
2745 LdapQuery *qry;
2746 gboolean delFlag;
2748 qry = ( LdapQuery * ) folder->folderData;
2749 queryID = ADDRQUERY_ID(qry);
2750 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2751 delFlag = ldapquery_remove_results( qry );
2752 if (delFlag) {
2753 ldapqry_free( qry );
2755 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2757 if( delFlag ) {
2758 g_print( "delFlag IS-TRUE\n" );
2760 else {
2761 g_print( "delFlag IS-FALSE\n" );
2764 #endif
2766 /* g_print( "addrindex_remove_results/end\n" ); */
2768 /* Delete query request */
2769 if( queryID > 0 ) {
2770 qrymgr_delete_request( queryID );
2774 /* **********************************************************************
2775 * Address completion stuff.
2776 * ***********************************************************************
2779 static void addrindex_load_completion_load_persons(
2780 gint (*callBackFunc) ( const gchar *, const gchar *,
2781 const gchar *, const gchar *, GList * ),
2782 AddressDataSource *ds)
2784 GList *listP, *nodeP;
2785 GList *nodeM;
2786 gchar *sName;
2788 /* Read address book */
2789 if( addrindex_ds_get_modify_flag( ds ) ) {
2790 addrindex_ds_read_data( ds );
2793 if( ! addrindex_ds_get_read_flag( ds ) ) {
2794 addrindex_ds_read_data( ds );
2797 /* Get all groups */
2798 listP = addrindex_ds_get_all_groups( ds );
2799 nodeP = listP;
2800 while( nodeP ) {
2801 ItemGroup *group = nodeP->data;
2802 GList *emails = NULL;
2803 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2804 ItemEMail *email = nodeM->data;
2805 if (email->address)
2806 emails = g_list_append(emails, email);
2808 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2809 NULL, NULL, emails );
2810 nodeP = g_list_next( nodeP );
2813 /* Free up the list */
2814 g_list_free( listP );
2815 /* Get all persons */
2816 listP = addrindex_ds_get_all_persons( ds );
2817 nodeP = listP;
2818 while( nodeP ) {
2819 ItemPerson *person = nodeP->data;
2820 nodeM = person->listEMail;
2822 /* Figure out name to use */
2823 sName = ADDRITEM_NAME(person);
2824 if( sName == NULL || *sName == '\0' ) {
2825 sName = person->nickName;
2828 /* Process each E-Mail address */
2829 while( nodeM ) {
2830 ItemEMail *email = nodeM->data;
2832 callBackFunc( sName, email->address, person->nickName,
2833 ADDRITEM_NAME(email), NULL );
2835 nodeM = g_list_next( nodeM );
2837 nodeP = g_list_next( nodeP );
2840 /* Free up the list */
2841 g_list_free( listP );
2845 * This function is used by the address completion function to load
2846 * addresses for all non-external address book interfaces.
2848 * \param callBackFunc Function to be called when an address is
2849 * to be loaded.
2850 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2851 * or "Any", assume the whole addressbook
2852 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2855 gboolean addrindex_load_completion(
2856 gint (*callBackFunc) ( const gchar *, const gchar *,
2857 const gchar *, const gchar *, GList * ),
2858 gchar *folderpath )
2860 GList *nodeIf, *nodeDS;
2862 if( folderpath != NULL ) {
2863 AddressDataSource *book;
2864 ItemFolder* folder;
2866 /* split the folder path we've received, we'll try to match this path, subpath by
2867 subpath against the book/folder structure in order and restrict loading of
2868 addresses to that subpart (if matches). book/folder path must exist and
2869 folderpath must not be empty or NULL */
2871 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2872 g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath);
2873 return FALSE;
2876 if( folder != NULL ) {
2878 GList *items;
2879 GList *nodeM;
2880 gchar *sName;
2881 ItemPerson *person;
2883 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2885 /* Load email addresses */
2886 items = addritem_folder_get_person_list( folder );
2887 for( ; items != NULL; items = g_list_next( items ) ) {
2888 person = items->data;
2889 nodeM = person->listEMail;
2891 /* Figure out name to use */
2892 sName = ADDRITEM_NAME(person);
2893 if( sName == NULL || *sName == '\0' ) {
2894 sName = person->nickName;
2897 /* Process each E-Mail address */
2898 while( nodeM ) {
2899 ItemEMail *email = nodeM->data;
2901 callBackFunc( sName, email->address, person->nickName,
2902 ADDRITEM_NAME(email), NULL );
2904 nodeM = g_list_next( nodeM );
2907 /* Free up the list */
2908 mgu_clear_list( items );
2909 g_list_free( items );
2911 return TRUE;
2913 } else {
2915 if( book != NULL ) {
2917 AddressBookFile *abf = book->rawDataSource;
2919 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf?abf->fileName:"(null)");
2921 addrindex_load_completion_load_persons( callBackFunc, book );
2923 return TRUE;
2925 } else {
2926 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
2929 return FALSE;
2931 } else {
2933 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2934 while( nodeIf ) {
2935 AddressInterface *iface = nodeIf->data;
2937 nodeIf = g_list_next( nodeIf );
2939 if( ! iface->useInterface || iface->externalQuery )
2940 continue;
2942 nodeDS = iface->listSource;
2943 while( nodeDS ) {
2944 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
2945 nodeDS = g_list_next( nodeDS );
2950 return TRUE;
2954 * This function can be used to collect information about
2955 * addressbook entries that contain a specific attribute.
2957 * \param attr Name of attribute to look for
2958 * \param callBackFunc Function to be called when a matching attribute was found
2959 * \return <i>TRUE</i>
2961 gboolean addrindex_load_person_attribute(
2962 const gchar *attr,
2963 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
2965 AddressDataSource *ds;
2966 GList *nodeIf, *nodeDS;
2967 GList *listP, *nodeP;
2968 GList *nodeA;
2970 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2971 while( nodeIf ) {
2972 gchar *cur_bname;
2973 AddressInterface *iface = nodeIf->data;
2975 nodeIf = g_list_next( nodeIf );
2977 if( ! iface->useInterface || iface->externalQuery )
2978 continue;
2980 nodeDS = iface->listSource;
2981 while( nodeDS ) {
2982 ds = nodeDS->data;
2984 /* Read address book */
2985 if( addrindex_ds_get_modify_flag( ds ) ) {
2986 addrindex_ds_read_data( ds );
2989 if( ! addrindex_ds_get_read_flag( ds ) ) {
2990 addrindex_ds_read_data( ds );
2993 /* Check addressbook name */
2994 cur_bname = addrindex_ds_get_name( ds );
2996 /* Get all persons */
2997 listP = addrindex_ds_get_all_persons( ds );
2998 nodeP = listP;
2999 while( nodeP ) {
3000 ItemPerson *person = nodeP->data;
3002 /* Return all ItemPerson's if attr is NULL */
3003 if( attr == NULL ) {
3004 callBackFunc(person, cur_bname);
3007 /* Return ItemPerson's with specific attribute */
3008 else {
3009 nodeA = person->listAttrib;
3010 /* Process each User Attribute */
3011 while( nodeA ) {
3012 UserAttribute *attrib = nodeA->data;
3013 if( attrib->name &&
3014 !strcmp( attrib->name,attr ) ) {
3015 callBackFunc(person, cur_bname);
3017 nodeA = g_list_next( nodeA );
3020 nodeP = g_list_next( nodeP );
3022 /* Free up the list */
3023 g_list_free( listP );
3025 nodeDS = g_list_next( nodeDS );
3028 return TRUE;
3032 * End of Source.