add Charles to the man page
[claws.git] / src / addrindex.c
blob307527faa04d4e9a705c68af389c3d0d6037dccc
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2012 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 #include "claws-features.h"
27 #endif
29 #include "defs.h"
31 #include <glib.h>
32 #include <glib/gi18n.h>
34 #include "mgutils.h"
35 #include "addritem.h"
36 #include "addrcache.h"
37 #include "addrbook.h"
38 #include "addressbook.h"
39 #include "addrindex.h"
40 #include "xml.h"
41 #include "addrquery.h"
42 #include "addr_compl.h"
43 #include "utils.h"
44 #include "alertpanel.h"
46 #ifndef DEV_STANDALONE
47 #include "prefs_gtk.h"
48 #include "codeconv.h"
49 #endif
51 #include "vcard.h"
53 #ifdef USE_JPILOT
54 #include "jpilot.h"
55 #endif
57 #ifdef USE_LDAP
58 #include "ldapserver.h"
59 #include "ldapctrl.h"
60 #include "ldapquery.h"
61 #include "ldapupdate.h"
62 #include "ldaputil.h"
63 #endif
65 #ifdef G_OS_WIN32
66 #undef interface
67 #endif
69 #define TAG_ADDRESS_INDEX "addressbook"
71 #define TAG_IF_ADDRESS_BOOK "book_list"
72 #define TAG_IF_VCARD "vcard_list"
73 #define TAG_IF_JPILOT "jpilot_list"
74 #define TAG_IF_LDAP "ldap_list"
76 #define TAG_DS_ADDRESS_BOOK "book"
77 #define TAG_DS_VCARD "vcard"
78 #define TAG_DS_JPILOT "jpilot"
79 #define TAG_DS_LDAP "server"
81 /* XML Attribute names */
82 #define ATTAG_BOOK_NAME "name"
83 #define ATTAG_BOOK_FILE "file"
85 #define ATTAG_VCARD_NAME "name"
86 #define ATTAG_VCARD_FILE "file"
88 #define ATTAG_JPILOT_NAME "name"
89 #define ATTAG_JPILOT_FILE "file"
90 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
91 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
92 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
93 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
94 #define ATTAG_JPILOT_CUSTOM "custom-"
96 #define ATTAG_LDAP_NAME "name"
97 #define ATTAG_LDAP_HOST "host"
98 #define ATTAG_LDAP_PORT "port"
99 #define ATTAG_LDAP_BASE_DN "base-dn"
100 #define ATTAG_LDAP_BIND_DN "bind-dn"
101 #define ATTAG_LDAP_BIND_PASS "bind-pass"
102 #define ATTAG_LDAP_CRITERIA "criteria"
103 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
104 #define ATTAG_LDAP_TIMEOUT "timeout"
105 #define ATTAG_LDAP_MAX_AGE "max-age"
106 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
107 #define ATTAG_LDAP_MATCH_OPT "match-opt"
108 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
109 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
111 #define ELTAG_LDAP_ATTR_SRCH "attribute"
112 #define ATTAG_LDAP_ATTR_NAME "name"
114 /* Attribute values */
115 #define ATVAL_BOOLEAN_YES "yes"
116 #define ATVAL_BOOLEAN_NO "no"
117 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
118 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
120 /* New attributes */
121 #define ATTAG_LDAP_DEFAULT "default"
123 #define DISP_NEW_COMMON _("Common addresses")
124 #define DISP_NEW_PERSONAL _("Personal addresses")
126 /* Old address book */
127 #define TAG_IF_OLD_COMMON "common_address"
128 #define TAG_IF_OLD_PERSONAL "personal_address"
130 #define DISP_OLD_COMMON _("Common address")
131 #define DISP_OLD_PERSONAL _("Personal address")
134 * Singleton object.
136 static AddressIndex *_addressIndex_ = NULL;
139 * Define attribute name-value pair.
141 typedef struct _AddressIfAttr AddressIfAttrib;
142 struct _AddressIfAttr {
143 gchar *name;
144 gchar *value;
147 static AddressDataSource *addrindex_create_datasource ( AddressIfType ifType );
149 static GList *addrindex_ds_get_all_persons ( AddressDataSource *ds );
150 static GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
151 static AddressDataSource *addrindex_get_datasource ( AddressIndex *addrIndex,
152 const gchar *cacheID );
153 static AddressInterface *addrindex_get_interface ( AddressIndex *addrIndex,
154 AddressIfType ifType );
155 static gint addrindex_write_to ( AddressIndex *addrIndex,
156 const gchar *newFile );
159 * Define DOM fragment.
161 typedef struct _AddressIfFrag AddressIfFragment;
162 struct _AddressIfFrag {
163 gchar *name;
164 GList *children;
165 GList *attributes;
169 * Build interface with default values.
171 * \param type Interface type.
172 * \param name Interface name.
173 * \param tagIf XML tag name for interface in address index file.
174 * \param tagDS XML tag name for datasource in address index file.
175 * \return Address interface object.
177 static AddressInterface *addrindex_create_interface(
178 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
180 AddressInterface *iface = g_new0( AddressInterface, 1 );
182 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
183 ADDRITEM_ID(iface) = NULL;
184 ADDRITEM_NAME(iface) = g_strdup( name );
185 ADDRITEM_PARENT(iface) = NULL;
186 ADDRITEM_SUBTYPE(iface) = type;
187 iface->type = type;
188 iface->name = g_strdup( name );
189 iface->listTag = g_strdup( tagIf );
190 iface->itemTag = g_strdup( tagDS );
191 iface->legacyFlag = FALSE;
192 iface->haveLibrary = TRUE;
193 iface->useInterface = TRUE;
194 iface->readOnly = TRUE;
196 /* Set callbacks to NULL values - override for each interface */
197 iface->getAccessFlag = NULL;
198 iface->getModifyFlag = NULL;
199 iface->getReadFlag = NULL;
200 iface->getStatusCode = NULL;
201 iface->getReadData = NULL;
202 iface->getRootFolder = NULL;
203 iface->getListFolder = NULL;
204 iface->getListPerson = NULL;
205 iface->getAllPersons = NULL;
206 iface->getAllGroups = NULL;
207 iface->getName = NULL;
208 iface->listSource = NULL;
210 /* Search stuff */
211 iface->externalQuery = FALSE;
212 iface->searchOrder = 0; /* Ignored */
213 iface->startSearch = NULL;
214 iface->stopSearch = NULL;
216 return iface;
220 * Build table of of all address book interfaces.
221 * \param addrIndex Address index object.
223 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
224 AddressInterface *iface;
226 /* Create intrinsic XML address book interface */
227 iface = addrindex_create_interface(
228 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
229 TAG_DS_ADDRESS_BOOK );
230 iface->readOnly = FALSE;
231 iface->getModifyFlag = ( void * ) addrbook_get_modified;
232 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
233 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
234 iface->getStatusCode = ( void * ) addrbook_get_status;
235 iface->getReadData = ( void * ) addrbook_read_data;
236 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
237 iface->getListFolder = ( void * ) addrbook_get_list_folder;
238 iface->getListPerson = ( void * ) addrbook_get_list_person;
239 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
240 iface->getAllGroups = ( void * ) addrbook_get_all_groups;
241 iface->getName = ( void * ) addrbook_get_name;
242 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
243 iface->searchOrder = 0;
245 /* Add to list of interfaces in address book */
246 addrIndex->interfaceList =
247 g_list_append( addrIndex->interfaceList, iface );
248 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
250 /* Create vCard interface */
251 iface = addrindex_create_interface(
252 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
253 iface->getModifyFlag = ( void * ) vcard_get_modified;
254 iface->getAccessFlag = ( void * ) vcard_get_accessed;
255 iface->getReadFlag = ( void * ) vcard_get_read_flag;
256 iface->getStatusCode = ( void * ) vcard_get_status;
257 iface->getReadData = ( void * ) vcard_read_data;
258 iface->getRootFolder = ( void * ) vcard_get_root_folder;
259 iface->getListFolder = ( void * ) vcard_get_list_folder;
260 iface->getListPerson = ( void * ) vcard_get_list_person;
261 iface->getAllPersons = ( void * ) vcard_get_all_persons;
262 iface->getName = ( void * ) vcard_get_name;
263 iface->setAccessFlag = ( void * ) vcard_set_accessed;
264 iface->searchOrder = 0;
265 addrIndex->interfaceList =
266 g_list_append( addrIndex->interfaceList, iface );
267 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
269 /* Create JPilot interface */
270 iface = addrindex_create_interface(
271 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
272 TAG_DS_JPILOT );
273 #ifdef USE_JPILOT
274 iface->haveLibrary = jpilot_test_pilot_lib();
275 iface->useInterface = iface->haveLibrary;
276 iface->getModifyFlag = ( void * ) jpilot_get_modified;
277 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
278 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
279 iface->getStatusCode = ( void * ) jpilot_get_status;
280 iface->getReadData = ( void * ) jpilot_read_data;
281 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
282 iface->getListFolder = ( void * ) jpilot_get_list_folder;
283 iface->getListPerson = ( void * ) jpilot_get_list_person;
284 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
285 iface->getName = ( void * ) jpilot_get_name;
286 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
287 iface->searchOrder = 0;
288 #else
289 iface->useInterface = FALSE;
290 iface->haveLibrary = FALSE;
291 #endif
292 addrIndex->interfaceList =
293 g_list_append( addrIndex->interfaceList, iface );
294 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
296 /* Create LDAP interface */
297 iface = addrindex_create_interface(
298 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
299 #ifdef USE_LDAP
300 iface->readOnly = FALSE;
301 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
302 iface->haveLibrary = ldaputil_test_ldap_lib();
303 iface->useInterface = iface->haveLibrary;
304 iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
305 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
306 iface->getReadFlag = ( void * ) ldapsvr_get_read_flag;
307 iface->getStatusCode = ( void * ) ldapsvr_get_status;
308 iface->getReadData = ( void * ) ldapsvr_read_data;
309 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
310 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
311 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
312 iface->getName = ( void * ) ldapsvr_get_name;
313 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
314 iface->externalQuery = TRUE;
315 iface->searchOrder = 1;
316 #else
317 iface->useInterface = FALSE;
318 iface->haveLibrary = FALSE;
319 #endif
320 addrIndex->interfaceList =
321 g_list_append( addrIndex->interfaceList, iface );
322 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
324 /* Two old legacy data sources (pre 0.7.0) */
325 iface = addrindex_create_interface(
326 ADDR_IF_COMMON, "Old Address - common",
327 TAG_IF_OLD_COMMON, NULL );
328 iface->legacyFlag = TRUE;
329 addrIndex->interfaceList =
330 g_list_append( addrIndex->interfaceList, iface );
331 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
333 iface = addrindex_create_interface(
334 ADDR_IF_COMMON, "Old Address - personal",
335 TAG_IF_OLD_PERSONAL, NULL );
336 iface->legacyFlag = TRUE;
337 addrIndex->interfaceList =
338 g_list_append( addrIndex->interfaceList, iface );
339 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
344 * Free DOM fragment.
345 * \param fragment Fragment to free.
347 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
348 GList *node;
350 /* Free children */
351 node = fragment->children;
352 while( node ) {
353 AddressIfFragment *child = node->data;
354 addrindex_free_fragment( child );
355 node->data = NULL;
356 node = g_list_next( node );
358 g_list_free( fragment->children );
360 /* Free attributes */
361 node = fragment->attributes;
362 while( node ) {
363 AddressIfAttrib *nv = node->data;
364 g_free( nv->name );
365 g_free( nv->value );
366 g_free( nv );
367 node->data = NULL;
368 node = g_list_next( node );
370 g_list_free( fragment->attributes );
372 g_free( fragment->name );
373 fragment->name = NULL;
374 fragment->attributes = NULL;
375 fragment->children = NULL;
377 g_free( fragment );
381 * Create a new data source.
382 * \param ifType Interface type to create.
383 * \return Initialized data source.
385 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
386 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
388 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
389 ADDRITEM_ID(ds) = NULL;
390 ADDRITEM_NAME(ds) = NULL;
391 ADDRITEM_PARENT(ds) = NULL;
392 ADDRITEM_SUBTYPE(ds) = 0;
393 ds->type = ifType;
394 ds->rawDataSource = NULL;
395 ds->interface = NULL;
396 return ds;
400 * Free up data source.
401 * \param ds Data source to free.
403 void addrindex_free_datasource( AddressDataSource *ds ) {
404 AddressInterface *iface;
406 cm_return_if_fail( ds != NULL );
408 iface = ds->interface;
409 if( ds->rawDataSource != NULL ) {
410 if( iface != NULL ) {
411 if( iface->useInterface ) {
412 if( iface->type == ADDR_IF_BOOK ) {
413 AddressBookFile *abf = ds->rawDataSource;
414 addrbook_free_book( abf );
416 else if( iface->type == ADDR_IF_VCARD ) {
417 VCardFile *vcf = ds->rawDataSource;
418 vcard_free( vcf );
420 #ifdef USE_JPILOT
421 else if( iface->type == ADDR_IF_JPILOT ) {
422 JPilotFile *jpf = ds->rawDataSource;
423 jpilot_free( jpf );
425 #endif
426 #ifdef USE_LDAP
427 else if( iface->type == ADDR_IF_LDAP ) {
428 LdapServer *server = ds->rawDataSource;
429 ldapsvr_free( server );
431 #endif
432 else {
435 else {
436 AddressIfFragment *fragment = ds->rawDataSource;
437 addrindex_free_fragment( fragment );
442 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
443 ADDRITEM_ID(ds) = NULL;
444 ADDRITEM_NAME(ds) = NULL;
445 ADDRITEM_PARENT(ds) = NULL;
446 ADDRITEM_SUBTYPE(ds) = 0;
447 ds->type = ADDR_IF_NONE;
448 ds->interface = NULL;
449 ds->rawDataSource = NULL;
451 g_free( ds );
455 * Free up all data sources for specified interface.
456 * \param iface Address interface to process.
458 static void addrindex_free_all_datasources( AddressInterface *iface ) {
459 GList *node = iface->listSource;
460 while( node ) {
461 AddressDataSource *ds = node->data;
462 addrindex_free_datasource( ds );
463 node->data = NULL;
464 node = g_list_next( node );
469 * Free up specified interface.
470 * \param iface Interface to process.
472 static void addrindex_free_interface( AddressInterface *iface ) {
473 /* Free up data sources */
474 addrindex_free_all_datasources( iface );
475 g_list_free( iface->listSource );
477 /* Free internal storage */
478 g_free( ADDRITEM_ID(iface) );
479 g_free( ADDRITEM_NAME(iface) );
480 g_free( iface->name );
481 g_free( iface->listTag );
482 g_free( iface->itemTag );
484 /* Clear all pointers */
485 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
486 ADDRITEM_ID(iface) = NULL;
487 ADDRITEM_NAME(iface) = NULL;
488 ADDRITEM_PARENT(iface) = NULL;
489 ADDRITEM_SUBTYPE(iface) = 0;
490 iface->type = ADDR_IF_NONE;
491 iface->name = NULL;
492 iface->listTag = NULL;
493 iface->itemTag = NULL;
494 iface->legacyFlag = FALSE;
495 iface->useInterface = FALSE;
496 iface->haveLibrary = FALSE;
497 iface->listSource = NULL;
499 /* Search stuff */
500 iface->searchOrder = 0;
501 iface->startSearch = NULL;
502 iface->stopSearch = NULL;
504 g_free( iface );
508 * Return cache ID for specified data source.
510 * \param addrIndex Address index.
511 * \param ds Data source.
512 * \return ID or NULL if not found. This should be <code>g_free()</code>
513 * when done.
515 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
516 gchar *cacheID = NULL;
517 AddrBookBase *adbase;
518 AddressCache *cache;
520 cm_return_val_if_fail( addrIndex != NULL, NULL );
521 cm_return_val_if_fail( ds != NULL, NULL );
523 adbase = ( AddrBookBase * ) ds->rawDataSource;
524 if( adbase ) {
525 cache = adbase->addressCache;
526 if( cache ) {
527 cacheID = g_strdup( cache->cacheID );
531 return cacheID;
535 * Return reference to data source for specified cacheID.
536 * \param addrIndex Address index.
537 * \param cacheID ID.
538 * \return Data source, or NULL if not found.
540 static AddressDataSource *addrindex_get_datasource(
541 AddressIndex *addrIndex, const gchar *cacheID )
543 cm_return_val_if_fail( addrIndex != NULL, NULL );
544 cm_return_val_if_fail( cacheID != NULL, NULL );
545 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
549 * Return reference to address cache for specified cacheID.
550 * \param addrIndex Address index.
551 * \param cacheID ID.
552 * \return Address cache, or NULL if not found.
554 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
555 AddressDataSource *ds;
556 AddrBookBase *adbase;
557 AddressCache *cache;
559 cm_return_val_if_fail( addrIndex != NULL, NULL );
560 cm_return_val_if_fail( cacheID != NULL, NULL );
562 cache = NULL;
563 ds = addrindex_get_datasource( addrIndex, cacheID );
564 if( ds ) {
565 adbase = ( AddrBookBase * ) ds->rawDataSource;
566 cache = adbase->addressCache;
568 return cache;
572 * Add data source into hash table.
573 * \param addrIndex Address index.
574 * \param ds Data source.
576 static void addrindex_hash_add_cache(
577 AddressIndex *addrIndex, AddressDataSource *ds )
579 gchar *cacheID;
581 cacheID = addrindex_get_cache_id( addrIndex, ds );
582 if( cacheID ) {
583 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
588 * Free hash table callback function.
590 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
591 g_free( key );
592 key = NULL;
593 value = NULL;
594 return TRUE;
598 * Free hash table of address cache items.
600 static void addrindex_free_cache_hash( GHashTable *table ) {
601 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
602 g_hash_table_destroy( table );
606 * Remove data source from internal hashtable.
607 * \param addrIndex Address index.
608 * \param ds Data source to remove.
610 static void addrindex_hash_remove_cache(
611 AddressIndex *addrIndex, AddressDataSource *ds )
613 gchar *cacheID;
615 cacheID = addrindex_get_cache_id( addrIndex, ds );
616 if( cacheID ) {
617 g_hash_table_remove( addrIndex->hashCache, cacheID );
618 g_free( cacheID );
619 cacheID = NULL;
624 * Create a new address index. This is created as a singleton object.
625 * \return Initialized address index object.
627 AddressIndex *addrindex_create_index( void ) {
628 AddressIndex *index;
630 if( _addressIndex_ == NULL ) {
631 index = g_new0( AddressIndex, 1 );
632 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
633 ADDRITEM_ID(index) = NULL;
634 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
635 ADDRITEM_PARENT(index) = NULL;
636 ADDRITEM_SUBTYPE(index) = 0;
637 index->filePath = NULL;
638 index->fileName = NULL;
639 index->retVal = MGU_SUCCESS;
640 index->needsConversion = FALSE;
641 index->wasConverted = FALSE;
642 index->conversionError = FALSE;
643 index->interfaceList = NULL;
644 index->lastType = ADDR_IF_NONE;
645 index->dirtyFlag = FALSE;
646 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
647 index->loadedFlag = FALSE;
648 index->searchOrder = NULL;
649 addrindex_build_if_list( index );
650 _addressIndex_ = index;
652 return _addressIndex_;
656 * Property - Specify file path to address index file.
657 * \param addrIndex Address index.
658 * \param value Path to index file.
660 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
661 cm_return_if_fail( addrIndex != NULL );
662 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
666 * Property - Specify file name to address index file.
667 * \param addrIndex Address index.
668 * \param value File name.
670 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
671 cm_return_if_fail( addrIndex != NULL );
672 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
676 * Return list of address interfaces.
677 * \param addrIndex Address index.
678 * \return List of address interfaces.
680 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
681 cm_return_val_if_fail( addrIndex != NULL, NULL );
682 return addrIndex->interfaceList;
686 * Perform any other initialization of address index.
688 void addrindex_initialize( void ) {
689 qrymgr_initialize();
690 addrcompl_initialize();
694 * Perform any other teardown of address index.
696 void addrindex_teardown( void ) {
697 addrcompl_teardown();
698 qrymgr_teardown();
702 * Free up address index.
703 * \param addrIndex Address index.
705 void addrindex_free_index( AddressIndex *addrIndex ) {
706 GList *node;
708 cm_return_if_fail( addrIndex != NULL );
710 /* Search stuff */
711 g_list_free( addrIndex->searchOrder );
712 addrIndex->searchOrder = NULL;
714 /* Free internal storage */
715 g_free( ADDRITEM_ID(addrIndex) );
716 g_free( ADDRITEM_NAME(addrIndex) );
717 g_free( addrIndex->filePath );
718 g_free( addrIndex->fileName );
720 /* Clear pointers */
721 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
722 ADDRITEM_ID(addrIndex) = NULL;
723 ADDRITEM_NAME(addrIndex) = NULL;
724 ADDRITEM_PARENT(addrIndex) = NULL;
725 ADDRITEM_SUBTYPE(addrIndex) = 0;
726 addrIndex->filePath = NULL;
727 addrIndex->fileName = NULL;
728 addrIndex->retVal = MGU_SUCCESS;
729 addrIndex->needsConversion = FALSE;
730 addrIndex->wasConverted = FALSE;
731 addrIndex->conversionError = FALSE;
732 addrIndex->lastType = ADDR_IF_NONE;
733 addrIndex->dirtyFlag = FALSE;
735 /* Free up interfaces */
736 node = addrIndex->interfaceList;
737 while( node ) {
738 AddressInterface *iface = node->data;
739 addrindex_free_interface( iface );
740 node = g_list_next( node );
742 g_list_free( addrIndex->interfaceList );
743 addrIndex->interfaceList = NULL;
745 /* Free up hash cache */
746 addrindex_free_cache_hash( addrIndex->hashCache );
747 addrIndex->hashCache = NULL;
749 addrIndex->loadedFlag = FALSE;
751 g_free( addrIndex );
752 addrIndex = NULL;
753 _addressIndex_ = NULL;
757 * Print address index.
758 * \param addrIndex Address index.
759 * \parem stream Stream to print.
761 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
762 cm_return_if_fail( addrIndex != NULL );
763 fprintf( stream, "AddressIndex:\n" );
764 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
765 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
766 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
767 fprintf( stream, "\tconverted: '%s'\n",
768 addrIndex->wasConverted ? "yes" : "no" );
769 fprintf( stream, "\tcvt error: '%s'\n",
770 addrIndex->conversionError ? "yes" : "no" );
771 fprintf( stream, "\t---\n" );
775 * Retrieve reference to address interface for specified interface type.
776 * \param addrIndex Address index.
777 * \param ifType Interface type.
778 * \return Address interface, or NULL if not found.
780 static AddressInterface *addrindex_get_interface(
781 AddressIndex *addrIndex, AddressIfType ifType )
783 AddressInterface *retVal = NULL;
784 GList *node;
786 cm_return_val_if_fail( addrIndex != NULL, NULL );
788 node = addrIndex->interfaceList;
789 while( node ) {
790 AddressInterface *iface = node->data;
791 node = g_list_next( node );
792 if( iface->type == ifType ) {
793 retVal = iface;
794 break;
797 return retVal;
801 * Add raw data source to index. The raw data object (an AddressBookFile or
802 * VCardFile object, for example) should be supplied as the raw dataSource
803 * argument.
805 * \param addrIndex Address index.
806 * \param ifType Interface type to add.
807 * \param dataSource Actual raw data source to add.
808 * \return Data source added, or NULL if invalid interface type.
810 AddressDataSource *addrindex_index_add_datasource(
811 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
813 AddressInterface *iface;
814 AddressDataSource *ds = NULL;
816 cm_return_val_if_fail( addrIndex != NULL, NULL );
817 cm_return_val_if_fail( dataSource != NULL, NULL );
819 iface = addrindex_get_interface( addrIndex, ifType );
820 if( iface ) {
821 ds = addrindex_create_datasource( ifType );
822 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
823 ds->type = ifType;
824 ds->rawDataSource = dataSource;
825 ds->interface = iface;
826 iface->listSource = g_list_append( iface->listSource, ds );
827 addrIndex->dirtyFlag = TRUE;
829 addrindex_hash_add_cache( addrIndex, ds );
831 return ds;
835 * Remove specified data source from index.
836 * \param addrIndex Address index.
837 * \param dataSource Data source to add.
838 * \return Reference to data source if removed, or NULL if data source was not
839 * found in index. Note the this object must still be freed.
841 AddressDataSource *addrindex_index_remove_datasource(
842 AddressIndex *addrIndex, AddressDataSource *dataSource )
844 AddressDataSource *retVal = FALSE;
845 AddressInterface *iface;
847 cm_return_val_if_fail( addrIndex != NULL, NULL );
848 cm_return_val_if_fail( dataSource != NULL, NULL );
850 iface = addrindex_get_interface( addrIndex, dataSource->type );
851 if( iface ) {
852 iface->listSource = g_list_remove( iface->listSource, dataSource );
853 addrIndex->dirtyFlag = TRUE;
854 dataSource->interface = NULL;
856 /* Remove cache from hash table */
857 addrindex_hash_remove_cache( addrIndex, dataSource );
859 retVal = dataSource;
861 return retVal;
865 * Retrieve a reference to address interface for specified interface type and
866 * XML interface tag name.
867 * \param addrIndex Address index.
868 * \param tag XML interface tag name to match.
869 * \param ifType Interface type to match.
870 * \return Reference to address index, or NULL if not found in index.
872 static AddressInterface *addrindex_tag_get_interface(
873 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
875 AddressInterface *retVal = NULL;
876 GList *node = addrIndex->interfaceList;
878 while( node ) {
879 AddressInterface *iface = node->data;
880 node = g_list_next( node );
881 if( tag ) {
882 if( strcmp( iface->listTag, tag ) == 0 ) {
883 retVal = iface;
884 break;
887 else {
888 if( iface->type == ifType ) {
889 retVal = iface;
890 break;
894 return retVal;
898 * Retrieve a reference to address interface for specified interface type and
899 * XML datasource tag name.
900 * \param addrIndex Address index.
901 * \param ifType Interface type to match.
902 * \param tag XML datasource tag name to match.
903 * \return Reference to address index, or NULL if not found in index.
905 static AddressInterface *addrindex_tag_get_datasource(
906 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
908 AddressInterface *retVal = NULL;
909 GList *node = addrIndex->interfaceList;
911 while( node ) {
912 AddressInterface *iface = node->data;
913 node = g_list_next( node );
914 if( iface->type == ifType && iface->itemTag ) {
915 if( strcmp( iface->itemTag, tag ) == 0 ) {
916 retVal = iface;
917 break;
921 return retVal;
924 /* **********************************************************************
925 * Interface XML parsing functions.
926 * ***********************************************************************
930 * Write start of XML element to file.
931 * \param fp File.
932 * \param lvl Indentation level.
933 * \param name Element name.
935 static int addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
936 gint i;
937 for( i = 0; i < lvl; i++ )
938 if (fputs( " ", fp ) == EOF)
939 return -1;
940 if (fputs( "<", fp ) == EOF)
941 return -1;
942 if (fputs( name, fp ) == EOF)
943 return -1;
944 return 0;
948 * Write end of XML element to file.
949 * \param fp File.
950 * \param lvl Indentation level.
951 * \param name Element name.
953 static int addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
954 gint i;
955 for( i = 0; i < lvl; i++ )
956 if (fputs( " ", fp ) == EOF)
957 return -1;
958 if (fputs( "</", fp ) == EOF)
959 return -1;
960 if (fputs( name, fp ) == EOF)
961 return -1;
962 if (fputs( ">\n", fp ) == EOF)
963 return -1;
964 return 0;
968 * Write XML attribute to file.
969 * \param fp File.
970 * \param name Attribute name.
971 * \param value Attribute value.
973 static int addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
974 if (fputs( " ", fp ) == EOF)
975 return -1;
976 if (fputs( name, fp ) == EOF)
977 return -1;
978 if (fputs( "=\"", fp ) == EOF)
979 return -1;
980 if (xml_file_put_escape_str( fp, value ) < 0)
981 return -1;
982 if (fputs( "\"", fp ) == EOF)
983 return -1;
984 return 0;
987 #if !defined(USE_LDAP) || !defined(USE_JPILOT)
989 * Return DOM fragment for current XML tag from file.
990 * \param file XML file being processed.
991 * \return Fragment representing DOM fragment for configuration element.
993 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
994 AddressIfFragment *fragment;
995 AddressIfFragment *child;
996 AddressIfAttrib *nv;
997 XMLTag *xtag;
998 GList *list;
999 GList *attr;
1000 gchar *name;
1001 gchar *value;
1002 guint prevLevel;
1003 gint rc;
1005 /* g_print( "addrindex_read_fragment\n" ); */
1007 prevLevel = file->level;
1009 /* Get current tag name */
1010 xtag = xml_get_current_tag( file );
1012 /* Create new fragment */
1013 fragment = g_new0( AddressIfFragment, 1 );
1014 fragment->name = g_strdup( xtag->tag );
1015 fragment->children = NULL;
1016 fragment->attributes = NULL;
1018 /* Read attributes */
1019 list = NULL;
1020 attr = xml_get_current_tag_attr( file );
1021 while( attr ) {
1022 name = ((XMLAttr *)attr->data)->name;
1023 value = ((XMLAttr *)attr->data)->value;
1024 nv = g_new0( AddressIfAttrib, 1 );
1025 nv->name = g_strdup( name );
1026 nv->value = g_strdup( value );
1027 list = g_list_append( list, nv );
1028 attr = g_list_next( attr );
1030 fragment->attributes = list;
1032 /* Now read the children */
1033 while( TRUE ) {
1034 rc = xml_parse_next_tag( file );
1035 if( rc != 0 ) {
1036 /* End of file? */
1037 break;
1039 if( file->level < prevLevel ) {
1040 /* We must be above level we start at */
1041 break;
1043 child = addrindex_read_fragment( file );
1044 fragment->children = g_list_append( fragment->children, child );
1047 return fragment;
1051 * Write DOM fragment to file.
1052 * \param fp File to write.
1053 * \param fragment DOM fragment for configuration element.
1054 * \param lvl Indent level.
1056 static int addrindex_write_fragment(
1057 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1059 GList *node;
1061 if( fragment ) {
1062 if (addrindex_write_elem_s( fp, lvl, fragment->name ) < 0)
1063 return -1;
1064 node = fragment->attributes;
1065 while( node ) {
1066 AddressIfAttrib *nv = node->data;
1067 if (addrindex_write_attr( fp, nv->name, nv->value ) < 0)
1068 return -1;
1069 node = g_list_next( node );
1071 if( fragment->children ) {
1072 if (fputs(" >\n", fp) == EOF)
1073 return -1;
1075 /* Output children */
1076 node = fragment->children;
1077 while( node ) {
1078 AddressIfFragment *child = node->data;
1079 if (addrindex_write_fragment( fp, child, 1+lvl ) < 0)
1080 return -1;
1081 node = g_list_next( node );
1084 /* Output closing tag */
1085 if (addrindex_write_elem_e( fp, lvl, fragment->name ) < 0)
1086 return -1;
1088 else {
1089 if (fputs(" />\n", fp) == EOF)
1090 return -1;
1094 return 0;
1096 #endif
1098 * Read/parse address index file, creating a data source for a regular
1099 * intrinsic XML addressbook.
1100 * \param file Address index file.
1101 * \return Data source.
1103 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1104 AddressDataSource *ds;
1105 AddressBookFile *abf;
1106 GList *attr;
1108 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1109 abf = addrbook_create_book();
1110 attr = xml_get_current_tag_attr( file );
1111 while( attr ) {
1112 gchar *name = ((XMLAttr *)attr->data)->name;
1113 gchar *value = ((XMLAttr *)attr->data)->value;
1114 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1115 addrbook_set_name( abf, value );
1117 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1118 addrbook_set_file( abf, value );
1120 attr = g_list_next( attr );
1122 ds->rawDataSource = abf;
1123 return ds;
1126 static int addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1127 AddressBookFile *abf = ds->rawDataSource;
1128 if( abf ) {
1129 if (addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK ) < 0)
1130 return -1;
1131 if (addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) ) < 0)
1132 return -1;
1133 if (addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName ) < 0)
1134 return -1;
1135 if (fputs( " />\n", fp ) == EOF)
1136 return -1;
1138 return 0;
1141 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1142 AddressDataSource *ds;
1143 VCardFile *vcf;
1144 GList *attr;
1146 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1147 vcf = vcard_create();
1148 attr = xml_get_current_tag_attr( file );
1149 while( attr ) {
1150 gchar *name = ((XMLAttr *)attr->data)->name;
1151 gchar *value = ((XMLAttr *)attr->data)->value;
1152 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1153 vcard_set_name( vcf, value );
1155 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1156 vcard_set_file( vcf, value );
1158 attr = g_list_next( attr );
1160 ds->rawDataSource = vcf;
1161 return ds;
1164 static int addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1165 VCardFile *vcf = ds->rawDataSource;
1166 if( vcf ) {
1167 if (addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD ) < 0)
1168 return -1;
1169 if (addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) ) < 0)
1170 return -1;
1171 if (addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path ) < 0)
1172 return -1;
1173 if (fputs( " />\n", fp ) == EOF)
1174 return -1;
1176 return 0;
1179 #ifdef USE_JPILOT
1180 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1181 AddressDataSource *ds;
1182 JPilotFile *jpf;
1183 GList *attr;
1185 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1186 jpf = jpilot_create();
1187 attr = xml_get_current_tag_attr( file );
1188 while( attr ) {
1189 gchar *name = ((XMLAttr *)attr->data)->name;
1190 gchar *value = ((XMLAttr *)attr->data)->value;
1191 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1192 jpilot_set_name( jpf, value );
1194 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1195 jpilot_set_file( jpf, value );
1197 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1198 jpilot_add_custom_label( jpf, value );
1200 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1201 jpilot_add_custom_label( jpf, value );
1203 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1204 jpilot_add_custom_label( jpf, value );
1206 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1207 jpilot_add_custom_label( jpf, value );
1209 attr = g_list_next( attr );
1211 ds->rawDataSource = jpf;
1212 return ds;
1215 static int addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1216 JPilotFile *jpf = ds->rawDataSource;
1217 if( jpf ) {
1218 gint ind;
1219 GList *node;
1220 GList *customLbl = jpilot_get_custom_labels( jpf );
1221 if (addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT ) < 0)
1222 return -1;
1223 if (addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) ) < 0)
1224 return -1;
1225 if (addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path ) < 0)
1226 return -1;
1227 node = customLbl;
1228 ind = 1;
1229 while( node ) {
1230 gchar name[256];
1231 g_snprintf( name, sizeof(name), "%s%d",
1232 ATTAG_JPILOT_CUSTOM, ind );
1233 if (addrindex_write_attr( fp, name, node->data ) < 0)
1234 return -1;
1235 ind++;
1236 node = g_list_next( node );
1238 if (fputs( " />\n", fp ) == EOF)
1239 return -1;
1241 return 0;
1244 #else
1246 * Just read/write DOM fragments (preserve data found in file).
1248 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1249 AddressDataSource *ds;
1251 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1252 ds->rawDataSource = addrindex_read_fragment( file );
1253 return ds;
1256 static int addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1257 AddressIfFragment *fragment = ds->rawDataSource;
1258 if( fragment ) {
1259 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1260 return -1;
1262 return 0;
1264 #endif
1266 #ifdef USE_LDAP
1268 * Parse LDAP criteria attribute data from XML file.
1269 * \param file Index file.
1270 * \param ctl LDAP control object to populate.
1272 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1273 guint prevLevel;
1274 XMLTag *xtag;
1275 XMLTag *xtagPrev;
1276 gint rc;
1277 GList *attr;
1278 GList *list;
1279 GList *node;
1281 if( file == NULL ) {
1282 return;
1285 list = NULL;
1286 prevLevel = file->level;
1287 xtagPrev = xml_get_current_tag( file );
1288 while( TRUE ) {
1289 rc = xml_parse_next_tag( file );
1290 if( rc != 0 ) {
1291 /* Terminate prematurely */
1292 mgu_free_dlist( list );
1293 list = NULL;
1294 return;
1296 if( file->level < prevLevel ) {
1297 /* We must be above level we start at */
1298 break;
1301 /* Get a tag (element) */
1302 xtag = xml_get_current_tag( file );
1303 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1304 /* LDAP criteria attribute */
1305 attr = xml_get_current_tag_attr( file );
1306 while( attr ) {
1307 gchar *name = ((XMLAttr *)attr->data)->name;
1308 gchar *value = ((XMLAttr *)attr->data)->value;
1309 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1310 if( value && strlen( value ) > 0 ) {
1311 list = g_list_append(
1312 list, g_strdup( value ) );
1315 attr = g_list_next( attr );
1318 else {
1319 if( xtag != xtagPrev ) {
1320 /* Found a new tag */
1321 break;
1324 xtag = xtagPrev;
1327 /* Build list of search attributes */
1328 ldapctl_criteria_list_clear( ctl );
1329 node = list;
1330 while( node ) {
1331 ldapctl_criteria_list_add( ctl, node->data );
1332 g_free( node->data );
1333 node->data = NULL;
1334 node = g_list_next( node );
1336 g_list_free( list );
1337 list = NULL;
1341 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1343 * Parse LDAP control data from XML file.
1344 * \param file Index file.
1345 * \return Initialized data soruce object.
1347 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1348 AddressDataSource *ds;
1349 LdapServer *server;
1350 LdapControl *ctl;
1351 GList *attr;
1352 gchar *serverName = NULL;
1353 gchar *criteria = NULL;
1354 gboolean bDynSearch;
1355 gboolean bTLS, bSSL;
1356 gint iMatch;
1358 /* g_print( "addrindex_parse_ldap\n" ); */
1359 /* Set up some defaults */
1360 bDynSearch = FALSE;
1361 bTLS = FALSE;
1362 bSSL = FALSE;
1363 iMatch = LDAPCTL_MATCH_BEGINWITH;
1365 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1366 ctl = ldapctl_create();
1367 attr = xml_get_current_tag_attr( file );
1368 while( attr ) {
1369 gchar *name = ((XMLAttr *)attr->data)->name;
1370 gchar *value = ((XMLAttr *)attr->data)->value;
1371 gint ivalue = atoi( value );
1373 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1374 g_free( serverName );
1375 serverName = g_strdup( value );
1377 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1378 ldapctl_set_host( ctl, value );
1380 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1381 ldapctl_set_port( ctl, ivalue );
1383 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1384 ldapctl_set_base_dn( ctl, value );
1386 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1387 ldapctl_set_bind_dn( ctl, value );
1389 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1390 ldapctl_set_bind_password( ctl, value, FALSE, FALSE );
1392 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1393 g_free( criteria );
1394 criteria = g_strdup( value );
1395 g_print("criteria %s\n", criteria);
1397 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1398 ldapctl_set_max_entries( ctl, ivalue );
1400 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1401 ldapctl_set_timeout( ctl, ivalue );
1403 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1404 ldapctl_set_max_query_age( ctl, ivalue );
1406 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1407 bDynSearch = FALSE;
1408 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1409 bDynSearch = TRUE;
1412 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1413 iMatch = LDAPCTL_MATCH_BEGINWITH;
1414 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1415 iMatch = LDAPCTL_MATCH_CONTAINS;
1418 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1419 bTLS = FALSE;
1420 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1421 bTLS = TRUE;
1424 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1425 bSSL = FALSE;
1426 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1427 bSSL = TRUE;
1430 attr = g_list_next( attr );
1433 server = ldapsvr_create_noctl();
1434 ldapsvr_set_name( server, serverName );
1435 ldapsvr_set_search_flag( server, bDynSearch );
1436 ldapctl_set_matching_option( ctl, iMatch );
1437 ldapctl_set_tls( ctl, bTLS );
1438 ldapctl_set_ssl( ctl, bSSL );
1439 g_free( serverName );
1440 ldapsvr_set_control( server, ctl );
1441 ds->rawDataSource = server;
1443 addrindex_parse_ldap_attrlist( file, ctl );
1445 * If criteria have been specified and no attributes were listed, then
1446 * convert old style criteria into an attribute list. Any criteria will
1447 * be dropped when saving data.
1449 if( criteria ) {
1450 if( ! ldapctl_get_criteria_list( ctl ) ) {
1451 ldapctl_parse_ldap_search( ctl, criteria );
1453 g_free( criteria );
1455 /* ldapsvr_print_data( server, stdout ); */
1457 return ds;
1460 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1461 LdapServer *server = ds->rawDataSource;
1462 LdapControl *ctl = NULL;
1463 GList *node;
1464 gchar value[256];
1466 if( server ) {
1467 ctl = server->control;
1469 if( ctl == NULL ) return 0;
1471 /* Output start element with attributes */
1472 if (addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP ) < 0)
1473 return -1;
1474 if (addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) ) < 0)
1475 return -1;
1476 if (addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName ) < 0)
1477 return -1;
1479 sprintf( value, "%d", ctl->port );
1480 if (addrindex_write_attr( fp, ATTAG_LDAP_PORT, value ) < 0)
1481 return -1;
1483 if (addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN ) < 0)
1484 return -1;
1485 if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN ) < 0)
1486 return -1;
1487 if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass ) < 0)
1488 return -1;
1490 sprintf( value, "%d", ctl->maxEntries );
1491 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value ) < 0)
1492 return -1;
1493 sprintf( value, "%d", ctl->timeOut );
1494 if (addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value ) < 0)
1495 return -1;
1496 sprintf( value, "%d", ctl->maxQueryAge );
1497 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value ) < 0)
1498 return -1;
1500 if (addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1501 server->searchFlag ?
1502 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1503 return -1;
1505 if (addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1506 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1507 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN ) < 0)
1508 return -1;
1510 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1511 ctl->enableTLS ?
1512 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1513 return -1;
1514 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1515 ctl->enableSSL ?
1516 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1517 return -1;
1519 if (fputs(" >\n", fp) == EOF)
1520 return -1;
1522 /* Output attributes */
1523 node = ldapctl_get_criteria_list( ctl );
1524 while( node ) {
1525 if (addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH ) < 0)
1526 return -1;
1527 if (addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data ) < 0)
1528 return -1;
1529 if (fputs(" />\n", fp) == EOF)
1530 return -1;
1531 node = g_list_next( node );
1534 /* End of element */
1535 if (addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP ) < 0)
1536 return -1;
1538 return 0;
1541 #else
1543 * Just read/write DOM fragments (preserve data found in file).
1545 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1546 AddressDataSource *ds;
1548 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1549 ds->rawDataSource = addrindex_read_fragment( file );
1550 return ds;
1553 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1554 AddressIfFragment *fragment = ds->rawDataSource;
1555 if( fragment ) {
1556 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1557 return -1;
1559 return 0;
1561 #endif
1563 /* **********************************************************************
1564 * Address index I/O functions.
1565 * ***********************************************************************
1568 * Read address index file, creating appropriate data sources for each address
1569 * index file entry.
1571 * \param addrIndex Address index.
1572 * \param file Address index file.
1574 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1575 XMLTag *xtag;
1576 AddressInterface *iface = NULL, *dsIFace = NULL;
1577 AddressDataSource *ds;
1578 gint rc;
1580 addrIndex->loadedFlag = FALSE;
1581 for (;;) {
1582 rc = xml_parse_next_tag( file );
1583 if( rc < 0 || file->level == 0 ) return;
1585 xtag = xml_get_current_tag( file );
1587 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1588 if( iface ) {
1589 addrIndex->lastType = iface->type;
1590 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1592 else {
1593 dsIFace = addrindex_tag_get_datasource(
1594 addrIndex, addrIndex->lastType, xtag->tag );
1595 if( dsIFace ) {
1596 /* Add data source to list */
1597 ds = NULL;
1598 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1599 ds = addrindex_parse_book( file );
1600 if( ds->rawDataSource ) {
1601 addrbook_set_path( ds->rawDataSource,
1602 addrIndex->filePath );
1605 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1606 ds = addrindex_parse_vcard( file );
1608 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1609 ds = addrindex_parse_jpilot( file );
1611 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1612 ds = addrindex_parse_ldap( file );
1614 if( ds ) {
1615 ds->interface = dsIFace;
1616 addrindex_hash_add_cache( addrIndex, ds );
1617 dsIFace->listSource =
1618 g_list_append( dsIFace->listSource, ds );
1626 * Search order sorting comparison function for building search order list.
1628 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1629 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1630 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1632 return ifaceA->searchOrder - ifaceB->searchOrder;
1636 * Build list of data sources to process.
1637 * \param addrIndex Address index object.
1639 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1640 GList *nodeIf;
1642 /* Clear existing list */
1643 g_list_free( addrIndex->searchOrder );
1644 addrIndex->searchOrder = NULL;
1646 /* Build new list */
1647 nodeIf = addrIndex->interfaceList;
1648 while( nodeIf ) {
1649 AddressInterface *iface = nodeIf->data;
1650 if( iface->useInterface ) {
1651 if( iface->searchOrder > 0 ) {
1652 /* Add to search order list */
1653 addrIndex->searchOrder = g_list_insert_sorted(
1654 addrIndex->searchOrder, iface,
1655 addrindex_search_order_compare );
1658 nodeIf = g_list_next( nodeIf );
1662 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1663 XMLFile *file = NULL;
1664 gchar *fileSpec = NULL;
1666 cm_return_val_if_fail( addrIndex != NULL, -1 );
1668 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1669 addrIndex->retVal = MGU_NO_FILE;
1670 file = xml_open_file( fileSpec );
1671 g_free( fileSpec );
1673 if( file == NULL ) {
1675 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1677 return addrIndex->retVal;
1680 addrIndex->retVal = MGU_BAD_FORMAT;
1681 if( xml_get_dtd( file ) == 0 ) {
1682 if( xml_parse_next_tag( file ) == 0 ) {
1683 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1684 addrindex_read_index( addrIndex, file );
1685 addrIndex->retVal = MGU_SUCCESS;
1689 xml_close_file( file );
1691 addrindex_build_search_order( addrIndex );
1693 return addrIndex->retVal;
1696 static int addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1697 GList *nodeIF, *nodeDS;
1698 gint lvlList = 1;
1699 gint lvlItem = 1 + lvlList;
1701 nodeIF = addrIndex->interfaceList;
1702 while( nodeIF ) {
1703 AddressInterface *iface = nodeIF->data;
1704 if( ! iface->legacyFlag ) {
1705 nodeDS = iface->listSource;
1706 if (addrindex_write_elem_s( fp, lvlList, iface->listTag ) < 0)
1707 return -1;
1708 if (fputs( ">\n", fp ) == EOF)
1709 return -1;
1710 while( nodeDS ) {
1711 AddressDataSource *ds = nodeDS->data;
1712 if( ds ) {
1713 if( iface->type == ADDR_IF_BOOK ) {
1714 if (addrindex_write_book( fp, ds, lvlItem ) < 0)
1715 return -1;
1717 if( iface->type == ADDR_IF_VCARD ) {
1718 if (addrindex_write_vcard( fp, ds, lvlItem ) < 0)
1719 return -1;
1721 if( iface->type == ADDR_IF_JPILOT ) {
1722 if (addrindex_write_jpilot( fp, ds, lvlItem ) < 0)
1723 return -1;
1725 if( iface->type == ADDR_IF_LDAP ) {
1726 if (addrindex_write_ldap( fp, ds, lvlItem ) < 0)
1727 return -1;
1730 nodeDS = g_list_next( nodeDS );
1732 if (addrindex_write_elem_e( fp, lvlList, iface->listTag ) < 0)
1733 return -1;
1735 nodeIF = g_list_next( nodeIF );
1737 return 0;
1741 * Write data to specified file.
1742 * Enter: addrIndex Address index object.
1743 * newFile New file name.
1744 * return: Status code, from addrIndex->retVal.
1745 * Note: File will be created in directory specified by addrIndex.
1747 static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1748 FILE *fp;
1749 gchar *fileSpec;
1750 #ifndef DEV_STANDALONE
1751 PrefFile *pfile;
1752 #endif
1754 cm_return_val_if_fail( addrIndex != NULL, -1 );
1756 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1757 addrIndex->retVal = MGU_OPEN_FILE;
1758 #ifdef DEV_STANDALONE
1759 fp = g_fopen( fileSpec, "wb" );
1760 g_free( fileSpec );
1761 if( fp ) {
1762 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1763 #else
1764 pfile = prefs_write_open( fileSpec );
1765 g_free( fileSpec );
1766 if( pfile ) {
1767 fp = pfile->fp;
1768 if (fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL ) < 0)
1769 goto fail;
1770 #endif
1771 if (addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1772 goto fail;
1773 if (fputs( ">\n", fp ) == EOF)
1774 goto fail;
1776 if (addrindex_write_index( addrIndex, fp ) < 0)
1777 goto fail;
1778 if (addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1779 goto fail;
1781 addrIndex->retVal = MGU_SUCCESS;
1782 #ifdef DEV_STANDALONE
1783 fclose( fp );
1784 #else
1785 if( prefs_file_close( pfile ) < 0 ) {
1786 addrIndex->retVal = MGU_ERROR_WRITE;
1788 #endif
1791 fileSpec = NULL;
1792 return addrIndex->retVal;
1793 fail:
1794 g_warning("error writing AB index");
1795 addrIndex->retVal = MGU_ERROR_WRITE;
1796 if (pfile)
1797 prefs_file_close_revert( pfile );
1798 return addrIndex->retVal;
1802 * Save address index data to original file.
1803 * return: Status code, from addrIndex->retVal.
1805 gint addrindex_save_data( AddressIndex *addrIndex ) {
1806 #ifdef USE_LDAP
1807 GList *nodeIf;
1808 GList *nodeDS;
1809 #endif
1811 cm_return_val_if_fail( addrIndex != NULL, -1 );
1813 #ifdef USE_LDAP
1814 nodeIf = addrIndex->interfaceList;
1815 /* save LDAP interfaces */
1816 while ( nodeIf ) {
1817 AddressInterface *iface = nodeIf->data;
1818 if( iface->type == ADDR_IF_LDAP ) {
1819 nodeDS = iface->listSource;
1820 while( nodeDS ) {
1821 AddressDataSource *ds = nodeDS->data;
1822 LdapServer *abf = ds->rawDataSource;
1823 if( ldapsvr_get_read_flag( abf ) ) {
1824 if( ldapsvr_get_modified( abf ) ) {
1825 ldapsvr_update_book( abf, NULL );
1826 if( abf->retVal != LDAPRC_SUCCESS ) {
1827 alertpanel( _("Address(es) update"),
1828 _("Update failed. Changes not written to Directory."),
1829 GTK_STOCK_CLOSE, NULL, NULL );
1831 else {
1832 abf->retVal = MGU_SUCCESS;
1833 ldapsvr_set_modified( abf, FALSE );
1837 nodeDS = g_list_next( nodeDS );
1839 break;
1841 nodeIf = g_list_next( nodeIf );
1843 #endif
1844 addrIndex->retVal = MGU_NO_FILE;
1845 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1846 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1848 addrindex_write_to( addrIndex, addrIndex->fileName );
1849 if( addrIndex->retVal == MGU_SUCCESS ) {
1850 addrIndex->dirtyFlag = FALSE;
1852 return addrIndex->retVal;
1856 * Save all address book files which may have changed.
1857 * Return: Status code, set if there was a problem saving data.
1859 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1860 gint retVal = MGU_SUCCESS;
1861 GList *nodeIf, *nodeDS;
1863 nodeIf = addrIndex->interfaceList;
1864 while( nodeIf ) {
1865 AddressInterface *iface = nodeIf->data;
1866 if( iface->type == ADDR_IF_BOOK ) {
1867 nodeDS = iface->listSource;
1868 while( nodeDS ) {
1869 AddressDataSource *ds = nodeDS->data;
1870 AddressBookFile *abf = ds->rawDataSource;
1871 if( addrbook_get_dirty( abf ) ) {
1872 if( addrbook_get_read_flag( abf ) ) {
1873 addrbook_save_data( abf );
1874 if( abf->retVal != MGU_SUCCESS ) {
1875 retVal = abf->retVal;
1879 nodeDS = g_list_next( nodeDS );
1881 break;
1883 nodeIf = g_list_next( nodeIf );
1885 return retVal;
1889 /* **********************************************************************
1890 * Address book conversion to new format.
1891 * ***********************************************************************
1894 #define ELTAG_IF_OLD_FOLDER "folder"
1895 #define ELTAG_IF_OLD_GROUP "group"
1896 #define ELTAG_IF_OLD_ITEM "item"
1897 #define ELTAG_IF_OLD_NAME "name"
1898 #define ELTAG_IF_OLD_ADDRESS "address"
1899 #define ELTAG_IF_OLD_REMARKS "remarks"
1900 #define ATTAG_IF_OLD_NAME "name"
1902 #define TEMPNODE_ROOT 0
1903 #define TEMPNODE_FOLDER 1
1904 #define TEMPNODE_GROUP 2
1905 #define TEMPNODE_ADDRESS 3
1907 typedef struct _AddressCvt_Node AddressCvtNode;
1908 struct _AddressCvt_Node {
1909 gint type;
1910 gchar *name;
1911 gchar *address;
1912 gchar *remarks;
1913 GList *list;
1917 * Parse current address item.
1919 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1920 gchar *element;
1921 guint level;
1922 AddressCvtNode *nn;
1924 nn = g_new0( AddressCvtNode, 1 );
1925 nn->type = TEMPNODE_ADDRESS;
1926 nn->list = NULL;
1928 level = file->level;
1930 for (;;) {
1931 xml_parse_next_tag(file);
1932 if (file->level < level) return nn;
1934 element = xml_get_element( file );
1935 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1936 nn->name = g_strdup( element );
1938 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1939 nn->address = g_strdup( element );
1941 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1942 nn->remarks = g_strdup( element );
1944 g_free(element);
1945 xml_parse_next_tag(file);
1950 * Create a temporary node below specified node.
1952 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1953 AddressCvtNode *nn;
1954 nn = g_new0( AddressCvtNode, 1 );
1955 nn->type = type;
1956 nn->name = g_strdup( name );
1957 nn->remarks = g_strdup( rem );
1958 node->list = g_list_append( node->list, nn );
1959 return nn;
1963 * Process current temporary node.
1965 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1966 GList *attr;
1967 guint prev_level;
1968 AddressCvtNode *newNode = NULL;
1969 gchar *name;
1970 gchar *value;
1972 for (;;) {
1973 prev_level = file->level;
1974 xml_parse_next_tag( file );
1975 if (file->level < prev_level) return;
1976 name = NULL;
1977 value = NULL;
1979 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1980 attr = xml_get_current_tag_attr(file);
1981 if (attr) {
1982 name = ((XMLAttr *)attr->data)->name;
1983 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1984 value = ((XMLAttr *)attr->data)->value;
1987 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1988 addrindex_add_obj( file, newNode );
1991 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1992 attr = xml_get_current_tag_attr(file);
1993 if (attr) {
1994 name = ((XMLAttr *)attr->data)->name;
1995 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1996 value = ((XMLAttr *)attr->data)->value;
1999 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
2000 addrindex_add_obj( file, newNode );
2002 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
2003 newNode = addrindex_parse_item( file );
2004 node->list = g_list_append( node->list, newNode );
2006 else {
2007 g_warning("Invalid tag");
2013 * Consume all nodes below current tag.
2015 static void addrindex_consume_tree( XMLFile *file ) {
2016 guint prev_level;
2018 for (;;) {
2019 prev_level = file->level;
2020 xml_parse_next_tag( file );
2021 if (file->level < prev_level)
2022 return;
2024 addrindex_consume_tree( file );
2029 * Free up temporary tree.
2031 static void addrindex_free_node( AddressCvtNode *node ) {
2032 GList *list = node->list;
2034 while( list ) {
2035 AddressCvtNode *lNode = list->data;
2036 list = g_list_next( list );
2037 addrindex_free_node( lNode );
2039 node->type = TEMPNODE_ROOT;
2040 g_free( node->name );
2041 g_free( node->address );
2042 g_free( node->remarks );
2043 g_list_free( node->list );
2044 g_free( node );
2048 * Process address book for specified node.
2050 static void addrindex_process_node(
2051 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
2052 ItemGroup *parentGrp, ItemFolder *folderGrp )
2054 GList *list;
2055 ItemFolder *itemFolder = NULL;
2056 ItemGroup *itemGParent = parentGrp;
2057 ItemFolder *itemGFolder = folderGrp;
2058 AddressCache *cache = abf->addressCache;
2060 if( node->type == TEMPNODE_ROOT ) {
2061 itemFolder = parent;
2063 else if( node->type == TEMPNODE_FOLDER ) {
2064 itemFolder = addritem_create_item_folder();
2065 addritem_folder_set_name( itemFolder, node->name );
2066 addrcache_id_folder( cache, itemFolder );
2067 addrcache_folder_add_folder( cache, parent, itemFolder );
2068 itemGFolder = NULL;
2070 else if( node->type == TEMPNODE_GROUP ) {
2071 ItemGroup *itemGroup;
2072 gchar *fName;
2074 /* Create a folder for group */
2075 fName = g_strdup_printf( "Cvt - %s", node->name );
2076 itemGFolder = addritem_create_item_folder();
2077 addritem_folder_set_name( itemGFolder, fName );
2078 addrcache_id_folder( cache, itemGFolder );
2079 addrcache_folder_add_folder( cache, parent, itemGFolder );
2080 g_free( fName );
2082 /* Add group into folder */
2083 itemGroup = addritem_create_item_group();
2084 addritem_group_set_name( itemGroup, node->name );
2085 addrcache_id_group( cache, itemGroup );
2086 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2087 itemGParent = itemGroup;
2089 else if( node->type == TEMPNODE_ADDRESS ) {
2090 ItemPerson *itemPerson;
2091 ItemEMail *itemEMail;
2093 /* Create person and email objects */
2094 itemPerson = addritem_create_item_person();
2095 addritem_person_set_common_name( itemPerson, node->name );
2096 addrcache_id_person( cache, itemPerson );
2097 itemEMail = addritem_create_item_email();
2098 addritem_email_set_address( itemEMail, node->address );
2099 addritem_email_set_remarks( itemEMail, node->remarks );
2100 addrcache_id_email( cache, itemEMail );
2101 addrcache_person_add_email( cache, itemPerson, itemEMail );
2103 /* Add person into appropriate folder */
2104 if( itemGFolder ) {
2105 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2107 else {
2108 addrcache_folder_add_person( cache, parent, itemPerson );
2111 /* Add email address only into group */
2112 if( parentGrp ) {
2113 addrcache_group_add_email( cache, parentGrp, itemEMail );
2117 list = node->list;
2118 while( list ) {
2119 AddressCvtNode *lNode = list->data;
2120 list = g_list_next( list );
2121 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2126 * Process address book to specified file number.
2128 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2129 gboolean retVal = FALSE;
2130 AddressBookFile *abf = NULL;
2131 AddressCvtNode *rootNode = NULL;
2132 gchar *newFile = NULL;
2133 GList *fileList = NULL;
2134 gint fileNum = 0;
2136 /* Setup root node */
2137 rootNode = g_new0( AddressCvtNode, 1 );
2138 rootNode->type = TEMPNODE_ROOT;
2139 rootNode->name = g_strdup( "root" );
2140 rootNode->list = NULL;
2141 addrindex_add_obj( file, rootNode );
2142 /* addrindex_print_node( rootNode, stdout ); */
2144 /* Create new address book */
2145 abf = addrbook_create_book();
2146 addrbook_set_name( abf, displayName );
2147 addrbook_set_path( abf, addrIndex->filePath );
2149 /* Determine next available file number */
2150 fileList = addrbook_get_bookfile_list( abf );
2151 if( fileList ) {
2152 fileNum = 1 + abf->maxValue;
2154 g_list_free( fileList );
2155 fileList = NULL;
2157 newFile = addrbook_gen_new_file_name( fileNum );
2158 if( newFile ) {
2159 addrbook_set_file( abf, newFile );
2162 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2164 /* addrbook_dump_book( abf, stdout ); */
2165 addrbook_save_data( abf );
2166 addrIndex->retVal = abf->retVal;
2167 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2169 addrbook_free_book( abf );
2170 abf = NULL;
2171 addrindex_free_node( rootNode );
2172 rootNode = NULL;
2174 /* Create entries in address index */
2175 if( retVal ) {
2176 abf = addrbook_create_book();
2177 addrbook_set_name( abf, displayName );
2178 addrbook_set_path( abf, addrIndex->filePath );
2179 addrbook_set_file( abf, newFile );
2180 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2183 return retVal;
2187 * Process tree converting data.
2189 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2190 guint prev_level;
2191 XMLTag *xtag;
2193 /* Process file */
2194 for (;;) {
2195 prev_level = file->level;
2196 xml_parse_next_tag( file );
2197 if (file->level < prev_level) return;
2199 xtag = xml_get_current_tag( file );
2200 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2201 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2202 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2203 addrIndex->needsConversion = FALSE;
2204 addrIndex->wasConverted = TRUE;
2205 continue;
2207 return;
2209 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2210 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2211 addrIndex->needsConversion = FALSE;
2212 addrIndex->wasConverted = TRUE;
2213 continue;
2215 return;
2217 addrindex_consume_tree( file );
2221 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2222 XMLFile *file = NULL;
2223 gchar *fileSpec;
2225 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2226 addrIndex->retVal = MGU_NO_FILE;
2227 file = xml_open_file( fileSpec );
2228 g_free( fileSpec );
2230 if( file == NULL ) {
2231 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2232 return addrIndex->retVal;
2235 addrIndex->retVal = MGU_BAD_FORMAT;
2236 if( xml_get_dtd( file ) == 0 ) {
2237 if( xml_parse_next_tag( file ) == 0 ) {
2238 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2239 addrindex_convert_tree( addrIndex, file );
2243 xml_close_file( file );
2244 return addrIndex->retVal;
2248 * Create a new address book file.
2250 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2251 gboolean retVal = FALSE;
2252 AddressBookFile *abf = NULL;
2253 gchar *newFile = NULL;
2254 GList *fileList = NULL;
2255 gint fileNum = 0;
2257 /* Create new address book */
2258 abf = addrbook_create_book();
2259 addrbook_set_name( abf, displayName );
2260 addrbook_set_path( abf, addrIndex->filePath );
2262 /* Determine next available file number */
2263 fileList = addrbook_get_bookfile_list( abf );
2264 if( fileList ) {
2265 fileNum = 1 + abf->maxValue;
2267 g_list_free( fileList );
2268 fileList = NULL;
2270 newFile = addrbook_gen_new_file_name( fileNum );
2271 if( newFile ) {
2272 addrbook_set_file( abf, newFile );
2275 addrbook_save_data( abf );
2276 addrIndex->retVal = abf->retVal;
2277 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2278 addrbook_free_book( abf );
2279 abf = NULL;
2281 /* Create entries in address index */
2282 if( retVal ) {
2283 abf = addrbook_create_book();
2284 addrbook_set_name( abf, displayName );
2285 addrbook_set_path( abf, addrIndex->filePath );
2286 addrbook_set_file( abf, newFile );
2287 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2290 return retVal;
2294 * Read data for address index performing a conversion if necesary.
2295 * Enter: addrIndex Address index object.
2296 * return: Status code, from addrIndex->retVal.
2297 * Note: New address book files will be created in directory specified by
2298 * addrIndex. Three files will be created, for the following:
2299 * "Common addresses"
2300 * "Personal addresses"
2301 * "Gathered addresses" - a new address book.
2303 gint addrindex_read_data( AddressIndex *addrIndex ) {
2304 cm_return_val_if_fail( addrIndex != NULL, -1 );
2306 addrIndex->conversionError = FALSE;
2307 addrindex_read_file( addrIndex );
2308 if( addrIndex->retVal == MGU_SUCCESS ) {
2309 if( addrIndex->needsConversion ) {
2310 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS )
2311 addrIndex->conversionError = FALSE;
2312 else
2313 addrIndex->conversionError = TRUE;
2315 addrIndex->dirtyFlag = TRUE;
2317 return addrIndex->retVal;
2321 * Create new address books for a new address index.
2322 * Enter: addrIndex Address index object.
2323 * return: Status code, from addrIndex->retVal.
2324 * Note: New address book files will be created in directory specified by
2325 * addrIndex. Three files will be created, for the following:
2326 * "Common addresses"
2327 * "Personal addresses"
2328 * "Gathered addresses" - a new address book.
2330 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2331 gboolean flg;
2333 cm_return_val_if_fail( addrIndex != NULL, -1 );
2335 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2336 if( flg ) {
2337 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2338 addrIndex->dirtyFlag = TRUE;
2340 return addrIndex->retVal;
2343 /* **********************************************************************
2344 * New interface stuff.
2345 * ***********************************************************************
2349 * Return modified flag for specified data source.
2351 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2352 gboolean retVal = FALSE;
2353 AddressInterface *iface;
2355 if( ds == NULL ) return retVal;
2356 iface = ds->interface;
2357 if( iface == NULL ) return retVal;
2358 if( iface->getModifyFlag ) {
2359 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2361 return retVal;
2365 * Return accessed flag for specified data source.
2367 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2368 gboolean retVal = FALSE;
2369 AddressInterface *iface;
2371 if( ds == NULL ) return retVal;
2372 iface = ds->interface;
2373 if( iface == NULL ) return retVal;
2374 if( iface->getAccessFlag ) {
2375 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2377 return retVal;
2381 * Return data read flag for specified data source.
2383 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2384 gboolean retVal = TRUE;
2385 AddressInterface *iface;
2387 if( ds == NULL ) return retVal;
2388 iface = ds->interface;
2389 if( iface == NULL ) return retVal;
2390 if( iface->getReadFlag ) {
2391 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2393 return retVal;
2397 * Return status code for specified data source.
2399 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2400 gint retVal = MGU_SUCCESS;
2401 AddressInterface *iface;
2403 if( ds == NULL ) return retVal;
2404 iface = ds->interface;
2405 if( iface == NULL ) return retVal;
2406 if( iface->getStatusCode ) {
2407 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2409 return retVal;
2413 * Return data read flag for specified data source.
2415 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2416 gint retVal = MGU_SUCCESS;
2417 AddressInterface *iface;
2419 if( ds == NULL ) return retVal;
2420 iface = ds->interface;
2421 if( iface == NULL ) return retVal;
2422 if( iface->getReadData ) {
2424 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2425 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2427 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2429 return retVal;
2433 * Return data read flag for specified data source.
2435 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2436 ItemFolder *retVal = NULL;
2437 AddressInterface *iface;
2439 if( ds == NULL ) return retVal;
2440 iface = ds->interface;
2441 if( iface == NULL ) return retVal;
2442 if( iface->getRootFolder ) {
2443 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2445 return retVal;
2449 * Return name for specified data source.
2451 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2452 gchar *retVal = FALSE;
2453 AddressInterface *iface;
2455 if( ds == NULL ) return retVal;
2456 iface = ds->interface;
2457 if( iface == NULL ) return retVal;
2458 if( iface->getName ) {
2459 retVal = ( iface->getName ) ( ds->rawDataSource );
2461 return retVal;
2465 * Set the access flag inside the data source.
2467 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2468 AddressInterface *iface;
2470 if( ds == NULL ) return;
2471 iface = ds->interface;
2472 if( iface == NULL ) return;
2473 if( iface->setAccessFlag ) {
2474 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2479 * Return read only flag for specified data source.
2481 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2482 AddressInterface *iface;
2483 if( ds == NULL ) return TRUE;
2484 iface = ds->interface;
2485 if( iface == NULL ) return TRUE;
2486 return iface->readOnly;
2490 * Return list of all persons for specified data source.
2492 static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2493 GList *retVal = NULL;
2494 AddressInterface *iface;
2496 if( ds == NULL ) return retVal;
2497 iface = ds->interface;
2498 if( iface == NULL ) return retVal;
2499 if( iface->getAllPersons ) {
2500 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2502 return retVal;
2506 * Return list of all groups for specified data source.
2508 static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2509 GList *retVal = NULL;
2510 AddressInterface *iface;
2512 if( ds == NULL ) return retVal;
2513 iface = ds->interface;
2514 if( iface == NULL ) return retVal;
2515 if( iface->getAllGroups ) {
2516 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2518 return retVal;
2521 /* **********************************************************************
2522 * Address search stuff.
2523 * ***********************************************************************
2527 * Setup or register the dynamic search that will be performed. The search
2528 * is registered with the query manager.
2530 * \param searchTerm Search term. A private copy will be made.
2531 * \param callBackEntry Callback function that should be called when
2532 * each entry is received.
2533 * \param callBackEnd Callback function that should be called when
2534 * search has finished running.
2535 * \return ID allocated to query that will be executed.
2537 gint addrindex_setup_search(
2538 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2540 QueryRequest *req;
2541 gint queryID;
2543 /* Set up a dynamic address query */
2544 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2545 queryID = req->queryID;
2546 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2548 /* g_print( "***> query ID ::%d::\n", queryID ); */
2549 return queryID;
2552 #ifdef USE_LDAP
2555 * Function prototypes (not in header file or circular reference errors are
2556 * encountered!)
2558 LdapQuery *ldapsvr_new_dynamic_search(
2559 LdapServer *server, QueryRequest *req );
2560 LdapQuery *ldapsvr_new_explicit_search(
2561 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2562 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2564 #endif
2567 * Execute the previously registered dynamic search.
2569 * \param req Address query object to execute.
2570 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2571 * failed.
2573 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2574 AddressInterface *iface;
2575 AddressDataSource *ds;
2576 GList *nodeIf;
2577 GList *nodeDS;
2578 gint type;
2580 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2581 nodeIf = _addressIndex_->searchOrder;
2582 while( nodeIf ) {
2583 iface = nodeIf->data;
2584 nodeIf = g_list_next( nodeIf );
2586 if( ! iface->useInterface ) {
2587 continue;
2589 if( ! iface->externalQuery ) {
2590 continue;
2593 type = iface->type;
2594 nodeDS = iface->listSource;
2595 while( nodeDS ) {
2596 ds = nodeDS->data;
2597 nodeDS = g_list_next( nodeDS );
2598 #ifdef USE_LDAP
2599 if( type == ADDR_IF_LDAP ) {
2600 LdapServer *server;
2601 LdapQuery *qry;
2603 server = ds->rawDataSource;
2604 if( ! server->searchFlag ) {
2605 continue;
2607 if( ldapsvr_reuse_previous( server, req ) ) {
2608 continue;
2611 /* Start a new dynamic search */
2612 qry = ldapsvr_new_dynamic_search( server, req );
2613 if( qry ) {
2614 ldapsvr_execute_query( server, qry );
2617 #endif
2620 return TRUE;
2624 * Stop the previously registered search.
2626 * \param queryID ID of search query to stop.
2628 void addrindex_stop_search( const gint queryID ){
2629 QueryRequest *req;
2630 AddrQueryObject *aqo;
2631 GList *node;
2633 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2634 /* If query ID does not match, search has not been setup */
2635 req = qrymgr_find_request( queryID );
2636 if( req == NULL ) {
2637 return;
2640 /* Stop all queries that were associated with request */
2641 node = req->queryList;
2642 while( node ) {
2643 aqo = node->data;
2644 #ifdef USE_LDAP
2645 if( aqo->queryType == ADDRQUERY_LDAP ) {
2646 LdapQuery *qry = ( LdapQuery * ) aqo;
2647 ldapqry_set_stop_flag( qry, TRUE );
2649 #endif
2650 node->data = NULL;
2651 node = g_list_next( node );
2654 /* Delete query request */
2655 qrymgr_delete_request( queryID );
2659 * Setup or register the explicit search that will be performed. The search is
2660 * registered with the query manager.
2662 * \param ds Data source to search.
2663 * \param searchTerm Search term to locate.
2664 * \param folder Folder to receive search results; may be NULL.
2665 * \param callbackEnd Function to call when search has terminated.
2666 * \param callbackEntry Function to called for each entry processed.
2667 * \return ID allocated to query that will be executed.
2669 gint addrindex_setup_explicit_search(
2670 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2671 void *callBackEnd, void *callBackEntry )
2673 QueryRequest *req;
2674 gint queryID;
2675 gchar *name;
2676 gchar *mySearch;
2678 /* Name the query */
2679 name = g_strdup_printf( "Search '%s'", searchTerm );
2681 /* Set up query request */
2682 if (!strcmp(searchTerm, "*"))
2683 mySearch = g_strdup("*@");
2684 else
2685 mySearch = g_strdup(searchTerm);
2687 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2689 g_free(mySearch);
2691 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2692 queryID = req->queryID;
2694 if( ds->type == ADDR_IF_LDAP ) {
2695 #ifdef USE_LDAP
2696 LdapServer *server;
2698 server = ds->rawDataSource;
2699 ldapsvr_new_explicit_search( server, req, folder );
2700 #endif
2702 else {
2703 qrymgr_delete_request( queryID );
2704 queryID = 0;
2706 g_free( name );
2708 return queryID;
2712 * Execute the previously registered explicit search.
2714 * \param req Address query request object to execute.
2715 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2716 * failed.
2718 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2719 gboolean retVal;
2720 AddrQueryObject *aqo;
2722 retVal = FALSE;
2724 /* Note: there should only be one query in the list. */
2725 aqo = req->queryList->data;
2726 #ifdef USE_LDAP
2727 if( aqo->queryType == ADDRQUERY_LDAP ) {
2728 LdapServer *server;
2729 LdapQuery *qry;
2731 qry = ( LdapQuery * ) aqo;
2732 server = qry->server;
2734 /* Start the search */
2735 retVal = TRUE;
2736 ldapsvr_execute_query( server, qry );
2738 #endif
2739 return retVal;
2743 * Start the previously registered search.
2745 * \param queryID ID of search query to be executed.
2746 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2747 * failed.
2749 gboolean addrindex_start_search( const gint queryID ) {
2750 gboolean retVal;
2751 QueryRequest *req;
2752 AddrSearchType searchType;
2754 retVal = FALSE;
2755 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2756 req = qrymgr_find_request( queryID );
2757 if( req == NULL ) {
2758 return retVal;
2761 searchType = req->searchType;
2762 if( searchType == ADDRSEARCH_DYNAMIC ) {
2763 retVal = addrindex_start_dynamic( req );
2765 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2766 retVal = addrindex_start_explicit( req );
2769 return retVal;
2773 * Remove results (folder and data) for specified data source and folder.
2774 * \param ds Data source to process.
2775 * \param folder Results folder to remove.
2777 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2778 AddrBookBase *adbase;
2779 gint queryID = 0;
2781 /* g_print( "addrindex_remove_results/start\n" ); */
2783 /* Test for folder */
2784 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2785 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2786 adbase = ( AddrBookBase * ) ds->rawDataSource;
2787 if( adbase == NULL ) return;
2789 /* Hide folder to prevent re-display */
2790 addritem_folder_set_hidden( folder, TRUE );
2792 if( ds->type == ADDR_IF_LDAP ) {
2793 #ifdef USE_LDAP
2794 LdapQuery *qry;
2795 gboolean delFlag;
2797 qry = ( LdapQuery * ) folder->folderData;
2798 queryID = ADDRQUERY_ID(qry);
2799 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2800 delFlag = ldapquery_remove_results( qry );
2801 if (delFlag) {
2802 ldapqry_free( qry );
2804 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2806 if( delFlag ) {
2807 g_print( "delFlag IS-TRUE\n" );
2809 else {
2810 g_print( "delFlag IS-FALSE\n" );
2813 #endif
2815 /* g_print( "addrindex_remove_results/end\n" ); */
2817 /* Delete query request */
2818 if( queryID > 0 ) {
2819 qrymgr_delete_request( queryID );
2823 /* **********************************************************************
2824 * Address completion stuff.
2825 * ***********************************************************************
2828 static void addrindex_load_completion_load_persons(
2829 gint (*callBackFunc) ( const gchar *, const gchar *,
2830 const gchar *, const gchar *, GList * ),
2831 AddressDataSource *ds)
2833 GList *listP, *nodeP;
2834 GList *nodeM;
2835 gchar *sName;
2837 /* Read address book */
2838 if( addrindex_ds_get_modify_flag( ds ) ) {
2839 addrindex_ds_read_data( ds );
2842 if( ! addrindex_ds_get_read_flag( ds ) ) {
2843 addrindex_ds_read_data( ds );
2846 /* Get all groups */
2847 listP = addrindex_ds_get_all_groups( ds );
2848 nodeP = listP;
2849 while( nodeP ) {
2850 ItemGroup *group = nodeP->data;
2851 GList *emails = NULL;
2852 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2853 ItemEMail *email = nodeM->data;
2854 if (email->address)
2855 emails = g_list_append(emails, email);
2857 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2858 NULL, NULL, emails );
2859 nodeP = g_list_next( nodeP );
2862 /* Free up the list */
2863 g_list_free( listP );
2864 /* Get all persons */
2865 listP = addrindex_ds_get_all_persons( ds );
2866 nodeP = listP;
2867 while( nodeP ) {
2868 ItemPerson *person = nodeP->data;
2869 nodeM = person->listEMail;
2871 /* Figure out name to use */
2872 sName = ADDRITEM_NAME(person);
2873 if( sName == NULL || *sName == '\0' ) {
2874 sName = person->nickName;
2877 /* Process each E-Mail address */
2878 while( nodeM ) {
2879 ItemEMail *email = nodeM->data;
2881 callBackFunc( sName, email->address, person->nickName,
2882 ADDRITEM_NAME(email), NULL );
2884 nodeM = g_list_next( nodeM );
2886 nodeP = g_list_next( nodeP );
2889 /* Free up the list */
2890 g_list_free( listP );
2894 * This function is used by the address completion function to load
2895 * addresses for all non-external address book interfaces.
2897 * \param callBackFunc Function to be called when an address is
2898 * to be loaded.
2899 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2900 * or "Any", assume the whole addressbook
2901 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2904 gboolean addrindex_load_completion(
2905 gint (*callBackFunc) ( const gchar *, const gchar *,
2906 const gchar *, const gchar *, GList * ),
2907 gchar *folderpath )
2909 GList *nodeIf, *nodeDS;
2911 if( folderpath != NULL ) {
2912 AddressDataSource *book;
2913 ItemFolder* folder;
2915 /* split the folder path we've received, we'll try to match this path, subpath by
2916 subpath against the book/folder structure in order and restrict loading of
2917 addresses to that subpart (if matches). book/folder path must exist and
2918 folderpath must not be empty or NULL */
2920 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2921 g_warning("addrindex_load_completion: folder path '%s' doesn't exist", folderpath);
2922 return FALSE;
2925 if( folder != NULL ) {
2927 GList *items;
2928 GList *nodeM;
2929 gchar *sName;
2930 ItemPerson *person;
2932 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2934 /* Load email addresses */
2935 items = addritem_folder_get_person_list( folder );
2936 for( ; items != NULL; items = g_list_next( items ) ) {
2937 person = items->data;
2938 nodeM = person->listEMail;
2940 /* Figure out name to use */
2941 sName = ADDRITEM_NAME(person);
2942 if( sName == NULL || *sName == '\0' ) {
2943 sName = person->nickName;
2946 /* Process each E-Mail address */
2947 while( nodeM ) {
2948 ItemEMail *email = nodeM->data;
2950 callBackFunc( sName, email->address, person->nickName,
2951 ADDRITEM_NAME(email), NULL );
2953 nodeM = g_list_next( nodeM );
2956 /* Free up the list */
2957 mgu_clear_list( items );
2958 g_list_free( items );
2960 return TRUE;
2962 } else {
2964 if( book != NULL ) {
2966 AddressBookFile *abf = book->rawDataSource;
2968 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf?abf->fileName:"(null)");
2970 addrindex_load_completion_load_persons( callBackFunc, book );
2972 return TRUE;
2974 } else {
2975 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer");
2978 return FALSE;
2980 } else {
2982 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2983 while( nodeIf ) {
2984 AddressInterface *iface = nodeIf->data;
2986 nodeIf = g_list_next( nodeIf );
2988 if( ! iface->useInterface || iface->externalQuery )
2989 continue;
2991 nodeDS = iface->listSource;
2992 while( nodeDS ) {
2993 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
2994 nodeDS = g_list_next( nodeDS );
2999 return TRUE;
3003 * This function can be used to collect information about
3004 * addressbook entries that contain a specific attribute.
3006 * \param attr Name of attribute to look for
3007 * \param callBackFunc Function to be called when a matching attribute was found
3008 * \return <i>TRUE</i>
3010 gboolean addrindex_load_person_attribute(
3011 const gchar *attr,
3012 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
3014 AddressDataSource *ds;
3015 GList *nodeIf, *nodeDS;
3016 GList *listP, *nodeP;
3017 GList *nodeA;
3019 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3020 while( nodeIf ) {
3021 gchar *cur_bname;
3022 AddressInterface *iface = nodeIf->data;
3024 nodeIf = g_list_next( nodeIf );
3026 if( ! iface->useInterface || iface->externalQuery )
3027 continue;
3029 nodeDS = iface->listSource;
3030 while( nodeDS ) {
3031 ds = nodeDS->data;
3033 /* Read address book */
3034 if( addrindex_ds_get_modify_flag( ds ) ) {
3035 addrindex_ds_read_data( ds );
3038 if( ! addrindex_ds_get_read_flag( ds ) ) {
3039 addrindex_ds_read_data( ds );
3042 /* Check addressbook name */
3043 cur_bname = addrindex_ds_get_name( ds );
3045 /* Get all persons */
3046 listP = addrindex_ds_get_all_persons( ds );
3047 nodeP = listP;
3048 while( nodeP ) {
3049 ItemPerson *person = nodeP->data;
3051 /* Return all ItemPerson's if attr is NULL */
3052 if( attr == NULL ) {
3053 callBackFunc(person, cur_bname);
3056 /* Return ItemPerson's with specific attribute */
3057 else {
3058 nodeA = person->listAttrib;
3059 /* Process each User Attribute */
3060 while( nodeA ) {
3061 UserAttribute *attrib = nodeA->data;
3062 if( attrib->name &&
3063 !strcmp( attrib->name,attr ) ) {
3064 callBackFunc(person, cur_bname);
3066 nodeA = g_list_next( nodeA );
3069 nodeP = g_list_next( nodeP );
3071 /* Free up the list */
3072 g_list_free( listP );
3074 nodeDS = g_list_next( nodeDS );
3077 return TRUE;
3081 * This function can be used to collect information about
3082 * addressbook entries
3084 * \param callBackFunc Function to be called for each ItemPerson
3085 * \return <i>TRUE</i>
3087 gboolean addrindex_load_person_ds( gint (*callBackFunc)
3088 ( ItemPerson *, AddressDataSource * ) )
3090 AddressDataSource *ds;
3091 GList *nodeIf, *nodeDS;
3092 GList *listP, *nodeP;
3094 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3095 while( nodeIf ) {
3096 AddressInterface *iface = nodeIf->data;
3098 nodeIf = g_list_next( nodeIf );
3100 if( ! iface->useInterface || iface->externalQuery )
3101 continue;
3103 nodeDS = iface->listSource;
3104 while( nodeDS ) {
3105 ds = nodeDS->data;
3107 /* Read address book */
3108 if( addrindex_ds_get_modify_flag( ds ) ) {
3109 addrindex_ds_read_data( ds );
3112 if( ! addrindex_ds_get_read_flag( ds ) ) {
3113 addrindex_ds_read_data( ds );
3116 /* Get all persons */
3117 listP = addrindex_ds_get_all_persons( ds );
3118 nodeP = listP;
3119 while( nodeP ) {
3120 ItemPerson *person = nodeP->data;
3122 callBackFunc(person, ds);
3123 nodeP = g_list_next( nodeP );
3125 /* Free up the list */
3126 g_list_free( listP );
3128 nodeDS = g_list_next( nodeDS );
3131 return TRUE;
3134 gchar *addrindex_get_picture_file(const gchar *emailaddr)
3136 AddressDataSource *ds;
3137 GList *nodeIf, *nodeDS;
3138 GList *listP, *nodeP;
3139 gboolean found = FALSE;
3140 gchar *filename = NULL;
3141 gchar *raw_addr = NULL;
3143 if (!emailaddr)
3144 return NULL;
3146 Xstrdup_a(raw_addr, emailaddr, return NULL);
3147 extract_address(raw_addr);
3149 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3150 while( nodeIf ) {
3151 AddressInterface *iface = nodeIf->data;
3153 nodeIf = g_list_next( nodeIf );
3155 if( ! iface->useInterface || iface->externalQuery )
3156 continue;
3158 nodeDS = iface->listSource;
3159 while( nodeDS && !found) {
3160 ds = nodeDS->data;
3162 /* Read address book */
3163 if( addrindex_ds_get_modify_flag( ds ) ) {
3164 addrindex_ds_read_data( ds );
3167 if( ! addrindex_ds_get_read_flag( ds ) ) {
3168 addrindex_ds_read_data( ds );
3171 /* Get all persons */
3172 listP = addrindex_ds_get_all_persons( ds );
3173 nodeP = listP;
3174 while( nodeP ) {
3175 GList *nodeM;
3176 ItemPerson *person = nodeP->data;
3177 nodeM = person->listEMail;
3178 while(nodeM) {
3179 ItemEMail *email = nodeM->data;
3180 if (email->address && !strcasecmp(raw_addr, email->address)) {
3181 found = TRUE;
3182 filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S,
3183 ADDRBOOK_DIR, G_DIR_SEPARATOR_S,
3184 person->picture, ".png", NULL );
3185 break;
3187 nodeM = nodeM->next;
3189 nodeP = g_list_next( nodeP );
3191 /* Free up the list */
3192 g_list_free( listP );
3194 nodeDS = g_list_next( nodeDS );
3198 return filename;
3202 * End of Source.