2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2003 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * General functions for accessing address index file.
35 #include "addrcache.h"
37 #include "addrindex.h"
39 #include "addrquery.h"
41 #ifndef DEV_STANDALONE
42 #include "prefs_gtk.h"
53 #include "ldapserver.h"
55 #include "ldapquery.h"
58 #define TAG_ADDRESS_INDEX "addressbook"
60 #define TAG_IF_ADDRESS_BOOK "book_list"
61 #define TAG_IF_VCARD "vcard_list"
62 #define TAG_IF_JPILOT "jpilot_list"
63 #define TAG_IF_LDAP "ldap_list"
65 #define TAG_DS_ADDRESS_BOOK "book"
66 #define TAG_DS_VCARD "vcard"
67 #define TAG_DS_JPILOT "jpilot"
68 #define TAG_DS_LDAP "server"
70 /* XML Attribute names */
71 #define ATTAG_BOOK_NAME "name"
72 #define ATTAG_BOOK_FILE "file"
74 #define ATTAG_VCARD_NAME "name"
75 #define ATTAG_VCARD_FILE "file"
77 #define ATTAG_JPILOT_NAME "name"
78 #define ATTAG_JPILOT_FILE "file"
79 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
80 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
81 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
82 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
83 #define ATTAG_JPILOT_CUSTOM "custom-"
85 #define ATTAG_LDAP_NAME "name"
86 #define ATTAG_LDAP_HOST "host"
87 #define ATTAG_LDAP_PORT "port"
88 #define ATTAG_LDAP_BASE_DN "base-dn"
89 #define ATTAG_LDAP_BIND_DN "bind-dn"
90 #define ATTAG_LDAP_BIND_PASS "bind-pass"
91 #define ATTAG_LDAP_CRITERIA "criteria"
92 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
93 #define ATTAG_LDAP_TIMEOUT "timeout"
94 #define ATTAG_LDAP_MAX_AGE "max-age"
95 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
97 #define ELTAG_LDAP_ATTR_SRCH "attribute"
98 #define ATTAG_LDAP_ATTR_NAME "name"
101 #define ATTAG_LDAP_DEFAULT "default"
105 N_("Personal address")
108 #define DISP_NEW_COMMON _("Common address")
109 #define DISP_NEW_PERSONAL _("Personal address")
111 /* Old address book */
112 #define TAG_IF_OLD_COMMON "common_address"
113 #define TAG_IF_OLD_PERSONAL "personal_address"
115 #define DISP_OLD_COMMON _("Common address")
116 #define DISP_OLD_PERSONAL _("Personal address")
119 * Define attribute name-value pair.
121 typedef struct _AddressIfAttr AddressIfAttrib;
122 struct _AddressIfAttr {
128 * Define DOM fragment.
130 typedef struct _AddressIfFrag AddressIfFragment;
131 struct _AddressIfFrag {
138 * Build interface with default values.
140 * \param type Interface type.
141 * \param name Interface name.
142 * \param tagIf XML tag name for interface in address index file.
143 * \param tagDS XML tag name for datasource in address index file.
144 * \return Address interface object.
146 static AddressInterface *addrindex_create_interface(
147 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
149 AddressInterface *iface = g_new0( AddressInterface, 1 );
151 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
152 ADDRITEM_ID(iface) = NULL;
153 ADDRITEM_NAME(iface) = g_strdup( name );
154 ADDRITEM_PARENT(iface) = NULL;
155 ADDRITEM_SUBTYPE(iface) = type;
157 iface->name = g_strdup( name );
158 iface->listTag = g_strdup( tagIf );
159 iface->itemTag = g_strdup( tagDS );
160 iface->legacyFlag = FALSE;
161 iface->haveLibrary = TRUE;
162 iface->useInterface = TRUE;
163 iface->readOnly = TRUE;
165 /* Set callbacks to NULL values - override for each interface */
166 iface->getAccessFlag = NULL;
167 iface->getModifyFlag = NULL;
168 iface->getReadFlag = NULL;
169 iface->getStatusCode = NULL;
170 iface->getReadData = NULL;
171 iface->getRootFolder = NULL;
172 iface->getListFolder = NULL;
173 iface->getListPerson = NULL;
174 iface->getAllPersons = NULL;
175 iface->getAllGroups = NULL;
176 iface->getName = NULL;
177 iface->listSource = NULL;
180 iface->externalQuery = FALSE;
181 iface->searchOrder = 0; /* Ignored */
182 iface->startSearch = NULL;
183 iface->stopSearch = NULL;
189 * Build table of of all address book interfaces.
190 * \param addrIndex Address index object.
192 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
193 AddressInterface *iface;
195 /* Create intrinsic XML address book interface */
196 iface = addrindex_create_interface(
197 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
198 TAG_DS_ADDRESS_BOOK );
199 iface->readOnly = FALSE;
200 iface->getModifyFlag = ( void * ) addrbook_get_modified;
201 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
202 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
203 iface->getStatusCode = ( void * ) addrbook_get_status;
204 iface->getReadData = ( void * ) addrbook_read_data;
205 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
206 iface->getListFolder = ( void * ) addrbook_get_list_folder;
207 iface->getListPerson = ( void * ) addrbook_get_list_person;
208 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
209 iface->getName = ( void * ) addrbook_get_name;
210 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
211 iface->searchOrder = 0;
213 /* Add to list of interfaces in address book */
214 addrIndex->interfaceList =
215 g_list_append( addrIndex->interfaceList, iface );
216 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
218 /* Create vCard interface */
219 iface = addrindex_create_interface(
220 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
221 iface->getModifyFlag = ( void * ) vcard_get_modified;
222 iface->getAccessFlag = ( void * ) vcard_get_accessed;
223 iface->getReadFlag = ( void * ) vcard_get_read_flag;
224 iface->getStatusCode = ( void * ) vcard_get_status;
225 iface->getReadData = ( void * ) vcard_read_data;
226 iface->getRootFolder = ( void * ) vcard_get_root_folder;
227 iface->getListFolder = ( void * ) vcard_get_list_folder;
228 iface->getListPerson = ( void * ) vcard_get_list_person;
229 iface->getAllPersons = ( void * ) vcard_get_all_persons;
230 iface->getName = ( void * ) vcard_get_name;
231 iface->setAccessFlag = ( void * ) vcard_set_accessed;
232 iface->searchOrder = 0;
233 addrIndex->interfaceList =
234 g_list_append( addrIndex->interfaceList, iface );
235 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
237 /* Create JPilot interface */
238 iface = addrindex_create_interface(
239 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
242 iface->haveLibrary = jpilot_test_pilot_lib();
243 iface->useInterface = iface->haveLibrary;
244 iface->getModifyFlag = ( void * ) jpilot_get_modified;
245 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
246 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
247 iface->getStatusCode = ( void * ) jpilot_get_status;
248 iface->getReadData = ( void * ) jpilot_read_data;
249 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
250 iface->getListFolder = ( void * ) jpilot_get_list_folder;
251 iface->getListPerson = ( void * ) jpilot_get_list_person;
252 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
253 iface->getName = ( void * ) jpilot_get_name;
254 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
255 iface->searchOrder = 0;
257 iface->useInterface = FALSE;
258 iface->haveLibrary = FALSE;
260 addrIndex->interfaceList =
261 g_list_append( addrIndex->interfaceList, iface );
262 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
264 /* Create LDAP interface */
265 iface = addrindex_create_interface(
266 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
268 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
269 iface->haveLibrary = ldaputil_test_ldap_lib();
270 iface->useInterface = iface->haveLibrary;
271 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
272 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
273 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
274 iface->getStatusCode = ( void * ) ldapsvr_get_status;
275 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
276 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
277 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
278 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
279 iface->getName = ( void * ) ldapsvr_get_name;
280 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
281 iface->externalQuery = TRUE;
282 iface->searchOrder = 1;
284 iface->useInterface = FALSE;
285 iface->haveLibrary = FALSE;
287 addrIndex->interfaceList =
288 g_list_append( addrIndex->interfaceList, iface );
289 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
291 /* Two old legacy data sources (pre 0.7.0) */
292 iface = addrindex_create_interface(
293 ADDR_IF_COMMON, "Old Address - common",
294 TAG_IF_OLD_COMMON, NULL );
295 iface->legacyFlag = TRUE;
296 addrIndex->interfaceList =
297 g_list_append( addrIndex->interfaceList, iface );
298 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
300 iface = addrindex_create_interface(
301 ADDR_IF_COMMON, "Old Address - personal",
302 TAG_IF_OLD_PERSONAL, NULL );
303 iface->legacyFlag = TRUE;
304 addrIndex->interfaceList =
305 g_list_append( addrIndex->interfaceList, iface );
306 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
312 * \param fragment Fragment to free.
314 static addrindex_free_fragment( AddressIfFragment *fragment ) {
318 node = fragment->children;
320 AddressIfFragment *child = node->data;
321 addrindex_free_fragment( child );
323 node = g_list_next( node );
325 g_list_free( fragment->children );
327 /* Free attributes */
328 node = fragment->attributes;
330 AddressIfAttrib *nv = node->data;
335 node = g_list_next( node );
337 g_list_free( fragment->attributes );
339 g_free( fragment->name );
340 fragment->name = NULL;
341 fragment->attributes = NULL;
342 fragment->children = NULL;
348 * Create a new data source.
349 * \param ifType Interface type to create.
350 * \return Initialized data source.
352 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
353 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
355 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
356 ADDRITEM_ID(ds) = NULL;
357 ADDRITEM_NAME(ds) = NULL;
358 ADDRITEM_PARENT(ds) = NULL;
359 ADDRITEM_SUBTYPE(ds) = 0;
361 ds->rawDataSource = NULL;
362 ds->interface = NULL;
367 * Free up data source.
368 * \param ds Data source to free.
370 void addrindex_free_datasource( AddressDataSource *ds ) {
371 AddressInterface *iface;
373 g_return_if_fail( ds != NULL );
375 iface = ds->interface;
376 if( ds->rawDataSource != NULL ) {
377 if( iface != NULL ) {
378 if( iface->useInterface ) {
379 if( iface->type == ADDR_IF_BOOK ) {
380 AddressBookFile *abf = ds->rawDataSource;
381 addrbook_free_book( abf );
383 else if( iface->type == ADDR_IF_VCARD ) {
384 VCardFile *vcf = ds->rawDataSource;
388 else if( iface->type == ADDR_IF_JPILOT ) {
389 JPilotFile *jpf = ds->rawDataSource;
394 else if( iface->type == ADDR_IF_LDAP ) {
395 LdapServer *server = ds->rawDataSource;
396 ldapsvr_free( server );
403 AddressIfFragment *fragment = ds->rawDataSource;
404 addrindex_free_fragment( fragment );
409 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
410 ADDRITEM_ID(ds) = NULL;
411 ADDRITEM_NAME(ds) = NULL;
412 ADDRITEM_PARENT(ds) = NULL;
413 ADDRITEM_SUBTYPE(ds) = 0;
414 ds->type = ADDR_IF_NONE;
415 ds->interface = NULL;
416 ds->rawDataSource = NULL;
422 * Free up all data sources for specified interface.
423 * \param iface Address interface to process.
425 static void addrindex_free_all_datasources( AddressInterface *iface ) {
426 GList *node = iface->listSource;
428 AddressDataSource *ds = node->data;
429 addrindex_free_datasource( ds );
431 node = g_list_next( node );
436 * Free up specified interface.
437 * \param iface Interface to process.
439 static void addrindex_free_interface( AddressInterface *iface ) {
440 /* Free up data sources */
441 addrindex_free_all_datasources( iface );
442 g_list_free( iface->listSource );
444 /* Free internal storage */
445 g_free( ADDRITEM_ID(iface) );
446 g_free( ADDRITEM_NAME(iface) );
447 g_free( iface->name );
448 g_free( iface->listTag );
449 g_free( iface->itemTag );
451 /* Clear all pointers */
452 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
453 ADDRITEM_ID(iface) = NULL;
454 ADDRITEM_NAME(iface) = NULL;
455 ADDRITEM_PARENT(iface) = NULL;
456 ADDRITEM_SUBTYPE(iface) = 0;
457 iface->type = ADDR_IF_NONE;
459 iface->listTag = NULL;
460 iface->itemTag = NULL;
461 iface->legacyFlag = FALSE;
462 iface->useInterface = FALSE;
463 iface->haveLibrary = FALSE;
464 iface->listSource = NULL;
467 iface->searchOrder = 0;
468 iface->startSearch = NULL;
469 iface->stopSearch = NULL;
475 * Return cache ID for specified data source.
477 * \param addrIndex Address index.
478 * \param ds Data source.
479 * \return ID or NULL if not found. This should be <code>g_free()</code>
482 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
483 gchar *cacheID = NULL;
484 AddrBookBase *adbase;
487 g_return_val_if_fail( addrIndex != NULL, NULL );
488 g_return_val_if_fail( ds != NULL, NULL );
490 adbase = ( AddrBookBase * ) ds->rawDataSource;
492 cache = adbase->addressCache;
494 cacheID = g_strdup( cache->cacheID );
502 * Return reference to data source for specified cacheID.
503 * \param addrIndex Address index.
505 * \return Data source, or NULL if not found.
507 AddressDataSource *addrindex_get_datasource(
508 AddressIndex *addrIndex, const gchar *cacheID )
510 g_return_val_if_fail( addrIndex != NULL, NULL );
511 g_return_val_if_fail( cacheID != NULL, NULL );
512 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
516 * Return reference to address cache for specified cacheID.
517 * \param addrIndex Address index.
519 * \return Address cache, or NULL if not found.
521 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
522 AddressDataSource *ds;
523 AddrBookBase *adbase;
526 g_return_val_if_fail( addrIndex != NULL, NULL );
527 g_return_val_if_fail( cacheID != NULL, NULL );
530 ds = addrindex_get_datasource( addrIndex, cacheID );
532 adbase = ( AddrBookBase * ) ds->rawDataSource;
533 cache = adbase->addressCache;
539 * Add data source into hash table.
540 * \param addrIndex Address index.
541 * \param ds Data source.
543 static void addrindex_hash_add_cache(
544 AddressIndex *addrIndex, AddressDataSource *ds )
548 cacheID = addrindex_get_cache_id( addrIndex, ds );
550 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
555 * Free hash table callback function.
557 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
565 * Free hash table of address cache items.
567 static void addrindex_free_cache_hash( GHashTable *table ) {
568 g_hash_table_freeze( table );
569 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
570 g_hash_table_thaw( table );
571 g_hash_table_destroy( table );
575 * Remove data source from internal hashtable.
576 * \param addrIndex Address index.
577 * \param ds Data source to remove.
579 static void addrindex_hash_remove_cache(
580 AddressIndex *addrIndex, AddressDataSource *ds )
584 cacheID = addrindex_get_cache_id( addrIndex, ds );
586 g_hash_table_remove( addrIndex->hashCache, cacheID );
593 * Create a new address index.
594 * \return Initialized address index object.
596 AddressIndex *addrindex_create_index( void ) {
597 AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
599 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
600 ADDRITEM_ID(addrIndex) = NULL;
601 ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
602 ADDRITEM_PARENT(addrIndex) = NULL;
603 ADDRITEM_SUBTYPE(addrIndex) = 0;
604 addrIndex->filePath = NULL;
605 addrIndex->fileName = NULL;
606 addrIndex->retVal = MGU_SUCCESS;
607 addrIndex->needsConversion = FALSE;
608 addrIndex->wasConverted = FALSE;
609 addrIndex->conversionError = FALSE;
610 addrIndex->interfaceList = NULL;
611 addrIndex->lastType = ADDR_IF_NONE;
612 addrIndex->dirtyFlag = FALSE;
613 addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
614 addrIndex->loadedFlag = FALSE;
615 addrIndex->searchOrder = NULL;
616 addrindex_build_if_list( addrIndex );
621 * Property - Specify file path to address index file.
622 * \param addrIndex Address index.
623 * \param value Path to index file.
625 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
626 g_return_if_fail( addrIndex != NULL );
627 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
631 * Property - Specify file name to address index file.
632 * \param addrIndex Address index.
633 * \param value File name.
635 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
636 g_return_if_fail( addrIndex != NULL );
637 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
641 * Property - Specify file path to be used.
642 * \param addrIndex Address index.
643 * \param value Path to JPilot file.
645 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
646 g_return_if_fail( addrIndex != NULL );
647 addrIndex->dirtyFlag = value;
651 * Property - get loaded flag. Note that this flag is set after reading data
652 * from the address books.
653 * \param addrIndex Address index.
654 * \return <i>TRUE</i> if address index data was loaded.
656 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
657 g_return_val_if_fail( addrIndex != NULL, FALSE );
658 return addrIndex->loadedFlag;
662 * Return list of address interfaces.
663 * \param addrIndex Address index.
664 * \return List of address interfaces.
666 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
667 g_return_val_if_fail( addrIndex != NULL, NULL );
668 return addrIndex->interfaceList;
672 * Perform any other initialization of address index.
673 * \param addrIndex Address index.
675 void addrindex_initialize( AddressIndex *addrIndex ) {
676 addrcompl_initialize( addrIndex );
680 * Perform any other teardown of address index.
681 * \param addrIndex Address index.
683 void addrindex_teardown( AddressIndex *addrIndex ) {
684 addrcompl_teardown();
688 * Free up address index.
689 * \param addrIndex Address index.
691 void addrindex_free_index( AddressIndex *addrIndex ) {
694 g_return_if_fail( addrIndex != NULL );
697 g_list_free( addrIndex->searchOrder );
698 addrIndex->searchOrder = NULL;
700 /* Free internal storage */
701 g_free( ADDRITEM_ID(addrIndex) );
702 g_free( ADDRITEM_NAME(addrIndex) );
703 g_free( addrIndex->filePath );
704 g_free( addrIndex->fileName );
707 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
708 ADDRITEM_ID(addrIndex) = NULL;
709 ADDRITEM_NAME(addrIndex) = NULL;
710 ADDRITEM_PARENT(addrIndex) = NULL;
711 ADDRITEM_SUBTYPE(addrIndex) = 0;
712 addrIndex->filePath = NULL;
713 addrIndex->fileName = NULL;
714 addrIndex->retVal = MGU_SUCCESS;
715 addrIndex->needsConversion = FALSE;
716 addrIndex->wasConverted = FALSE;
717 addrIndex->conversionError = FALSE;
718 addrIndex->lastType = ADDR_IF_NONE;
719 addrIndex->dirtyFlag = FALSE;
721 /* Free up interfaces */
722 node = addrIndex->interfaceList;
724 AddressInterface *iface = node->data;
725 addrindex_free_interface( iface );
726 node = g_list_next( node );
728 g_list_free( addrIndex->interfaceList );
729 addrIndex->interfaceList = NULL;
731 /* Free up hash cache */
732 addrindex_free_cache_hash( addrIndex->hashCache );
733 addrIndex->hashCache = NULL;
735 addrIndex->loadedFlag = FALSE;
741 * Print address index.
742 * \param addrIndex Address index.
743 * \parem stream Stream to print.
745 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
746 g_return_if_fail( addrIndex != NULL );
747 fprintf( stream, "AddressIndex:\n" );
748 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
749 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
750 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
751 fprintf( stream, "\tconverted: '%s'\n",
752 addrIndex->wasConverted ? "yes" : "no" );
753 fprintf( stream, "\tcvt error: '%s'\n",
754 addrIndex->conversionError ? "yes" : "no" );
755 fprintf( stream, "\t---\n" );
759 * Retrieve reference to address interface for specified interface type.
760 * \param addrIndex Address index.
761 * \param ifType Interface type.
762 * \return Address interface, or NULL if not found.
764 AddressInterface *addrindex_get_interface(
765 AddressIndex *addrIndex, AddressIfType ifType )
767 AddressInterface *retVal = NULL;
770 g_return_val_if_fail( addrIndex != NULL, NULL );
772 node = addrIndex->interfaceList;
774 AddressInterface *iface = node->data;
775 node = g_list_next( node );
776 if( iface->type == ifType ) {
785 * Add raw data source to index. The raw data object (an AddressBookFile or
786 * VCardFile object, for example) should be supplied as the raw dataSource
789 * \param addrIndex Address index.
790 * \param ifType Interface type to add.
791 * \param dataSource Actual raw data source to add.
792 * \return Data source added, or NULL if invalid interface type.
794 AddressDataSource *addrindex_index_add_datasource(
795 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
797 AddressInterface *iface;
798 AddressDataSource *ds = NULL;
800 g_return_val_if_fail( addrIndex != NULL, NULL );
801 g_return_val_if_fail( dataSource != NULL, NULL );
803 iface = addrindex_get_interface( addrIndex, ifType );
805 ds = addrindex_create_datasource( ifType );
806 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
808 ds->rawDataSource = dataSource;
809 ds->interface = iface;
810 iface->listSource = g_list_append( iface->listSource, ds );
811 addrIndex->dirtyFlag = TRUE;
813 addrindex_hash_add_cache( addrIndex, ds );
819 * Remove specified data source from index.
820 * \param addrIndex Address index.
821 * \param dataSource Data source to add.
822 * \return Reference to data source if removed, or NULL if data source was not
823 * found in index. Note the this object must still be freed.
825 AddressDataSource *addrindex_index_remove_datasource(
826 AddressIndex *addrIndex, AddressDataSource *dataSource )
828 AddressDataSource *retVal = FALSE;
829 AddressInterface *iface;
831 g_return_val_if_fail( addrIndex != NULL, NULL );
832 g_return_val_if_fail( dataSource != NULL, NULL );
834 iface = addrindex_get_interface( addrIndex, dataSource->type );
836 iface->listSource = g_list_remove( iface->listSource, dataSource );
837 addrIndex->dirtyFlag = TRUE;
838 dataSource->interface = NULL;
840 /* Remove cache from hash table */
841 addrindex_hash_remove_cache( addrIndex, dataSource );
849 * Retrieve a reference to address interface for specified interface type and
850 * XML interface tag name.
851 * \param addrIndex Address index.
852 * \param tag XML interface tag name to match.
853 * \param ifType Interface type to match.
854 * \return Reference to address index, or NULL if not found in index.
856 static AddressInterface *addrindex_tag_get_interface(
857 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
859 AddressInterface *retVal = NULL;
860 GList *node = addrIndex->interfaceList;
863 AddressInterface *iface = node->data;
864 node = g_list_next( node );
866 if( strcmp( iface->listTag, tag ) == 0 ) {
872 if( iface->type == ifType ) {
882 * Retrieve a reference to address interface for specified interface type and
883 * XML datasource tag name.
884 * \param addrIndex Address index.
885 * \param ifType Interface type to match.
886 * \param tag XML datasource tag name to match.
887 * \return Reference to address index, or NULL if not found in index.
889 static AddressInterface *addrindex_tag_get_datasource(
890 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
892 AddressInterface *retVal = NULL;
893 GList *node = addrIndex->interfaceList;
896 AddressInterface *iface = node->data;
897 node = g_list_next( node );
898 if( iface->type == ifType && iface->itemTag ) {
899 if( strcmp( iface->itemTag, tag ) == 0 ) {
908 /* **********************************************************************
909 * Interface XML parsing functions.
910 * ***********************************************************************
914 * Write start of XML element to file.
916 * \param lvl Indentation level.
917 * \param name Element name.
919 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
921 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
927 * Write end of XML element to file.
929 * \param lvl Indentation level.
930 * \param name Element name.
932 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
934 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
941 * Write XML attribute to file.
943 * \param name Attribute name.
944 * \param value Attribute value.
946 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
950 xml_file_put_escape_str( fp, value );
955 * Return DOM fragment for current XML tag from file.
956 * \param file XML file being processed.
957 * \return Fragment representing DOM fragment for configuration element.
959 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
960 AddressIfFragment *fragment;
961 AddressIfFragment *child;
971 /* printf( "addrindex_read_fragment\n" ); */
973 prevLevel = file->level;
975 /* Get current tag name */
976 xtag = xml_get_current_tag( file );
978 /* Create new fragment */
979 fragment = g_new0( AddressIfFragment, 1 );
980 fragment->name = g_strdup( xtag->tag );
981 fragment->children = NULL;
982 fragment->attributes = NULL;
984 /* Read attributes */
986 attr = xml_get_current_tag_attr( file );
988 name = ((XMLAttr *)attr->data)->name;
989 value = ((XMLAttr *)attr->data)->value;
990 nv = g_new0( AddressIfAttrib, 1 );
991 nv->name = g_strdup( name );
992 nv->value = g_strdup( value );
993 list = g_list_append( list, nv );
994 attr = g_list_next( attr );
996 fragment->attributes = list;
998 /* Now read the children */
1000 rc = xml_parse_next_tag( file );
1005 if( file->level < prevLevel ) {
1006 /* We must be above level we start at */
1009 child = addrindex_read_fragment( file );
1010 fragment->children = g_list_append( fragment->children, child );
1017 * Write DOM fragment to file.
1018 * \param fp File to write.
1019 * \param fragment DOM fragment for configuration element.
1020 * \param lvl Indent level.
1022 static void addrindex_write_fragment(
1023 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1028 addrindex_write_elem_s( fp, lvl, fragment->name );
1029 node = fragment->attributes;
1031 AddressIfAttrib *nv = node->data;
1032 addrindex_write_attr( fp, nv->name, nv->value );
1033 node = g_list_next( node );
1035 if( fragment->children ) {
1038 /* Output children */
1039 node = fragment->children;
1041 AddressIfFragment *child = node->data;
1042 addrindex_write_fragment( fp, child, 1+lvl );
1043 node = g_list_next( node );
1046 /* Output closing tag */
1047 addrindex_write_elem_e( fp, lvl, fragment->name );
1056 static void addrindex_print_fragment_r(
1057 const AddressIfFragment *fragment, FILE *stream, gint lvl )
1062 for( i = 0; i < lvl; i++ )
1063 fprintf( stream, " " );
1064 fprintf( stream, "Element:%s:\n", fragment->name );
1065 node = fragment->attributes;
1067 AddressIfAttrib *nv = node->data;
1068 for( i = 0; i < lvl; i++ )
1069 fprintf( stream, " " );
1070 fprintf( stream, " %s : %s\n", nv->name, nv->value );
1071 node = g_list_next( node );
1073 node = fragment->children;
1075 AddressIfFragment *child = node->data;
1076 addrindex_print_fragment_r( child, stream, 1+lvl );
1077 node = g_list_next( node );
1081 static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
1082 addrindex_print_fragment_r( fragment, stream, 0 );
1087 * Read/parse address index file, creating a data source for a regular
1088 * intrinsic XML addressbook.
1089 * \param file Address index file.
1090 * \return Data source.
1092 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1093 AddressDataSource *ds;
1094 AddressBookFile *abf;
1097 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1098 abf = addrbook_create_book();
1099 attr = xml_get_current_tag_attr( file );
1101 gchar *name = ((XMLAttr *)attr->data)->name;
1102 gchar *value = ((XMLAttr *)attr->data)->value;
1103 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1104 addrbook_set_name( abf, value );
1106 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1107 addrbook_set_file( abf, value );
1109 attr = g_list_next( attr );
1111 ds->rawDataSource = abf;
1115 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1116 AddressBookFile *abf = ds->rawDataSource;
1118 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1119 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1120 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1121 fputs( " />\n", fp );
1125 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1126 AddressDataSource *ds;
1130 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1131 vcf = vcard_create();
1132 attr = xml_get_current_tag_attr( file );
1134 gchar *name = ((XMLAttr *)attr->data)->name;
1135 gchar *value = ((XMLAttr *)attr->data)->value;
1136 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1137 vcard_set_name( vcf, value );
1139 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1140 vcard_set_file( vcf, value );
1142 attr = g_list_next( attr );
1144 ds->rawDataSource = vcf;
1148 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1149 VCardFile *vcf = ds->rawDataSource;
1151 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1152 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1153 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1154 fputs( " />\n", fp );
1159 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1160 AddressDataSource *ds;
1164 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1165 jpf = jpilot_create();
1166 attr = xml_get_current_tag_attr( file );
1168 gchar *name = ((XMLAttr *)attr->data)->name;
1169 gchar *value = ((XMLAttr *)attr->data)->value;
1170 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1171 jpilot_set_name( jpf, value );
1173 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1174 jpilot_set_file( jpf, value );
1176 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1177 jpilot_add_custom_label( jpf, value );
1179 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1180 jpilot_add_custom_label( jpf, value );
1182 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1183 jpilot_add_custom_label( jpf, value );
1185 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1186 jpilot_add_custom_label( jpf, value );
1188 attr = g_list_next( attr );
1190 ds->rawDataSource = jpf;
1194 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1195 JPilotFile *jpf = ds->rawDataSource;
1199 GList *customLbl = jpilot_get_custom_labels( jpf );
1200 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1201 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1202 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1207 g_snprintf( name, sizeof(name), "%s%d",
1208 ATTAG_JPILOT_CUSTOM, ind );
1209 addrindex_write_attr( fp, name, node->data );
1211 node = g_list_next( node );
1213 fputs( " />\n", fp );
1219 * Just read/write DOM fragments (preserve data found in file).
1221 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1222 AddressDataSource *ds;
1224 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1225 ds->rawDataSource = addrindex_read_fragment( file );
1229 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1230 AddressIfFragment *fragment = ds->rawDataSource;
1232 addrindex_write_fragment( fp, fragment, lvl );
1239 * Parse LDAP criteria attribute data from XML file.
1240 * \param file Index file.
1241 * \param ctl LDAP control object to populate.
1243 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1252 if( file == NULL ) {
1257 prevLevel = file->level;
1258 xtagPrev = xml_get_current_tag( file );
1260 rc = xml_parse_next_tag( file );
1262 /* Terminate prematurely */
1263 mgu_free_dlist( list );
1267 if( file->level < prevLevel ) {
1268 /* We must be above level we start at */
1272 /* Get a tag (element) */
1273 xtag = xml_get_current_tag( file );
1274 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1275 /* LDAP criteria attribute */
1276 attr = xml_get_current_tag_attr( file );
1278 gchar *name = ((XMLAttr *)attr->data)->name;
1279 gchar *value = ((XMLAttr *)attr->data)->value;
1280 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1281 if( value && strlen( value ) > 0 ) {
1282 list = g_list_append(
1283 list, g_strdup( value ) );
1286 attr = g_list_next( attr );
1290 if( xtag != xtagPrev ) {
1291 /* Found a new tag */
1298 /* Build list of search attributes */
1299 ldapctl_criteria_list_clear( ctl );
1302 ldapctl_criteria_list_add( ctl, node->data );
1303 g_free( node->data );
1305 node = g_list_next( node );
1307 g_list_free( list );
1312 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1313 AddressDataSource *ds;
1317 gchar *serverName = NULL;
1318 gchar *criteria = NULL;
1319 gboolean bSearch = FALSE;
1320 gboolean cvtFlag = TRUE;
1322 /* printf( "addrindex_parse_ldap\n" ); */
1324 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1325 ctl = ldapctl_create();
1326 attr = xml_get_current_tag_attr( file );
1328 gchar *name = ((XMLAttr *)attr->data)->name;
1329 gchar *value = ((XMLAttr *)attr->data)->value;
1330 gint ivalue = atoi( value );
1332 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1333 if( serverName ) g_free( serverName );
1334 serverName = g_strdup( value );
1336 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1337 ldapctl_set_host( ctl, value );
1339 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1340 ldapctl_set_port( ctl, ivalue );
1342 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1343 ldapctl_set_base_dn( ctl, value );
1345 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1346 ldapctl_set_bind_dn( ctl, value );
1348 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1349 ldapctl_set_bind_password( ctl, value );
1351 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1352 if( criteria ) g_free( criteria );
1353 criteria = g_strdup( value );
1355 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1356 ldapctl_set_max_entries( ctl, ivalue );
1358 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1359 ldapctl_set_timeout( ctl, ivalue );
1361 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1362 ldapctl_set_max_query_age( ctl, ivalue );
1364 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1367 if( strcmp( value, "yes" ) == 0 ) {
1371 attr = g_list_next( attr );
1374 server = ldapsvr_create_noctl();
1375 ldapsvr_set_name( server, serverName );
1376 ldapsvr_set_search_flag( server, bSearch );
1377 g_free( serverName );
1378 ldapsvr_set_control( server, ctl );
1379 ds->rawDataSource = server;
1381 addrindex_parse_ldap_attrlist( file, ctl );
1383 * If criteria have been specified and no attributes were listed, then
1384 * convert old style criteria into an attribute list. Any criteria will
1385 * be dropped when saving data.
1388 if( ! ldapctl_get_criteria_list( ctl ) ) {
1389 ldapctl_parse_ldap_search( ctl, criteria );
1394 * If no search flag was found, then we are converting from old format
1395 * server data to new format.
1398 ldapsvr_set_search_flag( server, TRUE );
1400 /* ldapsvr_print_data( server, stdout ); */
1405 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1406 LdapServer *server = ds->rawDataSource;
1407 LdapControl *ctl = NULL;
1412 ctl = server->control;
1414 if( ctl == NULL ) return;
1416 /* Output start element with attributes */
1417 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1418 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1419 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1421 sprintf( value, "%d", ctl->port );
1422 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1424 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1425 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1426 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1428 sprintf( value, "%d", ctl->maxEntries );
1429 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1430 sprintf( value, "%d", ctl->timeOut );
1431 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1432 sprintf( value, "%d", ctl->maxQueryAge );
1433 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1435 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1436 server->searchFlag ? "yes" : "no" );
1440 /* Output attributes */
1441 node = ldapctl_get_criteria_list( ctl );
1443 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1444 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1446 node = g_list_next( node );
1449 /* End of element */
1450 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1456 * Just read/write DOM fragments (preserve data found in file).
1458 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1459 AddressDataSource *ds;
1461 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1462 ds->rawDataSource = addrindex_read_fragment( file );
1466 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1467 AddressIfFragment *fragment = ds->rawDataSource;
1469 addrindex_write_fragment( fp, fragment, lvl );
1474 /* **********************************************************************
1475 * Address index I/O functions.
1476 * ***********************************************************************
1479 * Read address index file, creating appropriate data sources for each address
1482 * \param addrIndex Address index.
1483 * \param file Address index file.
1485 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1488 AddressInterface *iface = NULL, *dsIFace = NULL;
1489 AddressDataSource *ds;
1492 addrIndex->loadedFlag = FALSE;
1494 prev_level = file->level;
1495 rc = xml_parse_next_tag( file );
1496 if( file->level == 0 ) return;
1498 xtag = xml_get_current_tag( file );
1500 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1502 addrIndex->lastType = iface->type;
1503 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1506 dsIFace = addrindex_tag_get_datasource(
1507 addrIndex, addrIndex->lastType, xtag->tag );
1509 /* Add data source to list */
1511 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1512 ds = addrindex_parse_book( file );
1513 if( ds->rawDataSource ) {
1514 addrbook_set_path( ds->rawDataSource,
1515 addrIndex->filePath );
1518 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1519 ds = addrindex_parse_vcard( file );
1521 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1522 ds = addrindex_parse_jpilot( file );
1524 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1525 ds = addrindex_parse_ldap( file );
1528 ds->interface = dsIFace;
1529 addrindex_hash_add_cache( addrIndex, ds );
1530 dsIFace->listSource =
1531 g_list_append( dsIFace->listSource, ds );
1539 * Search order sorting comparison function for building search order list.
1541 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1542 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1543 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1545 return ifaceA->searchOrder - ifaceB->searchOrder;
1549 * Build list of data sources to process.
1550 * \param addrIndex Address index object.
1552 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1553 AddressInterface *iface;
1556 /* Clear existing list */
1557 g_list_free( addrIndex->searchOrder );
1558 addrIndex->searchOrder = NULL;
1560 /* Build new list */
1561 nodeIf = addrIndex->interfaceList;
1563 AddressInterface *iface = nodeIf->data;
1564 if( iface->useInterface ) {
1565 if( iface->searchOrder > 0 ) {
1566 /* Add to search order list */
1567 addrIndex->searchOrder = g_list_insert_sorted(
1568 addrIndex->searchOrder, iface,
1569 addrindex_search_order_compare );
1572 nodeIf = g_list_next( nodeIf );
1576 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1577 XMLFile *file = NULL;
1578 gchar *fileSpec = NULL;
1580 g_return_val_if_fail( addrIndex != NULL, -1 );
1582 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1583 addrIndex->retVal = MGU_NO_FILE;
1584 file = xml_open_file( fileSpec );
1587 if( file == NULL ) {
1589 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1591 return addrIndex->retVal;
1594 addrIndex->retVal = MGU_BAD_FORMAT;
1595 if( xml_get_dtd( file ) == 0 ) {
1596 if( xml_parse_next_tag( file ) == 0 ) {
1597 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1598 addrindex_read_index( addrIndex, file );
1599 addrIndex->retVal = MGU_SUCCESS;
1603 xml_close_file( file );
1605 addrindex_build_search_order( addrIndex );
1607 return addrIndex->retVal;
1610 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1611 GList *nodeIF, *nodeDS;
1613 gint lvlItem = 1 + lvlList;
1615 nodeIF = addrIndex->interfaceList;
1617 AddressInterface *iface = nodeIF->data;
1618 if( ! iface->legacyFlag ) {
1619 nodeDS = iface->listSource;
1620 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1623 AddressDataSource *ds = nodeDS->data;
1625 if( iface->type == ADDR_IF_BOOK ) {
1626 addrindex_write_book( fp, ds, lvlItem );
1628 if( iface->type == ADDR_IF_VCARD ) {
1629 addrindex_write_vcard( fp, ds, lvlItem );
1631 if( iface->type == ADDR_IF_JPILOT ) {
1632 addrindex_write_jpilot( fp, ds, lvlItem );
1634 if( iface->type == ADDR_IF_LDAP ) {
1635 addrindex_write_ldap( fp, ds, lvlItem );
1638 nodeDS = g_list_next( nodeDS );
1640 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1642 nodeIF = g_list_next( nodeIF );
1647 * Write data to specified file.
1648 * Enter: addrIndex Address index object.
1649 * newFile New file name.
1650 * return: Status code, from addrIndex->retVal.
1651 * Note: File will be created in directory specified by addrIndex.
1653 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1656 #ifndef DEV_STANDALONE
1660 g_return_val_if_fail( addrIndex != NULL, -1 );
1662 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1663 addrIndex->retVal = MGU_OPEN_FILE;
1664 #ifdef DEV_STANDALONE
1665 fp = fopen( fileSpec, "wb" );
1668 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1670 pfile = prefs_write_open( fileSpec );
1674 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
1675 conv_get_current_charset_str() );
1677 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1680 addrindex_write_index( addrIndex, fp );
1681 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1683 addrIndex->retVal = MGU_SUCCESS;
1684 #ifdef DEV_STANDALONE
1687 if( prefs_file_close( pfile ) < 0 ) {
1688 addrIndex->retVal = MGU_ERROR_WRITE;
1694 return addrIndex->retVal;
1698 * Save address index data to original file.
1699 * return: Status code, from addrIndex->retVal.
1701 gint addrindex_save_data( AddressIndex *addrIndex ) {
1702 g_return_val_if_fail( addrIndex != NULL, -1 );
1704 addrIndex->retVal = MGU_NO_FILE;
1705 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1706 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1708 addrindex_write_to( addrIndex, addrIndex->fileName );
1709 if( addrIndex->retVal == MGU_SUCCESS ) {
1710 addrIndex->dirtyFlag = FALSE;
1712 return addrIndex->retVal;
1716 * Save all address book files which may have changed.
1717 * Return: Status code, set if there was a problem saving data.
1719 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1720 gint retVal = MGU_SUCCESS;
1721 GList *nodeIf, *nodeDS;
1723 nodeIf = addrIndex->interfaceList;
1725 AddressInterface *iface = nodeIf->data;
1726 if( iface->type == ADDR_IF_BOOK ) {
1727 nodeDS = iface->listSource;
1729 AddressDataSource *ds = nodeDS->data;
1730 AddressBookFile *abf = ds->rawDataSource;
1731 if( addrbook_get_dirty( abf ) ) {
1732 if( addrbook_get_read_flag( abf ) ) {
1733 addrbook_save_data( abf );
1734 if( abf->retVal != MGU_SUCCESS ) {
1735 retVal = abf->retVal;
1739 nodeDS = g_list_next( nodeDS );
1743 nodeIf = g_list_next( nodeIf );
1749 /* **********************************************************************
1750 * Address book conversion to new format.
1751 * ***********************************************************************
1754 #define ELTAG_IF_OLD_FOLDER "folder"
1755 #define ELTAG_IF_OLD_GROUP "group"
1756 #define ELTAG_IF_OLD_ITEM "item"
1757 #define ELTAG_IF_OLD_NAME "name"
1758 #define ELTAG_IF_OLD_ADDRESS "address"
1759 #define ELTAG_IF_OLD_REMARKS "remarks"
1760 #define ATTAG_IF_OLD_NAME "name"
1762 #define TEMPNODE_ROOT 0
1763 #define TEMPNODE_FOLDER 1
1764 #define TEMPNODE_GROUP 2
1765 #define TEMPNODE_ADDRESS 3
1767 typedef struct _AddressCvt_Node AddressCvtNode;
1768 struct _AddressCvt_Node {
1777 * Parse current address item.
1779 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1784 nn = g_new0( AddressCvtNode, 1 );
1785 nn->type = TEMPNODE_ADDRESS;
1788 level = file->level;
1791 xml_parse_next_tag(file);
1792 if (file->level < level) return nn;
1794 element = xml_get_element( file );
1795 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1796 nn->name = g_strdup( element );
1798 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1799 nn->address = g_strdup( element );
1801 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1802 nn->remarks = g_strdup( element );
1804 xml_parse_next_tag(file);
1809 * Create a temporary node below specified node.
1811 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1813 nn = g_new0( AddressCvtNode, 1 );
1815 nn->name = g_strdup( name );
1816 nn->remarks = g_strdup( rem );
1817 node->list = g_list_append( node->list, nn );
1822 * Process current temporary node.
1824 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1827 AddressCvtNode *newNode = NULL;
1832 prev_level = file->level;
1833 xml_parse_next_tag( file );
1834 if (file->level < prev_level) return;
1838 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1839 attr = xml_get_current_tag_attr(file);
1841 name = ((XMLAttr *)attr->data)->name;
1842 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1843 value = ((XMLAttr *)attr->data)->value;
1846 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1847 addrindex_add_obj( file, newNode );
1850 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1851 attr = xml_get_current_tag_attr(file);
1853 name = ((XMLAttr *)attr->data)->name;
1854 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1855 value = ((XMLAttr *)attr->data)->value;
1858 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1859 addrindex_add_obj( file, newNode );
1861 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1862 newNode = addrindex_parse_item( file );
1863 node->list = g_list_append( node->list, newNode );
1866 /* printf( "invalid: !!! \n" ); */
1867 attr = xml_get_current_tag_attr( file );
1873 * Consume all nodes below current tag.
1875 static void addrindex_consume_tree( XMLFile *file ) {
1882 prev_level = file->level;
1883 xml_parse_next_tag( file );
1884 if (file->level < prev_level) return;
1886 xtag = xml_get_current_tag( file );
1887 /* printf( "tag : %s\n", xtag->tag ); */
1888 element = xml_get_element( file );
1889 attr = xml_get_current_tag_attr( file );
1890 /* show_attribs( attr ); */
1891 /* printf( "\ttag value : %s :\n", element ); */
1892 addrindex_consume_tree( file );
1897 * Print temporary tree.
1899 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1902 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1903 fprintf( stream, "\tname :%s:\n", node->name );
1904 fprintf( stream, "\taddr :%s:\n", node->address );
1905 fprintf( stream, "\trems :%s:\n", node->remarks );
1907 fprintf( stream, "\t--list----\n" );
1911 AddressCvtNode *lNode = list->data;
1912 list = g_list_next( list );
1913 addrindex_print_node( lNode, stream );
1915 fprintf( stream, "\t==list-%d==\n", node->type );
1919 * Free up temporary tree.
1921 static void addrindex_free_node( AddressCvtNode *node ) {
1922 GList *list = node->list;
1925 AddressCvtNode *lNode = list->data;
1926 list = g_list_next( list );
1927 addrindex_free_node( lNode );
1929 node->type = TEMPNODE_ROOT;
1930 g_free( node->name );
1931 g_free( node->address );
1932 g_free( node->remarks );
1933 g_list_free( node->list );
1938 * Process address book for specified node.
1940 static void addrindex_process_node(
1941 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1942 ItemGroup *parentGrp, ItemFolder *folderGrp )
1945 ItemFolder *itemFolder = NULL;
1946 ItemGroup *itemGParent = parentGrp;
1947 ItemFolder *itemGFolder = folderGrp;
1948 AddressCache *cache = abf->addressCache;
1950 if( node->type == TEMPNODE_ROOT ) {
1951 itemFolder = parent;
1953 else if( node->type == TEMPNODE_FOLDER ) {
1954 itemFolder = addritem_create_item_folder();
1955 addritem_folder_set_name( itemFolder, node->name );
1956 addrcache_id_folder( cache, itemFolder );
1957 addrcache_folder_add_folder( cache, parent, itemFolder );
1960 else if( node->type == TEMPNODE_GROUP ) {
1961 ItemGroup *itemGroup;
1964 /* Create a folder for group */
1965 fName = g_strdup_printf( "Cvt - %s", node->name );
1966 itemGFolder = addritem_create_item_folder();
1967 addritem_folder_set_name( itemGFolder, fName );
1968 addrcache_id_folder( cache, itemGFolder );
1969 addrcache_folder_add_folder( cache, parent, itemGFolder );
1972 /* Add group into folder */
1973 itemGroup = addritem_create_item_group();
1974 addritem_group_set_name( itemGroup, node->name );
1975 addrcache_id_group( cache, itemGroup );
1976 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1977 itemGParent = itemGroup;
1979 else if( node->type == TEMPNODE_ADDRESS ) {
1980 ItemPerson *itemPerson;
1981 ItemEMail *itemEMail;
1983 /* Create person and email objects */
1984 itemPerson = addritem_create_item_person();
1985 addritem_person_set_common_name( itemPerson, node->name );
1986 addrcache_id_person( cache, itemPerson );
1987 itemEMail = addritem_create_item_email();
1988 addritem_email_set_address( itemEMail, node->address );
1989 addritem_email_set_remarks( itemEMail, node->remarks );
1990 addrcache_id_email( cache, itemEMail );
1991 addrcache_person_add_email( cache, itemPerson, itemEMail );
1993 /* Add person into appropriate folder */
1995 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
1998 addrcache_folder_add_person( cache, parent, itemPerson );
2001 /* Add email address only into group */
2003 addrcache_group_add_email( cache, parentGrp, itemEMail );
2009 AddressCvtNode *lNode = list->data;
2010 list = g_list_next( list );
2011 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2016 * Process address book to specified file number.
2018 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2019 gboolean retVal = FALSE;
2020 AddressBookFile *abf = NULL;
2021 AddressCvtNode *rootNode = NULL;
2022 gchar *newFile = NULL;
2023 GList *fileList = NULL;
2026 /* Setup root node */
2027 rootNode = g_new0( AddressCvtNode, 1 );
2028 rootNode->type = TEMPNODE_ROOT;
2029 rootNode->name = g_strdup( "root" );
2030 rootNode->list = NULL;
2031 addrindex_add_obj( file, rootNode );
2032 /* addrindex_print_node( rootNode, stdout ); */
2034 /* Create new address book */
2035 abf = addrbook_create_book();
2036 addrbook_set_name( abf, displayName );
2037 addrbook_set_path( abf, addrIndex->filePath );
2039 /* Determine next available file number */
2040 fileList = addrbook_get_bookfile_list( abf );
2042 fileNum = 1 + abf->maxValue;
2044 g_list_free( fileList );
2047 newFile = addrbook_gen_new_file_name( fileNum );
2049 addrbook_set_file( abf, newFile );
2052 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2054 /* addrbook_dump_book( abf, stdout ); */
2055 addrbook_save_data( abf );
2056 addrIndex->retVal = abf->retVal;
2057 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2059 addrbook_free_book( abf );
2061 addrindex_free_node( rootNode );
2064 /* Create entries in address index */
2066 abf = addrbook_create_book();
2067 addrbook_set_name( abf, displayName );
2068 addrbook_set_path( abf, addrIndex->filePath );
2069 addrbook_set_file( abf, newFile );
2070 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2077 * Process tree converting data.
2079 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2087 prev_level = file->level;
2088 xml_parse_next_tag( file );
2089 if (file->level < prev_level) return;
2091 xtag = xml_get_current_tag( file );
2092 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2093 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2094 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2095 addrIndex->needsConversion = FALSE;
2096 addrIndex->wasConverted = TRUE;
2101 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2102 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2103 addrIndex->needsConversion = FALSE;
2104 addrIndex->wasConverted = TRUE;
2109 element = xml_get_element( file );
2110 attr = xml_get_current_tag_attr( file );
2111 /* show_attribs( attr ); */
2112 /* printf( "\ttag value : %s :\n", element ); */
2113 addrindex_consume_tree( file );
2117 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2118 XMLFile *file = NULL;
2121 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2122 addrIndex->retVal = MGU_NO_FILE;
2123 file = xml_open_file( fileSpec );
2126 if( file == NULL ) {
2127 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2128 return addrIndex->retVal;
2131 addrIndex->retVal = MGU_BAD_FORMAT;
2132 if( xml_get_dtd( file ) == 0 ) {
2133 if( xml_parse_next_tag( file ) == 0 ) {
2134 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2135 addrindex_convert_tree( addrIndex, file );
2139 xml_close_file( file );
2140 return addrIndex->retVal;
2144 * Create a new address book file.
2146 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2147 gboolean retVal = FALSE;
2148 AddressBookFile *abf = NULL;
2149 gchar *newFile = NULL;
2150 GList *fileList = NULL;
2153 /* Create new address book */
2154 abf = addrbook_create_book();
2155 addrbook_set_name( abf, displayName );
2156 addrbook_set_path( abf, addrIndex->filePath );
2158 /* Determine next available file number */
2159 fileList = addrbook_get_bookfile_list( abf );
2161 fileNum = 1 + abf->maxValue;
2163 g_list_free( fileList );
2166 newFile = addrbook_gen_new_file_name( fileNum );
2168 addrbook_set_file( abf, newFile );
2171 addrbook_save_data( abf );
2172 addrIndex->retVal = abf->retVal;
2173 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2174 addrbook_free_book( abf );
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 * Read data for address index performing a conversion if necesary.
2191 * Enter: addrIndex Address index object.
2192 * return: Status code, from addrIndex->retVal.
2193 * Note: New address book files will be created in directory specified by
2194 * addrIndex. Three files will be created, for the following:
2195 * "Common addresses"
2196 * "Personal addresses"
2197 * "Gathered addresses" - a new address book.
2199 gint addrindex_read_data( AddressIndex *addrIndex ) {
2200 g_return_val_if_fail( addrIndex != NULL, -1 );
2202 addrIndex->conversionError = FALSE;
2203 addrindex_read_file( addrIndex );
2204 if( addrIndex->retVal == MGU_SUCCESS ) {
2205 if( addrIndex->needsConversion ) {
2206 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2207 addrIndex->conversionError = TRUE;
2210 addrIndex->conversionError = TRUE;
2213 addrIndex->dirtyFlag = TRUE;
2215 return addrIndex->retVal;
2219 * Create new address books for a new address index.
2220 * Enter: addrIndex Address index object.
2221 * return: Status code, from addrIndex->retVal.
2222 * Note: New address book files will be created in directory specified by
2223 * addrIndex. Three files will be created, for the following:
2224 * "Common addresses"
2225 * "Personal addresses"
2226 * "Gathered addresses" - a new address book.
2228 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2231 g_return_val_if_fail( addrIndex != NULL, -1 );
2233 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2235 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2236 addrIndex->dirtyFlag = TRUE;
2238 return addrIndex->retVal;
2241 /* **********************************************************************
2242 * New interface stuff.
2243 * ***********************************************************************
2247 * Return modified flag for specified data source.
2249 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2250 gboolean retVal = FALSE;
2251 AddressInterface *iface;
2253 if( ds == NULL ) return retVal;
2254 iface = ds->interface;
2255 if( iface == NULL ) return retVal;
2256 if( iface->getModifyFlag ) {
2257 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2263 * Return accessed flag for specified data source.
2265 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2266 gboolean retVal = FALSE;
2267 AddressInterface *iface;
2269 if( ds == NULL ) return retVal;
2270 iface = ds->interface;
2271 if( iface == NULL ) return retVal;
2272 if( iface->getAccessFlag ) {
2273 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2279 * Return data read flag for specified data source.
2281 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2282 gboolean retVal = TRUE;
2283 AddressInterface *iface;
2285 if( ds == NULL ) return retVal;
2286 iface = ds->interface;
2287 if( iface == NULL ) return retVal;
2288 if( iface->getReadFlag ) {
2289 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2295 * Return status code for specified data source.
2297 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2298 gint retVal = MGU_SUCCESS;
2299 AddressInterface *iface;
2301 if( ds == NULL ) return retVal;
2302 iface = ds->interface;
2303 if( iface == NULL ) return retVal;
2304 if( iface->getStatusCode ) {
2305 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2311 * Return data read flag for specified data source.
2313 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2314 gint retVal = MGU_SUCCESS;
2315 AddressInterface *iface;
2317 if( ds == NULL ) return retVal;
2318 iface = ds->interface;
2319 if( iface == NULL ) return retVal;
2320 if( iface->getReadData ) {
2321 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2322 /* printf( "addrindex_ds_read_data...reading:::%s:::\n", name ); */
2323 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2329 * Return data read flag for specified data source.
2331 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2332 ItemFolder *retVal = NULL;
2333 AddressInterface *iface;
2335 if( ds == NULL ) return retVal;
2336 iface = ds->interface;
2337 if( iface == NULL ) return retVal;
2338 if( iface->getRootFolder ) {
2339 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2345 * Return list of folders for specified data source.
2347 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2348 GList *retVal = FALSE;
2349 AddressInterface *iface;
2351 if( ds == NULL ) return retVal;
2352 iface = ds->interface;
2353 if( iface == NULL ) return retVal;
2354 if( iface->getListFolder ) {
2355 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2361 * Return list of persons in root folder for specified data source.
2363 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2364 GList *retVal = FALSE;
2365 AddressInterface *iface;
2367 if( ds == NULL ) return retVal;
2368 iface = ds->interface;
2369 if( iface == NULL ) return retVal;
2370 if( iface->getListPerson ) {
2371 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2377 * Return name for specified data source.
2379 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2380 gchar *retVal = FALSE;
2381 AddressInterface *iface;
2383 if( ds == NULL ) return retVal;
2384 iface = ds->interface;
2385 if( iface == NULL ) return retVal;
2386 if( iface->getName ) {
2387 retVal = ( iface->getName ) ( ds->rawDataSource );
2393 * Set the access flag inside the data source.
2395 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2396 AddressInterface *iface;
2398 if( ds == NULL ) return;
2399 iface = ds->interface;
2400 if( iface == NULL ) return;
2401 if( iface->setAccessFlag ) {
2402 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2407 * Return read only flag for specified data source.
2409 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2410 AddressInterface *iface;
2411 if( ds == NULL ) return TRUE;
2412 iface = ds->interface;
2413 if( iface == NULL ) return TRUE;
2414 return iface->readOnly;
2418 * Return list of all persons for specified data source.
2420 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2421 GList *retVal = NULL;
2422 AddressInterface *iface;
2424 if( ds == NULL ) return retVal;
2425 iface = ds->interface;
2426 if( iface == NULL ) return retVal;
2427 if( iface->getAllPersons ) {
2428 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2434 * Return list of all groups for specified data source.
2436 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2437 GList *retVal = NULL;
2438 AddressInterface *iface;
2440 if( ds == NULL ) return retVal;
2441 iface = ds->interface;
2442 if( iface == NULL ) return retVal;
2443 if( iface->getAllGroups ) {
2444 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2449 /* **********************************************************************
2450 * Address search stuff.
2451 * ***********************************************************************
2455 * Current query ID. This is incremented for each query created.
2457 static gint _currentQueryID_ = 0;
2460 * Variables for the search that is being performed.
2462 static gchar *_searchTerm_ = NULL;
2463 static gpointer _searchTarget_ = NULL;
2464 static AddrSearchCallbackFunc *_searchCallback_ = NULL;
2467 * Setup or register the search that will be performed.
2468 * \param addrIndex Address index object.
2469 * \param searchTerm Search term. A private copy will be made.
2470 * \param target Target object that will receive data.
2471 * \param callBack Callback function.
2472 * \return ID allocated to query that will be executed.
2474 gint addrindex_setup_search(
2475 AddressIndex *addrIndex, const gchar *searchTerm,
2476 const gpointer target, AddrSearchCallbackFunc callBack )
2480 /* printf( "search term ::%s::\n", searchTerm ); */
2481 g_free( _searchTerm_ );
2482 _searchTerm_ = g_strdup( searchTerm );
2484 queryID = ++_currentQueryID_;
2485 _searchTarget_ = target;
2486 _searchCallback_ = callBack;
2487 /* printf( "query ID ::%d::\n", queryID ); */
2493 * LDAP callback entry point for each address entry found.
2494 * \param qry LDAP query.
2495 * \param listEMail List of Item EMail objects found.
2497 static void addrindex_ldap_entry_cb( LdapQuery *qry, GList *listEMail ) {
2501 printf( "\naddrindex::addrindex_ldap_entry_cb ::%s::\n", qry->queryName );
2504 ItemEMail *email = node->data;
2505 printf( "\temail ::%s::\n", email->address );
2506 node = g_list_next( node );
2509 if( _searchCallback_ ) {
2510 ( _searchCallback_ ) ( qry->queryID, listEMail, _searchTarget_ );
2512 g_list_free( listEMail );
2516 * LDAP callback entry point for completion of search.
2517 * \param qry LDAP query.
2519 static void addrindex_ldap_end_cb( LdapQuery *qry ) {
2520 /* printf( "\naddrindex::addrindex_ldap_end_cb ::%s::\n", qry->queryName ); */
2524 * Return results of previous query.
2526 * \return List of ItemEMail objects.
2528 static void addrindex_ldap_use_previous( const ItemFolder *folder, const gint queryID )
2535 if( _searchCallback_ ) {
2536 node = folder->listPerson;
2538 AddrItemObject *aio = node->data;
2539 if( aio && aio->type == ITEMTYPE_PERSON ) {
2540 ItemPerson *person = node->data;
2541 nodeEM = person->listEMail;
2543 ItemEMail *email = nodeEM->data;
2544 nodeEM = g_list_next( nodeEM );
2545 listEMail = g_list_append( listEMail, email );
2548 node = g_list_next( node );
2550 ( _searchCallback_ ) ( queryID, listEMail, _searchTarget_ );
2551 g_list_free( listEMail );
2555 LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm );
2558 * Construct an LDAP query and initiate an LDAP search.
2559 * \param server LDAP server object.
2560 * \param queryID ID of search query to be executed.
2562 static void addrindex_search_ldap( LdapServer *server, const gint queryID ) {
2566 if( ! server->searchFlag ) return;
2568 /* Retire any aged queries */
2569 ldapsvr_retire_query( server );
2571 /* Test whether any queries for the same term exist */
2572 qry = ldapsvr_locate_query( server, _searchTerm_ );
2574 ItemFolder *folder = qry->folder;
2576 /* Touch query to ensure it hangs around for a bit longer */
2577 ldapqry_touch( qry );
2579 addrindex_ldap_use_previous( folder, queryID );
2584 /* Construct a query */
2585 qry = ldapqry_create();
2586 ldapqry_set_query_id( qry, queryID );
2587 ldapqry_set_search_value( qry, _searchTerm_ );
2588 ldapqry_set_query_type( qry, LDAPQUERY_DYNAMIC );
2589 ldapqry_set_callback_entry( qry, addrindex_ldap_entry_cb );
2590 ldapqry_set_callback_end( qry, addrindex_ldap_end_cb );
2592 /* Name the query */
2593 name = g_strdup_printf( "Search for '%s'", _searchTerm_ );
2594 ldapqry_set_name( qry, name );
2597 ldapsvr_add_query( server, qry );
2598 ldapsvr_execute_query( server, qry );
2602 * Construct an LDAP query and initiate an LDAP search.
2603 * \param server LDAP server object to search.
2604 * \param searchTerm Search term to locate.
2605 * \param callbackEnd Function to call when search has terminated.
2608 void addrindex_search_ldap_noid(
2609 LdapServer *server, const gchar *searchTerm, void * callbackEnd )
2614 /* Construct a query */
2615 qry = ldapqry_create();
2616 ldapqry_set_search_value( qry, searchTerm );
2617 ldapqry_set_query_type( qry, LDAPQUERY_STATIC );
2618 ldapqry_set_callback_end( qry, callbackEnd );
2620 /* Name the query */
2621 name = g_strdup_printf( "Static Search for '%s'", searchTerm );
2622 ldapqry_set_name( qry, name );
2625 ldapsvr_add_query( server, qry );
2626 /* printf( "addrindex_search_ldap_noid::executing static search...\n" ); */
2627 ldapsvr_execute_query( server, qry );
2632 * Perform the previously registered search.
2633 * \param addrIndex Address index object.
2634 * \param queryID ID of search query to be executed.
2635 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2638 gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
2639 AddressInterface *iface;
2640 AddressDataSource *ds;
2645 /* printf( "addrindex_start_search::%d::\n", queryID ); */
2646 nodeIf = addrIndex->searchOrder;
2648 iface = nodeIf->data;
2649 nodeIf = g_list_next( nodeIf );
2651 if( ! iface->useInterface ) {
2655 if( ! iface->externalQuery ) {
2660 nodeDS = iface->listSource;
2663 nodeDS = g_list_next( nodeDS );
2665 if( type == ADDR_IF_LDAP ) {
2666 LdapServer *server = ds->rawDataSource;
2667 addrindex_search_ldap( server, queryID );
2676 * Stop the previously registered search.
2677 * \param addrIndex Address index object.
2678 * \param queryID ID of search query to stop.
2680 void addrindex_stop_search( AddressIndex *addrIndex, const gint queryID ){
2682 AddressInterface *iface;
2683 AddressDataSource *ds;
2688 /* If query ID does not match, search has not been setup */
2689 /* if( queryID != _queryID_ ) return; */
2691 /* printf( "addrindex_stop_search::%d::\n", queryID ); */
2692 nodeIf = addrIndex->searchOrder;
2694 iface = nodeIf->data;
2695 nodeIf = g_list_next( nodeIf );
2697 if( ! iface->useInterface ) {
2702 nodeDS = iface->listSource;
2705 nodeDS = g_list_next( nodeDS );
2706 if( type == ADDR_IF_LDAP ) {
2707 LdapServer *server = ds->rawDataSource;
2708 ldapsvr_stop_all_query( server );
2716 * Read all address books that do not support dynamic queries.
2717 * \param addrIndex Address index object.
2719 void addrindex_read_all( AddressIndex *addrIndex ) {
2720 AddressInterface *iface;
2721 AddressDataSource *ds;
2725 nodeIf = addrIndex->searchOrder;
2727 iface = nodeIf->data;
2728 nodeIf = g_list_next( nodeIf );
2730 if( ! iface->useInterface ) {
2733 if( iface->externalQuery ) {
2736 nodeDS = iface->listSource;
2739 nodeDS = g_list_next( nodeDS );
2741 /* Read address book */
2742 if( addrindex_ds_get_modify_flag( ds ) ) {
2743 addrindex_ds_read_data( ds );
2747 if( ! addrindex_ds_get_read_flag( ds ) ) {
2748 addrindex_ds_read_data( ds );
2753 addrIndex->loadedFlag = TRUE;
2757 * This function is used by the address completion function to load
2758 * addresses for all non-external address book interfaces.
2760 * \param addrIndex Address index object.
2761 * \param callBackFunc Function to be called when an address is
2763 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2765 gboolean addrindex_load_completion(
2766 AddressIndex *addrIndex,
2767 gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) )
2769 AddressDataSource *ds;
2770 AddressInterface *iface;
2771 GList *nodeIf, *nodeDS;
2772 GList *listP, *nodeP;
2774 gchar *sName, *sAddress, *sAlias, *sFriendly;
2776 if( addrIndex == NULL ) return FALSE;
2778 nodeIf = addrindex_get_interface_list( addrIndex );
2780 AddressInterface *iface = nodeIf->data;
2782 nodeIf = g_list_next( nodeIf );
2783 if( ! iface->useInterface ) {
2786 if( iface->externalQuery ) {
2789 nodeDS = iface->listSource;
2793 /* Read address book */
2794 if( addrindex_ds_get_modify_flag( ds ) ) {
2795 addrindex_ds_read_data( ds );
2798 if( ! addrindex_ds_get_read_flag( ds ) ) {
2799 addrindex_ds_read_data( ds );
2802 /* Get all persons */
2803 listP = addrindex_ds_get_all_persons( ds );
2806 ItemPerson *person = nodeP->data;
2807 nodeM = person->listEMail;
2809 /* Figure out name to use */
2810 sName = person->nickName;
2811 if( sName == NULL || *sName == '\0' ) {
2812 sName = ADDRITEM_NAME(person);
2815 /* Process each E-Mail address */
2817 ItemEMail *email = nodeM->data;
2820 sAddress = email->address;
2821 if( sAddress || *sAddress != '\0' ) {
2822 sAlias = ADDRITEM_NAME(email);
2823 if( sAlias && *sAlias != '\0' ) {
2826 ( callBackFunc ) ( sFriendly, sAddress, sName );
2829 nodeM = g_list_next( nodeM );
2831 nodeP = g_list_next( nodeP );
2833 /* Free up the list */
2834 g_list_free( listP );
2836 nodeDS = g_list_next( nodeDS );