diff --git a/src/plugins/api.c b/src/plugins/api.c index 965eedde..ac419ebe 100644 --- a/src/plugins/api.c +++ b/src/plugins/api.c @@ -468,13 +468,14 @@ api_incoming_message(const char *const barejid, const char *const resource, cons } void -api_disco_add_feature(char *feature) +api_disco_add_feature(char *plugin_name, char *feature) { if (feature == NULL) { return; } - disco_add_feature(feature); + disco_add_feature(plugin_name, feature); + caps_reset_ver(); // resend presence to update server's disco info data for this client diff --git a/src/plugins/api.h b/src/plugins/api.h index 70ac02a2..98728eb6 100644 --- a/src/plugins/api.h +++ b/src/plugins/api.h @@ -91,6 +91,6 @@ int api_settings_string_list_clear(const char *const group, const char *const ke void api_incoming_message(const char *const barejid, const char *const resource, const char *const message); -void api_disco_add_feature(char *feature); +void api_disco_add_feature(char *plugin_name, char *feature); #endif diff --git a/src/plugins/c_api.c b/src/plugins/c_api.c index 89d84d34..43428140 100644 --- a/src/plugins/c_api.c +++ b/src/plugins/c_api.c @@ -317,9 +317,11 @@ c_api_incoming_message(char *barejid, char *resource, char *message) } static void -c_api_disco_add_feature(char *feature) +c_api_disco_add_feature(const char *filename, char *feature) { - api_disco_add_feature(feature); + char *plugin_name = _c_plugin_name(filename); + api_disco_add_feature(plugin_name, feature); + free(plugin_name); } void @@ -386,7 +388,7 @@ c_api_init(void) prof_settings_string_list_remove = c_api_settings_string_list_remove; prof_settings_string_list_clear = c_api_settings_string_list_clear; prof_incoming_message = c_api_incoming_message; - prof_disco_add_feature = c_api_disco_add_feature; + _prof_disco_add_feature = c_api_disco_add_feature; } static char * diff --git a/src/plugins/c_plugins.c b/src/plugins/c_plugins.c index 688ba312..e6ec2b7d 100644 --- a/src/plugins/c_plugins.c +++ b/src/plugins/c_plugins.c @@ -44,6 +44,7 @@ #include "config/files.h" #include "plugins/api.h" #include "plugins/callbacks.h" +#include "plugins/disco.h" #include "plugins/plugins.h" #include "plugins/c_plugins.h" #include "plugins/c_api.h" @@ -541,6 +542,8 @@ c_plugin_destroy(ProfPlugin *plugin) callbacks_remove(plugin->name); + disco_remove_features(plugin->name); + if (dlclose (plugin->module)) { log_warning ("dlclose failed to close `%s' with `%s'", plugin->name, dlerror ()); } diff --git a/src/plugins/disco.c b/src/plugins/disco.c index ac9aff6e..bf42d4c0 100644 --- a/src/plugins/disco.c +++ b/src/plugins/disco.c @@ -37,29 +37,78 @@ #include -static GList *disco_features = NULL; +static GHashTable *plugin_to_features = NULL; + +static void +_free_features(GList *features) +{ + g_list_free_full(features, free); +} void -disco_add_feature(char* feature) +disco_add_feature(const char *plugin_name, char* feature) { - if (feature == NULL) { + if (feature == NULL || plugin_name == NULL) { return; } - disco_features = g_list_append(disco_features, strdup(feature)); + if (!plugin_to_features) { + plugin_to_features = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_free_features); + } + + GList *features = g_hash_table_lookup(plugin_to_features, plugin_name); + if (!features) { + features = g_list_append(features, strdup(feature)); + g_hash_table_insert(plugin_to_features, strdup(plugin_name), features); + } else { + features = g_list_append(features, strdup(feature)); + } +} + +void +disco_remove_features(const char *plugin_name) +{ + if (!plugin_to_features) { + return; + } + + if (!g_hash_table_contains(plugin_to_features, plugin_name)) { + return; + } + + g_hash_table_remove(plugin_to_features, plugin_name); } GList* disco_get_features(void) { - return disco_features; + GList *result = NULL; + if (!plugin_to_features) { + return result; + } + + GList *lists = g_hash_table_get_values(plugin_to_features); + GList *curr_list = lists; + while (curr_list) { + GList *features = curr_list->data; + GList *curr = features; + while (curr) { + result = g_list_append(result, curr->data); + curr = g_list_next(curr); + } + curr_list = g_list_next(curr_list); + } + + g_list_free(lists); + + return result; } void disco_close(void) { - if (disco_features) { - g_list_free_full(disco_features, free); - disco_features = NULL; + if (plugin_to_features) { + g_hash_table_destroy(plugin_to_features); + plugin_to_features = NULL; } } diff --git a/src/plugins/disco.h b/src/plugins/disco.h index 0fb3f628..f16e2642 100644 --- a/src/plugins/disco.h +++ b/src/plugins/disco.h @@ -35,7 +35,8 @@ #ifndef PLUGINS_DISCO_H #define PLUGINS_DISCO_H -void disco_add_feature(char *feature); +void disco_add_feature(const char* plugin_name, char *feature); +void disco_remove_features(const char *plugin_name); GList* disco_get_features(void); void disco_close(void); diff --git a/src/plugins/plugins.c b/src/plugins/plugins.c index 21dd0422..97e328d7 100644 --- a/src/plugins/plugins.c +++ b/src/plugins/plugins.c @@ -40,6 +40,7 @@ #include "common.h" #include "config/files.h" #include "config/preferences.h" +#include "event/client_events.h" #include "plugins/callbacks.h" #include "plugins/autocompleters.h" #include "plugins/api.h" @@ -207,6 +208,15 @@ plugins_unload(const char *const name) #endif prefs_remove_plugin(name); g_hash_table_remove(plugins, name); + + caps_reset_ver(); + // resend presence to update server's disco info data for this client + if (connection_get_status() == JABBER_CONNECTED) { + char* account_name = session_get_account_name(); + resource_presence_t last_presence = accounts_get_last_presence(account_name); + char *msg = connection_get_presence_msg(); + cl_ev_presence_send(last_presence, msg, 0); + } } return TRUE; } diff --git a/src/plugins/profapi.c b/src/plugins/profapi.c index bb08623b..b2130a01 100644 --- a/src/plugins/profapi.c +++ b/src/plugins/profapi.c @@ -88,4 +88,4 @@ int (*prof_settings_string_list_clear)(char *group, char *key) = NULL; void (*prof_incoming_message)(char *barejid, char *resource, char *message) = NULL; -void (*prof_disco_add_feature)(char *feature) = NULL; +void (*_prof_disco_add_feature)(const char *filename, char *feature) = NULL; diff --git a/src/plugins/profapi.h b/src/plugins/profapi.h index 0ab5520d..e7119a2b 100644 --- a/src/plugins/profapi.h +++ b/src/plugins/profapi.h @@ -41,6 +41,7 @@ #define prof_completer_remove(key, items) _prof_completer_remove(__FILE__, key, items) #define prof_completer_clear(key) _prof_completer_clear(__FILE__, key) #define prof_win_create(win, input_handler) _prof_win_create(__FILE__, win, input_handler) +#define prof_disco_add_feature(feature) _prof_disco_add_feature(__FILE__, feature) typedef char* PROF_WIN_TAG; typedef void(*CMD_CB)(char **args); @@ -98,6 +99,6 @@ int (*prof_settings_string_list_clear)(char *group, char *key); void (*prof_incoming_message)(char *barejid, char *resource, char *message); -void (*prof_disco_add_feature)(char *feature); +void (*_prof_disco_add_feature)(const char *filename, char *feature); #endif diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c index b58237a9..f2bce2e3 100644 --- a/src/plugins/python_api.c +++ b/src/plugins/python_api.c @@ -974,12 +974,15 @@ python_api_disco_add_feature(PyObject *self, PyObject *args) } char *feature_str = python_str_or_unicode_to_string(feature); + char *plugin_name = _python_plugin_name(); allow_python_threads(); - api_disco_add_feature(feature_str); + api_disco_add_feature(plugin_name, feature_str); free(feature_str); disable_python_threads(); + free(plugin_name); + Py_RETURN_NONE; } diff --git a/src/plugins/python_plugins.c b/src/plugins/python_plugins.c index b38afaab..66efec54 100644 --- a/src/plugins/python_plugins.c +++ b/src/plugins/python_plugins.c @@ -40,6 +40,7 @@ #include "config/files.h" #include "plugins/api.h" #include "plugins/callbacks.h" +#include "plugins/disco.h" #include "plugins/plugins.h" #include "plugins/python_api.h" #include "plugins/python_plugins.h" @@ -826,6 +827,7 @@ python_plugin_destroy(ProfPlugin *plugin) { disable_python_threads(); callbacks_remove(plugin->name); + disco_remove_features(plugin->name); free(plugin->name); free(plugin); allow_python_threads(); diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c index 218ed2a2..c270bd09 100644 --- a/src/xmpp/capabilities.c +++ b/src/xmpp/capabilities.c @@ -653,6 +653,7 @@ caps_create_query_response_stanza(xmpp_ctx_t *const ctx) curr = g_list_next(curr); } + g_list_free(plugin_features); xmpp_stanza_release(feature_receipts); xmpp_stanza_release(feature_ping);