2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2007 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.
31 #include <glib/gi18n.h>
35 #include "addrcache.h"
37 #include "addressbook.h"
38 #include "addrindex.h"
40 #include "addrquery.h"
41 #include "addr_compl.h"
43 #include "alertpanel.h"
45 #ifndef DEV_STANDALONE
46 #include "prefs_gtk.h"
57 #include "ldapserver.h"
59 #include "ldapquery.h"
60 #include "ldapupdate.h"
64 #define TAG_ADDRESS_INDEX "addressbook"
66 #define TAG_IF_ADDRESS_BOOK "book_list"
67 #define TAG_IF_VCARD "vcard_list"
68 #define TAG_IF_JPILOT "jpilot_list"
69 #define TAG_IF_LDAP "ldap_list"
71 #define TAG_DS_ADDRESS_BOOK "book"
72 #define TAG_DS_VCARD "vcard"
73 #define TAG_DS_JPILOT "jpilot"
74 #define TAG_DS_LDAP "server"
76 /* XML Attribute names */
77 #define ATTAG_BOOK_NAME "name"
78 #define ATTAG_BOOK_FILE "file"
80 #define ATTAG_VCARD_NAME "name"
81 #define ATTAG_VCARD_FILE "file"
83 #define ATTAG_JPILOT_NAME "name"
84 #define ATTAG_JPILOT_FILE "file"
85 #define ATTAG_JPILOT_CUSTOM_1 "custom-1"
86 #define ATTAG_JPILOT_CUSTOM_2 "custom-2"
87 #define ATTAG_JPILOT_CUSTOM_3 "custom-3"
88 #define ATTAG_JPILOT_CUSTOM_4 "custom-4"
89 #define ATTAG_JPILOT_CUSTOM "custom-"
91 #define ATTAG_LDAP_NAME "name"
92 #define ATTAG_LDAP_HOST "host"
93 #define ATTAG_LDAP_PORT "port"
94 #define ATTAG_LDAP_BASE_DN "base-dn"
95 #define ATTAG_LDAP_BIND_DN "bind-dn"
96 #define ATTAG_LDAP_BIND_PASS "bind-pass"
97 #define ATTAG_LDAP_CRITERIA "criteria"
98 #define ATTAG_LDAP_MAX_ENTRY "max-entry"
99 #define ATTAG_LDAP_TIMEOUT "timeout"
100 #define ATTAG_LDAP_MAX_AGE "max-age"
101 #define ATTAG_LDAP_DYN_SEARCH "dyn-search"
102 #define ATTAG_LDAP_MATCH_OPT "match-opt"
103 #define ATTAG_LDAP_ENABLE_TLS "enable-tls"
104 #define ATTAG_LDAP_ENABLE_SSL "enable-ssl"
106 #define ELTAG_LDAP_ATTR_SRCH "attribute"
107 #define ATTAG_LDAP_ATTR_NAME "name"
109 /* Attribute values */
110 #define ATVAL_BOOLEAN_YES "yes"
111 #define ATVAL_BOOLEAN_NO "no"
112 #define ATVAL_LDAP_MATCH_BEGIN "begin-with"
113 #define ATVAL_LDAP_MATCH_CONTAINS "contains"
116 #define ATTAG_LDAP_DEFAULT "default"
118 #define DISP_NEW_COMMON _("Common addresses")
119 #define DISP_NEW_PERSONAL _("Personal addresses")
121 /* Old address book */
122 #define TAG_IF_OLD_COMMON "common_address"
123 #define TAG_IF_OLD_PERSONAL "personal_address"
125 #define DISP_OLD_COMMON _("Common address")
126 #define DISP_OLD_PERSONAL _("Personal address")
131 static AddressIndex
*_addressIndex_
= NULL
;
134 * Define attribute name-value pair.
136 typedef struct _AddressIfAttr AddressIfAttrib
;
137 struct _AddressIfAttr
{
142 static AddressDataSource
*addrindex_create_datasource ( AddressIfType ifType
);
144 static GList
*addrindex_ds_get_all_persons ( AddressDataSource
*ds
);
145 static GList
*addrindex_ds_get_all_groups ( AddressDataSource
*ds
);
146 static AddressDataSource
*addrindex_get_datasource ( AddressIndex
*addrIndex
,
147 const gchar
*cacheID
);
148 static AddressInterface
*addrindex_get_interface ( AddressIndex
*addrIndex
,
149 AddressIfType ifType
);
150 static gint
addrindex_write_to ( AddressIndex
*addrIndex
,
151 const gchar
*newFile
);
154 * Define DOM fragment.
156 typedef struct _AddressIfFrag AddressIfFragment
;
157 struct _AddressIfFrag
{
164 * Build interface with default values.
166 * \param type Interface type.
167 * \param name Interface name.
168 * \param tagIf XML tag name for interface in address index file.
169 * \param tagDS XML tag name for datasource in address index file.
170 * \return Address interface object.
172 static AddressInterface
*addrindex_create_interface(
173 gint type
, gchar
*name
, gchar
*tagIf
, gchar
*tagDS
)
175 AddressInterface
*iface
= g_new0( AddressInterface
, 1 );
177 ADDRITEM_TYPE(iface
) = ITEMTYPE_INTERFACE
;
178 ADDRITEM_ID(iface
) = NULL
;
179 ADDRITEM_NAME(iface
) = g_strdup( name
);
180 ADDRITEM_PARENT(iface
) = NULL
;
181 ADDRITEM_SUBTYPE(iface
) = type
;
183 iface
->name
= g_strdup( name
);
184 iface
->listTag
= g_strdup( tagIf
);
185 iface
->itemTag
= g_strdup( tagDS
);
186 iface
->legacyFlag
= FALSE
;
187 iface
->haveLibrary
= TRUE
;
188 iface
->useInterface
= TRUE
;
189 iface
->readOnly
= TRUE
;
191 /* Set callbacks to NULL values - override for each interface */
192 iface
->getAccessFlag
= NULL
;
193 iface
->getModifyFlag
= NULL
;
194 iface
->getReadFlag
= NULL
;
195 iface
->getStatusCode
= NULL
;
196 iface
->getReadData
= NULL
;
197 iface
->getRootFolder
= NULL
;
198 iface
->getListFolder
= NULL
;
199 iface
->getListPerson
= NULL
;
200 iface
->getAllPersons
= NULL
;
201 iface
->getAllGroups
= NULL
;
202 iface
->getName
= NULL
;
203 iface
->listSource
= NULL
;
206 iface
->externalQuery
= FALSE
;
207 iface
->searchOrder
= 0; /* Ignored */
208 iface
->startSearch
= NULL
;
209 iface
->stopSearch
= NULL
;
215 * Build table of of all address book interfaces.
216 * \param addrIndex Address index object.
218 static void addrindex_build_if_list( AddressIndex
*addrIndex
) {
219 AddressInterface
*iface
;
221 /* Create intrinsic XML address book interface */
222 iface
= addrindex_create_interface(
223 ADDR_IF_BOOK
, "Address Book", TAG_IF_ADDRESS_BOOK
,
224 TAG_DS_ADDRESS_BOOK
);
225 iface
->readOnly
= FALSE
;
226 iface
->getModifyFlag
= ( void * ) addrbook_get_modified
;
227 iface
->getAccessFlag
= ( void * ) addrbook_get_accessed
;
228 iface
->getReadFlag
= ( void * ) addrbook_get_read_flag
;
229 iface
->getStatusCode
= ( void * ) addrbook_get_status
;
230 iface
->getReadData
= ( void * ) addrbook_read_data
;
231 iface
->getRootFolder
= ( void * ) addrbook_get_root_folder
;
232 iface
->getListFolder
= ( void * ) addrbook_get_list_folder
;
233 iface
->getListPerson
= ( void * ) addrbook_get_list_person
;
234 iface
->getAllPersons
= ( void * ) addrbook_get_all_persons
;
235 iface
->getAllGroups
= ( void * ) addrbook_get_all_groups
;
236 iface
->getName
= ( void * ) addrbook_get_name
;
237 iface
->setAccessFlag
= ( void * ) addrbook_set_accessed
;
238 iface
->searchOrder
= 0;
240 /* Add to list of interfaces in address book */
241 addrIndex
->interfaceList
=
242 g_list_append( addrIndex
->interfaceList
, iface
);
243 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
245 /* Create vCard interface */
246 iface
= addrindex_create_interface(
247 ADDR_IF_VCARD
, "vCard", TAG_IF_VCARD
, TAG_DS_VCARD
);
248 iface
->getModifyFlag
= ( void * ) vcard_get_modified
;
249 iface
->getAccessFlag
= ( void * ) vcard_get_accessed
;
250 iface
->getReadFlag
= ( void * ) vcard_get_read_flag
;
251 iface
->getStatusCode
= ( void * ) vcard_get_status
;
252 iface
->getReadData
= ( void * ) vcard_read_data
;
253 iface
->getRootFolder
= ( void * ) vcard_get_root_folder
;
254 iface
->getListFolder
= ( void * ) vcard_get_list_folder
;
255 iface
->getListPerson
= ( void * ) vcard_get_list_person
;
256 iface
->getAllPersons
= ( void * ) vcard_get_all_persons
;
257 iface
->getName
= ( void * ) vcard_get_name
;
258 iface
->setAccessFlag
= ( void * ) vcard_set_accessed
;
259 iface
->searchOrder
= 0;
260 addrIndex
->interfaceList
=
261 g_list_append( addrIndex
->interfaceList
, iface
);
262 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
264 /* Create JPilot interface */
265 iface
= addrindex_create_interface(
266 ADDR_IF_JPILOT
, "J-Pilot", TAG_IF_JPILOT
,
269 iface
->haveLibrary
= jpilot_test_pilot_lib();
270 iface
->useInterface
= iface
->haveLibrary
;
271 iface
->getModifyFlag
= ( void * ) jpilot_get_modified
;
272 iface
->getAccessFlag
= ( void * ) jpilot_get_accessed
;
273 iface
->getReadFlag
= ( void * ) jpilot_get_read_flag
;
274 iface
->getStatusCode
= ( void * ) jpilot_get_status
;
275 iface
->getReadData
= ( void * ) jpilot_read_data
;
276 iface
->getRootFolder
= ( void * ) jpilot_get_root_folder
;
277 iface
->getListFolder
= ( void * ) jpilot_get_list_folder
;
278 iface
->getListPerson
= ( void * ) jpilot_get_list_person
;
279 iface
->getAllPersons
= ( void * ) jpilot_get_all_persons
;
280 iface
->getName
= ( void * ) jpilot_get_name
;
281 iface
->setAccessFlag
= ( void * ) jpilot_set_accessed
;
282 iface
->searchOrder
= 0;
284 iface
->useInterface
= FALSE
;
285 iface
->haveLibrary
= FALSE
;
287 addrIndex
->interfaceList
=
288 g_list_append( addrIndex
->interfaceList
, iface
);
289 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
291 /* Create LDAP interface */
292 iface
= addrindex_create_interface(
293 ADDR_IF_LDAP
, "LDAP", TAG_IF_LDAP
, TAG_DS_LDAP
);
295 iface
->readOnly
= FALSE
;
296 /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
297 iface
->haveLibrary
= ldaputil_test_ldap_lib();
298 iface
->useInterface
= iface
->haveLibrary
;
299 iface
->getModifyFlag
= ( void * ) ldapsvr_get_modified
;
300 iface
->getAccessFlag
= ( void * ) ldapsvr_get_accessed
;
301 iface
->getReadFlag
= ( void * ) ldapsvr_get_read_flag
;
302 iface
->getStatusCode
= ( void * ) ldapsvr_get_status
;
303 iface
->getReadData
= ( void * ) ldapsvr_read_data
;
304 iface
->getRootFolder
= ( void * ) ldapsvr_get_root_folder
;
305 iface
->getListFolder
= ( void * ) ldapsvr_get_list_folder
;
306 iface
->getListPerson
= ( void * ) ldapsvr_get_list_person
;
307 iface
->getName
= ( void * ) ldapsvr_get_name
;
308 iface
->setAccessFlag
= ( void * ) ldapsvr_set_accessed
;
309 iface
->externalQuery
= TRUE
;
310 iface
->searchOrder
= 1;
312 iface
->useInterface
= FALSE
;
313 iface
->haveLibrary
= FALSE
;
315 addrIndex
->interfaceList
=
316 g_list_append( addrIndex
->interfaceList
, iface
);
317 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
319 /* Two old legacy data sources (pre 0.7.0) */
320 iface
= addrindex_create_interface(
321 ADDR_IF_COMMON
, "Old Address - common",
322 TAG_IF_OLD_COMMON
, NULL
);
323 iface
->legacyFlag
= TRUE
;
324 addrIndex
->interfaceList
=
325 g_list_append( addrIndex
->interfaceList
, iface
);
326 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
328 iface
= addrindex_create_interface(
329 ADDR_IF_COMMON
, "Old Address - personal",
330 TAG_IF_OLD_PERSONAL
, NULL
);
331 iface
->legacyFlag
= TRUE
;
332 addrIndex
->interfaceList
=
333 g_list_append( addrIndex
->interfaceList
, iface
);
334 ADDRITEM_PARENT(iface
) = ADDRITEM_OBJECT(addrIndex
);
340 * \param fragment Fragment to free.
342 static void addrindex_free_fragment( AddressIfFragment
*fragment
) {
346 node
= fragment
->children
;
348 AddressIfFragment
*child
= node
->data
;
349 addrindex_free_fragment( child
);
351 node
= g_list_next( node
);
353 g_list_free( fragment
->children
);
355 /* Free attributes */
356 node
= fragment
->attributes
;
358 AddressIfAttrib
*nv
= node
->data
;
363 node
= g_list_next( node
);
365 g_list_free( fragment
->attributes
);
367 g_free( fragment
->name
);
368 fragment
->name
= NULL
;
369 fragment
->attributes
= NULL
;
370 fragment
->children
= NULL
;
376 * Create a new data source.
377 * \param ifType Interface type to create.
378 * \return Initialized data source.
380 AddressDataSource
*addrindex_create_datasource( AddressIfType ifType
) {
381 AddressDataSource
*ds
= g_new0( AddressDataSource
, 1 );
383 ADDRITEM_TYPE(ds
) = ITEMTYPE_DATASOURCE
;
384 ADDRITEM_ID(ds
) = NULL
;
385 ADDRITEM_NAME(ds
) = NULL
;
386 ADDRITEM_PARENT(ds
) = NULL
;
387 ADDRITEM_SUBTYPE(ds
) = 0;
389 ds
->rawDataSource
= NULL
;
390 ds
->interface
= NULL
;
395 * Free up data source.
396 * \param ds Data source to free.
398 void addrindex_free_datasource( AddressDataSource
*ds
) {
399 AddressInterface
*iface
;
401 g_return_if_fail( ds
!= NULL
);
403 iface
= ds
->interface
;
404 if( ds
->rawDataSource
!= NULL
) {
405 if( iface
!= NULL
) {
406 if( iface
->useInterface
) {
407 if( iface
->type
== ADDR_IF_BOOK
) {
408 AddressBookFile
*abf
= ds
->rawDataSource
;
409 addrbook_free_book( abf
);
411 else if( iface
->type
== ADDR_IF_VCARD
) {
412 VCardFile
*vcf
= ds
->rawDataSource
;
416 else if( iface
->type
== ADDR_IF_JPILOT
) {
417 JPilotFile
*jpf
= ds
->rawDataSource
;
422 else if( iface
->type
== ADDR_IF_LDAP
) {
423 LdapServer
*server
= ds
->rawDataSource
;
424 ldapsvr_free( server
);
431 AddressIfFragment
*fragment
= ds
->rawDataSource
;
432 addrindex_free_fragment( fragment
);
437 ADDRITEM_TYPE(ds
) = ITEMTYPE_NONE
;
438 ADDRITEM_ID(ds
) = NULL
;
439 ADDRITEM_NAME(ds
) = NULL
;
440 ADDRITEM_PARENT(ds
) = NULL
;
441 ADDRITEM_SUBTYPE(ds
) = 0;
442 ds
->type
= ADDR_IF_NONE
;
443 ds
->interface
= NULL
;
444 ds
->rawDataSource
= NULL
;
450 * Free up all data sources for specified interface.
451 * \param iface Address interface to process.
453 static void addrindex_free_all_datasources( AddressInterface
*iface
) {
454 GList
*node
= iface
->listSource
;
456 AddressDataSource
*ds
= node
->data
;
457 addrindex_free_datasource( ds
);
459 node
= g_list_next( node
);
464 * Free up specified interface.
465 * \param iface Interface to process.
467 static void addrindex_free_interface( AddressInterface
*iface
) {
468 /* Free up data sources */
469 addrindex_free_all_datasources( iface
);
470 g_list_free( iface
->listSource
);
472 /* Free internal storage */
473 g_free( ADDRITEM_ID(iface
) );
474 g_free( ADDRITEM_NAME(iface
) );
475 g_free( iface
->name
);
476 g_free( iface
->listTag
);
477 g_free( iface
->itemTag
);
479 /* Clear all pointers */
480 ADDRITEM_TYPE(iface
) = ITEMTYPE_NONE
;
481 ADDRITEM_ID(iface
) = NULL
;
482 ADDRITEM_NAME(iface
) = NULL
;
483 ADDRITEM_PARENT(iface
) = NULL
;
484 ADDRITEM_SUBTYPE(iface
) = 0;
485 iface
->type
= ADDR_IF_NONE
;
487 iface
->listTag
= NULL
;
488 iface
->itemTag
= NULL
;
489 iface
->legacyFlag
= FALSE
;
490 iface
->useInterface
= FALSE
;
491 iface
->haveLibrary
= FALSE
;
492 iface
->listSource
= NULL
;
495 iface
->searchOrder
= 0;
496 iface
->startSearch
= NULL
;
497 iface
->stopSearch
= NULL
;
503 * Return cache ID for specified data source.
505 * \param addrIndex Address index.
506 * \param ds Data source.
507 * \return ID or NULL if not found. This should be <code>g_free()</code>
510 gchar
*addrindex_get_cache_id( AddressIndex
*addrIndex
, AddressDataSource
*ds
) {
511 gchar
*cacheID
= NULL
;
512 AddrBookBase
*adbase
;
515 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
516 g_return_val_if_fail( ds
!= NULL
, NULL
);
518 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
520 cache
= adbase
->addressCache
;
522 cacheID
= g_strdup( cache
->cacheID
);
530 * Return reference to data source for specified cacheID.
531 * \param addrIndex Address index.
533 * \return Data source, or NULL if not found.
535 static AddressDataSource
*addrindex_get_datasource(
536 AddressIndex
*addrIndex
, const gchar
*cacheID
)
538 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
539 g_return_val_if_fail( cacheID
!= NULL
, NULL
);
540 return ( AddressDataSource
* ) g_hash_table_lookup( addrIndex
->hashCache
, cacheID
);
544 * Return reference to address cache for specified cacheID.
545 * \param addrIndex Address index.
547 * \return Address cache, or NULL if not found.
549 AddressCache
*addrindex_get_cache( AddressIndex
*addrIndex
, const gchar
*cacheID
) {
550 AddressDataSource
*ds
;
551 AddrBookBase
*adbase
;
554 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
555 g_return_val_if_fail( cacheID
!= NULL
, NULL
);
558 ds
= addrindex_get_datasource( addrIndex
, cacheID
);
560 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
561 cache
= adbase
->addressCache
;
567 * Add data source into hash table.
568 * \param addrIndex Address index.
569 * \param ds Data source.
571 static void addrindex_hash_add_cache(
572 AddressIndex
*addrIndex
, AddressDataSource
*ds
)
576 cacheID
= addrindex_get_cache_id( addrIndex
, ds
);
578 g_hash_table_insert( addrIndex
->hashCache
, cacheID
, ds
);
583 * Free hash table callback function.
585 static gboolean
addrindex_free_cache_cb( gpointer key
, gpointer value
, gpointer data
) {
593 * Free hash table of address cache items.
595 static void addrindex_free_cache_hash( GHashTable
*table
) {
596 g_hash_table_foreach_remove( table
, addrindex_free_cache_cb
, NULL
);
597 g_hash_table_destroy( table
);
601 * Remove data source from internal hashtable.
602 * \param addrIndex Address index.
603 * \param ds Data source to remove.
605 static void addrindex_hash_remove_cache(
606 AddressIndex
*addrIndex
, AddressDataSource
*ds
)
610 cacheID
= addrindex_get_cache_id( addrIndex
, ds
);
612 g_hash_table_remove( addrIndex
->hashCache
, cacheID
);
619 * Create a new address index. This is created as a singleton object.
620 * \return Initialized address index object.
622 AddressIndex
*addrindex_create_index( void ) {
625 if( _addressIndex_
== NULL
) {
626 index
= g_new0( AddressIndex
, 1 );
627 ADDRITEM_TYPE(index
) = ITEMTYPE_INDEX
;
628 ADDRITEM_ID(index
) = NULL
;
629 ADDRITEM_NAME(index
) = g_strdup( "Address Index" );
630 ADDRITEM_PARENT(index
) = NULL
;
631 ADDRITEM_SUBTYPE(index
) = 0;
632 index
->filePath
= NULL
;
633 index
->fileName
= NULL
;
634 index
->retVal
= MGU_SUCCESS
;
635 index
->needsConversion
= FALSE
;
636 index
->wasConverted
= FALSE
;
637 index
->conversionError
= FALSE
;
638 index
->interfaceList
= NULL
;
639 index
->lastType
= ADDR_IF_NONE
;
640 index
->dirtyFlag
= FALSE
;
641 index
->hashCache
= g_hash_table_new( g_str_hash
, g_str_equal
);
642 index
->loadedFlag
= FALSE
;
643 index
->searchOrder
= NULL
;
644 addrindex_build_if_list( index
);
645 _addressIndex_
= index
;
647 return _addressIndex_
;
651 * Property - Specify file path to address index file.
652 * \param addrIndex Address index.
653 * \param value Path to index file.
655 void addrindex_set_file_path( AddressIndex
*addrIndex
, const gchar
*value
) {
656 g_return_if_fail( addrIndex
!= NULL
);
657 addrIndex
->filePath
= mgu_replace_string( addrIndex
->filePath
, value
);
661 * Property - Specify file name to address index file.
662 * \param addrIndex Address index.
663 * \param value File name.
665 void addrindex_set_file_name( AddressIndex
*addrIndex
, const gchar
*value
) {
666 g_return_if_fail( addrIndex
!= NULL
);
667 addrIndex
->fileName
= mgu_replace_string( addrIndex
->fileName
, value
);
671 * Return list of address interfaces.
672 * \param addrIndex Address index.
673 * \return List of address interfaces.
675 GList
*addrindex_get_interface_list( AddressIndex
*addrIndex
) {
676 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
677 return addrIndex
->interfaceList
;
681 * Perform any other initialization of address index.
683 void addrindex_initialize( void ) {
685 addrcompl_initialize();
689 * Perform any other teardown of address index.
691 void addrindex_teardown( void ) {
692 addrcompl_teardown();
697 * Free up address index.
698 * \param addrIndex Address index.
700 void addrindex_free_index( AddressIndex
*addrIndex
) {
703 g_return_if_fail( addrIndex
!= NULL
);
706 g_list_free( addrIndex
->searchOrder
);
707 addrIndex
->searchOrder
= NULL
;
709 /* Free internal storage */
710 g_free( ADDRITEM_ID(addrIndex
) );
711 g_free( ADDRITEM_NAME(addrIndex
) );
712 g_free( addrIndex
->filePath
);
713 g_free( addrIndex
->fileName
);
716 ADDRITEM_TYPE(addrIndex
) = ITEMTYPE_NONE
;
717 ADDRITEM_ID(addrIndex
) = NULL
;
718 ADDRITEM_NAME(addrIndex
) = NULL
;
719 ADDRITEM_PARENT(addrIndex
) = NULL
;
720 ADDRITEM_SUBTYPE(addrIndex
) = 0;
721 addrIndex
->filePath
= NULL
;
722 addrIndex
->fileName
= NULL
;
723 addrIndex
->retVal
= MGU_SUCCESS
;
724 addrIndex
->needsConversion
= FALSE
;
725 addrIndex
->wasConverted
= FALSE
;
726 addrIndex
->conversionError
= FALSE
;
727 addrIndex
->lastType
= ADDR_IF_NONE
;
728 addrIndex
->dirtyFlag
= FALSE
;
730 /* Free up interfaces */
731 node
= addrIndex
->interfaceList
;
733 AddressInterface
*iface
= node
->data
;
734 addrindex_free_interface( iface
);
735 node
= g_list_next( node
);
737 g_list_free( addrIndex
->interfaceList
);
738 addrIndex
->interfaceList
= NULL
;
740 /* Free up hash cache */
741 addrindex_free_cache_hash( addrIndex
->hashCache
);
742 addrIndex
->hashCache
= NULL
;
744 addrIndex
->loadedFlag
= FALSE
;
748 _addressIndex_
= NULL
;
752 * Print address index.
753 * \param addrIndex Address index.
754 * \parem stream Stream to print.
756 void addrindex_print_index( AddressIndex
*addrIndex
, FILE *stream
) {
757 g_return_if_fail( addrIndex
!= NULL
);
758 fprintf( stream
, "AddressIndex:\n" );
759 fprintf( stream
, "\tfile path: '%s'\n", addrIndex
->filePath
);
760 fprintf( stream
, "\tfile name: '%s'\n", addrIndex
->fileName
);
761 fprintf( stream
, "\t status: %d\n", addrIndex
->retVal
);
762 fprintf( stream
, "\tconverted: '%s'\n",
763 addrIndex
->wasConverted
? "yes" : "no" );
764 fprintf( stream
, "\tcvt error: '%s'\n",
765 addrIndex
->conversionError
? "yes" : "no" );
766 fprintf( stream
, "\t---\n" );
770 * Retrieve reference to address interface for specified interface type.
771 * \param addrIndex Address index.
772 * \param ifType Interface type.
773 * \return Address interface, or NULL if not found.
775 static AddressInterface
*addrindex_get_interface(
776 AddressIndex
*addrIndex
, AddressIfType ifType
)
778 AddressInterface
*retVal
= NULL
;
781 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
783 node
= addrIndex
->interfaceList
;
785 AddressInterface
*iface
= node
->data
;
786 node
= g_list_next( node
);
787 if( iface
->type
== ifType
) {
796 * Add raw data source to index. The raw data object (an AddressBookFile or
797 * VCardFile object, for example) should be supplied as the raw dataSource
800 * \param addrIndex Address index.
801 * \param ifType Interface type to add.
802 * \param dataSource Actual raw data source to add.
803 * \return Data source added, or NULL if invalid interface type.
805 AddressDataSource
*addrindex_index_add_datasource(
806 AddressIndex
*addrIndex
, AddressIfType ifType
, gpointer dataSource
)
808 AddressInterface
*iface
;
809 AddressDataSource
*ds
= NULL
;
811 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
812 g_return_val_if_fail( dataSource
!= NULL
, NULL
);
814 iface
= addrindex_get_interface( addrIndex
, ifType
);
816 ds
= addrindex_create_datasource( ifType
);
817 ADDRITEM_PARENT(ds
) = ADDRITEM_OBJECT(iface
);
819 ds
->rawDataSource
= dataSource
;
820 ds
->interface
= iface
;
821 iface
->listSource
= g_list_append( iface
->listSource
, ds
);
822 addrIndex
->dirtyFlag
= TRUE
;
824 addrindex_hash_add_cache( addrIndex
, ds
);
830 * Remove specified data source from index.
831 * \param addrIndex Address index.
832 * \param dataSource Data source to add.
833 * \return Reference to data source if removed, or NULL if data source was not
834 * found in index. Note the this object must still be freed.
836 AddressDataSource
*addrindex_index_remove_datasource(
837 AddressIndex
*addrIndex
, AddressDataSource
*dataSource
)
839 AddressDataSource
*retVal
= FALSE
;
840 AddressInterface
*iface
;
842 g_return_val_if_fail( addrIndex
!= NULL
, NULL
);
843 g_return_val_if_fail( dataSource
!= NULL
, NULL
);
845 iface
= addrindex_get_interface( addrIndex
, dataSource
->type
);
847 iface
->listSource
= g_list_remove( iface
->listSource
, dataSource
);
848 addrIndex
->dirtyFlag
= TRUE
;
849 dataSource
->interface
= NULL
;
851 /* Remove cache from hash table */
852 addrindex_hash_remove_cache( addrIndex
, dataSource
);
860 * Retrieve a reference to address interface for specified interface type and
861 * XML interface tag name.
862 * \param addrIndex Address index.
863 * \param tag XML interface tag name to match.
864 * \param ifType Interface type to match.
865 * \return Reference to address index, or NULL if not found in index.
867 static AddressInterface
*addrindex_tag_get_interface(
868 AddressIndex
*addrIndex
, gchar
*tag
, AddressIfType ifType
)
870 AddressInterface
*retVal
= NULL
;
871 GList
*node
= addrIndex
->interfaceList
;
874 AddressInterface
*iface
= node
->data
;
875 node
= g_list_next( node
);
877 if( strcmp( iface
->listTag
, tag
) == 0 ) {
883 if( iface
->type
== ifType
) {
893 * Retrieve a reference to address interface for specified interface type and
894 * XML datasource tag name.
895 * \param addrIndex Address index.
896 * \param ifType Interface type to match.
897 * \param tag XML datasource tag name to match.
898 * \return Reference to address index, or NULL if not found in index.
900 static AddressInterface
*addrindex_tag_get_datasource(
901 AddressIndex
*addrIndex
, AddressIfType ifType
, gchar
*tag
)
903 AddressInterface
*retVal
= NULL
;
904 GList
*node
= addrIndex
->interfaceList
;
907 AddressInterface
*iface
= node
->data
;
908 node
= g_list_next( node
);
909 if( iface
->type
== ifType
&& iface
->itemTag
) {
910 if( strcmp( iface
->itemTag
, tag
) == 0 ) {
919 /* **********************************************************************
920 * Interface XML parsing functions.
921 * ***********************************************************************
925 * Write start of XML element to file.
927 * \param lvl Indentation level.
928 * \param name Element name.
930 static void addrindex_write_elem_s( FILE *fp
, const gint lvl
, const gchar
*name
) {
932 for( i
= 0; i
< lvl
; i
++ ) fputs( " ", fp
);
938 * Write end of XML element to file.
940 * \param lvl Indentation level.
941 * \param name Element name.
943 static void addrindex_write_elem_e( FILE *fp
, const gint lvl
, const gchar
*name
) {
945 for( i
= 0; i
< lvl
; i
++ ) fputs( " ", fp
);
952 * Write XML attribute to file.
954 * \param name Attribute name.
955 * \param value Attribute value.
957 static void addrindex_write_attr( FILE *fp
, const gchar
*name
, const gchar
*value
) {
961 xml_file_put_escape_str( fp
, value
);
966 * Return DOM fragment for current XML tag from file.
967 * \param file XML file being processed.
968 * \return Fragment representing DOM fragment for configuration element.
970 static AddressIfFragment
*addrindex_read_fragment( XMLFile
*file
) {
971 AddressIfFragment
*fragment
;
972 AddressIfFragment
*child
;
982 /* g_print( "addrindex_read_fragment\n" ); */
984 prevLevel
= file
->level
;
986 /* Get current tag name */
987 xtag
= xml_get_current_tag( file
);
989 /* Create new fragment */
990 fragment
= g_new0( AddressIfFragment
, 1 );
991 fragment
->name
= g_strdup( xtag
->tag
);
992 fragment
->children
= NULL
;
993 fragment
->attributes
= NULL
;
995 /* Read attributes */
997 attr
= xml_get_current_tag_attr( file
);
999 name
= ((XMLAttr
*)attr
->data
)->name
;
1000 value
= ((XMLAttr
*)attr
->data
)->value
;
1001 nv
= g_new0( AddressIfAttrib
, 1 );
1002 nv
->name
= g_strdup( name
);
1003 nv
->value
= g_strdup( value
);
1004 list
= g_list_append( list
, nv
);
1005 attr
= g_list_next( attr
);
1007 fragment
->attributes
= list
;
1009 /* Now read the children */
1011 rc
= xml_parse_next_tag( file
);
1016 if( file
->level
< prevLevel
) {
1017 /* We must be above level we start at */
1020 child
= addrindex_read_fragment( file
);
1021 fragment
->children
= g_list_append( fragment
->children
, child
);
1028 * Write DOM fragment to file.
1029 * \param fp File to write.
1030 * \param fragment DOM fragment for configuration element.
1031 * \param lvl Indent level.
1033 static void addrindex_write_fragment(
1034 FILE *fp
, const AddressIfFragment
*fragment
, const gint lvl
)
1039 addrindex_write_elem_s( fp
, lvl
, fragment
->name
);
1040 node
= fragment
->attributes
;
1042 AddressIfAttrib
*nv
= node
->data
;
1043 addrindex_write_attr( fp
, nv
->name
, nv
->value
);
1044 node
= g_list_next( node
);
1046 if( fragment
->children
) {
1049 /* Output children */
1050 node
= fragment
->children
;
1052 AddressIfFragment
*child
= node
->data
;
1053 addrindex_write_fragment( fp
, child
, 1+lvl
);
1054 node
= g_list_next( node
);
1057 /* Output closing tag */
1058 addrindex_write_elem_e( fp
, lvl
, fragment
->name
);
1067 * Read/parse address index file, creating a data source for a regular
1068 * intrinsic XML addressbook.
1069 * \param file Address index file.
1070 * \return Data source.
1072 static AddressDataSource
*addrindex_parse_book( XMLFile
*file
) {
1073 AddressDataSource
*ds
;
1074 AddressBookFile
*abf
;
1077 ds
= addrindex_create_datasource( ADDR_IF_BOOK
);
1078 abf
= addrbook_create_book();
1079 attr
= xml_get_current_tag_attr( file
);
1081 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1082 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1083 if( strcmp( name
, ATTAG_BOOK_NAME
) == 0 ) {
1084 addrbook_set_name( abf
, value
);
1086 else if( strcmp( name
, ATTAG_BOOK_FILE
) == 0) {
1087 addrbook_set_file( abf
, value
);
1089 attr
= g_list_next( attr
);
1091 ds
->rawDataSource
= abf
;
1095 static void addrindex_write_book( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1096 AddressBookFile
*abf
= ds
->rawDataSource
;
1098 addrindex_write_elem_s( fp
, lvl
, TAG_DS_ADDRESS_BOOK
);
1099 addrindex_write_attr( fp
, ATTAG_BOOK_NAME
, addrbook_get_name( abf
) );
1100 addrindex_write_attr( fp
, ATTAG_BOOK_FILE
, abf
->fileName
);
1101 fputs( " />\n", fp
);
1105 static AddressDataSource
*addrindex_parse_vcard( XMLFile
*file
) {
1106 AddressDataSource
*ds
;
1110 ds
= addrindex_create_datasource( ADDR_IF_VCARD
);
1111 vcf
= vcard_create();
1112 attr
= xml_get_current_tag_attr( file
);
1114 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1115 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1116 if( strcmp( name
, ATTAG_VCARD_NAME
) == 0 ) {
1117 vcard_set_name( vcf
, value
);
1119 else if( strcmp( name
, ATTAG_VCARD_FILE
) == 0) {
1120 vcard_set_file( vcf
, value
);
1122 attr
= g_list_next( attr
);
1124 ds
->rawDataSource
= vcf
;
1128 static void addrindex_write_vcard( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1129 VCardFile
*vcf
= ds
->rawDataSource
;
1131 addrindex_write_elem_s( fp
, lvl
, TAG_DS_VCARD
);
1132 addrindex_write_attr( fp
, ATTAG_VCARD_NAME
, vcard_get_name( vcf
) );
1133 addrindex_write_attr( fp
, ATTAG_VCARD_FILE
, vcf
->path
);
1134 fputs( " />\n", fp
);
1139 static AddressDataSource
*addrindex_parse_jpilot( XMLFile
*file
) {
1140 AddressDataSource
*ds
;
1144 ds
= addrindex_create_datasource( ADDR_IF_JPILOT
);
1145 jpf
= jpilot_create();
1146 attr
= xml_get_current_tag_attr( file
);
1148 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1149 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1150 if( strcmp( name
, ATTAG_JPILOT_NAME
) == 0 ) {
1151 jpilot_set_name( jpf
, value
);
1153 else if( strcmp( name
, ATTAG_JPILOT_FILE
) == 0 ) {
1154 jpilot_set_file( jpf
, value
);
1156 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_1
) == 0 ) {
1157 jpilot_add_custom_label( jpf
, value
);
1159 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_2
) == 0 ) {
1160 jpilot_add_custom_label( jpf
, value
);
1162 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_3
) == 0 ) {
1163 jpilot_add_custom_label( jpf
, value
);
1165 else if( strcmp( name
, ATTAG_JPILOT_CUSTOM_4
) == 0 ) {
1166 jpilot_add_custom_label( jpf
, value
);
1168 attr
= g_list_next( attr
);
1170 ds
->rawDataSource
= jpf
;
1174 static void addrindex_write_jpilot( FILE *fp
,AddressDataSource
*ds
, gint lvl
) {
1175 JPilotFile
*jpf
= ds
->rawDataSource
;
1179 GList
*customLbl
= jpilot_get_custom_labels( jpf
);
1180 addrindex_write_elem_s( fp
, lvl
, TAG_DS_JPILOT
);
1181 addrindex_write_attr( fp
, ATTAG_JPILOT_NAME
, jpilot_get_name( jpf
) );
1182 addrindex_write_attr( fp
, ATTAG_JPILOT_FILE
, jpf
->path
);
1187 g_snprintf( name
, sizeof(name
), "%s%d",
1188 ATTAG_JPILOT_CUSTOM
, ind
);
1189 addrindex_write_attr( fp
, name
, node
->data
);
1191 node
= g_list_next( node
);
1193 fputs( " />\n", fp
);
1199 * Just read/write DOM fragments (preserve data found in file).
1201 static AddressDataSource
*addrindex_parse_jpilot( XMLFile
*file
) {
1202 AddressDataSource
*ds
;
1204 ds
= addrindex_create_datasource( ADDR_IF_JPILOT
);
1205 ds
->rawDataSource
= addrindex_read_fragment( file
);
1209 static void addrindex_write_jpilot( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1210 AddressIfFragment
*fragment
= ds
->rawDataSource
;
1212 addrindex_write_fragment( fp
, fragment
, lvl
);
1219 * Parse LDAP criteria attribute data from XML file.
1220 * \param file Index file.
1221 * \param ctl LDAP control object to populate.
1223 static void addrindex_parse_ldap_attrlist( XMLFile
*file
, LdapControl
*ctl
) {
1232 if( file
== NULL
) {
1237 prevLevel
= file
->level
;
1238 xtagPrev
= xml_get_current_tag( file
);
1240 rc
= xml_parse_next_tag( file
);
1242 /* Terminate prematurely */
1243 mgu_free_dlist( list
);
1247 if( file
->level
< prevLevel
) {
1248 /* We must be above level we start at */
1252 /* Get a tag (element) */
1253 xtag
= xml_get_current_tag( file
);
1254 if( strcmp( xtag
->tag
, ELTAG_LDAP_ATTR_SRCH
) == 0 ) {
1255 /* LDAP criteria attribute */
1256 attr
= xml_get_current_tag_attr( file
);
1258 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1259 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1260 if( strcmp( name
, ATTAG_LDAP_ATTR_NAME
) == 0 ) {
1261 if( value
&& strlen( value
) > 0 ) {
1262 list
= g_list_append(
1263 list
, g_strdup( value
) );
1266 attr
= g_list_next( attr
);
1270 if( xtag
!= xtagPrev
) {
1271 /* Found a new tag */
1278 /* Build list of search attributes */
1279 ldapctl_criteria_list_clear( ctl
);
1282 ldapctl_criteria_list_add( ctl
, node
->data
);
1283 g_free( node
->data
);
1285 node
= g_list_next( node
);
1287 g_list_free( list
);
1292 void ldapsvr_set_control( LdapServer
*server
, LdapControl
*ctl
);
1294 * Parse LDAP control data from XML file.
1295 * \param file Index file.
1296 * \return Initialized data soruce object.
1298 static AddressDataSource
*addrindex_parse_ldap( XMLFile
*file
) {
1299 AddressDataSource
*ds
;
1303 gchar
*serverName
= NULL
;
1304 gchar
*criteria
= NULL
;
1305 gboolean bDynSearch
;
1306 gboolean bTLS
, bSSL
;
1309 /* g_print( "addrindex_parse_ldap\n" ); */
1310 /* Set up some defaults */
1314 iMatch
= LDAPCTL_MATCH_BEGINWITH
;
1316 ds
= addrindex_create_datasource( ADDR_IF_LDAP
);
1317 ctl
= ldapctl_create();
1318 attr
= xml_get_current_tag_attr( file
);
1320 gchar
*name
= ((XMLAttr
*)attr
->data
)->name
;
1321 gchar
*value
= ((XMLAttr
*)attr
->data
)->value
;
1322 gint ivalue
= atoi( value
);
1324 if( strcmp( name
, ATTAG_LDAP_NAME
) == 0 ) {
1325 g_free( serverName
);
1326 serverName
= g_strdup( value
);
1328 else if( strcmp( name
, ATTAG_LDAP_HOST
) == 0 ) {
1329 ldapctl_set_host( ctl
, value
);
1331 else if( strcmp( name
, ATTAG_LDAP_PORT
) == 0 ) {
1332 ldapctl_set_port( ctl
, ivalue
);
1334 else if( strcmp( name
, ATTAG_LDAP_BASE_DN
) == 0 ) {
1335 ldapctl_set_base_dn( ctl
, value
);
1337 else if( strcmp( name
, ATTAG_LDAP_BIND_DN
) == 0 ) {
1338 ldapctl_set_bind_dn( ctl
, value
);
1340 else if( strcmp( name
, ATTAG_LDAP_BIND_PASS
) == 0 ) {
1341 ldapctl_set_bind_password( ctl
, value
);
1343 else if( strcmp( name
, ATTAG_LDAP_CRITERIA
) == 0 ) {
1345 criteria
= g_strdup( value
);
1346 g_print("criteria %s\n", criteria
);
1348 else if( strcmp( name
, ATTAG_LDAP_MAX_ENTRY
) == 0 ) {
1349 ldapctl_set_max_entries( ctl
, ivalue
);
1351 else if( strcmp( name
, ATTAG_LDAP_TIMEOUT
) == 0 ) {
1352 ldapctl_set_timeout( ctl
, ivalue
);
1354 else if( strcmp( name
, ATTAG_LDAP_MAX_AGE
) == 0 ) {
1355 ldapctl_set_max_query_age( ctl
, ivalue
);
1357 else if( strcmp( name
, ATTAG_LDAP_DYN_SEARCH
) == 0 ) {
1359 if( strcmp( value
, ATVAL_BOOLEAN_YES
) == 0 ) {
1363 else if( strcmp( name
, ATTAG_LDAP_MATCH_OPT
) == 0 ) {
1364 iMatch
= LDAPCTL_MATCH_BEGINWITH
;
1365 if( strcmp( value
, ATVAL_LDAP_MATCH_CONTAINS
) == 0 ) {
1366 iMatch
= LDAPCTL_MATCH_CONTAINS
;
1369 else if( strcmp( name
, ATTAG_LDAP_ENABLE_TLS
) == 0 ) {
1371 if( strcmp( value
, ATVAL_BOOLEAN_YES
) == 0 ) {
1375 else if( strcmp( name
, ATTAG_LDAP_ENABLE_SSL
) == 0 ) {
1377 if( strcmp( value
, ATVAL_BOOLEAN_YES
) == 0 ) {
1381 attr
= g_list_next( attr
);
1384 server
= ldapsvr_create_noctl();
1385 ldapsvr_set_name( server
, serverName
);
1386 ldapsvr_set_search_flag( server
, bDynSearch
);
1387 ldapctl_set_matching_option( ctl
, iMatch
);
1389 ldapctl_set_tls( ctl
, bTLS
);
1390 ldapctl_set_ssl( ctl
, bSSL
);
1392 g_free( serverName
);
1393 ldapsvr_set_control( server
, ctl
);
1394 ds
->rawDataSource
= server
;
1396 addrindex_parse_ldap_attrlist( file
, ctl
);
1398 * If criteria have been specified and no attributes were listed, then
1399 * convert old style criteria into an attribute list. Any criteria will
1400 * be dropped when saving data.
1403 if( ! ldapctl_get_criteria_list( ctl
) ) {
1404 ldapctl_parse_ldap_search( ctl
, criteria
);
1408 /* ldapsvr_print_data( server, stdout ); */
1413 static void addrindex_write_ldap( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1414 LdapServer
*server
= ds
->rawDataSource
;
1415 LdapControl
*ctl
= NULL
;
1420 ctl
= server
->control
;
1422 if( ctl
== NULL
) return;
1424 /* Output start element with attributes */
1425 addrindex_write_elem_s( fp
, lvl
, TAG_DS_LDAP
);
1426 addrindex_write_attr( fp
, ATTAG_LDAP_NAME
, ldapsvr_get_name( server
) );
1427 addrindex_write_attr( fp
, ATTAG_LDAP_HOST
, ctl
->hostName
);
1429 sprintf( value
, "%d", ctl
->port
);
1430 addrindex_write_attr( fp
, ATTAG_LDAP_PORT
, value
);
1432 addrindex_write_attr( fp
, ATTAG_LDAP_BASE_DN
, ctl
->baseDN
);
1433 addrindex_write_attr( fp
, ATTAG_LDAP_BIND_DN
, ctl
->bindDN
);
1434 addrindex_write_attr( fp
, ATTAG_LDAP_BIND_PASS
, ctl
->bindPass
);
1436 sprintf( value
, "%d", ctl
->maxEntries
);
1437 addrindex_write_attr( fp
, ATTAG_LDAP_MAX_ENTRY
, value
);
1438 sprintf( value
, "%d", ctl
->timeOut
);
1439 addrindex_write_attr( fp
, ATTAG_LDAP_TIMEOUT
, value
);
1440 sprintf( value
, "%d", ctl
->maxQueryAge
);
1441 addrindex_write_attr( fp
, ATTAG_LDAP_MAX_AGE
, value
);
1443 addrindex_write_attr( fp
, ATTAG_LDAP_DYN_SEARCH
,
1444 server
->searchFlag
?
1445 ATVAL_BOOLEAN_YES
: ATVAL_BOOLEAN_NO
);
1447 addrindex_write_attr( fp
, ATTAG_LDAP_MATCH_OPT
,
1448 ( ctl
->matchingOption
== LDAPCTL_MATCH_CONTAINS
) ?
1449 ATVAL_LDAP_MATCH_CONTAINS
: ATVAL_LDAP_MATCH_BEGIN
);
1451 addrindex_write_attr( fp
, ATTAG_LDAP_ENABLE_TLS
,
1453 ATVAL_BOOLEAN_YES
: ATVAL_BOOLEAN_NO
);
1454 addrindex_write_attr( fp
, ATTAG_LDAP_ENABLE_SSL
,
1456 ATVAL_BOOLEAN_YES
: ATVAL_BOOLEAN_NO
);
1460 /* Output attributes */
1461 node
= ldapctl_get_criteria_list( ctl
);
1463 addrindex_write_elem_s( fp
, 1+lvl
, ELTAG_LDAP_ATTR_SRCH
);
1464 addrindex_write_attr( fp
, ATTAG_LDAP_ATTR_NAME
, node
->data
);
1466 node
= g_list_next( node
);
1469 /* End of element */
1470 addrindex_write_elem_e( fp
, lvl
, TAG_DS_LDAP
);
1475 * Just read/write DOM fragments (preserve data found in file).
1477 static AddressDataSource
*addrindex_parse_ldap( XMLFile
*file
) {
1478 AddressDataSource
*ds
;
1480 ds
= addrindex_create_datasource( ADDR_IF_LDAP
);
1481 ds
->rawDataSource
= addrindex_read_fragment( file
);
1485 static void addrindex_write_ldap( FILE *fp
, AddressDataSource
*ds
, gint lvl
) {
1486 AddressIfFragment
*fragment
= ds
->rawDataSource
;
1488 addrindex_write_fragment( fp
, fragment
, lvl
);
1493 /* **********************************************************************
1494 * Address index I/O functions.
1495 * ***********************************************************************
1498 * Read address index file, creating appropriate data sources for each address
1501 * \param addrIndex Address index.
1502 * \param file Address index file.
1504 static void addrindex_read_index( AddressIndex
*addrIndex
, XMLFile
*file
) {
1507 AddressInterface
*iface
= NULL
, *dsIFace
= NULL
;
1508 AddressDataSource
*ds
;
1511 addrIndex
->loadedFlag
= FALSE
;
1513 prev_level
= file
->level
;
1514 rc
= xml_parse_next_tag( file
);
1515 if( file
->level
== 0 ) return;
1517 xtag
= xml_get_current_tag( file
);
1519 iface
= addrindex_tag_get_interface( addrIndex
, xtag
->tag
, ADDR_IF_NONE
);
1521 addrIndex
->lastType
= iface
->type
;
1522 if( iface
->legacyFlag
) addrIndex
->needsConversion
= TRUE
;
1525 dsIFace
= addrindex_tag_get_datasource(
1526 addrIndex
, addrIndex
->lastType
, xtag
->tag
);
1528 /* Add data source to list */
1530 if( addrIndex
->lastType
== ADDR_IF_BOOK
) {
1531 ds
= addrindex_parse_book( file
);
1532 if( ds
->rawDataSource
) {
1533 addrbook_set_path( ds
->rawDataSource
,
1534 addrIndex
->filePath
);
1537 else if( addrIndex
->lastType
== ADDR_IF_VCARD
) {
1538 ds
= addrindex_parse_vcard( file
);
1540 else if( addrIndex
->lastType
== ADDR_IF_JPILOT
) {
1541 ds
= addrindex_parse_jpilot( file
);
1543 else if( addrIndex
->lastType
== ADDR_IF_LDAP
) {
1544 ds
= addrindex_parse_ldap( file
);
1547 ds
->interface
= dsIFace
;
1548 addrindex_hash_add_cache( addrIndex
, ds
);
1549 dsIFace
->listSource
=
1550 g_list_append( dsIFace
->listSource
, ds
);
1558 * Search order sorting comparison function for building search order list.
1560 static gint
addrindex_search_order_compare( gconstpointer ptrA
, gconstpointer ptrB
) {
1561 AddressInterface
*ifaceA
= ( AddressInterface
* ) ptrA
;
1562 AddressInterface
*ifaceB
= ( AddressInterface
* ) ptrB
;
1564 return ifaceA
->searchOrder
- ifaceB
->searchOrder
;
1568 * Build list of data sources to process.
1569 * \param addrIndex Address index object.
1571 static void addrindex_build_search_order( AddressIndex
*addrIndex
) {
1574 /* Clear existing list */
1575 g_list_free( addrIndex
->searchOrder
);
1576 addrIndex
->searchOrder
= NULL
;
1578 /* Build new list */
1579 nodeIf
= addrIndex
->interfaceList
;
1581 AddressInterface
*iface
= nodeIf
->data
;
1582 if( iface
->useInterface
) {
1583 if( iface
->searchOrder
> 0 ) {
1584 /* Add to search order list */
1585 addrIndex
->searchOrder
= g_list_insert_sorted(
1586 addrIndex
->searchOrder
, iface
,
1587 addrindex_search_order_compare
);
1590 nodeIf
= g_list_next( nodeIf
);
1594 static gint
addrindex_read_file( AddressIndex
*addrIndex
) {
1595 XMLFile
*file
= NULL
;
1596 gchar
*fileSpec
= NULL
;
1598 g_return_val_if_fail( addrIndex
!= NULL
, -1 );
1600 fileSpec
= g_strconcat( addrIndex
->filePath
, G_DIR_SEPARATOR_S
, addrIndex
->fileName
, NULL
);
1601 addrIndex
->retVal
= MGU_NO_FILE
;
1602 file
= xml_open_file( fileSpec
);
1605 if( file
== NULL
) {
1607 g_print( " file '%s' does not exist.\n", addrIndex->fileName );
1609 return addrIndex
->retVal
;
1612 addrIndex
->retVal
= MGU_BAD_FORMAT
;
1613 if( xml_get_dtd( file
) == 0 ) {
1614 if( xml_parse_next_tag( file
) == 0 ) {
1615 if( xml_compare_tag( file
, TAG_ADDRESS_INDEX
) ) {
1616 addrindex_read_index( addrIndex
, file
);
1617 addrIndex
->retVal
= MGU_SUCCESS
;
1621 xml_close_file( file
);
1623 addrindex_build_search_order( addrIndex
);
1625 return addrIndex
->retVal
;
1628 static void addrindex_write_index( AddressIndex
*addrIndex
, FILE *fp
) {
1629 GList
*nodeIF
, *nodeDS
;
1631 gint lvlItem
= 1 + lvlList
;
1633 nodeIF
= addrIndex
->interfaceList
;
1635 AddressInterface
*iface
= nodeIF
->data
;
1636 if( ! iface
->legacyFlag
) {
1637 nodeDS
= iface
->listSource
;
1638 addrindex_write_elem_s( fp
, lvlList
, iface
->listTag
);
1641 AddressDataSource
*ds
= nodeDS
->data
;
1643 if( iface
->type
== ADDR_IF_BOOK
) {
1644 addrindex_write_book( fp
, ds
, lvlItem
);
1646 if( iface
->type
== ADDR_IF_VCARD
) {
1647 addrindex_write_vcard( fp
, ds
, lvlItem
);
1649 if( iface
->type
== ADDR_IF_JPILOT
) {
1650 addrindex_write_jpilot( fp
, ds
, lvlItem
);
1652 if( iface
->type
== ADDR_IF_LDAP
) {
1653 addrindex_write_ldap( fp
, ds
, lvlItem
);
1656 nodeDS
= g_list_next( nodeDS
);
1658 addrindex_write_elem_e( fp
, lvlList
, iface
->listTag
);
1660 nodeIF
= g_list_next( nodeIF
);
1665 * Write data to specified file.
1666 * Enter: addrIndex Address index object.
1667 * newFile New file name.
1668 * return: Status code, from addrIndex->retVal.
1669 * Note: File will be created in directory specified by addrIndex.
1671 static gint
addrindex_write_to( AddressIndex
*addrIndex
, const gchar
*newFile
) {
1674 #ifndef DEV_STANDALONE
1678 g_return_val_if_fail( addrIndex
!= NULL
, -1 );
1680 fileSpec
= g_strconcat( addrIndex
->filePath
, G_DIR_SEPARATOR_S
, newFile
, NULL
);
1681 addrIndex
->retVal
= MGU_OPEN_FILE
;
1682 #ifdef DEV_STANDALONE
1683 fp
= g_fopen( fileSpec
, "wb" );
1686 fputs( "<?xml version=\"1.0\" ?>\n", fp
);
1688 pfile
= prefs_write_open( fileSpec
);
1692 fprintf( fp
, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL
);
1694 addrindex_write_elem_s( fp
, 0, TAG_ADDRESS_INDEX
);
1697 addrindex_write_index( addrIndex
, fp
);
1698 addrindex_write_elem_e( fp
, 0, TAG_ADDRESS_INDEX
);
1700 addrIndex
->retVal
= MGU_SUCCESS
;
1701 #ifdef DEV_STANDALONE
1704 if( prefs_file_close( pfile
) < 0 ) {
1705 addrIndex
->retVal
= MGU_ERROR_WRITE
;
1711 return addrIndex
->retVal
;
1715 * Save address index data to original file.
1716 * return: Status code, from addrIndex->retVal.
1718 gint
addrindex_save_data( AddressIndex
*addrIndex
) {
1719 GList
*nodeIf
, *nodeDS
;
1721 g_return_val_if_fail( addrIndex
!= NULL
, -1 );
1722 nodeIf
= addrIndex
->interfaceList
;
1725 /* save LDAP interfaces */
1727 AddressInterface
*iface
= nodeIf
->data
;
1728 if( iface
->type
== ADDR_IF_LDAP
) {
1729 nodeDS
= iface
->listSource
;
1731 AddressDataSource
*ds
= nodeDS
->data
;
1732 LdapServer
*abf
= ds
->rawDataSource
;
1733 if( ldapsvr_get_read_flag( abf
) ) {
1734 if( ldapsvr_get_modified( abf
) ) {
1735 ldapsvr_update_book( abf
, NULL
);
1736 if( abf
->retVal
!= LDAPRC_SUCCESS
) {
1737 alertpanel( _("Address(es) update"),
1738 _("Update failed. Changes not written to Directory."),
1739 GTK_STOCK_CLOSE
, NULL
, NULL
);
1742 abf
->retVal
= MGU_SUCCESS
;
1743 ldapsvr_set_modified( abf
, FALSE
);
1747 nodeDS
= g_list_next( nodeDS
);
1751 nodeIf
= g_list_next( nodeIf
);
1754 addrIndex
->retVal
= MGU_NO_FILE
;
1755 if( addrIndex
->fileName
== NULL
|| *addrIndex
->fileName
== '\0' ) return addrIndex
->retVal
;
1756 if( addrIndex
->filePath
== NULL
|| *addrIndex
->filePath
== '\0' ) return addrIndex
->retVal
;
1758 addrindex_write_to( addrIndex
, addrIndex
->fileName
);
1759 if( addrIndex
->retVal
== MGU_SUCCESS
) {
1760 addrIndex
->dirtyFlag
= FALSE
;
1762 return addrIndex
->retVal
;
1766 * Save all address book files which may have changed.
1767 * Return: Status code, set if there was a problem saving data.
1769 gint
addrindex_save_all_books( AddressIndex
*addrIndex
) {
1770 gint retVal
= MGU_SUCCESS
;
1771 GList
*nodeIf
, *nodeDS
;
1773 nodeIf
= addrIndex
->interfaceList
;
1775 AddressInterface
*iface
= nodeIf
->data
;
1776 if( iface
->type
== ADDR_IF_BOOK
) {
1777 nodeDS
= iface
->listSource
;
1779 AddressDataSource
*ds
= nodeDS
->data
;
1780 AddressBookFile
*abf
= ds
->rawDataSource
;
1781 if( addrbook_get_dirty( abf
) ) {
1782 if( addrbook_get_read_flag( abf
) ) {
1783 addrbook_save_data( abf
);
1784 if( abf
->retVal
!= MGU_SUCCESS
) {
1785 retVal
= abf
->retVal
;
1789 nodeDS
= g_list_next( nodeDS
);
1793 nodeIf
= g_list_next( nodeIf
);
1799 /* **********************************************************************
1800 * Address book conversion to new format.
1801 * ***********************************************************************
1804 #define ELTAG_IF_OLD_FOLDER "folder"
1805 #define ELTAG_IF_OLD_GROUP "group"
1806 #define ELTAG_IF_OLD_ITEM "item"
1807 #define ELTAG_IF_OLD_NAME "name"
1808 #define ELTAG_IF_OLD_ADDRESS "address"
1809 #define ELTAG_IF_OLD_REMARKS "remarks"
1810 #define ATTAG_IF_OLD_NAME "name"
1812 #define TEMPNODE_ROOT 0
1813 #define TEMPNODE_FOLDER 1
1814 #define TEMPNODE_GROUP 2
1815 #define TEMPNODE_ADDRESS 3
1817 typedef struct _AddressCvt_Node AddressCvtNode
;
1818 struct _AddressCvt_Node
{
1827 * Parse current address item.
1829 static AddressCvtNode
*addrindex_parse_item( XMLFile
*file
) {
1834 nn
= g_new0( AddressCvtNode
, 1 );
1835 nn
->type
= TEMPNODE_ADDRESS
;
1838 level
= file
->level
;
1841 xml_parse_next_tag(file
);
1842 if (file
->level
< level
) return nn
;
1844 element
= xml_get_element( file
);
1845 if( xml_compare_tag( file
, ELTAG_IF_OLD_NAME
) ) {
1846 nn
->name
= g_strdup( element
);
1848 if( xml_compare_tag( file
, ELTAG_IF_OLD_ADDRESS
) ) {
1849 nn
->address
= g_strdup( element
);
1851 if( xml_compare_tag( file
, ELTAG_IF_OLD_REMARKS
) ) {
1852 nn
->remarks
= g_strdup( element
);
1855 xml_parse_next_tag(file
);
1860 * Create a temporary node below specified node.
1862 static AddressCvtNode
*addrindex_add_object( AddressCvtNode
*node
, gint type
, gchar
*name
, gchar
*addr
, char *rem
) {
1864 nn
= g_new0( AddressCvtNode
, 1 );
1866 nn
->name
= g_strdup( name
);
1867 nn
->remarks
= g_strdup( rem
);
1868 node
->list
= g_list_append( node
->list
, nn
);
1873 * Process current temporary node.
1875 static void addrindex_add_obj( XMLFile
*file
, AddressCvtNode
*node
) {
1878 AddressCvtNode
*newNode
= NULL
;
1883 prev_level
= file
->level
;
1884 xml_parse_next_tag( file
);
1885 if (file
->level
< prev_level
) return;
1889 if( xml_compare_tag( file
, ELTAG_IF_OLD_GROUP
) ) {
1890 attr
= xml_get_current_tag_attr(file
);
1892 name
= ((XMLAttr
*)attr
->data
)->name
;
1893 if( strcmp( name
, ATTAG_IF_OLD_NAME
) == 0 ) {
1894 value
= ((XMLAttr
*)attr
->data
)->value
;
1897 newNode
= addrindex_add_object( node
, TEMPNODE_GROUP
, value
, "", "" );
1898 addrindex_add_obj( file
, newNode
);
1901 else if( xml_compare_tag( file
, ELTAG_IF_OLD_FOLDER
) ) {
1902 attr
= xml_get_current_tag_attr(file
);
1904 name
= ((XMLAttr
*)attr
->data
)->name
;
1905 if( strcmp( name
, ATTAG_IF_OLD_NAME
) == 0 ) {
1906 value
= ((XMLAttr
*)attr
->data
)->value
;
1909 newNode
= addrindex_add_object( node
, TEMPNODE_FOLDER
, value
, "", "" );
1910 addrindex_add_obj( file
, newNode
);
1912 else if( xml_compare_tag( file
, ELTAG_IF_OLD_ITEM
) ) {
1913 newNode
= addrindex_parse_item( file
);
1914 node
->list
= g_list_append( node
->list
, newNode
);
1917 /* g_print( "invalid: !!! \n" ); */
1918 attr
= xml_get_current_tag_attr( file
);
1924 * Consume all nodes below current tag.
1926 static void addrindex_consume_tree( XMLFile
*file
) {
1933 prev_level
= file
->level
;
1934 xml_parse_next_tag( file
);
1935 if (file
->level
< prev_level
) return;
1937 xtag
= xml_get_current_tag( file
);
1938 /* g_print( "tag : %s\n", xtag->tag ); */
1939 element
= xml_get_element( file
);
1940 attr
= xml_get_current_tag_attr( file
);
1941 /* show_attribs( attr ); */
1942 /* g_print( "\ttag value : %s :\n", element ); */
1943 addrindex_consume_tree( file
);
1948 * Print temporary tree.
1950 static void addrindex_print_node( AddressCvtNode
*node
, FILE *stream
) {
1953 fprintf( stream
, "Node:\ttype :%d:\n", node
->type
);
1954 fprintf( stream
, "\tname :%s:\n", node
->name
);
1955 fprintf( stream
, "\taddr :%s:\n", node
->address
);
1956 fprintf( stream
, "\trems :%s:\n", node
->remarks
);
1958 fprintf( stream
, "\t--list----\n" );
1962 AddressCvtNode
*lNode
= list
->data
;
1963 list
= g_list_next( list
);
1964 addrindex_print_node( lNode
, stream
);
1966 fprintf( stream
, "\t==list-%d==\n", node
->type
);
1970 * Free up temporary tree.
1972 static void addrindex_free_node( AddressCvtNode
*node
) {
1973 GList
*list
= node
->list
;
1976 AddressCvtNode
*lNode
= list
->data
;
1977 list
= g_list_next( list
);
1978 addrindex_free_node( lNode
);
1980 node
->type
= TEMPNODE_ROOT
;
1981 g_free( node
->name
);
1982 g_free( node
->address
);
1983 g_free( node
->remarks
);
1984 g_list_free( node
->list
);
1989 * Process address book for specified node.
1991 static void addrindex_process_node(
1992 AddressBookFile
*abf
, AddressCvtNode
*node
, ItemFolder
*parent
,
1993 ItemGroup
*parentGrp
, ItemFolder
*folderGrp
)
1996 ItemFolder
*itemFolder
= NULL
;
1997 ItemGroup
*itemGParent
= parentGrp
;
1998 ItemFolder
*itemGFolder
= folderGrp
;
1999 AddressCache
*cache
= abf
->addressCache
;
2001 if( node
->type
== TEMPNODE_ROOT
) {
2002 itemFolder
= parent
;
2004 else if( node
->type
== TEMPNODE_FOLDER
) {
2005 itemFolder
= addritem_create_item_folder();
2006 addritem_folder_set_name( itemFolder
, node
->name
);
2007 addrcache_id_folder( cache
, itemFolder
);
2008 addrcache_folder_add_folder( cache
, parent
, itemFolder
);
2011 else if( node
->type
== TEMPNODE_GROUP
) {
2012 ItemGroup
*itemGroup
;
2015 /* Create a folder for group */
2016 fName
= g_strdup_printf( "Cvt - %s", node
->name
);
2017 itemGFolder
= addritem_create_item_folder();
2018 addritem_folder_set_name( itemGFolder
, fName
);
2019 addrcache_id_folder( cache
, itemGFolder
);
2020 addrcache_folder_add_folder( cache
, parent
, itemGFolder
);
2023 /* Add group into folder */
2024 itemGroup
= addritem_create_item_group();
2025 addritem_group_set_name( itemGroup
, node
->name
);
2026 addrcache_id_group( cache
, itemGroup
);
2027 addrcache_folder_add_group( cache
, itemGFolder
, itemGroup
);
2028 itemGParent
= itemGroup
;
2030 else if( node
->type
== TEMPNODE_ADDRESS
) {
2031 ItemPerson
*itemPerson
;
2032 ItemEMail
*itemEMail
;
2034 /* Create person and email objects */
2035 itemPerson
= addritem_create_item_person();
2036 addritem_person_set_common_name( itemPerson
, node
->name
);
2037 addrcache_id_person( cache
, itemPerson
);
2038 itemEMail
= addritem_create_item_email();
2039 addritem_email_set_address( itemEMail
, node
->address
);
2040 addritem_email_set_remarks( itemEMail
, node
->remarks
);
2041 addrcache_id_email( cache
, itemEMail
);
2042 addrcache_person_add_email( cache
, itemPerson
, itemEMail
);
2044 /* Add person into appropriate folder */
2046 addrcache_folder_add_person( cache
, itemGFolder
, itemPerson
);
2049 addrcache_folder_add_person( cache
, parent
, itemPerson
);
2052 /* Add email address only into group */
2054 addrcache_group_add_email( cache
, parentGrp
, itemEMail
);
2060 AddressCvtNode
*lNode
= list
->data
;
2061 list
= g_list_next( list
);
2062 addrindex_process_node( abf
, lNode
, itemFolder
, itemGParent
, itemGFolder
);
2067 * Process address book to specified file number.
2069 static gboolean
addrindex_process_book( AddressIndex
*addrIndex
, XMLFile
*file
, gchar
*displayName
) {
2070 gboolean retVal
= FALSE
;
2071 AddressBookFile
*abf
= NULL
;
2072 AddressCvtNode
*rootNode
= NULL
;
2073 gchar
*newFile
= NULL
;
2074 GList
*fileList
= NULL
;
2077 /* Setup root node */
2078 rootNode
= g_new0( AddressCvtNode
, 1 );
2079 rootNode
->type
= TEMPNODE_ROOT
;
2080 rootNode
->name
= g_strdup( "root" );
2081 rootNode
->list
= NULL
;
2082 addrindex_add_obj( file
, rootNode
);
2083 /* addrindex_print_node( rootNode, stdout ); */
2085 /* Create new address book */
2086 abf
= addrbook_create_book();
2087 addrbook_set_name( abf
, displayName
);
2088 addrbook_set_path( abf
, addrIndex
->filePath
);
2090 /* Determine next available file number */
2091 fileList
= addrbook_get_bookfile_list( abf
);
2093 fileNum
= 1 + abf
->maxValue
;
2095 g_list_free( fileList
);
2098 newFile
= addrbook_gen_new_file_name( fileNum
);
2100 addrbook_set_file( abf
, newFile
);
2103 addrindex_process_node( abf
, rootNode
, abf
->addressCache
->rootFolder
, NULL
, NULL
);
2105 /* addrbook_dump_book( abf, stdout ); */
2106 addrbook_save_data( abf
);
2107 addrIndex
->retVal
= abf
->retVal
;
2108 if( abf
->retVal
== MGU_SUCCESS
) retVal
= TRUE
;
2110 addrbook_free_book( abf
);
2112 addrindex_free_node( rootNode
);
2115 /* Create entries in address index */
2117 abf
= addrbook_create_book();
2118 addrbook_set_name( abf
, displayName
);
2119 addrbook_set_path( abf
, addrIndex
->filePath
);
2120 addrbook_set_file( abf
, newFile
);
2121 addrindex_index_add_datasource( addrIndex
, ADDR_IF_BOOK
, abf
);
2128 * Process tree converting data.
2130 static void addrindex_convert_tree( AddressIndex
*addrIndex
, XMLFile
*file
) {
2138 prev_level
= file
->level
;
2139 xml_parse_next_tag( file
);
2140 if (file
->level
< prev_level
) return;
2142 xtag
= xml_get_current_tag( file
);
2143 /* g_print( "tag : %d : %s\n", prev_level, xtag->tag ); */
2144 if( strcmp( xtag
->tag
, TAG_IF_OLD_COMMON
) == 0 ) {
2145 if( addrindex_process_book( addrIndex
, file
, DISP_OLD_COMMON
) ) {
2146 addrIndex
->needsConversion
= FALSE
;
2147 addrIndex
->wasConverted
= TRUE
;
2152 if( strcmp( xtag
->tag
, TAG_IF_OLD_PERSONAL
) == 0 ) {
2153 if( addrindex_process_book( addrIndex
, file
, DISP_OLD_PERSONAL
) ) {
2154 addrIndex
->needsConversion
= FALSE
;
2155 addrIndex
->wasConverted
= TRUE
;
2160 element
= xml_get_element( file
);
2161 attr
= xml_get_current_tag_attr( file
);
2162 /* show_attribs( attr ); */
2163 /* g_print( "\ttag value : %s :\n", element ); */
2164 addrindex_consume_tree( file
);
2168 static gint
addrindex_convert_data( AddressIndex
*addrIndex
) {
2169 XMLFile
*file
= NULL
;
2172 fileSpec
= g_strconcat( addrIndex
->filePath
, G_DIR_SEPARATOR_S
, addrIndex
->fileName
, NULL
);
2173 addrIndex
->retVal
= MGU_NO_FILE
;
2174 file
= xml_open_file( fileSpec
);
2177 if( file
== NULL
) {
2178 /* g_print( " file '%s' does not exist.\n", addrIndex->fileName ); */
2179 return addrIndex
->retVal
;
2182 addrIndex
->retVal
= MGU_BAD_FORMAT
;
2183 if( xml_get_dtd( file
) == 0 ) {
2184 if( xml_parse_next_tag( file
) == 0 ) {
2185 if( xml_compare_tag( file
, TAG_ADDRESS_INDEX
) ) {
2186 addrindex_convert_tree( addrIndex
, file
);
2190 xml_close_file( file
);
2191 return addrIndex
->retVal
;
2195 * Create a new address book file.
2197 static gboolean
addrindex_create_new_book( AddressIndex
*addrIndex
, gchar
*displayName
) {
2198 gboolean retVal
= FALSE
;
2199 AddressBookFile
*abf
= NULL
;
2200 gchar
*newFile
= NULL
;
2201 GList
*fileList
= NULL
;
2204 /* Create new address book */
2205 abf
= addrbook_create_book();
2206 addrbook_set_name( abf
, displayName
);
2207 addrbook_set_path( abf
, addrIndex
->filePath
);
2209 /* Determine next available file number */
2210 fileList
= addrbook_get_bookfile_list( abf
);
2212 fileNum
= 1 + abf
->maxValue
;
2214 g_list_free( fileList
);
2217 newFile
= addrbook_gen_new_file_name( fileNum
);
2219 addrbook_set_file( abf
, newFile
);
2222 addrbook_save_data( abf
);
2223 addrIndex
->retVal
= abf
->retVal
;
2224 if( abf
->retVal
== MGU_SUCCESS
) retVal
= TRUE
;
2225 addrbook_free_book( abf
);
2228 /* Create entries in address index */
2230 abf
= addrbook_create_book();
2231 addrbook_set_name( abf
, displayName
);
2232 addrbook_set_path( abf
, addrIndex
->filePath
);
2233 addrbook_set_file( abf
, newFile
);
2234 addrindex_index_add_datasource( addrIndex
, ADDR_IF_BOOK
, abf
);
2241 * Read data for address index performing a conversion if necesary.
2242 * Enter: addrIndex Address index object.
2243 * return: Status code, from addrIndex->retVal.
2244 * Note: New address book files will be created in directory specified by
2245 * addrIndex. Three files will be created, for the following:
2246 * "Common addresses"
2247 * "Personal addresses"
2248 * "Gathered addresses" - a new address book.
2250 gint
addrindex_read_data( AddressIndex
*addrIndex
) {
2251 g_return_val_if_fail( addrIndex
!= NULL
, -1 );
2253 addrIndex
->conversionError
= FALSE
;
2254 addrindex_read_file( addrIndex
);
2255 if( addrIndex
->retVal
== MGU_SUCCESS
) {
2256 if( addrIndex
->needsConversion
) {
2257 if( addrindex_convert_data( addrIndex
) == MGU_SUCCESS
) {
2258 addrIndex
->conversionError
= TRUE
;
2261 addrIndex
->conversionError
= TRUE
;
2264 addrIndex
->dirtyFlag
= TRUE
;
2266 return addrIndex
->retVal
;
2270 * Create new address books for a new address index.
2271 * Enter: addrIndex Address index object.
2272 * return: Status code, from addrIndex->retVal.
2273 * Note: New address book files will be created in directory specified by
2274 * addrIndex. Three files will be created, for the following:
2275 * "Common addresses"
2276 * "Personal addresses"
2277 * "Gathered addresses" - a new address book.
2279 gint
addrindex_create_new_books( AddressIndex
*addrIndex
) {
2282 g_return_val_if_fail( addrIndex
!= NULL
, -1 );
2284 flg
= addrindex_create_new_book( addrIndex
, DISP_NEW_COMMON
);
2286 flg
= addrindex_create_new_book( addrIndex
, DISP_NEW_PERSONAL
);
2287 addrIndex
->dirtyFlag
= TRUE
;
2289 return addrIndex
->retVal
;
2292 /* **********************************************************************
2293 * New interface stuff.
2294 * ***********************************************************************
2298 * Return modified flag for specified data source.
2300 gboolean
addrindex_ds_get_modify_flag( AddressDataSource
*ds
) {
2301 gboolean retVal
= FALSE
;
2302 AddressInterface
*iface
;
2304 if( ds
== NULL
) return retVal
;
2305 iface
= ds
->interface
;
2306 if( iface
== NULL
) return retVal
;
2307 if( iface
->getModifyFlag
) {
2308 retVal
= ( iface
->getModifyFlag
) ( ds
->rawDataSource
);
2314 * Return accessed flag for specified data source.
2316 gboolean
addrindex_ds_get_access_flag( AddressDataSource
*ds
) {
2317 gboolean retVal
= FALSE
;
2318 AddressInterface
*iface
;
2320 if( ds
== NULL
) return retVal
;
2321 iface
= ds
->interface
;
2322 if( iface
== NULL
) return retVal
;
2323 if( iface
->getAccessFlag
) {
2324 retVal
= ( iface
->getAccessFlag
) ( ds
->rawDataSource
);
2330 * Return data read flag for specified data source.
2332 gboolean
addrindex_ds_get_read_flag( AddressDataSource
*ds
) {
2333 gboolean retVal
= TRUE
;
2334 AddressInterface
*iface
;
2336 if( ds
== NULL
) return retVal
;
2337 iface
= ds
->interface
;
2338 if( iface
== NULL
) return retVal
;
2339 if( iface
->getReadFlag
) {
2340 retVal
= ( iface
->getReadFlag
) ( ds
->rawDataSource
);
2346 * Return status code for specified data source.
2348 gint
addrindex_ds_get_status_code( AddressDataSource
*ds
) {
2349 gint retVal
= MGU_SUCCESS
;
2350 AddressInterface
*iface
;
2352 if( ds
== NULL
) return retVal
;
2353 iface
= ds
->interface
;
2354 if( iface
== NULL
) return retVal
;
2355 if( iface
->getStatusCode
) {
2356 retVal
= ( iface
->getStatusCode
) ( ds
->rawDataSource
);
2362 * Return data read flag for specified data source.
2364 gint
addrindex_ds_read_data( AddressDataSource
*ds
) {
2365 gint retVal
= MGU_SUCCESS
;
2366 AddressInterface
*iface
;
2368 if( ds
== NULL
) return retVal
;
2369 iface
= ds
->interface
;
2370 if( iface
== NULL
) return retVal
;
2371 if( iface
->getReadData
) {
2373 gchar *name = ( iface->getName ) ( ds->rawDataSource );
2374 g_print( "addrindex_ds_read_data...reading:::%s:::\n", name );
2376 retVal
= ( iface
->getReadData
) ( ds
->rawDataSource
);
2382 * Return data read flag for specified data source.
2384 ItemFolder
*addrindex_ds_get_root_folder( AddressDataSource
*ds
) {
2385 ItemFolder
*retVal
= NULL
;
2386 AddressInterface
*iface
;
2388 if( ds
== NULL
) return retVal
;
2389 iface
= ds
->interface
;
2390 if( iface
== NULL
) return retVal
;
2391 if( iface
->getRootFolder
) {
2392 retVal
= ( iface
->getRootFolder
) ( ds
->rawDataSource
);
2398 * Return name for specified data source.
2400 gchar
*addrindex_ds_get_name( AddressDataSource
*ds
) {
2401 gchar
*retVal
= FALSE
;
2402 AddressInterface
*iface
;
2404 if( ds
== NULL
) return retVal
;
2405 iface
= ds
->interface
;
2406 if( iface
== NULL
) return retVal
;
2407 if( iface
->getName
) {
2408 retVal
= ( iface
->getName
) ( ds
->rawDataSource
);
2414 * Set the access flag inside the data source.
2416 void addrindex_ds_set_access_flag( AddressDataSource
*ds
, gboolean
*value
) {
2417 AddressInterface
*iface
;
2419 if( ds
== NULL
) return;
2420 iface
= ds
->interface
;
2421 if( iface
== NULL
) return;
2422 if( iface
->setAccessFlag
) {
2423 ( iface
->setAccessFlag
) ( ds
->rawDataSource
, value
);
2428 * Return read only flag for specified data source.
2430 gboolean
addrindex_ds_get_readonly( AddressDataSource
*ds
) {
2431 AddressInterface
*iface
;
2432 if( ds
== NULL
) return TRUE
;
2433 iface
= ds
->interface
;
2434 if( iface
== NULL
) return TRUE
;
2435 return iface
->readOnly
;
2439 * Return list of all persons for specified data source.
2441 static GList
*addrindex_ds_get_all_persons( AddressDataSource
*ds
) {
2442 GList
*retVal
= NULL
;
2443 AddressInterface
*iface
;
2445 if( ds
== NULL
) return retVal
;
2446 iface
= ds
->interface
;
2447 if( iface
== NULL
) return retVal
;
2448 if( iface
->getAllPersons
) {
2449 retVal
= ( iface
->getAllPersons
) ( ds
->rawDataSource
);
2455 * Return list of all groups for specified data source.
2457 static GList
*addrindex_ds_get_all_groups( AddressDataSource
*ds
) {
2458 GList
*retVal
= NULL
;
2459 AddressInterface
*iface
;
2461 if( ds
== NULL
) return retVal
;
2462 iface
= ds
->interface
;
2463 if( iface
== NULL
) return retVal
;
2464 if( iface
->getAllGroups
) {
2465 retVal
= ( iface
->getAllGroups
) ( ds
->rawDataSource
);
2470 /* **********************************************************************
2471 * Address search stuff.
2472 * ***********************************************************************
2476 * Setup or register the dynamic search that will be performed. The search
2477 * is registered with the query manager.
2479 * \param searchTerm Search term. A private copy will be made.
2480 * \param callBackEntry Callback function that should be called when
2481 * each entry is received.
2482 * \param callBackEnd Callback function that should be called when
2483 * search has finished running.
2484 * \return ID allocated to query that will be executed.
2486 gint
addrindex_setup_search(
2487 const gchar
*searchTerm
, void *callBackEnd
, void *callBackEntry
)
2492 /* Set up a dynamic address query */
2493 req
= qrymgr_add_request( searchTerm
, callBackEnd
, callBackEntry
);
2494 queryID
= req
->queryID
;
2495 qryreq_set_search_type( req
, ADDRSEARCH_DYNAMIC
);
2497 /* g_print( "***> query ID ::%d::\n", queryID ); */
2504 * Function prototypes (not in header file or circular reference errors are
2507 LdapQuery
*ldapsvr_new_dynamic_search(
2508 LdapServer
*server
, QueryRequest
*req
);
2509 LdapQuery
*ldapsvr_new_explicit_search(
2510 LdapServer
*server
, QueryRequest
*req
, ItemFolder
*folder
);
2511 void ldapsvr_execute_query( LdapServer
*server
, LdapQuery
*qry
);
2516 * Execute the previously registered dynamic search.
2518 * \param req Address query object to execute.
2519 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2522 static gboolean
addrindex_start_dynamic( QueryRequest
*req
) {
2523 AddressInterface
*iface
;
2524 AddressDataSource
*ds
;
2529 /* g_print( "addrindex_start_dynamic::%d::\n", req->queryID ); */
2530 nodeIf
= _addressIndex_
->searchOrder
;
2532 iface
= nodeIf
->data
;
2533 nodeIf
= g_list_next( nodeIf
);
2535 if( ! iface
->useInterface
) {
2538 if( ! iface
->externalQuery
) {
2543 nodeDS
= iface
->listSource
;
2546 nodeDS
= g_list_next( nodeDS
);
2548 if( type
== ADDR_IF_LDAP
) {
2552 server
= ds
->rawDataSource
;
2553 if( ! server
->searchFlag
) {
2556 if( ldapsvr_reuse_previous( server
, req
) ) {
2560 /* Start a new dynamic search */
2561 qry
= ldapsvr_new_dynamic_search( server
, req
);
2563 ldapsvr_execute_query( server
, qry
);
2573 * Stop the previously registered search.
2575 * \param queryID ID of search query to stop.
2577 void addrindex_stop_search( const gint queryID
){
2579 AddrQueryObject
*aqo
;
2582 /* g_print( "addrindex_stop_search/queryID=%d\n", queryID ); */
2583 /* If query ID does not match, search has not been setup */
2584 req
= qrymgr_find_request( queryID
);
2589 /* Stop all queries that were associated with request */
2590 node
= req
->queryList
;
2594 if( aqo
->queryType
== ADDRQUERY_LDAP
) {
2595 LdapQuery
*qry
= ( LdapQuery
* ) aqo
;
2596 ldapqry_set_stop_flag( qry
, TRUE
);
2600 node
= g_list_next( node
);
2603 /* Delete query request */
2604 qrymgr_delete_request( queryID
);
2608 * Setup or register the explicit search that will be performed. The search is
2609 * registered with the query manager.
2611 * \param ds Data source to search.
2612 * \param searchTerm Search term to locate.
2613 * \param folder Folder to receive search results; may be NULL.
2614 * \param callbackEnd Function to call when search has terminated.
2615 * \param callbackEntry Function to called for each entry processed.
2616 * \return ID allocated to query that will be executed.
2618 gint
addrindex_setup_explicit_search(
2619 AddressDataSource
*ds
, const gchar
*searchTerm
, ItemFolder
*folder
,
2620 void *callBackEnd
, void *callBackEntry
)
2627 /* Name the query */
2628 name
= g_strdup_printf( "Search '%s'", searchTerm
);
2630 /* Set up query request */
2631 if (!strcmp(searchTerm
, "*"))
2632 mySearch
= g_strdup("*@");
2634 mySearch
= g_strdup(searchTerm
);
2636 req
= qrymgr_add_request( mySearch
, callBackEnd
, callBackEntry
);
2640 qryreq_set_search_type( req
, ADDRSEARCH_EXPLICIT
);
2641 queryID
= req
->queryID
;
2643 if( ds
->type
== ADDR_IF_LDAP
) {
2647 server
= ds
->rawDataSource
;
2648 ldapsvr_new_explicit_search( server
, req
, folder
);
2652 qrymgr_delete_request( queryID
);
2661 * Execute the previously registered explicit search.
2663 * \param req Address query request object to execute.
2664 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2667 static gboolean
addrindex_start_explicit( QueryRequest
*req
) {
2669 AddrQueryObject
*aqo
;
2673 /* Note: there should only be one query in the list. */
2674 aqo
= req
->queryList
->data
;
2676 if( aqo
->queryType
== ADDRQUERY_LDAP
) {
2680 qry
= ( LdapQuery
* ) aqo
;
2681 server
= qry
->server
;
2683 /* Start the search */
2685 ldapsvr_execute_query( server
, qry
);
2692 * Start the previously registered search.
2694 * \param queryID ID of search query to be executed.
2695 * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
2698 gboolean
addrindex_start_search( const gint queryID
) {
2701 AddrSearchType searchType
;
2704 /* g_print( "addrindex_start_search/queryID=%d\n", queryID ); */
2705 req
= qrymgr_find_request( queryID
);
2710 searchType
= req
->searchType
;
2711 if( searchType
== ADDRSEARCH_DYNAMIC
) {
2712 retVal
= addrindex_start_dynamic( req
);
2714 else if( searchType
== ADDRSEARCH_EXPLICIT
) {
2715 retVal
= addrindex_start_explicit( req
);
2722 * Remove results (folder and data) for specified data source and folder.
2723 * \param ds Data source to process.
2724 * \param folder Results folder to remove.
2726 void addrindex_remove_results( AddressDataSource
*ds
, ItemFolder
*folder
) {
2727 AddrBookBase
*adbase
;
2728 AddressCache
*cache
;
2731 /* g_print( "addrindex_remove_results/start\n" ); */
2733 /* Test for folder */
2734 if( folder
->folderType
!= ADDRFOLDER_QUERY_RESULTS
) return;
2735 /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
2736 adbase
= ( AddrBookBase
* ) ds
->rawDataSource
;
2737 if( adbase
== NULL
) return;
2738 cache
= adbase
->addressCache
;
2740 /* Hide folder to prevent re-display */
2741 addritem_folder_set_hidden( folder
, TRUE
);
2743 if( ds
->type
== ADDR_IF_LDAP
) {
2748 qry
= ( LdapQuery
* ) folder
->folderData
;
2749 queryID
= ADDRQUERY_ID(qry
);
2750 /* g_print( "calling ldapquery_remove_results...queryID=%d\n", queryID ); */
2751 delFlag
= ldapquery_remove_results( qry
);
2753 ldapqry_free( qry
);
2755 /* g_print( "calling ldapquery_remove_results...done\n" ); */
2758 g_print( "delFlag IS-TRUE\n" );
2761 g_print( "delFlag IS-FALSE\n" );
2766 /* g_print( "addrindex_remove_results/end\n" ); */
2768 /* Delete query request */
2770 qrymgr_delete_request( queryID
);
2774 /* **********************************************************************
2775 * Address completion stuff.
2776 * ***********************************************************************
2779 static void addrindex_load_completion_load_persons(
2780 gint (*callBackFunc
) ( const gchar
*, const gchar
*,
2781 const gchar
*, const gchar
*, GList
* ),
2782 AddressDataSource
*ds
)
2784 GList
*listP
, *nodeP
;
2788 /* Read address book */
2789 if( addrindex_ds_get_modify_flag( ds
) ) {
2790 addrindex_ds_read_data( ds
);
2793 if( ! addrindex_ds_get_read_flag( ds
) ) {
2794 addrindex_ds_read_data( ds
);
2797 /* Get all groups */
2798 listP
= addrindex_ds_get_all_groups( ds
);
2801 ItemGroup
*group
= nodeP
->data
;
2802 GList
*emails
= NULL
;
2803 for (nodeM
= group
->listEMail
; nodeM
; nodeM
= g_list_next(nodeM
)) {
2804 ItemEMail
*email
= nodeM
->data
;
2806 emails
= g_list_append(emails
, email
);
2808 callBackFunc( ((AddrItemObject
*)group
)->name
, NULL
,
2809 NULL
, NULL
, emails
);
2810 nodeP
= g_list_next( nodeP
);
2813 /* Free up the list */
2814 g_list_free( listP
);
2815 /* Get all persons */
2816 listP
= addrindex_ds_get_all_persons( ds
);
2819 ItemPerson
*person
= nodeP
->data
;
2820 nodeM
= person
->listEMail
;
2822 /* Figure out name to use */
2823 sName
= ADDRITEM_NAME(person
);
2824 if( sName
== NULL
|| *sName
== '\0' ) {
2825 sName
= person
->nickName
;
2828 /* Process each E-Mail address */
2830 ItemEMail
*email
= nodeM
->data
;
2832 callBackFunc( sName
, email
->address
, person
->nickName
,
2833 ADDRITEM_NAME(email
), NULL
);
2835 nodeM
= g_list_next( nodeM
);
2837 nodeP
= g_list_next( nodeP
);
2840 /* Free up the list */
2841 g_list_free( listP
);
2845 * This function is used by the address completion function to load
2846 * addresses for all non-external address book interfaces.
2848 * \param callBackFunc Function to be called when an address is
2850 * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
2851 * or "Any", assume the whole addressbook
2852 * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
2855 gboolean
addrindex_load_completion(
2856 gint (*callBackFunc
) ( const gchar
*, const gchar
*,
2857 const gchar
*, const gchar
*, GList
* ),
2860 GList
*nodeIf
, *nodeDS
;
2862 if( folderpath
!= NULL
) {
2863 AddressDataSource
*book
;
2866 /* split the folder path we've received, we'll try to match this path, subpath by
2867 subpath against the book/folder structure in order and restrict loading of
2868 addresses to that subpart (if matches). book/folder path must exist and
2869 folderpath must not be empty or NULL */
2871 if( ! addressbook_peek_folder_exists( folderpath
, &book
, &folder
) ) {
2872 g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath
);
2876 if( folder
!= NULL
) {
2883 debug_print("addrindex_load_completion: folder %p '%s'\n", folder
, folder
->obj
.name
);
2885 /* Load email addresses */
2886 items
= addritem_folder_get_person_list( folder
);
2887 for( ; items
!= NULL
; items
= g_list_next( items
) ) {
2888 person
= items
->data
;
2889 nodeM
= person
->listEMail
;
2891 /* Figure out name to use */
2892 sName
= ADDRITEM_NAME(person
);
2893 if( sName
== NULL
|| *sName
== '\0' ) {
2894 sName
= person
->nickName
;
2897 /* Process each E-Mail address */
2899 ItemEMail
*email
= nodeM
->data
;
2901 callBackFunc( sName
, email
->address
, person
->nickName
,
2902 ADDRITEM_NAME(email
), NULL
);
2904 nodeM
= g_list_next( nodeM
);
2907 /* Free up the list */
2908 mgu_clear_list( items
);
2909 g_list_free( items
);
2915 if( book
!= NULL
) {
2917 AddressBookFile
*abf
= book
->rawDataSource
;
2919 debug_print("addrindex_load_completion: book %p '%s'\n", book
, abf
?abf
->fileName
:"(null)");
2921 addrindex_load_completion_load_persons( callBackFunc
, book
);
2926 g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
2933 nodeIf
= addrindex_get_interface_list( _addressIndex_
);
2935 AddressInterface
*iface
= nodeIf
->data
;
2937 nodeIf
= g_list_next( nodeIf
);
2939 if( ! iface
->useInterface
|| iface
->externalQuery
)
2942 nodeDS
= iface
->listSource
;
2944 addrindex_load_completion_load_persons( callBackFunc
, nodeDS
->data
);
2945 nodeDS
= g_list_next( nodeDS
);
2954 * This function can be used to collect information about
2955 * addressbook entries that contain a specific attribute.
2957 * \param attr Name of attribute to look for
2958 * \param callBackFunc Function to be called when a matching attribute was found
2959 * \return <i>TRUE</i>
2961 gboolean
addrindex_load_person_attribute(
2963 gint (*callBackFunc
) ( ItemPerson
*, const gchar
* ) )
2965 AddressDataSource
*ds
;
2966 GList
*nodeIf
, *nodeDS
;
2967 GList
*listP
, *nodeP
;
2970 nodeIf
= addrindex_get_interface_list( _addressIndex_
);
2973 AddressInterface
*iface
= nodeIf
->data
;
2975 nodeIf
= g_list_next( nodeIf
);
2977 if( ! iface
->useInterface
|| iface
->externalQuery
)
2980 nodeDS
= iface
->listSource
;
2984 /* Read address book */
2985 if( addrindex_ds_get_modify_flag( ds
) ) {
2986 addrindex_ds_read_data( ds
);
2989 if( ! addrindex_ds_get_read_flag( ds
) ) {
2990 addrindex_ds_read_data( ds
);
2993 /* Check addressbook name */
2994 cur_bname
= addrindex_ds_get_name( ds
);
2996 /* Get all persons */
2997 listP
= addrindex_ds_get_all_persons( ds
);
3000 ItemPerson
*person
= nodeP
->data
;
3002 /* Return all ItemPerson's if attr is NULL */
3003 if( attr
== NULL
) {
3004 callBackFunc(person
, cur_bname
);
3007 /* Return ItemPerson's with specific attribute */
3009 nodeA
= person
->listAttrib
;
3010 /* Process each User Attribute */
3012 UserAttribute
*attrib
= nodeA
->data
;
3014 !strcmp( attrib
->name
,attr
) ) {
3015 callBackFunc(person
, cur_bname
);
3017 nodeA
= g_list_next( nodeA
);
3020 nodeP
= g_list_next( nodeP
);
3022 /* Free up the list */
3023 g_list_free( listP
);
3025 nodeDS
= g_list_next( nodeDS
);