Fix error creation and warning
[claws.git] / src / addrindex.c
blob1395bf0bb659458386311557e8fa0fd7865d0285
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2022 the Claws Mail team and Match Grun
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/>.
20 * General functions for accessing address index file.
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #include "claws-features.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"
44 #include "passwordstore.h"
45 #include "file-utils.h"
47 #ifndef DEV_STANDALONE
48 #include "prefs_gtk.h"
49 #include "codeconv.h"
50 #endif
52 #include "vcard.h"
54 #ifdef USE_JPILOT
55 #include "jpilot.h"
56 #endif
58 #ifdef USE_LDAP
59 #include "ldapserver.h"
60 #include "ldapctrl.h"
61 #include "ldapquery.h"
62 #include "ldapupdate.h"
63 #include "ldaputil.h"
64 #endif
66 #ifdef G_OS_WIN32
67 #undef interface
68 #endif
70 #define TAG_ADDRESS_INDEX "addressbook"
72 #define TAG_IF_ADDRESS_BOOK "book_list"
73 #define TAG_IF_VCARD "vcard_list"
74 #define TAG_IF_JPILOT "jpilot_list"
75 #define TAG_IF_LDAP "ldap_list"
77 #define TAG_DS_ADDRESS_BOOK "book"
78 #define TAG_DS_VCARD "vcard"
79 #define TAG_DS_JPILOT "jpilot"
80 #define TAG_DS_LDAP "server"
82 /* XML Attribute names */
83 #define ATTAG_BOOK_NAME "name"
84 #define ATTAG_BOOK_FILE "file"
86 #define ATTAG_VCARD_NAME "name"
87 #define ATTAG_VCARD_FILE "file"
89 #define ATTAG_JPILOT_NAME "name"
90 #define ATTAG_JPILOT_FILE "file"
91 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
92 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
93 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
94 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
95 #define ATTAG_JPILOT_CUSTOM "custom-"
97 #define ATTAG_LDAP_NAME "name"
98 #define ATTAG_LDAP_HOST "host"
99 #define ATTAG_LDAP_PORT "port"
100 #define ATTAG_LDAP_BASE_DN "base-dn"
101 #define ATTAG_LDAP_BIND_DN "bind-dn"
102 #define ATTAG_LDAP_BIND_PASS "bind-pass"
103 #define ATTAG_LDAP_CRITERIA "criteria"
104 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
105 #define ATTAG_LDAP_TIMEOUT "timeout"
106 #define ATTAG_LDAP_MAX_AGE "max-age"
107 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
108 #define ATTAG_LDAP_MATCH_OPT "match-opt"
109 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
110 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
112 #define ELTAG_LDAP_ATTR_SRCH "attribute"
113 #define ATTAG_LDAP_ATTR_NAME "name"
115 /* Attribute values */
116 #define ATVAL_BOOLEAN_YES "yes"
117 #define ATVAL_BOOLEAN_NO "no"
118 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
119 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
121 /* New attributes */
122 #define ATTAG_LDAP_DEFAULT "default"
124 #define DISP_NEW_COMMON _("Common addresses")
125 #define DISP_NEW_PERSONAL _("Personal addresses")
127 /* Old address book */
128 #define TAG_IF_OLD_COMMON "common_address"
129 #define TAG_IF_OLD_PERSONAL "personal_address"
131 #define DISP_OLD_COMMON _("Common address")
132 #define DISP_OLD_PERSONAL _("Personal address")
135 * Singleton object.
137 static AddressIndex *_addressIndex_ = NULL;
140 * Define attribute name-value pair.
142 typedef struct _AddressIfAttr AddressIfAttrib;
143 struct _AddressIfAttr {
144 gchar *name;
145 gchar *value;
148 static AddressDataSource *addrindex_create_datasource ( AddressIfType ifType );
150 static GList *addrindex_ds_get_all_persons ( AddressDataSource *ds );
151 static GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
152 static AddressDataSource *addrindex_get_datasource ( AddressIndex *addrIndex,
153 const gchar *cacheID );
154 static AddressInterface *addrindex_get_interface ( AddressIndex *addrIndex,
155 AddressIfType ifType );
156 static gint addrindex_write_to ( AddressIndex *addrIndex,
157 const gchar *newFile );
160 * Define DOM fragment.
162 typedef struct _AddressIfFrag AddressIfFragment;
163 struct _AddressIfFrag {
164 AddressBookType type;
165 AddressCache *addressCache;
166 gchar *name;
167 GList *children;
168 GList *attributes;
172 * Build interface with default values.
174 * \param type Interface type.
175 * \param name Interface name.
176 * \param tagIf XML tag name for interface in address index file.
177 * \param tagDS XML tag name for datasource in address index file.
178 * \return Address interface object.
180 static AddressInterface *addrindex_create_interface(
181 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
183 AddressInterface *iface = g_new0( AddressInterface, 1 );
185 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
186 ADDRITEM_ID(iface) = NULL;
187 ADDRITEM_NAME(iface) = g_strdup( name );
188 ADDRITEM_PARENT(iface) = NULL;
189 ADDRITEM_SUBTYPE(iface) = type;
190 iface->type = type;
191 iface->name = g_strdup( name );
192 iface->listTag = g_strdup( tagIf );
193 iface->itemTag = g_strdup( tagDS );
194 iface->legacyFlag = FALSE;
195 iface->haveLibrary = TRUE;
196 iface->useInterface = TRUE;
197 iface->readOnly = TRUE;
199 /* Set callbacks to NULL values - override for each interface */
200 iface->getAccessFlag = NULL;
201 iface->getModifyFlag = NULL;
202 iface->getReadFlag = NULL;
203 iface->getStatusCode = NULL;
204 iface->getReadData = NULL;
205 iface->getRootFolder = NULL;
206 iface->getListFolder = NULL;
207 iface->getListPerson = NULL;
208 iface->getAllPersons = NULL;
209 iface->getAllGroups = NULL;
210 iface->getName = NULL;
211 iface->listSource = NULL;
213 /* Search stuff */
214 iface->externalQuery = FALSE;
215 iface->searchOrder = 0; /* Ignored */
216 iface->startSearch = NULL;
217 iface->stopSearch = NULL;
219 return iface;
223 * Build table of of all address book interfaces.
224 * \param addrIndex Address index object.
226 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
227 AddressInterface *iface;
229 /* Create intrinsic XML address book interface */
230 iface = addrindex_create_interface(
231 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
232 TAG_DS_ADDRESS_BOOK );
233 iface->readOnly = FALSE;
234 iface->getModifyFlag = ( void * ) addrbook_get_modified;
235 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
236 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
237 iface->getStatusCode = ( void * ) addrbook_get_status;
238 iface->getReadData = ( void * ) addrbook_read_data;
239 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
240 iface->getListFolder = ( void * ) addrbook_get_list_folder;
241 iface->getListPerson = ( void * ) addrbook_get_list_person;
242 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
243 iface->getAllGroups = ( void * ) addrbook_get_all_groups;
244 iface->getName = ( void * ) addrbook_get_name;
245 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
246 iface->searchOrder = 0;
248 /* Add to list of interfaces in address book */
249 addrIndex->interfaceList =
250 g_list_append( addrIndex->interfaceList, iface );
251 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
253 /* Create vCard interface */
254 iface = addrindex_create_interface(
255 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
256 iface->getModifyFlag = ( void * ) vcard_get_modified;
257 iface->getAccessFlag = ( void * ) vcard_get_accessed;
258 iface->getReadFlag = ( void * ) vcard_get_read_flag;
259 iface->getStatusCode = ( void * ) vcard_get_status;
260 iface->getReadData = ( void * ) vcard_read_data;
261 iface->getRootFolder = ( void * ) vcard_get_root_folder;
262 iface->getListFolder = ( void * ) vcard_get_list_folder;
263 iface->getListPerson = ( void * ) vcard_get_list_person;
264 iface->getAllPersons = ( void * ) vcard_get_all_persons;
265 iface->getName = ( void * ) vcard_get_name;
266 iface->setAccessFlag = ( void * ) vcard_set_accessed;
267 iface->searchOrder = 0;
268 addrIndex->interfaceList =
269 g_list_append( addrIndex->interfaceList, iface );
270 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
272 /* Create JPilot interface */
273 iface = addrindex_create_interface(
274 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
275 TAG_DS_JPILOT );
276 #ifdef USE_JPILOT
277 iface->haveLibrary = jpilot_test_pilot_lib();
278 iface->useInterface = iface->haveLibrary;
279 iface->getModifyFlag = ( void * ) jpilot_get_modified;
280 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
281 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
282 iface->getStatusCode = ( void * ) jpilot_get_status;
283 iface->getReadData = ( void * ) jpilot_read_data;
284 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
285 iface->getListFolder = ( void * ) jpilot_get_list_folder;
286 iface->getListPerson = ( void * ) jpilot_get_list_person;
287 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
288 iface->getName = ( void * ) jpilot_get_name;
289 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
290 iface->searchOrder = 0;
291 #else
292 iface->useInterface = FALSE;
293 iface->haveLibrary = FALSE;
294 #endif
295 addrIndex->interfaceList =
296 g_list_append( addrIndex->interfaceList, iface );
297 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
299 /* Create LDAP interface */
300 iface = addrindex_create_interface(
301 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
302 #ifdef USE_LDAP
303 iface->readOnly = FALSE;
304 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
305 iface->haveLibrary = ldaputil_test_ldap_lib();
306 iface->useInterface = iface->haveLibrary;
307 iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
308 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
309 iface->getReadFlag = ( void * ) ldapsvr_get_read_flag;
310 iface->getStatusCode = ( void * ) ldapsvr_get_status;
311 iface->getReadData = ( void * ) ldapsvr_read_data;
312 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
313 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
314 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
315 iface->getName = ( void * ) ldapsvr_get_name;
316 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
317 iface->externalQuery = TRUE;
318 iface->searchOrder = 1;
319 #else
320 iface->useInterface = FALSE;
321 iface->haveLibrary = FALSE;
322 #endif
323 addrIndex->interfaceList =
324 g_list_append( addrIndex->interfaceList, iface );
325 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
327 /* Two old legacy data sources (pre 0.7.0) */
328 iface = addrindex_create_interface(
329 ADDR_IF_COMMON, "Old Address - common",
330 TAG_IF_OLD_COMMON, NULL );
331 iface->legacyFlag = TRUE;
332 addrIndex->interfaceList =
333 g_list_append( addrIndex->interfaceList, iface );
334 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
336 iface = addrindex_create_interface(
337 ADDR_IF_COMMON, "Old Address - personal",
338 TAG_IF_OLD_PERSONAL, NULL );
339 iface->legacyFlag = TRUE;
340 addrIndex->interfaceList =
341 g_list_append( addrIndex->interfaceList, iface );
342 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
347 * Free DOM fragment.
348 * \param fragment Fragment to free.
350 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
351 GList *node;
353 /* Free children */
354 node = fragment->children;
355 while( node ) {
356 AddressIfFragment *child = node->data;
357 addrindex_free_fragment( child );
358 node->data = NULL;
359 node = g_list_next( node );
361 g_list_free( fragment->children );
363 /* Free attributes */
364 node = fragment->attributes;
365 while( node ) {
366 AddressIfAttrib *nv = node->data;
367 g_free( nv->name );
368 g_free( nv->value );
369 g_free( nv );
370 node->data = NULL;
371 node = g_list_next( node );
373 g_list_free( fragment->attributes );
375 g_free( fragment->name );
376 fragment->name = NULL;
377 fragment->attributes = NULL;
378 fragment->children = NULL;
380 g_free( fragment );
384 * Create a new data source.
385 * \param ifType Interface type to create.
386 * \return Initialized data source.
388 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
389 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
391 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
392 ADDRITEM_ID(ds) = NULL;
393 ADDRITEM_NAME(ds) = NULL;
394 ADDRITEM_PARENT(ds) = NULL;
395 ADDRITEM_SUBTYPE(ds) = 0;
396 ds->type = ifType;
397 ds->rawDataSource = NULL;
398 ds->interface = NULL;
399 return ds;
403 * Free up data source.
404 * \param ds Data source to free.
406 void addrindex_free_datasource( AddressDataSource *ds ) {
407 AddressInterface *iface;
409 cm_return_if_fail( ds != NULL );
411 iface = ds->interface;
412 if( ds->rawDataSource != NULL ) {
413 if( iface != NULL ) {
414 if( iface->useInterface ) {
415 if( iface->type == ADDR_IF_BOOK ) {
416 AddressBookFile *abf = ds->rawDataSource;
417 addrbook_free_book( abf );
419 else if( iface->type == ADDR_IF_VCARD ) {
420 VCardFile *vcf = ds->rawDataSource;
421 vcard_free( vcf );
423 #ifdef USE_JPILOT
424 else if( iface->type == ADDR_IF_JPILOT ) {
425 JPilotFile *jpf = ds->rawDataSource;
426 jpilot_free( jpf );
428 #endif
429 #ifdef USE_LDAP
430 else if( iface->type == ADDR_IF_LDAP ) {
431 LdapServer *server = ds->rawDataSource;
432 ldapsvr_free( server );
434 #endif
435 else {
438 else {
439 AddressIfFragment *fragment = ds->rawDataSource;
440 addrindex_free_fragment( fragment );
445 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
446 ADDRITEM_ID(ds) = NULL;
447 ADDRITEM_NAME(ds) = NULL;
448 ADDRITEM_PARENT(ds) = NULL;
449 ADDRITEM_SUBTYPE(ds) = 0;
450 ds->type = ADDR_IF_NONE;
451 ds->interface = NULL;
452 ds->rawDataSource = NULL;
454 g_free( ds );
458 * Free up all data sources for specified interface.
459 * \param iface Address interface to process.
461 static void addrindex_free_all_datasources( AddressInterface *iface ) {
462 GList *node = iface->listSource;
463 while( node ) {
464 AddressDataSource *ds = node->data;
465 addrindex_free_datasource( ds );
466 node->data = NULL;
467 node = g_list_next( node );
472 * Free up specified interface.
473 * \param iface Interface to process.
475 static void addrindex_free_interface( AddressInterface *iface ) {
476 /* Free up data sources */
477 addrindex_free_all_datasources( iface );
478 g_list_free( iface->listSource );
480 /* Free internal storage */
481 g_free( ADDRITEM_ID(iface) );
482 g_free( ADDRITEM_NAME(iface) );
483 g_free( iface->name );
484 g_free( iface->listTag );
485 g_free( iface->itemTag );
487 /* Clear all pointers */
488 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
489 ADDRITEM_ID(iface) = NULL;
490 ADDRITEM_NAME(iface) = NULL;
491 ADDRITEM_PARENT(iface) = NULL;
492 ADDRITEM_SUBTYPE(iface) = 0;
493 iface->type = ADDR_IF_NONE;
494 iface->name = NULL;
495 iface->listTag = NULL;
496 iface->itemTag = NULL;
497 iface->legacyFlag = FALSE;
498 iface->useInterface = FALSE;
499 iface->haveLibrary = FALSE;
500 iface->listSource = NULL;
502 /* Search stuff */
503 iface->searchOrder = 0;
504 iface->startSearch = NULL;
505 iface->stopSearch = NULL;
507 g_free( iface );
511 * Return cache ID for specified data source.
513 * \param addrIndex Address index.
514 * \param ds Data source.
515 * \return ID or NULL if not found. This should be <code>g_free()</code>
516 * when done.
518 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
519 gchar *cacheID = NULL;
520 AddrBookBase *adbase;
521 AddressCache *cache;
523 cm_return_val_if_fail( addrIndex != NULL, NULL );
524 cm_return_val_if_fail( ds != NULL, NULL );
526 adbase = ( AddrBookBase * ) ds->rawDataSource;
527 if( adbase ) {
528 cache = adbase->addressCache;
529 if( cache ) {
530 cacheID = g_strdup( cache->cacheID );
534 return cacheID;
538 * Return reference to data source for specified cacheID.
539 * \param addrIndex Address index.
540 * \param cacheID ID.
541 * \return Data source, or NULL if not found.
543 static AddressDataSource *addrindex_get_datasource(
544 AddressIndex *addrIndex, const gchar *cacheID )
546 cm_return_val_if_fail( addrIndex != NULL, NULL );
547 cm_return_val_if_fail( cacheID != NULL, NULL );
548 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
552 * Return reference to address cache for specified cacheID.
553 * \param addrIndex Address index.
554 * \param cacheID ID.
555 * \return Address cache, or NULL if not found.
557 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
558 AddressDataSource *ds;
559 AddrBookBase *adbase;
560 AddressCache *cache;
562 cm_return_val_if_fail( addrIndex != NULL, NULL );
563 cm_return_val_if_fail( cacheID != NULL, NULL );
565 cache = NULL;
566 ds = addrindex_get_datasource( addrIndex, cacheID );
567 if( ds ) {
568 adbase = ( AddrBookBase * ) ds->rawDataSource;
569 cache = adbase->addressCache;
571 return cache;
575 * Add data source into hash table.
576 * \param addrIndex Address index.
577 * \param ds Data source.
579 static void addrindex_hash_add_cache(
580 AddressIndex *addrIndex, AddressDataSource *ds )
582 gchar *cacheID;
584 cacheID = addrindex_get_cache_id( addrIndex, ds );
585 if( cacheID ) {
586 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
591 * Free hash table callback function.
593 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
594 g_free( key );
595 key = NULL;
596 value = NULL;
597 return TRUE;
601 * Free hash table of address cache items.
603 static void addrindex_free_cache_hash( GHashTable *table ) {
604 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
605 g_hash_table_destroy( table );
609 * Remove data source from internal hashtable.
610 * \param addrIndex Address index.
611 * \param ds Data source to remove.
613 static void addrindex_hash_remove_cache(
614 AddressIndex *addrIndex, AddressDataSource *ds )
616 gchar *cacheID;
618 cacheID = addrindex_get_cache_id( addrIndex, ds );
619 if( cacheID ) {
620 g_hash_table_remove( addrIndex->hashCache, cacheID );
621 g_free( cacheID );
622 cacheID = NULL;
627 * Create a new address index. This is created as a singleton object.
628 * \return Initialized address index object.
630 AddressIndex *addrindex_create_index( void ) {
631 AddressIndex *index;
633 if( _addressIndex_ == NULL ) {
634 index = g_new0( AddressIndex, 1 );
635 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
636 ADDRITEM_ID(index) = NULL;
637 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
638 ADDRITEM_PARENT(index) = NULL;
639 ADDRITEM_SUBTYPE(index) = 0;
640 index->filePath = NULL;
641 index->fileName = NULL;
642 index->retVal = MGU_SUCCESS;
643 index->needsConversion = FALSE;
644 index->wasConverted = FALSE;
645 index->conversionError = FALSE;
646 index->interfaceList = NULL;
647 index->lastType = ADDR_IF_NONE;
648 index->dirtyFlag = FALSE;
649 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
650 index->loadedFlag = FALSE;
651 index->searchOrder = NULL;
652 addrindex_build_if_list( index );
653 _addressIndex_ = index;
655 return _addressIndex_;
659 * Property - Specify file path to address index file.
660 * \param addrIndex Address index.
661 * \param value Path to index file.
663 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
664 cm_return_if_fail( addrIndex != NULL );
665 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
669 * Property - Specify file name to address index file.
670 * \param addrIndex Address index.
671 * \param value File name.
673 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
674 cm_return_if_fail( addrIndex != NULL );
675 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
679 * Return list of address interfaces.
680 * \param addrIndex Address index.
681 * \return List of address interfaces.
683 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
684 cm_return_val_if_fail( addrIndex != NULL, NULL );
685 return addrIndex->interfaceList;
689 * Perform any other initialization of address index.
691 void addrindex_initialize( void ) {
692 qrymgr_initialize();
693 addrcompl_initialize();
697 * Perform any other teardown of address index.
699 void addrindex_teardown( void ) {
700 addrcompl_teardown();
701 qrymgr_teardown();
705 * Free up address index.
706 * \param addrIndex Address index.
708 void addrindex_free_index( AddressIndex *addrIndex ) {
709 GList *node;
711 cm_return_if_fail( addrIndex != NULL );
713 /* Search stuff */
714 g_list_free( addrIndex->searchOrder );
715 addrIndex->searchOrder = NULL;
717 /* Free internal storage */
718 g_free( ADDRITEM_ID(addrIndex) );
719 g_free( ADDRITEM_NAME(addrIndex) );
720 g_free( addrIndex->filePath );
721 g_free( addrIndex->fileName );
723 /* Clear pointers */
724 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
725 ADDRITEM_ID(addrIndex) = NULL;
726 ADDRITEM_NAME(addrIndex) = NULL;
727 ADDRITEM_PARENT(addrIndex) = NULL;
728 ADDRITEM_SUBTYPE(addrIndex) = 0;
729 addrIndex->filePath = NULL;
730 addrIndex->fileName = NULL;
731 addrIndex->retVal = MGU_SUCCESS;
732 addrIndex->needsConversion = FALSE;
733 addrIndex->wasConverted = FALSE;
734 addrIndex->conversionError = FALSE;
735 addrIndex->lastType = ADDR_IF_NONE;
736 addrIndex->dirtyFlag = FALSE;
738 /* Free up interfaces */
739 node = addrIndex->interfaceList;
740 while( node ) {
741 AddressInterface *iface = node->data;
742 addrindex_free_interface( iface );
743 node = g_list_next( node );
745 g_list_free( addrIndex->interfaceList );
746 addrIndex->interfaceList = NULL;
748 /* Free up hash cache */
749 addrindex_free_cache_hash( addrIndex->hashCache );
750 addrIndex->hashCache = NULL;
752 addrIndex->loadedFlag = FALSE;
754 g_free( addrIndex );
755 addrIndex = NULL;
756 _addressIndex_ = NULL;
760 * Print address index.
761 * \param addrIndex Address index.
762 * \parem stream Stream to print.
764 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
765 cm_return_if_fail( addrIndex != NULL );
766 fprintf( stream, "AddressIndex:\n" );
767 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
768 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
769 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
770 fprintf( stream, "\tconverted: '%s'\n",
771 addrIndex->wasConverted ? "yes" : "no" );
772 fprintf( stream, "\tcvt error: '%s'\n",
773 addrIndex->conversionError ? "yes" : "no" );
774 fprintf( stream, "\t---\n" );
778 * Retrieve reference to address interface for specified interface type.
779 * \param addrIndex Address index.
780 * \param ifType Interface type.
781 * \return Address interface, or NULL if not found.
783 static AddressInterface *addrindex_get_interface(
784 AddressIndex *addrIndex, AddressIfType ifType )
786 AddressInterface *retVal = NULL;
787 GList *node;
789 cm_return_val_if_fail( addrIndex != NULL, NULL );
791 node = addrIndex->interfaceList;
792 while( node ) {
793 AddressInterface *iface = node->data;
794 node = g_list_next( node );
795 if( iface->type == ifType ) {
796 retVal = iface;
797 break;
800 return retVal;
804 * Add raw data source to index. The raw data object (an AddressBookFile or
805 * VCardFile object, for example) should be supplied as the raw dataSource
806 * argument.
808 * \param addrIndex Address index.
809 * \param ifType Interface type to add.
810 * \param dataSource Actual raw data source to add.
811 * \return Data source added, or NULL if invalid interface type.
813 AddressDataSource *addrindex_index_add_datasource(
814 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
816 AddressInterface *iface;
817 AddressDataSource *ds = NULL;
819 cm_return_val_if_fail( addrIndex != NULL, NULL );
820 cm_return_val_if_fail( dataSource != NULL, NULL );
822 iface = addrindex_get_interface( addrIndex, ifType );
823 if( iface ) {
824 ds = addrindex_create_datasource( ifType );
825 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
826 ds->type = ifType;
827 ds->rawDataSource = dataSource;
828 ds->interface = iface;
829 iface->listSource = g_list_append( iface->listSource, ds );
830 addrIndex->dirtyFlag = TRUE;
832 addrindex_hash_add_cache( addrIndex, ds );
834 return ds;
838 * Remove specified data source from index.
839 * \param addrIndex Address index.
840 * \param dataSource Data source to add.
841 * \return Reference to data source if removed, or NULL if data source was not
842 * found in index. Note the this object must still be freed.
844 AddressDataSource *addrindex_index_remove_datasource(
845 AddressIndex *addrIndex, AddressDataSource *dataSource )
847 AddressDataSource *retVal = FALSE;
848 AddressInterface *iface;
850 cm_return_val_if_fail( addrIndex != NULL, NULL );
851 cm_return_val_if_fail( dataSource != NULL, NULL );
853 iface = addrindex_get_interface( addrIndex, dataSource->type );
854 if( iface ) {
855 iface->listSource = g_list_remove( iface->listSource, dataSource );
856 addrIndex->dirtyFlag = TRUE;
857 dataSource->interface = NULL;
859 /* Remove cache from hash table */
860 addrindex_hash_remove_cache( addrIndex, dataSource );
862 retVal = dataSource;
864 return retVal;
868 * Retrieve a reference to address interface for specified interface type and
869 * XML interface tag name.
870 * \param addrIndex Address index.
871 * \param tag XML interface tag name to match.
872 * \param ifType Interface type to match.
873 * \return Reference to address index, or NULL if not found in index.
875 static AddressInterface *addrindex_tag_get_interface(
876 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
878 AddressInterface *retVal = NULL;
879 GList *node = addrIndex->interfaceList;
881 while( node ) {
882 AddressInterface *iface = node->data;
883 node = g_list_next( node );
884 if( tag ) {
885 if( strcmp( iface->listTag, tag ) == 0 ) {
886 retVal = iface;
887 break;
890 else {
891 if( iface->type == ifType ) {
892 retVal = iface;
893 break;
897 return retVal;
901 * Retrieve a reference to address interface for specified interface type and
902 * XML datasource tag name.
903 * \param addrIndex Address index.
904 * \param ifType Interface type to match.
905 * \param tag XML datasource tag name to match.
906 * \return Reference to address index, or NULL if not found in index.
908 static AddressInterface *addrindex_tag_get_datasource(
909 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
911 AddressInterface *retVal = NULL;
912 GList *node = addrIndex->interfaceList;
914 while( node ) {
915 AddressInterface *iface = node->data;
916 node = g_list_next( node );
917 if( iface->type == ifType && iface->itemTag ) {
918 if( strcmp( iface->itemTag, tag ) == 0 ) {
919 retVal = iface;
920 break;
924 return retVal;
927 /* **********************************************************************
928 * Interface XML parsing functions.
929 * ***********************************************************************
933 * Write start of XML element to file.
934 * \param fp File.
935 * \param lvl Indentation level.
936 * \param name Element name.
938 static int addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
939 gint i;
940 for( i = 0; i < lvl; i++ )
941 if (claws_fputs( " ", fp ) == EOF)
942 return -1;
943 if (claws_fputs( "<", fp ) == EOF)
944 return -1;
945 if (claws_fputs( name, fp ) == EOF)
946 return -1;
947 return 0;
951 * Write end of XML element to file.
952 * \param fp File.
953 * \param lvl Indentation level.
954 * \param name Element name.
956 static int addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
957 gint i;
958 for( i = 0; i < lvl; i++ )
959 if (claws_fputs( " ", fp ) == EOF)
960 return -1;
961 if (claws_fputs( "</", fp ) == EOF)
962 return -1;
963 if (claws_fputs( name, fp ) == EOF)
964 return -1;
965 if (claws_fputs( ">\n", fp ) == EOF)
966 return -1;
967 return 0;
971 * Write XML attribute to file.
972 * \param fp File.
973 * \param name Attribute name.
974 * \param value Attribute value.
976 static int addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
977 if (claws_fputs( " ", fp ) == EOF)
978 return -1;
979 if (claws_fputs( name, fp ) == EOF)
980 return -1;
981 if (claws_fputs( "=\"", fp ) == EOF)
982 return -1;
983 if (xml_file_put_escape_str( fp, value ) < 0)
984 return -1;
985 if (claws_fputs( "\"", fp ) == EOF)
986 return -1;
987 return 0;
990 #if !defined(USE_LDAP) || !defined(USE_JPILOT)
992 * Return DOM fragment for current XML tag from file.
993 * \param file XML file being processed.
994 * \return Fragment representing DOM fragment for configuration element.
996 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
997 AddressIfFragment *fragment;
998 AddressIfFragment *child;
999 AddressIfAttrib *nv;
1000 XMLTag *xtag;
1001 GList *list;
1002 GList *attr;
1003 gchar *name;
1004 gchar *value;
1005 guint prevLevel;
1006 gint rc;
1008 /* g_print( "addrindex_read_fragment\n" ); */
1010 prevLevel = file->level;
1012 /* Get current tag name */
1013 xtag = xml_get_current_tag( file );
1015 /* Create new fragment */
1016 fragment = g_new0( AddressIfFragment, 1 );
1017 fragment->type = ADBOOKTYPE_NONE;
1018 fragment->addressCache = NULL;
1019 fragment->name = g_strdup( xtag->tag );
1020 fragment->children = NULL;
1021 fragment->attributes = NULL;
1023 /* Read attributes */
1024 list = NULL;
1025 attr = xml_get_current_tag_attr( file );
1026 while( attr ) {
1027 name = ((XMLAttr *)attr->data)->name;
1028 value = ((XMLAttr *)attr->data)->value;
1029 nv = g_new0( AddressIfAttrib, 1 );
1030 nv->name = g_strdup( name );
1031 nv->value = g_strdup( value );
1032 list = g_list_append( list, nv );
1033 attr = g_list_next( attr );
1035 fragment->attributes = list;
1037 /* Now read the children */
1038 while( TRUE ) {
1039 rc = xml_parse_next_tag( file );
1040 if( rc != 0 ) {
1041 /* End of file? */
1042 break;
1044 if( file->level < prevLevel ) {
1045 /* We must be above level we start at */
1046 break;
1048 child = addrindex_read_fragment( file );
1049 fragment->children = g_list_append( fragment->children, child );
1052 return fragment;
1056 * Write DOM fragment to file.
1057 * \param fp File to write.
1058 * \param fragment DOM fragment for configuration element.
1059 * \param lvl Indent level.
1061 static int addrindex_write_fragment(
1062 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1064 GList *node;
1066 if( fragment ) {
1067 if (addrindex_write_elem_s( fp, lvl, fragment->name ) < 0)
1068 return -1;
1069 node = fragment->attributes;
1070 while( node ) {
1071 AddressIfAttrib *nv = node->data;
1072 if (addrindex_write_attr( fp, nv->name, nv->value ) < 0)
1073 return -1;
1074 node = g_list_next( node );
1076 if( fragment->children ) {
1077 if (claws_fputs(" >\n", fp) == EOF)
1078 return -1;
1080 /* Output children */
1081 node = fragment->children;
1082 while( node ) {
1083 AddressIfFragment *child = node->data;
1084 if (addrindex_write_fragment( fp, child, 1+lvl ) < 0)
1085 return -1;
1086 node = g_list_next( node );
1089 /* Output closing tag */
1090 if (addrindex_write_elem_e( fp, lvl, fragment->name ) < 0)
1091 return -1;
1093 else {
1094 if (claws_fputs(" />\n", fp) == EOF)
1095 return -1;
1099 return 0;
1101 #endif
1103 * Read/parse address index file, creating a data source for a regular
1104 * intrinsic XML addressbook.
1105 * \param file Address index file.
1106 * \return Data source.
1108 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1109 AddressDataSource *ds;
1110 AddressBookFile *abf;
1111 GList *attr;
1113 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1114 abf = addrbook_create_book();
1115 attr = xml_get_current_tag_attr( file );
1116 while( attr ) {
1117 gchar *name = ((XMLAttr *)attr->data)->name;
1118 gchar *value = ((XMLAttr *)attr->data)->value;
1119 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1120 addrbook_set_name( abf, value );
1122 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1123 addrbook_set_file( abf, value );
1125 attr = g_list_next( attr );
1127 ds->rawDataSource = abf;
1128 return ds;
1131 static int addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1132 AddressBookFile *abf = ds->rawDataSource;
1133 if( abf ) {
1134 if (addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK ) < 0)
1135 return -1;
1136 if (addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) ) < 0)
1137 return -1;
1138 if (addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName ) < 0)
1139 return -1;
1140 if (claws_fputs( " />\n", fp ) == EOF)
1141 return -1;
1143 return 0;
1146 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1147 AddressDataSource *ds;
1148 VCardFile *vcf;
1149 GList *attr;
1151 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1152 vcf = vcard_create();
1153 attr = xml_get_current_tag_attr( file );
1154 while( attr ) {
1155 gchar *name = ((XMLAttr *)attr->data)->name;
1156 gchar *value = ((XMLAttr *)attr->data)->value;
1157 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1158 vcard_set_name( vcf, value );
1160 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1161 vcard_set_file( vcf, value );
1163 attr = g_list_next( attr );
1165 ds->rawDataSource = vcf;
1166 return ds;
1169 static int addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1170 VCardFile *vcf = ds->rawDataSource;
1171 if( vcf ) {
1172 if (addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD ) < 0)
1173 return -1;
1174 if (addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) ) < 0)
1175 return -1;
1176 if (addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path ) < 0)
1177 return -1;
1178 if (claws_fputs( " />\n", fp ) == EOF)
1179 return -1;
1181 return 0;
1184 #ifdef USE_JPILOT
1185 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1186 AddressDataSource *ds;
1187 JPilotFile *jpf;
1188 GList *attr;
1190 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1191 jpf = jpilot_create();
1192 attr = xml_get_current_tag_attr( file );
1193 while( attr ) {
1194 gchar *name = ((XMLAttr *)attr->data)->name;
1195 gchar *value = ((XMLAttr *)attr->data)->value;
1196 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1197 jpilot_set_name( jpf, value );
1199 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1200 jpilot_set_file( jpf, value );
1202 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1203 jpilot_add_custom_label( jpf, value );
1205 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1206 jpilot_add_custom_label( jpf, value );
1208 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1209 jpilot_add_custom_label( jpf, value );
1211 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1212 jpilot_add_custom_label( jpf, value );
1214 attr = g_list_next( attr );
1216 ds->rawDataSource = jpf;
1217 return ds;
1220 static int addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1221 JPilotFile *jpf = ds->rawDataSource;
1222 if( jpf ) {
1223 gint ind;
1224 GList *node;
1225 GList *customLbl = jpilot_get_custom_labels( jpf );
1226 if (addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT ) < 0)
1227 return -1;
1228 if (addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) ) < 0)
1229 return -1;
1230 if (addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path ) < 0)
1231 return -1;
1232 node = customLbl;
1233 ind = 1;
1234 while( node ) {
1235 gchar name[256];
1236 g_snprintf( name, sizeof(name), "%s%d",
1237 ATTAG_JPILOT_CUSTOM, ind );
1238 if (addrindex_write_attr( fp, name, node->data ) < 0)
1239 return -1;
1240 ind++;
1241 node = g_list_next( node );
1243 if (claws_fputs( " />\n", fp ) == EOF)
1244 return -1;
1246 return 0;
1249 #else
1251 * Just read/write DOM fragments (preserve data found in file).
1253 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1254 AddressDataSource *ds;
1256 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1257 ds->rawDataSource = addrindex_read_fragment( file );
1258 return ds;
1261 static int addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1262 AddressIfFragment *fragment = ds->rawDataSource;
1263 if( fragment ) {
1264 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1265 return -1;
1267 return 0;
1269 #endif
1271 #ifdef USE_LDAP
1273 * Parse LDAP criteria attribute data from XML file.
1274 * \param file Index file.
1275 * \param ctl LDAP control object to populate.
1277 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1278 guint prevLevel;
1279 XMLTag *xtag;
1280 XMLTag *xtagPrev;
1281 gint rc;
1282 GList *attr;
1283 GList *list;
1284 GList *node;
1286 if( file == NULL ) {
1287 return;
1290 list = NULL;
1291 prevLevel = file->level;
1292 xtagPrev = xml_get_current_tag( file );
1293 while( TRUE ) {
1294 rc = xml_parse_next_tag( file );
1295 if( rc != 0 ) {
1296 /* Terminate prematurely */
1297 g_list_free_full( list, g_free );
1298 list = NULL;
1299 return;
1301 if( file->level < prevLevel ) {
1302 /* We must be above level we start at */
1303 break;
1306 /* Get a tag (element) */
1307 xtag = xml_get_current_tag( file );
1308 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1309 /* LDAP criteria attribute */
1310 attr = xml_get_current_tag_attr( file );
1311 while( attr ) {
1312 gchar *name = ((XMLAttr *)attr->data)->name;
1313 gchar *value = ((XMLAttr *)attr->data)->value;
1314 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1315 if( value && strlen( value ) > 0 ) {
1316 list = g_list_append(
1317 list, g_strdup( value ) );
1320 attr = g_list_next( attr );
1323 else {
1324 if( xtag != xtagPrev ) {
1325 /* Found a new tag */
1326 break;
1331 /* Build list of search attributes */
1332 ldapctl_criteria_list_clear( ctl );
1333 node = list;
1334 while( node ) {
1335 ldapctl_criteria_list_add( ctl, node->data );
1336 g_free( node->data );
1337 node->data = NULL;
1338 node = g_list_next( node );
1340 g_list_free( list );
1341 list = NULL;
1345 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1347 * Parse LDAP control data from XML file.
1348 * \param file Index file.
1349 * \return Initialized data soruce object.
1351 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1352 AddressDataSource *ds;
1353 LdapServer *server;
1354 LdapControl *ctl;
1355 GList *attr;
1356 gchar *serverName = NULL;
1357 gchar *criteria = NULL;
1358 gboolean bDynSearch;
1359 gboolean bTLS, bSSL;
1360 gint iMatch;
1361 gchar *password = NULL;
1363 /* g_print( "addrindex_parse_ldap\n" ); */
1364 /* Set up some defaults */
1365 bDynSearch = FALSE;
1366 bTLS = FALSE;
1367 bSSL = FALSE;
1368 iMatch = LDAPCTL_MATCH_BEGINWITH;
1370 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1371 ctl = ldapctl_create();
1372 attr = xml_get_current_tag_attr( file );
1373 while( attr ) {
1374 gchar *name = ((XMLAttr *)attr->data)->name;
1375 gchar *value = ((XMLAttr *)attr->data)->value;
1376 gint ivalue = atoi( value );
1378 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1379 g_free( serverName );
1380 serverName = g_strdup( value );
1382 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1383 ldapctl_set_host( ctl, value );
1385 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1386 ldapctl_set_port( ctl, ivalue );
1388 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1389 ldapctl_set_base_dn( ctl, value );
1391 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1392 ldapctl_set_bind_dn( ctl, value );
1394 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1395 password = value;
1397 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1398 g_free( criteria );
1399 criteria = g_strdup( value );
1400 g_print("criteria %s\n", criteria);
1402 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1403 ldapctl_set_max_entries( ctl, ivalue );
1405 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1406 ldapctl_set_timeout( ctl, ivalue );
1408 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1409 ldapctl_set_max_query_age( ctl, ivalue );
1411 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1412 bDynSearch = FALSE;
1413 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1414 bDynSearch = TRUE;
1417 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1418 iMatch = LDAPCTL_MATCH_BEGINWITH;
1419 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1420 iMatch = LDAPCTL_MATCH_CONTAINS;
1423 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1424 bTLS = FALSE;
1425 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1426 bTLS = TRUE;
1429 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1430 bSSL = FALSE;
1431 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1432 bSSL = TRUE;
1435 attr = g_list_next( attr );
1438 if (password != NULL)
1439 passwd_store_set(PWS_CORE, "LDAP", ctl->hostName, password, TRUE);
1441 server = ldapsvr_create_noctl();
1442 ldapsvr_set_name( server, serverName );
1443 ldapsvr_set_search_flag( server, bDynSearch );
1444 ldapctl_set_matching_option( ctl, iMatch );
1445 ldapctl_set_tls( ctl, bTLS );
1446 ldapctl_set_ssl( ctl, bSSL );
1447 g_free( serverName );
1448 ldapsvr_set_control( server, ctl );
1449 ds->rawDataSource = server;
1451 addrindex_parse_ldap_attrlist( file, ctl );
1453 * If criteria have been specified and no attributes were listed, then
1454 * convert old style criteria into an attribute list. Any criteria will
1455 * be dropped when saving data.
1457 if( criteria ) {
1458 if( ! ldapctl_get_criteria_list( ctl ) ) {
1459 ldapctl_parse_ldap_search( ctl, criteria );
1461 g_free( criteria );
1463 #ifdef DEBUG_LDAP
1464 ldapsvr_print_data( server, stdout );
1465 #endif
1467 return ds;
1470 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1471 LdapServer *server = ds->rawDataSource;
1472 LdapControl *ctl = NULL;
1473 GList *node;
1474 gchar value[256];
1476 if( server ) {
1477 ctl = server->control;
1479 if( ctl == NULL ) return 0;
1481 /* Output start element with attributes */
1482 if (addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP ) < 0)
1483 return -1;
1484 if (addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) ) < 0)
1485 return -1;
1486 if (addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName ) < 0)
1487 return -1;
1489 sprintf( value, "%d", ctl->port );
1490 if (addrindex_write_attr( fp, ATTAG_LDAP_PORT, value ) < 0)
1491 return -1;
1493 if (addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN ) < 0)
1494 return -1;
1495 if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN ) < 0)
1496 return -1;
1498 sprintf( value, "%d", ctl->maxEntries );
1499 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value ) < 0)
1500 return -1;
1501 sprintf( value, "%d", ctl->timeOut );
1502 if (addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value ) < 0)
1503 return -1;
1504 sprintf( value, "%d", ctl->maxQueryAge );
1505 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value ) < 0)
1506 return -1;
1508 if (addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1509 server->searchFlag ?
1510 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1511 return -1;
1513 if (addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1514 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1515 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN ) < 0)
1516 return -1;
1518 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1519 ctl->enableTLS ?
1520 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1521 return -1;
1522 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1523 ctl->enableSSL ?
1524 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1525 return -1;
1527 if (claws_fputs(" >\n", fp) == EOF)
1528 return -1;
1530 /* Output attributes */
1531 node = ldapctl_get_criteria_list( ctl );
1532 while( node ) {
1533 if (addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH ) < 0)
1534 return -1;
1535 if (addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data ) < 0)
1536 return -1;
1537 if (claws_fputs(" />\n", fp) == EOF)
1538 return -1;
1539 node = g_list_next( node );
1542 /* End of element */
1543 if (addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP ) < 0)
1544 return -1;
1546 return 0;
1549 #else
1551 * Just read/write DOM fragments (preserve data found in file).
1553 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1554 AddressDataSource *ds;
1556 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1557 ds->rawDataSource = addrindex_read_fragment( file );
1558 return ds;
1561 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1562 AddressIfFragment *fragment = ds->rawDataSource;
1563 if( fragment ) {
1564 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1565 return -1;
1567 return 0;
1569 #endif
1571 /* **********************************************************************
1572 * Address index I/O functions.
1573 * ***********************************************************************
1576 * Read address index file, creating appropriate data sources for each address
1577 * index file entry.
1579 * \param addrIndex Address index.
1580 * \param file Address index file.
1582 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1583 XMLTag *xtag;
1584 AddressInterface *iface = NULL, *dsIFace = NULL;
1585 AddressDataSource *ds;
1586 gint rc;
1588 addrIndex->loadedFlag = FALSE;
1589 for (;;) {
1590 rc = xml_parse_next_tag( file );
1591 if( rc < 0 || file->level == 0 ) return;
1593 xtag = xml_get_current_tag( file );
1595 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1596 if( iface ) {
1597 addrIndex->lastType = iface->type;
1598 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1600 else {
1601 dsIFace = addrindex_tag_get_datasource(
1602 addrIndex, addrIndex->lastType, xtag->tag );
1603 if( dsIFace ) {
1604 /* Add data source to list */
1605 ds = NULL;
1606 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1607 ds = addrindex_parse_book( file );
1608 if( ds->rawDataSource ) {
1609 addrbook_set_path( ds->rawDataSource,
1610 addrIndex->filePath );
1613 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1614 ds = addrindex_parse_vcard( file );
1616 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1617 ds = addrindex_parse_jpilot( file );
1619 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1620 ds = addrindex_parse_ldap( file );
1622 if( ds ) {
1623 ds->interface = dsIFace;
1624 addrindex_hash_add_cache( addrIndex, ds );
1625 dsIFace->listSource =
1626 g_list_append( dsIFace->listSource, ds );
1634 * Search order sorting comparison function for building search order list.
1636 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1637 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1638 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1640 return ifaceA->searchOrder - ifaceB->searchOrder;
1644 * Build list of data sources to process.
1645 * \param addrIndex Address index object.
1647 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1648 GList *nodeIf;
1650 /* Clear existing list */
1651 g_list_free( addrIndex->searchOrder );
1652 addrIndex->searchOrder = NULL;
1654 /* Build new list */
1655 nodeIf = addrIndex->interfaceList;
1656 while( nodeIf ) {
1657 AddressInterface *iface = nodeIf->data;
1658 if( iface->useInterface ) {
1659 if( iface->searchOrder > 0 ) {
1660 /* Add to search order list */
1661 addrIndex->searchOrder = g_list_insert_sorted(
1662 addrIndex->searchOrder, iface,
1663 addrindex_search_order_compare );
1666 nodeIf = g_list_next( nodeIf );
1670 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1671 XMLFile *file = NULL;
1672 gchar *fileSpec = NULL;
1674 cm_return_val_if_fail( addrIndex != NULL, -1 );
1676 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1677 addrIndex->retVal = MGU_NO_FILE;
1678 file = xml_open_file( fileSpec );
1679 g_free( fileSpec );
1681 if( file == NULL ) {
1683 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1685 return addrIndex->retVal;
1688 addrIndex->retVal = MGU_BAD_FORMAT;
1689 if( xml_get_dtd( file ) == 0 ) {
1690 if( xml_parse_next_tag( file ) == 0 ) {
1691 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1692 addrindex_read_index( addrIndex, file );
1693 addrIndex->retVal = MGU_SUCCESS;
1697 xml_close_file( file );
1699 addrindex_build_search_order( addrIndex );
1701 return addrIndex->retVal;
1704 static int addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1705 GList *nodeIF, *nodeDS;
1706 gint lvlList = 1;
1707 gint lvlItem = 1 + lvlList;
1709 nodeIF = addrIndex->interfaceList;
1710 while( nodeIF ) {
1711 AddressInterface *iface = nodeIF->data;
1712 if( ! iface->legacyFlag ) {
1713 nodeDS = iface->listSource;
1714 if (addrindex_write_elem_s( fp, lvlList, iface->listTag ) < 0)
1715 return -1;
1716 if (claws_fputs( ">\n", fp ) == EOF)
1717 return -1;
1718 while( nodeDS ) {
1719 AddressDataSource *ds = nodeDS->data;
1720 if( ds ) {
1721 if( iface->type == ADDR_IF_BOOK ) {
1722 if (addrindex_write_book( fp, ds, lvlItem ) < 0)
1723 return -1;
1725 if( iface->type == ADDR_IF_VCARD ) {
1726 if (addrindex_write_vcard( fp, ds, lvlItem ) < 0)
1727 return -1;
1729 if( iface->type == ADDR_IF_JPILOT ) {
1730 if (addrindex_write_jpilot( fp, ds, lvlItem ) < 0)
1731 return -1;
1733 if( iface->type == ADDR_IF_LDAP ) {
1734 if (addrindex_write_ldap( fp, ds, lvlItem ) < 0)
1735 return -1;
1738 nodeDS = g_list_next( nodeDS );
1740 if (addrindex_write_elem_e( fp, lvlList, iface->listTag ) < 0)
1741 return -1;
1743 nodeIF = g_list_next( nodeIF );
1745 return 0;
1749 * Write data to specified file.
1750 * Enter: addrIndex Address index object.
1751 * newFile New file name.
1752 * return: Status code, from addrIndex->retVal.
1753 * Note: File will be created in directory specified by addrIndex.
1755 static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1756 FILE *fp;
1757 gchar *fileSpec;
1758 #ifndef DEV_STANDALONE
1759 PrefFile *pfile;
1760 #endif
1762 cm_return_val_if_fail( addrIndex != NULL, -1 );
1764 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1765 addrIndex->retVal = MGU_OPEN_FILE;
1766 #ifdef DEV_STANDALONE
1767 fp = claws_fopen( fileSpec, "wb" );
1768 g_free( fileSpec );
1769 if( fp ) {
1770 claws_fputs( "<?xml version=\"1.0\" ?>\n", fp );
1771 #else
1772 pfile = prefs_write_open( fileSpec );
1773 g_free( fileSpec );
1774 if( pfile ) {
1775 fp = pfile->fp;
1776 if (fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL ) < 0)
1777 goto fail;
1778 #endif
1779 if (addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1780 goto fail;
1781 if (claws_fputs( ">\n", fp ) == EOF)
1782 goto fail;
1784 if (addrindex_write_index( addrIndex, fp ) < 0)
1785 goto fail;
1786 if (addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1787 goto fail;
1789 addrIndex->retVal = MGU_SUCCESS;
1790 #ifdef DEV_STANDALONE
1791 claws_safe_fclose( fp );
1792 #else
1793 if( prefs_file_close( pfile ) < 0 ) {
1794 addrIndex->retVal = MGU_ERROR_WRITE;
1796 #endif
1799 fileSpec = NULL;
1800 return addrIndex->retVal;
1801 fail:
1802 g_warning("error writing AB index");
1803 addrIndex->retVal = MGU_ERROR_WRITE;
1804 if (pfile)
1805 prefs_file_close_revert( pfile );
1806 return addrIndex->retVal;
1810 * Save address index data to original file.
1811 * return: Status code, from addrIndex->retVal.
1813 gint addrindex_save_data( AddressIndex *addrIndex ) {
1814 #ifdef USE_LDAP
1815 GList *nodeIf;
1816 GList *nodeDS;
1817 #endif
1819 cm_return_val_if_fail( addrIndex != NULL, -1 );
1821 #ifdef USE_LDAP
1822 nodeIf = addrIndex->interfaceList;
1823 /* save LDAP interfaces */
1824 while ( nodeIf ) {
1825 AddressInterface *iface = nodeIf->data;
1826 if( iface->type == ADDR_IF_LDAP ) {
1827 nodeDS = iface->listSource;
1828 while( nodeDS ) {
1829 AddressDataSource *ds = nodeDS->data;
1830 LdapServer *abf = ds->rawDataSource;
1831 if( ldapsvr_get_read_flag( abf ) ) {
1832 if( ldapsvr_get_modified( abf ) ) {
1833 ldapsvr_update_book( abf, NULL );
1834 if( abf->retVal != LDAPRC_SUCCESS ) {
1835 alertpanel( _("Address(es) update"),
1836 _("Update failed. Changes not written to Directory."),
1837 "window-close", _("_Close"), NULL, NULL,
1838 NULL, NULL, ALERTFOCUS_FIRST );
1840 else {
1841 abf->retVal = MGU_SUCCESS;
1842 ldapsvr_set_modified( abf, FALSE );
1846 nodeDS = g_list_next( nodeDS );
1848 break;
1850 nodeIf = g_list_next( nodeIf );
1852 #endif
1853 addrIndex->retVal = MGU_NO_FILE;
1854 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1855 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1857 addrindex_write_to( addrIndex, addrIndex->fileName );
1858 if( addrIndex->retVal == MGU_SUCCESS ) {
1859 addrIndex->dirtyFlag = FALSE;
1861 return addrIndex->retVal;
1865 * Save all address book files which may have changed.
1866 * Return: Status code, set if there was a problem saving data.
1868 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1869 gint retVal = MGU_SUCCESS;
1870 GList *nodeIf, *nodeDS;
1872 nodeIf = addrIndex->interfaceList;
1873 while( nodeIf ) {
1874 AddressInterface *iface = nodeIf->data;
1875 if( iface->type == ADDR_IF_BOOK ) {
1876 nodeDS = iface->listSource;
1877 while( nodeDS ) {
1878 AddressDataSource *ds = nodeDS->data;
1879 AddressBookFile *abf = ds->rawDataSource;
1880 if( addrbook_get_dirty( abf ) ) {
1881 if( addrbook_get_read_flag( abf ) ) {
1882 addrbook_save_data( abf );
1883 if( abf->retVal != MGU_SUCCESS ) {
1884 retVal = abf->retVal;
1888 nodeDS = g_list_next( nodeDS );
1890 break;
1892 nodeIf = g_list_next( nodeIf );
1894 return retVal;
1898 /* **********************************************************************
1899 * Address book conversion to new format.
1900 * ***********************************************************************
1903 #define ELTAG_IF_OLD_FOLDER "folder"
1904 #define ELTAG_IF_OLD_GROUP "group"
1905 #define ELTAG_IF_OLD_ITEM "item"
1906 #define ELTAG_IF_OLD_NAME "name"
1907 #define ELTAG_IF_OLD_ADDRESS "address"
1908 #define ELTAG_IF_OLD_REMARKS "remarks"
1909 #define ATTAG_IF_OLD_NAME "name"
1911 #define TEMPNODE_ROOT 0
1912 #define TEMPNODE_FOLDER 1
1913 #define TEMPNODE_GROUP 2
1914 #define TEMPNODE_ADDRESS 3
1916 typedef struct _AddressCvt_Node AddressCvtNode;
1917 struct _AddressCvt_Node {
1918 gint type;
1919 gchar *name;
1920 gchar *address;
1921 gchar *remarks;
1922 GList *list;
1926 * Parse current address item.
1928 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1929 gchar *element;
1930 guint level;
1931 AddressCvtNode *nn;
1933 nn = g_new0( AddressCvtNode, 1 );
1934 nn->type = TEMPNODE_ADDRESS;
1935 nn->list = NULL;
1937 level = file->level;
1939 for (;;) {
1940 xml_parse_next_tag(file);
1941 if (file->level < level) return nn;
1943 element = xml_get_element( file );
1944 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1945 nn->name = g_strdup( element );
1947 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1948 nn->address = g_strdup( element );
1950 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1951 nn->remarks = g_strdup( element );
1953 g_free(element);
1954 xml_parse_next_tag(file);
1959 * Create a temporary node below specified node.
1961 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1962 AddressCvtNode *nn;
1963 nn = g_new0( AddressCvtNode, 1 );
1964 nn->type = type;
1965 nn->name = g_strdup( name );
1966 nn->remarks = g_strdup( rem );
1967 node->list = g_list_append( node->list, nn );
1968 return nn;
1972 * Process current temporary node.
1974 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1975 GList *attr;
1976 guint prev_level;
1977 AddressCvtNode *newNode = NULL;
1978 gchar *name;
1979 gchar *value;
1981 for (;;) {
1982 prev_level = file->level;
1983 xml_parse_next_tag( file );
1984 if (file->level < prev_level) return;
1985 name = NULL;
1986 value = NULL;
1988 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1989 attr = xml_get_current_tag_attr(file);
1990 if (attr) {
1991 name = ((XMLAttr *)attr->data)->name;
1992 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1993 value = ((XMLAttr *)attr->data)->value;
1996 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1997 addrindex_add_obj( file, newNode );
2000 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
2001 attr = xml_get_current_tag_attr(file);
2002 if (attr) {
2003 name = ((XMLAttr *)attr->data)->name;
2004 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
2005 value = ((XMLAttr *)attr->data)->value;
2008 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
2009 addrindex_add_obj( file, newNode );
2011 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
2012 newNode = addrindex_parse_item( file );
2013 node->list = g_list_append( node->list, newNode );
2015 else {
2016 g_warning("invalid tag");
2022 * Consume all nodes below current tag.
2024 static void addrindex_consume_tree( XMLFile *file ) {
2025 guint prev_level;
2027 for (;;) {
2028 prev_level = file->level;
2029 xml_parse_next_tag( file );
2030 if (file->level < prev_level)
2031 return;
2033 addrindex_consume_tree( file );
2038 * Free up temporary tree.
2040 static void addrindex_free_node( AddressCvtNode *node ) {
2041 GList *list = node->list;
2043 while( list ) {
2044 AddressCvtNode *lNode = list->data;
2045 list = g_list_next( list );
2046 addrindex_free_node( lNode );
2048 node->type = TEMPNODE_ROOT;
2049 g_free( node->name );
2050 g_free( node->address );
2051 g_free( node->remarks );
2052 g_list_free( node->list );
2053 g_free( node );
2057 * Process address book for specified node.
2059 static void addrindex_process_node(
2060 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
2061 ItemGroup *parentGrp, ItemFolder *folderGrp )
2063 GList *list;
2064 ItemFolder *itemFolder = NULL;
2065 ItemGroup *itemGParent = parentGrp;
2066 ItemFolder *itemGFolder = folderGrp;
2067 AddressCache *cache = abf->addressCache;
2069 if( node->type == TEMPNODE_ROOT ) {
2070 itemFolder = parent;
2072 else if( node->type == TEMPNODE_FOLDER ) {
2073 itemFolder = addritem_create_item_folder();
2074 addritem_folder_set_name( itemFolder, node->name );
2075 addrcache_id_folder( cache, itemFolder );
2076 addrcache_folder_add_folder( cache, parent, itemFolder );
2077 itemGFolder = NULL;
2079 else if( node->type == TEMPNODE_GROUP ) {
2080 ItemGroup *itemGroup;
2081 gchar *fName;
2083 /* Create a folder for group */
2084 fName = g_strdup_printf( "Cvt - %s", node->name );
2085 itemGFolder = addritem_create_item_folder();
2086 addritem_folder_set_name( itemGFolder, fName );
2087 addrcache_id_folder( cache, itemGFolder );
2088 addrcache_folder_add_folder( cache, parent, itemGFolder );
2089 g_free( fName );
2091 /* Add group into folder */
2092 itemGroup = addritem_create_item_group();
2093 addritem_group_set_name( itemGroup, node->name );
2094 addrcache_id_group( cache, itemGroup );
2095 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2096 itemGParent = itemGroup;
2098 else if( node->type == TEMPNODE_ADDRESS ) {
2099 ItemPerson *itemPerson;
2100 ItemEMail *itemEMail;
2102 /* Create person and email objects */
2103 itemPerson = addritem_create_item_person();
2104 addritem_person_set_common_name( itemPerson, node->name );
2105 addrcache_id_person( cache, itemPerson );
2106 itemEMail = addritem_create_item_email();
2107 addritem_email_set_address( itemEMail, node->address );
2108 addritem_email_set_remarks( itemEMail, node->remarks );
2109 addrcache_id_email( cache, itemEMail );
2110 addrcache_person_add_email( cache, itemPerson, itemEMail );
2112 /* Add person into appropriate folder */
2113 if( itemGFolder ) {
2114 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2116 else {
2117 addrcache_folder_add_person( cache, parent, itemPerson );
2120 /* Add email address only into group */
2121 if( parentGrp ) {
2122 addrcache_group_add_email( cache, parentGrp, itemEMail );
2126 list = node->list;
2127 while( list ) {
2128 AddressCvtNode *lNode = list->data;
2129 list = g_list_next( list );
2130 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2135 * Process address book to specified file number.
2137 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2138 gboolean retVal = FALSE;
2139 AddressBookFile *abf = NULL;
2140 AddressCvtNode *rootNode = NULL;
2141 gchar *newFile = NULL;
2142 GList *fileList = NULL;
2143 gint fileNum = 0;
2145 /* Setup root node */
2146 rootNode = g_new0( AddressCvtNode, 1 );
2147 rootNode->type = TEMPNODE_ROOT;
2148 rootNode->name = g_strdup( "root" );
2149 rootNode->list = NULL;
2150 addrindex_add_obj( file, rootNode );
2151 /* addrindex_print_node( rootNode, stdout ); */
2153 /* Create new address book */
2154 abf = addrbook_create_book();
2155 addrbook_set_name( abf, displayName );
2156 addrbook_set_path( abf, addrIndex->filePath );
2158 /* Determine next available file number */
2159 fileList = addrbook_get_bookfile_list( abf );
2160 if( fileList ) {
2161 fileNum = 1 + abf->maxValue;
2163 g_list_free( fileList );
2164 fileList = NULL;
2166 newFile = addrbook_gen_new_file_name( fileNum );
2167 if( newFile ) {
2168 addrbook_set_file( abf, newFile );
2171 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2173 #ifdef DEBUG_ADDRBOOK
2174 addrbook_dump_book( abf, stdout );
2175 #endif
2176 addrbook_save_data( abf );
2177 addrIndex->retVal = abf->retVal;
2178 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2180 addrbook_free_book( abf );
2181 abf = NULL;
2182 addrindex_free_node( rootNode );
2183 rootNode = NULL;
2185 /* Create entries in address index */
2186 if( retVal ) {
2187 abf = addrbook_create_book();
2188 addrbook_set_name( abf, displayName );
2189 addrbook_set_path( abf, addrIndex->filePath );
2190 addrbook_set_file( abf, newFile );
2191 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2194 return retVal;
2198 * Process tree converting data.
2200 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2201 guint prev_level;
2202 XMLTag *xtag;
2204 /* Process file */
2205 for (;;) {
2206 prev_level = file->level;
2207 xml_parse_next_tag( file );
2208 if (file->level < prev_level) return;
2210 xtag = xml_get_current_tag( file );
2211 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2212 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2213 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2214 addrIndex->needsConversion = FALSE;
2215 addrIndex->wasConverted = TRUE;
2216 continue;
2218 return;
2220 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2221 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2222 addrIndex->needsConversion = FALSE;
2223 addrIndex->wasConverted = TRUE;
2224 continue;
2226 return;
2228 addrindex_consume_tree( file );
2232 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2233 XMLFile *file = NULL;
2234 gchar *fileSpec;
2236 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2237 addrIndex->retVal = MGU_NO_FILE;
2238 file = xml_open_file( fileSpec );
2239 g_free( fileSpec );
2241 if( file == NULL ) {
2242 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2243 return addrIndex->retVal;
2246 addrIndex->retVal = MGU_BAD_FORMAT;
2247 if( xml_get_dtd( file ) == 0 ) {
2248 if( xml_parse_next_tag( file ) == 0 ) {
2249 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2250 addrindex_convert_tree( addrIndex, file );
2254 xml_close_file( file );
2255 return addrIndex->retVal;
2259 * Create a new address book file.
2261 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2262 gboolean retVal = FALSE;
2263 AddressBookFile *abf = NULL;
2264 gchar *newFile = NULL;
2265 GList *fileList = NULL;
2266 gint fileNum = 0;
2268 /* Create new address book */
2269 abf = addrbook_create_book();
2270 addrbook_set_name( abf, displayName );
2271 addrbook_set_path( abf, addrIndex->filePath );
2273 /* Determine next available file number */
2274 fileList = addrbook_get_bookfile_list( abf );
2275 if( fileList ) {
2276 fileNum = 1 + abf->maxValue;
2278 g_list_free( fileList );
2279 fileList = NULL;
2281 newFile = addrbook_gen_new_file_name( fileNum );
2282 if( newFile ) {
2283 addrbook_set_file( abf, newFile );
2286 addrbook_save_data( abf );
2287 addrIndex->retVal = abf->retVal;
2288 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2289 addrbook_free_book( abf );
2290 abf = NULL;
2292 /* Create entries in address index */
2293 if( retVal ) {
2294 abf = addrbook_create_book();
2295 addrbook_set_name( abf, displayName );
2296 addrbook_set_path( abf, addrIndex->filePath );
2297 addrbook_set_file( abf, newFile );
2298 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2301 return retVal;
2305 * Read data for address index performing a conversion if necesary.
2306 * Enter: addrIndex Address index object.
2307 * return: Status code, from addrIndex->retVal.
2308 * Note: New address book files will be created in directory specified by
2309 * addrIndex. Three files will be created, for the following:
2310 * "Common addresses"
2311 * "Personal addresses"
2312 * "Gathered addresses" - a new address book.
2314 gint addrindex_read_data( AddressIndex *addrIndex ) {
2315 cm_return_val_if_fail( addrIndex != NULL, -1 );
2317 addrIndex->conversionError = FALSE;
2318 addrindex_read_file( addrIndex );
2319 if( addrIndex->retVal == MGU_SUCCESS ) {
2320 if( addrIndex->needsConversion ) {
2321 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS )
2322 addrIndex->conversionError = FALSE;
2323 else
2324 addrIndex->conversionError = TRUE;
2326 addrIndex->dirtyFlag = TRUE;
2328 return addrIndex->retVal;
2332 * Create new address books for a new address index.
2333 * Enter: addrIndex Address index object.
2334 * return: Status code, from addrIndex->retVal.
2335 * Note: New address book files will be created in directory specified by
2336 * addrIndex. Three files will be created, for the following:
2337 * "Common addresses"
2338 * "Personal addresses"
2339 * "Gathered addresses" - a new address book.
2341 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2342 gboolean flg;
2344 cm_return_val_if_fail( addrIndex != NULL, -1 );
2346 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2347 if( flg ) {
2348 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2349 addrIndex->dirtyFlag = TRUE;
2351 return addrIndex->retVal;
2354 /* **********************************************************************
2355 * New interface stuff.
2356 * ***********************************************************************
2360 * Return modified flag for specified data source.
2362 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2363 gboolean retVal = FALSE;
2364 AddressInterface *iface;
2366 if( ds == NULL ) return retVal;
2367 iface = ds->interface;
2368 if( iface == NULL ) return retVal;
2369 if( iface->getModifyFlag ) {
2370 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2372 return retVal;
2376 * Return accessed flag for specified data source.
2378 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2379 gboolean retVal = FALSE;
2380 AddressInterface *iface;
2382 if( ds == NULL ) return retVal;
2383 iface = ds->interface;
2384 if( iface == NULL ) return retVal;
2385 if( iface->getAccessFlag ) {
2386 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2388 return retVal;
2392 * Return data read flag for specified data source.
2394 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2395 gboolean retVal = TRUE;
2396 AddressInterface *iface;
2398 if( ds == NULL ) return retVal;
2399 iface = ds->interface;
2400 if( iface == NULL ) return retVal;
2401 if( iface->getReadFlag ) {
2402 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2404 return retVal;
2408 * Return status code for specified data source.
2410 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2411 gint retVal = MGU_SUCCESS;
2412 AddressInterface *iface;
2414 if( ds == NULL ) return retVal;
2415 iface = ds->interface;
2416 if( iface == NULL ) return retVal;
2417 if( iface->getStatusCode ) {
2418 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2420 return retVal;
2424 * Return data read flag for specified data source.
2426 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2427 gint retVal = MGU_SUCCESS;
2428 AddressInterface *iface;
2430 if( ds == NULL ) return retVal;
2431 iface = ds->interface;
2432 if( iface == NULL ) return retVal;
2433 if( iface->getReadData ) {
2435 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2436 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2438 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2440 return retVal;
2444 * Return data read flag for specified data source.
2446 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2447 ItemFolder *retVal = NULL;
2448 AddressInterface *iface;
2450 if( ds == NULL ) return retVal;
2451 iface = ds->interface;
2452 if( iface == NULL ) return retVal;
2453 if( iface->getRootFolder ) {
2454 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2456 return retVal;
2460 * Return name for specified data source.
2462 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2463 gchar *retVal = FALSE;
2464 AddressInterface *iface;
2466 if( ds == NULL ) return retVal;
2467 iface = ds->interface;
2468 if( iface == NULL ) return retVal;
2469 if( iface->getName ) {
2470 retVal = ( iface->getName ) ( ds->rawDataSource );
2472 return retVal;
2476 * Set the access flag inside the data source.
2478 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2479 AddressInterface *iface;
2481 if( ds == NULL ) return;
2482 iface = ds->interface;
2483 if( iface == NULL ) return;
2484 if( iface->setAccessFlag ) {
2485 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2490 * Return read only flag for specified data source.
2492 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2493 AddressInterface *iface;
2494 if( ds == NULL ) return TRUE;
2495 iface = ds->interface;
2496 if( iface == NULL ) return TRUE;
2497 return iface->readOnly;
2501 * Return list of all persons for specified data source.
2503 static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2504 GList *retVal = NULL;
2505 AddressInterface *iface;
2507 if( ds == NULL ) return retVal;
2508 iface = ds->interface;
2509 if( iface == NULL ) return retVal;
2510 if( iface->getAllPersons ) {
2511 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2513 return retVal;
2517 * Return list of all groups for specified data source.
2519 static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2520 GList *retVal = NULL;
2521 AddressInterface *iface;
2523 if( ds == NULL ) return retVal;
2524 iface = ds->interface;
2525 if( iface == NULL ) return retVal;
2526 if( iface->getAllGroups ) {
2527 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2529 return retVal;
2532 /* **********************************************************************
2533 * Address search stuff.
2534 * ***********************************************************************
2538 * Setup or register the dynamic search that will be performed. The search
2539 * is registered with the query manager.
2541 * \param searchTerm Search term. A private copy will be made.
2542 * \param callBackEntry Callback function that should be called when
2543 * each entry is received.
2544 * \param callBackEnd Callback function that should be called when
2545 * search has finished running.
2546 * \return ID allocated to query that will be executed.
2548 gint addrindex_setup_search(
2549 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2551 QueryRequest *req;
2552 gint queryID;
2554 /* Set up a dynamic address query */
2555 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2556 queryID = req->queryID;
2557 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2559 /* g_print( "***> query ID ::%d::\n", queryID ); */
2560 return queryID;
2563 #ifdef USE_LDAP
2566 * Function prototypes (not in header file or circular reference errors are
2567 * encountered!)
2569 LdapQuery *ldapsvr_new_dynamic_search(
2570 LdapServer *server, QueryRequest *req );
2571 LdapQuery *ldapsvr_new_explicit_search(
2572 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2573 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2575 #endif
2578 * Execute the previously registered dynamic search.
2580 * \param req Address query object to execute.
2581 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2582 * failed.
2584 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2585 AddressInterface *iface;
2586 AddressDataSource *ds;
2587 GList *nodeIf;
2588 GList *nodeDS;
2589 gint type;
2591 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2592 nodeIf = _addressIndex_->searchOrder;
2593 while( nodeIf ) {
2594 iface = nodeIf->data;
2595 nodeIf = g_list_next( nodeIf );
2597 if( ! iface->useInterface ) {
2598 continue;
2600 if( ! iface->externalQuery ) {
2601 continue;
2604 type = iface->type;
2605 nodeDS = iface->listSource;
2606 while( nodeDS ) {
2607 ds = nodeDS->data;
2608 nodeDS = g_list_next( nodeDS );
2609 #ifdef USE_LDAP
2610 if( type == ADDR_IF_LDAP ) {
2611 LdapServer *server;
2612 LdapQuery *qry;
2614 server = ds->rawDataSource;
2615 if( ! server->searchFlag ) {
2616 continue;
2618 if( ldapsvr_reuse_previous( server, req ) ) {
2619 continue;
2622 /* Start a new dynamic search */
2623 qry = ldapsvr_new_dynamic_search( server, req );
2624 if( qry ) {
2625 ldapsvr_execute_query( server, qry );
2628 #endif
2631 return TRUE;
2635 * Stop the previously registered search.
2637 * \param queryID ID of search query to stop.
2639 void addrindex_stop_search( const gint queryID ){
2640 QueryRequest *req;
2641 AddrQueryObject *aqo;
2642 GList *node;
2644 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2645 /* If query ID does not match, search has not been setup */
2646 req = qrymgr_find_request( queryID );
2647 if( req == NULL ) {
2648 return;
2651 /* Stop all queries that were associated with request */
2652 node = req->queryList;
2653 while( node ) {
2654 aqo = node->data;
2655 #ifdef USE_LDAP
2656 if( aqo->queryType == ADDRQUERY_LDAP ) {
2657 LdapQuery *qry = ( LdapQuery * ) aqo;
2658 ldapqry_set_stop_flag( qry, TRUE );
2660 #endif
2661 node->data = NULL;
2662 node = g_list_next( node );
2665 /* Delete query request */
2666 qrymgr_delete_request( queryID );
2670 * Setup or register the explicit search that will be performed. The search is
2671 * registered with the query manager.
2673 * \param ds Data source to search.
2674 * \param searchTerm Search term to locate.
2675 * \param folder Folder to receive search results; may be NULL.
2676 * \param callbackEnd Function to call when search has terminated.
2677 * \param callbackEntry Function to called for each entry processed.
2678 * \return ID allocated to query that will be executed.
2680 gint addrindex_setup_explicit_search(
2681 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2682 void *callBackEnd, void *callBackEntry )
2684 QueryRequest *req;
2685 gint queryID;
2686 gchar *name;
2687 gchar *mySearch;
2689 /* Name the query */
2690 name = g_strdup_printf( "Search '%s'", searchTerm );
2692 /* Set up query request */
2693 if (!strcmp(searchTerm, "*"))
2694 mySearch = g_strdup("*@");
2695 else
2696 mySearch = g_strdup(searchTerm);
2698 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2700 g_free(mySearch);
2702 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2703 queryID = req->queryID;
2705 if( ds->type == ADDR_IF_LDAP ) {
2706 #ifdef USE_LDAP
2707 LdapServer *server;
2709 server = ds->rawDataSource;
2710 ldapsvr_new_explicit_search( server, req, folder );
2711 #endif
2713 else {
2714 qrymgr_delete_request( queryID );
2715 queryID = 0;
2717 g_free( name );
2719 return queryID;
2723 * Execute the previously registered explicit search.
2725 * \param req Address query request object to execute.
2726 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2727 * failed.
2729 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2730 gboolean retVal;
2731 AddrQueryObject *aqo;
2733 retVal = FALSE;
2735 /* Note: there should only be one query in the list. */
2736 aqo = req->queryList->data;
2737 #ifdef USE_LDAP
2738 if( aqo->queryType == ADDRQUERY_LDAP ) {
2739 LdapServer *server;
2740 LdapQuery *qry;
2742 qry = ( LdapQuery * ) aqo;
2743 server = qry->server;
2745 /* Start the search */
2746 retVal = TRUE;
2747 ldapsvr_execute_query( server, qry );
2749 #endif
2750 return retVal;
2754 * Start the previously registered search.
2756 * \param queryID ID of search query to be executed.
2757 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2758 * failed.
2760 gboolean addrindex_start_search( const gint queryID ) {
2761 gboolean retVal;
2762 QueryRequest *req;
2763 AddrSearchType searchType;
2765 retVal = FALSE;
2766 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2767 req = qrymgr_find_request( queryID );
2768 if( req == NULL ) {
2769 return retVal;
2772 searchType = req->searchType;
2773 if( searchType == ADDRSEARCH_DYNAMIC ) {
2774 retVal = addrindex_start_dynamic( req );
2776 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2777 retVal = addrindex_start_explicit( req );
2780 return retVal;
2784 * Remove results (folder and data) for specified data source and folder.
2785 * \param ds Data source to process.
2786 * \param folder Results folder to remove.
2788 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2789 AddrBookBase *adbase;
2790 gint queryID = 0;
2792 /* g_print( "addrindex_remove_results/start\n" ); */
2794 /* Test for folder */
2795 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2796 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2797 adbase = ( AddrBookBase * ) ds->rawDataSource;
2798 if( adbase == NULL ) return;
2800 /* Hide folder to prevent re-display */
2801 addritem_folder_set_hidden( folder, TRUE );
2803 if( ds->type == ADDR_IF_LDAP ) {
2804 #ifdef USE_LDAP
2805 LdapQuery *qry;
2806 gboolean delFlag;
2808 qry = ( LdapQuery * ) folder->folderData;
2809 queryID = ADDRQUERY_ID(qry);
2810 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2811 delFlag = ldapquery_remove_results( qry );
2812 if (delFlag) {
2813 ldapqry_free( qry );
2815 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2817 if( delFlag ) {
2818 g_print( "delFlag IS-TRUE\n" );
2820 else {
2821 g_print( "delFlag IS-FALSE\n" );
2824 #endif
2826 /* g_print( "addrindex_remove_results/end\n" ); */
2828 /* Delete query request */
2829 if( queryID > 0 ) {
2830 qrymgr_delete_request( queryID );
2834 /* **********************************************************************
2835 * Address completion stuff.
2836 * ***********************************************************************
2839 static void addrindex_load_completion_load_persons(
2840 gint (*callBackFunc) ( const gchar *, const gchar *,
2841 const gchar *, const gchar *, GList * ),
2842 AddressDataSource *ds)
2844 GList *listP, *nodeP;
2845 GList *nodeM;
2846 gchar *sName;
2848 /* Read address book */
2849 if( addrindex_ds_get_modify_flag( ds ) ) {
2850 addrindex_ds_read_data( ds );
2853 if( ! addrindex_ds_get_read_flag( ds ) ) {
2854 addrindex_ds_read_data( ds );
2857 /* Get all groups */
2858 listP = addrindex_ds_get_all_groups( ds );
2859 nodeP = listP;
2860 while( nodeP ) {
2861 ItemGroup *group = nodeP->data;
2862 GList *emails = NULL;
2863 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2864 ItemEMail *email = nodeM->data;
2865 if (email->address)
2866 emails = g_list_append(emails, email);
2868 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2869 NULL, NULL, emails );
2870 nodeP = g_list_next( nodeP );
2873 /* Free up the list */
2874 g_list_free( listP );
2875 /* Get all persons */
2876 listP = addrindex_ds_get_all_persons( ds );
2877 nodeP = listP;
2878 while( nodeP ) {
2879 ItemPerson *person = nodeP->data;
2880 nodeM = person->listEMail;
2882 /* Figure out name to use */
2883 sName = ADDRITEM_NAME(person);
2884 if( sName == NULL || *sName == '\0' ) {
2885 sName = person->nickName;
2888 /* Process each E-Mail address */
2889 while( nodeM ) {
2890 ItemEMail *email = nodeM->data;
2892 callBackFunc( sName, email->address, person->nickName,
2893 ADDRITEM_NAME(email), NULL );
2895 nodeM = g_list_next( nodeM );
2897 nodeP = g_list_next( nodeP );
2900 /* Free up the list */
2901 g_list_free( listP );
2905 * This function is used by the address completion function to load
2906 * addresses for all non-external address book interfaces.
2908 * \param callBackFunc Function to be called when an address is
2909 * to be loaded.
2910 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2911 * or "Any", assume the whole addressbook
2912 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2915 gboolean addrindex_load_completion(
2916 gint (*callBackFunc) ( const gchar *, const gchar *,
2917 const gchar *, const gchar *, GList * ),
2918 gchar *folderpath )
2920 GList *nodeIf, *nodeDS;
2922 if( folderpath != NULL ) {
2923 AddressDataSource *book;
2924 ItemFolder* folder;
2926 /* split the folder path we've received, we'll try to match this path, subpath by
2927 subpath against the book/folder structure in order and restrict loading of
2928 addresses to that subpart (if matches). book/folder path must exist and
2929 folderpath must not be empty or NULL */
2931 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2932 g_warning("addrindex_load_completion: folder path '%s' doesn't exist", folderpath);
2933 return FALSE;
2936 if( folder != NULL ) {
2938 GList *items;
2939 GList *nodeM;
2940 gchar *sName;
2941 ItemPerson *person;
2943 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2945 /* Load email addresses */
2946 items = addritem_folder_get_person_list( folder );
2947 for( ; items != NULL; items = g_list_next( items ) ) {
2948 person = items->data;
2949 nodeM = person->listEMail;
2951 /* Figure out name to use */
2952 sName = ADDRITEM_NAME(person);
2953 if( sName == NULL || *sName == '\0' ) {
2954 sName = person->nickName;
2957 /* Process each E-Mail address */
2958 while( nodeM ) {
2959 ItemEMail *email = nodeM->data;
2961 callBackFunc( sName, email->address, person->nickName,
2962 ADDRITEM_NAME(email), NULL );
2964 nodeM = g_list_next( nodeM );
2967 /* Free up the list (but not the data inside the
2968 * individual list items) */
2969 g_list_free( items );
2971 return TRUE;
2973 } else {
2975 if( book != NULL ) {
2977 AddressBookFile *abf = book->rawDataSource;
2979 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf?abf->fileName:"(null)");
2981 addrindex_load_completion_load_persons( callBackFunc, book );
2983 return TRUE;
2985 } else {
2986 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer");
2989 return FALSE;
2991 } else {
2993 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2994 while( nodeIf ) {
2995 AddressInterface *iface = nodeIf->data;
2997 nodeIf = g_list_next( nodeIf );
2999 if( ! iface->useInterface || iface->externalQuery )
3000 continue;
3002 nodeDS = iface->listSource;
3003 while( nodeDS ) {
3004 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
3005 nodeDS = g_list_next( nodeDS );
3010 return TRUE;
3014 * This function can be used to collect information about
3015 * addressbook entries that contain a specific attribute.
3017 * \param attr Name of attribute to look for
3018 * \param callBackFunc Function to be called when a matching attribute was found
3019 * \return <i>TRUE</i>
3021 gboolean addrindex_load_person_attribute(
3022 const gchar *attr,
3023 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
3025 AddressDataSource *ds;
3026 GList *nodeIf, *nodeDS;
3027 GList *listP, *nodeP;
3028 GList *nodeA;
3030 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3031 while( nodeIf ) {
3032 gchar *cur_bname;
3033 AddressInterface *iface = nodeIf->data;
3035 nodeIf = g_list_next( nodeIf );
3037 if( ! iface->useInterface || iface->externalQuery )
3038 continue;
3040 nodeDS = iface->listSource;
3041 while( nodeDS ) {
3042 ds = nodeDS->data;
3044 /* Read address book */
3045 if( addrindex_ds_get_modify_flag( ds ) ) {
3046 addrindex_ds_read_data( ds );
3049 if( ! addrindex_ds_get_read_flag( ds ) ) {
3050 addrindex_ds_read_data( ds );
3053 /* Check addressbook name */
3054 cur_bname = addrindex_ds_get_name( ds );
3056 /* Get all persons */
3057 listP = addrindex_ds_get_all_persons( ds );
3058 nodeP = listP;
3059 while( nodeP ) {
3060 ItemPerson *person = nodeP->data;
3062 /* Return all ItemPerson's if attr is NULL */
3063 if( attr == NULL ) {
3064 callBackFunc(person, cur_bname);
3067 /* Return ItemPerson's with specific attribute */
3068 else {
3069 nodeA = person->listAttrib;
3070 /* Process each User Attribute */
3071 while( nodeA ) {
3072 UserAttribute *attrib = nodeA->data;
3073 if( attrib->name &&
3074 !strcmp( attrib->name,attr ) ) {
3075 callBackFunc(person, cur_bname);
3077 nodeA = g_list_next( nodeA );
3080 nodeP = g_list_next( nodeP );
3082 /* Free up the list */
3083 g_list_free( listP );
3085 nodeDS = g_list_next( nodeDS );
3088 return TRUE;
3092 * This function can be used to collect information about
3093 * addressbook entries
3095 * \param callBackFunc Function to be called for each ItemPerson
3096 * \return <i>TRUE</i>
3098 gboolean addrindex_load_person_ds( gint (*callBackFunc)
3099 ( ItemPerson *, AddressDataSource * ) )
3101 AddressDataSource *ds;
3102 GList *nodeIf, *nodeDS;
3103 GList *listP, *nodeP;
3105 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3106 while( nodeIf ) {
3107 AddressInterface *iface = nodeIf->data;
3109 nodeIf = g_list_next( nodeIf );
3111 if( ! iface->useInterface || iface->externalQuery )
3112 continue;
3114 nodeDS = iface->listSource;
3115 while( nodeDS ) {
3116 ds = nodeDS->data;
3118 /* Read address book */
3119 if( addrindex_ds_get_modify_flag( ds ) ) {
3120 addrindex_ds_read_data( ds );
3123 if( ! addrindex_ds_get_read_flag( ds ) ) {
3124 addrindex_ds_read_data( ds );
3127 /* Get all persons */
3128 listP = addrindex_ds_get_all_persons( ds );
3129 nodeP = listP;
3130 while( nodeP ) {
3131 ItemPerson *person = nodeP->data;
3133 callBackFunc(person, ds);
3134 nodeP = g_list_next( nodeP );
3136 /* Free up the list */
3137 g_list_free( listP );
3139 nodeDS = g_list_next( nodeDS );
3142 return TRUE;
3145 gchar *addrindex_get_picture_file(const gchar *emailaddr)
3147 AddressDataSource *ds;
3148 GList *nodeIf, *nodeDS;
3149 GList *listP, *nodeP;
3150 gboolean found = FALSE;
3151 gchar *filename = NULL;
3152 gchar *raw_addr = NULL;
3154 if (!emailaddr)
3155 return NULL;
3157 Xstrdup_a(raw_addr, emailaddr, return NULL);
3158 extract_address(raw_addr);
3160 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3161 while( nodeIf ) {
3162 AddressInterface *iface = nodeIf->data;
3164 nodeIf = g_list_next( nodeIf );
3166 if( ! iface->useInterface || iface->externalQuery )
3167 continue;
3169 nodeDS = iface->listSource;
3170 while( nodeDS && !found) {
3171 ds = nodeDS->data;
3173 /* Read address book */
3174 if( addrindex_ds_get_modify_flag( ds ) ) {
3175 addrindex_ds_read_data( ds );
3178 if( ! addrindex_ds_get_read_flag( ds ) ) {
3179 addrindex_ds_read_data( ds );
3182 /* Get all persons */
3183 listP = addrindex_ds_get_all_persons( ds );
3184 nodeP = listP;
3185 while( nodeP && !found) {
3186 GList *nodeM;
3187 ItemPerson *person = nodeP->data;
3188 nodeM = person->listEMail;
3189 while(nodeM) {
3190 ItemEMail *email = nodeM->data;
3191 if (email->address && !strcasecmp(raw_addr, email->address)) {
3192 found = TRUE;
3193 filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S,
3194 ADDRBOOK_DIR, G_DIR_SEPARATOR_S,
3195 person->picture, ".png", NULL );
3196 break;
3198 nodeM = nodeM->next;
3200 nodeP = g_list_next( nodeP );
3202 /* Free up the list */
3203 g_list_free( listP );
3205 nodeDS = g_list_next( nodeDS );
3209 return filename;
3212 #ifdef USE_LDAP
3213 GSList *addrindex_get_password_protected_ldap_servers()
3215 AddressInterface *iface;
3216 AddressDataSource *ds;
3217 GList *nodeIf;
3218 GList *nodeDS;
3219 GSList *list = NULL;
3220 LdapServer *server;
3221 LdapControl *ctl;
3223 nodeIf = _addressIndex_->searchOrder;
3224 while (nodeIf) {
3225 iface = nodeIf->data;
3226 nodeIf = g_list_next(nodeIf);
3228 if (!iface->useInterface)
3229 continue;
3230 if (!iface->externalQuery)
3231 continue;
3232 if (iface->type != ADDR_IF_LDAP)
3233 continue;
3235 nodeDS = iface->listSource;
3236 while (nodeDS) {
3237 ds = nodeDS->data;
3238 nodeDS = g_list_next(nodeDS);
3239 server = ds->rawDataSource;
3240 if (!server->searchFlag)
3241 continue;
3243 ctl = server->control;
3245 if (!ctl)
3246 continue;
3248 if (ctl->bindDN != NULL && strlen(ctl->bindDN)) {
3249 list = g_slist_append(list, server);
3254 return list;
3256 #endif /* USE_LDAP */
3259 * End of Source.