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.
26 #include "claws-features.h"
32 #include <glib/gi18n.h>
36 #include "addrcache.h"
38 #include "addressbook.h"
39 #include "addrindex.h"
41 #include "addrquery.h"
42 #include "addr_compl.h"
44 #include "alertpanel.h"
45 #include "passwordstore.h"
47 #ifndef DEV_STANDALONE
48 #include "prefs_gtk.h"
59 #include "ldapserver.h"
61 #include "ldapquery.h"
62 #include "ldapupdate.h"
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"
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")
137 static AddressIndex *_addressIndex_ = NULL;
140 * Define attribute name-value pair.
142 typedef struct _AddressIfAttr AddressIfAttrib;
143 struct _AddressIfAttr {
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 {
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;
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;
212 iface->externalQuery = FALSE;
213 iface->searchOrder = 0; /* Ignored */
214 iface->startSearch = NULL;
215 iface->stopSearch = NULL;
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,
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;
290 iface->useInterface = FALSE;
291 iface->haveLibrary = FALSE;
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 );
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;
318 iface->useInterface = FALSE;
319 iface->haveLibrary = FALSE;
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);
346 * \param fragment Fragment to free.
348 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
352 node = fragment->children;
354 AddressIfFragment *child = node->data;
355 addrindex_free_fragment( child );
357 node = g_list_next( node );
359 g_list_free( fragment->children );
361 /* Free attributes */
362 node = fragment->attributes;
364 AddressIfAttrib *nv = node->data;
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;
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;
395 ds->rawDataSource = NULL;
396 ds->interface = NULL;
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;
422 else if( iface->type == ADDR_IF_JPILOT ) {
423 JPilotFile *jpf = ds->rawDataSource;
428 else if( iface->type == ADDR_IF_LDAP ) {
429 LdapServer *server = ds->rawDataSource;
430 ldapsvr_free( server );
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;
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;
462 AddressDataSource *ds = node->data;
463 addrindex_free_datasource( ds );
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;
493 iface->listTag = NULL;
494 iface->itemTag = NULL;
495 iface->legacyFlag = FALSE;
496 iface->useInterface = FALSE;
497 iface->haveLibrary = FALSE;
498 iface->listSource = NULL;
501 iface->searchOrder = 0;
502 iface->startSearch = NULL;
503 iface->stopSearch = NULL;
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>
516 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
517 gchar *cacheID = NULL;
518 AddrBookBase *adbase;
521 cm_return_val_if_fail( addrIndex != NULL, NULL );
522 cm_return_val_if_fail( ds != NULL, NULL );
524 adbase = ( AddrBookBase * ) ds->rawDataSource;
526 cache = adbase->addressCache;
528 cacheID = g_strdup( cache->cacheID );
536 * Return reference to data source for specified cacheID.
537 * \param addrIndex Address index.
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.
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;
560 cm_return_val_if_fail( addrIndex != NULL, NULL );
561 cm_return_val_if_fail( cacheID != NULL, NULL );
564 ds = addrindex_get_datasource( addrIndex, cacheID );
566 adbase = ( AddrBookBase * ) ds->rawDataSource;
567 cache = adbase->addressCache;
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 )
582 cacheID = addrindex_get_cache_id( addrIndex, ds );
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 ) {
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 )
616 cacheID = addrindex_get_cache_id( addrIndex, ds );
618 g_hash_table_remove( addrIndex->hashCache, cacheID );
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 ) {
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 ) {
691 addrcompl_initialize();
695 * Perform any other teardown of address index.
697 void addrindex_teardown( void ) {
698 addrcompl_teardown();
703 * Free up address index.
704 * \param addrIndex Address index.
706 void addrindex_free_index( AddressIndex *addrIndex ) {
709 cm_return_if_fail( addrIndex != NULL );
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 );
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;
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;
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;
787 cm_return_val_if_fail( addrIndex != NULL, NULL );
789 node = addrIndex->interfaceList;
791 AddressInterface *iface = node->data;
792 node = g_list_next( node );
793 if( iface->type == ifType ) {
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
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 );
822 ds = addrindex_create_datasource( ifType );
823 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
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 );
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 );
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 );
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;
880 AddressInterface *iface = node->data;
881 node = g_list_next( node );
883 if( strcmp( iface->listTag, tag ) == 0 ) {
889 if( iface->type == ifType ) {
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;
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 ) {
925 /* **********************************************************************
926 * Interface XML parsing functions.
927 * ***********************************************************************
931 * Write start of XML element to 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 ) {
938 for( i = 0; i < lvl; i++ )
939 if (fputs( " ", fp ) == EOF)
941 if (fputs( "<", fp ) == EOF)
943 if (fputs( name, fp ) == EOF)
949 * Write end of XML element to 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 ) {
956 for( i = 0; i < lvl; i++ )
957 if (fputs( " ", fp ) == EOF)
959 if (fputs( "</", fp ) == EOF)
961 if (fputs( name, fp ) == EOF)
963 if (fputs( ">\n", fp ) == EOF)
969 * Write XML attribute to 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)
977 if (fputs( name, fp ) == EOF)
979 if (fputs( "=\"", fp ) == EOF)
981 if (xml_file_put_escape_str( fp, value ) < 0)
983 if (fputs( "\"", fp ) == EOF)
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;
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 */
1021 attr = xml_get_current_tag_attr( file );
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 */
1035 rc = xml_parse_next_tag( file );
1040 if( file->level < prevLevel ) {
1041 /* We must be above level we start at */
1044 child = addrindex_read_fragment( file );
1045 fragment->children = g_list_append( fragment->children, child );
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 )
1063 if (addrindex_write_elem_s( fp, lvl, fragment->name ) < 0)
1065 node = fragment->attributes;
1067 AddressIfAttrib *nv = node->data;
1068 if (addrindex_write_attr( fp, nv->name, nv->value ) < 0)
1070 node = g_list_next( node );
1072 if( fragment->children ) {
1073 if (fputs(" >\n", fp) == EOF)
1076 /* Output children */
1077 node = fragment->children;
1079 AddressIfFragment *child = node->data;
1080 if (addrindex_write_fragment( fp, child, 1+lvl ) < 0)
1082 node = g_list_next( node );
1085 /* Output closing tag */
1086 if (addrindex_write_elem_e( fp, lvl, fragment->name ) < 0)
1090 if (fputs(" />\n", fp) == EOF)
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;
1109 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1110 abf = addrbook_create_book();
1111 attr = xml_get_current_tag_attr( file );
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;
1127 static int addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1128 AddressBookFile *abf = ds->rawDataSource;
1130 if (addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK ) < 0)
1132 if (addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) ) < 0)
1134 if (addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName ) < 0)
1136 if (fputs( " />\n", fp ) == EOF)
1142 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1143 AddressDataSource *ds;
1147 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1148 vcf = vcard_create();
1149 attr = xml_get_current_tag_attr( file );
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;
1165 static int addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1166 VCardFile *vcf = ds->rawDataSource;
1168 if (addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD ) < 0)
1170 if (addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) ) < 0)
1172 if (addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path ) < 0)
1174 if (fputs( " />\n", fp ) == EOF)
1181 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1182 AddressDataSource *ds;
1186 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1187 jpf = jpilot_create();
1188 attr = xml_get_current_tag_attr( file );
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;
1216 static int addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1217 JPilotFile *jpf = ds->rawDataSource;
1221 GList *customLbl = jpilot_get_custom_labels( jpf );
1222 if (addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT ) < 0)
1224 if (addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) ) < 0)
1226 if (addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path ) < 0)
1232 g_snprintf( name, sizeof(name), "%s%d",
1233 ATTAG_JPILOT_CUSTOM, ind );
1234 if (addrindex_write_attr( fp, name, node->data ) < 0)
1237 node = g_list_next( node );
1239 if (fputs( " />\n", fp ) == EOF)
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 );
1257 static int addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1258 AddressIfFragment *fragment = ds->rawDataSource;
1260 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
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 ) {
1282 if( file == NULL ) {
1287 prevLevel = file->level;
1288 xtagPrev = xml_get_current_tag( file );
1290 rc = xml_parse_next_tag( file );
1292 /* Terminate prematurely */
1293 mgu_free_dlist( list );
1297 if( file->level < prevLevel ) {
1298 /* We must be above level we start at */
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 );
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 );
1320 if( xtag != xtagPrev ) {
1321 /* Found a new tag */
1328 /* Build list of search attributes */
1329 ldapctl_criteria_list_clear( ctl );
1332 ldapctl_criteria_list_add( ctl, node->data );
1333 g_free( node->data );
1335 node = g_list_next( node );
1337 g_list_free( list );
1342 void ldapsvr_set_control( LdapServer *server, LdapControl *ctl );
1344 * Parse LDAP control data from XML file.
1345 * \param file Index file.
1346 * \return Initialized data soruce object.
1348 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1349 AddressDataSource *ds;
1353 gchar *serverName = NULL;
1354 gchar *criteria = NULL;
1355 gboolean bDynSearch;
1356 gboolean bTLS, bSSL;
1358 gchar *password = NULL;
1360 /* g_print( "addrindex_parse_ldap\n" ); */
1361 /* Set up some defaults */
1365 iMatch = LDAPCTL_MATCH_BEGINWITH;
1367 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1368 ctl = ldapctl_create();
1369 attr = xml_get_current_tag_attr( file );
1371 gchar *name = ((XMLAttr *)attr->data)->name;
1372 gchar *value = ((XMLAttr *)attr->data)->value;
1373 gint ivalue = atoi( value );
1375 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1376 g_free( serverName );
1377 serverName = g_strdup( value );
1379 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1380 ldapctl_set_host( ctl, value );
1382 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1383 ldapctl_set_port( ctl, ivalue );
1385 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1386 ldapctl_set_base_dn( ctl, value );
1388 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1389 ldapctl_set_bind_dn( ctl, value );
1391 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1394 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1396 criteria = g_strdup( value );
1397 g_print("criteria %s\n", criteria);
1399 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1400 ldapctl_set_max_entries( ctl, ivalue );
1402 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1403 ldapctl_set_timeout( ctl, ivalue );
1405 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1406 ldapctl_set_max_query_age( ctl, ivalue );
1408 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1410 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1414 else if( strcmp( name, ATTAG_LDAP_MATCH_OPT ) == 0 ) {
1415 iMatch = LDAPCTL_MATCH_BEGINWITH;
1416 if( strcmp( value, ATVAL_LDAP_MATCH_CONTAINS ) == 0 ) {
1417 iMatch = LDAPCTL_MATCH_CONTAINS;
1420 else if( strcmp( name, ATTAG_LDAP_ENABLE_TLS ) == 0 ) {
1422 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1426 else if( strcmp( name, ATTAG_LDAP_ENABLE_SSL ) == 0 ) {
1428 if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
1432 attr = g_list_next( attr );
1435 if (password != NULL)
1436 passwd_store_set(PWS_CORE, "LDAP", ctl->hostName, password, TRUE);
1438 server = ldapsvr_create_noctl();
1439 ldapsvr_set_name( server, serverName );
1440 ldapsvr_set_search_flag( server, bDynSearch );
1441 ldapctl_set_matching_option( ctl, iMatch );
1442 ldapctl_set_tls( ctl, bTLS );
1443 ldapctl_set_ssl( ctl, bSSL );
1444 g_free( serverName );
1445 ldapsvr_set_control( server, ctl );
1446 ds->rawDataSource = server;
1448 addrindex_parse_ldap_attrlist( file, ctl );
1450 * If criteria have been specified and no attributes were listed, then
1451 * convert old style criteria into an attribute list. Any criteria will
1452 * be dropped when saving data.
1455 if( ! ldapctl_get_criteria_list( ctl ) ) {
1456 ldapctl_parse_ldap_search( ctl, criteria );
1460 /* ldapsvr_print_data( server, stdout ); */
1465 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1466 LdapServer *server = ds->rawDataSource;
1467 LdapControl *ctl = NULL;
1472 ctl = server->control;
1474 if( ctl == NULL ) return 0;
1476 /* Output start element with attributes */
1477 if (addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP ) < 0)
1479 if (addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) ) < 0)
1481 if (addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName ) < 0)
1484 sprintf( value, "%d", ctl->port );
1485 if (addrindex_write_attr( fp, ATTAG_LDAP_PORT, value ) < 0)
1488 if (addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN ) < 0)
1490 if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN ) < 0)
1493 sprintf( value, "%d", ctl->maxEntries );
1494 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value ) < 0)
1496 sprintf( value, "%d", ctl->timeOut );
1497 if (addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value ) < 0)
1499 sprintf( value, "%d", ctl->maxQueryAge );
1500 if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value ) < 0)
1503 if (addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1504 server->searchFlag ?
1505 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1508 if (addrindex_write_attr( fp, ATTAG_LDAP_MATCH_OPT,
1509 ( ctl->matchingOption == LDAPCTL_MATCH_CONTAINS ) ?
1510 ATVAL_LDAP_MATCH_CONTAINS : ATVAL_LDAP_MATCH_BEGIN ) < 0)
1513 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_TLS,
1515 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1517 if (addrindex_write_attr( fp, ATTAG_LDAP_ENABLE_SSL,
1519 ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
1522 if (fputs(" >\n", fp) == EOF)
1525 /* Output attributes */
1526 node = ldapctl_get_criteria_list( ctl );
1528 if (addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH ) < 0)
1530 if (addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data ) < 0)
1532 if (fputs(" />\n", fp) == EOF)
1534 node = g_list_next( node );
1537 /* End of element */
1538 if (addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP ) < 0)
1546 * Just read/write DOM fragments (preserve data found in file).
1548 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1549 AddressDataSource *ds;
1551 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1552 ds->rawDataSource = addrindex_read_fragment( file );
1556 static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1557 AddressIfFragment *fragment = ds->rawDataSource;
1559 if (addrindex_write_fragment( fp, fragment, lvl ) < 0)
1566 /* **********************************************************************
1567 * Address index I/O functions.
1568 * ***********************************************************************
1571 * Read address index file, creating appropriate data sources for each address
1574 * \param addrIndex Address index.
1575 * \param file Address index file.
1577 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1579 AddressInterface *iface = NULL, *dsIFace = NULL;
1580 AddressDataSource *ds;
1583 addrIndex->loadedFlag = FALSE;
1585 rc = xml_parse_next_tag( file );
1586 if( rc < 0 || file->level == 0 ) return;
1588 xtag = xml_get_current_tag( file );
1590 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1592 addrIndex->lastType = iface->type;
1593 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1596 dsIFace = addrindex_tag_get_datasource(
1597 addrIndex, addrIndex->lastType, xtag->tag );
1599 /* Add data source to list */
1601 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1602 ds = addrindex_parse_book( file );
1603 if( ds->rawDataSource ) {
1604 addrbook_set_path( ds->rawDataSource,
1605 addrIndex->filePath );
1608 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1609 ds = addrindex_parse_vcard( file );
1611 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1612 ds = addrindex_parse_jpilot( file );
1614 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1615 ds = addrindex_parse_ldap( file );
1618 ds->interface = dsIFace;
1619 addrindex_hash_add_cache( addrIndex, ds );
1620 dsIFace->listSource =
1621 g_list_append( dsIFace->listSource, ds );
1629 * Search order sorting comparison function for building search order list.
1631 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1632 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1633 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1635 return ifaceA->searchOrder - ifaceB->searchOrder;
1639 * Build list of data sources to process.
1640 * \param addrIndex Address index object.
1642 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1645 /* Clear existing list */
1646 g_list_free( addrIndex->searchOrder );
1647 addrIndex->searchOrder = NULL;
1649 /* Build new list */
1650 nodeIf = addrIndex->interfaceList;
1652 AddressInterface *iface = nodeIf->data;
1653 if( iface->useInterface ) {
1654 if( iface->searchOrder > 0 ) {
1655 /* Add to search order list */
1656 addrIndex->searchOrder = g_list_insert_sorted(
1657 addrIndex->searchOrder, iface,
1658 addrindex_search_order_compare );
1661 nodeIf = g_list_next( nodeIf );
1665 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1666 XMLFile *file = NULL;
1667 gchar *fileSpec = NULL;
1669 cm_return_val_if_fail( addrIndex != NULL, -1 );
1671 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1672 addrIndex->retVal = MGU_NO_FILE;
1673 file = xml_open_file( fileSpec );
1676 if( file == NULL ) {
1678 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1680 return addrIndex->retVal;
1683 addrIndex->retVal = MGU_BAD_FORMAT;
1684 if( xml_get_dtd( file ) == 0 ) {
1685 if( xml_parse_next_tag( file ) == 0 ) {
1686 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1687 addrindex_read_index( addrIndex, file );
1688 addrIndex->retVal = MGU_SUCCESS;
1692 xml_close_file( file );
1694 addrindex_build_search_order( addrIndex );
1696 return addrIndex->retVal;
1699 static int addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1700 GList *nodeIF, *nodeDS;
1702 gint lvlItem = 1 + lvlList;
1704 nodeIF = addrIndex->interfaceList;
1706 AddressInterface *iface = nodeIF->data;
1707 if( ! iface->legacyFlag ) {
1708 nodeDS = iface->listSource;
1709 if (addrindex_write_elem_s( fp, lvlList, iface->listTag ) < 0)
1711 if (fputs( ">\n", fp ) == EOF)
1714 AddressDataSource *ds = nodeDS->data;
1716 if( iface->type == ADDR_IF_BOOK ) {
1717 if (addrindex_write_book( fp, ds, lvlItem ) < 0)
1720 if( iface->type == ADDR_IF_VCARD ) {
1721 if (addrindex_write_vcard( fp, ds, lvlItem ) < 0)
1724 if( iface->type == ADDR_IF_JPILOT ) {
1725 if (addrindex_write_jpilot( fp, ds, lvlItem ) < 0)
1728 if( iface->type == ADDR_IF_LDAP ) {
1729 if (addrindex_write_ldap( fp, ds, lvlItem ) < 0)
1733 nodeDS = g_list_next( nodeDS );
1735 if (addrindex_write_elem_e( fp, lvlList, iface->listTag ) < 0)
1738 nodeIF = g_list_next( nodeIF );
1744 * Write data to specified file.
1745 * Enter: addrIndex Address index object.
1746 * newFile New file name.
1747 * return: Status code, from addrIndex->retVal.
1748 * Note: File will be created in directory specified by addrIndex.
1750 static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1753 #ifndef DEV_STANDALONE
1757 cm_return_val_if_fail( addrIndex != NULL, -1 );
1759 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1760 addrIndex->retVal = MGU_OPEN_FILE;
1761 #ifdef DEV_STANDALONE
1762 fp = g_fopen( fileSpec, "wb" );
1765 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1767 pfile = prefs_write_open( fileSpec );
1771 if (fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL ) < 0)
1774 if (addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1776 if (fputs( ">\n", fp ) == EOF)
1779 if (addrindex_write_index( addrIndex, fp ) < 0)
1781 if (addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX ) < 0)
1784 addrIndex->retVal = MGU_SUCCESS;
1785 #ifdef DEV_STANDALONE
1788 if( prefs_file_close( pfile ) < 0 ) {
1789 addrIndex->retVal = MGU_ERROR_WRITE;
1795 return addrIndex->retVal;
1797 g_warning("error writing AB index");
1798 addrIndex->retVal = MGU_ERROR_WRITE;
1800 prefs_file_close_revert( pfile );
1801 return addrIndex->retVal;
1805 * Save address index data to original file.
1806 * return: Status code, from addrIndex->retVal.
1808 gint addrindex_save_data( AddressIndex *addrIndex ) {
1814 cm_return_val_if_fail( addrIndex != NULL, -1 );
1817 nodeIf = addrIndex->interfaceList;
1818 /* save LDAP interfaces */
1820 AddressInterface *iface = nodeIf->data;
1821 if( iface->type == ADDR_IF_LDAP ) {
1822 nodeDS = iface->listSource;
1824 AddressDataSource *ds = nodeDS->data;
1825 LdapServer *abf = ds->rawDataSource;
1826 if( ldapsvr_get_read_flag( abf ) ) {
1827 if( ldapsvr_get_modified( abf ) ) {
1828 ldapsvr_update_book( abf, NULL );
1829 if( abf->retVal != LDAPRC_SUCCESS ) {
1830 alertpanel( _("Address(es) update"),
1831 _("Update failed. Changes not written to Directory."),
1832 GTK_STOCK_CLOSE, NULL, NULL );
1835 abf->retVal = MGU_SUCCESS;
1836 ldapsvr_set_modified( abf, FALSE );
1840 nodeDS = g_list_next( nodeDS );
1844 nodeIf = g_list_next( nodeIf );
1847 addrIndex->retVal = MGU_NO_FILE;
1848 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1849 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1851 addrindex_write_to( addrIndex, addrIndex->fileName );
1852 if( addrIndex->retVal == MGU_SUCCESS ) {
1853 addrIndex->dirtyFlag = FALSE;
1855 return addrIndex->retVal;
1859 * Save all address book files which may have changed.
1860 * Return: Status code, set if there was a problem saving data.
1862 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1863 gint retVal = MGU_SUCCESS;
1864 GList *nodeIf, *nodeDS;
1866 nodeIf = addrIndex->interfaceList;
1868 AddressInterface *iface = nodeIf->data;
1869 if( iface->type == ADDR_IF_BOOK ) {
1870 nodeDS = iface->listSource;
1872 AddressDataSource *ds = nodeDS->data;
1873 AddressBookFile *abf = ds->rawDataSource;
1874 if( addrbook_get_dirty( abf ) ) {
1875 if( addrbook_get_read_flag( abf ) ) {
1876 addrbook_save_data( abf );
1877 if( abf->retVal != MGU_SUCCESS ) {
1878 retVal = abf->retVal;
1882 nodeDS = g_list_next( nodeDS );
1886 nodeIf = g_list_next( nodeIf );
1892 /* **********************************************************************
1893 * Address book conversion to new format.
1894 * ***********************************************************************
1897 #define ELTAG_IF_OLD_FOLDER "folder"
1898 #define ELTAG_IF_OLD_GROUP "group"
1899 #define ELTAG_IF_OLD_ITEM "item"
1900 #define ELTAG_IF_OLD_NAME "name"
1901 #define ELTAG_IF_OLD_ADDRESS "address"
1902 #define ELTAG_IF_OLD_REMARKS "remarks"
1903 #define ATTAG_IF_OLD_NAME "name"
1905 #define TEMPNODE_ROOT 0
1906 #define TEMPNODE_FOLDER 1
1907 #define TEMPNODE_GROUP 2
1908 #define TEMPNODE_ADDRESS 3
1910 typedef struct _AddressCvt_Node AddressCvtNode;
1911 struct _AddressCvt_Node {
1920 * Parse current address item.
1922 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1927 nn = g_new0( AddressCvtNode, 1 );
1928 nn->type = TEMPNODE_ADDRESS;
1931 level = file->level;
1934 xml_parse_next_tag(file);
1935 if (file->level < level) return nn;
1937 element = xml_get_element( file );
1938 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1939 nn->name = g_strdup( element );
1941 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1942 nn->address = g_strdup( element );
1944 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1945 nn->remarks = g_strdup( element );
1948 xml_parse_next_tag(file);
1953 * Create a temporary node below specified node.
1955 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1957 nn = g_new0( AddressCvtNode, 1 );
1959 nn->name = g_strdup( name );
1960 nn->remarks = g_strdup( rem );
1961 node->list = g_list_append( node->list, nn );
1966 * Process current temporary node.
1968 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1971 AddressCvtNode *newNode = NULL;
1976 prev_level = file->level;
1977 xml_parse_next_tag( file );
1978 if (file->level < prev_level) return;
1982 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1983 attr = xml_get_current_tag_attr(file);
1985 name = ((XMLAttr *)attr->data)->name;
1986 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1987 value = ((XMLAttr *)attr->data)->value;
1990 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1991 addrindex_add_obj( file, newNode );
1994 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1995 attr = xml_get_current_tag_attr(file);
1997 name = ((XMLAttr *)attr->data)->name;
1998 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1999 value = ((XMLAttr *)attr->data)->value;
2002 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
2003 addrindex_add_obj( file, newNode );
2005 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
2006 newNode = addrindex_parse_item( file );
2007 node->list = g_list_append( node->list, newNode );
2010 g_warning("Invalid tag");
2016 * Consume all nodes below current tag.
2018 static void addrindex_consume_tree( XMLFile *file ) {
2022 prev_level = file->level;
2023 xml_parse_next_tag( file );
2024 if (file->level < prev_level)
2027 addrindex_consume_tree( file );
2032 * Free up temporary tree.
2034 static void addrindex_free_node( AddressCvtNode *node ) {
2035 GList *list = node->list;
2038 AddressCvtNode *lNode = list->data;
2039 list = g_list_next( list );
2040 addrindex_free_node( lNode );
2042 node->type = TEMPNODE_ROOT;
2043 g_free( node->name );
2044 g_free( node->address );
2045 g_free( node->remarks );
2046 g_list_free( node->list );
2051 * Process address book for specified node.
2053 static void addrindex_process_node(
2054 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
2055 ItemGroup *parentGrp, ItemFolder *folderGrp )
2058 ItemFolder *itemFolder = NULL;
2059 ItemGroup *itemGParent = parentGrp;
2060 ItemFolder *itemGFolder = folderGrp;
2061 AddressCache *cache = abf->addressCache;
2063 if( node->type == TEMPNODE_ROOT ) {
2064 itemFolder = parent;
2066 else if( node->type == TEMPNODE_FOLDER ) {
2067 itemFolder = addritem_create_item_folder();
2068 addritem_folder_set_name( itemFolder, node->name );
2069 addrcache_id_folder( cache, itemFolder );
2070 addrcache_folder_add_folder( cache, parent, itemFolder );
2073 else if( node->type == TEMPNODE_GROUP ) {
2074 ItemGroup *itemGroup;
2077 /* Create a folder for group */
2078 fName = g_strdup_printf( "Cvt - %s", node->name );
2079 itemGFolder = addritem_create_item_folder();
2080 addritem_folder_set_name( itemGFolder, fName );
2081 addrcache_id_folder( cache, itemGFolder );
2082 addrcache_folder_add_folder( cache, parent, itemGFolder );
2085 /* Add group into folder */
2086 itemGroup = addritem_create_item_group();
2087 addritem_group_set_name( itemGroup, node->name );
2088 addrcache_id_group( cache, itemGroup );
2089 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
2090 itemGParent = itemGroup;
2092 else if( node->type == TEMPNODE_ADDRESS ) {
2093 ItemPerson *itemPerson;
2094 ItemEMail *itemEMail;
2096 /* Create person and email objects */
2097 itemPerson = addritem_create_item_person();
2098 addritem_person_set_common_name( itemPerson, node->name );
2099 addrcache_id_person( cache, itemPerson );
2100 itemEMail = addritem_create_item_email();
2101 addritem_email_set_address( itemEMail, node->address );
2102 addritem_email_set_remarks( itemEMail, node->remarks );
2103 addrcache_id_email( cache, itemEMail );
2104 addrcache_person_add_email( cache, itemPerson, itemEMail );
2106 /* Add person into appropriate folder */
2108 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2111 addrcache_folder_add_person( cache, parent, itemPerson );
2114 /* Add email address only into group */
2116 addrcache_group_add_email( cache, parentGrp, itemEMail );
2122 AddressCvtNode *lNode = list->data;
2123 list = g_list_next( list );
2124 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2129 * Process address book to specified file number.
2131 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2132 gboolean retVal = FALSE;
2133 AddressBookFile *abf = NULL;
2134 AddressCvtNode *rootNode = NULL;
2135 gchar *newFile = NULL;
2136 GList *fileList = NULL;
2139 /* Setup root node */
2140 rootNode = g_new0( AddressCvtNode, 1 );
2141 rootNode->type = TEMPNODE_ROOT;
2142 rootNode->name = g_strdup( "root" );
2143 rootNode->list = NULL;
2144 addrindex_add_obj( file, rootNode );
2145 /* addrindex_print_node( rootNode, stdout ); */
2147 /* Create new address book */
2148 abf = addrbook_create_book();
2149 addrbook_set_name( abf, displayName );
2150 addrbook_set_path( abf, addrIndex->filePath );
2152 /* Determine next available file number */
2153 fileList = addrbook_get_bookfile_list( abf );
2155 fileNum = 1 + abf->maxValue;
2157 g_list_free( fileList );
2160 newFile = addrbook_gen_new_file_name( fileNum );
2162 addrbook_set_file( abf, newFile );
2165 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2167 /* addrbook_dump_book( abf, stdout ); */
2168 addrbook_save_data( abf );
2169 addrIndex->retVal = abf->retVal;
2170 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2172 addrbook_free_book( abf );
2174 addrindex_free_node( rootNode );
2177 /* Create entries in address index */
2179 abf = addrbook_create_book();
2180 addrbook_set_name( abf, displayName );
2181 addrbook_set_path( abf, addrIndex->filePath );
2182 addrbook_set_file( abf, newFile );
2183 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2190 * Process tree converting data.
2192 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2198 prev_level = file->level;
2199 xml_parse_next_tag( file );
2200 if (file->level < prev_level) return;
2202 xtag = xml_get_current_tag( file );
2203 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2204 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2205 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2206 addrIndex->needsConversion = FALSE;
2207 addrIndex->wasConverted = TRUE;
2212 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2213 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2214 addrIndex->needsConversion = FALSE;
2215 addrIndex->wasConverted = TRUE;
2220 addrindex_consume_tree( file );
2224 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2225 XMLFile *file = NULL;
2228 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2229 addrIndex->retVal = MGU_NO_FILE;
2230 file = xml_open_file( fileSpec );
2233 if( file == NULL ) {
2234 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2235 return addrIndex->retVal;
2238 addrIndex->retVal = MGU_BAD_FORMAT;
2239 if( xml_get_dtd( file ) == 0 ) {
2240 if( xml_parse_next_tag( file ) == 0 ) {
2241 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2242 addrindex_convert_tree( addrIndex, file );
2246 xml_close_file( file );
2247 return addrIndex->retVal;
2251 * Create a new address book file.
2253 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2254 gboolean retVal = FALSE;
2255 AddressBookFile *abf = NULL;
2256 gchar *newFile = NULL;
2257 GList *fileList = NULL;
2260 /* Create new address book */
2261 abf = addrbook_create_book();
2262 addrbook_set_name( abf, displayName );
2263 addrbook_set_path( abf, addrIndex->filePath );
2265 /* Determine next available file number */
2266 fileList = addrbook_get_bookfile_list( abf );
2268 fileNum = 1 + abf->maxValue;
2270 g_list_free( fileList );
2273 newFile = addrbook_gen_new_file_name( fileNum );
2275 addrbook_set_file( abf, newFile );
2278 addrbook_save_data( abf );
2279 addrIndex->retVal = abf->retVal;
2280 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2281 addrbook_free_book( abf );
2284 /* Create entries in address index */
2286 abf = addrbook_create_book();
2287 addrbook_set_name( abf, displayName );
2288 addrbook_set_path( abf, addrIndex->filePath );
2289 addrbook_set_file( abf, newFile );
2290 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2297 * Read data for address index performing a conversion if necesary.
2298 * Enter: addrIndex Address index object.
2299 * return: Status code, from addrIndex->retVal.
2300 * Note: New address book files will be created in directory specified by
2301 * addrIndex. Three files will be created, for the following:
2302 * "Common addresses"
2303 * "Personal addresses"
2304 * "Gathered addresses" - a new address book.
2306 gint addrindex_read_data( AddressIndex *addrIndex ) {
2307 cm_return_val_if_fail( addrIndex != NULL, -1 );
2309 addrIndex->conversionError = FALSE;
2310 addrindex_read_file( addrIndex );
2311 if( addrIndex->retVal == MGU_SUCCESS ) {
2312 if( addrIndex->needsConversion ) {
2313 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS )
2314 addrIndex->conversionError = FALSE;
2316 addrIndex->conversionError = TRUE;
2318 addrIndex->dirtyFlag = TRUE;
2320 return addrIndex->retVal;
2324 * Create new address books for a new address index.
2325 * Enter: addrIndex Address index object.
2326 * return: Status code, from addrIndex->retVal.
2327 * Note: New address book files will be created in directory specified by
2328 * addrIndex. Three files will be created, for the following:
2329 * "Common addresses"
2330 * "Personal addresses"
2331 * "Gathered addresses" - a new address book.
2333 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2336 cm_return_val_if_fail( addrIndex != NULL, -1 );
2338 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2340 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2341 addrIndex->dirtyFlag = TRUE;
2343 return addrIndex->retVal;
2346 /* **********************************************************************
2347 * New interface stuff.
2348 * ***********************************************************************
2352 * Return modified flag for specified data source.
2354 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2355 gboolean retVal = FALSE;
2356 AddressInterface *iface;
2358 if( ds == NULL ) return retVal;
2359 iface = ds->interface;
2360 if( iface == NULL ) return retVal;
2361 if( iface->getModifyFlag ) {
2362 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2368 * Return accessed flag for specified data source.
2370 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2371 gboolean retVal = FALSE;
2372 AddressInterface *iface;
2374 if( ds == NULL ) return retVal;
2375 iface = ds->interface;
2376 if( iface == NULL ) return retVal;
2377 if( iface->getAccessFlag ) {
2378 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2384 * Return data read flag for specified data source.
2386 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2387 gboolean retVal = TRUE;
2388 AddressInterface *iface;
2390 if( ds == NULL ) return retVal;
2391 iface = ds->interface;
2392 if( iface == NULL ) return retVal;
2393 if( iface->getReadFlag ) {
2394 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2400 * Return status code for specified data source.
2402 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2403 gint retVal = MGU_SUCCESS;
2404 AddressInterface *iface;
2406 if( ds == NULL ) return retVal;
2407 iface = ds->interface;
2408 if( iface == NULL ) return retVal;
2409 if( iface->getStatusCode ) {
2410 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2416 * Return data read flag for specified data source.
2418 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2419 gint retVal = MGU_SUCCESS;
2420 AddressInterface *iface;
2422 if( ds == NULL ) return retVal;
2423 iface = ds->interface;
2424 if( iface == NULL ) return retVal;
2425 if( iface->getReadData ) {
2427 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2428 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2430 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2436 * Return data read flag for specified data source.
2438 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2439 ItemFolder *retVal = NULL;
2440 AddressInterface *iface;
2442 if( ds == NULL ) return retVal;
2443 iface = ds->interface;
2444 if( iface == NULL ) return retVal;
2445 if( iface->getRootFolder ) {
2446 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2452 * Return name for specified data source.
2454 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2455 gchar *retVal = FALSE;
2456 AddressInterface *iface;
2458 if( ds == NULL ) return retVal;
2459 iface = ds->interface;
2460 if( iface == NULL ) return retVal;
2461 if( iface->getName ) {
2462 retVal = ( iface->getName ) ( ds->rawDataSource );
2468 * Set the access flag inside the data source.
2470 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2471 AddressInterface *iface;
2473 if( ds == NULL ) return;
2474 iface = ds->interface;
2475 if( iface == NULL ) return;
2476 if( iface->setAccessFlag ) {
2477 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2482 * Return read only flag for specified data source.
2484 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2485 AddressInterface *iface;
2486 if( ds == NULL ) return TRUE;
2487 iface = ds->interface;
2488 if( iface == NULL ) return TRUE;
2489 return iface->readOnly;
2493 * Return list of all persons for specified data source.
2495 static GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2496 GList *retVal = NULL;
2497 AddressInterface *iface;
2499 if( ds == NULL ) return retVal;
2500 iface = ds->interface;
2501 if( iface == NULL ) return retVal;
2502 if( iface->getAllPersons ) {
2503 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2509 * Return list of all groups for specified data source.
2511 static GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2512 GList *retVal = NULL;
2513 AddressInterface *iface;
2515 if( ds == NULL ) return retVal;
2516 iface = ds->interface;
2517 if( iface == NULL ) return retVal;
2518 if( iface->getAllGroups ) {
2519 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2524 /* **********************************************************************
2525 * Address search stuff.
2526 * ***********************************************************************
2530 * Setup or register the dynamic search that will be performed. The search
2531 * is registered with the query manager.
2533 * \param searchTerm Search term. A private copy will be made.
2534 * \param callBackEntry Callback function that should be called when
2535 * each entry is received.
2536 * \param callBackEnd Callback function that should be called when
2537 * search has finished running.
2538 * \return ID allocated to query that will be executed.
2540 gint addrindex_setup_search(
2541 const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
2546 /* Set up a dynamic address query */
2547 req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
2548 queryID = req->queryID;
2549 qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
2551 /* g_print( "***> query ID ::%d::\n", queryID ); */
2558 * Function prototypes (not in header file or circular reference errors are
2561 LdapQuery *ldapsvr_new_dynamic_search(
2562 LdapServer *server, QueryRequest *req );
2563 LdapQuery *ldapsvr_new_explicit_search(
2564 LdapServer *server, QueryRequest *req, ItemFolder *folder );
2565 void ldapsvr_execute_query( LdapServer *server, LdapQuery *qry );
2570 * Execute the previously registered dynamic search.
2572 * \param req Address query object to execute.
2573 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2576 static gboolean addrindex_start_dynamic( QueryRequest *req ) {
2577 AddressInterface *iface;
2578 AddressDataSource *ds;
2583 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2584 nodeIf = _addressIndex_->searchOrder;
2586 iface = nodeIf->data;
2587 nodeIf = g_list_next( nodeIf );
2589 if( ! iface->useInterface ) {
2592 if( ! iface->externalQuery ) {
2597 nodeDS = iface->listSource;
2600 nodeDS = g_list_next( nodeDS );
2602 if( type == ADDR_IF_LDAP ) {
2606 server = ds->rawDataSource;
2607 if( ! server->searchFlag ) {
2610 if( ldapsvr_reuse_previous( server, req ) ) {
2614 /* Start a new dynamic search */
2615 qry = ldapsvr_new_dynamic_search( server, req );
2617 ldapsvr_execute_query( server, qry );
2627 * Stop the previously registered search.
2629 * \param queryID ID of search query to stop.
2631 void addrindex_stop_search( const gint queryID ){
2633 AddrQueryObject *aqo;
2636 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2637 /* If query ID does not match, search has not been setup */
2638 req = qrymgr_find_request( queryID );
2643 /* Stop all queries that were associated with request */
2644 node = req->queryList;
2648 if( aqo->queryType == ADDRQUERY_LDAP ) {
2649 LdapQuery *qry = ( LdapQuery * ) aqo;
2650 ldapqry_set_stop_flag( qry, TRUE );
2654 node = g_list_next( node );
2657 /* Delete query request */
2658 qrymgr_delete_request( queryID );
2662 * Setup or register the explicit search that will be performed. The search is
2663 * registered with the query manager.
2665 * \param ds Data source to search.
2666 * \param searchTerm Search term to locate.
2667 * \param folder Folder to receive search results; may be NULL.
2668 * \param callbackEnd Function to call when search has terminated.
2669 * \param callbackEntry Function to called for each entry processed.
2670 * \return ID allocated to query that will be executed.
2672 gint addrindex_setup_explicit_search(
2673 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2674 void *callBackEnd, void *callBackEntry )
2681 /* Name the query */
2682 name = g_strdup_printf( "Search '%s'", searchTerm );
2684 /* Set up query request */
2685 if (!strcmp(searchTerm, "*"))
2686 mySearch = g_strdup("*@");
2688 mySearch = g_strdup(searchTerm);
2690 req = qrymgr_add_request( mySearch, callBackEnd, callBackEntry );
2694 qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
2695 queryID = req->queryID;
2697 if( ds->type == ADDR_IF_LDAP ) {
2701 server = ds->rawDataSource;
2702 ldapsvr_new_explicit_search( server, req, folder );
2706 qrymgr_delete_request( queryID );
2715 * Execute the previously registered explicit search.
2717 * \param req Address query request object to execute.
2718 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2721 static gboolean addrindex_start_explicit( QueryRequest *req ) {
2723 AddrQueryObject *aqo;
2727 /* Note: there should only be one query in the list. */
2728 aqo = req->queryList->data;
2730 if( aqo->queryType == ADDRQUERY_LDAP ) {
2734 qry = ( LdapQuery * ) aqo;
2735 server = qry->server;
2737 /* Start the search */
2739 ldapsvr_execute_query( server, qry );
2746 * Start the previously registered search.
2748 * \param queryID ID of search query to be executed.
2749 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2752 gboolean addrindex_start_search( const gint queryID ) {
2755 AddrSearchType searchType;
2758 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2759 req = qrymgr_find_request( queryID );
2764 searchType = req->searchType;
2765 if( searchType == ADDRSEARCH_DYNAMIC ) {
2766 retVal = addrindex_start_dynamic( req );
2768 else if( searchType == ADDRSEARCH_EXPLICIT ) {
2769 retVal = addrindex_start_explicit( req );
2776 * Remove results (folder and data) for specified data source and folder.
2777 * \param ds Data source to process.
2778 * \param folder Results folder to remove.
2780 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
2781 AddrBookBase *adbase;
2784 /* g_print( "addrindex_remove_results/start\n" ); */
2786 /* Test for folder */
2787 if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
2788 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2789 adbase = ( AddrBookBase * ) ds->rawDataSource;
2790 if( adbase == NULL ) return;
2792 /* Hide folder to prevent re-display */
2793 addritem_folder_set_hidden( folder, TRUE );
2795 if( ds->type == ADDR_IF_LDAP ) {
2800 qry = ( LdapQuery * ) folder->folderData;
2801 queryID = ADDRQUERY_ID(qry);
2802 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2803 delFlag = ldapquery_remove_results( qry );
2805 ldapqry_free( qry );
2807 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2810 g_print( "delFlag IS-TRUE\n" );
2813 g_print( "delFlag IS-FALSE\n" );
2818 /* g_print( "addrindex_remove_results/end\n" ); */
2820 /* Delete query request */
2822 qrymgr_delete_request( queryID );
2826 /* **********************************************************************
2827 * Address completion stuff.
2828 * ***********************************************************************
2831 static void addrindex_load_completion_load_persons(
2832 gint (*callBackFunc) ( const gchar *, const gchar *,
2833 const gchar *, const gchar *, GList * ),
2834 AddressDataSource *ds)
2836 GList *listP, *nodeP;
2840 /* Read address book */
2841 if( addrindex_ds_get_modify_flag( ds ) ) {
2842 addrindex_ds_read_data( ds );
2845 if( ! addrindex_ds_get_read_flag( ds ) ) {
2846 addrindex_ds_read_data( ds );
2849 /* Get all groups */
2850 listP = addrindex_ds_get_all_groups( ds );
2853 ItemGroup *group = nodeP->data;
2854 GList *emails = NULL;
2855 for (nodeM = group->listEMail; nodeM; nodeM = g_list_next(nodeM)) {
2856 ItemEMail *email = nodeM->data;
2858 emails = g_list_append(emails, email);
2860 callBackFunc( ((AddrItemObject *)group)->name, NULL,
2861 NULL, NULL, emails );
2862 nodeP = g_list_next( nodeP );
2865 /* Free up the list */
2866 g_list_free( listP );
2867 /* Get all persons */
2868 listP = addrindex_ds_get_all_persons( ds );
2871 ItemPerson *person = nodeP->data;
2872 nodeM = person->listEMail;
2874 /* Figure out name to use */
2875 sName = ADDRITEM_NAME(person);
2876 if( sName == NULL || *sName == '\0' ) {
2877 sName = person->nickName;
2880 /* Process each E-Mail address */
2882 ItemEMail *email = nodeM->data;
2884 callBackFunc( sName, email->address, person->nickName,
2885 ADDRITEM_NAME(email), NULL );
2887 nodeM = g_list_next( nodeM );
2889 nodeP = g_list_next( nodeP );
2892 /* Free up the list */
2893 g_list_free( listP );
2897 * This function is used by the address completion function to load
2898 * addresses for all non-external address book interfaces.
2900 * \param callBackFunc Function to be called when an address is
2902 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2903 * or "Any", assume the whole addressbook
2904 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2907 gboolean addrindex_load_completion(
2908 gint (*callBackFunc) ( const gchar *, const gchar *,
2909 const gchar *, const gchar *, GList * ),
2912 GList *nodeIf, *nodeDS;
2914 if( folderpath != NULL ) {
2915 AddressDataSource *book;
2918 /* split the folder path we've received, we'll try to match this path, subpath by
2919 subpath against the book/folder structure in order and restrict loading of
2920 addresses to that subpart (if matches). book/folder path must exist and
2921 folderpath must not be empty or NULL */
2923 if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
2924 g_warning("addrindex_load_completion: folder path '%s' doesn't exist", folderpath);
2928 if( folder != NULL ) {
2935 debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
2937 /* Load email addresses */
2938 items = addritem_folder_get_person_list( folder );
2939 for( ; items != NULL; items = g_list_next( items ) ) {
2940 person = items->data;
2941 nodeM = person->listEMail;
2943 /* Figure out name to use */
2944 sName = ADDRITEM_NAME(person);
2945 if( sName == NULL || *sName == '\0' ) {
2946 sName = person->nickName;
2949 /* Process each E-Mail address */
2951 ItemEMail *email = nodeM->data;
2953 callBackFunc( sName, email->address, person->nickName,
2954 ADDRITEM_NAME(email), NULL );
2956 nodeM = g_list_next( nodeM );
2959 /* Free up the list */
2960 mgu_clear_list( items );
2961 g_list_free( items );
2967 if( book != NULL ) {
2969 AddressBookFile *abf = book->rawDataSource;
2971 debug_print("addrindex_load_completion: book %p '%s'\n", book, abf?abf->fileName:"(null)");
2973 addrindex_load_completion_load_persons( callBackFunc, book );
2978 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer");
2985 nodeIf = addrindex_get_interface_list( _addressIndex_ );
2987 AddressInterface *iface = nodeIf->data;
2989 nodeIf = g_list_next( nodeIf );
2991 if( ! iface->useInterface || iface->externalQuery )
2994 nodeDS = iface->listSource;
2996 addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
2997 nodeDS = g_list_next( nodeDS );
3006 * This function can be used to collect information about
3007 * addressbook entries that contain a specific attribute.
3009 * \param attr Name of attribute to look for
3010 * \param callBackFunc Function to be called when a matching attribute was found
3011 * \return <i>TRUE</i>
3013 gboolean addrindex_load_person_attribute(
3015 gint (*callBackFunc) ( ItemPerson *, const gchar * ) )
3017 AddressDataSource *ds;
3018 GList *nodeIf, *nodeDS;
3019 GList *listP, *nodeP;
3022 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3025 AddressInterface *iface = nodeIf->data;
3027 nodeIf = g_list_next( nodeIf );
3029 if( ! iface->useInterface || iface->externalQuery )
3032 nodeDS = iface->listSource;
3036 /* Read address book */
3037 if( addrindex_ds_get_modify_flag( ds ) ) {
3038 addrindex_ds_read_data( ds );
3041 if( ! addrindex_ds_get_read_flag( ds ) ) {
3042 addrindex_ds_read_data( ds );
3045 /* Check addressbook name */
3046 cur_bname = addrindex_ds_get_name( ds );
3048 /* Get all persons */
3049 listP = addrindex_ds_get_all_persons( ds );
3052 ItemPerson *person = nodeP->data;
3054 /* Return all ItemPerson's if attr is NULL */
3055 if( attr == NULL ) {
3056 callBackFunc(person, cur_bname);
3059 /* Return ItemPerson's with specific attribute */
3061 nodeA = person->listAttrib;
3062 /* Process each User Attribute */
3064 UserAttribute *attrib = nodeA->data;
3066 !strcmp( attrib->name,attr ) ) {
3067 callBackFunc(person, cur_bname);
3069 nodeA = g_list_next( nodeA );
3072 nodeP = g_list_next( nodeP );
3074 /* Free up the list */
3075 g_list_free( listP );
3077 nodeDS = g_list_next( nodeDS );
3084 * This function can be used to collect information about
3085 * addressbook entries
3087 * \param callBackFunc Function to be called for each ItemPerson
3088 * \return <i>TRUE</i>
3090 gboolean addrindex_load_person_ds( gint (*callBackFunc)
3091 ( ItemPerson *, AddressDataSource * ) )
3093 AddressDataSource *ds;
3094 GList *nodeIf, *nodeDS;
3095 GList *listP, *nodeP;
3097 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3099 AddressInterface *iface = nodeIf->data;
3101 nodeIf = g_list_next( nodeIf );
3103 if( ! iface->useInterface || iface->externalQuery )
3106 nodeDS = iface->listSource;
3110 /* Read address book */
3111 if( addrindex_ds_get_modify_flag( ds ) ) {
3112 addrindex_ds_read_data( ds );
3115 if( ! addrindex_ds_get_read_flag( ds ) ) {
3116 addrindex_ds_read_data( ds );
3119 /* Get all persons */
3120 listP = addrindex_ds_get_all_persons( ds );
3123 ItemPerson *person = nodeP->data;
3125 callBackFunc(person, ds);
3126 nodeP = g_list_next( nodeP );
3128 /* Free up the list */
3129 g_list_free( listP );
3131 nodeDS = g_list_next( nodeDS );
3137 gchar *addrindex_get_picture_file(const gchar *emailaddr)
3139 AddressDataSource *ds;
3140 GList *nodeIf, *nodeDS;
3141 GList *listP, *nodeP;
3142 gboolean found = FALSE;
3143 gchar *filename = NULL;
3144 gchar *raw_addr = NULL;
3149 Xstrdup_a(raw_addr, emailaddr, return NULL);
3150 extract_address(raw_addr);
3152 nodeIf = addrindex_get_interface_list( _addressIndex_ );
3154 AddressInterface *iface = nodeIf->data;
3156 nodeIf = g_list_next( nodeIf );
3158 if( ! iface->useInterface || iface->externalQuery )
3161 nodeDS = iface->listSource;
3162 while( nodeDS && !found) {
3165 /* Read address book */
3166 if( addrindex_ds_get_modify_flag( ds ) ) {
3167 addrindex_ds_read_data( ds );
3170 if( ! addrindex_ds_get_read_flag( ds ) ) {
3171 addrindex_ds_read_data( ds );
3174 /* Get all persons */
3175 listP = addrindex_ds_get_all_persons( ds );
3179 ItemPerson *person = nodeP->data;
3180 nodeM = person->listEMail;
3182 ItemEMail *email = nodeM->data;
3183 if (email->address && !strcasecmp(raw_addr, email->address)) {
3185 filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S,
3186 ADDRBOOK_DIR, G_DIR_SEPARATOR_S,
3187 person->picture, ".png", NULL );
3190 nodeM = nodeM->next;
3192 nodeP = g_list_next( nodeP );
3194 /* Free up the list */
3195 g_list_free( listP );
3197 nodeDS = g_list_next( nodeDS );