about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/api.c5
-rw-r--r--src/plugins/api.h2
-rw-r--r--src/plugins/c_api.c8
-rw-r--r--src/plugins/c_plugins.c3
-rw-r--r--src/plugins/disco.c65
-rw-r--r--src/plugins/disco.h3
-rw-r--r--src/plugins/plugins.c10
-rw-r--r--src/plugins/profapi.c2
-rw-r--r--src/plugins/profapi.h3
-rw-r--r--src/plugins/python_api.c5
-rw-r--r--src/plugins/python_plugins.c2
-rw-r--r--src/xmpp/capabilities.c1
12 files changed, 91 insertions, 18 deletions
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 <glib.h>
 
-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);