mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-07 05:53:06 +00:00
The LDAP suggestions are now correctly displayed in the suggestions
This commit is contained in:
parent
8aa375d637
commit
cfbd9b8429
4 changed files with 132 additions and 107 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
97
gtk/main.c
97
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;
|
||||
|
|
|
|||
15
gtk/main.ui
15
gtk/main.ui
|
|
@ -1063,21 +1063,6 @@
|
|||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="test_btn">
|
||||
<property name="label" translatable="yes">TEST</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="test_btn_clicked_cb" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_call">
|
||||
<property name="can_focus">True</property>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue