From 0cc6cf5fed537e1625b716e21f1fb632507de508 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?=
 <rafael.carre@savoirfairelinux.com>
Date: Fri, 26 Aug 2011 13:14:45 -0400
Subject: [PATCH] * #6740 : fix history double free

calls are added to history only after they are removed from the current calls list
---
 gnome/src/actions.c           | 104 ++++++++--------------------------
 gnome/src/contacts/calllist.c |  74 +++++-------------------
 gnome/src/contacts/calllist.h |   4 --
 gnome/src/contacts/calltab.c  |  16 +-----
 gnome/src/contacts/calltab.h  |   2 -
 gnome/src/dbus/dbus.c         |  24 ++------
 6 files changed, 48 insertions(+), 176 deletions(-)

diff --git a/gnome/src/actions.c b/gnome/src/actions.c
index 4e949ff7fc..9898c6d58c 100644
--- a/gnome/src/actions.c
+++ b/gnome/src/actions.c
@@ -329,13 +329,8 @@ void sflphone_fill_account_list (void)
 
 gboolean sflphone_init (GError **error)
 {
-    if (!dbus_connect (error)) {
+    if (!dbus_connect (error) || !dbus_register (getpid (), "Gtk+ Client", error))
         return FALSE;
-    }
-
-    if (!dbus_register (getpid (), "Gtk+ Client", error)) {
-        return FALSE;
-    }
 
     abookfactory_init_factory();
 
@@ -616,19 +611,16 @@ sflphone_display_transfer_status (const gchar* message)
 void
 sflphone_incoming_call (callable_obj_t * c)
 {
-    gchar *msg = "";
-
     c->_history_state = MISSED;
     calllist_add_call (current_calls, c);
-    calllist_add_call (history, c);
     calltree_add_call (current_calls, c, NULL);
-    calltree_add_call (history, c, NULL);
+
     update_actions();
     calltree_display (current_calls);
 
     // Change the status bar if we are dealing with a direct SIP call
     if (_is_direct_call (c)) {
-        msg = g_markup_printf_escaped (_ ("Direct SIP call"));
+        gchar *msg = g_markup_printf_escaped (_ ("Direct SIP call"));
         statusbar_pop_message (__MSG_ACCOUNT_DEFAULT);
         statusbar_push_message (msg , NULL, __MSG_ACCOUNT_DEFAULT);
         g_free (msg);
@@ -853,26 +845,15 @@ sflphone_keypad (guint keyval, gchar * key)
     }
 }
 
-static int _place_direct_call (const callable_obj_t * c)
+static void place_direct_call (const callable_obj_t * c)
 {
-    if (c->_state == CALL_STATE_DIALING) {
-        dbus_place_call (c);
-    } else {
-        return -1;
-    }
-
-    return 0;
+    assert(c->_state == CALL_STATE_DIALING);
 }
 
-static int _place_registered_call (callable_obj_t * c)
+static int place_registered_call (callable_obj_t * c)
 {
     account_t * current = NULL;
 
-    if (c == NULL) {
-        DEBUG ("Actions: Callable_obj_t is NULL in _place_registered_call");
-        return -1;
-    }
-
     if (c->_state != CALL_STATE_DIALING)
         return -1;
 
@@ -927,82 +908,47 @@ static int _place_registered_call (callable_obj_t * c)
 
     c->_history_state = OUTGOING;
 
-    calllist_add_call (history, c);
-    calltree_add_call (history, c, NULL);
-
     return 0;
 }
 
 void
 sflphone_place_call (callable_obj_t * c)
 {
-    gchar *msg = "";
-
-    if (c == NULL) {
-        DEBUG ("Actions: Unexpected condition: callable_obj_t is null in %s at %d", __FILE__, __LINE__);
-        return;
-    }
-
     DEBUG ("Actions: Placing call with %s @ %s and accountid %s", c->_peer_name, c->_peer_number, c->_accountID);
 
     if (_is_direct_call (c)) {
-        msg = g_markup_printf_escaped (_ ("Direct SIP call"));
+        gchar *msg = g_markup_printf_escaped (_ ("Direct SIP call"));
         statusbar_pop_message (__MSG_ACCOUNT_DEFAULT);
         statusbar_push_message (msg , NULL, __MSG_ACCOUNT_DEFAULT);
         g_free (msg);
 
-        if (_place_direct_call (c) < 0) {
-            DEBUG ("An error occured while placing direct call in %s at %d", __FILE__, __LINE__);
-            return;
-        }
-    } else {
-        if (_place_registered_call (c) < 0) {
-            DEBUG ("An error occured while placing registered call in %s at %d", __FILE__, __LINE__);
-            return;
-        }
-    }
+        place_direct_call (c);
+    } else if (place_registered_call (c) < 0)
+        DEBUG ("An error occured while placing registered call in %s at %d", __FILE__, __LINE__);
 }
 
 
 void
 sflphone_detach_participant (const gchar* callID)
 {
-    DEBUG ("Action: Detach participant from conference");
-
-    if (callID == NULL) {
-        callable_obj_t * selectedCall = calltab_get_selected_call (current_calls);
-        DEBUG ("Action: Detach participant %s", selectedCall->_callID);
-
-        if (selectedCall->_confID) {
-            g_free (selectedCall->_confID);
-            selectedCall->_confID = NULL;
-        }
-
-        // Instant messaging widget should have been deactivated during the conference
-        if (selectedCall->_im_widget)
-            im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
-
-        calltree_remove_call (current_calls, selectedCall, NULL);
-        calltree_add_call (current_calls, selectedCall, NULL);
-        dbus_detach_participant (selectedCall->_callID);
-    } else {
-        callable_obj_t * selectedCall = calllist_get_call (current_calls, callID);
-        DEBUG ("Action: Darticipant %s", callID);
-
-        if (selectedCall->_confID) {
-            g_free (selectedCall->_confID);
-            selectedCall->_confID = NULL;
-        }
+    callable_obj_t * selectedCall;
+    if (callID == NULL)
+        selectedCall = calltab_get_selected_call (current_calls);
+    else
+        selectedCall = calllist_get_call (current_calls, callID);
 
-        // Instant messagin widget should have been deactivated during the conference
-        if (selectedCall->_im_widget)
-            im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
+    DEBUG ("Action: Detach participant %s", selectedCall->_callID);
 
-        calltree_remove_call (current_calls, selectedCall, NULL);
-        calltree_add_call (current_calls, selectedCall, NULL);
-        dbus_detach_participant (callID);
+    if (selectedCall->_confID) {
+        g_free (selectedCall->_confID);
+        selectedCall->_confID = NULL;
     }
-
+    // Instant messaging widget should have been deactivated during the conference
+    if (selectedCall->_im_widget)
+        im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
+    calltree_remove_call (current_calls, selectedCall, NULL);
+    calltree_add_call (current_calls, selectedCall, NULL);
+    dbus_detach_participant (selectedCall->_callID);
 }
 
 void
diff --git a/gnome/src/contacts/calllist.c b/gnome/src/contacts/calllist.c
index cb9eb87669..3cd3cbcc47 100644
--- a/gnome/src/contacts/calllist.c
+++ b/gnome/src/contacts/calllist.c
@@ -36,25 +36,11 @@
 static
 gint is_callID_callstruct(gconstpointer a, gconstpointer b)
 {
-    QueueElement *c = (QueueElement *) a;
-    callable_obj_t *call;
-
-    if(c == NULL) {
-        return 1;
-    }
-
-    if(c->type != HIST_CALL) {
+    const QueueElement *c = a;
+    if(c == NULL || c->type != HIST_CALL)
 	return 1;
-    }
-    
-    call = c->elem.call;
 
-    if(g_strcasecmp(call->_callID, (const gchar *) b) == 0) {
-        return 0;
-    }
-    else {
-	return 1;	
-    }
+    return g_strcasecmp(c->elem.call->_callID, (const gchar *) b);
 }
 
 // TODO : sflphoneGTK : try to do this more generic
@@ -93,13 +79,6 @@ void calllist_add_contact (gchar *contact_name, gchar *contact_phone, contact_ty
     calltree_add_call (contacts, new_call, NULL);
 }
 
-void
-calllist_init (calltab_t* tab)
-{
-    tab->callQueue = g_queue_new ();
-    tab->selectedCall = NULL;
-}
-
 /*
  * Function passed to calllist_clean to free every QueueElement.
  */
@@ -130,10 +109,8 @@ calllist_reset (calltab_t* tab)
 
 void calllist_add_history_call (callable_obj_t *obj)
 {
-    QueueElement *element;  
-
     if (eel_gconf_get_integer (HISTORY_ENABLED)) {
-        element = (QueueElement *)malloc(sizeof(QueueElement));
+        QueueElement *element = malloc(sizeof(QueueElement));
 	element->type = HIST_CALL;
 	element->elem.call = obj;  
         g_queue_push_tail (history->callQueue, (gpointer) element);
@@ -143,10 +120,8 @@ void calllist_add_history_call (callable_obj_t *obj)
 
 void calllist_add_history_conference(conference_obj_t *obj)
 {
-    QueueElement *element;
-
     if(eel_gconf_get_integer (HISTORY_ENABLED)) {
-	element = (QueueElement *)malloc(sizeof(QueueElement));
+        QueueElement *element = malloc(sizeof(QueueElement));
 	element->type = HIST_CONFERENCE;
 	element->elem.conf = obj;
         g_queue_push_tail (history->callQueue, (gpointer) element);
@@ -157,11 +132,9 @@ void calllist_add_history_conference(conference_obj_t *obj)
 void
 calllist_add_call (calltab_t* tab, callable_obj_t * c)
 {
-    QueueElement *element;
-
     DEBUG("Calllist: Add Call %s", c->_callID);
 
-    element = (QueueElement *)malloc(sizeof(QueueElement));
+    QueueElement *element = malloc(sizeof(QueueElement));
     element->type = HIST_CALL;
     element->elem.call = c;
     g_queue_push_tail (tab->callQueue, (gpointer) element);
@@ -170,12 +143,8 @@ calllist_add_call (calltab_t* tab, callable_obj_t * c)
 void
 calllist_clean_history (void)
 {
-    guint i;
     guint size = calllist_get_size (history);
-
-    DEBUG ("CallList: History list size %d", size);
-
-    for (i = 0 ; i < size; i++) {
+    for (guint i = 0 ; i < size; i++) {
         QueueElement* c = calllist_get_nth (history , i);
 	if(c->type == HIST_CALL) {
             calltree_remove_call (history, c->elem.call, NULL);
@@ -189,36 +158,34 @@ calllist_clean_history (void)
     calllist_reset (history);
 }
 
-// TODO : sflphoneGTK : try to do this more generic
 void
 calllist_remove_from_history (callable_obj_t* c)
 {
     calllist_remove_call (history, c->_callID);
     calltree_remove_call (history, c, NULL);
-    DEBUG ("CallList: Size of history = %d" , calllist_get_size (history));
 }
 
 void
 calllist_remove_call (calltab_t* tab, const gchar * callID)
 {
-    QueueElement *element;
-    GList *c;
-    
     DEBUG("CallList: Remove call %s from list", callID);
 
-    c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
+    GList *c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
     if(c == NULL) {
         DEBUG("CallList: Could not remove call %s", callID);
     	return;
     }
 
-    element = (QueueElement *)c->data;
+    QueueElement *element = (QueueElement *)c->data;
     if(element->type != HIST_CALL) {
         ERROR("CallList: Error: Element %s is not a call", callID);
         return;
     }
 
     g_queue_remove (tab->callQueue, element);
+
+    calllist_add_call (history, element->elem.call);
+    calltree_add_call (history, element->elem.call, NULL);
 }
 
 
@@ -226,13 +193,7 @@ callable_obj_t *
 calllist_get_by_state (calltab_t* tab, call_state_t state)
 {
     GList * c = g_queue_find_custom (tab->callQueue, &state, get_state_callstruct);
-
-    if (c) {
-        return (callable_obj_t *) c->data;
-    } else {
-        return NULL;
-    }
-
+    return c ? c->data : NULL;
 }
 
 guint
@@ -250,9 +211,6 @@ calllist_get_nth (calltab_t* tab, guint n)
 callable_obj_t *
 calllist_get_call (calltab_t* tab, const gchar * callID)
 {
-    QueueElement *element;
-    callable_obj_t *call;
- 
     DEBUG("CallList: Get call: %s", callID);
     
     GList * c = g_queue_find_custom (tab->callQueue, callID, is_callID_callstruct);
@@ -261,13 +219,11 @@ calllist_get_call (calltab_t* tab, const gchar * callID)
         return NULL;
     }
 
-    element = (QueueElement *)c->data;
+    QueueElement *element = c->data;
     if(element->type != HIST_CALL) {
 	ERROR("CallList: Error: Element %s is not a call", callID);
 	return NULL;
     }
 
-    call = element->elem.call;
-
-    return call;
+    return element->elem.call;
 }
diff --git a/gnome/src/contacts/calllist.h b/gnome/src/contacts/calllist.h
index ea7e087df3..288162457b 100644
--- a/gnome/src/contacts/calllist.h
+++ b/gnome/src/contacts/calllist.h
@@ -73,10 +73,6 @@ void calllist_add_history_call (callable_obj_t *obj);
 
 void calllist_add_history_conference (conference_obj_t *obj);
 
-/** This function initialize a call list. */
-void
-calllist_init (calltab_t* tab);
-
 /** This function empty and free the call list. */
 void
 calllist_clean (calltab_t* tab);
diff --git a/gnome/src/contacts/calltab.c b/gnome/src/contacts/calltab.c
index 148dda4e37..0df4e7dda1 100644
--- a/gnome/src/contacts/calltab.c
+++ b/gnome/src/contacts/calltab.c
@@ -40,7 +40,9 @@ calltab_t* calltab_init (gboolean searchbar_type, gchar *name)
     ret->_name = g_strdup (name);
 
     calltree_create (ret, searchbar_type);
-    calllist_init (ret);
+
+    ret->callQueue = g_queue_new ();
+    ret->selectedCall = NULL;
 
     return ret;
 }
@@ -84,18 +86,6 @@ calltab_get_selected_conf (calltab_t *tab)
     return tab->selectedConf;
 }
 
-void
-calltab_unselect_all(calltab_t *tab) 
-{
-    if(tab == NULL) {
-        ERROR("CallTab: Tab is NULL");
-	return;
-    }
-
-    tab->selectedCall = NULL;
-    tab->selectedConf = NULL;
-}
-
 void
 calltab_create_searchbar (calltab_t* tab)
 {
diff --git a/gnome/src/contacts/calltab.h b/gnome/src/contacts/calltab.h
index a428bad26e..e9d0e70b1a 100644
--- a/gnome/src/contacts/calltab.h
+++ b/gnome/src/contacts/calltab.h
@@ -64,8 +64,6 @@ calltab_get_selected_call (calltab_t *);
 conference_obj_t *
 calltab_get_selected_conf (calltab_t *);
 
-void calltab_unselect_all(calltab_t *);
-
 void
 calltab_create_searchbar (calltab_t *);
 
diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c
index adbc9b4ed3..62b7fe91db 100644
--- a/gnome/src/dbus/dbus.c
+++ b/gnome/src/dbus/dbus.c
@@ -139,9 +139,7 @@ new_call_created_cb (DBusGProxy *proxy UNUSED, const gchar *accountID,
     time(&c->_time_start);
 
     calllist_add_call(current_calls, c);
-    calllist_add_call(history, c);
     calltree_add_call(current_calls, c, NULL);
-    calltree_add_call(history, c, NULL);
 
     update_actions();
     calltree_display(current_calls);
@@ -252,10 +250,6 @@ call_state_cb (DBusGProxy *proxy UNUSED, const gchar* callID, const gchar* state
 {
     DEBUG ("DBUS: Call %s state %s",callID, state);
     callable_obj_t *c = calllist_get_call (current_calls, callID);
-    if(c == NULL) {
-	ERROR("DBUS: Error: Call is NULL in ");
-    }
-
     if (c) {
         if (g_strcmp0 (state, "HUNGUP") == 0) {
             if (c->_state == CALL_STATE_CURRENT) {
@@ -286,33 +280,25 @@ call_state_cb (DBusGProxy *proxy UNUSED, const gchar* callID, const gchar* state
             sflphone_busy (c);
         }
     } else {
+        ERROR("DBUS: Error: Call is NULL in %s", __func__);
+
         // The callID is unknow, threat it like a new call
         // If it were an incoming call, we won't be here
         // It means that a new call has been initiated with an other client (cli for instance)
         if ((g_strcmp0 (state, "RINGING")) == 0 ||
             (g_strcmp0 (state, "CURRENT")) == 0 ||
             (g_strcmp0 (state, "RECORD"))) {
-            GHashTable *call_details;
-            gchar *type;
 
             DEBUG ("DBUS: New ringing call! accountID: %s", callID);
 
             // We fetch the details associated to the specified call
-            call_details = dbus_get_call_details (callID);
+            GHashTable *call_details = dbus_get_call_details (callID);
             callable_obj_t *new_call = create_new_call_from_details (callID, call_details);
 
-            // Restore the callID to be synchronous with the daemon
-            new_call->_callID = g_strdup (callID);
-            type = g_hash_table_lookup (call_details, "CALL_TYPE");
-
-            if (g_strcasecmp (type, "0") == 0) {
-                new_call->_history_state = INCOMING;
-            } else {
-                new_call->_history_state = OUTGOING;
-            }
+            new_call->_history_state = (g_strcasecmp (g_hash_table_lookup (call_details, "CALL_TYPE"), "0") == 0)
+                      ? INCOMING : OUTGOING;
 
             calllist_add_call (current_calls, new_call);
-            calllist_add_call (history, new_call);
             calltree_add_call (current_calls, new_call, NULL);
             update_actions();
             calltree_display (current_calls);
-- 
GitLab