aboutsummaryrefslogtreecommitdiff
path: root/src/addrcache.c
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-01-12 11:22:08 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-01-12 11:22:08 +0000
commitb9ca7b1ef5cd1f96ae6e28ae78d12c1e3258c23f (patch)
tree1203adec5f70af1ddd49868528d8d3a5b9004329 /src/addrcache.c
Initial import of Sylpheed (GTK2 version).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src/addrcache.c')
-rw-r--r--src/addrcache.c1232
1 files changed, 1232 insertions, 0 deletions
diff --git a/src/addrcache.c b/src/addrcache.c
new file mode 100644
index 00000000..6a491256
--- /dev/null
+++ b/src/addrcache.c
@@ -0,0 +1,1232 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2001 Match Grun
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Functions to maintain address cache.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+/* #include "mgutils.h" */
+#include "addritem.h"
+#include "addrcache.h"
+
+#define ID_TIME_OFFSET 998000000
+#define ADDRCACHE_MAX_SEARCH_COUNT 1000
+
+/*
+* Create new address cache.
+*/
+AddressCache *addrcache_create() {
+ AddressCache *cache;
+ gint t;
+
+ cache = g_new0( AddressCache, 1 );
+ cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
+
+ cache->dataRead = FALSE;
+ cache->modified = FALSE;
+ cache->modifyTime = 0;
+
+ /* Generate the next ID using system time */
+ cache->nextID = 1;
+ t = time( NULL );
+ if( t > 0 ) {
+ cache->nextID = t - ID_TIME_OFFSET;
+ }
+
+ cache->tempList = NULL;
+ cache->rootFolder = addritem_create_item_folder();
+ cache->rootFolder->isRoot = TRUE;
+ ADDRITEM_PARENT(cache->rootFolder) = NULL;
+ return cache;
+}
+
+/*
+* Properties.
+*/
+ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return cache->rootFolder;
+}
+GList *addrcache_get_list_folder( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return cache->rootFolder->listFolder;
+}
+GList *addrcache_get_list_person( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return cache->rootFolder->listPerson;
+}
+
+/*
+* Generate next ID.
+*/
+void addrcache_next_id( AddressCache *cache ) {
+ g_return_if_fail( cache != NULL );
+ cache->nextID++;
+}
+
+/*
+* Refresh internal variables. This can be used force a reload.
+*/
+void addrcache_refresh( AddressCache *cache ) {
+ cache->dataRead = FALSE;
+ cache->modified = TRUE;
+ cache->modifyTime = 0;
+}
+
+/*
+* Free hash table visitor function.
+*/
+static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
+ AddrItemObject *obj = ( AddrItemObject * ) value;
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ addritem_free_item_person( ( ItemPerson * ) obj );
+ }
+ else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ addritem_free_item_group( ( ItemGroup * ) obj );
+ }
+ else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
+ addritem_free_item_folder( ( ItemFolder * ) obj );
+ }
+ key = NULL;
+ value = NULL;
+ return 0;
+}
+
+/*
+* Free hash table of address cache items.
+*/
+static void addrcache_free_item_hash( GHashTable *table ) {
+ g_return_if_fail( table != NULL );
+ g_hash_table_freeze( table );
+ g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
+ g_hash_table_thaw( table );
+ g_hash_table_destroy( table );
+}
+
+/*
+* Free up folders and groups.
+*/
+static void addrcache_free_all_folders( ItemFolder *parent ) {
+ GList *node = parent->listFolder;
+ while( node ) {
+ ItemFolder *folder = node->data;
+ addrcache_free_all_folders( folder );
+ node = g_list_next( node );
+ }
+ g_list_free( parent->listPerson );
+ g_list_free( parent->listGroup );
+ g_list_free( parent->listFolder );
+ parent->listPerson = NULL;
+ parent->listGroup = NULL;
+ parent->listFolder = NULL;
+}
+
+/*
+* Clear the address cache.
+*/
+void addrcache_clear( AddressCache *cache ) {
+ g_return_if_fail( cache != NULL );
+
+ /* Free up folders and hash table */
+ addrcache_free_all_folders( cache->rootFolder );
+ addrcache_free_item_hash( cache->itemHash );
+ cache->itemHash = NULL;
+ ADDRITEM_PARENT(cache->rootFolder) = NULL;
+ addritem_free_item_folder( cache->rootFolder );
+ cache->rootFolder = NULL;
+ g_list_free( cache->tempList );
+ cache->tempList = NULL;
+
+ /* Reset to initial state */
+ cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
+ cache->rootFolder = addritem_create_item_folder();
+ cache->rootFolder->isRoot = TRUE;
+ ADDRITEM_PARENT(cache->rootFolder) = NULL;
+
+ addrcache_refresh( cache );
+
+}
+
+/*
+* Free address cache.
+*/
+void addrcache_free( AddressCache *cache ) {
+ g_return_if_fail( cache != NULL );
+
+ addrcache_free_all_folders( cache->rootFolder );
+ addrcache_free_item_hash( cache->itemHash );
+ cache->itemHash = NULL;
+ ADDRITEM_PARENT(cache->rootFolder) = NULL;
+ addritem_free_item_folder( cache->rootFolder );
+ cache->rootFolder = NULL;
+ g_list_free( cache->tempList );
+ cache->tempList = NULL;
+ g_free( cache );
+}
+
+/*
+* Check whether file has changed by comparing with cache.
+* return: TRUE if file has changed.
+*/
+gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
+ gboolean retVal;
+ struct stat filestat;
+ retVal = TRUE;
+ if( path ) {
+ if( 0 == lstat( path, &filestat ) ) {
+ if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
+ }
+ }
+ return retVal;
+}
+
+/*
+* Save file time to cache.
+* return: TRUE if time marked.
+*/
+gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
+ gboolean retVal = FALSE;
+ struct stat filestat;
+ if( path ) {
+ if( 0 == lstat( path, &filestat ) ) {
+ cache->modifyTime = filestat.st_mtime;
+ retVal = TRUE;
+ }
+ }
+ return retVal;
+}
+
+/*
+* Print list of items.
+*/
+void addrcache_print_item_list( GList *list, FILE *stream ) {
+ GList *node = list;
+ while( node ) {
+ AddrItemObject *obj = node->data;
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ addritem_print_item_person( ( ItemPerson * ) obj, stream );
+ }
+ else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ addritem_print_item_group( ( ItemGroup * ) obj, stream );
+ }
+ else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
+ addritem_print_item_folder( ( ItemFolder * ) obj, stream );
+ }
+ node = g_list_next( node );
+ }
+ fprintf( stream, "\t---\n" );
+}
+
+/*
+* Print item hash table visitor function.
+*/
+static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
+ AddrItemObject *obj = ( AddrItemObject * ) value;
+ FILE *stream = ( FILE * ) data;
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ addritem_print_item_person( ( ItemPerson * ) obj, stream );
+ }
+ else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ addritem_print_item_group( ( ItemGroup * ) obj, stream );
+ }
+ else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
+ addritem_print_item_folder( ( ItemFolder * ) obj, stream );
+ }
+}
+
+/*
+* Dump entire address cache hash table contents.
+*/
+void addrcache_print( AddressCache *cache, FILE *stream ) {
+ g_return_if_fail( cache != NULL );
+ fprintf( stream, "AddressCache:\n" );
+ fprintf( stream, "next id : %d\n", cache->nextID );
+ fprintf( stream, "mod time : %ld\n", cache->modifyTime );
+ fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
+ fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
+}
+
+/*
+* Dump entire address cache hash table contents.
+*/
+void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
+ g_return_if_fail( cache != NULL );
+ addrcache_print( cache, stream );
+ g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
+}
+
+/*
+ * Allocate ID for person.
+ */
+void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
+ g_return_if_fail( cache != NULL );
+ g_return_if_fail( person != NULL );
+ if( ADDRITEM_ID(person) ) return;
+ addrcache_next_id( cache );
+ ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
+}
+
+/*
+ * Allocate ID for group.
+ */
+void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
+ g_return_if_fail( cache != NULL );
+ g_return_if_fail( group != NULL );
+ if( ADDRITEM_ID(group) ) return;
+ addrcache_next_id( cache );
+ ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
+}
+
+/*
+ * Allocate ID for folder.
+ */
+void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
+ g_return_if_fail( cache != NULL );
+ g_return_if_fail( folder != NULL );
+ if( ADDRITEM_ID(folder) ) return;
+ addrcache_next_id( cache );
+ ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
+}
+
+/*
+ * Allocate ID for email address.
+ */
+void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
+ g_return_if_fail( cache != NULL );
+ g_return_if_fail( email != NULL );
+ if( ADDRITEM_ID(email) ) return;
+ addrcache_next_id( cache );
+ ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
+}
+
+/*
+ * Allocate ID for user attribute.
+ */
+void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
+ g_return_if_fail( cache != NULL );
+ g_return_if_fail( attrib != NULL );
+ if( attrib->uid ) return;
+ addrcache_next_id( cache );
+ attrib->uid = g_strdup_printf( "%d", cache->nextID );
+}
+
+/*
+* Add person to hash table.
+* return: TRUE if item added.
+*/
+gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
+ if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
+ return FALSE;
+ }
+ g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
+ return TRUE;
+}
+
+/*
+* Add group to hash table.
+* return: TRUE if item added.
+*/
+gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( group != NULL, FALSE );
+
+ if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
+ return FALSE;
+ }
+ g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
+ return TRUE;
+}
+
+/*
+* Add folder to hash table.
+* return: TRUE if item added.
+*/
+gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( folder != NULL, FALSE );
+
+ if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
+ return FALSE;
+ }
+ g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
+ return TRUE;
+}
+
+/*
+* Add person to specified folder in cache.
+*/
+gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
+ gboolean retVal = FALSE;
+
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( folder != NULL, FALSE );
+ g_return_val_if_fail( item != NULL, FALSE );
+
+ retVal = addrcache_hash_add_person( cache, item );
+ if( retVal ) {
+ addritem_folder_add_person( folder, item );
+ }
+ return retVal;
+}
+
+/*
+* Add folder to specified folder in cache.
+*/
+gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
+ gboolean retVal = FALSE;
+
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( folder != NULL, FALSE );
+ g_return_val_if_fail( item != NULL, FALSE );
+
+ retVal = addrcache_hash_add_folder( cache, item );
+ if( retVal ) {
+ addritem_folder_add_folder( folder, item );
+ }
+ return TRUE;
+}
+
+/*
+* Add folder to specified folder in cache.
+*/
+gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
+ gboolean retVal = FALSE;
+
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( folder != NULL, FALSE );
+ g_return_val_if_fail( item != NULL, FALSE );
+
+ retVal = addrcache_hash_add_group( cache, item );
+ if( retVal ) {
+ addritem_folder_add_group( folder, item );
+ }
+ return retVal;
+}
+
+/*
+* Add person to address cache.
+* return: TRUE if item added.
+*/
+gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
+ gboolean retVal = FALSE;
+
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( person != NULL, FALSE );
+
+ retVal = addrcache_hash_add_person( cache, person );
+ if( retVal ) {
+ addritem_folder_add_person( cache->rootFolder, person );
+ }
+ return retVal;
+}
+
+/*
+* Add EMail address to person.
+* return: TRUE if item added.
+*/
+gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( person != NULL, FALSE );
+ g_return_val_if_fail( email != NULL, FALSE );
+
+ addritem_person_add_email( person, email );
+ return TRUE;
+}
+
+/*
+* Add group to address cache.
+* return: TRUE if item added.
+*/
+gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
+ gboolean retVal = FALSE;
+
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( group != NULL, FALSE );
+
+ retVal = addrcache_hash_add_group( cache, group );
+ if( retVal ) {
+ addritem_folder_add_group( cache->rootFolder, group );
+ }
+ return retVal;
+}
+
+/*
+* Add EMail address to person.
+* return: TRUE if item added.
+*/
+gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( group != NULL, FALSE );
+ g_return_val_if_fail( email != NULL, FALSE );
+
+ addritem_group_add_email( group, email );
+ return TRUE;
+}
+
+/*
+* Add folder to address cache.
+* return: TRUE if item added.
+*/
+gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
+ gboolean retVal = FALSE;
+
+ g_return_val_if_fail( cache != NULL, FALSE );
+ g_return_val_if_fail( folder != NULL, FALSE );
+
+ retVal = addrcache_hash_add_folder( cache, folder );
+ if( retVal ) {
+ addritem_folder_add_folder( cache->rootFolder, folder );
+ }
+ return retVal;
+}
+
+/*
+* Return pointer to object (either person or group) for specified ID.
+* param: uid Object ID.
+* return: Object, or NULL if not found.
+*/
+AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
+ AddrItemObject *obj = NULL;
+ gchar *uidH;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ /* Check for matching UID */
+ uidH = ADDRITEM_ID(obj);
+ if( uidH ) {
+ if( strcmp( uidH, uid ) == 0 ) return obj;
+ }
+ }
+ return NULL;
+}
+
+/*
+* Return pointer for specified object ID.
+* param: uid Object ID.
+* return: Person object, or NULL if not found.
+*/
+ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
+ ItemPerson *person = NULL;
+ AddrItemObject *obj = addrcache_get_object( cache, uid );
+
+ if( obj ) {
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ person = ( ItemPerson * ) obj;
+ }
+ }
+ return person;
+}
+
+/*
+* Return pointer for specified object ID.
+* param: uid group ID.
+* return: Group object, or NULL if not found.
+*/
+ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
+ ItemGroup *group = NULL;
+ AddrItemObject *obj = addrcache_get_object( cache, uid );
+
+ if( obj ) {
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ group = ( ItemGroup * ) obj;
+ }
+ }
+ return group;
+}
+
+/*
+* Find email address in address cache.
+* param: uid Object ID for person.
+* eid EMail ID.
+* return: email object for specified object ID and email ID, or NULL if not found.
+*/
+ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *uid, const gchar *eid ) {
+ AddrItemObject *objP;
+
+ if( eid == NULL || *eid == '\0' ) return NULL;
+
+ objP = addrcache_get_object( cache, uid );
+ if( objP ) {
+ if( ADDRITEM_TYPE(objP) == ITEMTYPE_PERSON ) {
+ /* Sequential search through email addresses */
+ ItemPerson *person = ( ItemPerson * ) objP;
+ GList *nodeMail = person->listEMail;
+ while( nodeMail ) {
+ AddrItemObject *objE = nodeMail->data;
+ gchar *ide = ADDRITEM_ID(objE);
+ if( ide ) {
+ if( strcmp( ide, eid ) == 0 ) {
+ return ( ItemEMail * ) objE;
+ }
+ }
+ nodeMail = g_list_next( nodeMail );
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+* Remove attribute from person.
+* param: uid Object ID for person.
+* aid Attribute ID.
+* return: UserAttribute object, or NULL if not found. Note that object should still be freed.
+*/
+UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
+ UserAttribute *attrib = NULL;
+ ItemPerson *person;
+
+ if( aid == NULL || *aid == '\0' ) return NULL;
+
+ person = addrcache_get_person( cache, uid );
+ if( person ) {
+ attrib = addritem_person_remove_attrib_id( person, aid );
+ }
+ return attrib;
+}
+
+/*
+* Remove attribute from person.
+* param: person Person.
+* attrib Attribute to remove.
+* return: UserAttribute object. Note that object should still be freed.
+*/
+UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
+ UserAttribute *found = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( person && attrib ) {
+ found = addritem_person_remove_attribute( person, attrib );
+ }
+ return found;
+}
+
+/*
+* Remove group from address cache for specified ID.
+* param: uid Object ID.
+* return: Group, or NULL if not found. Note that object should still be freed.
+*/
+ItemGroup *addrcache_remove_group_id( AddressCache *cache, const gchar *uid ) {
+ AddrItemObject *obj = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ ItemGroup *group = ( ItemGroup * ) obj;
+ ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
+ if( ! parent ) parent = cache->rootFolder;
+ /* Remove group from parent's list and hash table */
+ parent->listGroup = g_list_remove( parent->listGroup, group );
+ g_hash_table_remove( cache->itemHash, uid );
+ return ( ItemGroup * ) obj;
+ }
+ }
+ return NULL;
+}
+
+/*
+* Remove group from address cache.
+* param: group Group to remove.
+* return: Group, or NULL if not found. Note that object should still be freed.
+*/
+ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
+ AddrItemObject *obj = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( group ) {
+ gchar *uid = ADDRITEM_ID(group);
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
+ if( ! parent ) parent = cache->rootFolder;
+
+ /* Remove group from parent's list and hash table */
+ parent->listGroup = g_list_remove( parent->listGroup, obj );
+ g_hash_table_remove( cache->itemHash, uid );
+ return group;
+ }
+ }
+ return NULL;
+}
+
+/*
+* Remove person's email address from all groups in folder.
+*/
+static void addrcache_foldergrp_rem_person( ItemFolder *folder, ItemPerson *person ) {
+ GList *nodeGrp = folder->listGroup;
+
+ while( nodeGrp ) {
+ ItemGroup *group = nodeGrp->data;
+ if( group ) {
+ /* Remove each email address that belongs to the person from the list */
+ GList *node = person->listEMail;
+ while( node ) {
+ group->listEMail = g_list_remove( group->listEMail, node->data );
+ node = g_list_next( node );
+ }
+ }
+ nodeGrp = g_list_next( nodeGrp );
+ }
+}
+
+/*
+* Remove person from address cache for specified ID. Note that person still retains
+* their EMail addresses. Also, links to these email addresses will be severed from
+* the group.
+* param: uid Object ID.
+* return: Person, or NULL if not found. Note that object should still be freed.
+*/
+ItemPerson *addrcache_remove_person_id( AddressCache *cache, const gchar *uid ) {
+ AddrItemObject *obj = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ /* Remove person's email addresses from all groups where */
+ /* referenced and from hash table. */
+ ItemPerson *person = ( ItemPerson * ) obj;
+ ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
+ if( ! parent ) parent = cache->rootFolder;
+ /* Remove emails from groups, remove from parent's list */
+ /* and hash table */
+ addrcache_foldergrp_rem_person( parent, person );
+ parent->listPerson = g_list_remove( parent->listPerson, person );
+ g_hash_table_remove( cache->itemHash, uid );
+ return person;
+ }
+ }
+ return NULL;
+}
+
+/*
+* Remove specified person from address cache.
+* param: person Person to remove.
+* return: Person, or NULL if not found. Note that object should still be freed.
+*/
+ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
+ AddrItemObject *obj = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( person ) {
+ gchar *uid = ADDRITEM_ID(person);
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ /* Remove person's email addresses from all groups where */
+ /* referenced and from hash table. */
+ ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
+ if( ! parent ) parent = cache->rootFolder;
+ addrcache_foldergrp_rem_person( parent, person );
+ parent->listPerson = g_list_remove( parent->listPerson, person );
+ g_hash_table_remove( cache->itemHash, uid );
+ return person;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+* Remove email from group item hash table visitor function.
+*/
+static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
+ AddrItemObject *obj = ( AddrItemObject * ) value;
+ ItemEMail *email = ( ItemEMail * ) data;
+
+ if( !email ) return;
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ ItemGroup *group = ( ItemGroup * ) value;
+ if( group ) {
+ /* Remove each email address that belongs to the person from the list */
+ group->listEMail = g_list_remove( group->listEMail, email );
+ }
+ }
+}
+
+/*
+* Remove email address in address cache for specified ID.
+* param: uid Object ID for person.
+* eid EMail ID.
+* return: EMail object, or NULL if not found. Note that object should still be freed.
+*/
+ItemEMail *addrcache_person_remove_email_id( AddressCache *cache, const gchar *uid, const gchar *eid ) {
+ ItemEMail *email = NULL;
+ ItemPerson *person;
+
+ if( eid == NULL || *eid == '\0' ) return NULL;
+
+ person = addrcache_get_person( cache, uid );
+ if( person ) {
+ email = addritem_person_remove_email_id( person, eid );
+ if( email ) {
+ /* Remove email from all groups. */
+ g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
+
+ /* Remove email from person's address list */
+ if( person->listEMail ) {
+ person->listEMail = g_list_remove( person->listEMail, email );
+ }
+ /* Unlink reference to person. */
+ ADDRITEM_PARENT(email) = NULL;
+ }
+ }
+ return email;
+}
+
+/*
+* Remove email address in address cache for specified person.
+* param: person Person.
+* email EMail to remove.
+* return: EMail object, or NULL if not found. Note that object should still be freed.
+*/
+ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
+ ItemEMail *found = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( person && email ) {
+ found = addritem_person_remove_email( person, email );
+ if( found ) {
+ /* Remove email from all groups. */
+ g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
+
+ /* Remove email from person's address list */
+ if( person->listEMail ) {
+ person->listEMail = g_list_remove( person->listEMail, email );
+ }
+ /* Unlink reference to person. */
+ ADDRITEM_PARENT(email) = NULL;
+ }
+ }
+ return found;
+}
+
+/*
+* Return link list of address items for root level folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to use the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
+ GList *list = NULL;
+ GList *node = NULL;
+ ItemFolder *f = folder;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( ! f ) f = cache->rootFolder;
+ node = f->listPerson;
+ while( node ) {
+ list = g_list_append( list, node->data );
+ node = g_list_next( node );
+ }
+ node = f->listGroup;
+ while( node ) {
+ list = g_list_append( list, node->data );
+ node = g_list_next( node );
+ }
+ return list;
+}
+
+/*
+* Return link list of persons for specified folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to use the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
+ ItemFolder *f = folder;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( ! f ) f = cache->rootFolder;
+ return addritem_folder_get_person_list( f );
+}
+
+/*
+* Return link list of group items for specified folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to use the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
+ ItemFolder *f = folder;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( ! f ) f = cache->rootFolder;
+ return addritem_folder_get_group_list( f );
+}
+
+/*
+* Return link list of folder items for specified folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to used the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
+ GList *node = NULL;
+ GList *list = NULL;
+ ItemFolder *f = folder;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( ! f ) f = cache->rootFolder;
+ node = f->listFolder;
+ while( node ) {
+ list = g_list_append( list, node->data );
+ node = g_list_next( node );
+ }
+ return list;
+}
+
+/*
+* Return link list of address items for root level folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to used the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_get_address_list( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return addrcache_folder_get_address_list( cache, cache->rootFolder );
+}
+
+/*
+* Return link list of persons for root level folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to used the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_get_person_list( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return addritem_folder_get_person_list( cache->rootFolder );
+}
+
+/*
+* Return link list of group items in root level folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to used the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_get_group_list( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return cache->rootFolder->listGroup;
+}
+
+/*
+* Return link list of folder items in root level folder. Note that the list contains
+* references to items and should be g_free() when done. Do *NOT* attempt to used the
+* addrcache_free_xxx() functions... this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_get_folder_list( AddressCache *cache ) {
+ g_return_val_if_fail( cache != NULL, NULL );
+ return cache->rootFolder->listFolder;
+}
+
+/*
+* Group visitor function.
+*/
+static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
+ AddrItemObject *obj = ( AddrItemObject * ) value;
+
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ AddressCache *cache = data;
+ ItemGroup *group = ( ItemGroup * ) obj;
+ ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
+ GList *node = group->listEMail;
+ while( node ) {
+ ItemEMail *email = ( ItemEMail * ) node->data;
+ if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
+ if( ! g_list_find( cache->tempList, group ) ) {
+ cache->tempList = g_list_append( cache->tempList, group );
+ }
+ }
+ node = g_list_next( node );
+ }
+ }
+}
+
+/*
+* Return link list of groups which contain a reference to specified person's email
+* address.
+*/
+GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
+ GList *list = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ cache->tempList = NULL;
+ cache->tempList = g_list_append( cache->tempList, person );
+ g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
+ cache->tempList = g_list_remove( cache->tempList, person );
+ list = cache->tempList;
+ cache->tempList = NULL;
+ return list;
+}
+
+/*
+* Find root folder for specified folder.
+* Enter: folder Folder to search.
+* Return: root folder, or NULL if not found.
+*/
+ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
+ ItemFolder *item = folder;
+ gint count = 0;
+
+ while( item ) {
+ if( item->isRoot ) break;
+ if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
+ item = NULL;
+ break;
+ }
+ item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
+ }
+ return item;
+}
+
+/*
+* Get all person visitor function.
+*/
+static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
+ AddrItemObject *obj = ( AddrItemObject * ) value;
+
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
+ AddressCache *cache = data;
+ cache->tempList = g_list_append( cache->tempList, obj );
+ }
+}
+
+/*
+* Return link list of all persons in address cache. Note that the list contains
+* references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
+* this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_get_all_persons( AddressCache *cache ) {
+ GList *list = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ cache->tempList = NULL;
+ g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
+ list = cache->tempList;
+ cache->tempList = NULL;
+ return list;
+}
+
+/*
+* Get all groups visitor function.
+*/
+static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
+ AddrItemObject *obj = ( AddrItemObject * ) value;
+
+ if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
+ AddressCache *cache = data;
+ cache->tempList = g_list_append( cache->tempList, obj );
+ }
+}
+
+/*
+* Return link list of all groups in address cache. Note that the list contains
+* references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
+* this will destroy the address cache data!
+* Return: List of items, or NULL if none.
+*/
+GList *addrcache_get_all_groups( AddressCache *cache ) {
+ GList *list = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ cache->tempList = NULL;
+ g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
+ list = cache->tempList;
+ cache->tempList = NULL;
+ return list;
+}
+
+/*
+* Remove folder from cache. Children are re-parented to parent folder.
+* param: folder Folder to remove.
+* return: Folder, or NULL if not found. Note that object should still be freed.
+*/
+ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
+ AddrItemObject *obj = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( folder ) {
+ gchar *uid = ADDRITEM_ID(folder);
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
+ GList *node;
+ AddrItemObject *aio;
+ if( ! parent ) parent = cache->rootFolder;
+
+ /* Re-parent children in folder */
+ node = folder->listFolder;
+ while( node ) {
+ aio = ( AddrItemObject * ) node->data;
+ parent->listFolder = g_list_append( parent->listFolder, aio );
+ aio->parent = ADDRITEM_OBJECT(parent);
+ node = g_list_next( node );
+ }
+ node = folder->listPerson;
+ while( node ) {
+ aio = ( AddrItemObject * ) node->data;
+ parent->listPerson = g_list_append( parent->listPerson, aio );
+ aio->parent = ADDRITEM_OBJECT(parent);
+ node = g_list_next( node );
+ }
+ node = folder->listGroup;
+ while( node ) {
+ aio = ( AddrItemObject * ) node->data;
+ parent->listGroup = g_list_append( parent->listGroup, aio );
+ aio->parent = ADDRITEM_OBJECT(parent);
+ node = g_list_next( node );
+ }
+
+ /* Remove folder from parent's list and hash table */
+ parent->listFolder = g_list_remove( parent->listFolder, folder );
+ ADDRITEM_PARENT(folder) = NULL;
+ g_hash_table_remove( cache->itemHash, uid );
+ return folder;
+ }
+ }
+ return NULL;
+}
+
+/*
+* Remove folder from cache. Children are deleted.
+* param: folder Folder to remove.
+* return: Folder, or NULL if not found. Note that object should still be freed.
+*/
+ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
+ AddrItemObject *obj = NULL;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( folder ) {
+ gchar *uid = ADDRITEM_ID(folder);
+ if( uid == NULL || *uid == '\0' ) return NULL;
+ obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
+ if( obj ) {
+ ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
+ if( ! parent ) parent = cache->rootFolder;
+
+ /* Remove groups */
+ while( folder->listGroup ) {
+ ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
+ item = addrcache_remove_group( cache, item );
+ if( item ) {
+ addritem_free_item_group( item );
+ item = NULL;
+ }
+ }
+
+ while( folder->listPerson ) {
+ ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
+ item = addrcache_remove_person( cache, item );
+ if( item ) {
+ addritem_free_item_person( item );
+ item = NULL;
+ }
+ }
+
+ /* Recursive deletion of folder */
+ while( folder->listFolder ) {
+ ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
+ item = addrcache_remove_folder_delete( cache, item );
+ if( item ) {
+ addritem_free_item_folder( item );
+ item = NULL;
+ }
+ }
+
+ /* Remove folder from parent's list and hash table */
+ parent->listFolder = g_list_remove( parent->listFolder, folder );
+ ADDRITEM_PARENT(folder) = NULL;
+ g_hash_table_remove( cache->itemHash, uid );
+ return folder;
+ }
+ }
+ return NULL;
+}
+
+/*
+* Add person and address data to cache.
+* Enter: cache Cache.
+* folder Folder where to add person, or NULL for root folder.
+* name Common name.
+* address EMail address.
+* remarks Remarks.
+* Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
+* this will destroy the address book data.
+*/
+ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
+ const gchar *address, const gchar *remarks )
+{
+ ItemPerson *person = NULL;
+ ItemEMail *email = NULL;
+ ItemFolder *f = folder;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( ! f ) f = cache->rootFolder;
+
+ /* Create person object */
+ person = addritem_create_item_person();
+ addritem_person_set_common_name( person, name );
+ addrcache_id_person( cache, person );
+ addrcache_folder_add_person( cache, f, person );
+
+ /* Create email object */
+ email = addritem_create_item_email();
+ addritem_email_set_address( email, address );
+ addritem_email_set_remarks( email, remarks );
+ addrcache_id_email( cache, email );
+ addritem_person_add_email( person, email );
+
+ return person;
+}
+
+/*
+* End of Source.
+*/