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"
40 #include "addr_compl.h"
42 #ifndef DEV_STANDALONE
43 #include "prefs_gtk.h"
54 #include "ldapserver.h"
56 #include "ldapquery.h"
59 #define TAG_ADDRESS_INDEX "addressbook"
61 #define TAG_IF_ADDRESS_BOOK "book_list"
62 #define TAG_IF_VCARD "vcard_list"
63 #define TAG_IF_JPILOT "jpilot_list"
64 #define TAG_IF_LDAP "ldap_list"
66 #define TAG_DS_ADDRESS_BOOK "book"
67 #define TAG_DS_VCARD "vcard"
68 #define TAG_DS_JPILOT "jpilot"
69 #define TAG_DS_LDAP "server"
71 /* XML Attribute names */
72 #define ATTAG_BOOK_NAME "name"
73 #define ATTAG_BOOK_FILE "file"
75 #define ATTAG_VCARD_NAME "name"
76 #define ATTAG_VCARD_FILE "file"
78 #define ATTAG_JPILOT_NAME "name"
79 #define ATTAG_JPILOT_FILE "file"
80 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
81 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
82 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
83 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
84 #define ATTAG_JPILOT_CUSTOM "custom-"
86 #define ATTAG_LDAP_NAME "name"
87 #define ATTAG_LDAP_HOST "host"
88 #define ATTAG_LDAP_PORT "port"
89 #define ATTAG_LDAP_BASE_DN "base-dn"
90 #define ATTAG_LDAP_BIND_DN "bind-dn"
91 #define ATTAG_LDAP_BIND_PASS "bind-pass"
92 #define ATTAG_LDAP_CRITERIA "criteria"
93 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
94 #define ATTAG_LDAP_TIMEOUT "timeout"
95 #define ATTAG_LDAP_MAX_AGE "max-age"
96 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
98 #define ELTAG_LDAP_ATTR_SRCH "attribute"
99 #define ATTAG_LDAP_ATTR_NAME "name"
102 #define ATTAG_LDAP_DEFAULT "default"
106 N_("Personal address")
109 #define DISP_NEW_COMMON _("Common address")
110 #define DISP_NEW_PERSONAL _("Personal address")
112 /* Old address book */
113 #define TAG_IF_OLD_COMMON "common_address"
114 #define TAG_IF_OLD_PERSONAL "personal_address"
116 #define DISP_OLD_COMMON _("Common address")
117 #define DISP_OLD_PERSONAL _("Personal address")
120 * Define attribute name-value pair.
122 typedef struct _AddressIfAttr AddressIfAttrib;
123 struct _AddressIfAttr {
129 * Define DOM fragment.
131 typedef struct _AddressIfFrag AddressIfFragment;
132 struct _AddressIfFrag {
139 * Build interface with default values.
141 * \param type Interface type.
142 * \param name Interface name.
143 * \param tagIf XML tag name for interface in address index file.
144 * \param tagDS XML tag name for datasource in address index file.
145 * \return Address interface object.
147 static AddressInterface *addrindex_create_interface(
148 gint type, gchar *name, gchar *tagIf, gchar *tagDS )
150 AddressInterface *iface = g_new0( AddressInterface, 1 );
152 ADDRITEM_TYPE(iface) = ITEMTYPE_INTERFACE;
153 ADDRITEM_ID(iface) = NULL;
154 ADDRITEM_NAME(iface) = g_strdup( name );
155 ADDRITEM_PARENT(iface) = NULL;
156 ADDRITEM_SUBTYPE(iface) = type;
158 iface->name = g_strdup( name );
159 iface->listTag = g_strdup( tagIf );
160 iface->itemTag = g_strdup( tagDS );
161 iface->legacyFlag = FALSE;
162 iface->haveLibrary = TRUE;
163 iface->useInterface = TRUE;
164 iface->readOnly = TRUE;
166 /* Set callbacks to NULL values - override for each interface */
167 iface->getAccessFlag = NULL;
168 iface->getModifyFlag = NULL;
169 iface->getReadFlag = NULL;
170 iface->getStatusCode = NULL;
171 iface->getReadData = NULL;
172 iface->getRootFolder = NULL;
173 iface->getListFolder = NULL;
174 iface->getListPerson = NULL;
175 iface->getAllPersons = NULL;
176 iface->getAllGroups = NULL;
177 iface->getName = NULL;
178 iface->listSource = NULL;
181 iface->externalQuery = FALSE;
182 iface->searchOrder = 0; /* Ignored */
183 iface->startSearch = NULL;
184 iface->stopSearch = NULL;
190 * Build table of of all address book interfaces.
191 * \param addrIndex Address index object.
193 static void addrindex_build_if_list( AddressIndex *addrIndex ) {
194 AddressInterface *iface;
196 /* Create intrinsic XML address book interface */
197 iface = addrindex_create_interface(
198 ADDR_IF_BOOK, "Address Book", TAG_IF_ADDRESS_BOOK,
199 TAG_DS_ADDRESS_BOOK );
200 iface->readOnly = FALSE;
201 iface->getModifyFlag = ( void * ) addrbook_get_modified;
202 iface->getAccessFlag = ( void * ) addrbook_get_accessed;
203 iface->getReadFlag = ( void * ) addrbook_get_read_flag;
204 iface->getStatusCode = ( void * ) addrbook_get_status;
205 iface->getReadData = ( void * ) addrbook_read_data;
206 iface->getRootFolder = ( void * ) addrbook_get_root_folder;
207 iface->getListFolder = ( void * ) addrbook_get_list_folder;
208 iface->getListPerson = ( void * ) addrbook_get_list_person;
209 iface->getAllPersons = ( void * ) addrbook_get_all_persons;
210 iface->getName = ( void * ) addrbook_get_name;
211 iface->setAccessFlag = ( void * ) addrbook_set_accessed;
212 iface->searchOrder = 0;
214 /* Add to list of interfaces in address book */
215 addrIndex->interfaceList =
216 g_list_append( addrIndex->interfaceList, iface );
217 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
219 /* Create vCard interface */
220 iface = addrindex_create_interface(
221 ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
222 iface->getModifyFlag = ( void * ) vcard_get_modified;
223 iface->getAccessFlag = ( void * ) vcard_get_accessed;
224 iface->getReadFlag = ( void * ) vcard_get_read_flag;
225 iface->getStatusCode = ( void * ) vcard_get_status;
226 iface->getReadData = ( void * ) vcard_read_data;
227 iface->getRootFolder = ( void * ) vcard_get_root_folder;
228 iface->getListFolder = ( void * ) vcard_get_list_folder;
229 iface->getListPerson = ( void * ) vcard_get_list_person;
230 iface->getAllPersons = ( void * ) vcard_get_all_persons;
231 iface->getName = ( void * ) vcard_get_name;
232 iface->setAccessFlag = ( void * ) vcard_set_accessed;
233 iface->searchOrder = 0;
234 addrIndex->interfaceList =
235 g_list_append( addrIndex->interfaceList, iface );
236 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
238 /* Create JPilot interface */
239 iface = addrindex_create_interface(
240 ADDR_IF_JPILOT, "J-Pilot", TAG_IF_JPILOT,
243 iface->haveLibrary = jpilot_test_pilot_lib();
244 iface->useInterface = iface->haveLibrary;
245 iface->getModifyFlag = ( void * ) jpilot_get_modified;
246 iface->getAccessFlag = ( void * ) jpilot_get_accessed;
247 iface->getReadFlag = ( void * ) jpilot_get_read_flag;
248 iface->getStatusCode = ( void * ) jpilot_get_status;
249 iface->getReadData = ( void * ) jpilot_read_data;
250 iface->getRootFolder = ( void * ) jpilot_get_root_folder;
251 iface->getListFolder = ( void * ) jpilot_get_list_folder;
252 iface->getListPerson = ( void * ) jpilot_get_list_person;
253 iface->getAllPersons = ( void * ) jpilot_get_all_persons;
254 iface->getName = ( void * ) jpilot_get_name;
255 iface->setAccessFlag = ( void * ) jpilot_set_accessed;
256 iface->searchOrder = 0;
258 iface->useInterface = FALSE;
259 iface->haveLibrary = FALSE;
261 addrIndex->interfaceList =
262 g_list_append( addrIndex->interfaceList, iface );
263 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
265 /* Create LDAP interface */
266 iface = addrindex_create_interface(
267 ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
269 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
270 iface->haveLibrary = ldaputil_test_ldap_lib();
271 iface->useInterface = iface->haveLibrary;
272 /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
273 iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
274 /* iface->getReadFlag = ( void * ) ldapsvr_get_read_flag; */
275 iface->getStatusCode = ( void * ) ldapsvr_get_status;
276 /* iface->getReadData = ( void * ) ldapsvr_read_data; */
277 iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
278 iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
279 iface->getListPerson = ( void * ) ldapsvr_get_list_person;
280 iface->getName = ( void * ) ldapsvr_get_name;
281 iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
282 iface->externalQuery = TRUE;
283 iface->searchOrder = 1;
285 iface->useInterface = FALSE;
286 iface->haveLibrary = FALSE;
288 addrIndex->interfaceList =
289 g_list_append( addrIndex->interfaceList, iface );
290 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
292 /* Two old legacy data sources (pre 0.7.0) */
293 iface = addrindex_create_interface(
294 ADDR_IF_COMMON, "Old Address - common",
295 TAG_IF_OLD_COMMON, NULL );
296 iface->legacyFlag = TRUE;
297 addrIndex->interfaceList =
298 g_list_append( addrIndex->interfaceList, iface );
299 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
301 iface = addrindex_create_interface(
302 ADDR_IF_COMMON, "Old Address - personal",
303 TAG_IF_OLD_PERSONAL, NULL );
304 iface->legacyFlag = TRUE;
305 addrIndex->interfaceList =
306 g_list_append( addrIndex->interfaceList, iface );
307 ADDRITEM_PARENT(iface) = ADDRITEM_OBJECT(addrIndex);
313 * \param fragment Fragment to free.
315 static void addrindex_free_fragment( AddressIfFragment *fragment ) {
319 node = fragment->children;
321 AddressIfFragment *child = node->data;
322 addrindex_free_fragment( child );
324 node = g_list_next( node );
326 g_list_free( fragment->children );
328 /* Free attributes */
329 node = fragment->attributes;
331 AddressIfAttrib *nv = node->data;
336 node = g_list_next( node );
338 g_list_free( fragment->attributes );
340 g_free( fragment->name );
341 fragment->name = NULL;
342 fragment->attributes = NULL;
343 fragment->children = NULL;
349 * Create a new data source.
350 * \param ifType Interface type to create.
351 * \return Initialized data source.
353 AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
354 AddressDataSource *ds = g_new0( AddressDataSource, 1 );
356 ADDRITEM_TYPE(ds) = ITEMTYPE_DATASOURCE;
357 ADDRITEM_ID(ds) = NULL;
358 ADDRITEM_NAME(ds) = NULL;
359 ADDRITEM_PARENT(ds) = NULL;
360 ADDRITEM_SUBTYPE(ds) = 0;
362 ds->rawDataSource = NULL;
363 ds->interface = NULL;
368 * Free up data source.
369 * \param ds Data source to free.
371 void addrindex_free_datasource( AddressDataSource *ds ) {
372 AddressInterface *iface;
374 g_return_if_fail( ds != NULL );
376 iface = ds->interface;
377 if( ds->rawDataSource != NULL ) {
378 if( iface != NULL ) {
379 if( iface->useInterface ) {
380 if( iface->type == ADDR_IF_BOOK ) {
381 AddressBookFile *abf = ds->rawDataSource;
382 addrbook_free_book( abf );
384 else if( iface->type == ADDR_IF_VCARD ) {
385 VCardFile *vcf = ds->rawDataSource;
389 else if( iface->type == ADDR_IF_JPILOT ) {
390 JPilotFile *jpf = ds->rawDataSource;
395 else if( iface->type == ADDR_IF_LDAP ) {
396 LdapServer *server = ds->rawDataSource;
397 ldapsvr_free( server );
404 AddressIfFragment *fragment = ds->rawDataSource;
405 addrindex_free_fragment( fragment );
410 ADDRITEM_TYPE(ds) = ITEMTYPE_NONE;
411 ADDRITEM_ID(ds) = NULL;
412 ADDRITEM_NAME(ds) = NULL;
413 ADDRITEM_PARENT(ds) = NULL;
414 ADDRITEM_SUBTYPE(ds) = 0;
415 ds->type = ADDR_IF_NONE;
416 ds->interface = NULL;
417 ds->rawDataSource = NULL;
423 * Free up all data sources for specified interface.
424 * \param iface Address interface to process.
426 static void addrindex_free_all_datasources( AddressInterface *iface ) {
427 GList *node = iface->listSource;
429 AddressDataSource *ds = node->data;
430 addrindex_free_datasource( ds );
432 node = g_list_next( node );
437 * Free up specified interface.
438 * \param iface Interface to process.
440 static void addrindex_free_interface( AddressInterface *iface ) {
441 /* Free up data sources */
442 addrindex_free_all_datasources( iface );
443 g_list_free( iface->listSource );
445 /* Free internal storage */
446 g_free( ADDRITEM_ID(iface) );
447 g_free( ADDRITEM_NAME(iface) );
448 g_free( iface->name );
449 g_free( iface->listTag );
450 g_free( iface->itemTag );
452 /* Clear all pointers */
453 ADDRITEM_TYPE(iface) = ITEMTYPE_NONE;
454 ADDRITEM_ID(iface) = NULL;
455 ADDRITEM_NAME(iface) = NULL;
456 ADDRITEM_PARENT(iface) = NULL;
457 ADDRITEM_SUBTYPE(iface) = 0;
458 iface->type = ADDR_IF_NONE;
460 iface->listTag = NULL;
461 iface->itemTag = NULL;
462 iface->legacyFlag = FALSE;
463 iface->useInterface = FALSE;
464 iface->haveLibrary = FALSE;
465 iface->listSource = NULL;
468 iface->searchOrder = 0;
469 iface->startSearch = NULL;
470 iface->stopSearch = NULL;
476 * Return cache ID for specified data source.
478 * \param addrIndex Address index.
479 * \param ds Data source.
480 * \return ID or NULL if not found. This should be <code>g_free()</code>
483 gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds ) {
484 gchar *cacheID = NULL;
485 AddrBookBase *adbase;
488 g_return_val_if_fail( addrIndex != NULL, NULL );
489 g_return_val_if_fail( ds != NULL, NULL );
491 adbase = ( AddrBookBase * ) ds->rawDataSource;
493 cache = adbase->addressCache;
495 cacheID = g_strdup( cache->cacheID );
503 * Return reference to data source for specified cacheID.
504 * \param addrIndex Address index.
506 * \return Data source, or NULL if not found.
508 AddressDataSource *addrindex_get_datasource(
509 AddressIndex *addrIndex, const gchar *cacheID )
511 g_return_val_if_fail( addrIndex != NULL, NULL );
512 g_return_val_if_fail( cacheID != NULL, NULL );
513 return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
517 * Return reference to address cache for specified cacheID.
518 * \param addrIndex Address index.
520 * \return Address cache, or NULL if not found.
522 AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID ) {
523 AddressDataSource *ds;
524 AddrBookBase *adbase;
527 g_return_val_if_fail( addrIndex != NULL, NULL );
528 g_return_val_if_fail( cacheID != NULL, NULL );
531 ds = addrindex_get_datasource( addrIndex, cacheID );
533 adbase = ( AddrBookBase * ) ds->rawDataSource;
534 cache = adbase->addressCache;
540 * Add data source into hash table.
541 * \param addrIndex Address index.
542 * \param ds Data source.
544 static void addrindex_hash_add_cache(
545 AddressIndex *addrIndex, AddressDataSource *ds )
549 cacheID = addrindex_get_cache_id( addrIndex, ds );
551 g_hash_table_insert( addrIndex->hashCache, cacheID, ds );
556 * Free hash table callback function.
558 static gboolean addrindex_free_cache_cb( gpointer key, gpointer value, gpointer data ) {
566 * Free hash table of address cache items.
568 static void addrindex_free_cache_hash( GHashTable *table ) {
569 g_hash_table_freeze( table );
570 g_hash_table_foreach_remove( table, addrindex_free_cache_cb, NULL );
571 g_hash_table_thaw( table );
572 g_hash_table_destroy( table );
576 * Remove data source from internal hashtable.
577 * \param addrIndex Address index.
578 * \param ds Data source to remove.
580 static void addrindex_hash_remove_cache(
581 AddressIndex *addrIndex, AddressDataSource *ds )
585 cacheID = addrindex_get_cache_id( addrIndex, ds );
587 g_hash_table_remove( addrIndex->hashCache, cacheID );
594 * Create a new address index.
595 * \return Initialized address index object.
597 AddressIndex *addrindex_create_index( void ) {
598 AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
600 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
601 ADDRITEM_ID(addrIndex) = NULL;
602 ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
603 ADDRITEM_PARENT(addrIndex) = NULL;
604 ADDRITEM_SUBTYPE(addrIndex) = 0;
605 addrIndex->filePath = NULL;
606 addrIndex->fileName = NULL;
607 addrIndex->retVal = MGU_SUCCESS;
608 addrIndex->needsConversion = FALSE;
609 addrIndex->wasConverted = FALSE;
610 addrIndex->conversionError = FALSE;
611 addrIndex->interfaceList = NULL;
612 addrIndex->lastType = ADDR_IF_NONE;
613 addrIndex->dirtyFlag = FALSE;
614 addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
615 addrIndex->loadedFlag = FALSE;
616 addrIndex->searchOrder = NULL;
617 addrindex_build_if_list( addrIndex );
622 * Property - Specify file path to address index file.
623 * \param addrIndex Address index.
624 * \param value Path to index file.
626 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
627 g_return_if_fail( addrIndex != NULL );
628 addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
632 * Property - Specify file name to address index file.
633 * \param addrIndex Address index.
634 * \param value File name.
636 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
637 g_return_if_fail( addrIndex != NULL );
638 addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
642 * Property - Specify file path to be used.
643 * \param addrIndex Address index.
644 * \param value Path to JPilot file.
646 void addrindex_set_dirty( AddressIndex *addrIndex, const gboolean value ) {
647 g_return_if_fail( addrIndex != NULL );
648 addrIndex->dirtyFlag = value;
652 * Property - get loaded flag. Note that this flag is set after reading data
653 * from the address books.
654 * \param addrIndex Address index.
655 * \return <i>TRUE</i> if address index data was loaded.
657 gboolean addrindex_get_loaded( AddressIndex *addrIndex ) {
658 g_return_val_if_fail( addrIndex != NULL, FALSE );
659 return addrIndex->loadedFlag;
663 * Return list of address interfaces.
664 * \param addrIndex Address index.
665 * \return List of address interfaces.
667 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
668 g_return_val_if_fail( addrIndex != NULL, NULL );
669 return addrIndex->interfaceList;
673 * Perform any other initialization of address index.
674 * \param addrIndex Address index.
676 void addrindex_initialize( AddressIndex *addrIndex ) {
678 addrcompl_initialize( addrIndex );
682 * Perform any other teardown of address index.
683 * \param addrIndex Address index.
685 void addrindex_teardown( AddressIndex *addrIndex ) {
686 addrcompl_teardown();
691 * Free up address index.
692 * \param addrIndex Address index.
694 void addrindex_free_index( AddressIndex *addrIndex ) {
697 g_return_if_fail( addrIndex != NULL );
700 g_list_free( addrIndex->searchOrder );
701 addrIndex->searchOrder = NULL;
703 /* Free internal storage */
704 g_free( ADDRITEM_ID(addrIndex) );
705 g_free( ADDRITEM_NAME(addrIndex) );
706 g_free( addrIndex->filePath );
707 g_free( addrIndex->fileName );
710 ADDRITEM_TYPE(addrIndex) = ITEMTYPE_NONE;
711 ADDRITEM_ID(addrIndex) = NULL;
712 ADDRITEM_NAME(addrIndex) = NULL;
713 ADDRITEM_PARENT(addrIndex) = NULL;
714 ADDRITEM_SUBTYPE(addrIndex) = 0;
715 addrIndex->filePath = NULL;
716 addrIndex->fileName = NULL;
717 addrIndex->retVal = MGU_SUCCESS;
718 addrIndex->needsConversion = FALSE;
719 addrIndex->wasConverted = FALSE;
720 addrIndex->conversionError = FALSE;
721 addrIndex->lastType = ADDR_IF_NONE;
722 addrIndex->dirtyFlag = FALSE;
724 /* Free up interfaces */
725 node = addrIndex->interfaceList;
727 AddressInterface *iface = node->data;
728 addrindex_free_interface( iface );
729 node = g_list_next( node );
731 g_list_free( addrIndex->interfaceList );
732 addrIndex->interfaceList = NULL;
734 /* Free up hash cache */
735 addrindex_free_cache_hash( addrIndex->hashCache );
736 addrIndex->hashCache = NULL;
738 addrIndex->loadedFlag = FALSE;
744 * Print address index.
745 * \param addrIndex Address index.
746 * \parem stream Stream to print.
748 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
749 g_return_if_fail( addrIndex != NULL );
750 fprintf( stream, "AddressIndex:\n" );
751 fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
752 fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
753 fprintf( stream, "\t status: %d\n", addrIndex->retVal );
754 fprintf( stream, "\tconverted: '%s'\n",
755 addrIndex->wasConverted ? "yes" : "no" );
756 fprintf( stream, "\tcvt error: '%s'\n",
757 addrIndex->conversionError ? "yes" : "no" );
758 fprintf( stream, "\t---\n" );
762 * Retrieve reference to address interface for specified interface type.
763 * \param addrIndex Address index.
764 * \param ifType Interface type.
765 * \return Address interface, or NULL if not found.
767 AddressInterface *addrindex_get_interface(
768 AddressIndex *addrIndex, AddressIfType ifType )
770 AddressInterface *retVal = NULL;
773 g_return_val_if_fail( addrIndex != NULL, NULL );
775 node = addrIndex->interfaceList;
777 AddressInterface *iface = node->data;
778 node = g_list_next( node );
779 if( iface->type == ifType ) {
788 * Add raw data source to index. The raw data object (an AddressBookFile or
789 * VCardFile object, for example) should be supplied as the raw dataSource
792 * \param addrIndex Address index.
793 * \param ifType Interface type to add.
794 * \param dataSource Actual raw data source to add.
795 * \return Data source added, or NULL if invalid interface type.
797 AddressDataSource *addrindex_index_add_datasource(
798 AddressIndex *addrIndex, AddressIfType ifType, gpointer dataSource )
800 AddressInterface *iface;
801 AddressDataSource *ds = NULL;
803 g_return_val_if_fail( addrIndex != NULL, NULL );
804 g_return_val_if_fail( dataSource != NULL, NULL );
806 iface = addrindex_get_interface( addrIndex, ifType );
808 ds = addrindex_create_datasource( ifType );
809 ADDRITEM_PARENT(ds) = ADDRITEM_OBJECT(iface);
811 ds->rawDataSource = dataSource;
812 ds->interface = iface;
813 iface->listSource = g_list_append( iface->listSource, ds );
814 addrIndex->dirtyFlag = TRUE;
816 addrindex_hash_add_cache( addrIndex, ds );
822 * Remove specified data source from index.
823 * \param addrIndex Address index.
824 * \param dataSource Data source to add.
825 * \return Reference to data source if removed, or NULL if data source was not
826 * found in index. Note the this object must still be freed.
828 AddressDataSource *addrindex_index_remove_datasource(
829 AddressIndex *addrIndex, AddressDataSource *dataSource )
831 AddressDataSource *retVal = FALSE;
832 AddressInterface *iface;
834 g_return_val_if_fail( addrIndex != NULL, NULL );
835 g_return_val_if_fail( dataSource != NULL, NULL );
837 iface = addrindex_get_interface( addrIndex, dataSource->type );
839 iface->listSource = g_list_remove( iface->listSource, dataSource );
840 addrIndex->dirtyFlag = TRUE;
841 dataSource->interface = NULL;
843 /* Remove cache from hash table */
844 addrindex_hash_remove_cache( addrIndex, dataSource );
852 * Retrieve a reference to address interface for specified interface type and
853 * XML interface tag name.
854 * \param addrIndex Address index.
855 * \param tag XML interface tag name to match.
856 * \param ifType Interface type to match.
857 * \return Reference to address index, or NULL if not found in index.
859 static AddressInterface *addrindex_tag_get_interface(
860 AddressIndex *addrIndex, gchar *tag, AddressIfType ifType )
862 AddressInterface *retVal = NULL;
863 GList *node = addrIndex->interfaceList;
866 AddressInterface *iface = node->data;
867 node = g_list_next( node );
869 if( strcmp( iface->listTag, tag ) == 0 ) {
875 if( iface->type == ifType ) {
885 * Retrieve a reference to address interface for specified interface type and
886 * XML datasource tag name.
887 * \param addrIndex Address index.
888 * \param ifType Interface type to match.
889 * \param tag XML datasource tag name to match.
890 * \return Reference to address index, or NULL if not found in index.
892 static AddressInterface *addrindex_tag_get_datasource(
893 AddressIndex *addrIndex, AddressIfType ifType, gchar *tag )
895 AddressInterface *retVal = NULL;
896 GList *node = addrIndex->interfaceList;
899 AddressInterface *iface = node->data;
900 node = g_list_next( node );
901 if( iface->type == ifType && iface->itemTag ) {
902 if( strcmp( iface->itemTag, tag ) == 0 ) {
911 /* **********************************************************************
912 * Interface XML parsing functions.
913 * ***********************************************************************
917 * Write start of XML element to file.
919 * \param lvl Indentation level.
920 * \param name Element name.
922 static void addrindex_write_elem_s( FILE *fp, const gint lvl, const gchar *name ) {
924 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
930 * Write end of XML element to file.
932 * \param lvl Indentation level.
933 * \param name Element name.
935 static void addrindex_write_elem_e( FILE *fp, const gint lvl, const gchar *name ) {
937 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
944 * Write XML attribute to file.
946 * \param name Attribute name.
947 * \param value Attribute value.
949 static void addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value ) {
953 xml_file_put_escape_str( fp, value );
958 * Return DOM fragment for current XML tag from file.
959 * \param file XML file being processed.
960 * \return Fragment representing DOM fragment for configuration element.
962 static AddressIfFragment *addrindex_read_fragment( XMLFile *file ) {
963 AddressIfFragment *fragment;
964 AddressIfFragment *child;
974 /* printf( "addrindex_read_fragment\n" ); */
976 prevLevel = file->level;
978 /* Get current tag name */
979 xtag = xml_get_current_tag( file );
981 /* Create new fragment */
982 fragment = g_new0( AddressIfFragment, 1 );
983 fragment->name = g_strdup( xtag->tag );
984 fragment->children = NULL;
985 fragment->attributes = NULL;
987 /* Read attributes */
989 attr = xml_get_current_tag_attr( file );
991 name = ((XMLAttr *)attr->data)->name;
992 value = ((XMLAttr *)attr->data)->value;
993 nv = g_new0( AddressIfAttrib, 1 );
994 nv->name = g_strdup( name );
995 nv->value = g_strdup( value );
996 list = g_list_append( list, nv );
997 attr = g_list_next( attr );
999 fragment->attributes = list;
1001 /* Now read the children */
1003 rc = xml_parse_next_tag( file );
1008 if( file->level < prevLevel ) {
1009 /* We must be above level we start at */
1012 child = addrindex_read_fragment( file );
1013 fragment->children = g_list_append( fragment->children, child );
1020 * Write DOM fragment to file.
1021 * \param fp File to write.
1022 * \param fragment DOM fragment for configuration element.
1023 * \param lvl Indent level.
1025 static void addrindex_write_fragment(
1026 FILE *fp, const AddressIfFragment *fragment, const gint lvl )
1031 addrindex_write_elem_s( fp, lvl, fragment->name );
1032 node = fragment->attributes;
1034 AddressIfAttrib *nv = node->data;
1035 addrindex_write_attr( fp, nv->name, nv->value );
1036 node = g_list_next( node );
1038 if( fragment->children ) {
1041 /* Output children */
1042 node = fragment->children;
1044 AddressIfFragment *child = node->data;
1045 addrindex_write_fragment( fp, child, 1+lvl );
1046 node = g_list_next( node );
1049 /* Output closing tag */
1050 addrindex_write_elem_e( fp, lvl, fragment->name );
1059 static void addrindex_print_fragment_r(
1060 const AddressIfFragment *fragment, FILE *stream, gint lvl )
1065 for( i = 0; i < lvl; i++ )
1066 fprintf( stream, " " );
1067 fprintf( stream, "Element:%s:\n", fragment->name );
1068 node = fragment->attributes;
1070 AddressIfAttrib *nv = node->data;
1071 for( i = 0; i < lvl; i++ )
1072 fprintf( stream, " " );
1073 fprintf( stream, " %s : %s\n", nv->name, nv->value );
1074 node = g_list_next( node );
1076 node = fragment->children;
1078 AddressIfFragment *child = node->data;
1079 addrindex_print_fragment_r( child, stream, 1+lvl );
1080 node = g_list_next( node );
1084 static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
1085 addrindex_print_fragment_r( fragment, stream, 0 );
1090 * Read/parse address index file, creating a data source for a regular
1091 * intrinsic XML addressbook.
1092 * \param file Address index file.
1093 * \return Data source.
1095 static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
1096 AddressDataSource *ds;
1097 AddressBookFile *abf;
1100 ds = addrindex_create_datasource( ADDR_IF_BOOK );
1101 abf = addrbook_create_book();
1102 attr = xml_get_current_tag_attr( file );
1104 gchar *name = ((XMLAttr *)attr->data)->name;
1105 gchar *value = ((XMLAttr *)attr->data)->value;
1106 if( strcmp( name, ATTAG_BOOK_NAME ) == 0 ) {
1107 addrbook_set_name( abf, value );
1109 else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
1110 addrbook_set_file( abf, value );
1112 attr = g_list_next( attr );
1114 ds->rawDataSource = abf;
1118 static void addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
1119 AddressBookFile *abf = ds->rawDataSource;
1121 addrindex_write_elem_s( fp, lvl, TAG_DS_ADDRESS_BOOK );
1122 addrindex_write_attr( fp, ATTAG_BOOK_NAME, addrbook_get_name( abf ) );
1123 addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName );
1124 fputs( " />\n", fp );
1128 static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
1129 AddressDataSource *ds;
1133 ds = addrindex_create_datasource( ADDR_IF_VCARD );
1134 vcf = vcard_create();
1135 attr = xml_get_current_tag_attr( file );
1137 gchar *name = ((XMLAttr *)attr->data)->name;
1138 gchar *value = ((XMLAttr *)attr->data)->value;
1139 if( strcmp( name, ATTAG_VCARD_NAME ) == 0 ) {
1140 vcard_set_name( vcf, value );
1142 else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
1143 vcard_set_file( vcf, value );
1145 attr = g_list_next( attr );
1147 ds->rawDataSource = vcf;
1151 static void addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
1152 VCardFile *vcf = ds->rawDataSource;
1154 addrindex_write_elem_s( fp, lvl, TAG_DS_VCARD );
1155 addrindex_write_attr( fp, ATTAG_VCARD_NAME, vcard_get_name( vcf ) );
1156 addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path );
1157 fputs( " />\n", fp );
1162 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1163 AddressDataSource *ds;
1167 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1168 jpf = jpilot_create();
1169 attr = xml_get_current_tag_attr( file );
1171 gchar *name = ((XMLAttr *)attr->data)->name;
1172 gchar *value = ((XMLAttr *)attr->data)->value;
1173 if( strcmp( name, ATTAG_JPILOT_NAME ) == 0 ) {
1174 jpilot_set_name( jpf, value );
1176 else if( strcmp( name, ATTAG_JPILOT_FILE ) == 0 ) {
1177 jpilot_set_file( jpf, value );
1179 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_1 ) == 0 ) {
1180 jpilot_add_custom_label( jpf, value );
1182 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_2 ) == 0 ) {
1183 jpilot_add_custom_label( jpf, value );
1185 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_3 ) == 0 ) {
1186 jpilot_add_custom_label( jpf, value );
1188 else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
1189 jpilot_add_custom_label( jpf, value );
1191 attr = g_list_next( attr );
1193 ds->rawDataSource = jpf;
1197 static void addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
1198 JPilotFile *jpf = ds->rawDataSource;
1202 GList *customLbl = jpilot_get_custom_labels( jpf );
1203 addrindex_write_elem_s( fp, lvl, TAG_DS_JPILOT );
1204 addrindex_write_attr( fp, ATTAG_JPILOT_NAME, jpilot_get_name( jpf ) );
1205 addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path );
1210 g_snprintf( name, sizeof(name), "%s%d",
1211 ATTAG_JPILOT_CUSTOM, ind );
1212 addrindex_write_attr( fp, name, node->data );
1214 node = g_list_next( node );
1216 fputs( " />\n", fp );
1222 * Just read/write DOM fragments (preserve data found in file).
1224 static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
1225 AddressDataSource *ds;
1227 ds = addrindex_create_datasource( ADDR_IF_JPILOT );
1228 ds->rawDataSource = addrindex_read_fragment( file );
1232 static void addrindex_write_jpilot( FILE *fp, AddressDataSource *ds, gint lvl ) {
1233 AddressIfFragment *fragment = ds->rawDataSource;
1235 addrindex_write_fragment( fp, fragment, lvl );
1242 * Parse LDAP criteria attribute data from XML file.
1243 * \param file Index file.
1244 * \param ctl LDAP control object to populate.
1246 static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
1255 if( file == NULL ) {
1260 prevLevel = file->level;
1261 xtagPrev = xml_get_current_tag( file );
1263 rc = xml_parse_next_tag( file );
1265 /* Terminate prematurely */
1266 mgu_free_dlist( list );
1270 if( file->level < prevLevel ) {
1271 /* We must be above level we start at */
1275 /* Get a tag (element) */
1276 xtag = xml_get_current_tag( file );
1277 if( strcmp( xtag->tag, ELTAG_LDAP_ATTR_SRCH ) == 0 ) {
1278 /* LDAP criteria attribute */
1279 attr = xml_get_current_tag_attr( file );
1281 gchar *name = ((XMLAttr *)attr->data)->name;
1282 gchar *value = ((XMLAttr *)attr->data)->value;
1283 if( strcmp( name, ATTAG_LDAP_ATTR_NAME ) == 0 ) {
1284 if( value && strlen( value ) > 0 ) {
1285 list = g_list_append(
1286 list, g_strdup( value ) );
1289 attr = g_list_next( attr );
1293 if( xtag != xtagPrev ) {
1294 /* Found a new tag */
1301 /* Build list of search attributes */
1302 ldapctl_criteria_list_clear( ctl );
1305 ldapctl_criteria_list_add( ctl, node->data );
1306 g_free( node->data );
1308 node = g_list_next( node );
1310 g_list_free( list );
1315 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1316 AddressDataSource *ds;
1320 gchar *serverName = NULL;
1321 gchar *criteria = NULL;
1322 gboolean bSearch = FALSE;
1323 gboolean cvtFlag = TRUE;
1325 /* printf( "addrindex_parse_ldap\n" ); */
1327 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1328 ctl = ldapctl_create();
1329 attr = xml_get_current_tag_attr( file );
1331 gchar *name = ((XMLAttr *)attr->data)->name;
1332 gchar *value = ((XMLAttr *)attr->data)->value;
1333 gint ivalue = atoi( value );
1335 if( strcmp( name, ATTAG_LDAP_NAME ) == 0 ) {
1336 if( serverName ) g_free( serverName );
1337 serverName = g_strdup( value );
1339 else if( strcmp( name, ATTAG_LDAP_HOST ) == 0 ) {
1340 ldapctl_set_host( ctl, value );
1342 else if( strcmp( name, ATTAG_LDAP_PORT ) == 0 ) {
1343 ldapctl_set_port( ctl, ivalue );
1345 else if( strcmp( name, ATTAG_LDAP_BASE_DN ) == 0 ) {
1346 ldapctl_set_base_dn( ctl, value );
1348 else if( strcmp( name, ATTAG_LDAP_BIND_DN ) == 0 ) {
1349 ldapctl_set_bind_dn( ctl, value );
1351 else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
1352 ldapctl_set_bind_password( ctl, value );
1354 else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
1355 if( criteria ) g_free( criteria );
1356 criteria = g_strdup( value );
1358 else if( strcmp( name, ATTAG_LDAP_MAX_ENTRY ) == 0 ) {
1359 ldapctl_set_max_entries( ctl, ivalue );
1361 else if( strcmp( name, ATTAG_LDAP_TIMEOUT ) == 0 ) {
1362 ldapctl_set_timeout( ctl, ivalue );
1364 else if( strcmp( name, ATTAG_LDAP_MAX_AGE ) == 0 ) {
1365 ldapctl_set_max_query_age( ctl, ivalue );
1367 else if( strcmp( name, ATTAG_LDAP_DYN_SEARCH ) == 0 ) {
1370 if( strcmp( value, "yes" ) == 0 ) {
1374 attr = g_list_next( attr );
1377 server = ldapsvr_create_noctl();
1378 ldapsvr_set_name( server, serverName );
1379 ldapsvr_set_search_flag( server, bSearch );
1380 g_free( serverName );
1381 ldapsvr_set_control( server, ctl );
1382 ds->rawDataSource = server;
1384 addrindex_parse_ldap_attrlist( file, ctl );
1386 * If criteria have been specified and no attributes were listed, then
1387 * convert old style criteria into an attribute list. Any criteria will
1388 * be dropped when saving data.
1391 if( ! ldapctl_get_criteria_list( ctl ) ) {
1392 ldapctl_parse_ldap_search( ctl, criteria );
1397 * If no search flag was found, then we are converting from old format
1398 * server data to new format.
1401 ldapsvr_set_search_flag( server, TRUE );
1403 /* ldapsvr_print_data( server, stdout ); */
1408 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1409 LdapServer *server = ds->rawDataSource;
1410 LdapControl *ctl = NULL;
1415 ctl = server->control;
1417 if( ctl == NULL ) return;
1419 /* Output start element with attributes */
1420 addrindex_write_elem_s( fp, lvl, TAG_DS_LDAP );
1421 addrindex_write_attr( fp, ATTAG_LDAP_NAME, ldapsvr_get_name( server ) );
1422 addrindex_write_attr( fp, ATTAG_LDAP_HOST, ctl->hostName );
1424 sprintf( value, "%d", ctl->port );
1425 addrindex_write_attr( fp, ATTAG_LDAP_PORT, value );
1427 addrindex_write_attr( fp, ATTAG_LDAP_BASE_DN, ctl->baseDN );
1428 addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN );
1429 addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass );
1431 sprintf( value, "%d", ctl->maxEntries );
1432 addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value );
1433 sprintf( value, "%d", ctl->timeOut );
1434 addrindex_write_attr( fp, ATTAG_LDAP_TIMEOUT, value );
1435 sprintf( value, "%d", ctl->maxQueryAge );
1436 addrindex_write_attr( fp, ATTAG_LDAP_MAX_AGE, value );
1438 addrindex_write_attr( fp, ATTAG_LDAP_DYN_SEARCH,
1439 server->searchFlag ? "yes" : "no" );
1443 /* Output attributes */
1444 node = ldapctl_get_criteria_list( ctl );
1446 addrindex_write_elem_s( fp, 1+lvl, ELTAG_LDAP_ATTR_SRCH );
1447 addrindex_write_attr( fp, ATTAG_LDAP_ATTR_NAME, node->data );
1449 node = g_list_next( node );
1452 /* End of element */
1453 addrindex_write_elem_e( fp, lvl, TAG_DS_LDAP );
1459 * Just read/write DOM fragments (preserve data found in file).
1461 static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
1462 AddressDataSource *ds;
1464 ds = addrindex_create_datasource( ADDR_IF_LDAP );
1465 ds->rawDataSource = addrindex_read_fragment( file );
1469 static void addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
1470 AddressIfFragment *fragment = ds->rawDataSource;
1472 addrindex_write_fragment( fp, fragment, lvl );
1477 /* **********************************************************************
1478 * Address index I/O functions.
1479 * ***********************************************************************
1482 * Read address index file, creating appropriate data sources for each address
1485 * \param addrIndex Address index.
1486 * \param file Address index file.
1488 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
1491 AddressInterface *iface = NULL, *dsIFace = NULL;
1492 AddressDataSource *ds;
1495 addrIndex->loadedFlag = FALSE;
1497 prev_level = file->level;
1498 rc = xml_parse_next_tag( file );
1499 if( file->level == 0 ) return;
1501 xtag = xml_get_current_tag( file );
1503 iface = addrindex_tag_get_interface( addrIndex, xtag->tag, ADDR_IF_NONE );
1505 addrIndex->lastType = iface->type;
1506 if( iface->legacyFlag ) addrIndex->needsConversion = TRUE;
1509 dsIFace = addrindex_tag_get_datasource(
1510 addrIndex, addrIndex->lastType, xtag->tag );
1512 /* Add data source to list */
1514 if( addrIndex->lastType == ADDR_IF_BOOK ) {
1515 ds = addrindex_parse_book( file );
1516 if( ds->rawDataSource ) {
1517 addrbook_set_path( ds->rawDataSource,
1518 addrIndex->filePath );
1521 else if( addrIndex->lastType == ADDR_IF_VCARD ) {
1522 ds = addrindex_parse_vcard( file );
1524 else if( addrIndex->lastType == ADDR_IF_JPILOT ) {
1525 ds = addrindex_parse_jpilot( file );
1527 else if( addrIndex->lastType == ADDR_IF_LDAP ) {
1528 ds = addrindex_parse_ldap( file );
1531 ds->interface = dsIFace;
1532 addrindex_hash_add_cache( addrIndex, ds );
1533 dsIFace->listSource =
1534 g_list_append( dsIFace->listSource, ds );
1542 * Search order sorting comparison function for building search order list.
1544 static gint addrindex_search_order_compare( gconstpointer ptrA, gconstpointer ptrB ) {
1545 AddressInterface *ifaceA = ( AddressInterface * ) ptrA;
1546 AddressInterface *ifaceB = ( AddressInterface * ) ptrB;
1548 return ifaceA->searchOrder - ifaceB->searchOrder;
1552 * Build list of data sources to process.
1553 * \param addrIndex Address index object.
1555 static void addrindex_build_search_order( AddressIndex *addrIndex ) {
1558 /* Clear existing list */
1559 g_list_free( addrIndex->searchOrder );
1560 addrIndex->searchOrder = NULL;
1562 /* Build new list */
1563 nodeIf = addrIndex->interfaceList;
1565 AddressInterface *iface = nodeIf->data;
1566 if( iface->useInterface ) {
1567 if( iface->searchOrder > 0 ) {
1568 /* Add to search order list */
1569 addrIndex->searchOrder = g_list_insert_sorted(
1570 addrIndex->searchOrder, iface,
1571 addrindex_search_order_compare );
1574 nodeIf = g_list_next( nodeIf );
1578 static gint addrindex_read_file( AddressIndex *addrIndex ) {
1579 XMLFile *file = NULL;
1580 gchar *fileSpec = NULL;
1582 g_return_val_if_fail( addrIndex != NULL, -1 );
1584 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
1585 addrIndex->retVal = MGU_NO_FILE;
1586 file = xml_open_file( fileSpec );
1589 if( file == NULL ) {
1591 fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName );
1593 return addrIndex->retVal;
1596 addrIndex->retVal = MGU_BAD_FORMAT;
1597 if( xml_get_dtd( file ) == 0 ) {
1598 if( xml_parse_next_tag( file ) == 0 ) {
1599 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
1600 addrindex_read_index( addrIndex, file );
1601 addrIndex->retVal = MGU_SUCCESS;
1605 xml_close_file( file );
1607 addrindex_build_search_order( addrIndex );
1609 return addrIndex->retVal;
1612 static void addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
1613 GList *nodeIF, *nodeDS;
1615 gint lvlItem = 1 + lvlList;
1617 nodeIF = addrIndex->interfaceList;
1619 AddressInterface *iface = nodeIF->data;
1620 if( ! iface->legacyFlag ) {
1621 nodeDS = iface->listSource;
1622 addrindex_write_elem_s( fp, lvlList, iface->listTag );
1625 AddressDataSource *ds = nodeDS->data;
1627 if( iface->type == ADDR_IF_BOOK ) {
1628 addrindex_write_book( fp, ds, lvlItem );
1630 if( iface->type == ADDR_IF_VCARD ) {
1631 addrindex_write_vcard( fp, ds, lvlItem );
1633 if( iface->type == ADDR_IF_JPILOT ) {
1634 addrindex_write_jpilot( fp, ds, lvlItem );
1636 if( iface->type == ADDR_IF_LDAP ) {
1637 addrindex_write_ldap( fp, ds, lvlItem );
1640 nodeDS = g_list_next( nodeDS );
1642 addrindex_write_elem_e( fp, lvlList, iface->listTag );
1644 nodeIF = g_list_next( nodeIF );
1649 * Write data to specified file.
1650 * Enter: addrIndex Address index object.
1651 * newFile New file name.
1652 * return: Status code, from addrIndex->retVal.
1653 * Note: File will be created in directory specified by addrIndex.
1655 gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile ) {
1658 #ifndef DEV_STANDALONE
1662 g_return_val_if_fail( addrIndex != NULL, -1 );
1664 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
1665 addrIndex->retVal = MGU_OPEN_FILE;
1666 #ifdef DEV_STANDALONE
1667 fp = fopen( fileSpec, "wb" );
1670 fputs( "<?xml version=\"1.0\" ?>\n", fp );
1672 pfile = prefs_write_open( fileSpec );
1676 fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
1677 conv_get_current_charset_str() );
1679 addrindex_write_elem_s( fp, 0, TAG_ADDRESS_INDEX );
1682 addrindex_write_index( addrIndex, fp );
1683 addrindex_write_elem_e( fp, 0, TAG_ADDRESS_INDEX );
1685 addrIndex->retVal = MGU_SUCCESS;
1686 #ifdef DEV_STANDALONE
1689 if( prefs_file_close( pfile ) < 0 ) {
1690 addrIndex->retVal = MGU_ERROR_WRITE;
1696 return addrIndex->retVal;
1700 * Save address index data to original file.
1701 * return: Status code, from addrIndex->retVal.
1703 gint addrindex_save_data( AddressIndex *addrIndex ) {
1704 g_return_val_if_fail( addrIndex != NULL, -1 );
1706 addrIndex->retVal = MGU_NO_FILE;
1707 if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
1708 if( addrIndex->filePath == NULL || *addrIndex->filePath == '\0' ) return addrIndex->retVal;
1710 addrindex_write_to( addrIndex, addrIndex->fileName );
1711 if( addrIndex->retVal == MGU_SUCCESS ) {
1712 addrIndex->dirtyFlag = FALSE;
1714 return addrIndex->retVal;
1718 * Save all address book files which may have changed.
1719 * Return: Status code, set if there was a problem saving data.
1721 gint addrindex_save_all_books( AddressIndex *addrIndex ) {
1722 gint retVal = MGU_SUCCESS;
1723 GList *nodeIf, *nodeDS;
1725 nodeIf = addrIndex->interfaceList;
1727 AddressInterface *iface = nodeIf->data;
1728 if( iface->type == ADDR_IF_BOOK ) {
1729 nodeDS = iface->listSource;
1731 AddressDataSource *ds = nodeDS->data;
1732 AddressBookFile *abf = ds->rawDataSource;
1733 if( addrbook_get_dirty( abf ) ) {
1734 if( addrbook_get_read_flag( abf ) ) {
1735 addrbook_save_data( abf );
1736 if( abf->retVal != MGU_SUCCESS ) {
1737 retVal = abf->retVal;
1741 nodeDS = g_list_next( nodeDS );
1745 nodeIf = g_list_next( nodeIf );
1751 /* **********************************************************************
1752 * Address book conversion to new format.
1753 * ***********************************************************************
1756 #define ELTAG_IF_OLD_FOLDER "folder"
1757 #define ELTAG_IF_OLD_GROUP "group"
1758 #define ELTAG_IF_OLD_ITEM "item"
1759 #define ELTAG_IF_OLD_NAME "name"
1760 #define ELTAG_IF_OLD_ADDRESS "address"
1761 #define ELTAG_IF_OLD_REMARKS "remarks"
1762 #define ATTAG_IF_OLD_NAME "name"
1764 #define TEMPNODE_ROOT 0
1765 #define TEMPNODE_FOLDER 1
1766 #define TEMPNODE_GROUP 2
1767 #define TEMPNODE_ADDRESS 3
1769 typedef struct _AddressCvt_Node AddressCvtNode;
1770 struct _AddressCvt_Node {
1779 * Parse current address item.
1781 static AddressCvtNode *addrindex_parse_item( XMLFile *file ) {
1786 nn = g_new0( AddressCvtNode, 1 );
1787 nn->type = TEMPNODE_ADDRESS;
1790 level = file->level;
1793 xml_parse_next_tag(file);
1794 if (file->level < level) return nn;
1796 element = xml_get_element( file );
1797 if( xml_compare_tag( file, ELTAG_IF_OLD_NAME ) ) {
1798 nn->name = g_strdup( element );
1800 if( xml_compare_tag( file, ELTAG_IF_OLD_ADDRESS ) ) {
1801 nn->address = g_strdup( element );
1803 if( xml_compare_tag( file, ELTAG_IF_OLD_REMARKS ) ) {
1804 nn->remarks = g_strdup( element );
1806 xml_parse_next_tag(file);
1811 * Create a temporary node below specified node.
1813 static AddressCvtNode *addrindex_add_object( AddressCvtNode *node, gint type, gchar *name, gchar *addr, char *rem ) {
1815 nn = g_new0( AddressCvtNode, 1 );
1817 nn->name = g_strdup( name );
1818 nn->remarks = g_strdup( rem );
1819 node->list = g_list_append( node->list, nn );
1824 * Process current temporary node.
1826 static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
1829 AddressCvtNode *newNode = NULL;
1834 prev_level = file->level;
1835 xml_parse_next_tag( file );
1836 if (file->level < prev_level) return;
1840 if( xml_compare_tag( file, ELTAG_IF_OLD_GROUP ) ) {
1841 attr = xml_get_current_tag_attr(file);
1843 name = ((XMLAttr *)attr->data)->name;
1844 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1845 value = ((XMLAttr *)attr->data)->value;
1848 newNode = addrindex_add_object( node, TEMPNODE_GROUP, value, "", "" );
1849 addrindex_add_obj( file, newNode );
1852 else if( xml_compare_tag( file, ELTAG_IF_OLD_FOLDER ) ) {
1853 attr = xml_get_current_tag_attr(file);
1855 name = ((XMLAttr *)attr->data)->name;
1856 if( strcmp( name, ATTAG_IF_OLD_NAME ) == 0 ) {
1857 value = ((XMLAttr *)attr->data)->value;
1860 newNode = addrindex_add_object( node, TEMPNODE_FOLDER, value, "", "" );
1861 addrindex_add_obj( file, newNode );
1863 else if( xml_compare_tag( file, ELTAG_IF_OLD_ITEM ) ) {
1864 newNode = addrindex_parse_item( file );
1865 node->list = g_list_append( node->list, newNode );
1868 /* printf( "invalid: !!! \n" ); */
1869 attr = xml_get_current_tag_attr( file );
1875 * Consume all nodes below current tag.
1877 static void addrindex_consume_tree( XMLFile *file ) {
1884 prev_level = file->level;
1885 xml_parse_next_tag( file );
1886 if (file->level < prev_level) return;
1888 xtag = xml_get_current_tag( file );
1889 /* printf( "tag : %s\n", xtag->tag ); */
1890 element = xml_get_element( file );
1891 attr = xml_get_current_tag_attr( file );
1892 /* show_attribs( attr ); */
1893 /* printf( "\ttag value : %s :\n", element ); */
1894 addrindex_consume_tree( file );
1899 * Print temporary tree.
1901 static void addrindex_print_node( AddressCvtNode *node, FILE *stream ) {
1904 fprintf( stream, "Node:\ttype :%d:\n", node->type );
1905 fprintf( stream, "\tname :%s:\n", node->name );
1906 fprintf( stream, "\taddr :%s:\n", node->address );
1907 fprintf( stream, "\trems :%s:\n", node->remarks );
1909 fprintf( stream, "\t--list----\n" );
1913 AddressCvtNode *lNode = list->data;
1914 list = g_list_next( list );
1915 addrindex_print_node( lNode, stream );
1917 fprintf( stream, "\t==list-%d==\n", node->type );
1921 * Free up temporary tree.
1923 static void addrindex_free_node( AddressCvtNode *node ) {
1924 GList *list = node->list;
1927 AddressCvtNode *lNode = list->data;
1928 list = g_list_next( list );
1929 addrindex_free_node( lNode );
1931 node->type = TEMPNODE_ROOT;
1932 g_free( node->name );
1933 g_free( node->address );
1934 g_free( node->remarks );
1935 g_list_free( node->list );
1940 * Process address book for specified node.
1942 static void addrindex_process_node(
1943 AddressBookFile *abf, AddressCvtNode *node, ItemFolder *parent,
1944 ItemGroup *parentGrp, ItemFolder *folderGrp )
1947 ItemFolder *itemFolder = NULL;
1948 ItemGroup *itemGParent = parentGrp;
1949 ItemFolder *itemGFolder = folderGrp;
1950 AddressCache *cache = abf->addressCache;
1952 if( node->type == TEMPNODE_ROOT ) {
1953 itemFolder = parent;
1955 else if( node->type == TEMPNODE_FOLDER ) {
1956 itemFolder = addritem_create_item_folder();
1957 addritem_folder_set_name( itemFolder, node->name );
1958 addrcache_id_folder( cache, itemFolder );
1959 addrcache_folder_add_folder( cache, parent, itemFolder );
1962 else if( node->type == TEMPNODE_GROUP ) {
1963 ItemGroup *itemGroup;
1966 /* Create a folder for group */
1967 fName = g_strdup_printf( "Cvt - %s", node->name );
1968 itemGFolder = addritem_create_item_folder();
1969 addritem_folder_set_name( itemGFolder, fName );
1970 addrcache_id_folder( cache, itemGFolder );
1971 addrcache_folder_add_folder( cache, parent, itemGFolder );
1974 /* Add group into folder */
1975 itemGroup = addritem_create_item_group();
1976 addritem_group_set_name( itemGroup, node->name );
1977 addrcache_id_group( cache, itemGroup );
1978 addrcache_folder_add_group( cache, itemGFolder, itemGroup );
1979 itemGParent = itemGroup;
1981 else if( node->type == TEMPNODE_ADDRESS ) {
1982 ItemPerson *itemPerson;
1983 ItemEMail *itemEMail;
1985 /* Create person and email objects */
1986 itemPerson = addritem_create_item_person();
1987 addritem_person_set_common_name( itemPerson, node->name );
1988 addrcache_id_person( cache, itemPerson );
1989 itemEMail = addritem_create_item_email();
1990 addritem_email_set_address( itemEMail, node->address );
1991 addritem_email_set_remarks( itemEMail, node->remarks );
1992 addrcache_id_email( cache, itemEMail );
1993 addrcache_person_add_email( cache, itemPerson, itemEMail );
1995 /* Add person into appropriate folder */
1997 addrcache_folder_add_person( cache, itemGFolder, itemPerson );
2000 addrcache_folder_add_person( cache, parent, itemPerson );
2003 /* Add email address only into group */
2005 addrcache_group_add_email( cache, parentGrp, itemEMail );
2011 AddressCvtNode *lNode = list->data;
2012 list = g_list_next( list );
2013 addrindex_process_node( abf, lNode, itemFolder, itemGParent, itemGFolder );
2018 * Process address book to specified file number.
2020 static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file, gchar *displayName ) {
2021 gboolean retVal = FALSE;
2022 AddressBookFile *abf = NULL;
2023 AddressCvtNode *rootNode = NULL;
2024 gchar *newFile = NULL;
2025 GList *fileList = NULL;
2028 /* Setup root node */
2029 rootNode = g_new0( AddressCvtNode, 1 );
2030 rootNode->type = TEMPNODE_ROOT;
2031 rootNode->name = g_strdup( "root" );
2032 rootNode->list = NULL;
2033 addrindex_add_obj( file, rootNode );
2034 /* addrindex_print_node( rootNode, stdout ); */
2036 /* Create new address book */
2037 abf = addrbook_create_book();
2038 addrbook_set_name( abf, displayName );
2039 addrbook_set_path( abf, addrIndex->filePath );
2041 /* Determine next available file number */
2042 fileList = addrbook_get_bookfile_list( abf );
2044 fileNum = 1 + abf->maxValue;
2046 g_list_free( fileList );
2049 newFile = addrbook_gen_new_file_name( fileNum );
2051 addrbook_set_file( abf, newFile );
2054 addrindex_process_node( abf, rootNode, abf->addressCache->rootFolder, NULL, NULL );
2056 /* addrbook_dump_book( abf, stdout ); */
2057 addrbook_save_data( abf );
2058 addrIndex->retVal = abf->retVal;
2059 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2061 addrbook_free_book( abf );
2063 addrindex_free_node( rootNode );
2066 /* Create entries in address index */
2068 abf = addrbook_create_book();
2069 addrbook_set_name( abf, displayName );
2070 addrbook_set_path( abf, addrIndex->filePath );
2071 addrbook_set_file( abf, newFile );
2072 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2079 * Process tree converting data.
2081 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
2089 prev_level = file->level;
2090 xml_parse_next_tag( file );
2091 if (file->level < prev_level) return;
2093 xtag = xml_get_current_tag( file );
2094 /* printf( "tag : %d : %s\n", prev_level, xtag->tag ); */
2095 if( strcmp( xtag->tag, TAG_IF_OLD_COMMON ) == 0 ) {
2096 if( addrindex_process_book( addrIndex, file, DISP_OLD_COMMON ) ) {
2097 addrIndex->needsConversion = FALSE;
2098 addrIndex->wasConverted = TRUE;
2103 if( strcmp( xtag->tag, TAG_IF_OLD_PERSONAL ) == 0 ) {
2104 if( addrindex_process_book( addrIndex, file, DISP_OLD_PERSONAL ) ) {
2105 addrIndex->needsConversion = FALSE;
2106 addrIndex->wasConverted = TRUE;
2111 element = xml_get_element( file );
2112 attr = xml_get_current_tag_attr( file );
2113 /* show_attribs( attr ); */
2114 /* printf( "\ttag value : %s :\n", element ); */
2115 addrindex_consume_tree( file );
2119 static gint addrindex_convert_data( AddressIndex *addrIndex ) {
2120 XMLFile *file = NULL;
2123 fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
2124 addrIndex->retVal = MGU_NO_FILE;
2125 file = xml_open_file( fileSpec );
2128 if( file == NULL ) {
2129 /* fprintf( stdout, " file '%s' does not exist.\n", addrIndex->fileName ); */
2130 return addrIndex->retVal;
2133 addrIndex->retVal = MGU_BAD_FORMAT;
2134 if( xml_get_dtd( file ) == 0 ) {
2135 if( xml_parse_next_tag( file ) == 0 ) {
2136 if( xml_compare_tag( file, TAG_ADDRESS_INDEX ) ) {
2137 addrindex_convert_tree( addrIndex, file );
2141 xml_close_file( file );
2142 return addrIndex->retVal;
2146 * Create a new address book file.
2148 static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displayName ) {
2149 gboolean retVal = FALSE;
2150 AddressBookFile *abf = NULL;
2151 gchar *newFile = NULL;
2152 GList *fileList = NULL;
2155 /* Create new address book */
2156 abf = addrbook_create_book();
2157 addrbook_set_name( abf, displayName );
2158 addrbook_set_path( abf, addrIndex->filePath );
2160 /* Determine next available file number */
2161 fileList = addrbook_get_bookfile_list( abf );
2163 fileNum = 1 + abf->maxValue;
2165 g_list_free( fileList );
2168 newFile = addrbook_gen_new_file_name( fileNum );
2170 addrbook_set_file( abf, newFile );
2173 addrbook_save_data( abf );
2174 addrIndex->retVal = abf->retVal;
2175 if( abf->retVal == MGU_SUCCESS ) retVal = TRUE;
2176 addrbook_free_book( abf );
2179 /* Create entries in address index */
2181 abf = addrbook_create_book();
2182 addrbook_set_name( abf, displayName );
2183 addrbook_set_path( abf, addrIndex->filePath );
2184 addrbook_set_file( abf, newFile );
2185 addrindex_index_add_datasource( addrIndex, ADDR_IF_BOOK, abf );
2192 * Read data for address index performing a conversion if necesary.
2193 * Enter: addrIndex Address index object.
2194 * return: Status code, from addrIndex->retVal.
2195 * Note: New address book files will be created in directory specified by
2196 * addrIndex. Three files will be created, for the following:
2197 * "Common addresses"
2198 * "Personal addresses"
2199 * "Gathered addresses" - a new address book.
2201 gint addrindex_read_data( AddressIndex *addrIndex ) {
2202 g_return_val_if_fail( addrIndex != NULL, -1 );
2204 addrIndex->conversionError = FALSE;
2205 addrindex_read_file( addrIndex );
2206 if( addrIndex->retVal == MGU_SUCCESS ) {
2207 if( addrIndex->needsConversion ) {
2208 if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
2209 addrIndex->conversionError = TRUE;
2212 addrIndex->conversionError = TRUE;
2215 addrIndex->dirtyFlag = TRUE;
2217 return addrIndex->retVal;
2221 * Create new address books for a new address index.
2222 * Enter: addrIndex Address index object.
2223 * return: Status code, from addrIndex->retVal.
2224 * Note: New address book files will be created in directory specified by
2225 * addrIndex. Three files will be created, for the following:
2226 * "Common addresses"
2227 * "Personal addresses"
2228 * "Gathered addresses" - a new address book.
2230 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
2233 g_return_val_if_fail( addrIndex != NULL, -1 );
2235 flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
2237 flg = addrindex_create_new_book( addrIndex, DISP_NEW_PERSONAL );
2238 addrIndex->dirtyFlag = TRUE;
2240 return addrIndex->retVal;
2243 /* **********************************************************************
2244 * New interface stuff.
2245 * ***********************************************************************
2249 * Return modified flag for specified data source.
2251 gboolean addrindex_ds_get_modify_flag( AddressDataSource *ds ) {
2252 gboolean retVal = FALSE;
2253 AddressInterface *iface;
2255 if( ds == NULL ) return retVal;
2256 iface = ds->interface;
2257 if( iface == NULL ) return retVal;
2258 if( iface->getModifyFlag ) {
2259 retVal = ( iface->getModifyFlag ) ( ds->rawDataSource );
2265 * Return accessed flag for specified data source.
2267 gboolean addrindex_ds_get_access_flag( AddressDataSource *ds ) {
2268 gboolean retVal = FALSE;
2269 AddressInterface *iface;
2271 if( ds == NULL ) return retVal;
2272 iface = ds->interface;
2273 if( iface == NULL ) return retVal;
2274 if( iface->getAccessFlag ) {
2275 retVal = ( iface->getAccessFlag ) ( ds->rawDataSource );
2281 * Return data read flag for specified data source.
2283 gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
2284 gboolean retVal = TRUE;
2285 AddressInterface *iface;
2287 if( ds == NULL ) return retVal;
2288 iface = ds->interface;
2289 if( iface == NULL ) return retVal;
2290 if( iface->getReadFlag ) {
2291 retVal = ( iface->getReadFlag ) ( ds->rawDataSource );
2297 * Return status code for specified data source.
2299 gint addrindex_ds_get_status_code( AddressDataSource *ds ) {
2300 gint retVal = MGU_SUCCESS;
2301 AddressInterface *iface;
2303 if( ds == NULL ) return retVal;
2304 iface = ds->interface;
2305 if( iface == NULL ) return retVal;
2306 if( iface->getStatusCode ) {
2307 retVal = ( iface->getStatusCode ) ( ds->rawDataSource );
2313 * Return data read flag for specified data source.
2315 gint addrindex_ds_read_data( AddressDataSource *ds ) {
2316 gint retVal = MGU_SUCCESS;
2317 AddressInterface *iface;
2319 if( ds == NULL ) return retVal;
2320 iface = ds->interface;
2321 if( iface == NULL ) return retVal;
2322 if( iface->getReadData ) {
2324 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2325 printf( "addrindex_ds_read_data...reading:::%s:::\n", name );
2327 retVal = ( iface->getReadData ) ( ds->rawDataSource );
2333 * Return data read flag for specified data source.
2335 ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds ) {
2336 ItemFolder *retVal = NULL;
2337 AddressInterface *iface;
2339 if( ds == NULL ) return retVal;
2340 iface = ds->interface;
2341 if( iface == NULL ) return retVal;
2342 if( iface->getRootFolder ) {
2343 retVal = ( iface->getRootFolder ) ( ds->rawDataSource );
2349 * Return list of folders for specified data source.
2351 GList *addrindex_ds_get_list_folder( AddressDataSource *ds ) {
2352 GList *retVal = FALSE;
2353 AddressInterface *iface;
2355 if( ds == NULL ) return retVal;
2356 iface = ds->interface;
2357 if( iface == NULL ) return retVal;
2358 if( iface->getListFolder ) {
2359 retVal = ( iface->getListFolder ) ( ds->rawDataSource );
2365 * Return list of persons in root folder for specified data source.
2367 GList *addrindex_ds_get_list_person( AddressDataSource *ds ) {
2368 GList *retVal = FALSE;
2369 AddressInterface *iface;
2371 if( ds == NULL ) return retVal;
2372 iface = ds->interface;
2373 if( iface == NULL ) return retVal;
2374 if( iface->getListPerson ) {
2375 retVal = ( iface->getListPerson ) ( ds->rawDataSource );
2381 * Return name for specified data source.
2383 gchar *addrindex_ds_get_name( AddressDataSource *ds ) {
2384 gchar *retVal = FALSE;
2385 AddressInterface *iface;
2387 if( ds == NULL ) return retVal;
2388 iface = ds->interface;
2389 if( iface == NULL ) return retVal;
2390 if( iface->getName ) {
2391 retVal = ( iface->getName ) ( ds->rawDataSource );
2397 * Set the access flag inside the data source.
2399 void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
2400 AddressInterface *iface;
2402 if( ds == NULL ) return;
2403 iface = ds->interface;
2404 if( iface == NULL ) return;
2405 if( iface->setAccessFlag ) {
2406 ( iface->setAccessFlag ) ( ds->rawDataSource, value );
2411 * Return read only flag for specified data source.
2413 gboolean addrindex_ds_get_readonly( AddressDataSource *ds ) {
2414 AddressInterface *iface;
2415 if( ds == NULL ) return TRUE;
2416 iface = ds->interface;
2417 if( iface == NULL ) return TRUE;
2418 return iface->readOnly;
2422 * Return list of all persons for specified data source.
2424 GList *addrindex_ds_get_all_persons( AddressDataSource *ds ) {
2425 GList *retVal = NULL;
2426 AddressInterface *iface;
2428 if( ds == NULL ) return retVal;
2429 iface = ds->interface;
2430 if( iface == NULL ) return retVal;
2431 if( iface->getAllPersons ) {
2432 retVal = ( iface->getAllPersons ) ( ds->rawDataSource );
2438 * Return list of all groups for specified data source.
2440 GList *addrindex_ds_get_all_groups( AddressDataSource *ds ) {
2441 GList *retVal = NULL;
2442 AddressInterface *iface;
2444 if( ds == NULL ) return retVal;
2445 iface = ds->interface;
2446 if( iface == NULL ) return retVal;
2447 if( iface->getAllGroups ) {
2448 retVal = ( iface->getAllGroups ) ( ds->rawDataSource );
2453 /* **********************************************************************
2454 * Address search stuff.
2455 * ***********************************************************************
2459 * Current query ID. This is incremented for each query created.
2461 static gint _currentQueryID_ = 0;
2464 * Variables for the search that is being performed.
2466 static gchar *_searchTerm_ = NULL;
2467 static gpointer _searchTarget_ = NULL;
2468 static AddrSearchCallbackFunc *_searchCallback_ = NULL;
2471 * Setup or register the search that will be performed.
2472 * \param addrIndex Address index object.
2473 * \param searchTerm Search term. A private copy will be made.
2474 * \param target Target object that will receive data.
2475 * \param callBack Callback function.
2476 * \return ID allocated to query that will be executed.
2478 gint addrindex_setup_search(
2479 AddressIndex *addrIndex, const gchar *searchTerm,
2480 const gpointer target, AddrSearchCallbackFunc callBack )
2484 /* printf( "search term ::%s::\n", searchTerm ); */
2485 g_free( _searchTerm_ );
2486 _searchTerm_ = g_strdup( searchTerm );
2488 queryID = ++_currentQueryID_;
2489 _searchTarget_ = target;
2490 _searchCallback_ = callBack;
2491 /* printf( "query ID ::%d::\n", queryID ); */
2497 * LDAP callback entry point for each address entry found.
2498 * \param qry LDAP query.
2499 * \param listEMail List of Item EMail objects found.
2501 static void addrindex_ldap_entry_cb( LdapQuery *qry, GList *listEMail ) {
2505 printf( "\naddrindex::addrindex_ldap_entry_cb ::%s::\n", qry->queryName );
2508 ItemEMail *email = node->data;
2509 printf( "\temail ::%s::\n", email->address );
2510 node = g_list_next( node );
2513 if( _searchCallback_ ) {
2514 ( _searchCallback_ ) ( qry->queryID, listEMail, _searchTarget_ );
2516 g_list_free( listEMail );
2520 * LDAP callback entry point for completion of search.
2521 * \param qry LDAP query.
2523 static void addrindex_ldap_end_cb( LdapQuery *qry ) {
2524 /* printf( "\naddrindex::addrindex_ldap_end_cb ::%s::\n", qry->queryName ); */
2528 * Return results of previous query.
2530 * \return List of ItemEMail objects.
2532 static void addrindex_ldap_use_previous(
2533 const ItemFolder *folder, const gint queryID )
2540 if( _searchCallback_ ) {
2541 node = folder->listPerson;
2543 AddrItemObject *aio = node->data;
2544 if( aio && aio->type == ITEMTYPE_PERSON ) {
2545 ItemPerson *person = node->data;
2546 nodeEM = person->listEMail;
2548 ItemEMail *email = nodeEM->data;
2549 nodeEM = g_list_next( nodeEM );
2550 listEMail = g_list_append( listEMail, email );
2553 node = g_list_next( node );
2555 ( _searchCallback_ ) ( queryID, listEMail, _searchTarget_ );
2556 g_list_free( listEMail );
2561 * Function prototype (not in header file or circular reference encountered!)
2563 LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm );
2566 * Construct an LDAP query and initiate an LDAP dynamic search.
2567 * \param server LDAP server object.
2568 * \param queryID ID of search query to be executed.
2570 static void addrindex_search_ldap( LdapServer *server, const gint queryID ) {
2574 if( ! server->searchFlag ) return;
2576 /* Retire any aged queries */
2577 ldapsvr_retire_query( server );
2579 /* Test whether any queries for the same term exist */
2580 qry = ldapsvr_locate_query( server, _searchTerm_ );
2582 ItemFolder *folder = qry->folder;
2584 /* Touch query to ensure it hangs around for a bit longer */
2585 ldapqry_touch( qry );
2587 addrindex_ldap_use_previous( folder, queryID );
2592 /* Construct a query */
2593 qry = ldapqry_create();
2594 ldapqry_set_query_id( qry, queryID );
2595 ldapqry_set_search_value( qry, _searchTerm_ );
2596 ldapqry_set_query_type( qry, LDAPQUERY_DYNAMIC );
2597 ldapqry_set_callback_entry( qry, addrindex_ldap_entry_cb );
2598 ldapqry_set_callback_end( qry, addrindex_ldap_end_cb );
2600 /* Name the query */
2601 name = g_strdup_printf( "Search for '%s'", _searchTerm_ );
2602 ldapqry_set_name( qry, name );
2605 ldapsvr_add_query( server, qry );
2606 ldapsvr_execute_query( server, qry );
2612 * Perform the previously registered search.
2613 * \param addrIndex Address index object.
2614 * \param queryID ID of search query to be executed.
2615 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2618 gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
2619 AddressInterface *iface;
2620 AddressDataSource *ds;
2625 /* printf( "addrindex_start_search::%d::\n", queryID ); */
2626 nodeIf = addrIndex->searchOrder;
2628 iface = nodeIf->data;
2629 nodeIf = g_list_next( nodeIf );
2631 if( ! iface->useInterface ) {
2635 if( ! iface->externalQuery ) {
2640 nodeDS = iface->listSource;
2643 nodeDS = g_list_next( nodeDS );
2645 if( type == ADDR_IF_LDAP ) {
2646 LdapServer *server = ds->rawDataSource;
2647 addrindex_search_ldap( server, queryID );
2656 * Stop the previously registered search.
2657 * \param addrIndex Address index object.
2658 * \param queryID ID of search query to stop.
2660 void addrindex_stop_search( AddressIndex *addrIndex, const gint queryID ){
2662 AddressInterface *iface;
2663 AddressDataSource *ds;
2668 /* If query ID does not match, search has not been setup */
2669 /* if( queryID != _queryID_ ) return; */
2671 /* printf( "addrindex_stop_search::%d::\n", queryID ); */
2672 nodeIf = addrIndex->searchOrder;
2674 iface = nodeIf->data;
2675 nodeIf = g_list_next( nodeIf );
2677 if( ! iface->useInterface ) {
2682 nodeDS = iface->listSource;
2685 nodeDS = g_list_next( nodeDS );
2686 if( type == ADDR_IF_LDAP ) {
2687 LdapServer *server = ds->rawDataSource;
2688 ldapsvr_stop_all_query( server );
2697 * LDAP callback entry point for completion of search.
2698 * \param qry LDAP query.
2700 static void addrindex_ldap_end_static_cb( LdapQuery *qry ) {
2703 AddrQueryType queryType;
2704 AddrSearchStaticFunc *callBack;
2706 queryID = qry->queryID;
2707 queryType = qry->queryType;
2708 addrQry = qrymgr_find_query( queryID );
2709 if( addrQry == NULL ) {
2712 callBack = addrQry->callBack;
2715 qrymgr_delete_query( queryID );
2717 /* Execute callback function */
2718 callBack( queryID, queryType, qry->retVal );
2723 * Setup the explicit search that will be performed. The search is registered with
2724 * the query manager.
2726 * \param ds Data source to search.
2727 * \param searchTerm Search term to locate.
2728 * \param folder Folder to receive search results; may be NULL.
2729 * \param callbackEnd Function to call when search has terminated.
2730 * \return ID allocated to query that will be executed.
2732 gint addrindex_setup_static_search(
2733 AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
2740 queryID = ++_currentQueryID_;
2742 /* Name the query */
2743 name = g_strdup_printf( "Search '%s'", searchTerm );
2745 /* Set up a generic address query */
2746 addrQry = qrymgr_add_query( queryID, searchTerm, callbackEnd, NULL );
2748 if( ds->type == ADDR_IF_LDAP ) {
2753 server = ds->rawDataSource;
2755 /* Construct a query */
2756 qry = ldapqry_create();
2757 ldapqry_set_query_id( qry, queryID );
2758 ldapqry_set_name( qry, name );
2759 ldapqry_set_search_value( qry, searchTerm );
2760 ldapqry_set_query_type( qry, LDAPQUERY_STATIC );
2761 ldapqry_set_callback_end( qry, addrindex_ldap_end_static_cb );
2763 /* Specify folder type and back reference */
2764 qry->folder = folder;
2765 folder->folderType = ADDRFOLDER_LDAP_QUERY;
2766 folder->folderData = ( gpointer ) qry;
2769 ldapsvr_add_query( server, qry );
2771 /* Set up generic query */
2772 addrqry_set_query_type( addrQry, ADDRQUERY_LDAP );
2773 addrqry_set_server( addrQry, server );
2774 addrqry_set_query( addrQry, qry );
2778 qrymgr_delete_query( queryID );
2788 * Perform the previously registered explicit search.
2789 * \param queryID ID of search query to be executed.
2790 * \param idleID Idler ID.
2791 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2794 gboolean addrindex_start_static_search( const gint queryID, const guint idleID )
2800 addrQry = qrymgr_find_query( queryID );
2801 if( addrQry == NULL ) {
2805 if( addrQry->queryType == ADDRQUERY_LDAP ) {
2810 server = ( LdapServer * ) addrQry->serverObject;
2811 qry = ( LdapQuery * ) addrQry->queryObject;
2813 /* Retire any aged queries */
2814 ldapsvr_retire_query( server );
2816 /* Start the search */
2817 ldapsvr_execute_query( server, qry );
2823 addrqry_set_idle_id( addrQry, idleID );
2830 * Read all address books that do not support dynamic queries.
2831 * \param addrIndex Address index object.
2833 void addrindex_read_all( AddressIndex *addrIndex ) {
2834 AddressInterface *iface;
2835 AddressDataSource *ds;
2839 nodeIf = addrIndex->searchOrder;
2841 iface = nodeIf->data;
2842 nodeIf = g_list_next( nodeIf );
2844 if( ! iface->useInterface ) {
2847 if( iface->externalQuery ) {
2850 nodeDS = iface->listSource;
2853 nodeDS = g_list_next( nodeDS );
2855 /* Read address book */
2856 if( addrindex_ds_get_modify_flag( ds ) ) {
2857 addrindex_ds_read_data( ds );
2861 if( ! addrindex_ds_get_read_flag( ds ) ) {
2862 addrindex_ds_read_data( ds );
2867 addrIndex->loadedFlag = TRUE;
2871 * This function is used by the address completion function to load
2872 * addresses for all non-external address book interfaces.
2874 * \param addrIndex Address index object.
2875 * \param callBackFunc Function to be called when an address is
2877 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2879 gboolean addrindex_load_completion(
2880 AddressIndex *addrIndex,
2881 gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) )
2883 AddressDataSource *ds;
2884 GList *nodeIf, *nodeDS;
2885 GList *listP, *nodeP;
2887 gchar *sName, *sAddress, *sAlias, *sFriendly;
2889 if( addrIndex == NULL ) return FALSE;
2891 nodeIf = addrindex_get_interface_list( addrIndex );
2893 AddressInterface *iface = nodeIf->data;
2895 nodeIf = g_list_next( nodeIf );
2896 if( ! iface->useInterface ) {
2899 if( iface->externalQuery ) {
2902 nodeDS = iface->listSource;
2906 /* Read address book */
2907 if( addrindex_ds_get_modify_flag( ds ) ) {
2908 addrindex_ds_read_data( ds );
2911 if( ! addrindex_ds_get_read_flag( ds ) ) {
2912 addrindex_ds_read_data( ds );
2915 /* Get all persons */
2916 listP = addrindex_ds_get_all_persons( ds );
2919 ItemPerson *person = nodeP->data;
2920 nodeM = person->listEMail;
2922 /* Figure out name to use */
2923 sName = person->nickName;
2924 if( sName == NULL || *sName == '\0' ) {
2925 sName = ADDRITEM_NAME(person);
2928 /* Process each E-Mail address */
2930 ItemEMail *email = nodeM->data;
2933 sAddress = email->address;
2934 if( sAddress || *sAddress != '\0' ) {
2935 sAlias = ADDRITEM_NAME(email);
2936 if( sAlias && *sAlias != '\0' ) {
2939 ( callBackFunc ) ( sFriendly, sAddress, sName );
2942 nodeM = g_list_next( nodeM );
2944 nodeP = g_list_next( nodeP );
2946 /* Free up the list */
2947 g_list_free( listP );
2949 nodeDS = g_list_next( nodeDS );