2 * Claws Mail -- 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 * Functions to maintain address cache.
31 #include "addrcache.h"
34 #define ID_TIME_OFFSET 998000000
35 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
37 static int _nextCacheID__
= 0;
40 * Generate next cache ID.
42 static int addrcache_next_cache_id() {
45 if( _nextCacheID__
== 0 ) {
48 retVal
= _nextCacheID__
;
54 * Create new address cache.
56 AddressCache
*addrcache_create() {
60 cache
= g_new0( AddressCache
, 1 );
61 cache
->itemHash
= g_hash_table_new( g_str_hash
, g_str_equal
);
62 cache
->cacheID
= g_strdup_printf( "%d", addrcache_next_cache_id() );
64 cache
->dataRead
= FALSE
;
65 cache
->modified
= FALSE
;
66 cache
->dirtyFlag
= FALSE
;
67 cache
->accessFlag
= FALSE
;
69 cache
->modifyTime
= 0;
71 /* Generate the next ID using system time */
75 cache
->nextID
= t
- ID_TIME_OFFSET
;
78 cache
->tempList
= NULL
;
79 cache
->rootFolder
= addritem_create_item_folder();
80 cache
->rootFolder
->isRoot
= TRUE
;
81 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
88 ItemFolder
*addrcache_get_root_folder( AddressCache
*cache
) {
89 cm_return_val_if_fail( cache
!= NULL
, NULL
);
90 return cache
->rootFolder
;
92 GList
*addrcache_get_list_folder( AddressCache
*cache
) {
93 cm_return_val_if_fail( cache
!= NULL
, NULL
);
94 return cache
->rootFolder
->listFolder
;
96 GList
*addrcache_get_list_person( AddressCache
*cache
) {
97 cm_return_val_if_fail( cache
!= NULL
, NULL
);
98 return cache
->rootFolder
->listPerson
;
100 gboolean
addrcache_get_dirty( AddressCache
*cache
) {
101 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
102 return cache
->dirtyFlag
;
104 void addrcache_set_dirty( AddressCache
*cache
, const gboolean value
) {
105 cm_return_if_fail( cache
!= NULL
);
106 cache
->dirtyFlag
= value
;
108 gchar
*addrcache_get_name( AddressCache
*cache
) {
109 cm_return_val_if_fail( cache
!= NULL
, NULL
);
112 void addrcache_set_name( AddressCache
*cache
, const gchar
*value
) {
113 cm_return_if_fail( cache
!= NULL
);
114 cache
->name
= mgu_replace_string( cache
->name
, value
);
115 g_strstrip( cache
->name
);
116 cache
->dirtyFlag
= TRUE
;
122 static void addrcache_next_id( AddressCache
*cache
) {
123 cm_return_if_fail( cache
!= NULL
);
128 * Refresh internal variables. This can be used force a reload.
130 void addrcache_refresh( AddressCache
*cache
) {
131 cache
->dataRead
= FALSE
;
132 cache
->modified
= TRUE
;
133 cache
->accessFlag
= FALSE
;
134 cache
->modifyTime
= 0;
138 * Free hash table visitor function.
140 static gint
addrcache_free_item_vis( gpointer key
, gpointer value
, gpointer data
) {
141 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
143 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_PERSON
) {
144 addritem_free_item_person( ( ItemPerson
* ) obj
);
146 else if( ADDRITEM_TYPE(obj
) == ITEMTYPE_EMAIL
) {
147 addritem_free_item_email( ( ItemEMail
* ) obj
);
149 else if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
150 addritem_free_item_group( ( ItemGroup
* ) obj
);
152 else if( ADDRITEM_TYPE(obj
) == ITEMTYPE_FOLDER
) {
153 addritem_free_item_folder( ( ItemFolder
* ) obj
);
161 * Free hash table of address cache items.
163 static void addrcache_free_item_hash( GHashTable
*table
) {
164 cm_return_if_fail( table
!= NULL
);
165 g_hash_table_foreach_remove( table
, addrcache_free_item_vis
, NULL
);
169 * Free up folders and groups.
171 static void addrcache_free_all_folders( ItemFolder
*parent
) {
174 if( parent
== NULL
) return;
176 node
= parent
->listFolder
;
178 ItemFolder
*folder
= node
->data
;
179 addrcache_free_all_folders( folder
);
181 node
= g_list_next( node
);
183 g_list_free( parent
->listPerson
);
184 g_list_free( parent
->listGroup
);
185 g_list_free( parent
->listFolder
);
186 parent
->listPerson
= NULL
;
187 parent
->listGroup
= NULL
;
188 parent
->listFolder
= NULL
;
192 * Clear the address cache.
194 void addrcache_clear( AddressCache
*cache
) {
195 cm_return_if_fail( cache
!= NULL
);
197 /* g_print( "...addrcache_clear :%s:\n", cache->name ); */
198 /* Free up folders and hash table */
199 addrcache_free_all_folders( cache
->rootFolder
);
200 addrcache_free_item_hash( cache
->itemHash
);
201 g_hash_table_destroy( cache
->itemHash
);
202 cache
->itemHash
= NULL
;
203 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
204 addritem_free_item_folder( cache
->rootFolder
);
205 cache
->rootFolder
= NULL
;
206 if( cache
->tempList
) g_list_free( cache
->tempList
);
207 cache
->tempList
= NULL
;
209 /* Reset to initial state */
210 cache
->itemHash
= g_hash_table_new( g_str_hash
, g_str_equal
);
211 cache
->rootFolder
= addritem_create_item_folder();
212 cache
->rootFolder
->isRoot
= TRUE
;
213 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
215 addrcache_refresh( cache
);
219 * Free address cache.
221 void addrcache_free( AddressCache
*cache
) {
222 cm_return_if_fail( cache
!= NULL
);
224 cache
->dirtyFlag
= FALSE
;
225 addrcache_free_all_folders( cache
->rootFolder
);
226 addrcache_free_item_hash( cache
->itemHash
);
227 g_hash_table_destroy( cache
->itemHash
);
228 cache
->itemHash
= NULL
;
229 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
230 addritem_free_item_folder( cache
->rootFolder
);
231 cache
->rootFolder
= NULL
;
232 g_list_free( cache
->tempList
);
233 cache
->tempList
= NULL
;
234 g_free( cache
->cacheID
);
235 cache
->cacheID
= NULL
;
236 g_free( cache
->name
);
242 * Check whether file has changed by comparing with cache.
243 * return: TRUE if file has changed.
245 gboolean
addrcache_check_file( AddressCache
*cache
, gchar
*path
) {
250 if( 0 == g_stat( path
, &filestat
) ) {
251 if( filestat
.st_mtime
== cache
->modifyTime
) retVal
= FALSE
;
258 * Save file time to cache.
259 * return: TRUE if time marked.
261 gboolean
addrcache_mark_file( AddressCache
*cache
, gchar
*path
) {
262 gboolean retVal
= FALSE
;
265 if( 0 == g_stat( path
, &filestat
) ) {
266 cache
->modifyTime
= filestat
.st_mtime
;
274 * Dump entire address cache hash table contents.
276 void addrcache_print( AddressCache
*cache
, FILE *stream
) {
277 cm_return_if_fail( cache
!= NULL
);
278 fprintf( stream
, "AddressCache:\n" );
279 fprintf( stream
, "cache id : %s\n", cache
->cacheID
);
280 fprintf( stream
, "next id : %d\n", cache
->nextID
);
281 fprintf( stream
, "name : %s\n", cache
->name
);
282 fprintf( stream
, "mod time : %ld\n", (long int)cache
->modifyTime
);
283 fprintf( stream
, "modified : %s\n", cache
->modified
? "yes" : "no" );
284 fprintf( stream
, "data read: %s\n", cache
->dataRead
? "yes" : "no" );
288 * Allocate ID for person.
290 void addrcache_id_person( AddressCache
*cache
, ItemPerson
*person
) {
291 cm_return_if_fail( cache
!= NULL
);
292 cm_return_if_fail( person
!= NULL
);
293 if( ADDRITEM_ID(person
) ) return;
294 addrcache_next_id( cache
);
295 ADDRITEM_ID(person
) = g_strdup_printf( "%d", cache
->nextID
);
299 * Allocate ID for group.
301 void addrcache_id_group( AddressCache
*cache
, ItemGroup
*group
) {
302 cm_return_if_fail( cache
!= NULL
);
303 cm_return_if_fail( group
!= NULL
);
304 if( ADDRITEM_ID(group
) ) return;
305 addrcache_next_id( cache
);
306 ADDRITEM_ID(group
) = g_strdup_printf( "%d", cache
->nextID
);
310 * Allocate ID for folder.
312 void addrcache_id_folder( AddressCache
*cache
, ItemFolder
*folder
) {
313 cm_return_if_fail( cache
!= NULL
);
314 cm_return_if_fail( folder
!= NULL
);
315 if( ADDRITEM_ID(folder
) ) return;
316 addrcache_next_id( cache
);
317 ADDRITEM_ID(folder
) = g_strdup_printf( "%d", cache
->nextID
);
321 * Allocate ID for email address.
323 void addrcache_id_email( AddressCache
*cache
, ItemEMail
*email
) {
324 cm_return_if_fail( cache
!= NULL
);
325 cm_return_if_fail( email
!= NULL
);
326 if( ADDRITEM_ID(email
) ) return;
327 addrcache_next_id( cache
);
328 ADDRITEM_ID(email
) = g_strdup_printf( "%d", cache
->nextID
);
332 * Allocate ID for user attribute.
334 void addrcache_id_attribute( AddressCache
*cache
, UserAttribute
*attrib
) {
335 cm_return_if_fail( cache
!= NULL
);
336 cm_return_if_fail( attrib
!= NULL
);
337 if( attrib
->uid
) return;
338 addrcache_next_id( cache
);
339 attrib
->uid
= g_strdup_printf( "%d", cache
->nextID
);
343 * Add person to hash table.
344 * return: TRUE if item added.
346 gboolean
addrcache_hash_add_person( AddressCache
*cache
, ItemPerson
*person
) {
347 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(person
) ) ) {
350 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(person
), person
);
355 * Add email to hash table.
356 * return: TRUE if item added.
358 static gboolean
addrcache_hash_add_email( AddressCache
*cache
, ItemEMail
*email
) {
359 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(email
) ) ) {
362 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(email
), email
);
367 * Add group to hash table.
368 * return: TRUE if item added.
370 gboolean
addrcache_hash_add_group( AddressCache
*cache
, ItemGroup
*group
) {
371 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
372 cm_return_val_if_fail( group
!= NULL
, FALSE
);
374 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(group
) ) ) {
377 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(group
), group
);
382 * Add folder to hash table.
383 * return: TRUE if item added.
385 gboolean
addrcache_hash_add_folder( AddressCache
*cache
, ItemFolder
*folder
) {
386 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
387 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
389 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(folder
) ) ) {
392 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(folder
), folder
);
397 * Add person to specified folder in cache.
399 gboolean
addrcache_folder_add_person( AddressCache
*cache
, ItemFolder
*folder
, ItemPerson
*item
) {
400 gboolean retVal
= FALSE
;
402 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
403 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
404 cm_return_val_if_fail( item
!= NULL
, FALSE
);
406 retVal
= addrcache_hash_add_person( cache
, item
);
408 addritem_folder_add_person( folder
, item
);
409 cache
->dirtyFlag
= TRUE
;
415 * Add folder to specified folder in cache.
417 gboolean
addrcache_folder_add_folder( AddressCache
*cache
, ItemFolder
*folder
, ItemFolder
*item
) {
418 gboolean retVal
= FALSE
;
420 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
421 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
422 cm_return_val_if_fail( item
!= NULL
, FALSE
);
424 retVal
= addrcache_hash_add_folder( cache
, item
);
426 addritem_folder_add_folder( folder
, item
);
427 cache
->dirtyFlag
= TRUE
;
433 * Add folder to specified folder in cache.
435 gboolean
addrcache_folder_add_group( AddressCache
*cache
, ItemFolder
*folder
, ItemGroup
*item
) {
436 gboolean retVal
= FALSE
;
438 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
439 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
440 cm_return_val_if_fail( item
!= NULL
, FALSE
);
442 retVal
= addrcache_hash_add_group( cache
, item
);
444 addritem_folder_add_group( folder
, item
);
445 cache
->dirtyFlag
= TRUE
;
451 * Add person to address cache.
452 * return: TRUE if item added.
454 gboolean
addrcache_add_person( AddressCache
*cache
, ItemPerson
*person
) {
455 gboolean retVal
= FALSE
;
457 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
458 cm_return_val_if_fail( person
!= NULL
, FALSE
);
460 retVal
= addrcache_hash_add_person( cache
, person
);
462 addritem_folder_add_person( cache
->rootFolder
, person
);
463 cache
->dirtyFlag
= TRUE
;
469 * Add EMail address to person.
470 * return: TRUE if item added.
472 gboolean
addrcache_person_add_email( AddressCache
*cache
, ItemPerson
*person
, ItemEMail
*email
) {
473 gboolean retVal
= FALSE
;
475 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
476 cm_return_val_if_fail( person
!= NULL
, FALSE
);
477 cm_return_val_if_fail( email
!= NULL
, FALSE
);
479 retVal
= addrcache_hash_add_email( cache
, email
);
481 addritem_person_add_email( person
, email
);
482 cache
->dirtyFlag
= TRUE
;
488 * Add group to address cache.
489 * return: TRUE if item added.
491 gboolean
addrcache_add_group( AddressCache
*cache
, ItemGroup
*group
) {
492 gboolean retVal
= FALSE
;
494 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
495 cm_return_val_if_fail( group
!= NULL
, FALSE
);
497 retVal
= addrcache_hash_add_group( cache
, group
);
499 addritem_folder_add_group( cache
->rootFolder
, group
);
500 cache
->dirtyFlag
= TRUE
;
506 * Add EMail address to person.
507 * return: TRUE if item added.
509 gboolean
addrcache_group_add_email( AddressCache
*cache
, ItemGroup
*group
, ItemEMail
*email
) {
510 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
511 cm_return_val_if_fail( group
!= NULL
, FALSE
);
512 cm_return_val_if_fail( email
!= NULL
, FALSE
);
514 addritem_group_add_email( group
, email
);
515 cache
->dirtyFlag
= TRUE
;
520 * Add folder to address cache.
521 * return: TRUE if item added.
523 gboolean
addrcache_add_folder( AddressCache
*cache
, ItemFolder
*folder
) {
524 gboolean retVal
= FALSE
;
526 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
527 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
529 retVal
= addrcache_hash_add_folder( cache
, folder
);
531 addritem_folder_add_folder( cache
->rootFolder
, folder
);
532 cache
->dirtyFlag
= TRUE
;
538 * Move person to destination folder.
539 * Enter: cache Cache.
540 * person Person to move.
541 * target Target folder.
543 void addrcache_folder_move_person(
544 AddressCache
*cache
, ItemPerson
*person
, ItemFolder
*target
)
548 cm_return_if_fail( cache
!= NULL
);
549 cm_return_if_fail( person
!= NULL
);
551 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(person
);
552 if( ! parent
) parent
= cache
->rootFolder
;
553 parent
->listPerson
= g_list_remove( parent
->listPerson
, person
);
554 target
->listPerson
= g_list_append( target
->listPerson
, person
);
555 ADDRITEM_PARENT(person
) = ADDRITEM_OBJECT(target
);
556 cache
->dirtyFlag
= TRUE
;
560 * Move group to destination folder.
561 * Enter: cache Cache.
562 * group Group to move.
563 * target Target folder.
565 void addrcache_folder_move_group(
566 AddressCache
*cache
, ItemGroup
*group
, ItemFolder
*target
)
570 cm_return_if_fail( cache
!= NULL
);
571 cm_return_if_fail( group
!= NULL
);
573 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(group
);
574 if( ! parent
) parent
= cache
->rootFolder
;
575 parent
->listGroup
= g_list_remove( parent
->listGroup
, group
);
576 target
->listGroup
= g_list_append( target
->listGroup
, group
);
577 ADDRITEM_PARENT(group
) = ADDRITEM_OBJECT(target
);
578 cache
->dirtyFlag
= TRUE
;
582 * Move folder to destination folder.
583 * Enter: cache Cache.
584 * folder Folder to move.
585 * target Target folder.
587 void addrcache_folder_move_folder(
588 AddressCache
*cache
, ItemFolder
*folder
, ItemFolder
*target
)
592 cm_return_if_fail( cache
!= NULL
);
593 cm_return_if_fail( folder
!= NULL
);
595 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(folder
);
596 if( ! parent
) parent
= cache
->rootFolder
;
597 parent
->listFolder
= g_list_remove( parent
->listFolder
, folder
);
598 target
->listFolder
= g_list_append( target
->listFolder
, folder
);
599 ADDRITEM_PARENT(folder
) = ADDRITEM_OBJECT(target
);
600 cache
->dirtyFlag
= TRUE
;
604 * Return pointer to object (either person or group) for specified ID.
605 * param: uid Object ID.
606 * return: Object, or NULL if not found.
608 AddrItemObject
*addrcache_get_object( AddressCache
*cache
, const gchar
*uid
) {
609 AddrItemObject
*obj
= NULL
;
612 cm_return_val_if_fail( cache
!= NULL
, NULL
);
614 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
615 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
617 /* Check for matching UID */
618 uidH
= ADDRITEM_ID(obj
);
620 if( strcmp( uidH
, uid
) == 0 ) return obj
;
627 * Find email address in address cache.
628 * param: eid EMail ID.
629 * return: email object for specified object ID and email ID, or NULL if not found.
631 ItemEMail
*addrcache_get_email( AddressCache
*cache
, const gchar
*eid
) {
632 ItemEMail
*email
= NULL
;
633 AddrItemObject
*obj
= addrcache_get_object( cache
, eid
);
636 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_EMAIL
) {
637 email
= ( ItemEMail
* ) obj
;
644 * Remove group from address cache.
645 * param: group Group to remove.
646 * return: Group, or NULL if not found. Note that object should still be freed.
648 ItemGroup
*addrcache_remove_group( AddressCache
*cache
, ItemGroup
*group
) {
649 AddrItemObject
*obj
= NULL
;
651 cm_return_val_if_fail( cache
!= NULL
, NULL
);
654 gchar
*uid
= ADDRITEM_ID(group
);
655 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
656 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
658 ItemFolder
*parent
= ( ItemFolder
* ) ADDRITEM_PARENT(group
);
659 if( ! parent
) parent
= cache
->rootFolder
;
661 /* Remove group from parent's list and hash table */
662 parent
->listGroup
= g_list_remove( parent
->listGroup
, obj
);
663 g_hash_table_remove( cache
->itemHash
, uid
);
664 cache
->dirtyFlag
= TRUE
;
672 * Remove specified email from address cache. Note that object is only
673 * removed from cache and not parent objects.
674 * param: email EMail to remove.
675 * return: EMail, or NULL if not found. Note that object should still be freed.
677 ItemEMail
*addrcache_remove_email( AddressCache
*cache
, ItemEMail
*email
) {
678 AddrItemObject
*obj
= NULL
;
680 cm_return_val_if_fail( cache
!= NULL
, NULL
);
683 gchar
*eid
= ADDRITEM_ID(email
);
684 if( eid
== NULL
|| *eid
== '\0' ) return NULL
;
685 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, eid
);
687 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_EMAIL
) {
688 /* Remove email addresses from hash table. */
689 g_hash_table_remove( cache
->itemHash
, eid
);
690 cache
->dirtyFlag
= TRUE
;
699 * Hash table visitor function to remove email from group.
701 static void addrcache_allgrp_rem_email_vis( gpointer key
, gpointer value
, gpointer data
) {
702 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
703 ItemEMail
*email
= ( ItemEMail
* ) data
;
705 if( ! email
) return;
706 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
707 ItemGroup
*group
= ( ItemGroup
* ) value
;
709 /* Remove each email address that belongs to the person from the list */
710 group
->listEMail
= g_list_remove( group
->listEMail
, email
);
716 * Remove specified person from address cache.
717 * param: person Person to remove.
718 * return: Person, or NULL if not found. Note that object should still be freed.
720 ItemPerson
*addrcache_remove_person( AddressCache
*cache
, ItemPerson
*person
) {
721 AddrItemObject
*obj
= NULL
;
724 cm_return_val_if_fail( cache
!= NULL
, NULL
);
727 uid
= ADDRITEM_ID(person
);
728 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
729 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
731 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_PERSON
) {
735 /* Remove all email addresses for person */
736 /* from groups and from hash table */
737 node
= person
->listEMail
;
743 g_hash_table_foreach( cache
->itemHash
,
744 addrcache_allgrp_rem_email_vis
, email
);
745 eid
= ADDRITEM_ID( email
);
746 g_hash_table_remove( cache
->itemHash
, eid
);
747 node
= g_list_next( node
);
750 /* Remove person from owning folder */
751 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(person
);
752 if( ! parent
) parent
= cache
->rootFolder
;
753 parent
->listPerson
= g_list_remove( parent
->listPerson
, person
);
754 g_hash_table_remove( cache
->itemHash
, uid
);
755 cache
->dirtyFlag
= TRUE
;
764 * Remove email address in address cache for specified person.
765 * param: person Person.
766 * email EMail to remove.
767 * return: EMail object, or NULL if not found. Note that object should still be freed.
769 ItemEMail
*addrcache_person_remove_email( AddressCache
*cache
, ItemPerson
*person
, ItemEMail
*email
) {
770 ItemEMail
*found
= NULL
;
772 cm_return_val_if_fail( cache
!= NULL
, NULL
);
774 if( person
&& email
) {
775 found
= addritem_person_remove_email( person
, email
);
777 /* Remove email from all groups. */
778 g_hash_table_foreach( cache
->itemHash
, addrcache_allgrp_rem_email_vis
, email
);
780 /* Remove email from person's address list */
781 if( person
->listEMail
) {
782 person
->listEMail
= g_list_remove( person
->listEMail
, email
);
784 /* Unlink reference to person. */
785 ADDRITEM_PARENT(email
) = NULL
;
786 cache
->dirtyFlag
= TRUE
;
793 * Group visitor function.
795 static void addrcache_get_grp_person_vis( gpointer key
, gpointer value
, gpointer data
) {
796 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
798 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
799 AddressCache
*cache
= data
;
800 ItemGroup
*group
= ( ItemGroup
* ) obj
;
801 ItemPerson
*person
= ( ItemPerson
* ) cache
->tempList
->data
;
802 GList
*node
= group
->listEMail
;
804 ItemEMail
*email
= ( ItemEMail
* ) node
->data
;
805 if( ADDRITEM_PARENT(email
) == ADDRITEM_OBJECT(person
) ) {
806 if( ! g_list_find( cache
->tempList
, group
) ) {
807 cache
->tempList
= g_list_append( cache
->tempList
, group
);
810 node
= g_list_next( node
);
816 * Return linked list of groups which contain a reference to specified person's email
819 GList
*addrcache_get_group_for_person( AddressCache
*cache
, ItemPerson
*person
) {
822 cm_return_val_if_fail( cache
!= NULL
, NULL
);
824 cache
->tempList
= NULL
;
825 cache
->tempList
= g_list_append( cache
->tempList
, person
);
826 g_hash_table_foreach( cache
->itemHash
, addrcache_get_grp_person_vis
, cache
);
827 cache
->tempList
= g_list_remove( cache
->tempList
, person
);
828 list
= cache
->tempList
;
829 cache
->tempList
= NULL
;
834 * Get all person visitor function.
836 static void addrcache_get_all_persons_vis( gpointer key
, gpointer value
, gpointer data
) {
837 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
839 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_PERSON
) {
840 AddressCache
*cache
= data
;
841 cache
->tempList
= g_list_append( cache
->tempList
, obj
);
846 * Return link list of all persons in address cache. Note that the list contains
847 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
848 * this will destroy the address cache data!
849 * Return: List of items, or NULL if none.
851 GList
*addrcache_get_all_persons( AddressCache
*cache
) {
854 cm_return_val_if_fail( cache
!= NULL
, NULL
);
856 cache
->tempList
= NULL
;
857 g_hash_table_foreach( cache
->itemHash
, addrcache_get_all_persons_vis
, cache
);
858 list
= cache
->tempList
;
859 cache
->tempList
= NULL
;
864 * Get all groups visitor function.
866 static void addrcache_get_all_groups_vis( gpointer key
, gpointer value
, gpointer data
) {
867 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
869 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
870 AddressCache
*cache
= data
;
871 cache
->tempList
= g_list_append( cache
->tempList
, obj
);
876 * Return link list of all groups in address cache. Note that the list contains
877 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
878 * this will destroy the address cache data!
879 * Return: List of items, or NULL if none.
881 GList
*addrcache_get_all_groups( AddressCache
*cache
) {
884 cm_return_val_if_fail( cache
!= NULL
, NULL
);
886 cache
->tempList
= NULL
;
887 g_hash_table_foreach( cache
->itemHash
, addrcache_get_all_groups_vis
, cache
);
888 list
= cache
->tempList
;
889 cache
->tempList
= NULL
;
894 * Remove folder from cache. Children are re-parented to parent folder.
895 * param: folder Folder to remove.
896 * return: Folder, or NULL if not found. Note that object should still be freed.
898 ItemFolder
*addrcache_remove_folder( AddressCache
*cache
, ItemFolder
*folder
) {
899 AddrItemObject
*obj
= NULL
;
901 cm_return_val_if_fail( cache
!= NULL
, NULL
);
904 gchar
*uid
= ADDRITEM_ID(folder
);
905 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
906 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
908 ItemFolder
*parent
= ( ItemFolder
* ) ADDRITEM_PARENT(folder
);
911 if( ! parent
) parent
= cache
->rootFolder
;
913 /* Re-parent children in folder */
914 node
= folder
->listFolder
;
916 aio
= ( AddrItemObject
* ) node
->data
;
917 parent
->listFolder
= g_list_append( parent
->listFolder
, aio
);
918 aio
->parent
= ADDRITEM_OBJECT(parent
);
919 node
= g_list_next( node
);
921 node
= folder
->listPerson
;
923 aio
= ( AddrItemObject
* ) node
->data
;
924 parent
->listPerson
= g_list_append( parent
->listPerson
, aio
);
925 aio
->parent
= ADDRITEM_OBJECT(parent
);
926 node
= g_list_next( node
);
928 node
= folder
->listGroup
;
930 aio
= ( AddrItemObject
* ) node
->data
;
931 parent
->listGroup
= g_list_append( parent
->listGroup
, aio
);
932 aio
->parent
= ADDRITEM_OBJECT(parent
);
933 node
= g_list_next( node
);
936 /* Remove folder from parent's list and hash table */
937 parent
->listFolder
= g_list_remove( parent
->listFolder
, folder
);
938 ADDRITEM_PARENT(folder
) = NULL
;
939 g_hash_table_remove( cache
->itemHash
, uid
);
940 cache
->dirtyFlag
= TRUE
;
948 * Remove folder from cache. Children are deleted.
949 * param: folder Folder to remove.
950 * return: Folder, or NULL if not found. Note that object should still be freed.
952 ItemFolder
*addrcache_remove_folder_delete( AddressCache
*cache
, ItemFolder
*folder
) {
953 AddrItemObject
*obj
= NULL
;
955 cm_return_val_if_fail( cache
!= NULL
, NULL
);
958 gchar
*uid
= ADDRITEM_ID(folder
);
959 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
960 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
962 ItemFolder
*parent
= ( ItemFolder
* ) ADDRITEM_PARENT(folder
);
963 if( ! parent
) parent
= cache
->rootFolder
;
966 while( folder
->listGroup
) {
967 ItemGroup
*item
= ( ItemGroup
* ) folder
->listGroup
->data
;
968 item
= addrcache_remove_group( cache
, item
);
970 addritem_free_item_group( item
);
975 while( folder
->listPerson
) {
976 ItemPerson
*item
= ( ItemPerson
* ) folder
->listPerson
->data
;
977 item
= addrcache_remove_person( cache
, item
);
979 addritem_free_item_person( item
);
984 /* Recursive deletion of folder */
985 while( folder
->listFolder
) {
986 ItemFolder
*item
= ( ItemFolder
* ) folder
->listFolder
->data
;
987 item
= addrcache_remove_folder_delete( cache
, item
);
989 addritem_free_item_folder( item
);
994 /* Remove folder from parent's list and hash table */
995 parent
->listFolder
= g_list_remove( parent
->listFolder
, folder
);
996 ADDRITEM_PARENT(folder
) = NULL
;
997 g_hash_table_remove( cache
->itemHash
, uid
);
998 cache
->dirtyFlag
= TRUE
;
1006 * Add person and address data to cache.
1007 * \param cache Cache.
1008 * \param folder Folder where to add person, or NULL for root folder.
1009 * \param name Common name.
1010 * \param address EMail address.
1011 * \param remarks Remarks.
1012 * \return Person added. Do not *NOT* to use the
1013 * <code>addrbook_free_xxx()</code> functions...; this will destroy
1014 * the address book data.
1016 ItemPerson
*addrcache_add_contact(
1017 AddressCache
*cache
, ItemFolder
*folder
, const gchar
*name
,
1018 const gchar
*address
, const gchar
*remarks
)
1020 ItemPerson
*person
= NULL
;
1021 ItemEMail
*email
= NULL
;
1022 ItemFolder
*f
= folder
;
1024 cm_return_val_if_fail( cache
!= NULL
, NULL
);
1026 if( ! f
) f
= cache
->rootFolder
;
1028 /* Create person object */
1029 person
= addritem_create_item_person();
1030 addritem_person_set_common_name( person
, name
);
1031 addrcache_id_person( cache
, person
);
1032 addrcache_folder_add_person( cache
, f
, person
);
1034 /* Create email object */
1035 email
= addritem_create_item_email();
1036 addritem_email_set_address( email
, address
);
1037 addritem_email_set_remarks( email
, remarks
);
1038 addrcache_id_email( cache
, email
);
1039 addritem_person_add_email( person
, email
);
1040 cache
->dirtyFlag
= TRUE
;
1046 * Create a new folder and add to address cache.
1047 * \param cache Address cache.
1048 * \param folder Parent folder where to add folder, or <i>NULL</i> for
1050 * \return Folder that was created. This should <b>*NOT*</b> be
1051 * <code>g_free()</code> when done.
1053 ItemFolder
*addrcache_add_new_folder( AddressCache
*cache
, ItemFolder
*parent
)
1056 ItemFolder
*p
= parent
;
1058 cm_return_val_if_fail( cache
!= NULL
, NULL
);
1060 if( !p
) p
= cache
->rootFolder
;
1061 folder
= addritem_create_item_folder();
1062 addrcache_id_folder( cache
, folder
);
1063 if( addrcache_hash_add_folder( cache
, folder
) ) {
1064 p
->listFolder
= g_list_append( p
->listFolder
, folder
);
1065 ADDRITEM_PARENT(folder
) = ADDRITEM_OBJECT(p
);
1066 addrcache_set_dirty( cache
, TRUE
);
1069 addritem_free_item_folder( folder
);