Fix bug #3574: Template addressing
[claws.git] / src / addrindex.c
blobd11e2108958ca53f7ffcb47b956c99563d5d131c
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"
45 #include "passwordstore.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 gchar *name;
165 GList *children;
166 GList *attributes;
170 * Build interface with default values.
172 * \param type Interface type.
173 * \param name Interface name.
174 * \param tagIf XML tag name for interface in address index file.
175 * \param tagDS XML tag name for datasource in address index file.
176 * \return Address interface object.
178 static AddressInterface *addrindex_create_interface(
179 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
181 AddressInterface *iface = g_new0( AddressInterface, 1 );
183 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
184 ADDRITEM_ID(iface) = NULL;
185 ADDRITEM_NAME(iface) = g_strdup( name );
186 ADDRITEM_PARENT(iface) = NULL;
187 ADDRITEM_SUBTYPE(iface) = type;
188 iface->type = type;
189 iface->name = g_strdup( name );
190 iface->listTag = g_strdup( tagIf );
191 iface->itemTag = g_strdup( tagDS );
192 iface->legacyFlag = FALSE;
193 iface->haveLibrary = TRUE;
194 iface->useInterface = TRUE;
195 iface->readOnly = TRUE;
197 /* Set callbacks to NULL values - override for each interface */
198 iface->getAccessFlag = NULL;
199 iface->getModifyFlag = NULL;
200 iface->getReadFlag = NULL;
201 iface->getStatusCode = NULL;
202 iface->getReadData = NULL;
203 iface->getRootFolder = NULL;
204 iface->getListFolder = NULL;
205 iface->getListPerson = NULL;
206 iface->getAllPersons = NULL;
207 iface->getAllGroups = NULL;
208 iface->getName = NULL;
209 iface->listSource = NULL;
211 /* Search stuff */
212 iface->externalQuery = FALSE;
213 iface->searchOrder = 0; /* Ignored */
214 iface->startSearch = NULL;
215 iface->stopSearch = NULL;
217 return iface;
221 * Build table of of all address book interfaces.
222 * \param addrIndex Address index object.
224 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
225 AddressInterface *iface;
227 /* Create intrinsic XML address book interface */
228 iface = addrindex_create_interface(
229 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
230 TAG_DS_ADDRESS_BOOK );
231 iface->readOnly = FALSE;
232 iface->getModifyFlag = ( void * ) addrbook_get_modified;
233 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
234 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
235 iface->getStatusCode = ( void * ) addrbook_get_status;
236 iface->getReadData = ( void * ) addrbook_read_data;
237 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
238 iface->getListFolder = ( void * ) addrbook_get_list_folder;
239 iface->getListPerson = ( void * ) addrbook_get_list_person;
240 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
241 iface->getAllGroups = ( void * ) addrbook_get_all_groups;
242 iface->getName = ( void * ) addrbook_get_name;
243 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
244 iface->searchOrder = 0;
246 /* Add to list of interfaces in address book */
247 addrIndex->interfaceList =
248 g_list_append( addrIndex->interfaceList, iface );
249 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
251 /* Create vCard interface */
252 iface = addrindex_create_interface(
253 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
254 iface->getModifyFlag = ( void * ) vcard_get_modified;
255 iface->getAccessFlag = ( void * ) vcard_get_accessed;
256 iface->getReadFlag = ( void * ) vcard_get_read_flag;
257 iface->getStatusCode = ( void * ) vcard_get_status;
258 iface->getReadData = ( void * ) vcard_read_data;
259 iface->getRootFolder = ( void * ) vcard_get_root_folder;
260 iface->getListFolder = ( void * ) vcard_get_list_folder;
261 iface->getListPerson = ( void * ) vcard_get_list_person;
262 iface->getAllPersons = ( void * ) vcard_get_all_persons;
263 iface->getName = ( void * ) vcard_get_name;
264 iface->setAccessFlag = ( void * ) vcard_set_accessed;
265 iface->searchOrder = 0;
266 addrIndex->interfaceList =
267 g_list_append( addrIndex->interfaceList, iface );
268 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
270 /* Create JPilot interface */
271 iface = addrindex_create_interface(
272 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
273 TAG_DS_JPILOT );
274 #ifdef USE_JPILOT
275 iface->haveLibrary = jpilot_test_pilot_lib();
276 iface->useInterface = iface->haveLibrary;
277 iface->getModifyFlag = ( void * ) jpilot_get_modified;
278 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
279 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
280 iface->getStatusCode = ( void * ) jpilot_get_status;
281 iface->getReadData = ( void * ) jpilot_read_data;
282 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
283 iface->getListFolder = ( void * ) jpilot_get_list_folder;
284 iface->getListPerson = ( void * ) jpilot_get_list_person;
285 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
286 iface->getName = ( void * ) jpilot_get_name;
287 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
288 iface->searchOrder = 0;
289 #else
290 iface->useInterface = FALSE;
291 iface->haveLibrary = FALSE;
292 #endif
293 addrIndex->interfaceList =
294 g_list_append( addrIndex->interfaceList, iface );
295 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
297 /* Create LDAP interface */
298 iface = addrindex_create_interface(
299 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
300 #ifdef USE_LDAP
301 iface->readOnly = FALSE;
302 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
303 iface->haveLibrary = ldaputil_test_ldap_lib();
304 iface->useInterface = iface->haveLibrary;
305 iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
306 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
307 iface->getReadFlag = ( void * ) ldapsvr_get_read_flag;
308 iface->getStatusCode = ( void * ) ldapsvr_get_status;
309 iface->getReadData = ( void * ) ldapsvr_read_data;
310 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
311 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
312 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
313 iface->getName = ( void * ) ldapsvr_get_name;
314 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
315 iface->externalQuery = TRUE;
316 iface->searchOrder = 1;
317 #else
318 iface->useInterface = FALSE;
319 iface->haveLibrary = FALSE;
320 #endif
321 addrIndex->interfaceList =
322 g_list_append( addrIndex->interfaceList, iface );
323 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
325 /* Two old legacy data sources (pre 0.7.0) */
326 iface = addrindex_create_interface(
327 ADDR_IF_COMMON, "Old Address - common",
328 TAG_IF_OLD_COMMON, NULL );
329 iface->legacyFlag = TRUE;
330 addrIndex->interfaceList =
331 g_list_append( addrIndex->interfaceList, iface );
332 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
334 iface = addrindex_create_interface(
335 ADDR_IF_COMMON, "Old Address - personal",
336 TAG_IF_OLD_PERSONAL, NULL );
337 iface->legacyFlag = TRUE;
338 addrIndex->interfaceList =
339 g_list_append( addrIndex->interfaceList, iface );
340 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
345 * Free DOM fragment.
346 * \param fragment Fragment to free.
348 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
349 GList *node;
351 /* Free children */
352 node = fragment->children;
353 while( node ) {
354 AddressIfFragment *child = node->data;
355 addrindex_free_fragment( child );
356 node->data = NULL;
357 node = g_list_next( node );
359 g_list_free( fragment->children );
361 /* Free attributes */
362 node = fragment->attributes;
363 while( node ) {
364 AddressIfAttrib *nv = node->data;
365 g_free( nv->name );
366 g_free( nv->value );
367 g_free( nv );
368 node->data = NULL;
369 node = g_list_next( node );
371 g_list_free( fragment->attributes );
373 g_free( fragment->name );
374 fragment->name = NULL;
375 fragment->attributes = NULL;
376 fragment->children = NULL;
378 g_free( fragment );
382 * Create a new data source.
383 * \param ifType Interface type to create.
384 * \return Initialized data source.
386 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
387 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
389 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
390 ADDRITEM_ID(ds) = NULL;
391 ADDRITEM_NAME(ds) = NULL;
392 ADDRITEM_PARENT(ds) = NULL;
393 ADDRITEM_SUBTYPE(ds) = 0;
394 ds->type = ifType;
395 ds->rawDataSource = NULL;
396 ds->interface = NULL;
397 return ds;
401 * Free up data source.
402 * \param ds Data source to free.
404 void addrindex_free_datasource( AddressDataSource *ds ) {
405 AddressInterface *iface;
407 cm_return_if_fail( ds != NULL );
409 iface = ds->interface;
410 if( ds->rawDataSource != NULL ) {
411 if( iface != NULL ) {
412 if( iface->useInterface ) {
413 if( iface->type == ADDR_IF_BOOK ) {
414 AddressBookFile *abf = ds->rawDataSource;
415 addrbook_free_book( abf );
417 else if( iface->type == ADDR_IF_VCARD ) {
418 VCardFile *vcf = ds->rawDataSource;
419 vcard_free( vcf );
421 #ifdef USE_JPILOT
422 else if( iface->type == ADDR_IF_JPILOT ) {
423 JPilotFile *jpf = ds->rawDataSource;
424 jpilot_free( jpf );
426 #endif
427 #ifdef USE_LDAP
428 else if( iface->type == ADDR_IF_LDAP ) {
429 LdapServer *server = ds->rawDataSource;
430 ldapsvr_free( server );
432 #endif
433 else {
436 else {
437 AddressIfFragment *fragment = ds->rawDataSource;
438 addrindex_free_fragment( fragment );
443 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
444 ADDRITEM_ID(ds) = NULL;
445 ADDRITEM_NAME(ds) = NULL;
446 ADDRITEM_PARENT(ds) = NULL;
447 ADDRITEM_SUBTYPE(ds) = 0;
448 ds->type = ADDR_IF_NONE;
449 ds->interface = NULL;
450 ds->rawDataSource = NULL;
452 g_free( ds );
456 * Free up all data sources for specified interface.
457 * \param iface Address interface to process.
459 static void addrindex_free_all_datasources( AddressInterface *iface ) {
460 GList *node = iface->listSource;
461 while( node ) {
462 AddressDataSource *ds = node->data;
463 addrindex_free_datasource( ds );
464 node->data = NULL;
465 node = g_list_next( node );
470 * Free up specified interface.
471 * \param iface Interface to process.
473 static void addrindex_free_interface( AddressInterface *iface ) {
474 /* Free up data sources */
475 addrindex_free_all_datasources( iface );
476 g_list_free( iface->listSource );
478 /* Free internal storage */
479 g_free( ADDRITEM_ID(iface) );
480 g_free( ADDRITEM_NAME(iface) );
481 g_free( iface->name );
482 g_free( iface->listTag );
483 g_free( iface->itemTag );
485 /* Clear all pointers */
486 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
487 ADDRITEM_ID(iface) = NULL;
488 ADDRITEM_NAME(iface) = NULL;
489 ADDRITEM_PARENT(iface) = NULL;
490 ADDRITEM_SUBTYPE(iface) = 0;
491 iface->type = ADDR_IF_NONE;
492 iface->name = NULL;
493 iface->listTag = NULL;
494 iface->itemTag = NULL;
495 iface->legacyFlag = FALSE;
496 iface->useInterface = FALSE;
497 iface->haveLibrary = FALSE;
498 iface->listSource = NULL;
500 /* Search stuff */
501 iface->searchOrder = 0;
502 iface->startSearch = NULL;
503 iface->stopSearch = NULL;
505 g_free( iface );
509 * Return cache ID for specified data source.
511 * \param addrIndex Address index.
512 * \param ds Data source.
513 * \return ID or NULL if not found. This should be <code>g_free()</code>
514 * when done.
516 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
517 gchar *cacheID = NULL;
518 AddrBookBase *adbase;
519 AddressCache *cache;
521 cm_return_val_if_fail( addrIndex != NULL, NULL );
522 cm_return_val_if_fail( ds != NULL, NULL );
524 adbase = ( AddrBookBase * ) ds->rawDataSource;
525 if( adbase ) {
526 cache = adbase->addressCache;
527 if( cache ) {
528 cacheID = g_strdup( cache->cacheID );
532 return cacheID;
536 * Return reference to data source for specified cacheID.
537 * \param addrIndex Address index.
538 * \param cacheID ID.
539 * \return Data source, or NULL if not found.
541 static AddressDataSource *addrindex_get_datasource(
542 AddressIndex *addrIndex, const gchar *cacheID )
544 cm_return_val_if_fail( addrIndex != NULL, NULL );
545 cm_return_val_if_fail( cacheID != NULL, NULL );
546 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
550 * Return reference to address cache for specified cacheID.
551 * \param addrIndex Address index.
552 * \param cacheID ID.
553 * \return Address cache, or NULL if not found.
555 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
556 AddressDataSource *ds;
557 AddrBookBase *adbase;
558 AddressCache *cache;
560 cm_return_val_if_fail( addrIndex != NULL, NULL );
561 cm_return_val_if_fail( cacheID != NULL, NULL );
563 cache = NULL;
564 ds = addrindex_get_datasource( addrIndex, cacheID );
565 if( ds ) {
566 adbase = ( AddrBookBase * ) ds->rawDataSource;
567 cache = adbase->addressCache;
569 return cache;
573 * Add data source into hash table.
574 * \param addrIndex Address index.
575 * \param ds Data source.
577 static void addrindex_hash_add_cache(
578 AddressIndex *addrIndex, AddressDataSource *ds )
580 gchar *cacheID;
582 cacheID = addrindex_get_cache_id( addrIndex, ds );
583 if( cacheID ) {
584 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
589 * Free hash table callback function.
591 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
592 g_free( key );
593 key = NULL;
594 value = NULL;
595 return TRUE;
599 * Free hash table of address cache items.
601 static void addrindex_free_cache_hash( GHashTable *table ) {
602 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
603 g_hash_table_destroy( table );
607 * Remove data source from internal hashtable.
608 * \param addrIndex Address index.
609 * \param ds Data source to remove.
611 static void addrindex_hash_remove_cache(
612 AddressIndex *addrIndex, AddressDataSource *ds )
614 gchar *cacheID;
616 cacheID = addrindex_get_cache_id( addrIndex, ds );
617 if( cacheID ) {
618 g_hash_table_remove( addrIndex->hashCache, cacheID );
619 g_free( cacheID );
620 cacheID = NULL;
625 * Create a new address index. This is created as a singleton object.
626 * \return Initialized address index object.
628 AddressIndex *addrindex_create_index( void ) {
629 AddressIndex *index;
631 if( _addressIndex_ == NULL ) {
632 index = g_new0( AddressIndex, 1 );
633 ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
634 ADDRITEM_ID(index) = NULL;
635 ADDRITEM_NAME(index) = g_strdup( "Address Index" );
636 ADDRITEM_PARENT(index) = NULL;
637 ADDRITEM_SUBTYPE(index) = 0;
638 index->filePath = NULL;
639 index->fileName = NULL;
640 index->retVal = MGU_SUCCESS;
641 index->needsConversion = FALSE;
642 index->wasConverted = FALSE;
643 index->conversionError = FALSE;
644 index->interfaceList = NULL;
645 index->lastType = ADDR_IF_NONE;
646 index->dirtyFlag = FALSE;
647 index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
648 index->loadedFlag = FALSE;
649 index->searchOrder = NULL;
650 addrindex_build_if_list( index );
651 _addressIndex_ = index;
653 return _addressIndex_;
657 * Property - Specify file path to address index file.
658 * \param addrIndex Address index.
659 * \param value Path to index file.
661 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
662 cm_return_if_fail( addrIndex != NULL );
663 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
667 * Property - Specify file name to address index file.
668 * \param addrIndex Address index.
669 * \param value File name.
671 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
672 cm_return_if_fail( addrIndex != NULL );
673 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
677 * Return list of address interfaces.
678 * \param addrIndex Address index.
679 * \return List of address interfaces.
681 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
682 cm_return_val_if_fail( addrIndex != NULL, NULL );
683 return addrIndex->interfaceList;
687 * Perform any other initialization of address index.
689 void addrindex_initialize( void ) {
690 qrymgr_initialize();
691 addrcompl_initialize();
695 * Perform any other teardown of address index.
697 void addrindex_teardown( void ) {
698 addrcompl_teardown();
699 qrymgr_teardown();
703 * Free up address index.
704 * \param addrIndex Address index.
706 void addrindex_free_index( AddressIndex *addrIndex ) {
707 GList *node;
709 cm_return_if_fail( addrIndex != NULL );
711 /* Search stuff */
712 g_list_free( addrIndex->searchOrder );
713 addrIndex->searchOrder = NULL;
715 /* Free internal storage */
716 g_free( ADDRITEM_ID(addrIndex) );
717 g_free( ADDRITEM_NAME(addrIndex) );
718 g_free( addrIndex->filePath );
719 g_free( addrIndex->fileName );
721 /* Clear pointers */
722 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
723 ADDRITEM_ID(addrIndex) = NULL;
724 ADDRITEM_NAME(addrIndex) = NULL;
725 ADDRITEM_PARENT(addrIndex) = NULL;
726 ADDRITEM_SUBTYPE(addrIndex) = 0;
727 addrIndex->filePath = NULL;
728 addrIndex->fileName = NULL;
729 addrIndex->retVal = MGU_SUCCESS;
730 addrIndex->needsConversion = FALSE;
731 addrIndex->wasConverted = FALSE;
732 addrIndex->conversionError = FALSE;
733 addrIndex->lastType = ADDR_IF_NONE;
734 addrIndex->dirtyFlag = FALSE;
736 /* Free up interfaces */
737 node = addrIndex->interfaceList;
738 while( node ) {
739 AddressInterface *iface = node->data;
740 addrindex_free_interface( iface );
741 node = g_list_next( node );
743 g_list_free( addrIndex->interfaceList );
744 addrIndex->interfaceList = NULL;
746 /* Free up hash cache */
747 addrindex_free_cache_hash( addrIndex->hashCache );
748 addrIndex->hashCache = NULL;
750 addrIndex->loadedFlag = FALSE;
752 g_free( addrIndex );
753 addrIndex = NULL;
754 _addressIndex_ = NULL;
758 * Print address index.
759 * \param addrIndex Address index.
760 * \parem stream Stream to print.
762 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
763 cm_return_if_fail( addrIndex != NULL );
764 fprintf( stream, "AddressIndex:\n" );
765 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
766 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
767 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
768 fprintf( stream, "\tconverted: '%s'\n",
769 addrIndex->wasConverted ? "yes" : "no" );
770 fprintf( stream, "\tcvt error: '%s'\n",
771 addrIndex->conversionError ? "yes" : "no" );
772 fprintf( stream, "\t---\n" );
776 * Retrieve reference to address interface for specified interface type.
777 * \param addrIndex Address index.
778 * \param ifType Interface type.
779 * \return Address interface, or NULL if not found.
781 static AddressInterface *addrindex_get_interface(
782 AddressIndex *addrIndex, AddressIfType ifType )
784 AddressInterface *retVal = NULL;
785 GList *node;
787 cm_return_val_if_fail( addrIndex != NULL, NULL );
789 node = addrIndex->interfaceList;
790 while( node ) {
791 AddressInterface *iface = node->data;
792 node = g_list_next( node );
793 if( iface->type == ifType ) {
794 retVal = iface;
795 break;
798 return retVal;
802 * Add raw data source to index. The raw data object (an AddressBookFile or
803 * VCardFile object, for example) should be supplied as the raw dataSource
804 * argument.
806 * \param addrIndex Address index.
807 * \param ifType Interface type to add.
808 * \param dataSource Actual raw data source to add.
809 * \return Data source added, or NULL if invalid interface type.
811 AddressDataSource *addrindex_index_add_datasource(
812 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
814 AddressInterface *iface;
815 AddressDataSource *ds = NULL;
817 cm_return_val_if_fail( addrIndex != NULL, NULL );
818 cm_return_val_if_fail( dataSource != NULL, NULL );
820 iface = addrindex_get_interface( addrIndex, ifType );
821 if( iface ) {
822 ds = addrindex_create_datasource( ifType );
823 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
824 ds->type = ifType;
825 ds->rawDataSource = dataSource;
826 ds->interface = iface;
827 iface->listSource = g_list_append( iface->listSource, ds );
828 addrIndex->dirtyFlag = TRUE;
830 addrindex_hash_add_cache( addrIndex, ds );
832 return ds;
836 * Remove specified data source from index.
837 * \param addrIndex Address index.
838 * \param dataSource Data source to add.
839 * \return Reference to data source if removed, or NULL if data source was not
840 * found in index. Note the this object must still be freed.
842 AddressDataSource *addrindex_index_remove_datasource(
843 AddressIndex *addrIndex, AddressDataSource *dataSource )
845 AddressDataSource *retVal = FALSE;
846 AddressInterface *iface;
848 cm_return_val_if_fail( addrIndex != NULL, NULL );
849 cm_return_val_if_fail( dataSource != NULL, NULL );
851 iface = addrindex_get_interface( addrIndex, dataSource->type );
852 if( iface ) {
853 iface->listSource = g_list_remove( iface->listSource, dataSource );
854 addrIndex->dirtyFlag = TRUE;
855 dataSource->interface = NULL;
857 /* Remove cache from hash table */
858 addrindex_hash_remove_cache( addrIndex, dataSource );
860 retVal = dataSource;
862 return retVal;
866 * Retrieve a reference to address interface for specified interface type and
867 * XML interface tag name.
868 * \param addrIndex Address index.
869 * \param tag XML interface tag name to match.
870 * \param ifType Interface type to match.
871 * \return Reference to address index, or NULL if not found in index.
873 static AddressInterface *addrindex_tag_get_interface(
874 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
876 AddressInterface *retVal = NULL;
877 GList *node = addrIndex->interfaceList;
879 while( node ) {
880 AddressInterface *iface = node->data;
881 node = g_list_next( node );
882 if( tag ) {
883 if( strcmp( iface->listTag, tag ) == 0 ) {
884 retVal = iface;
885 break;
888 else {
889 if( iface->type == ifType ) {
890 retVal = iface;
891 break;
895 return retVal;
899 * Retrieve a reference to address interface for specified interface type and
900 * XML datasource tag name.
901 * \param addrIndex Address index.
902 * \param ifType Interface type to match.
903 * \param tag XML datasource tag name to match.
904 * \return Reference to address index, or NULL if not found in index.
906 static AddressInterface *addrindex_tag_get_datasource(
907 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
909 AddressInterface *retVal = NULL;
910 GList *node = addrIndex->interfaceList;
912 while( node ) {
913 AddressInterface *iface = node->data;
914 node = g_list_next( node );
915 if( iface->type == ifType && iface->itemTag ) {
916 if( strcmp( iface->itemTag, tag ) == 0 ) {
917 retVal = iface;
918 break;
922 return retVal;
925 /* **********************************************************************
926 * Interface XML parsing functions.
927 * ***********************************************************************
931 * Write start of XML element to file.
932 * \param fp File.
933 * \param lvl Indentation level.
934 * \param name Element name.
936 static int addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
937 gint i;
938 for( i = 0; i < lvl; i++ )
939 if (fputs( " ", fp ) == EOF)
940 return -1;
941 if (fputs( "<", fp ) == EOF)
942 return -1;
943 if (fputs( name, fp ) == EOF)
944 return -1;
945 return 0;
949 * Write end of XML element to file.
950 * \param fp File.
951 * \param lvl Indentation level.
952 * \param name Element name.
954 static int addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
955 gint i;
956 for( i = 0; i < lvl; i++ )
957 if (fputs( " ", fp ) == EOF)
958 return -1;
959 if (fputs( "</", fp ) == EOF)
960 return -1;
961 if (fputs( name, fp ) == EOF)
962 return -1;
963 if (fputs( ">\n", fp ) == EOF)
964 return -1;
965 return 0;
969 * Write XML attribute to file.
970 * \param fp File.
971 * \param name Attribute name.
972 * \param value Attribute value.
974 static int addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
975 if (fputs( " ", fp ) == EOF)
976 return -1;
977 if (fputs( name, fp ) == EOF)
978 return -1;
979 if (fputs( "=\"", fp ) == EOF)
980 return -1;
981 if (xml_file_put_escape_str( fp, value ) < 0)
982 return -1;
983 if (fputs( "\"", fp ) == EOF)
984 return -1;
985 return 0;
988 #if !defined(USE_LDAP) || !defined(USE_JPILOT)
990 * Return DOM fragment for current XML tag from file.
991 * \param file XML file being processed.
992 * \return Fragment representing DOM fragment for configuration element.
994 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
995 AddressIfFragment *fragment;
996 AddressIfFragment *child;
997 AddressIfAttrib *nv;
998 XMLTag *xtag;
999 GList *list;
1000 GList *attr;
1001 gchar *name;
1002 gchar *value;
1003 guint prevLevel;
1004 gint rc;
1006 /* g_print( "addrindex_read_fragment\n" ); */
1008 prevLevel = file->level;
1010 /* Get current tag name */
1011 xtag = xml_get_current_tag( file );
1013 /* Create new fragment */
1014 fragment = g_new0( AddressIfFragment, 1 );
1015 fragment->name = g_strdup( xtag->tag );
1016 fragment->children = NULL;
1017 fragment->attributes = NULL;
1019 /* Read attributes */
1020 list = NULL;
1021 attr = xml_get_current_tag_attr( file );
1022 while( attr ) {
1023 name = ((XMLAttr *)attr->data)->name;
1024 value = ((XMLAttr *)attr->data)->value;
1025 nv = g_new0( AddressIfAttrib, 1 );
1026 nv->name = g_strdup( name );
1027 nv->value = g_strdup( value );
1028 list = g_list_append( list, nv );
1029 attr = g_list_next( attr );
1031 fragment->attributes = list;
1033 /* Now read the children */
1034 while( TRUE ) {
1035 rc = xml_parse_next_tag( file );
1036 if( rc != 0 ) {
1037 /* End of file? */
1038 break;
1040 if( file->level < prevLevel ) {
1041 /* We must be above level we start at */
1042 break;
1044 child = addrindex_read_fragment( file );
1045 fragment->children = g_list_append( fragment->children, child );
1048 return fragment;
1052 * Write DOM fragment to file.
1053 * \param fp File to write.
1054 * \param fragment DOM fragment for configuration element.
1055 * \param lvl Indent level.
1057 static int addrindex_write_fragment(
1058 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1060 GList *node;
1062 if( fragment ) {
1063 if (addrindex_write_elem_s( fp, lvl, fragment->name ) < 0)
1064 return -1;
1065 node = fragment->attributes;
1066 while( node ) {
1067 AddressIfAttrib *nv = node->data;
1068 if (addrindex_write_attr( fp, nv->name, nv->value ) < 0)
1069 return -1;
1070 node = g_list_next( node );
1072 if( fragment->children ) {
1073 if (fputs(" >\n", fp) == EOF)
1074 return -1;
1076 /* Output children */
1077 node = fragment->children;
1078 while( node ) {
1079 AddressIfFragment *child = node->data;
1080 if (addrindex_write_fragment( fp, child, 1+lvl ) < 0)
1081 return -1;
1082 node = g_list_next( node );
1085 /* Output closing tag */
1086 if (addrindex_write_elem_e( fp, lvl, fragment->name ) < 0)
1087 return -1;
1089 else {
1090 if (fputs(" />\n", fp) == EOF)
1091 return -1;
1095 return 0;
1097 #endif
1099 * Read/parse address index file, creating a data source for a regular
1100 * intrinsic XML addressbook.
1101 * \param file Address index file.
1102 * \return Data source.
1104 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1105 AddressDataSource *ds;
1106 AddressBookFile *abf;
1107 GList *attr;
1109 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1110 abf = addrbook_create_book();
1111 attr = xml_get_current_tag_attr( file );
1112 while( attr ) {
1113 gchar *name = ((XMLAttr *)attr->data)->name;
1114 gchar *value = ((XMLAttr *)attr->data)->value;
1115 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1116 addrbook_set_name( abf, value );
1118 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1119 addrbook_set_file( abf, value );
1121 attr = g_list_next( attr );
1123 ds->rawDataSource = abf;
1124 return ds;
1127 static int addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1128 AddressBookFile *abf = ds->rawDataSource;
1129 if( abf ) {
1130 if (addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK ) < 0)
1131 return -1;
1132 if (addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) ) < 0)
1133 return -1;
1134 if (addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName ) < 0)
1135 return -1;
1136 if (fputs( " />\n", fp ) == EOF)
1137 return -1;
1139 return 0;
1142 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1143 AddressDataSource *ds;
1144 VCardFile *vcf;
1145 GList *attr;
1147 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1148 vcf = vcard_create();
1149 attr = xml_get_current_tag_attr( file );
1150 while( attr ) {
1151 gchar *name = ((XMLAttr *)attr->data)->name;
1152 gchar *value = ((XMLAttr *)attr->data)->value;
1153 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1154 vcard_set_name( vcf, value );
1156 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1157 vcard_set_file( vcf, value );
1159 attr = g_list_next( attr );
1161 ds->rawDataSource = vcf;
1162 return ds;
1165 static int addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1166 VCardFile *vcf = ds->rawDataSource;
1167 if( vcf ) {
1168 if (addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD ) < 0)
1169 return -1;
1170 if (addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) ) < 0)
1171 return -1;
1172 if (addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path ) < 0)
1173 return -1;
1174 if (fputs( " />\n", fp ) == EOF)
1175 return -1;
1177 return 0;
1180 #ifdef USE_JPILOT
1181 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1182 AddressDataSource *ds;
1183 JPilotFile *jpf;
1184 GList *attr;
1186 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1187 jpf = jpilot_create();
1188 attr = xml_get_current_tag_attr( file );
1189 while( attr ) {
1190 gchar *name = ((XMLAttr *)attr->data)->name;
1191 gchar *value = ((XMLAttr *)attr->data)->value;
1192 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1193 jpilot_set_name( jpf, value );
1195 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1196 jpilot_set_file( jpf, value );
1198 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1199 jpilot_add_custom_label( jpf, value );
1201 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1202 jpilot_add_custom_label( jpf, value );
1204 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1205 jpilot_add_custom_label( jpf, value );
1207 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1208 jpilot_add_custom_label( jpf, value );
1210 attr = g_list_next( attr );
1212 ds->rawDataSource = jpf;
1213 return ds;
1216 static int addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1217 JPilotFile *jpf = ds->rawDataSource;
1218 if( jpf ) {
1219 gint ind;
1220 GList *node;
1221 GList *customLbl = jpilot_get_custom_labels( jpf );
1222 if (addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT ) < 0)
1223 return -1;
1224 if (addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) ) < 0)
1225 return -1;
1226 if (addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path ) < 0)
1227 return -1;
1228 node = customLbl;
1229 ind = 1;
1230 while( node ) {
1231 gchar name[256];
1232 g_snprintf( name, sizeof(name), "%s%d",
1233 ATTAG_JPILOT_CUSTOM, ind );
1234 if (addrindex_write_attr( fp, name, node->data ) < 0)
1235 return -1;
1236 ind++;
1237 node = g_list_next( node );
1239 if (fputs( " />\n", fp ) == EOF)
1240 return -1;
1242 return 0;
1245 #else
1247 * Just read/write DOM fragments (preserve data found in file).
1249 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1250 AddressDataSource *ds;
1252 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1253 ds->rawDataSource = addrindex_read_fragment( file );
1254 return ds;
1257 static int addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1258 AddressIfFragment *fragment = ds->rawDataSource;
1259 if( fragment ) {
1260 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1261 return -1;
1263 return 0;
1265 #endif
1267 #ifdef USE_LDAP
1269 * Parse LDAP criteria attribute data from XML file.
1270 * \param file Index file.
1271 * \param ctl LDAP control object to populate.
1273 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1274 guint prevLevel;
1275 XMLTag *xtag;
1276 XMLTag *xtagPrev;
1277 gint rc;
1278 GList *attr;
1279 GList *list;
1280 GList *node;
1282 if( file == NULL ) {
1283 return;
1286 list = NULL;
1287 prevLevel = file->level;
1288 xtagPrev = xml_get_current_tag( file );
1289 while( TRUE ) {
1290 rc = xml_parse_next_tag( file );
1291 if( rc != 0 ) {
1292 /* Terminate prematurely */
1293 mgu_free_dlist( list );
1294 list = NULL;
1295 return;
1297 if( file->level < prevLevel ) {
1298 /* We must be above level we start at */
1299 break;
1302 /* Get a tag (element) */
1303 xtag = xml_get_current_tag( file );
1304 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1305 /* LDAP criteria attribute */
1306 attr = xml_get_current_tag_attr( file );
1307 while( attr ) {
1308 gchar *name = ((XMLAttr *)attr->data)->name;
1309 gchar *value = ((XMLAttr *)attr->data)->value;
1310 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1311 if( value && strlen( value ) > 0 ) {
1312 list = g_list_append(
1313 list, g_strdup( value ) );
1316 attr = g_list_next( attr );
1319 else {
1320 if( xtag != xtagPrev ) {
1321 /* Found a new tag */
1322 break;
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;
1357 gchar *password = NULL;
1359 /* g_print( "addrindex_parse_ldap\n" ); */
1360 /* Set up some defaults */
1361 bDynSearch = FALSE;
1362 bTLS = FALSE;
1363 bSSL = FALSE;
1364 iMatch = LDAPCTL_MATCH_BEGINWITH;
1366 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1367 ctl = ldapctl_create();
1368 attr = xml_get_current_tag_attr( file );
1369 while( attr ) {
1370 gchar *name = ((XMLAttr *)attr->data)->name;
1371 gchar *value = ((XMLAttr *)attr->data)->value;
1372 gint ivalue = atoi( value );
1374 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1375 g_free( serverName );
1376 serverName = g_strdup( value );
1378 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1379 ldapctl_set_host( ctl, value );
1381 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1382 ldapctl_set_port( ctl, ivalue );
1384 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1385 ldapctl_set_base_dn( ctl, value );
1387 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1388 ldapctl_set_bind_dn( ctl, value );
1390 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1391 password = value;
1393 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1394 g_free( criteria );
1395 criteria = g_strdup( value );
1396 g_print("criteria %s\n", criteria);
1398 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1399 ldapctl_set_max_entries( ctl, ivalue );
1401 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1402 ldapctl_set_timeout( ctl, ivalue );
1404 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1405 ldapctl_set_max_query_age( ctl, ivalue );
1407 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1408 bDynSearch = FALSE;
1409 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1410 bDynSearch = TRUE;
1413 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1414 iMatch = LDAPCTL_MATCH_BEGINWITH;
1415 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1416 iMatch = LDAPCTL_MATCH_CONTAINS;
1419 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1420 bTLS = FALSE;
1421 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1422 bTLS = TRUE;
1425 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1426 bSSL = FALSE;
1427 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1428 bSSL = TRUE;
1431 attr = g_list_next( attr );
1434 if (password != NULL)
1435 passwd_store_set(PWS_CORE, "LDAP", ctl->hostName, password, TRUE);
1437 server = ldapsvr_create_noctl();
1438 ldapsvr_set_name( server, serverName );
1439 ldapsvr_set_search_flag( server, bDynSearch );
1440 ldapctl_set_matching_option( ctl, iMatch );
1441 ldapctl_set_tls( ctl, bTLS );
1442 ldapctl_set_ssl( ctl, bSSL );
1443 g_free( serverName );
1444 ldapsvr_set_control( server, ctl );
1445 ds->rawDataSource = server;
1447 addrindex_parse_ldap_attrlist( file, ctl );
1449 * If criteria have been specified and no attributes were listed, then
1450 * convert old style criteria into an attribute list. Any criteria will
1451 * be dropped when saving data.
1453 if( criteria ) {
1454 if( ! ldapctl_get_criteria_list( ctl ) ) {
1455 ldapctl_parse_ldap_search( ctl, criteria );
1457 g_free( criteria );
1459 /* ldapsvr_print_data( server, stdout ); */
1461 return ds;
1464 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1465 LdapServer *server = ds->rawDataSource;
1466 LdapControl *ctl = NULL;
1467 GList *node;
1468 gchar value[256];
1470 if( server ) {
1471 ctl = server->control;
1473 if( ctl == NULL ) return 0;
1475 /* Output start element with attributes */
1476 if (addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP ) < 0)
1477 return -1;
1478 if (addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) ) < 0)
1479 return -1;
1480 if (addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName ) < 0)
1481 return -1;
1483 sprintf( value, "%d", ctl->port );
1484 if (addrindex_write_attr( fp, ATTAG_LDAP_PORT, value ) < 0)
1485 return -1;
1487 if (addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN ) < 0)
1488 return -1;
1489 if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN ) < 0)
1490 return -1;
1492 sprintf( value, "%d", ctl->maxEntries );
1493 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value ) < 0)
1494 return -1;
1495 sprintf( value, "%d", ctl->timeOut );
1496 if (addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value ) < 0)
1497 return -1;
1498 sprintf( value, "%d", ctl->maxQueryAge );
1499 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value ) < 0)
1500 return -1;
1502 if (addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1503 server->searchFlag ?
1504 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1505 return -1;
1507 if (addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1508 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1509 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN ) < 0)
1510 return -1;
1512 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1513 ctl->enableTLS ?
1514 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1515 return -1;
1516 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1517 ctl->enableSSL ?
1518 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1519 return -1;
1521 if (fputs(" >\n", fp) == EOF)
1522 return -1;
1524 /* Output attributes */
1525 node = ldapctl_get_criteria_list( ctl );
1526 while( node ) {
1527 if (addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH ) < 0)
1528 return -1;
1529 if (addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data ) < 0)
1530 return -1;
1531 if (fputs(" />\n", fp) == EOF)
1532 return -1;
1533 node = g_list_next( node );
1536 /* End of element */
1537 if (addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP ) < 0)
1538 return -1;
1540 return 0;
1543 #else
1545 * Just read/write DOM fragments (preserve data found in file).
1547 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1548 AddressDataSource *ds;
1550 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1551 ds->rawDataSource = addrindex_read_fragment( file );
1552 return ds;
1555 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1556 AddressIfFragment *fragment = ds->rawDataSource;
1557 if( fragment ) {
1558 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1559 return -1;
1561 return 0;
1563 #endif
1565 /* **********************************************************************
1566 * Address index I/O functions.
1567 * ***********************************************************************
1570 * Read address index file, creating appropriate data sources for each address
1571 * index file entry.
1573 * \param addrIndex Address index.
1574 * \param file Address index file.
1576 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1577 XMLTag *xtag;
1578 AddressInterface *iface = NULL, *dsIFace = NULL;
1579 AddressDataSource *ds;
1580 gint rc;
1582 addrIndex->loadedFlag = FALSE;
1583 for (;;) {
1584 rc = xml_parse_next_tag( file );
1585 if( rc < 0 || file->level == 0 ) return;
1587 xtag = xml_get_current_tag( file );
1589 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1590 if( iface ) {
1591 addrIndex->lastType = iface->type;
1592 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1594 else {
1595 dsIFace = addrindex_tag_get_datasource(
1596 addrIndex, addrIndex->lastType, xtag->tag );
1597 if( dsIFace ) {
1598 /* Add data source to list */
1599 ds = NULL;
1600 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1601 ds = addrindex_parse_book( file );
1602 if( ds->rawDataSource ) {
1603 addrbook_set_path( ds->rawDataSource,
1604 addrIndex->filePath );
1607 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1608 ds = addrindex_parse_vcard( file );
1610 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1611 ds = addrindex_parse_jpilot( file );
1613 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1614 ds = addrindex_parse_ldap( file );
1616 if( ds ) {
1617 ds->interface = dsIFace;
1618 addrindex_hash_add_cache( addrIndex, ds );
1619 dsIFace->listSource =
1620 g_list_append( dsIFace->listSource, ds );
1628 * Search order sorting comparison function for building search order list.
1630 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1631 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1632 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1634 return ifaceA->searchOrder - ifaceB->searchOrder;
1638 * Build list of data sources to process.
1639 * \param addrIndex Address index object.
1641 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1642 GList *nodeIf;
1644 /* Clear existing list */
1645 g_list_free( addrIndex->searchOrder );
1646 addrIndex->searchOrder = NULL;
1648 /* Build new list */
1649 nodeIf = addrIndex->interfaceList;
1650 while( nodeIf ) {
1651 AddressInterface *iface = nodeIf->data;
1652 if( iface->useInterface ) {
1653 if( iface->searchOrder > 0 ) {
1654 /* Add to search order list */
1655 addrIndex->searchOrder = g_list_insert_sorted(
1656 addrIndex->searchOrder, iface,
1657 addrindex_search_order_compare );
1660 nodeIf = g_list_next( nodeIf );
1664 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1665 XMLFile *file = NULL;
1666 gchar *fileSpec = NULL;
1668 cm_return_val_if_fail( addrIndex != NULL, -1 );
1670 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1671 addrIndex->retVal = MGU_NO_FILE;
1672 file = xml_open_file( fileSpec );
1673 g_free( fileSpec );
1675 if( file == NULL ) {
1677 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1679 return addrIndex->retVal;
1682 addrIndex->retVal = MGU_BAD_FORMAT;
1683 if( xml_get_dtd( file ) == 0 ) {
1684 if( xml_parse_next_tag( file ) == 0 ) {
1685 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1686 addrindex_read_index( addrIndex, file );
1687 addrIndex->retVal = MGU_SUCCESS;
1691 xml_close_file( file );
1693 addrindex_build_search_order( addrIndex );
1695 return addrIndex->retVal;
1698 static int addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1699 GList *nodeIF, *nodeDS;
1700 gint lvlList = 1;
1701 gint lvlItem = 1 + lvlList;
1703 nodeIF = addrIndex->interfaceList;
1704 while( nodeIF ) {
1705 AddressInterface *iface = nodeIF->data;
1706 if( ! iface->legacyFlag ) {
1707 nodeDS = iface->listSource;
1708 if (addrindex_write_elem_s( fp, lvlList, iface->listTag ) < 0)
1709 return -1;
1710 if (fputs( ">\n", fp ) == EOF)
1711 return -1;
1712 while( nodeDS ) {
1713 AddressDataSource *ds = nodeDS->data;
1714 if( ds ) {
1715 if( iface->type == ADDR_IF_BOOK ) {
1716 if (addrindex_write_book( fp, ds, lvlItem ) < 0)
1717 return -1;
1719 if( iface->type == ADDR_IF_VCARD ) {
1720 if (addrindex_write_vcard( fp, ds, lvlItem ) < 0)
1721 return -1;
1723 if( iface->type == ADDR_IF_JPILOT ) {
1724 if (addrindex_write_jpilot( fp, ds, lvlItem ) < 0)
1725 return -1;
1727 if( iface->type == ADDR_IF_LDAP ) {
1728 if (addrindex_write_ldap( fp, ds, lvlItem ) < 0)
1729 return -1;
1732 nodeDS = g_list_next( nodeDS );
1734 if (addrindex_write_elem_e( fp, lvlList, iface->listTag ) < 0)
1735 return -1;
1737 nodeIF = g_list_next( nodeIF );
1739 return 0;
1743 * Write data to specified file.
1744 * Enter: addrIndex Address index object.
1745 * newFile New file name.
1746 * return: Status code, from addrIndex->retVal.
1747 * Note: File will be created in directory specified by addrIndex.
1749 static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1750 FILE *fp;
1751 gchar *fileSpec;
1752 #ifndef DEV_STANDALONE
1753 PrefFile *pfile;
1754 #endif
1756 cm_return_val_if_fail( addrIndex != NULL, -1 );
1758 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1759 addrIndex->retVal = MGU_OPEN_FILE;
1760 #ifdef DEV_STANDALONE
1761 fp = g_fopen( fileSpec, "wb" );
1762 g_free( fileSpec );
1763 if( fp ) {
1764 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1765 #else
1766 pfile = prefs_write_open( fileSpec );
1767 g_free( fileSpec );
1768 if( pfile ) {
1769 fp = pfile->fp;
1770 if (fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL ) < 0)
1771 goto fail;
1772 #endif
1773 if (addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1774 goto fail;
1775 if (fputs( ">\n", fp ) == EOF)
1776 goto fail;
1778 if (addrindex_write_index( addrIndex, fp ) < 0)
1779 goto fail;
1780 if (addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1781 goto fail;
1783 addrIndex->retVal = MGU_SUCCESS;
1784 #ifdef DEV_STANDALONE
1785 fclose( fp );
1786 #else
1787 if( prefs_file_close( pfile ) < 0 ) {
1788 addrIndex->retVal = MGU_ERROR_WRITE;
1790 #endif
1793 fileSpec = NULL;
1794 return addrIndex->retVal;
1795 fail:
1796 g_warning("error writing AB index");
1797 addrIndex->retVal = MGU_ERROR_WRITE;
1798 if (pfile)
1799 prefs_file_close_revert( pfile );
1800 return addrIndex->retVal;
1804 * Save address index data to original file.
1805 * return: Status code, from addrIndex->retVal.
1807 gint addrindex_save_data( AddressIndex *addrIndex ) {
1808 #ifdef USE_LDAP
1809 GList *nodeIf;
1810 GList *nodeDS;
1811 #endif
1813 cm_return_val_if_fail( addrIndex != NULL, -1 );
1815 #ifdef USE_LDAP
1816 nodeIf = addrIndex->interfaceList;
1817 /* save LDAP interfaces */
1818 while ( nodeIf ) {
1819 AddressInterface *iface = nodeIf->data;
1820 if( iface->type == ADDR_IF_LDAP ) {
1821 nodeDS = iface->listSource;
1822 while( nodeDS ) {
1823 AddressDataSource *ds = nodeDS->data;
1824 LdapServer *abf = ds->rawDataSource;
1825 if( ldapsvr_get_read_flag( abf ) ) {
1826 if( ldapsvr_get_modified( abf ) ) {
1827 ldapsvr_update_book( abf, NULL );
1828 if( abf->retVal != LDAPRC_SUCCESS ) {
1829 alertpanel( _("Address(es) update"),
1830 _("Update failed. Changes not written to Directory."),
1831 GTK_STOCK_CLOSE, NULL, NULL );
1833 else {
1834 abf->retVal = MGU_SUCCESS;
1835 ldapsvr_set_modified( abf, FALSE );
1839 nodeDS = g_list_next( nodeDS );
1841 break;
1843 nodeIf = g_list_next( nodeIf );
1845 #endif
1846 addrIndex->retVal = MGU_NO_FILE;
1847 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1848 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1850 addrindex_write_to( addrIndex, addrIndex->fileName );
1851 if( addrIndex->retVal == MGU_SUCCESS ) {
1852 addrIndex->dirtyFlag = FALSE;
1854 return addrIndex->retVal;
1858 * Save all address book files which may have changed.
1859 * Return: Status code, set if there was a problem saving data.
1861 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1862 gint retVal = MGU_SUCCESS;
1863 GList *nodeIf, *nodeDS;
1865 nodeIf = addrIndex->interfaceList;
1866 while( nodeIf ) {
1867 AddressInterface *iface = nodeIf->data;
1868 if( iface->type == ADDR_IF_BOOK ) {
1869 nodeDS = iface->listSource;
1870 while( nodeDS ) {
1871 AddressDataSource *ds = nodeDS->data;
1872 AddressBookFile *abf = ds->rawDataSource;
1873 if( addrbook_get_dirty( abf ) ) {
1874 if( addrbook_get_read_flag( abf ) ) {
1875 addrbook_save_data( abf );
1876 if( abf->retVal != MGU_SUCCESS ) {
1877 retVal = abf->retVal;
1881 nodeDS = g_list_next( nodeDS );
1883 break;
1885 nodeIf = g_list_next( nodeIf );
1887 return retVal;
1891 /* **********************************************************************
1892 * Address book conversion to new format.
1893 * ***********************************************************************
1896 #define ELTAG_IF_OLD_FOLDER "folder"
1897 #define ELTAG_IF_OLD_GROUP "group"
1898 #define ELTAG_IF_OLD_ITEM "item"
1899 #define ELTAG_IF_OLD_NAME "name"
1900 #define ELTAG_IF_OLD_ADDRESS "address"
1901 #define ELTAG_IF_OLD_REMARKS "remarks"
1902 #define ATTAG_IF_OLD_NAME "name"
1904 #define TEMPNODE_ROOT 0
1905 #define TEMPNODE_FOLDER 1
1906 #define TEMPNODE_GROUP 2
1907 #define TEMPNODE_ADDRESS 3
1909 typedef struct _AddressCvt_Node AddressCvtNode;
1910 struct _AddressCvt_Node {
1911 gint type;
1912 gchar *name;
1913 gchar *address;
1914 gchar *remarks;
1915 GList *list;
1919 * Parse current address item.
1921 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1922 gchar *element;
1923 guint level;
1924 AddressCvtNode *nn;
1926 nn = g_new0( AddressCvtNode, 1 );
1927 nn->type = TEMPNODE_ADDRESS;
1928 nn->list = NULL;
1930 level = file->level;
1932 for (;;) {
1933 xml_parse_next_tag(file);
1934 if (file->level < level) return nn;
1936 element = xml_get_element( file );
1937 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1938 nn->name = g_strdup( element );
1940 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1941 nn->address = g_strdup( element );
1943 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1944 nn->remarks = g_strdup( element );
1946 g_free(element);
1947 xml_parse_next_tag(file);
1952 * Create a temporary node below specified node.
1954 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1955 AddressCvtNode *nn;
1956 nn = g_new0( AddressCvtNode, 1 );
1957 nn->type = type;
1958 nn->name = g_strdup( name );
1959 nn->remarks = g_strdup( rem );
1960 node->list = g_list_append( node->list, nn );
1961 return nn;
1965 * Process current temporary node.
1967 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1968 GList *attr;
1969 guint prev_level;
1970 AddressCvtNode *newNode = NULL;
1971 gchar *name;
1972 gchar *value;
1974 for (;;) {
1975 prev_level = file->level;
1976 xml_parse_next_tag( file );
1977 if (file->level < prev_level) return;
1978 name = NULL;
1979 value = NULL;
1981 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1982 attr = xml_get_current_tag_attr(file);
1983 if (attr) {
1984 name = ((XMLAttr *)attr->data)->name;
1985 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1986 value = ((XMLAttr *)attr->data)->value;
1989 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1990 addrindex_add_obj( file, newNode );
1993 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1994 attr = xml_get_current_tag_attr(file);
1995 if (attr) {
1996 name = ((XMLAttr *)attr->data)->name;
1997 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1998 value = ((XMLAttr *)attr->data)->value;
2001 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
2002 addrindex_add_obj( file, newNode );
2004 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
2005 newNode = addrindex_parse_item( file );
2006 node->list = g_list_append( node->list, newNode );
2008 else {
2009 g_warning("Invalid tag");
2015 * Consume all nodes below current tag.
2017 static void addrindex_consume_tree( XMLFile *file ) {
2018 guint prev_level;
2020 for (;;) {
2021 prev_level = file->level;
2022 xml_parse_next_tag( file );
2023 if (file->level < prev_level)
2024 return;
2026 addrindex_consume_tree( file );
2031 * Free up temporary tree.
2033 static void addrindex_free_node( AddressCvtNode *node ) {
2034 GList *list = node->list;
2036 while( list ) {
2037 AddressCvtNode *lNode = list->data;
2038 list = g_list_next( list );
2039 addrindex_free_node( lNode );
2041 node->type = TEMPNODE_ROOT;
2042 g_free( node->name );
2043 g_free( node->address );
2044 g_free( node->remarks );
2045 g_list_free( node->list );
2046 g_free( node );
2050 * Process address book for specified node.
2052 static void addrindex_process_node(
2053 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
2054 ItemGroup *parentGrp, ItemFolder *folderGrp )
2056 GList *list;
2057 ItemFolder *itemFolder = NULL;
2058 ItemGroup *itemGParent = parentGrp;
2059 ItemFolder *itemGFolder = folderGrp;
2060 AddressCache *cache = abf->addressCache;
2062 if( node->type == TEMPNODE_ROOT ) {
2063 itemFolder = parent;
2065 else if( node->type == TEMPNODE_FOLDER ) {
2066 itemFolder = addritem_create_item_folder();
2067 addritem_folder_set_name( itemFolder, node->name );
2068 addrcache_id_folder( cache, itemFolder );
2069 addrcache_folder_add_folder( cache, parent, itemFolder );
2070 itemGFolder = NULL;
2072 else if( node->type == TEMPNODE_GROUP ) {
2073 ItemGroup *itemGroup;
2074 gchar *fName;
2076 /* Create a folder for group */
2077 fName = g_strdup_printf( "Cvt - %s", node->name );
2078 itemGFolder = addritem_create_item_folder();
2079 addritem_folder_set_name( itemGFolder, fName );
2080 addrcache_id_folder( cache, itemGFolder );
2081 addrcache_folder_add_folder( cache, parent, itemGFolder );
2082 g_free( fName );
2084 /* Add group into folder */
2085 itemGroup = addritem_create_item_group();
2086 addritem_group_set_name( itemGroup, node->name );
2087 addrcache_id_group( cache, itemGroup );
2088 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2089 itemGParent = itemGroup;
2091 else if( node->type == TEMPNODE_ADDRESS ) {
2092 ItemPerson *itemPerson;
2093 ItemEMail *itemEMail;
2095 /* Create person and email objects */
2096 itemPerson = addritem_create_item_person();
2097 addritem_person_set_common_name( itemPerson, node->name );
2098 addrcache_id_person( cache, itemPerson );
2099 itemEMail = addritem_create_item_email();
2100 addritem_email_set_address( itemEMail, node->address );
2101 addritem_email_set_remarks( itemEMail, node->remarks );
2102 addrcache_id_email( cache, itemEMail );
2103 addrcache_person_add_email( cache, itemPerson, itemEMail );
2105 /* Add person into appropriate folder */
2106 if( itemGFolder ) {
2107 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2109 else {
2110 addrcache_folder_add_person( cache, parent, itemPerson );
2113 /* Add email address only into group */
2114 if( parentGrp ) {
2115 addrcache_group_add_email( cache, parentGrp, itemEMail );
2119 list = node->list;
2120 while( list ) {
2121 AddressCvtNode *lNode = list->data;
2122 list = g_list_next( list );
2123 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2128 * Process address book to specified file number.
2130 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2131 gboolean retVal = FALSE;
2132 AddressBookFile *abf = NULL;
2133 AddressCvtNode *rootNode = NULL;
2134 gchar *newFile = NULL;
2135 GList *fileList = NULL;
2136 gint fileNum = 0;
2138 /* Setup root node */
2139 rootNode = g_new0( AddressCvtNode, 1 );
2140 rootNode->type = TEMPNODE_ROOT;
2141 rootNode->name = g_strdup( "root" );
2142 rootNode->list = NULL;
2143 addrindex_add_obj( file, rootNode );
2144 /* addrindex_print_node( rootNode, stdout ); */
2146 /* Create new address book */
2147 abf = addrbook_create_book();
2148 addrbook_set_name( abf, displayName );
2149 addrbook_set_path( abf, addrIndex->filePath );
2151 /* Determine next available file number */
2152 fileList = addrbook_get_bookfile_list( abf );
2153 if( fileList ) {
2154 fileNum = 1 + abf->maxValue;
2156 g_list_free( fileList );
2157 fileList = NULL;
2159 newFile = addrbook_gen_new_file_name( fileNum );
2160 if( newFile ) {
2161 addrbook_set_file( abf, newFile );
2164 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2166 /* addrbook_dump_book( abf, stdout ); */
2167 addrbook_save_data( abf );
2168 addrIndex->retVal = abf->retVal;
2169 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2171 addrbook_free_book( abf );
2172 abf = NULL;
2173 addrindex_free_node( rootNode );
2174 rootNode = NULL;
2176 /* Create entries in address index */
2177 if( retVal ) {
2178 abf = addrbook_create_book();
2179 addrbook_set_name( abf, displayName );
2180 addrbook_set_path( abf, addrIndex->filePath );
2181 addrbook_set_file( abf, newFile );
2182 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2185 return retVal;
2189 * Process tree converting data.
2191 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2192 guint prev_level;
2193 XMLTag *xtag;
2195 /* Process file */
2196 for (;;) {
2197 prev_level = file->level;
2198 xml_parse_next_tag( file );
2199 if (file->level < prev_level) return;
2201 xtag = xml_get_current_tag( file );
2202 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2203 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2204 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2205 addrIndex->needsConversion = FALSE;
2206 addrIndex->wasConverted = TRUE;
2207 continue;
2209 return;
2211 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2212 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2213 addrIndex->needsConversion = FALSE;
2214 addrIndex->wasConverted = TRUE;
2215 continue;
2217 return;
2219 addrindex_consume_tree( file );
2223 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2224 XMLFile *file = NULL;
2225 gchar *fileSpec;
2227 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2228 addrIndex->retVal = MGU_NO_FILE;
2229 file = xml_open_file( fileSpec );
2230 g_free( fileSpec );
2232 if( file == NULL ) {
2233 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2234 return addrIndex->retVal;
2237 addrIndex->retVal = MGU_BAD_FORMAT;
2238 if( xml_get_dtd( file ) == 0 ) {
2239 if( xml_parse_next_tag( file ) == 0 ) {
2240 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2241 addrindex_convert_tree( addrIndex, file );
2245 xml_close_file( file );
2246 return addrIndex->retVal;
2250 * Create a new address book file.
2252 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2253 gboolean retVal = FALSE;
2254 AddressBookFile *abf = NULL;
2255 gchar *newFile = NULL;
2256 GList *fileList = NULL;
2257 gint fileNum = 0;
2259 /* Create new address book */
2260 abf = addrbook_create_book();
2261 addrbook_set_name( abf, displayName );
2262 addrbook_set_path( abf, addrIndex->filePath );
2264 /* Determine next available file number */
2265 fileList = addrbook_get_bookfile_list( abf );
2266 if( fileList ) {
2267 fileNum = 1 + abf->maxValue;
2269 g_list_free( fileList );
2270 fileList = NULL;
2272 newFile = addrbook_gen_new_file_name( fileNum );
2273 if( newFile ) {
2274 addrbook_set_file( abf, newFile );
2277 addrbook_save_data( abf );
2278 addrIndex->retVal = abf->retVal;
2279 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2280 addrbook_free_book( abf );
2281 abf = NULL;
2283 /* Create entries in address index */
2284 if( retVal ) {
2285 abf = addrbook_create_book();
2286 addrbook_set_name( abf, displayName );
2287 addrbook_set_path( abf, addrIndex->filePath );
2288 addrbook_set_file( abf, newFile );
2289 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2292 return retVal;
2296 * Read data for address index performing a conversion if necesary.
2297 * Enter: addrIndex Address index object.
2298 * return: Status code, from addrIndex->retVal.
2299 * Note: New address book files will be created in directory specified by
2300 * addrIndex. Three files will be created, for the following:
2301 * "Common addresses"
2302 * "Personal addresses"
2303 * "Gathered addresses" - a new address book.
2305 gint addrindex_read_data( AddressIndex *addrIndex ) {
2306 cm_return_val_if_fail( addrIndex != NULL, -1 );
2308 addrIndex->conversionError = FALSE;
2309 addrindex_read_file( addrIndex );
2310 if( addrIndex->retVal == MGU_SUCCESS ) {
2311 if( addrIndex->needsConversion ) {
2312 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS )
2313 addrIndex->conversionError = FALSE;
2314 else
2315 addrIndex->conversionError = TRUE;
2317 addrIndex->dirtyFlag = TRUE;
2319 return addrIndex->retVal;
2323 * Create new address books for a new address index.
2324 * Enter: addrIndex Address index object.
2325 * return: Status code, from addrIndex->retVal.
2326 * Note: New address book files will be created in directory specified by
2327 * addrIndex. Three files will be created, for the following:
2328 * "Common addresses"
2329 * "Personal addresses"
2330 * "Gathered addresses" - a new address book.
2332 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2333 gboolean flg;
2335 cm_return_val_if_fail( addrIndex != NULL, -1 );
2337 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2338 if( flg ) {
2339 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2340 addrIndex->dirtyFlag = TRUE;
2342 return addrIndex->retVal;
2345 /* **********************************************************************
2346 * New interface stuff.
2347 * ***********************************************************************
2351 * Return modified flag for specified data source.
2353 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2354 gboolean retVal = FALSE;
2355 AddressInterface *iface;
2357 if( ds == NULL ) return retVal;
2358 iface = ds->interface;
2359 if( iface == NULL ) return retVal;
2360 if( iface->getModifyFlag ) {
2361 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2363 return retVal;
2367 * Return accessed flag for specified data source.
2369 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2370 gboolean retVal = FALSE;
2371 AddressInterface *iface;
2373 if( ds == NULL ) return retVal;
2374 iface = ds->interface;
2375 if( iface == NULL ) return retVal;
2376 if( iface->getAccessFlag ) {
2377 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2379 return retVal;
2383 * Return data read flag for specified data source.
2385 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2386 gboolean retVal = TRUE;
2387 AddressInterface *iface;
2389 if( ds == NULL ) return retVal;
2390 iface = ds->interface;
2391 if( iface == NULL ) return retVal;
2392 if( iface->getReadFlag ) {
2393 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2395 return retVal;
2399 * Return status code for specified data source.
2401 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2402 gint retVal = MGU_SUCCESS;
2403 AddressInterface *iface;
2405 if( ds == NULL ) return retVal;
2406 iface = ds->interface;
2407 if( iface == NULL ) return retVal;
2408 if( iface->getStatusCode ) {
2409 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2411 return retVal;
2415 * Return data read flag for specified data source.
2417 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2418 gint retVal = MGU_SUCCESS;
2419 AddressInterface *iface;
2421 if( ds == NULL ) return retVal;
2422 iface = ds->interface;
2423 if( iface == NULL ) return retVal;
2424 if( iface->getReadData ) {
2426 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2427 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2429 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2431 return retVal;
2435 * Return data read flag for specified data source.
2437 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2438 ItemFolder *retVal = NULL;
2439 AddressInterface *iface;
2441 if( ds == NULL ) return retVal;
2442 iface = ds->interface;
2443 if( iface == NULL ) return retVal;
2444 if( iface->getRootFolder ) {
2445 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2447 return retVal;
2451 * Return name for specified data source.
2453 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2454 gchar *retVal = FALSE;
2455 AddressInterface *iface;
2457 if( ds == NULL ) return retVal;
2458 iface = ds->interface;
2459 if( iface == NULL ) return retVal;
2460 if( iface->getName ) {
2461 retVal = ( iface->getName ) ( ds->rawDataSource );
2463 return retVal;
2467 * Set the access flag inside the data source.
2469 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2470 AddressInterface *iface;
2472 if( ds == NULL ) return;
2473 iface = ds->interface;
2474 if( iface == NULL ) return;
2475 if( iface->setAccessFlag ) {
2476 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2481 * Return read only flag for specified data source.
2483 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2484 AddressInterface *iface;
2485 if( ds == NULL ) return TRUE;
2486 iface = ds->interface;
2487 if( iface == NULL ) return TRUE;
2488 return iface->readOnly;
2492 * Return list of all persons for specified data source.
2494 static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2495 GList *retVal = NULL;
2496 AddressInterface *iface;
2498 if( ds == NULL ) return retVal;
2499 iface = ds->interface;
2500 if( iface == NULL ) return retVal;
2501 if( iface->getAllPersons ) {
2502 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2504 return retVal;
2508 * Return list of all groups for specified data source.
2510 static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2511 GList *retVal = NULL;
2512 AddressInterface *iface;
2514 if( ds == NULL ) return retVal;
2515 iface = ds->interface;
2516 if( iface == NULL ) return retVal;
2517 if( iface->getAllGroups ) {
2518 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2520 return retVal;
2523 /* **********************************************************************
2524 * Address search stuff.
2525 * ***********************************************************************
2529 * Setup or register the dynamic search that will be performed. The search
2530 * is registered with the query manager.
2532 * \param searchTerm Search term. A private copy will be made.
2533 * \param callBackEntry Callback function that should be called when
2534 * each entry is received.
2535 * \param callBackEnd Callback function that should be called when
2536 * search has finished running.
2537 * \return ID allocated to query that will be executed.
2539 gint addrindex_setup_search(
2540 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2542 QueryRequest *req;
2543 gint queryID;
2545 /* Set up a dynamic address query */
2546 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2547 queryID = req->queryID;
2548 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2550 /* g_print( "***> query ID ::%d::\n", queryID ); */
2551 return queryID;
2554 #ifdef USE_LDAP
2557 * Function prototypes (not in header file or circular reference errors are
2558 * encountered!)
2560 LdapQuery *ldapsvr_new_dynamic_search(
2561 LdapServer *server, QueryRequest *req );
2562 LdapQuery *ldapsvr_new_explicit_search(
2563 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2564 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2566 #endif
2569 * Execute the previously registered dynamic search.
2571 * \param req Address query object to execute.
2572 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2573 * failed.
2575 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2576 AddressInterface *iface;
2577 AddressDataSource *ds;
2578 GList *nodeIf;
2579 GList *nodeDS;
2580 gint type;
2582 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2583 nodeIf = _addressIndex_->searchOrder;
2584 while( nodeIf ) {
2585 iface = nodeIf->data;
2586 nodeIf = g_list_next( nodeIf );
2588 if( ! iface->useInterface ) {
2589 continue;
2591 if( ! iface->externalQuery ) {
2592 continue;
2595 type = iface->type;
2596 nodeDS = iface->listSource;
2597 while( nodeDS ) {
2598 ds = nodeDS->data;
2599 nodeDS = g_list_next( nodeDS );
2600 #ifdef USE_LDAP
2601 if( type == ADDR_IF_LDAP ) {
2602 LdapServer *server;
2603 LdapQuery *qry;
2605 server = ds->rawDataSource;
2606 if( ! server->searchFlag ) {
2607 continue;
2609 if( ldapsvr_reuse_previous( server, req ) ) {
2610 continue;
2613 /* Start a new dynamic search */
2614 qry = ldapsvr_new_dynamic_search( server, req );
2615 if( qry ) {
2616 ldapsvr_execute_query( server, qry );
2619 #endif
2622 return TRUE;
2626 * Stop the previously registered search.
2628 * \param queryID ID of search query to stop.
2630 void addrindex_stop_search( const gint queryID ){
2631 QueryRequest *req;
2632 AddrQueryObject *aqo;
2633 GList *node;
2635 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2636 /* If query ID does not match, search has not been setup */
2637 req = qrymgr_find_request( queryID );
2638 if( req == NULL ) {
2639 return;
2642 /* Stop all queries that were associated with request */
2643 node = req->queryList;
2644 while( node ) {
2645 aqo = node->data;
2646 #ifdef USE_LDAP
2647 if( aqo->queryType == ADDRQUERY_LDAP ) {
2648 LdapQuery *qry = ( LdapQuery * ) aqo;
2649 ldapqry_set_stop_flag( qry, TRUE );
2651 #endif
2652 node->data = NULL;
2653 node = g_list_next( node );
2656 /* Delete query request */
2657 qrymgr_delete_request( queryID );
2661 * Setup or register the explicit search that will be performed. The search is
2662 * registered with the query manager.
2664 * \param ds Data source to search.
2665 * \param searchTerm Search term to locate.
2666 * \param folder Folder to receive search results; may be NULL.
2667 * \param callbackEnd Function to call when search has terminated.
2668 * \param callbackEntry Function to called for each entry processed.
2669 * \return ID allocated to query that will be executed.
2671 gint addrindex_setup_explicit_search(
2672 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2673 void *callBackEnd, void *callBackEntry )
2675 QueryRequest *req;
2676 gint queryID;
2677 gchar *name;
2678 gchar *mySearch;
2680 /* Name the query */
2681 name = g_strdup_printf( "Search '%s'", searchTerm );
2683 /* Set up query request */
2684 if (!strcmp(searchTerm, "*"))
2685 mySearch = g_strdup("*@");
2686 else
2687 mySearch = g_strdup(searchTerm);
2689 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2691 g_free(mySearch);
2693 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2694 queryID = req->queryID;
2696 if( ds->type == ADDR_IF_LDAP ) {
2697 #ifdef USE_LDAP
2698 LdapServer *server;
2700 server = ds->rawDataSource;
2701 ldapsvr_new_explicit_search( server, req, folder );
2702 #endif
2704 else {
2705 qrymgr_delete_request( queryID );
2706 queryID = 0;
2708 g_free( name );
2710 return queryID;
2714 * Execute the previously registered explicit search.
2716 * \param req Address query request object to execute.
2717 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2718 * failed.
2720 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2721 gboolean retVal;
2722 AddrQueryObject *aqo;
2724 retVal = FALSE;
2726 /* Note: there should only be one query in the list. */
2727 aqo = req->queryList->data;
2728 #ifdef USE_LDAP
2729 if( aqo->queryType == ADDRQUERY_LDAP ) {
2730 LdapServer *server;
2731 LdapQuery *qry;
2733 qry = ( LdapQuery * ) aqo;
2734 server = qry->server;
2736 /* Start the search */
2737 retVal = TRUE;
2738 ldapsvr_execute_query( server, qry );
2740 #endif
2741 return retVal;
2745 * Start the previously registered search.
2747 * \param queryID ID of search query to be executed.
2748 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2749 * failed.
2751 gboolean addrindex_start_search( const gint queryID ) {
2752 gboolean retVal;
2753 QueryRequest *req;
2754 AddrSearchType searchType;
2756 retVal = FALSE;
2757 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2758 req = qrymgr_find_request( queryID );
2759 if( req == NULL ) {
2760 return retVal;
2763 searchType = req->searchType;
2764 if( searchType == ADDRSEARCH_DYNAMIC ) {
2765 retVal = addrindex_start_dynamic( req );
2767 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2768 retVal = addrindex_start_explicit( req );
2771 return retVal;
2775 * Remove results (folder and data) for specified data source and folder.
2776 * \param ds Data source to process.
2777 * \param folder Results folder to remove.
2779 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2780 AddrBookBase *adbase;
2781 gint queryID = 0;
2783 /* g_print( "addrindex_remove_results/start\n" ); */
2785 /* Test for folder */
2786 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2787 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2788 adbase = ( AddrBookBase * ) ds->rawDataSource;
2789 if( adbase == NULL ) return;
2791 /* Hide folder to prevent re-display */
2792 addritem_folder_set_hidden( folder, TRUE );
2794 if( ds->type == ADDR_IF_LDAP ) {
2795 #ifdef USE_LDAP
2796 LdapQuery *qry;
2797 gboolean delFlag;
2799 qry = ( LdapQuery * ) folder->folderData;
2800 queryID = ADDRQUERY_ID(qry);
2801 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2802 delFlag = ldapquery_remove_results( qry );
2803 if (delFlag) {
2804 ldapqry_free( qry );
2806 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2808 if( delFlag ) {
2809 g_print( "delFlag IS-TRUE\n" );
2811 else {
2812 g_print( "delFlag IS-FALSE\n" );
2815 #endif
2817 /* g_print( "addrindex_remove_results/end\n" ); */
2819 /* Delete query request */
2820 if( queryID > 0 ) {
2821 qrymgr_delete_request( queryID );
2825 /* **********************************************************************
2826 * Address completion stuff.
2827 * ***********************************************************************
2830 static void addrindex_load_completion_load_persons(
2831 gint (*callBackFunc) ( const gchar *, const gchar *,
2832 const gchar *, const gchar *, GList * ),
2833 AddressDataSource *ds)
2835 GList *listP, *nodeP;
2836 GList *nodeM;
2837 gchar *sName;
2839 /* Read address book */
2840 if( addrindex_ds_get_modify_flag( ds ) ) {
2841 addrindex_ds_read_data( ds );
2844 if( ! addrindex_ds_get_read_flag( ds ) ) {
2845 addrindex_ds_read_data( ds );
2848 /* Get all groups */
2849 listP = addrindex_ds_get_all_groups( ds );
2850 nodeP = listP;
2851 while( nodeP ) {
2852 ItemGroup *group = nodeP->data;
2853 GList *emails = NULL;
2854 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2855 ItemEMail *email = nodeM->data;
2856 if (email->address)
2857 emails = g_list_append(emails, email);
2859 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2860 NULL, NULL, emails );
2861 nodeP = g_list_next( nodeP );
2864 /* Free up the list */
2865 g_list_free( listP );
2866 /* Get all persons */
2867 listP = addrindex_ds_get_all_persons( ds );
2868 nodeP = listP;
2869 while( nodeP ) {
2870 ItemPerson *person = nodeP->data;
2871 nodeM = person->listEMail;
2873 /* Figure out name to use */
2874 sName = ADDRITEM_NAME(person);
2875 if( sName == NULL || *sName == '\0' ) {
2876 sName = person->nickName;
2879 /* Process each E-Mail address */
2880 while( nodeM ) {
2881 ItemEMail *email = nodeM->data;
2883 callBackFunc( sName, email->address, person->nickName,
2884 ADDRITEM_NAME(email), NULL );
2886 nodeM = g_list_next( nodeM );
2888 nodeP = g_list_next( nodeP );
2891 /* Free up the list */
2892 g_list_free( listP );
2896 * This function is used by the address completion function to load
2897 * addresses for all non-external address book interfaces.
2899 * \param callBackFunc Function to be called when an address is
2900 * to be loaded.
2901 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2902 * or "Any", assume the whole addressbook
2903 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2906 gboolean addrindex_load_completion(
2907 gint (*callBackFunc) ( const gchar *, const gchar *,
2908 const gchar *, const gchar *, GList * ),
2909 gchar *folderpath )
2911 GList *nodeIf, *nodeDS;
2913 if( folderpath != NULL ) {
2914 AddressDataSource *book;
2915 ItemFolder* folder;
2917 /* split the folder path we've received, we'll try to match this path, subpath by
2918 subpath against the book/folder structure in order and restrict loading of
2919 addresses to that subpart (if matches). book/folder path must exist and
2920 folderpath must not be empty or NULL */
2922 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2923 g_warning("addrindex_load_completion: folder path '%s' doesn't exist", folderpath);
2924 return FALSE;
2927 if( folder != NULL ) {
2929 GList *items;
2930 GList *nodeM;
2931 gchar *sName;
2932 ItemPerson *person;
2934 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2936 /* Load email addresses */
2937 items = addritem_folder_get_person_list( folder );
2938 for( ; items != NULL; items = g_list_next( items ) ) {
2939 person = items->data;
2940 nodeM = person->listEMail;
2942 /* Figure out name to use */
2943 sName = ADDRITEM_NAME(person);
2944 if( sName == NULL || *sName == '\0' ) {
2945 sName = person->nickName;
2948 /* Process each E-Mail address */
2949 while( nodeM ) {
2950 ItemEMail *email = nodeM->data;
2952 callBackFunc( sName, email->address, person->nickName,
2953 ADDRITEM_NAME(email), NULL );
2955 nodeM = g_list_next( nodeM );
2958 /* Free up the list */
2959 mgu_clear_list( items );
2960 g_list_free( items );
2962 return TRUE;
2964 } else {
2966 if( book != NULL ) {
2968 AddressBookFile *abf = book->rawDataSource;
2970 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf?abf->fileName:"(null)");
2972 addrindex_load_completion_load_persons( callBackFunc, book );
2974 return TRUE;
2976 } else {
2977 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer");
2980 return FALSE;
2982 } else {
2984 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2985 while( nodeIf ) {
2986 AddressInterface *iface = nodeIf->data;
2988 nodeIf = g_list_next( nodeIf );
2990 if( ! iface->useInterface || iface->externalQuery )
2991 continue;
2993 nodeDS = iface->listSource;
2994 while( nodeDS ) {
2995 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
2996 nodeDS = g_list_next( nodeDS );
3001 return TRUE;
3005 * This function can be used to collect information about
3006 * addressbook entries that contain a specific attribute.
3008 * \param attr Name of attribute to look for
3009 * \param callBackFunc Function to be called when a matching attribute was found
3010 * \return <i>TRUE</i>
3012 gboolean addrindex_load_person_attribute(
3013 const gchar *attr,
3014 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
3016 AddressDataSource *ds;
3017 GList *nodeIf, *nodeDS;
3018 GList *listP, *nodeP;
3019 GList *nodeA;
3021 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3022 while( nodeIf ) {
3023 gchar *cur_bname;
3024 AddressInterface *iface = nodeIf->data;
3026 nodeIf = g_list_next( nodeIf );
3028 if( ! iface->useInterface || iface->externalQuery )
3029 continue;
3031 nodeDS = iface->listSource;
3032 while( nodeDS ) {
3033 ds = nodeDS->data;
3035 /* Read address book */
3036 if( addrindex_ds_get_modify_flag( ds ) ) {
3037 addrindex_ds_read_data( ds );
3040 if( ! addrindex_ds_get_read_flag( ds ) ) {
3041 addrindex_ds_read_data( ds );
3044 /* Check addressbook name */
3045 cur_bname = addrindex_ds_get_name( ds );
3047 /* Get all persons */
3048 listP = addrindex_ds_get_all_persons( ds );
3049 nodeP = listP;
3050 while( nodeP ) {
3051 ItemPerson *person = nodeP->data;
3053 /* Return all ItemPerson's if attr is NULL */
3054 if( attr == NULL ) {
3055 callBackFunc(person, cur_bname);
3058 /* Return ItemPerson's with specific attribute */
3059 else {
3060 nodeA = person->listAttrib;
3061 /* Process each User Attribute */
3062 while( nodeA ) {
3063 UserAttribute *attrib = nodeA->data;
3064 if( attrib->name &&
3065 !strcmp( attrib->name,attr ) ) {
3066 callBackFunc(person, cur_bname);
3068 nodeA = g_list_next( nodeA );
3071 nodeP = g_list_next( nodeP );
3073 /* Free up the list */
3074 g_list_free( listP );
3076 nodeDS = g_list_next( nodeDS );
3079 return TRUE;
3083 * This function can be used to collect information about
3084 * addressbook entries
3086 * \param callBackFunc Function to be called for each ItemPerson
3087 * \return <i>TRUE</i>
3089 gboolean addrindex_load_person_ds( gint (*callBackFunc)
3090 ( ItemPerson *, AddressDataSource * ) )
3092 AddressDataSource *ds;
3093 GList *nodeIf, *nodeDS;
3094 GList *listP, *nodeP;
3096 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3097 while( nodeIf ) {
3098 AddressInterface *iface = nodeIf->data;
3100 nodeIf = g_list_next( nodeIf );
3102 if( ! iface->useInterface || iface->externalQuery )
3103 continue;
3105 nodeDS = iface->listSource;
3106 while( nodeDS ) {
3107 ds = nodeDS->data;
3109 /* Read address book */
3110 if( addrindex_ds_get_modify_flag( ds ) ) {
3111 addrindex_ds_read_data( ds );
3114 if( ! addrindex_ds_get_read_flag( ds ) ) {
3115 addrindex_ds_read_data( ds );
3118 /* Get all persons */
3119 listP = addrindex_ds_get_all_persons( ds );
3120 nodeP = listP;
3121 while( nodeP ) {
3122 ItemPerson *person = nodeP->data;
3124 callBackFunc(person, ds);
3125 nodeP = g_list_next( nodeP );
3127 /* Free up the list */
3128 g_list_free( listP );
3130 nodeDS = g_list_next( nodeDS );
3133 return TRUE;
3136 gchar *addrindex_get_picture_file(const gchar *emailaddr)
3138 AddressDataSource *ds;
3139 GList *nodeIf, *nodeDS;
3140 GList *listP, *nodeP;
3141 gboolean found = FALSE;
3142 gchar *filename = NULL;
3143 gchar *raw_addr = NULL;
3145 if (!emailaddr)
3146 return NULL;
3148 Xstrdup_a(raw_addr, emailaddr, return NULL);
3149 extract_address(raw_addr);
3151 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3152 while( nodeIf ) {
3153 AddressInterface *iface = nodeIf->data;
3155 nodeIf = g_list_next( nodeIf );
3157 if( ! iface->useInterface || iface->externalQuery )
3158 continue;
3160 nodeDS = iface->listSource;
3161 while( nodeDS && !found) {
3162 ds = nodeDS->data;
3164 /* Read address book */
3165 if( addrindex_ds_get_modify_flag( ds ) ) {
3166 addrindex_ds_read_data( ds );
3169 if( ! addrindex_ds_get_read_flag( ds ) ) {
3170 addrindex_ds_read_data( ds );
3173 /* Get all persons */
3174 listP = addrindex_ds_get_all_persons( ds );
3175 nodeP = listP;
3176 while( nodeP ) {
3177 GList *nodeM;
3178 ItemPerson *person = nodeP->data;
3179 nodeM = person->listEMail;
3180 while(nodeM) {
3181 ItemEMail *email = nodeM->data;
3182 if (email->address && !strcasecmp(raw_addr, email->address)) {
3183 found = TRUE;
3184 filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S,
3185 ADDRBOOK_DIR, G_DIR_SEPARATOR_S,
3186 person->picture, ".png", NULL );
3187 break;
3189 nodeM = nodeM->next;
3191 nodeP = g_list_next( nodeP );
3193 /* Free up the list */
3194 g_list_free( listP );
3196 nodeDS = g_list_next( nodeDS );
3200 return filename;
3204 * End of Source.