fix bug 643638
[claws.git] / src / addrbook.c
index dcdad5c7bfeb3df12b5b0ee883aa774ba9203c76..138b9b62e4110bb1ab7c9f430f5a86eb362613f8 100644 (file)
@@ -1180,9 +1180,11 @@ ItemEMail *addrbook_move_email_after( AddressBookFile *book, ItemPerson *person,
 }
 
 /*
-* Hash table visitor function.
+* Hash table visitor function for deletion of hashtable entries.
 */
-static gboolean addrbook_free_simple_hash_vis( gpointer *key, gpointer *value, gpointer *data ) {
+static gboolean addrbook_free_simple_hash_vis(
+       gpointer *key, gpointer *value, gpointer *data )
+{
        g_free( key );
        key = NULL;
        value = NULL;
@@ -1193,51 +1195,43 @@ static gboolean addrbook_free_simple_hash_vis( gpointer *key, gpointer *value, g
 * Update address book email list for specified person.
 * Enter: book      Address book.
 *        person    Person to update.
-*        listEMail New list of email addresses.
+*        listEMail List of new email addresses.
 * Note: The existing email addresses are replaced with the new addresses. Any references
 * to old addresses in the groups are re-linked to the new addresses. All old addresses
 * linked to the person are removed.
 */
-void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GList *listEMail ) {
+void addrbook_update_address_list(
+       AddressBookFile *book, ItemPerson *person, GList *listEMail )
+{
        GList *node;
-       GList *oldData;
+       GList *listDelete;
        GList *listGroup;
 
        g_return_if_fail( book != NULL );
        g_return_if_fail( person != NULL );
 
-       /* Remember old list */
-       oldData = person->listEMail;
-
-       /* Attach new address list to person. */
-       node = listEMail;
-       while( node ) {
-               ItemEMail *email = node->data;
-               if( ADDRITEM_ID(email) == NULL ) {
-                       /* Allocate an ID */
-                       addrcache_id_email( book->addressCache, email );
-               }
-               ADDRITEM_PARENT(email) = ADDRITEM_OBJECT(person);
-               node = g_list_next( node );
-       }
-       person->listEMail = listEMail;
-
-       /* Get groups where person's email is listed */
+       /* Get groups where person's existing email addresses are listed */
        listGroup = addrcache_get_group_for_person( book->addressCache, person );
        if( listGroup ) {
                GHashTable *hashEMail;
+               GHashTable *hashEMailAlias;
                GList *nodeGrp;
 
                /* Load hash table with new address entries */
                hashEMail = g_hash_table_new( g_str_hash, g_str_equal );
+               hashEMailAlias = g_hash_table_new( g_str_hash, g_str_equal );
                node = listEMail;
                while( node ) {
                        ItemEMail *email = node->data;
                        gchar *addr = g_strdup( email->address );
+                       gchar *alias = email->obj.name ;
                        g_strdown( addr );
                        if( ! g_hash_table_lookup( hashEMail, addr ) ) {
                                g_hash_table_insert( hashEMail, addr, email );
                        }
+                       if ( *alias != '\0' && ! g_hash_table_lookup( hashEMailAlias, alias ) ) {
+                               g_hash_table_insert( hashEMailAlias, alias, email );
+                       }
                        node = g_list_next( node );
                }
 
@@ -1253,17 +1247,31 @@ void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GL
                        nodeGrpEM = groupEMail;
                        while( nodeGrpEM ) {
                                ItemEMail *emailGrp = ( ItemEMail * ) nodeGrpEM->data;
+
                                if( ADDRITEM_PARENT(emailGrp) == ADDRITEM_OBJECT(person) ) {
                                        /* Found an email address for this person */
                                        ItemEMail *emailNew = NULL;
-                                       gchar *addr = g_strdup( emailGrp->address );
+                                       gchar *addr = g_strdup( emailGrp->address );
+                                       gchar *alias = emailGrp->obj.name;
                                        g_strdown( addr );
-                                       emailNew = ( ItemEMail * ) g_hash_table_lookup( hashEMail, addr );
+                                       emailNew = ( ItemEMail * )
+                                               g_hash_table_lookup( hashEMail, addr );
                                        g_free( addr );
+                                       /* If no match by e-mail, try to match by e-mail alias */
+                                       if( ! emailNew && *alias != '\0' ) {
+                                               emailNew = ( ItemEMail * )
+                                                       g_hash_table_lookup( hashEMailAlias, alias);
+                                       }
+                                       
                                        if( emailNew ) {
                                                /* Point to this entry */
                                                nodeGrpEM->data = emailNew;
                                        }
+                                       else if(g_hash_table_size(hashEMail)==1) {
+                                               /* If the person has just one e-mail address, then 
+                                                  change e-mail address in group list */
+                                               nodeGrpEM->data = listEMail->data;
+                                       } 
                                        else {
                                                /* Mark for removal */
                                                listRemove = g_list_append( listRemove, emailGrp );
@@ -1281,23 +1289,65 @@ void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GL
                                nodeGrpEM = g_list_next( nodeGrpEM );
                        }
 
+                       g_list_free( listRemove );
+
                        /* Move on to next group */
                        nodeGrp = g_list_next( nodeGrp );
 
                }
 
                /* Clear hash table */
-               g_hash_table_foreach_remove( hashEMail, ( GHRFunc ) addrbook_free_simple_hash_vis, NULL );
+               g_hash_table_foreach_remove(
+                       hashEMail, ( GHRFunc ) addrbook_free_simple_hash_vis, NULL );
                g_hash_table_destroy( hashEMail );
                hashEMail = NULL;
+               g_hash_table_destroy( hashEMailAlias );
+               hashEMailAlias = NULL;
                g_list_free( listGroup );
                listGroup = NULL;
        }
+
+       /* Remove old addresses from person and cache */
+       listDelete = NULL;
+       node = person->listEMail;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               if( addrcache_person_remove_email( book->addressCache, person, email ) ) {
+                       addrcache_remove_email( book->addressCache, email );
+               }
+               listDelete = g_list_append( listDelete, email );
+               node = person->listEMail;
+       }
+
+       /* Add new address entries */
+       node = listEMail;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               if( ADDRITEM_ID(email) == NULL ) {
+                       /* Allocate an ID for new address */
+                       addrcache_id_email( book->addressCache, email );
+               }
+               addrcache_person_add_email( book->addressCache, person, email );
+               node = g_list_next( node );
+       }
+
        addrcache_set_dirty( book->addressCache, TRUE );
 
-       /* Free up old data */
-       addritem_free_list_email( oldData );
-       oldData = NULL;
+       /* Free up memory */
+       g_list_free( listEMail );
+       listEMail = NULL;
+
+       node = listDelete;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               addritem_free_item_email( email );
+               node = g_list_next( node );
+       }
+       g_list_free( listDelete );
+       listDelete = NULL;
 
 }
 
@@ -1334,22 +1384,6 @@ ItemPerson *addrbook_add_address_list( AddressBookFile *book, ItemFolder *folder
        return person;
 }
 
-/*
-* Load hash table visitor function.
-*/
-static void addrbook_load_hash_table_email_vis( gpointer key, gpointer value, gpointer data ) {
-       AddrItemObject *obj = ( AddrItemObject * ) value;
-
-       if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
-               GHashTable *table = ( GHashTable * ) data;
-               gchar *newKey = g_strdup( key );
-               ItemEMail *email = ( ItemEMail * ) obj;
-               if( ! g_hash_table_lookup( table, newKey ) ) {
-                       g_hash_table_insert( table, newKey, email );
-               }
-       }
-}
-
 /*
 * Build available email list visitor function.
 */
@@ -1709,8 +1743,8 @@ gchar *addrbook_gen_new_file_name( gint fileNum ) {
        if( n < 1 ) n = 1;
        nmax = -1 + (long int) pow( 10, FILE_NUMDIGITS );
        if( fileNum > nmax ) return NULL;
-       sprintf( fmt, "%%s%%0%dd%%s", FILE_NUMDIGITS );
-       sprintf( buf, fmt, ADDRBOOK_PREFIX, n, ADDRBOOK_SUFFIX );
+       g_snprintf( fmt, sizeof(fmt), "%%s%%0%dd%%s", FILE_NUMDIGITS );
+       g_snprintf( buf, sizeof(buf), fmt, ADDRBOOK_PREFIX, n, ADDRBOOK_SUFFIX );
        return g_strdup( buf );
 }