From cfbd9b8429118730f63bd049886264a110a45b19 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Wed, 4 Dec 2013 09:13:40 +0100 Subject: [PATCH] The LDAP suggestions are now correctly displayed in the suggestions --- coreapi/ldap/ldapprovider.c | 66 +++++++++++++------------ gtk/loginframe.c | 61 ----------------------- gtk/main.c | 97 ++++++++++++++++++++++++++++++++++++- gtk/main.ui | 15 ------ 4 files changed, 132 insertions(+), 107 deletions(-) diff --git a/coreapi/ldap/ldapprovider.c b/coreapi/ldap/ldapprovider.c index d71989726..34de6f5a9 100644 --- a/coreapi/ldap/ldapprovider.c +++ b/coreapi/ldap/ldapprovider.c @@ -73,6 +73,7 @@ struct _LinphoneLDAPContactSearch char* filter; bool_t complete; MSList* found_entries; + int found_count; }; @@ -80,7 +81,7 @@ struct _LinphoneLDAPContactSearch * LinphoneLDAPContactSearch * *************************/ -LinphoneLDAPContactSearch*linphone_ldap_contact_search_create(LinphoneLDAPContactProvider* cp, const char* predicate, ContactSearchCallback cb, void* cb_data) +LinphoneLDAPContactSearch* linphone_ldap_contact_search_create(LinphoneLDAPContactProvider* cp, const char* predicate, ContactSearchCallback cb, void* cb_data) { LinphoneLDAPContactSearch* search = belle_sip_object_new(LinphoneLDAPContactSearch); @@ -118,9 +119,16 @@ LinphoneLDAPContactSearch*linphone_ldap_contact_search_create(LinphoneLDAPContac return search; } +void linphone_ldap_contact_search_destroy_friend( void* entry ) +{ + linphone_friend_destroy((LinphoneFriend*)entry); +} + static void linphone_ldap_contact_search_destroy( LinphoneLDAPContactSearch* obj ) { ms_message("~LinphoneLDAPContactSearch(%p)", obj); + ms_list_for_each(obj->found_entries, linphone_ldap_contact_search_destroy_friend); + obj->found_entries = ms_list_free(obj->found_entries); if( obj->filter ) ms_free(obj->filter); } @@ -136,6 +144,11 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneLDAPContactSearch,LinphoneContactSearch, /* *************************** * LinphoneLDAPContactProvider * ***************************/ +static inline LinphoneLDAPContactSearch* linphone_ldap_request_entry_search( LinphoneLDAPContactProvider* obj, int msgid ); +static unsigned int linphone_ldap_contact_provider_cancel_search(LinphoneContactProvider* obj, LinphoneContactSearch *req); +static void linphone_ldap_contact_provider_conf_destroy(LinphoneLDAPContactProvider* obj ); + +/* Authentication methods */ struct AuthMethodDescription{ LDAPAuthMethod method; const char* description; @@ -147,10 +160,6 @@ static struct AuthMethodDescription ldap_auth_method_description[] = { {SASL, "sasl"}, {0, NULL} }; -static inline LinphoneLDAPContactSearch* linphone_ldap_request_entry_search( LinphoneLDAPContactProvider* obj, int msgid ); -static unsigned int linphone_ldap_contact_provider_cancel_search(LinphoneContactProvider* obj, LinphoneContactSearch *req); -static void linphone_ldap_contact_provider_conf_destroy(LinphoneLDAPContactProvider* obj ); - static LDAPAuthMethod linphone_ldap_contact_provider_auth_method( const char* description ) { @@ -163,7 +172,7 @@ static LDAPAuthMethod linphone_ldap_contact_provider_auth_method( const char* de return ANONYMOUS; } -static void linphone_ldap_contact_provider_destroy_request(void *req, void *dummy) +static void linphone_ldap_contact_provider_destroy_request(void *req) { belle_sip_object_unref(req); } @@ -171,7 +180,7 @@ static void linphone_ldap_contact_provider_destroy_request(void *req, void *dumm static void linphone_ldap_contact_provider_destroy( LinphoneLDAPContactProvider* obj ) { // clean pending requests - ms_list_for_each2(obj->requests, linphone_ldap_contact_provider_destroy_request, 0); + ms_list_for_each(obj->requests, linphone_ldap_contact_provider_destroy_request); if (obj->ld) ldap_unbind_ext(obj->ld, NULL, NULL); obj->ld = NULL; @@ -179,8 +188,7 @@ static void linphone_ldap_contact_provider_destroy( LinphoneLDAPContactProvider* linphone_ldap_contact_provider_conf_destroy(obj); } - -static int linphone_ldap_parse_bind_results( LinphoneLDAPContactProvider* obj, LDAPMessage* results ) +static int linphone_ldap_contact_provider_parse_bind_results( LinphoneLDAPContactProvider* obj, LDAPMessage* results ) { int ret = ldap_parse_sasl_bind_result(obj->ld, results, NULL, 0); if( ret != LDAP_SUCCESS ){ @@ -191,23 +199,23 @@ static int linphone_ldap_parse_bind_results( LinphoneLDAPContactProvider* obj, L return ret; } -static int linphone_ldap_complete_contact( LinphoneLDAPContactProvider* obj, struct LDAPFriendData* lf, const char* attr_name, const char* attr_value) +static int linphone_ldap_contact_provider_complete_contact( LinphoneLDAPContactProvider* obj, struct LDAPFriendData* lf, const char* attr_name, const char* attr_value) { if( strcmp(attr_name, obj->name_attr ) == 0 ){ - ms_message("Got name attr: %s", attr_value); lf->name = ms_strdup(attr_value); } else if( strcmp(attr_name, obj->sip_attr) == 0 ) { - ms_message("Got sip attr: %s", attr_value); lf->sip = ms_strdup(attr_value); } // return 1 if the structure has enough data to create a linphone friend - if( lf->name && lf->sip ) return 1; - else return 0; + if( lf->name && lf->sip ) + return 1; + else + return 0; } -static void linphone_ldap_handle_search_result( LinphoneLDAPContactProvider* obj, LinphoneLDAPContactSearch* req, LDAPMessage* message ) +static void linphone_ldap_contact_provider_handle_search_result( LinphoneLDAPContactProvider* obj, LinphoneLDAPContactSearch* req, LDAPMessage* message ) { int msgtype = ldap_msgtype(message); @@ -222,7 +230,7 @@ static void linphone_ldap_handle_search_result( LinphoneLDAPContactProvider* obj while( entry != NULL ){ struct LDAPFriendData ldap_data = {0}; - bool_t all_found = FALSE; + bool_t contact_complete = FALSE; BerElement* ber = NULL; char* attr = ldap_first_attribute(obj->ld, entry, &ber); char* dn = ldap_get_dn(obj->ld, entry); @@ -241,8 +249,8 @@ static void linphone_ldap_handle_search_result( LinphoneLDAPContactProvider* obj { ms_message("%s -> %s", attr, (*it)->bv_val); - all_found = linphone_ldap_complete_contact(obj, &ldap_data, attr, (*it)->bv_val); - if( all_found ) break; + contact_complete = linphone_ldap_contact_provider_complete_contact(obj, &ldap_data, attr, (*it)->bv_val); + if( contact_complete ) break; it++; } @@ -250,18 +258,19 @@ static void linphone_ldap_handle_search_result( LinphoneLDAPContactProvider* obj if( values ) ldap_value_free_len(values); ldap_memfree(attr); - if( all_found ) break; + if( contact_complete ) break; attr = ldap_next_attribute(obj->ld, entry, ber); } - if( all_found ) { + if( contact_complete ) { LinphoneAddress* la = linphone_core_interpret_url(lc, ldap_data.sip); if( la ){ LinphoneFriend* lf = linphone_core_create_friend(lc); linphone_friend_set_address(lf, la); linphone_friend_set_name(lf, ldap_data.name); req->found_entries = ms_list_append(req->found_entries, lf); + req->found_count++; ms_message("Added friend %s / %s", ldap_data.name, ldap_data.sip); ms_free(ldap_data.sip); ms_free(ldap_data.name); @@ -284,7 +293,6 @@ static void linphone_ldap_handle_search_result( LinphoneLDAPContactProvider* obj break; - default: ms_message("Unhandled message type %x", msgtype); break; } } @@ -298,7 +306,7 @@ static bool_t linphone_ldap_contact_provider_iterate(void *data) struct timeval timeout = {0,0}; LDAPMessage* results = NULL; - int ret = ldap_result(obj->ld, LDAP_RES_ANY, LDAP_MSG_ALL, &timeout, &results); + int ret = ldap_result(obj->ld, LDAP_RES_ANY, LDAP_MSG_ONE, &timeout, &results); if( ret != 0 && ret != -1) ms_message("ldap_result %x", ret); @@ -316,25 +324,25 @@ static bool_t linphone_ldap_contact_provider_iterate(void *data) if( ldap_msgid( results ) != obj->bind_msgid ) { ms_error("Bad msgid"); } else { - linphone_ldap_parse_bind_results( obj, results ); + linphone_ldap_contact_provider_parse_bind_results( obj, results ); obj->bind_msgid = 0; // we're bound now, don't bother checking again } break; } - case LDAP_RES_SEARCH_RESULT: case LDAP_RES_EXTENDED: case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: + case LDAP_RES_SEARCH_RESULT: { LDAPMessage* message = ldap_first_message(obj->ld, results); LinphoneLDAPContactSearch* req = linphone_ldap_request_entry_search(obj, ldap_msgid(message)); while( message != NULL ){ ms_message("Message @%p:id %d / type %x / associated request: %p", message, ldap_msgid(message), ldap_msgtype(message), req); - linphone_ldap_handle_search_result(obj, req, message ); + linphone_ldap_contact_provider_handle_search_result(obj, req, message ); message = ldap_next_message(obj->ld, message); } - if( req ) linphone_ldap_contact_provider_cancel_search(LINPHONE_CONTACT_PROVIDER(obj), LINPHONE_CONTACT_SEARCH(req)); + if( req && ret == LDAP_RES_SEARCH_RESULT) linphone_ldap_contact_provider_cancel_search(LINPHONE_CONTACT_PROVIDER(obj), LINPHONE_CONTACT_SEARCH(req)); break; } case LDAP_RES_MODIFY: @@ -501,9 +509,8 @@ static int linphone_ldap_request_entry_compare_strong(const void*a, const void* static inline LinphoneLDAPContactSearch* linphone_ldap_request_entry_search( LinphoneLDAPContactProvider* obj, int msgid ) { - LinphoneLDAPContactSearch dummy = { - .msgid = msgid - }; + LinphoneLDAPContactSearch dummy = {}; + dummy.msgid = msgid; MSList* list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy); if( list_entry ) return list_entry->data; @@ -558,7 +565,6 @@ static int linphone_ldap_marshal(LinphoneLDAPContactProvider* obj, char* buff, s error = belle_sip_snprintf(buff, buff_size, offset, "bind_msgid:%d,\n", obj->bind_msgid); if(error!= BELLE_SIP_OK) return error; - error = belle_sip_snprintf(buff, buff_size, offset, "CONFIG:\n" "tls: %d \n" diff --git a/gtk/loginframe.c b/gtk/loginframe.c index 2aa55d9dc..ef4ae9e05 100644 --- a/gtk/loginframe.c +++ b/gtk/loginframe.c @@ -167,67 +167,6 @@ void linphone_gtk_login_frame_connect_clicked(GtkWidget *button){ linphone_gtk_load_identities(); } -void test_cb( LinphoneContactSearch* req, MSList* friends, void* data ) -{ - ms_message("LDAP Search CB received:"); - GtkEntry* uribar = GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")); - GtkTreeModel* model = gtk_entry_completion_get_model(gtk_entry_get_completion(uribar)); - GtkListStore* list = GTK_LIST_STORE(model); - GtkTreeIter iter; - - - - // clear completion list from previous LDAP completion suggestions - if (!gtk_tree_model_get_iter_first(model,&iter)) return; - do { - int type; - char* url; - bool_t valid = TRUE; - gtk_tree_model_get(model,&iter,1,&type,0,&url,-1); - if (type == COMPLETION_LDAP) { - ms_message("Removing entry for %s", url?url:"NULL"); - valid = gtk_list_store_remove(list, &iter); - } else { - ms_message("Keep entry for %s (type %d)", url?url:"NULL", type); - } - - if( url ) g_free(url); - if( !valid ) break; - - }while(gtk_tree_model_iter_next(model,&iter)); - - while( friends ){ - LinphoneFriend* lf = friends->data; - if( lf ) { - const LinphoneAddress* la = linphone_friend_get_address(lf); - if( la ){ - char *addr = linphone_address_as_string(la); - - if( addr ){ - ms_message("Match: name=%s, addr=%s", linphone_friend_get_name(lf), addr); - gtk_list_store_insert_with_values(list, &iter, -1, - 0, addr, - 1, COMPLETION_LDAP, -1); - ms_free(addr); - } - } - } - friends = friends->next; - } - gtk_entry_completion_complete(gtk_entry_get_completion(uribar)); -} - - -void test_btn_clicked_cb(GtkWidget *button) -{ - ms_message("test_button_clicked_cb"); - LinphoneCore* core = linphone_gtk_get_core(); - GtkWidget *uri_bar=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"); - const gchar* pred = gtk_entry_buffer_get_text(gtk_entry_get_buffer((GtkEntry*)uri_bar)); - - linphone_core_ldap_launch_search(core, pred, test_cb, (void*)0x12345678); -} - void linphone_gtk_internet_kind_changed(GtkWidget *combo){ int netkind_id=gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); LinphoneCore *lc=linphone_gtk_get_core(); diff --git a/gtk/main.c b/gtk/main.c index 9bab5b833..870c1d40e 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -69,7 +69,7 @@ void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpoi static gboolean linphone_gtk_auto_answer(LinphoneCall *call); void linphone_gtk_status_icon_set_blinking(gboolean val); void _linphone_gtk_enable_video(gboolean val); - +void linphone_gtk_on_uribar_changed(GtkEditable *uribar, gpointer user_data); #ifndef HAVE_GTK_OSX static gint main_window_x=0; @@ -642,6 +642,10 @@ static gboolean uribar_completion_matchfunc(GtkEntryCompletion *completion, cons ret=TRUE; g_free(tmp); } + + if( address) + g_free(address); + return ret; } @@ -665,8 +669,11 @@ static void load_uri_history(){ } gtk_entry_completion_set_model(gep,GTK_TREE_MODEL(model)); gtk_entry_completion_set_text_column(gep,0); + gtk_entry_completion_set_popup_completion(gep, TRUE); gtk_entry_completion_set_match_func(gep,uribar_completion_matchfunc, NULL, NULL); + gtk_entry_completion_set_minimum_key_length(gep,3); gtk_entry_set_completion(uribar,gep); + g_signal_connect (G_OBJECT (uribar), "changed", G_CALLBACK(linphone_gtk_on_uribar_changed), NULL); } static void save_uri_history(){ @@ -718,6 +725,94 @@ static void completion_add_text(GtkEntry *entry, const char *text){ save_uri_history(); } +void on_contact_provider_search_results( LinphoneContactSearch* req, MSList* friends, void* data ) +{ + GtkTreeIter iter; + GtkEntry* uribar = GTK_ENTRY(data); + GtkEntryCompletion* compl = gtk_entry_get_completion(uribar); + GtkTreeModel* model = gtk_entry_completion_get_model(compl); + GtkListStore* list = GTK_LIST_STORE(model); + gboolean valid; + + // clear completion list from previous non-history completion suggestions + valid = gtk_tree_model_get_iter_first(model,&iter); + while(valid) + { + char* url; + int type; + gtk_tree_model_get(model,&iter, 0,&url, 1,&type, -1); + + if (type != COMPLETION_HISTORY) { + valid = gtk_list_store_remove(list, &iter); + } else { + valid = gtk_tree_model_iter_next(model,&iter); + } + + if( url ) g_free(url); + if( !valid ) break; + } + + // add new non-history related matches + while( friends ){ + LinphoneFriend* lf = friends->data; + if( lf ) { + const LinphoneAddress* la = linphone_friend_get_address(lf); + if( la ){ + char *addr = linphone_address_as_string(la); + + if( addr ){ + ms_message("[LDAP]Insert match: %s", addr); + gtk_list_store_insert_with_values(list, &iter, -1, + 0, addr, + 1, COMPLETION_LDAP, -1); + ms_free(addr); + } + } + } + friends = friends->next; + } + gtk_entry_completion_complete(compl); + + // Gtk bug? we need to emit a "changed" signal so that the completion appears if + // the list of results was previously empty + g_signal_handlers_block_by_func(uribar, linphone_gtk_on_uribar_changed, NULL); + g_signal_emit_by_name(uribar, "changed"); + g_signal_handlers_unblock_by_func(uribar, linphone_gtk_on_uribar_changed, NULL); +} + +struct CompletionTimeout { + guint timeout_id; +}; + +static gboolean launch_contact_provider_search(void *userdata) +{ + LinphoneCore* core = linphone_gtk_get_core(); + GtkWidget* uribar = GTK_WIDGET(userdata); + const gchar* predicate = gtk_entry_get_text((GtkEntry*)uribar); + + if( strlen(predicate) >= 3 ){ // don't search too small predicates + ms_message("launch_contact_provider_search"); + linphone_core_ldap_launch_search(core, predicate, on_contact_provider_search_results, uribar); + } + return FALSE; +} + +void linphone_gtk_on_uribar_changed(GtkEditable *uribar, gpointer user_data) +{ + gchar* text = gtk_editable_get_chars(uribar, 0,-1); + gint timeout = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(uribar), "complete_timeout")); + ms_message("URIBAR changed, new text: %s, userdata %p uribar @%p", text, user_data, uribar); + if( text ) g_free(text); + + + if( timeout != 0 ) { + g_source_remove(timeout); + } + timeout = g_timeout_add_seconds(1,(GSourceFunc)launch_contact_provider_search, uribar); + + gtk_object_set_data(GTK_OBJECT(uribar),"complete_timeout", GINT_TO_POINTER(timeout) ); +} + bool_t linphone_gtk_video_enabled(void){ const LinphoneVideoPolicy *vpol=linphone_core_get_video_policy(linphone_gtk_get_core()); return vpol->automatically_accept && vpol->automatically_initiate; diff --git a/gtk/main.ui b/gtk/main.ui index f27fd79bd..05461b6fc 100644 --- a/gtk/main.ui +++ b/gtk/main.ui @@ -1063,21 +1063,6 @@ 0 - - - TEST - True - True - True - False - - - - False - False - 1 - - True