2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2012 Match Grun and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * General functions for accessing address index file.
26 #include "claws-features.h"
32 #include <glib/gi18n.h>
36 #include "addrcache.h"
38 #include "addressbook.h"
39 #include "addrindex.h"
41 #include "addrquery.h"
42 #include "addr_compl.h"
44 #include "alertpanel.h"
46 #ifndef DEV_STANDALONE
47 #include "prefs_gtk.h"
58 #include "ldapserver.h"
60 #include "ldapquery.h"
61 #include "ldapupdate.h"
69 #define TAG_ADDRESS_INDEX "addressbook"
71 #define TAG_IF_ADDRESS_BOOK "book_list"
72 #define TAG_IF_VCARD "vcard_list"
73 #define TAG_IF_JPILOT "jpilot_list"
74 #define TAG_IF_LDAP "ldap_list"
76 #define TAG_DS_ADDRESS_BOOK "book"
77 #define TAG_DS_VCARD "vcard"
78 #define TAG_DS_JPILOT "jpilot"
79 #define TAG_DS_LDAP "server"
81 /* XML Attribute names */
82 #define ATTAG_BOOK_NAME "name"
83 #define ATTAG_BOOK_FILE "file"
85 #define ATTAG_VCARD_NAME "name"
86 #define ATTAG_VCARD_FILE "file"
88 #define ATTAG_JPILOT_NAME "name"
89 #define ATTAG_JPILOT_FILE "file"
90 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
91 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
92 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
93 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
94 #define ATTAG_JPILOT_CUSTOM "custom-"
96 #define ATTAG_LDAP_NAME "name"
97 #define ATTAG_LDAP_HOST "host"
98 #define ATTAG_LDAP_PORT "port"
99 #define ATTAG_LDAP_BASE_DN "base-dn"
100 #define ATTAG_LDAP_BIND_DN "bind-dn"
101 #define ATTAG_LDAP_BIND_PASS "bind-pass"
102 #define ATTAG_LDAP_CRITERIA "criteria"
103 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
104 #define ATTAG_LDAP_TIMEOUT "timeout"
105 #define ATTAG_LDAP_MAX_AGE "max-age"
106 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
107 #define ATTAG_LDAP_MATCH_OPT "match-opt"
108 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
109 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
111 #define ELTAG_LDAP_ATTR_SRCH "attribute"
112 #define ATTAG_LDAP_ATTR_NAME "name"
114 /* Attribute values */
115 #define ATVAL_BOOLEAN_YES "yes"
116 #define ATVAL_BOOLEAN_NO "no"
117 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
118 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
121 #define ATTAG_LDAP_DEFAULT "default"
123 #define DISP_NEW_COMMON _("Common addresses")
124 #define DISP_NEW_PERSONAL _("Personal addresses")
126 /* Old address book */
127 #define TAG_IF_OLD_COMMON "common_address"
128 #define TAG_IF_OLD_PERSONAL "personal_address"
130 #define DISP_OLD_COMMON _("Common address")
131 #define DISP_OLD_PERSONAL _("Personal address")
136 static AddressIndex
*_addressIndex_
= NULL
;
139 * Define attribute name-value pair.
141 typedef struct _AddressIfAttr AddressIfAttrib
;
142 struct _AddressIfAttr
{
147 static AddressDataSource
*addrindex_create_datasource ( AddressIfType ifType
);
149 static GList
*addrindex_ds_get_all_persons ( AddressDataSource
*ds
);
150 static GList
*addrindex_ds_get_all_groups ( AddressDataSource
*ds
);
151 static AddressDataSource
*addrindex_get_datasource ( AddressIndex
*addrIndex
,
152 const gchar
*cacheID
);
153 static AddressInterface
*addrindex_get_interface ( AddressIndex
*addrIndex
,
154 AddressIfType ifType
);
155 static gint
addrindex_write_to ( AddressIndex
*addrIndex
,
156 const gchar
*newFile
);
159 * Define DOM fragment.
161 typedef struct _AddressIfFrag AddressIfFragment
;
162 struct _AddressIfFrag
{
169 * Build interface with default values.
171 * \param type Interface type.
172 * \param name Interface name.
173 * \param tagIf XML tag name for interface in address index file.
174 * \param tagDS XML tag name for datasource in address index file.
175 * \return Address interface object.
177 static AddressInterface
*addrindex_create_interface(
178 gint type
, gchar
*name
, gchar
*tagIf
, gchar
*tagDS
)
180 AddressInterface
*iface
= g_new0( AddressInterface
, 1 );
182 ADDRITEM_TYPE(iface
) = ITEMTYPE_INTERFACE
;
183 ADDRITEM_ID(iface
) = NULL
;
184 ADDRITEM_NAME(iface
) = g_strdup( name
);
185 ADDRITEM_PARENT(iface
) = NULL
;
186 ADDRITEM_SUBTYPE(iface
) = type
;
188 iface
->name
= g_strdup( name
);
189 iface
->listTag
= g_strdup( tagIf
);
190 iface
->itemTag
= g_strdup( tagDS
);
191 iface
->legacyFlag
= FALSE
;
192 iface
->haveLibrary
= TRUE
;
193 iface
->useInterface
= TRUE
;
194 iface
->readOnly
= TRUE
;
196 /* Set callbacks to NULL values - override for each interface */
197 iface
->getAccessFlag
= NULL
;
198 iface
->getModifyFlag
= NULL
;
199 iface
->getReadFlag
= NULL
;
200 iface
->getStatusCode
= NULL
;
201 iface
->getReadData
= NULL
;
202 iface
->getRootFolder
= NULL
;
203 iface
->getListFolder
= NULL
;
204 iface
->getListPerson
= NULL
;
205 iface
->getAllPersons
= NULL
;
206 iface
->getAllGroups
= NULL
;
207 iface
->getName
= NULL
;
208 iface
->listSource
= NULL
;
211 iface
->externalQuery
= FALSE
;
212 iface
->searchOrder
= 0; /* Ignored */
213 iface
->startSearch
= NULL
;
214 iface
->stopSearch
= NULL
;
220 * Build table of of all address book interfaces.
221 * \param addrIndex Address index object.
223 static void addrindex_build_if_list( AddressIndex
*addrIndex
) {
224 AddressInterface
*iface
;
226 /* Create intrinsic XML address book interface */
227 iface
= addrindex_create_interface(
228 ADDR_IF_BOOK
, "Address Book", TAG_IF_ADDRESS_BOOK
,
229 TAG_DS_ADDRESS_BOOK
);
230 iface
->readOnly
= FALSE
;
231 iface
->getModifyFlag
= ( void * ) addrbook_get_modified
;
232 iface
->getAccessFlag
= ( void * ) addrbook_get_accessed
;
233 iface
->getReadFlag
= ( void * ) addrbook_get_read_flag
;
234 iface
->getStatusCode
= ( void * ) addrbook_get_status
;
235 iface
->getReadData
= ( void * ) addrbook_read_data
;
236 iface
->getRootFolder
= ( void * ) addrbook_get_root_folder
;
237 iface
->getListFolder
= ( void * ) addrbook_get_list_folder
;
238 iface
->getListPerson
= ( void * ) addrbook_get_list_person
;
239 iface
->getAllPersons
= ( void * ) addrbook_get_all_persons
;
240 iface
->getAllGroups
= ( void * ) addrbook_get_all_groups
;
241 iface
->getName
= ( void * ) addrbook_get_name
;
242 iface
->setAccessFlag
= ( void * ) addrbook_set_accessed
;
243 iface
->searchOrder
= 0;
245 /* Add to list of interfaces in address book */
246 addrIndex
->interfaceList
=
247 g_list_append( addrIndex
->interfaceList
, iface
);
248 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
250 /* Create vCard interface */
251 iface
= addrindex_create_interface(
252 ADDR_IF_VCARD
, "vCard", TAG_IF_VCARD
, TAG_DS_VCARD
);
253 iface
->getModifyFlag
= ( void * ) vcard_get_modified
;
254 iface
->getAccessFlag
= ( void * ) vcard_get_accessed
;
255 iface
->getReadFlag
= ( void * ) vcard_get_read_flag
;
256 iface
->getStatusCode
= ( void * ) vcard_get_status
;
257 iface
->getReadData
= ( void * ) vcard_read_data
;
258 iface
->getRootFolder
= ( void * ) vcard_get_root_folder
;
259 iface
->getListFolder
= ( void * ) vcard_get_list_folder
;
260 iface
->getListPerson
= ( void * ) vcard_get_list_person
;
261 iface
->getAllPersons
= ( void * ) vcard_get_all_persons
;
262 iface
->getName
= ( void * ) vcard_get_name
;
263 iface
->setAccessFlag
= ( void * ) vcard_set_accessed
;
264 iface
->searchOrder
= 0;
265 addrIndex
->interfaceList
=
266 g_list_append( addrIndex
->interfaceList
, iface
);
267 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
269 /* Create JPilot interface */
270 iface
= addrindex_create_interface(
271 ADDR_IF_JPILOT
, "J-Pilot", TAG_IF_JPILOT
,
274 iface
->haveLibrary
= jpilot_test_pilot_lib();
275 iface
->useInterface
= iface
->haveLibrary
;
276 iface
->getModifyFlag
= ( void * ) jpilot_get_modified
;
277 iface
->getAccessFlag
= ( void * ) jpilot_get_accessed
;
278 iface
->getReadFlag
= ( void * ) jpilot_get_read_flag
;
279 iface
->getStatusCode
= ( void * ) jpilot_get_status
;
280 iface
->getReadData
= ( void * ) jpilot_read_data
;
281 iface
->getRootFolder
= ( void * ) jpilot_get_root_folder
;
282 iface
->getListFolder
= ( void * ) jpilot_get_list_folder
;
283 iface
->getListPerson
= ( void * ) jpilot_get_list_person
;
284 iface
->getAllPersons
= ( void * ) jpilot_get_all_persons
;
285 iface
->getName
= ( void * ) jpilot_get_name
;
286 iface
->setAccessFlag
= ( void * ) jpilot_set_accessed
;
287 iface
->searchOrder
= 0;
289 iface
->useInterface
= FALSE
;
290 iface
->haveLibrary
= FALSE
;
292 addrIndex
->interfaceList
=
293 g_list_append( addrIndex
->interfaceList
, iface
);
294 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
296 /* Create LDAP interface */
297 iface
= addrindex_create_interface(
298 ADDR_IF_LDAP
, "LDAP", TAG_IF_LDAP
, TAG_DS_LDAP
);
300 iface
->readOnly
= FALSE
;
301 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
302 iface
->haveLibrary
= ldaputil_test_ldap_lib();
303 iface
->useInterface
= iface
->haveLibrary
;
304 iface
->getModifyFlag
= ( void * ) ldapsvr_get_modified
;
305 iface
->getAccessFlag
= ( void * ) ldapsvr_get_accessed
;
306 iface
->getReadFlag
= ( void * ) ldapsvr_get_read_flag
;
307 iface
->getStatusCode
= ( void * ) ldapsvr_get_status
;
308 iface
->getReadData
= ( void * ) ldapsvr_read_data
;
309 iface
->getRootFolder
= ( void * ) ldapsvr_get_root_folder
;
310 iface
->getListFolder
= ( void * ) ldapsvr_get_list_folder
;
311 iface
->getListPerson
= ( void * ) ldapsvr_get_list_person
;
312 iface
->getName
= ( void * ) ldapsvr_get_name
;
313 iface
->setAccessFlag
= ( void * ) ldapsvr_set_accessed
;
314 iface
->externalQuery
= TRUE
;
315 iface
->searchOrder
= 1;
317 iface
->useInterface
= FALSE
;
318 iface
->haveLibrary
= FALSE
;
320 addrIndex
->interfaceList
=
321 g_list_append( addrIndex
->interfaceList
, iface
);
322 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
324 /* Two old legacy data sources (pre 0.7.0) */
325 iface
= addrindex_create_interface(
326 ADDR_IF_COMMON
, "Old Address - common",
327 TAG_IF_OLD_COMMON
, NULL
);
328 iface
->legacyFlag
= TRUE
;
329 addrIndex
->interfaceList
=
330 g_list_append( addrIndex
->interfaceList
, iface
);
331 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
333 iface
= addrindex_create_interface(
334 ADDR_IF_COMMON
, "Old Address - personal",
335 TAG_IF_OLD_PERSONAL
, NULL
);
336 iface
->legacyFlag
= TRUE
;
337 addrIndex
->interfaceList
=
338 g_list_append( addrIndex
->interfaceList
, iface
);
339 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
345 * \param fragment Fragment to free.
347 static void addrindex_free_fragment( AddressIfFragment
*fragment
) {
351 node
= fragment
->children
;
353 AddressIfFragment
*child
= node
->data
;
354 addrindex_free_fragment( child
);
356 node
= g_list_next( node
);
358 g_list_free( fragment
->children
);
360 /* Free attributes */
361 node
= fragment
->attributes
;
363 AddressIfAttrib
*nv
= node
->data
;
368 node
= g_list_next( node
);
370 g_list_free( fragment
->attributes
);
372 g_free( fragment
->name
);
373 fragment
->name
= NULL
;
374 fragment
->attributes
= NULL
;
375 fragment
->children
= NULL
;
381 * Create a new data source.
382 * \param ifType Interface type to create.
383 * \return Initialized data source.
385 AddressDataSource
*addrindex_create_datasource( AddressIfType ifType
) {
386 AddressDataSource
*ds
= g_new0( AddressDataSource
, 1 );
388 ADDRITEM_TYPE(ds
) = ITEMTYPE_DATASOURCE
;
389 ADDRITEM_ID(ds
) = NULL
;
390 ADDRITEM_NAME(ds
) = NULL
;
391 ADDRITEM_PARENT(ds
) = NULL
;
392 ADDRITEM_SUBTYPE(ds
) = 0;
394 ds
->rawDataSource
= NULL
;
395 ds
->interface
= NULL
;
400 * Free up data source.
401 * \param ds Data source to free.
403 void addrindex_free_datasource( AddressDataSource
*ds
) {
404 AddressInterface
*iface
;
406 cm_return_if_fail( ds
!= NULL
);
408 iface
= ds
->interface
;
409 if( ds
->rawDataSource
!= NULL
) {
410 if( iface
!= NULL
) {
411 if( iface
->useInterface
) {
412 if( iface
->type
== ADDR_IF_BOOK
) {
413 AddressBookFile
*abf
= ds
->rawDataSource
;
414 addrbook_free_book( abf
);
416 else if( iface
->type
== ADDR_IF_VCARD
) {
417 VCardFile
*vcf
= ds
->rawDataSource
;
421 else if( iface
->type
== ADDR_IF_JPILOT
) {
422 JPilotFile
*jpf
= ds
->rawDataSource
;
427 else if( iface
->type
== ADDR_IF_LDAP
) {
428 LdapServer
*server
= ds
->rawDataSource
;
429 ldapsvr_free( server
);
436 AddressIfFragment
*fragment
= ds
->rawDataSource
;
437 addrindex_free_fragment( fragment
);
442 ADDRITEM_TYPE(ds
) = ITEMTYPE_NONE
;
443 ADDRITEM_ID(ds
) = NULL
;
444 ADDRITEM_NAME(ds
) = NULL
;
445 ADDRITEM_PARENT(ds
) = NULL
;
446 ADDRITEM_SUBTYPE(ds
) = 0;
447 ds
->type
= ADDR_IF_NONE
;
448 ds
->interface
= NULL
;
449 ds
->rawDataSource
= NULL
;
455 * Free up all data sources for specified interface.
456 * \param iface Address interface to process.
458 static void addrindex_free_all_datasources( AddressInterface
*iface
) {
459 GList
*node
= iface
->listSource
;
461 AddressDataSource
*ds
= node
->data
;
462 addrindex_free_datasource( ds
);
464 node
= g_list_next( node
);
469 * Free up specified interface.
470 * \param iface Interface to process.
472 static void addrindex_free_interface( AddressInterface
*iface
) {
473 /* Free up data sources */
474 addrindex_free_all_datasources( iface
);
475 g_list_free( iface
->listSource
);
477 /* Free internal storage */
478 g_free( ADDRITEM_ID(iface
) );
479 g_free( ADDRITEM_NAME(iface
) );
480 g_free( iface
->name
);
481 g_free( iface
->listTag
);
482 g_free( iface
->itemTag
);
484 /* Clear all pointers */
485 ADDRITEM_TYPE(iface
) = ITEMTYPE_NONE
;
486 ADDRITEM_ID(iface
) = NULL
;
487 ADDRITEM_NAME(iface
) = NULL
;
488 ADDRITEM_PARENT(iface
) = NULL
;
489 ADDRITEM_SUBTYPE(iface
) = 0;
490 iface
->type
= ADDR_IF_NONE
;
492 iface
->listTag
= NULL
;
493 iface
->itemTag
= NULL
;
494 iface
->legacyFlag
= FALSE
;
495 iface
->useInterface
= FALSE
;
496 iface
->haveLibrary
= FALSE
;
497 iface
->listSource
= NULL
;
500 iface
->searchOrder
= 0;
501 iface
->startSearch
= NULL
;
502 iface
->stopSearch
= NULL
;
508 * Return cache ID for specified data source.
510 * \param addrIndex Address index.
511 * \param ds Data source.
512 * \return ID or NULL if not found. This should be <code>g_free()</code>
515 gchar
*addrindex_get_cache_id( AddressIndex
*addrIndex
, AddressDataSource
*ds
) {
516 gchar
*cacheID
= NULL
;
517 AddrBookBase
*adbase
;
520 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
521 cm_return_val_if_fail( ds
!= NULL
, NULL
);
523 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
525 cache
= adbase
->addressCache
;
527 cacheID
= g_strdup( cache
->cacheID
);
535 * Return reference to data source for specified cacheID.
536 * \param addrIndex Address index.
538 * \return Data source, or NULL if not found.
540 static AddressDataSource
*addrindex_get_datasource(
541 AddressIndex
*addrIndex
, const gchar
*cacheID
)
543 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
544 cm_return_val_if_fail( cacheID
!= NULL
, NULL
);
545 return ( AddressDataSource
* ) g_hash_table_lookup( addrIndex
->hashCache
, cacheID
);
549 * Return reference to address cache for specified cacheID.
550 * \param addrIndex Address index.
552 * \return Address cache, or NULL if not found.
554 AddressCache
*addrindex_get_cache( AddressIndex
*addrIndex
, const gchar
*cacheID
) {
555 AddressDataSource
*ds
;
556 AddrBookBase
*adbase
;
559 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
560 cm_return_val_if_fail( cacheID
!= NULL
, NULL
);
563 ds
= addrindex_get_datasource( addrIndex
, cacheID
);
565 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
566 cache
= adbase
->addressCache
;
572 * Add data source into hash table.
573 * \param addrIndex Address index.
574 * \param ds Data source.
576 static void addrindex_hash_add_cache(
577 AddressIndex
*addrIndex
, AddressDataSource
*ds
)
581 cacheID
= addrindex_get_cache_id( addrIndex
, ds
);
583 g_hash_table_insert( addrIndex
->hashCache
, cacheID
, ds
);
588 * Free hash table callback function.
590 static gboolean
addrindex_free_cache_cb( gpointer key
, gpointer value
, gpointer data
) {
598 * Free hash table of address cache items.
600 static void addrindex_free_cache_hash( GHashTable
*table
) {
601 g_hash_table_foreach_remove( table
, addrindex_free_cache_cb
, NULL
);
602 g_hash_table_destroy( table
);
606 * Remove data source from internal hashtable.
607 * \param addrIndex Address index.
608 * \param ds Data source to remove.
610 static void addrindex_hash_remove_cache(
611 AddressIndex
*addrIndex
, AddressDataSource
*ds
)
615 cacheID
= addrindex_get_cache_id( addrIndex
, ds
);
617 g_hash_table_remove( addrIndex
->hashCache
, cacheID
);
624 * Create a new address index. This is created as a singleton object.
625 * \return Initialized address index object.
627 AddressIndex
*addrindex_create_index( void ) {
630 if( _addressIndex_
== NULL
) {
631 index
= g_new0( AddressIndex
, 1 );
632 ADDRITEM_TYPE(index
) = ITEMTYPE_INDEX
;
633 ADDRITEM_ID(index
) = NULL
;
634 ADDRITEM_NAME(index
) = g_strdup( "Address Index" );
635 ADDRITEM_PARENT(index
) = NULL
;
636 ADDRITEM_SUBTYPE(index
) = 0;
637 index
->filePath
= NULL
;
638 index
->fileName
= NULL
;
639 index
->retVal
= MGU_SUCCESS
;
640 index
->needsConversion
= FALSE
;
641 index
->wasConverted
= FALSE
;
642 index
->conversionError
= FALSE
;
643 index
->interfaceList
= NULL
;
644 index
->lastType
= ADDR_IF_NONE
;
645 index
->dirtyFlag
= FALSE
;
646 index
->hashCache
= g_hash_table_new( g_str_hash
, g_str_equal
);
647 index
->loadedFlag
= FALSE
;
648 index
->searchOrder
= NULL
;
649 addrindex_build_if_list( index
);
650 _addressIndex_
= index
;
652 return _addressIndex_
;
656 * Property - Specify file path to address index file.
657 * \param addrIndex Address index.
658 * \param value Path to index file.
660 void addrindex_set_file_path( AddressIndex
*addrIndex
, const gchar
*value
) {
661 cm_return_if_fail( addrIndex
!= NULL
);
662 addrIndex
->filePath
= mgu_replace_string( addrIndex
->filePath
, value
);
666 * Property - Specify file name to address index file.
667 * \param addrIndex Address index.
668 * \param value File name.
670 void addrindex_set_file_name( AddressIndex
*addrIndex
, const gchar
*value
) {
671 cm_return_if_fail( addrIndex
!= NULL
);
672 addrIndex
->fileName
= mgu_replace_string( addrIndex
->fileName
, value
);
676 * Return list of address interfaces.
677 * \param addrIndex Address index.
678 * \return List of address interfaces.
680 GList
*addrindex_get_interface_list( AddressIndex
*addrIndex
) {
681 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
682 return addrIndex
->interfaceList
;
686 * Perform any other initialization of address index.
688 void addrindex_initialize( void ) {
690 addrcompl_initialize();
694 * Perform any other teardown of address index.
696 void addrindex_teardown( void ) {
697 addrcompl_teardown();
702 * Free up address index.
703 * \param addrIndex Address index.
705 void addrindex_free_index( AddressIndex
*addrIndex
) {
708 cm_return_if_fail( addrIndex
!= NULL
);
711 g_list_free( addrIndex
->searchOrder
);
712 addrIndex
->searchOrder
= NULL
;
714 /* Free internal storage */
715 g_free( ADDRITEM_ID(addrIndex
) );
716 g_free( ADDRITEM_NAME(addrIndex
) );
717 g_free( addrIndex
->filePath
);
718 g_free( addrIndex
->fileName
);
721 ADDRITEM_TYPE(addrIndex
) = ITEMTYPE_NONE
;
722 ADDRITEM_ID(addrIndex
) = NULL
;
723 ADDRITEM_NAME(addrIndex
) = NULL
;
724 ADDRITEM_PARENT(addrIndex
) = NULL
;
725 ADDRITEM_SUBTYPE(addrIndex
) = 0;
726 addrIndex
->filePath
= NULL
;
727 addrIndex
->fileName
= NULL
;
728 addrIndex
->retVal
= MGU_SUCCESS
;
729 addrIndex
->needsConversion
= FALSE
;
730 addrIndex
->wasConverted
= FALSE
;
731 addrIndex
->conversionError
= FALSE
;
732 addrIndex
->lastType
= ADDR_IF_NONE
;
733 addrIndex
->dirtyFlag
= FALSE
;
735 /* Free up interfaces */
736 node
= addrIndex
->interfaceList
;
738 AddressInterface
*iface
= node
->data
;
739 addrindex_free_interface( iface
);
740 node
= g_list_next( node
);
742 g_list_free( addrIndex
->interfaceList
);
743 addrIndex
->interfaceList
= NULL
;
745 /* Free up hash cache */
746 addrindex_free_cache_hash( addrIndex
->hashCache
);
747 addrIndex
->hashCache
= NULL
;
749 addrIndex
->loadedFlag
= FALSE
;
753 _addressIndex_
= NULL
;
757 * Print address index.
758 * \param addrIndex Address index.
759 * \parem stream Stream to print.
761 void addrindex_print_index( AddressIndex
*addrIndex
, FILE *stream
) {
762 cm_return_if_fail( addrIndex
!= NULL
);
763 fprintf( stream
, "AddressIndex:\n" );
764 fprintf( stream
, "\tfile path: '%s'\n", addrIndex
->filePath
);
765 fprintf( stream
, "\tfile name: '%s'\n", addrIndex
->fileName
);
766 fprintf( stream
, "\t status: %d\n", addrIndex
->retVal
);
767 fprintf( stream
, "\tconverted: '%s'\n",
768 addrIndex
->wasConverted
? "yes" : "no" );
769 fprintf( stream
, "\tcvt error: '%s'\n",
770 addrIndex
->conversionError
? "yes" : "no" );
771 fprintf( stream
, "\t---\n" );
775 * Retrieve reference to address interface for specified interface type.
776 * \param addrIndex Address index.
777 * \param ifType Interface type.
778 * \return Address interface, or NULL if not found.
780 static AddressInterface
*addrindex_get_interface(
781 AddressIndex
*addrIndex
, AddressIfType ifType
)
783 AddressInterface
*retVal
= NULL
;
786 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
788 node
= addrIndex
->interfaceList
;
790 AddressInterface
*iface
= node
->data
;
791 node
= g_list_next( node
);
792 if( iface
->type
== ifType
) {
801 * Add raw data source to index. The raw data object (an AddressBookFile or
802 * VCardFile object, for example) should be supplied as the raw dataSource
805 * \param addrIndex Address index.
806 * \param ifType Interface type to add.
807 * \param dataSource Actual raw data source to add.
808 * \return Data source added, or NULL if invalid interface type.
810 AddressDataSource
*addrindex_index_add_datasource(
811 AddressIndex
*addrIndex
, AddressIfType ifType
, gpointer dataSource
)
813 AddressInterface
*iface
;
814 AddressDataSource
*ds
= NULL
;
816 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
817 cm_return_val_if_fail( dataSource
!= NULL
, NULL
);
819 iface
= addrindex_get_interface( addrIndex
, ifType
);
821 ds
= addrindex_create_datasource( ifType
);
822 ADDRITEM_PARENT(ds
) = ADDRITEM_OBJECT(iface
);
824 ds
->rawDataSource
= dataSource
;
825 ds
->interface
= iface
;
826 iface
->listSource
= g_list_append( iface
->listSource
, ds
);
827 addrIndex
->dirtyFlag
= TRUE
;
829 addrindex_hash_add_cache( addrIndex
, ds
);
835 * Remove specified data source from index.
836 * \param addrIndex Address index.
837 * \param dataSource Data source to add.
838 * \return Reference to data source if removed, or NULL if data source was not
839 * found in index. Note the this object must still be freed.
841 AddressDataSource
*addrindex_index_remove_datasource(
842 AddressIndex
*addrIndex
, AddressDataSource
*dataSource
)
844 AddressDataSource
*retVal
= FALSE
;
845 AddressInterface
*iface
;
847 cm_return_val_if_fail( addrIndex
!= NULL
, NULL
);
848 cm_return_val_if_fail( dataSource
!= NULL
, NULL
);
850 iface
= addrindex_get_interface( addrIndex
, dataSource
->type
);
852 iface
->listSource
= g_list_remove( iface
->listSource
, dataSource
);
853 addrIndex
->dirtyFlag
= TRUE
;
854 dataSource
->interface
= NULL
;
856 /* Remove cache from hash table */
857 addrindex_hash_remove_cache( addrIndex
, dataSource
);
865 * Retrieve a reference to address interface for specified interface type and
866 * XML interface tag name.
867 * \param addrIndex Address index.
868 * \param tag XML interface tag name to match.
869 * \param ifType Interface type to match.
870 * \return Reference to address index, or NULL if not found in index.
872 static AddressInterface
*addrindex_tag_get_interface(
873 AddressIndex
*addrIndex
, gchar
*tag
, AddressIfType ifType
)
875 AddressInterface
*retVal
= NULL
;
876 GList
*node
= addrIndex
->interfaceList
;
879 AddressInterface
*iface
= node
->data
;
880 node
= g_list_next( node
);
882 if( strcmp( iface
->listTag
, tag
) == 0 ) {
888 if( iface
->type
== ifType
) {
898 * Retrieve a reference to address interface for specified interface type and
899 * XML datasource tag name.
900 * \param addrIndex Address index.
901 * \param ifType Interface type to match.
902 * \param tag XML datasource tag name to match.
903 * \return Reference to address index, or NULL if not found in index.
905 static AddressInterface
*addrindex_tag_get_datasource(
906 AddressIndex
*addrIndex
, AddressIfType ifType
, gchar
*tag
)
908 AddressInterface
*retVal
= NULL
;
909 GList
*node
= addrIndex
->interfaceList
;
912 AddressInterface
*iface
= node
->data
;
913 node
= g_list_next( node
);
914 if( iface
->type
== ifType
&& iface
->itemTag
) {
915 if( strcmp( iface
->itemTag
, tag
) == 0 ) {
924 /* **********************************************************************
925 * Interface XML parsing functions.
926 * ***********************************************************************
930 * Write start of XML element to file.
932 * \param lvl Indentation level.
933 * \param name Element name.
935 static int addrindex_write_elem_s( FILE *fp
, const gint lvl
, const gchar
*name
) {
937 for( i
= 0; i
< lvl
; i
++ )
938 if (fputs( " ", fp
) == EOF
)
940 if (fputs( "<", fp
) == EOF
)
942 if (fputs( name
, fp
) == EOF
)
948 * Write end of XML element to file.
950 * \param lvl Indentation level.
951 * \param name Element name.
953 static int addrindex_write_elem_e( FILE *fp
, const gint lvl
, const gchar
*name
) {
955 for( i
= 0; i
< lvl
; i
++ )
956 if (fputs( " ", fp
) == EOF
)
958 if (fputs( "</", fp
) == EOF
)
960 if (fputs( name
, fp
) == EOF
)
962 if (fputs( ">\n", fp
) == EOF
)
968 * Write XML attribute to file.
970 * \param name Attribute name.
971 * \param value Attribute value.
973 static int addrindex_write_attr( FILE *fp
, const gchar
*name
, const gchar
*value
) {
974 if (fputs( " ", fp
) == EOF
)
976 if (fputs( name
, fp
) == EOF
)
978 if (fputs( "=\"", fp
) == EOF
)
980 if (xml_file_put_escape_str( fp
, value
) < 0)
982 if (fputs( "\"", fp
) == EOF
)
987 #if !defined(USE_LDAP) || !defined(USE_JPILOT)
989 * Return DOM fragment for current XML tag from file.
990 * \param file XML file being processed.
991 * \return Fragment representing DOM fragment for configuration element.
993 static AddressIfFragment
*addrindex_read_fragment( XMLFile
*file
) {
994 AddressIfFragment
*fragment
;
995 AddressIfFragment
*child
;
1005 /* g_print( "addrindex_read_fragment\n" ); */
1007 prevLevel
= file
->level
;
1009 /* Get current tag name */
1010 xtag
= xml_get_current_tag( file
);
1012 /* Create new fragment */
1013 fragment
= g_new0( AddressIfFragment
, 1 );
1014 fragment
->name
= g_strdup( xtag
->tag
);
1015 fragment
->children
= NULL
;
1016 fragment
->attributes
= NULL
;
1018 /* Read attributes */
1020 attr
= xml_get_current_tag_attr( file
);
1022 name
= ((XMLAttr
*)attr
->data
)->name
;
1023 value
= ((XMLAttr
*)attr
->data
)->value
;
1024 nv
= g_new0( AddressIfAttrib
, 1 );
1025 nv
->name
= g_strdup( name
);
1026 nv
->value
= g_strdup( value
);
1027 list
= g_list_append( list
, nv
);
1028 attr
= g_list_next( attr
);
1030 fragment
->attributes
= list
;
1032 /* Now read the children */
1034 rc
= xml_parse_next_tag( file
);
1039 if( file
->level
< prevLevel
) {
1040 /* We must be above level we start at */
1043 child
= addrindex_read_fragment( file
);
1044 fragment
->children
= g_list_append( fragment
->children
, child
);
1051 * Write DOM fragment to file.
1052 * \param fp File to write.
1053 * \param fragment DOM fragment for configuration element.
1054 * \param lvl Indent level.
1056 static int addrindex_write_fragment(
1057 FILE *fp
, const AddressIfFragment
*fragment
, const gint lvl
)
1062 if (addrindex_write_elem_s( fp
, lvl
, fragment
->name
) < 0)
1064 node
= fragment
->attributes
;
1066 AddressIfAttrib
*nv
= node
->data
;
1067 if (addrindex_write_attr( fp
, nv
->name
, nv
->value
) < 0)
1069 node
= g_list_next( node
);
1071 if( fragment
->children
) {
1072 if (fputs(" >\n", fp
) == EOF
)
1075 /* Output children */
1076 node
= fragment
->children
;
1078 AddressIfFragment
*child
= node
->data
;
1079 if (addrindex_write_fragment( fp
, child
, 1+lvl
) < 0)
1081 node
= g_list_next( node
);
1084 /* Output closing tag */
1085 if (addrindex_write_elem_e( fp
, lvl
, fragment
->name
) < 0)
1089 if (fputs(" />\n", fp
) == EOF
)
1098 * Read/parse address index file, creating a data source for a regular
1099 * intrinsic XML addressbook.
1100 * \param file Address index file.
1101 * \return Data source.
1103 static AddressDataSource
*addrindex_parse_book( XMLFile
*file
) {
1104 AddressDataSource
*ds
;
1105 AddressBookFile
*abf
;
1108 ds
= addrindex_create_datasource( ADDR_IF_BOOK
);
1109 abf
= addrbook_create_book();
1110 attr
= xml_get_current_tag_attr( file
);
1112 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1113 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1114 if( strcmp( name
, ATTAG_BOOK_NAME
) == 0 ) {
1115 addrbook_set_name( abf
, value
);
1117 else if( strcmp( name
, ATTAG_BOOK_FILE
) == 0) {
1118 addrbook_set_file( abf
, value
);
1120 attr
= g_list_next( attr
);
1122 ds
->rawDataSource
= abf
;
1126 static int addrindex_write_book( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1127 AddressBookFile
*abf
= ds
->rawDataSource
;
1129 if (addrindex_write_elem_s( fp
, lvl
, TAG_DS_ADDRESS_BOOK
) < 0)
1131 if (addrindex_write_attr( fp
, ATTAG_BOOK_NAME
, addrbook_get_name( abf
) ) < 0)
1133 if (addrindex_write_attr( fp
, ATTAG_BOOK_FILE
, abf
->fileName
) < 0)
1135 if (fputs( " />\n", fp
) == EOF
)
1141 static AddressDataSource
*addrindex_parse_vcard( XMLFile
*file
) {
1142 AddressDataSource
*ds
;
1146 ds
= addrindex_create_datasource( ADDR_IF_VCARD
);
1147 vcf
= vcard_create();
1148 attr
= xml_get_current_tag_attr( file
);
1150 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1151 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1152 if( strcmp( name
, ATTAG_VCARD_NAME
) == 0 ) {
1153 vcard_set_name( vcf
, value
);
1155 else if( strcmp( name
, ATTAG_VCARD_FILE
) == 0) {
1156 vcard_set_file( vcf
, value
);
1158 attr
= g_list_next( attr
);
1160 ds
->rawDataSource
= vcf
;
1164 static int addrindex_write_vcard( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1165 VCardFile
*vcf
= ds
->rawDataSource
;
1167 if (addrindex_write_elem_s( fp
, lvl
, TAG_DS_VCARD
) < 0)
1169 if (addrindex_write_attr( fp
, ATTAG_VCARD_NAME
, vcard_get_name( vcf
) ) < 0)
1171 if (addrindex_write_attr( fp
, ATTAG_VCARD_FILE
, vcf
->path
) < 0)
1173 if (fputs( " />\n", fp
) == EOF
)
1180 static AddressDataSource
*addrindex_parse_jpilot( XMLFile
*file
) {
1181 AddressDataSource
*ds
;
1185 ds
= addrindex_create_datasource( ADDR_IF_JPILOT
);
1186 jpf
= jpilot_create();
1187 attr
= xml_get_current_tag_attr( file
);
1189 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1190 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1191 if( strcmp( name
, ATTAG_JPILOT_NAME
) == 0 ) {
1192 jpilot_set_name( jpf
, value
);
1194 else if( strcmp( name
, ATTAG_JPILOT_FILE
) == 0 ) {
1195 jpilot_set_file( jpf
, value
);
1197 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_1
) == 0 ) {
1198 jpilot_add_custom_label( jpf
, value
);
1200 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_2
) == 0 ) {
1201 jpilot_add_custom_label( jpf
, value
);
1203 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_3
) == 0 ) {
1204 jpilot_add_custom_label( jpf
, value
);
1206 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_4
) == 0 ) {
1207 jpilot_add_custom_label( jpf
, value
);
1209 attr
= g_list_next( attr
);
1211 ds
->rawDataSource
= jpf
;
1215 static int addrindex_write_jpilot( FILE *fp
,AddressDataSource
*ds
, gint lvl
) {
1216 JPilotFile
*jpf
= ds
->rawDataSource
;
1220 GList
*customLbl
= jpilot_get_custom_labels( jpf
);
1221 if (addrindex_write_elem_s( fp
, lvl
, TAG_DS_JPILOT
) < 0)
1223 if (addrindex_write_attr( fp
, ATTAG_JPILOT_NAME
, jpilot_get_name( jpf
) ) < 0)
1225 if (addrindex_write_attr( fp
, ATTAG_JPILOT_FILE
, jpf
->path
) < 0)
1231 g_snprintf( name
, sizeof(name
), "%s%d",
1232 ATTAG_JPILOT_CUSTOM
, ind
);
1233 if (addrindex_write_attr( fp
, name
, node
->data
) < 0)
1236 node
= g_list_next( node
);
1238 if (fputs( " />\n", fp
) == EOF
)
1246 * Just read/write DOM fragments (preserve data found in file).
1248 static AddressDataSource
*addrindex_parse_jpilot( XMLFile
*file
) {
1249 AddressDataSource
*ds
;
1251 ds
= addrindex_create_datasource( ADDR_IF_JPILOT
);
1252 ds
->rawDataSource
= addrindex_read_fragment( file
);
1256 static int addrindex_write_jpilot( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1257 AddressIfFragment
*fragment
= ds
->rawDataSource
;
1259 if (addrindex_write_fragment( fp
, fragment
, lvl
) < 0)
1268 * Parse LDAP criteria attribute data from XML file.
1269 * \param file Index file.
1270 * \param ctl LDAP control object to populate.
1272 static void addrindex_parse_ldap_attrlist( XMLFile
*file
, LdapControl
*ctl
) {
1281 if( file
== NULL
) {
1286 prevLevel
= file
->level
;
1287 xtagPrev
= xml_get_current_tag( file
);
1289 rc
= xml_parse_next_tag( file
);
1291 /* Terminate prematurely */
1292 mgu_free_dlist( list
);
1296 if( file
->level
< prevLevel
) {
1297 /* We must be above level we start at */
1301 /* Get a tag (element) */
1302 xtag
= xml_get_current_tag( file
);
1303 if( strcmp( xtag
->tag
, ELTAG_LDAP_ATTR_SRCH
) == 0 ) {
1304 /* LDAP criteria attribute */
1305 attr
= xml_get_current_tag_attr( file
);
1307 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1308 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1309 if( strcmp( name
, ATTAG_LDAP_ATTR_NAME
) == 0 ) {
1310 if( value
&& strlen( value
) > 0 ) {
1311 list
= g_list_append(
1312 list
, g_strdup( value
) );
1315 attr
= g_list_next( attr
);
1319 if( xtag
!= xtagPrev
) {
1320 /* Found a new tag */
1327 /* Build list of search attributes */
1328 ldapctl_criteria_list_clear( ctl
);
1331 ldapctl_criteria_list_add( ctl
, node
->data
);
1332 g_free( node
->data
);
1334 node
= g_list_next( node
);
1336 g_list_free( list
);
1341 void ldapsvr_set_control( LdapServer
*server
, LdapControl
*ctl
);
1343 * Parse LDAP control data from XML file.
1344 * \param file Index file.
1345 * \return Initialized data soruce object.
1347 static AddressDataSource
*addrindex_parse_ldap( XMLFile
*file
) {
1348 AddressDataSource
*ds
;
1352 gchar
*serverName
= NULL
;
1353 gchar
*criteria
= NULL
;
1354 gboolean bDynSearch
;
1355 gboolean bTLS
, bSSL
;
1358 /* g_print( "addrindex_parse_ldap\n" ); */
1359 /* Set up some defaults */
1363 iMatch
= LDAPCTL_MATCH_BEGINWITH
;
1365 ds
= addrindex_create_datasource( ADDR_IF_LDAP
);
1366 ctl
= ldapctl_create();
1367 attr
= xml_get_current_tag_attr( file
);
1369 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1370 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1371 gint ivalue
= atoi( value
);
1373 if( strcmp( name
, ATTAG_LDAP_NAME
) == 0 ) {
1374 g_free( serverName
);
1375 serverName
= g_strdup( value
);
1377 else if( strcmp( name
, ATTAG_LDAP_HOST
) == 0 ) {
1378 ldapctl_set_host( ctl
, value
);
1380 else if( strcmp( name
, ATTAG_LDAP_PORT
) == 0 ) {
1381 ldapctl_set_port( ctl
, ivalue
);
1383 else if( strcmp( name
, ATTAG_LDAP_BASE_DN
) == 0 ) {
1384 ldapctl_set_base_dn( ctl
, value
);
1386 else if( strcmp( name
, ATTAG_LDAP_BIND_DN
) == 0 ) {
1387 ldapctl_set_bind_dn( ctl
, value
);
1389 else if( strcmp( name
, ATTAG_LDAP_BIND_PASS
) == 0 ) {
1390 ldapctl_set_bind_password( ctl
, value
, FALSE
, FALSE
);
1392 else if( strcmp( name
, ATTAG_LDAP_CRITERIA
) == 0 ) {
1394 criteria
= g_strdup( value
);
1395 g_print("criteria %s\n", criteria
);
1397 else if( strcmp( name
, ATTAG_LDAP_MAX_ENTRY
) == 0 ) {
1398 ldapctl_set_max_entries( ctl
, ivalue
);
1400 else if( strcmp( name
, ATTAG_LDAP_TIMEOUT
) == 0 ) {
1401 ldapctl_set_timeout( ctl
, ivalue
);
1403 else if( strcmp( name
, ATTAG_LDAP_MAX_AGE
) == 0 ) {
1404 ldapctl_set_max_query_age( ctl
, ivalue
);
1406 else if( strcmp( name
, ATTAG_LDAP_DYN_SEARCH
) == 0 ) {
1408 if( strcmp( value
, ATVAL_BOOLEAN_YES
) == 0 ) {
1412 else if( strcmp( name
, ATTAG_LDAP_MATCH_OPT
) == 0 ) {
1413 iMatch
= LDAPCTL_MATCH_BEGINWITH
;
1414 if( strcmp( value
, ATVAL_LDAP_MATCH_CONTAINS
) == 0 ) {
1415 iMatch
= LDAPCTL_MATCH_CONTAINS
;
1418 else if( strcmp( name
, ATTAG_LDAP_ENABLE_TLS
) == 0 ) {
1420 if( strcmp( value
, ATVAL_BOOLEAN_YES
) == 0 ) {
1424 else if( strcmp( name
, ATTAG_LDAP_ENABLE_SSL
) == 0 ) {
1426 if( strcmp( value
, ATVAL_BOOLEAN_YES
) == 0 ) {
1430 attr
= g_list_next( attr
);
1433 server
= ldapsvr_create_noctl();
1434 ldapsvr_set_name( server
, serverName
);
1435 ldapsvr_set_search_flag( server
, bDynSearch
);
1436 ldapctl_set_matching_option( ctl
, iMatch
);
1437 ldapctl_set_tls( ctl
, bTLS
);
1438 ldapctl_set_ssl( ctl
, bSSL
);
1439 g_free( serverName
);
1440 ldapsvr_set_control( server
, ctl
);
1441 ds
->rawDataSource
= server
;
1443 addrindex_parse_ldap_attrlist( file
, ctl
);
1445 * If criteria have been specified and no attributes were listed, then
1446 * convert old style criteria into an attribute list. Any criteria will
1447 * be dropped when saving data.
1450 if( ! ldapctl_get_criteria_list( ctl
) ) {
1451 ldapctl_parse_ldap_search( ctl
, criteria
);
1455 /* ldapsvr_print_data( server, stdout ); */
1460 static int addrindex_write_ldap( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1461 LdapServer
*server
= ds
->rawDataSource
;
1462 LdapControl
*ctl
= NULL
;
1467 ctl
= server
->control
;
1469 if( ctl
== NULL
) return 0;
1471 /* Output start element with attributes */
1472 if (addrindex_write_elem_s( fp
, lvl
, TAG_DS_LDAP
) < 0)
1474 if (addrindex_write_attr( fp
, ATTAG_LDAP_NAME
, ldapsvr_get_name( server
) ) < 0)
1476 if (addrindex_write_attr( fp
, ATTAG_LDAP_HOST
, ctl
->hostName
) < 0)
1479 sprintf( value
, "%d", ctl
->port
);
1480 if (addrindex_write_attr( fp
, ATTAG_LDAP_PORT
, value
) < 0)
1483 if (addrindex_write_attr( fp
, ATTAG_LDAP_BASE_DN
, ctl
->baseDN
) < 0)
1485 if (addrindex_write_attr( fp
, ATTAG_LDAP_BIND_DN
, ctl
->bindDN
) < 0)
1487 if (addrindex_write_attr( fp
, ATTAG_LDAP_BIND_PASS
, ctl
->bindPass
) < 0)
1490 sprintf( value
, "%d", ctl
->maxEntries
);
1491 if (addrindex_write_attr( fp
, ATTAG_LDAP_MAX_ENTRY
, value
) < 0)
1493 sprintf( value
, "%d", ctl
->timeOut
);
1494 if (addrindex_write_attr( fp
, ATTAG_LDAP_TIMEOUT
, value
) < 0)
1496 sprintf( value
, "%d", ctl
->maxQueryAge
);
1497 if (addrindex_write_attr( fp
, ATTAG_LDAP_MAX_AGE
, value
) < 0)
1500 if (addrindex_write_attr( fp
, ATTAG_LDAP_DYN_SEARCH
,
1501 server
->searchFlag
?
1502 ATVAL_BOOLEAN_YES
: ATVAL_BOOLEAN_NO
) < 0)
1505 if (addrindex_write_attr( fp
, ATTAG_LDAP_MATCH_OPT
,
1506 ( ctl
->matchingOption
== LDAPCTL_MATCH_CONTAINS
) ?
1507 ATVAL_LDAP_MATCH_CONTAINS
: ATVAL_LDAP_MATCH_BEGIN
) < 0)
1510 if (addrindex_write_attr( fp
, ATTAG_LDAP_ENABLE_TLS
,
1512 ATVAL_BOOLEAN_YES
: ATVAL_BOOLEAN_NO
) < 0)
1514 if (addrindex_write_attr( fp
, ATTAG_LDAP_ENABLE_SSL
,
1516 ATVAL_BOOLEAN_YES
: ATVAL_BOOLEAN_NO
) < 0)
1519 if (fputs(" >\n", fp
) == EOF
)
1522 /* Output attributes */
1523 node
= ldapctl_get_criteria_list( ctl
);
1525 if (addrindex_write_elem_s( fp
, 1+lvl
, ELTAG_LDAP_ATTR_SRCH
) < 0)
1527 if (addrindex_write_attr( fp
, ATTAG_LDAP_ATTR_NAME
, node
->data
) < 0)
1529 if (fputs(" />\n", fp
) == EOF
)
1531 node
= g_list_next( node
);
1534 /* End of element */
1535 if (addrindex_write_elem_e( fp
, lvl
, TAG_DS_LDAP
) < 0)
1543 * Just read/write DOM fragments (preserve data found in file).
1545 static AddressDataSource
*addrindex_parse_ldap( XMLFile
*file
) {
1546 AddressDataSource
*ds
;
1548 ds
= addrindex_create_datasource( ADDR_IF_LDAP
);
1549 ds
->rawDataSource
= addrindex_read_fragment( file
);
1553 static int addrindex_write_ldap( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1554 AddressIfFragment
*fragment
= ds
->rawDataSource
;
1556 if (addrindex_write_fragment( fp
, fragment
, lvl
) < 0)
1563 /* **********************************************************************
1564 * Address index I/O functions.
1565 * ***********************************************************************
1568 * Read address index file, creating appropriate data sources for each address
1571 * \param addrIndex Address index.
1572 * \param file Address index file.
1574 static void addrindex_read_index( AddressIndex
*addrIndex
, XMLFile
*file
) {
1576 AddressInterface
*iface
= NULL
, *dsIFace
= NULL
;
1577 AddressDataSource
*ds
;
1580 addrIndex
->loadedFlag
= FALSE
;
1582 rc
= xml_parse_next_tag( file
);
1583 if( rc
< 0 || file
->level
== 0 ) return;
1585 xtag
= xml_get_current_tag( file
);
1587 iface
= addrindex_tag_get_interface( addrIndex
, xtag
->tag
, ADDR_IF_NONE
);
1589 addrIndex
->lastType
= iface
->type
;
1590 if( iface
->legacyFlag
) addrIndex
->needsConversion
= TRUE
;
1593 dsIFace
= addrindex_tag_get_datasource(
1594 addrIndex
, addrIndex
->lastType
, xtag
->tag
);
1596 /* Add data source to list */
1598 if( addrIndex
->lastType
== ADDR_IF_BOOK
) {
1599 ds
= addrindex_parse_book( file
);
1600 if( ds
->rawDataSource
) {
1601 addrbook_set_path( ds
->rawDataSource
,
1602 addrIndex
->filePath
);
1605 else if( addrIndex
->lastType
== ADDR_IF_VCARD
) {
1606 ds
= addrindex_parse_vcard( file
);
1608 else if( addrIndex
->lastType
== ADDR_IF_JPILOT
) {
1609 ds
= addrindex_parse_jpilot( file
);
1611 else if( addrIndex
->lastType
== ADDR_IF_LDAP
) {
1612 ds
= addrindex_parse_ldap( file
);
1615 ds
->interface
= dsIFace
;
1616 addrindex_hash_add_cache( addrIndex
, ds
);
1617 dsIFace
->listSource
=
1618 g_list_append( dsIFace
->listSource
, ds
);
1626 * Search order sorting comparison function for building search order list.
1628 static gint
addrindex_search_order_compare( gconstpointer ptrA
, gconstpointer ptrB
) {
1629 AddressInterface
*ifaceA
= ( AddressInterface
* ) ptrA
;
1630 AddressInterface
*ifaceB
= ( AddressInterface
* ) ptrB
;
1632 return ifaceA
->searchOrder
- ifaceB
->searchOrder
;
1636 * Build list of data sources to process.
1637 * \param addrIndex Address index object.
1639 static void addrindex_build_search_order( AddressIndex
*addrIndex
) {
1642 /* Clear existing list */
1643 g_list_free( addrIndex
->searchOrder
);
1644 addrIndex
->searchOrder
= NULL
;
1646 /* Build new list */
1647 nodeIf
= addrIndex
->interfaceList
;
1649 AddressInterface
*iface
= nodeIf
->data
;
1650 if( iface
->useInterface
) {
1651 if( iface
->searchOrder
> 0 ) {
1652 /* Add to search order list */
1653 addrIndex
->searchOrder
= g_list_insert_sorted(
1654 addrIndex
->searchOrder
, iface
,
1655 addrindex_search_order_compare
);
1658 nodeIf
= g_list_next( nodeIf
);
1662 static gint
addrindex_read_file( AddressIndex
*addrIndex
) {
1663 XMLFile
*file
= NULL
;
1664 gchar
*fileSpec
= NULL
;
1666 cm_return_val_if_fail( addrIndex
!= NULL
, -1 );
1668 fileSpec
= g_strconcat( addrIndex
->filePath
, G_DIR_SEPARATOR_S
, addrIndex
->fileName
, NULL
);
1669 addrIndex
->retVal
= MGU_NO_FILE
;
1670 file
= xml_open_file( fileSpec
);
1673 if( file
== NULL
) {
1675 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1677 return addrIndex
->retVal
;
1680 addrIndex
->retVal
= MGU_BAD_FORMAT
;
1681 if( xml_get_dtd( file
) == 0 ) {
1682 if( xml_parse_next_tag( file
) == 0 ) {
1683 if( xml_compare_tag( file
, TAG_ADDRESS_INDEX
) ) {
1684 addrindex_read_index( addrIndex
, file
);
1685 addrIndex
->retVal
= MGU_SUCCESS
;
1689 xml_close_file( file
);
1691 addrindex_build_search_order( addrIndex
);
1693 return addrIndex
->retVal
;
1696 static int addrindex_write_index( AddressIndex
*addrIndex
, FILE *fp
) {
1697 GList
*nodeIF
, *nodeDS
;
1699 gint lvlItem
= 1 + lvlList
;
1701 nodeIF
= addrIndex
->interfaceList
;
1703 AddressInterface
*iface
= nodeIF
->data
;
1704 if( ! iface
->legacyFlag
) {
1705 nodeDS
= iface
->listSource
;
1706 if (addrindex_write_elem_s( fp
, lvlList
, iface
->listTag
) < 0)
1708 if (fputs( ">\n", fp
) == EOF
)
1711 AddressDataSource
*ds
= nodeDS
->data
;
1713 if( iface
->type
== ADDR_IF_BOOK
) {
1714 if (addrindex_write_book( fp
, ds
, lvlItem
) < 0)
1717 if( iface
->type
== ADDR_IF_VCARD
) {
1718 if (addrindex_write_vcard( fp
, ds
, lvlItem
) < 0)
1721 if( iface
->type
== ADDR_IF_JPILOT
) {
1722 if (addrindex_write_jpilot( fp
, ds
, lvlItem
) < 0)
1725 if( iface
->type
== ADDR_IF_LDAP
) {
1726 if (addrindex_write_ldap( fp
, ds
, lvlItem
) < 0)
1730 nodeDS
= g_list_next( nodeDS
);
1732 if (addrindex_write_elem_e( fp
, lvlList
, iface
->listTag
) < 0)
1735 nodeIF
= g_list_next( nodeIF
);
1741 * Write data to specified file.
1742 * Enter: addrIndex Address index object.
1743 * newFile New file name.
1744 * return: Status code, from addrIndex->retVal.
1745 * Note: File will be created in directory specified by addrIndex.
1747 static gint
addrindex_write_to( AddressIndex
*addrIndex
, const gchar
*newFile
) {
1750 #ifndef DEV_STANDALONE
1754 cm_return_val_if_fail( addrIndex
!= NULL
, -1 );
1756 fileSpec
= g_strconcat( addrIndex
->filePath
, G_DIR_SEPARATOR_S
, newFile
, NULL
);
1757 addrIndex
->retVal
= MGU_OPEN_FILE
;
1758 #ifdef DEV_STANDALONE
1759 fp
= g_fopen( fileSpec
, "wb" );
1762 fputs( "<?xml version=\"1.0\" ?>\n", fp
);
1764 pfile
= prefs_write_open( fileSpec
);
1768 if (fprintf( fp
, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL
) < 0)
1771 if (addrindex_write_elem_s( fp
, 0, TAG_ADDRESS_INDEX
) < 0)
1773 if (fputs( ">\n", fp
) == EOF
)
1776 if (addrindex_write_index( addrIndex
, fp
) < 0)
1778 if (addrindex_write_elem_e( fp
, 0, TAG_ADDRESS_INDEX
) < 0)
1781 addrIndex
->retVal
= MGU_SUCCESS
;
1782 #ifdef DEV_STANDALONE
1785 if( prefs_file_close( pfile
) < 0 ) {
1786 addrIndex
->retVal
= MGU_ERROR_WRITE
;
1792 return addrIndex
->retVal
;
1794 g_warning("error writing AB index");
1795 addrIndex
->retVal
= MGU_ERROR_WRITE
;
1797 prefs_file_close_revert( pfile
);
1798 return addrIndex
->retVal
;
1802 * Save address index data to original file.
1803 * return: Status code, from addrIndex->retVal.
1805 gint
addrindex_save_data( AddressIndex
*addrIndex
) {
1811 cm_return_val_if_fail( addrIndex
!= NULL
, -1 );
1814 nodeIf
= addrIndex
->interfaceList
;
1815 /* save LDAP interfaces */
1817 AddressInterface
*iface
= nodeIf
->data
;
1818 if( iface
->type
== ADDR_IF_LDAP
) {
1819 nodeDS
= iface
->listSource
;
1821 AddressDataSource
*ds
= nodeDS
->data
;
1822 LdapServer
*abf
= ds
->rawDataSource
;
1823 if( ldapsvr_get_read_flag( abf
) ) {
1824 if( ldapsvr_get_modified( abf
) ) {
1825 ldapsvr_update_book( abf
, NULL
);
1826 if( abf
->retVal
!= LDAPRC_SUCCESS
) {
1827 alertpanel( _("Address(es) update"),
1828 _("Update failed. Changes not written to Directory."),
1829 GTK_STOCK_CLOSE
, NULL
, NULL
);
1832 abf
->retVal
= MGU_SUCCESS
;
1833 ldapsvr_set_modified( abf
, FALSE
);
1837 nodeDS
= g_list_next( nodeDS
);
1841 nodeIf
= g_list_next( nodeIf
);
1844 addrIndex
->retVal
= MGU_NO_FILE
;
1845 if( addrIndex
->fileName
== NULL
|| *addrIndex
->fileName
== '\0' ) return addrIndex
->retVal
;
1846 if( addrIndex
->filePath
== NULL
|| *addrIndex
->filePath
== '\0' ) return addrIndex
->retVal
;
1848 addrindex_write_to( addrIndex
, addrIndex
->fileName
);
1849 if( addrIndex
->retVal
== MGU_SUCCESS
) {
1850 addrIndex
->dirtyFlag
= FALSE
;
1852 return addrIndex
->retVal
;
1856 * Save all address book files which may have changed.
1857 * Return: Status code, set if there was a problem saving data.
1859 gint
addrindex_save_all_books( AddressIndex
*addrIndex
) {
1860 gint retVal
= MGU_SUCCESS
;
1861 GList
*nodeIf
, *nodeDS
;
1863 nodeIf
= addrIndex
->interfaceList
;
1865 AddressInterface
*iface
= nodeIf
->data
;
1866 if( iface
->type
== ADDR_IF_BOOK
) {
1867 nodeDS
= iface
->listSource
;
1869 AddressDataSource
*ds
= nodeDS
->data
;
1870 AddressBookFile
*abf
= ds
->rawDataSource
;
1871 if( addrbook_get_dirty( abf
) ) {
1872 if( addrbook_get_read_flag( abf
) ) {
1873 addrbook_save_data( abf
);
1874 if( abf
->retVal
!= MGU_SUCCESS
) {
1875 retVal
= abf
->retVal
;
1879 nodeDS
= g_list_next( nodeDS
);
1883 nodeIf
= g_list_next( nodeIf
);
1889 /* **********************************************************************
1890 * Address book conversion to new format.
1891 * ***********************************************************************
1894 #define ELTAG_IF_OLD_FOLDER "folder"
1895 #define ELTAG_IF_OLD_GROUP "group"
1896 #define ELTAG_IF_OLD_ITEM "item"
1897 #define ELTAG_IF_OLD_NAME "name"
1898 #define ELTAG_IF_OLD_ADDRESS "address"
1899 #define ELTAG_IF_OLD_REMARKS "remarks"
1900 #define ATTAG_IF_OLD_NAME "name"
1902 #define TEMPNODE_ROOT 0
1903 #define TEMPNODE_FOLDER 1
1904 #define TEMPNODE_GROUP 2
1905 #define TEMPNODE_ADDRESS 3
1907 typedef struct _AddressCvt_Node AddressCvtNode
;
1908 struct _AddressCvt_Node
{
1917 * Parse current address item.
1919 static AddressCvtNode
*addrindex_parse_item( XMLFile
*file
) {
1924 nn
= g_new0( AddressCvtNode
, 1 );
1925 nn
->type
= TEMPNODE_ADDRESS
;
1928 level
= file
->level
;
1931 xml_parse_next_tag(file
);
1932 if (file
->level
< level
) return nn
;
1934 element
= xml_get_element( file
);
1935 if( xml_compare_tag( file
, ELTAG_IF_OLD_NAME
) ) {
1936 nn
->name
= g_strdup( element
);
1938 if( xml_compare_tag( file
, ELTAG_IF_OLD_ADDRESS
) ) {
1939 nn
->address
= g_strdup( element
);
1941 if( xml_compare_tag( file
, ELTAG_IF_OLD_REMARKS
) ) {
1942 nn
->remarks
= g_strdup( element
);
1945 xml_parse_next_tag(file
);
1950 * Create a temporary node below specified node.
1952 static AddressCvtNode
*addrindex_add_object( AddressCvtNode
*node
, gint type
, gchar
*name
, gchar
*addr
, char *rem
) {
1954 nn
= g_new0( AddressCvtNode
, 1 );
1956 nn
->name
= g_strdup( name
);
1957 nn
->remarks
= g_strdup( rem
);
1958 node
->list
= g_list_append( node
->list
, nn
);
1963 * Process current temporary node.
1965 static void addrindex_add_obj( XMLFile
*file
, AddressCvtNode
*node
) {
1968 AddressCvtNode
*newNode
= NULL
;
1973 prev_level
= file
->level
;
1974 xml_parse_next_tag( file
);
1975 if (file
->level
< prev_level
) return;
1979 if( xml_compare_tag( file
, ELTAG_IF_OLD_GROUP
) ) {
1980 attr
= xml_get_current_tag_attr(file
);
1982 name
= ((XMLAttr
*)attr
->data
)->name
;
1983 if( strcmp( name
, ATTAG_IF_OLD_NAME
) == 0 ) {
1984 value
= ((XMLAttr
*)attr
->data
)->value
;
1987 newNode
= addrindex_add_object( node
, TEMPNODE_GROUP
, value
, "", "" );
1988 addrindex_add_obj( file
, newNode
);
1991 else if( xml_compare_tag( file
, ELTAG_IF_OLD_FOLDER
) ) {
1992 attr
= xml_get_current_tag_attr(file
);
1994 name
= ((XMLAttr
*)attr
->data
)->name
;
1995 if( strcmp( name
, ATTAG_IF_OLD_NAME
) == 0 ) {
1996 value
= ((XMLAttr
*)attr
->data
)->value
;
1999 newNode
= addrindex_add_object( node
, TEMPNODE_FOLDER
, value
, "", "" );
2000 addrindex_add_obj( file
, newNode
);
2002 else if( xml_compare_tag( file
, ELTAG_IF_OLD_ITEM
) ) {
2003 newNode
= addrindex_parse_item( file
);
2004 node
->list
= g_list_append( node
->list
, newNode
);
2007 g_warning("Invalid tag");
2013 * Consume all nodes below current tag.
2015 static void addrindex_consume_tree( XMLFile
*file
) {
2019 prev_level
= file
->level
;
2020 xml_parse_next_tag( file
);
2021 if (file
->level
< prev_level
)
2024 addrindex_consume_tree( file
);
2029 * Free up temporary tree.
2031 static void addrindex_free_node( AddressCvtNode
*node
) {
2032 GList
*list
= node
->list
;
2035 AddressCvtNode
*lNode
= list
->data
;
2036 list
= g_list_next( list
);
2037 addrindex_free_node( lNode
);
2039 node
->type
= TEMPNODE_ROOT
;
2040 g_free( node
->name
);
2041 g_free( node
->address
);
2042 g_free( node
->remarks
);
2043 g_list_free( node
->list
);
2048 * Process address book for specified node.
2050 static void addrindex_process_node(
2051 AddressBookFile
*abf
, AddressCvtNode
*node
, ItemFolder
*parent
,
2052 ItemGroup
*parentGrp
, ItemFolder
*folderGrp
)
2055 ItemFolder
*itemFolder
= NULL
;
2056 ItemGroup
*itemGParent
= parentGrp
;
2057 ItemFolder
*itemGFolder
= folderGrp
;
2058 AddressCache
*cache
= abf
->addressCache
;
2060 if( node
->type
== TEMPNODE_ROOT
) {
2061 itemFolder
= parent
;
2063 else if( node
->type
== TEMPNODE_FOLDER
) {
2064 itemFolder
= addritem_create_item_folder();
2065 addritem_folder_set_name( itemFolder
, node
->name
);
2066 addrcache_id_folder( cache
, itemFolder
);
2067 addrcache_folder_add_folder( cache
, parent
, itemFolder
);
2070 else if( node
->type
== TEMPNODE_GROUP
) {
2071 ItemGroup
*itemGroup
;
2074 /* Create a folder for group */
2075 fName
= g_strdup_printf( "Cvt - %s", node
->name
);
2076 itemGFolder
= addritem_create_item_folder();
2077 addritem_folder_set_name( itemGFolder
, fName
);
2078 addrcache_id_folder( cache
, itemGFolder
);
2079 addrcache_folder_add_folder( cache
, parent
, itemGFolder
);
2082 /* Add group into folder */
2083 itemGroup
= addritem_create_item_group();
2084 addritem_group_set_name( itemGroup
, node
->name
);
2085 addrcache_id_group( cache
, itemGroup
);
2086 addrcache_folder_add_group( cache
, itemGFolder
, itemGroup
);
2087 itemGParent
= itemGroup
;
2089 else if( node
->type
== TEMPNODE_ADDRESS
) {
2090 ItemPerson
*itemPerson
;
2091 ItemEMail
*itemEMail
;
2093 /* Create person and email objects */
2094 itemPerson
= addritem_create_item_person();
2095 addritem_person_set_common_name( itemPerson
, node
->name
);
2096 addrcache_id_person( cache
, itemPerson
);
2097 itemEMail
= addritem_create_item_email();
2098 addritem_email_set_address( itemEMail
, node
->address
);
2099 addritem_email_set_remarks( itemEMail
, node
->remarks
);
2100 addrcache_id_email( cache
, itemEMail
);
2101 addrcache_person_add_email( cache
, itemPerson
, itemEMail
);
2103 /* Add person into appropriate folder */
2105 addrcache_folder_add_person( cache
, itemGFolder
, itemPerson
);
2108 addrcache_folder_add_person( cache
, parent
, itemPerson
);
2111 /* Add email address only into group */
2113 addrcache_group_add_email( cache
, parentGrp
, itemEMail
);
2119 AddressCvtNode
*lNode
= list
->data
;
2120 list
= g_list_next( list
);
2121 addrindex_process_node( abf
, lNode
, itemFolder
, itemGParent
, itemGFolder
);
2126 * Process address book to specified file number.
2128 static gboolean
addrindex_process_book( AddressIndex
*addrIndex
, XMLFile
*file
, gchar
*displayName
) {
2129 gboolean retVal
= FALSE
;
2130 AddressBookFile
*abf
= NULL
;
2131 AddressCvtNode
*rootNode
= NULL
;
2132 gchar
*newFile
= NULL
;
2133 GList
*fileList
= NULL
;
2136 /* Setup root node */
2137 rootNode
= g_new0( AddressCvtNode
, 1 );
2138 rootNode
->type
= TEMPNODE_ROOT
;
2139 rootNode
->name
= g_strdup( "root" );
2140 rootNode
->list
= NULL
;
2141 addrindex_add_obj( file
, rootNode
);
2142 /* addrindex_print_node( rootNode, stdout ); */
2144 /* Create new address book */
2145 abf
= addrbook_create_book();
2146 addrbook_set_name( abf
, displayName
);
2147 addrbook_set_path( abf
, addrIndex
->filePath
);
2149 /* Determine next available file number */
2150 fileList
= addrbook_get_bookfile_list( abf
);
2152 fileNum
= 1 + abf
->maxValue
;
2154 g_list_free( fileList
);
2157 newFile
= addrbook_gen_new_file_name( fileNum
);
2159 addrbook_set_file( abf
, newFile
);
2162 addrindex_process_node( abf
, rootNode
, abf
->addressCache
->rootFolder
, NULL
, NULL
);
2164 /* addrbook_dump_book( abf, stdout ); */
2165 addrbook_save_data( abf
);
2166 addrIndex
->retVal
= abf
->retVal
;
2167 if( abf
->retVal
== MGU_SUCCESS
) retVal
= TRUE
;
2169 addrbook_free_book( abf
);
2171 addrindex_free_node( rootNode
);
2174 /* Create entries in address index */
2176 abf
= addrbook_create_book();
2177 addrbook_set_name( abf
, displayName
);
2178 addrbook_set_path( abf
, addrIndex
->filePath
);
2179 addrbook_set_file( abf
, newFile
);
2180 addrindex_index_add_datasource( addrIndex
, ADDR_IF_BOOK
, abf
);
2187 * Process tree converting data.
2189 static void addrindex_convert_tree( AddressIndex
*addrIndex
, XMLFile
*file
) {
2195 prev_level
= file
->level
;
2196 xml_parse_next_tag( file
);
2197 if (file
->level
< prev_level
) return;
2199 xtag
= xml_get_current_tag( file
);
2200 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2201 if( strcmp( xtag
->tag
, TAG_IF_OLD_COMMON
) == 0 ) {
2202 if( addrindex_process_book( addrIndex
, file
, DISP_OLD_COMMON
) ) {
2203 addrIndex
->needsConversion
= FALSE
;
2204 addrIndex
->wasConverted
= TRUE
;
2209 if( strcmp( xtag
->tag
, TAG_IF_OLD_PERSONAL
) == 0 ) {
2210 if( addrindex_process_book( addrIndex
, file
, DISP_OLD_PERSONAL
) ) {
2211 addrIndex
->needsConversion
= FALSE
;
2212 addrIndex
->wasConverted
= TRUE
;
2217 addrindex_consume_tree( file
);
2221 static gint
addrindex_convert_data( AddressIndex
*addrIndex
) {
2222 XMLFile
*file
= NULL
;
2225 fileSpec
= g_strconcat( addrIndex
->filePath
, G_DIR_SEPARATOR_S
, addrIndex
->fileName
, NULL
);
2226 addrIndex
->retVal
= MGU_NO_FILE
;
2227 file
= xml_open_file( fileSpec
);
2230 if( file
== NULL
) {
2231 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2232 return addrIndex
->retVal
;
2235 addrIndex
->retVal
= MGU_BAD_FORMAT
;
2236 if( xml_get_dtd( file
) == 0 ) {
2237 if( xml_parse_next_tag( file
) == 0 ) {
2238 if( xml_compare_tag( file
, TAG_ADDRESS_INDEX
) ) {
2239 addrindex_convert_tree( addrIndex
, file
);
2243 xml_close_file( file
);
2244 return addrIndex
->retVal
;
2248 * Create a new address book file.
2250 static gboolean
addrindex_create_new_book( AddressIndex
*addrIndex
, gchar
*displayName
) {
2251 gboolean retVal
= FALSE
;
2252 AddressBookFile
*abf
= NULL
;
2253 gchar
*newFile
= NULL
;
2254 GList
*fileList
= NULL
;
2257 /* Create new address book */
2258 abf
= addrbook_create_book();
2259 addrbook_set_name( abf
, displayName
);
2260 addrbook_set_path( abf
, addrIndex
->filePath
);
2262 /* Determine next available file number */
2263 fileList
= addrbook_get_bookfile_list( abf
);
2265 fileNum
= 1 + abf
->maxValue
;
2267 g_list_free( fileList
);
2270 newFile
= addrbook_gen_new_file_name( fileNum
);
2272 addrbook_set_file( abf
, newFile
);
2275 addrbook_save_data( abf
);
2276 addrIndex
->retVal
= abf
->retVal
;
2277 if( abf
->retVal
== MGU_SUCCESS
) retVal
= TRUE
;
2278 addrbook_free_book( abf
);
2281 /* Create entries in address index */
2283 abf
= addrbook_create_book();
2284 addrbook_set_name( abf
, displayName
);
2285 addrbook_set_path( abf
, addrIndex
->filePath
);
2286 addrbook_set_file( abf
, newFile
);
2287 addrindex_index_add_datasource( addrIndex
, ADDR_IF_BOOK
, abf
);
2294 * Read data for address index performing a conversion if necesary.
2295 * Enter: addrIndex Address index object.
2296 * return: Status code, from addrIndex->retVal.
2297 * Note: New address book files will be created in directory specified by
2298 * addrIndex. Three files will be created, for the following:
2299 * "Common addresses"
2300 * "Personal addresses"
2301 * "Gathered addresses" - a new address book.
2303 gint
addrindex_read_data( AddressIndex
*addrIndex
) {
2304 cm_return_val_if_fail( addrIndex
!= NULL
, -1 );
2306 addrIndex
->conversionError
= FALSE
;
2307 addrindex_read_file( addrIndex
);
2308 if( addrIndex
->retVal
== MGU_SUCCESS
) {
2309 if( addrIndex
->needsConversion
) {
2310 if( addrindex_convert_data( addrIndex
) == MGU_SUCCESS
)
2311 addrIndex
->conversionError
= FALSE
;
2313 addrIndex
->conversionError
= TRUE
;
2315 addrIndex
->dirtyFlag
= TRUE
;
2317 return addrIndex
->retVal
;
2321 * Create new address books for a new address index.
2322 * Enter: addrIndex Address index object.
2323 * return: Status code, from addrIndex->retVal.
2324 * Note: New address book files will be created in directory specified by
2325 * addrIndex. Three files will be created, for the following:
2326 * "Common addresses"
2327 * "Personal addresses"
2328 * "Gathered addresses" - a new address book.
2330 gint
addrindex_create_new_books( AddressIndex
*addrIndex
) {
2333 cm_return_val_if_fail( addrIndex
!= NULL
, -1 );
2335 flg
= addrindex_create_new_book( addrIndex
, DISP_NEW_COMMON
);
2337 flg
= addrindex_create_new_book( addrIndex
, DISP_NEW_PERSONAL
);
2338 addrIndex
->dirtyFlag
= TRUE
;
2340 return addrIndex
->retVal
;
2343 /* **********************************************************************
2344 * New interface stuff.
2345 * ***********************************************************************
2349 * Return modified flag for specified data source.
2351 gboolean
addrindex_ds_get_modify_flag( AddressDataSource
*ds
) {
2352 gboolean retVal
= FALSE
;
2353 AddressInterface
*iface
;
2355 if( ds
== NULL
) return retVal
;
2356 iface
= ds
->interface
;
2357 if( iface
== NULL
) return retVal
;
2358 if( iface
->getModifyFlag
) {
2359 retVal
= ( iface
->getModifyFlag
) ( ds
->rawDataSource
);
2365 * Return accessed flag for specified data source.
2367 gboolean
addrindex_ds_get_access_flag( AddressDataSource
*ds
) {
2368 gboolean retVal
= FALSE
;
2369 AddressInterface
*iface
;
2371 if( ds
== NULL
) return retVal
;
2372 iface
= ds
->interface
;
2373 if( iface
== NULL
) return retVal
;
2374 if( iface
->getAccessFlag
) {
2375 retVal
= ( iface
->getAccessFlag
) ( ds
->rawDataSource
);
2381 * Return data read flag for specified data source.
2383 gboolean
addrindex_ds_get_read_flag( AddressDataSource
*ds
) {
2384 gboolean retVal
= TRUE
;
2385 AddressInterface
*iface
;
2387 if( ds
== NULL
) return retVal
;
2388 iface
= ds
->interface
;
2389 if( iface
== NULL
) return retVal
;
2390 if( iface
->getReadFlag
) {
2391 retVal
= ( iface
->getReadFlag
) ( ds
->rawDataSource
);
2397 * Return status code for specified data source.
2399 gint
addrindex_ds_get_status_code( AddressDataSource
*ds
) {
2400 gint retVal
= MGU_SUCCESS
;
2401 AddressInterface
*iface
;
2403 if( ds
== NULL
) return retVal
;
2404 iface
= ds
->interface
;
2405 if( iface
== NULL
) return retVal
;
2406 if( iface
->getStatusCode
) {
2407 retVal
= ( iface
->getStatusCode
) ( ds
->rawDataSource
);
2413 * Return data read flag for specified data source.
2415 gint
addrindex_ds_read_data( AddressDataSource
*ds
) {
2416 gint retVal
= MGU_SUCCESS
;
2417 AddressInterface
*iface
;
2419 if( ds
== NULL
) return retVal
;
2420 iface
= ds
->interface
;
2421 if( iface
== NULL
) return retVal
;
2422 if( iface
->getReadData
) {
2424 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2425 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2427 retVal
= ( iface
->getReadData
) ( ds
->rawDataSource
);
2433 * Return data read flag for specified data source.
2435 ItemFolder
*addrindex_ds_get_root_folder( AddressDataSource
*ds
) {
2436 ItemFolder
*retVal
= NULL
;
2437 AddressInterface
*iface
;
2439 if( ds
== NULL
) return retVal
;
2440 iface
= ds
->interface
;
2441 if( iface
== NULL
) return retVal
;
2442 if( iface
->getRootFolder
) {
2443 retVal
= ( iface
->getRootFolder
) ( ds
->rawDataSource
);
2449 * Return name for specified data source.
2451 gchar
*addrindex_ds_get_name( AddressDataSource
*ds
) {
2452 gchar
*retVal
= FALSE
;
2453 AddressInterface
*iface
;
2455 if( ds
== NULL
) return retVal
;
2456 iface
= ds
->interface
;
2457 if( iface
== NULL
) return retVal
;
2458 if( iface
->getName
) {
2459 retVal
= ( iface
->getName
) ( ds
->rawDataSource
);
2465 * Set the access flag inside the data source.
2467 void addrindex_ds_set_access_flag( AddressDataSource
*ds
, gboolean
*value
) {
2468 AddressInterface
*iface
;
2470 if( ds
== NULL
) return;
2471 iface
= ds
->interface
;
2472 if( iface
== NULL
) return;
2473 if( iface
->setAccessFlag
) {
2474 ( iface
->setAccessFlag
) ( ds
->rawDataSource
, value
);
2479 * Return read only flag for specified data source.
2481 gboolean
addrindex_ds_get_readonly( AddressDataSource
*ds
) {
2482 AddressInterface
*iface
;
2483 if( ds
== NULL
) return TRUE
;
2484 iface
= ds
->interface
;
2485 if( iface
== NULL
) return TRUE
;
2486 return iface
->readOnly
;
2490 * Return list of all persons for specified data source.
2492 static GList
*addrindex_ds_get_all_persons( AddressDataSource
*ds
) {
2493 GList
*retVal
= NULL
;
2494 AddressInterface
*iface
;
2496 if( ds
== NULL
) return retVal
;
2497 iface
= ds
->interface
;
2498 if( iface
== NULL
) return retVal
;
2499 if( iface
->getAllPersons
) {
2500 retVal
= ( iface
->getAllPersons
) ( ds
->rawDataSource
);
2506 * Return list of all groups for specified data source.
2508 static GList
*addrindex_ds_get_all_groups( AddressDataSource
*ds
) {
2509 GList
*retVal
= NULL
;
2510 AddressInterface
*iface
;
2512 if( ds
== NULL
) return retVal
;
2513 iface
= ds
->interface
;
2514 if( iface
== NULL
) return retVal
;
2515 if( iface
->getAllGroups
) {
2516 retVal
= ( iface
->getAllGroups
) ( ds
->rawDataSource
);
2521 /* **********************************************************************
2522 * Address search stuff.
2523 * ***********************************************************************
2527 * Setup or register the dynamic search that will be performed. The search
2528 * is registered with the query manager.
2530 * \param searchTerm Search term. A private copy will be made.
2531 * \param callBackEntry Callback function that should be called when
2532 * each entry is received.
2533 * \param callBackEnd Callback function that should be called when
2534 * search has finished running.
2535 * \return ID allocated to query that will be executed.
2537 gint
addrindex_setup_search(
2538 const gchar
*searchTerm
, void *callBackEnd
, void *callBackEntry
)
2543 /* Set up a dynamic address query */
2544 req
= qrymgr_add_request( searchTerm
, callBackEnd
, callBackEntry
);
2545 queryID
= req
->queryID
;
2546 qryreq_set_search_type( req
, ADDRSEARCH_DYNAMIC
);
2548 /* g_print( "***> query ID ::%d::\n", queryID ); */
2555 * Function prototypes (not in header file or circular reference errors are
2558 LdapQuery
*ldapsvr_new_dynamic_search(
2559 LdapServer
*server
, QueryRequest
*req
);
2560 LdapQuery
*ldapsvr_new_explicit_search(
2561 LdapServer
*server
, QueryRequest
*req
, ItemFolder
*folder
);
2562 void ldapsvr_execute_query( LdapServer
*server
, LdapQuery
*qry
);
2567 * Execute the previously registered dynamic search.
2569 * \param req Address query object to execute.
2570 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2573 static gboolean
addrindex_start_dynamic( QueryRequest
*req
) {
2574 AddressInterface
*iface
;
2575 AddressDataSource
*ds
;
2580 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2581 nodeIf
= _addressIndex_
->searchOrder
;
2583 iface
= nodeIf
->data
;
2584 nodeIf
= g_list_next( nodeIf
);
2586 if( ! iface
->useInterface
) {
2589 if( ! iface
->externalQuery
) {
2594 nodeDS
= iface
->listSource
;
2597 nodeDS
= g_list_next( nodeDS
);
2599 if( type
== ADDR_IF_LDAP
) {
2603 server
= ds
->rawDataSource
;
2604 if( ! server
->searchFlag
) {
2607 if( ldapsvr_reuse_previous( server
, req
) ) {
2611 /* Start a new dynamic search */
2612 qry
= ldapsvr_new_dynamic_search( server
, req
);
2614 ldapsvr_execute_query( server
, qry
);
2624 * Stop the previously registered search.
2626 * \param queryID ID of search query to stop.
2628 void addrindex_stop_search( const gint queryID
){
2630 AddrQueryObject
*aqo
;
2633 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2634 /* If query ID does not match, search has not been setup */
2635 req
= qrymgr_find_request( queryID
);
2640 /* Stop all queries that were associated with request */
2641 node
= req
->queryList
;
2645 if( aqo
->queryType
== ADDRQUERY_LDAP
) {
2646 LdapQuery
*qry
= ( LdapQuery
* ) aqo
;
2647 ldapqry_set_stop_flag( qry
, TRUE
);
2651 node
= g_list_next( node
);
2654 /* Delete query request */
2655 qrymgr_delete_request( queryID
);
2659 * Setup or register the explicit search that will be performed. The search is
2660 * registered with the query manager.
2662 * \param ds Data source to search.
2663 * \param searchTerm Search term to locate.
2664 * \param folder Folder to receive search results; may be NULL.
2665 * \param callbackEnd Function to call when search has terminated.
2666 * \param callbackEntry Function to called for each entry processed.
2667 * \return ID allocated to query that will be executed.
2669 gint
addrindex_setup_explicit_search(
2670 AddressDataSource
*ds
, const gchar
*searchTerm
, ItemFolder
*folder
,
2671 void *callBackEnd
, void *callBackEntry
)
2678 /* Name the query */
2679 name
= g_strdup_printf( "Search '%s'", searchTerm
);
2681 /* Set up query request */
2682 if (!strcmp(searchTerm
, "*"))
2683 mySearch
= g_strdup("*@");
2685 mySearch
= g_strdup(searchTerm
);
2687 req
= qrymgr_add_request( mySearch
, callBackEnd
, callBackEntry
);
2691 qryreq_set_search_type( req
, ADDRSEARCH_EXPLICIT
);
2692 queryID
= req
->queryID
;
2694 if( ds
->type
== ADDR_IF_LDAP
) {
2698 server
= ds
->rawDataSource
;
2699 ldapsvr_new_explicit_search( server
, req
, folder
);
2703 qrymgr_delete_request( queryID
);
2712 * Execute the previously registered explicit search.
2714 * \param req Address query request object to execute.
2715 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2718 static gboolean
addrindex_start_explicit( QueryRequest
*req
) {
2720 AddrQueryObject
*aqo
;
2724 /* Note: there should only be one query in the list. */
2725 aqo
= req
->queryList
->data
;
2727 if( aqo
->queryType
== ADDRQUERY_LDAP
) {
2731 qry
= ( LdapQuery
* ) aqo
;
2732 server
= qry
->server
;
2734 /* Start the search */
2736 ldapsvr_execute_query( server
, qry
);
2743 * Start the previously registered search.
2745 * \param queryID ID of search query to be executed.
2746 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2749 gboolean
addrindex_start_search( const gint queryID
) {
2752 AddrSearchType searchType
;
2755 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2756 req
= qrymgr_find_request( queryID
);
2761 searchType
= req
->searchType
;
2762 if( searchType
== ADDRSEARCH_DYNAMIC
) {
2763 retVal
= addrindex_start_dynamic( req
);
2765 else if( searchType
== ADDRSEARCH_EXPLICIT
) {
2766 retVal
= addrindex_start_explicit( req
);
2773 * Remove results (folder and data) for specified data source and folder.
2774 * \param ds Data source to process.
2775 * \param folder Results folder to remove.
2777 void addrindex_remove_results( AddressDataSource
*ds
, ItemFolder
*folder
) {
2778 AddrBookBase
*adbase
;
2781 /* g_print( "addrindex_remove_results/start\n" ); */
2783 /* Test for folder */
2784 if( folder
->folderType
!= ADDRFOLDER_QUERY_RESULTS
) return;
2785 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2786 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
2787 if( adbase
== NULL
) return;
2789 /* Hide folder to prevent re-display */
2790 addritem_folder_set_hidden( folder
, TRUE
);
2792 if( ds
->type
== ADDR_IF_LDAP
) {
2797 qry
= ( LdapQuery
* ) folder
->folderData
;
2798 queryID
= ADDRQUERY_ID(qry
);
2799 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2800 delFlag
= ldapquery_remove_results( qry
);
2802 ldapqry_free( qry
);
2804 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2807 g_print( "delFlag IS-TRUE\n" );
2810 g_print( "delFlag IS-FALSE\n" );
2815 /* g_print( "addrindex_remove_results/end\n" ); */
2817 /* Delete query request */
2819 qrymgr_delete_request( queryID
);
2823 /* **********************************************************************
2824 * Address completion stuff.
2825 * ***********************************************************************
2828 static void addrindex_load_completion_load_persons(
2829 gint (*callBackFunc
) ( const gchar
*, const gchar
*,
2830 const gchar
*, const gchar
*, GList
* ),
2831 AddressDataSource
*ds
)
2833 GList
*listP
, *nodeP
;
2837 /* Read address book */
2838 if( addrindex_ds_get_modify_flag( ds
) ) {
2839 addrindex_ds_read_data( ds
);
2842 if( ! addrindex_ds_get_read_flag( ds
) ) {
2843 addrindex_ds_read_data( ds
);
2846 /* Get all groups */
2847 listP
= addrindex_ds_get_all_groups( ds
);
2850 ItemGroup
*group
= nodeP
->data
;
2851 GList
*emails
= NULL
;
2852 for (nodeM
= group
->listEMail
; nodeM
; nodeM
= g_list_next(nodeM
)) {
2853 ItemEMail
*email
= nodeM
->data
;
2855 emails
= g_list_append(emails
, email
);
2857 callBackFunc( ((AddrItemObject
*)group
)->name
, NULL
,
2858 NULL
, NULL
, emails
);
2859 nodeP
= g_list_next( nodeP
);
2862 /* Free up the list */
2863 g_list_free( listP
);
2864 /* Get all persons */
2865 listP
= addrindex_ds_get_all_persons( ds
);
2868 ItemPerson
*person
= nodeP
->data
;
2869 nodeM
= person
->listEMail
;
2871 /* Figure out name to use */
2872 sName
= ADDRITEM_NAME(person
);
2873 if( sName
== NULL
|| *sName
== '\0' ) {
2874 sName
= person
->nickName
;
2877 /* Process each E-Mail address */
2879 ItemEMail
*email
= nodeM
->data
;
2881 callBackFunc( sName
, email
->address
, person
->nickName
,
2882 ADDRITEM_NAME(email
), NULL
);
2884 nodeM
= g_list_next( nodeM
);
2886 nodeP
= g_list_next( nodeP
);
2889 /* Free up the list */
2890 g_list_free( listP
);
2894 * This function is used by the address completion function to load
2895 * addresses for all non-external address book interfaces.
2897 * \param callBackFunc Function to be called when an address is
2899 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2900 * or "Any", assume the whole addressbook
2901 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2904 gboolean
addrindex_load_completion(
2905 gint (*callBackFunc
) ( const gchar
*, const gchar
*,
2906 const gchar
*, const gchar
*, GList
* ),
2909 GList
*nodeIf
, *nodeDS
;
2911 if( folderpath
!= NULL
) {
2912 AddressDataSource
*book
;
2915 /* split the folder path we've received, we'll try to match this path, subpath by
2916 subpath against the book/folder structure in order and restrict loading of
2917 addresses to that subpart (if matches). book/folder path must exist and
2918 folderpath must not be empty or NULL */
2920 if( ! addressbook_peek_folder_exists( folderpath
, &book
, &folder
) ) {
2921 g_warning("addrindex_load_completion: folder path '%s' doesn't exist", folderpath
);
2925 if( folder
!= NULL
) {
2932 debug_print("addrindex_load_completion: folder %p '%s'\n", folder
, folder
->obj
.name
);
2934 /* Load email addresses */
2935 items
= addritem_folder_get_person_list( folder
);
2936 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
2937 person
= items
->data
;
2938 nodeM
= person
->listEMail
;
2940 /* Figure out name to use */
2941 sName
= ADDRITEM_NAME(person
);
2942 if( sName
== NULL
|| *sName
== '\0' ) {
2943 sName
= person
->nickName
;
2946 /* Process each E-Mail address */
2948 ItemEMail
*email
= nodeM
->data
;
2950 callBackFunc( sName
, email
->address
, person
->nickName
,
2951 ADDRITEM_NAME(email
), NULL
);
2953 nodeM
= g_list_next( nodeM
);
2956 /* Free up the list */
2957 mgu_clear_list( items
);
2958 g_list_free( items
);
2964 if( book
!= NULL
) {
2966 AddressBookFile
*abf
= book
->rawDataSource
;
2968 debug_print("addrindex_load_completion: book %p '%s'\n", book
, abf
?abf
->fileName
:"(null)");
2970 addrindex_load_completion_load_persons( callBackFunc
, book
);
2975 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer");
2982 nodeIf
= addrindex_get_interface_list( _addressIndex_
);
2984 AddressInterface
*iface
= nodeIf
->data
;
2986 nodeIf
= g_list_next( nodeIf
);
2988 if( ! iface
->useInterface
|| iface
->externalQuery
)
2991 nodeDS
= iface
->listSource
;
2993 addrindex_load_completion_load_persons( callBackFunc
, nodeDS
->data
);
2994 nodeDS
= g_list_next( nodeDS
);
3003 * This function can be used to collect information about
3004 * addressbook entries that contain a specific attribute.
3006 * \param attr Name of attribute to look for
3007 * \param callBackFunc Function to be called when a matching attribute was found
3008 * \return <i>TRUE</i>
3010 gboolean
addrindex_load_person_attribute(
3012 gint (*callBackFunc
) ( ItemPerson
*, const gchar
* ) )
3014 AddressDataSource
*ds
;
3015 GList
*nodeIf
, *nodeDS
;
3016 GList
*listP
, *nodeP
;
3019 nodeIf
= addrindex_get_interface_list( _addressIndex_
);
3022 AddressInterface
*iface
= nodeIf
->data
;
3024 nodeIf
= g_list_next( nodeIf
);
3026 if( ! iface
->useInterface
|| iface
->externalQuery
)
3029 nodeDS
= iface
->listSource
;
3033 /* Read address book */
3034 if( addrindex_ds_get_modify_flag( ds
) ) {
3035 addrindex_ds_read_data( ds
);
3038 if( ! addrindex_ds_get_read_flag( ds
) ) {
3039 addrindex_ds_read_data( ds
);
3042 /* Check addressbook name */
3043 cur_bname
= addrindex_ds_get_name( ds
);
3045 /* Get all persons */
3046 listP
= addrindex_ds_get_all_persons( ds
);
3049 ItemPerson
*person
= nodeP
->data
;
3051 /* Return all ItemPerson's if attr is NULL */
3052 if( attr
== NULL
) {
3053 callBackFunc(person
, cur_bname
);
3056 /* Return ItemPerson's with specific attribute */
3058 nodeA
= person
->listAttrib
;
3059 /* Process each User Attribute */
3061 UserAttribute
*attrib
= nodeA
->data
;
3063 !strcmp( attrib
->name
,attr
) ) {
3064 callBackFunc(person
, cur_bname
);
3066 nodeA
= g_list_next( nodeA
);
3069 nodeP
= g_list_next( nodeP
);
3071 /* Free up the list */
3072 g_list_free( listP
);
3074 nodeDS
= g_list_next( nodeDS
);
3081 * This function can be used to collect information about
3082 * addressbook entries
3084 * \param callBackFunc Function to be called for each ItemPerson
3085 * \return <i>TRUE</i>
3087 gboolean
addrindex_load_person_ds( gint (*callBackFunc
)
3088 ( ItemPerson
*, AddressDataSource
* ) )
3090 AddressDataSource
*ds
;
3091 GList
*nodeIf
, *nodeDS
;
3092 GList
*listP
, *nodeP
;
3094 nodeIf
= addrindex_get_interface_list( _addressIndex_
);
3096 AddressInterface
*iface
= nodeIf
->data
;
3098 nodeIf
= g_list_next( nodeIf
);
3100 if( ! iface
->useInterface
|| iface
->externalQuery
)
3103 nodeDS
= iface
->listSource
;
3107 /* Read address book */
3108 if( addrindex_ds_get_modify_flag( ds
) ) {
3109 addrindex_ds_read_data( ds
);
3112 if( ! addrindex_ds_get_read_flag( ds
) ) {
3113 addrindex_ds_read_data( ds
);
3116 /* Get all persons */
3117 listP
= addrindex_ds_get_all_persons( ds
);
3120 ItemPerson
*person
= nodeP
->data
;
3122 callBackFunc(person
, ds
);
3123 nodeP
= g_list_next( nodeP
);
3125 /* Free up the list */
3126 g_list_free( listP
);
3128 nodeDS
= g_list_next( nodeDS
);
3134 gchar
*addrindex_get_picture_file(const gchar
*emailaddr
)
3136 AddressDataSource
*ds
;
3137 GList
*nodeIf
, *nodeDS
;
3138 GList
*listP
, *nodeP
;
3139 gboolean found
= FALSE
;
3140 gchar
*filename
= NULL
;
3141 gchar
*raw_addr
= NULL
;
3146 Xstrdup_a(raw_addr
, emailaddr
, return NULL
);
3147 extract_address(raw_addr
);
3149 nodeIf
= addrindex_get_interface_list( _addressIndex_
);
3151 AddressInterface
*iface
= nodeIf
->data
;
3153 nodeIf
= g_list_next( nodeIf
);
3155 if( ! iface
->useInterface
|| iface
->externalQuery
)
3158 nodeDS
= iface
->listSource
;
3159 while( nodeDS
&& !found
) {
3162 /* Read address book */
3163 if( addrindex_ds_get_modify_flag( ds
) ) {
3164 addrindex_ds_read_data( ds
);
3167 if( ! addrindex_ds_get_read_flag( ds
) ) {
3168 addrindex_ds_read_data( ds
);
3171 /* Get all persons */
3172 listP
= addrindex_ds_get_all_persons( ds
);
3176 ItemPerson
*person
= nodeP
->data
;
3177 nodeM
= person
->listEMail
;
3179 ItemEMail
*email
= nodeM
->data
;
3180 if (email
->address
&& !strcasecmp(raw_addr
, email
->address
)) {
3182 filename
= g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S
,
3183 ADDRBOOK_DIR
, G_DIR_SEPARATOR_S
,
3184 person
->picture
, ".png", NULL
);
3187 nodeM
= nodeM
->next
;
3189 nodeP
= g_list_next( nodeP
);
3191 /* Free up the list */
3192 g_list_free( listP
);
3194 nodeDS
= g_list_next( nodeDS
);