cpw.darkrain42.xmpp.disco: 8a2d3d89: Convert the disco browser to a plugin. R...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Mon May 25 22:30:49 EDT 2009
-----------------------------------------------------------------
Revision: 8a2d3d89b9dfc3024c007c23dcc8dc37e2f65eb6
Ancestor: b727fd1aecf23c72e9ec263c797199431603a1c5
Author: darkrain42 at pidgin.im
Date: 2009-05-26T02:27:49
Branch: im.pidgin.cpw.darkrain42.xmpp.disco
URL: http://d.pidgin.im/viewmtn/revision/info/8a2d3d89b9dfc3024c007c23dcc8dc37e2f65eb6
Deleted entries:
libpurple/disco.c libpurple/disco.h
Renamed entries:
pidgin/gtkdisco.c to pidgin/plugins/disco/gtkdisco.c
pidgin/gtkdisco.h to pidgin/plugins/disco/gtkdisco.h
Added files:
pidgin/plugins/disco/Makefile.am
pidgin/plugins/disco/xmppdisco.c
pidgin/plugins/disco/xmppdisco.h
Added directories:
pidgin/plugins/disco
Modified files:
configure.ac libpurple/Makefile.am libpurple/Makefile.mingw
libpurple/dbus-analyze-functions.py
libpurple/protocols/jabber/disco.c
libpurple/protocols/jabber/disco.h
libpurple/protocols/jabber/jabber.c
libpurple/protocols/jabber/jabber.h
libpurple/protocols/jabber/libxmpp.c libpurple/prpl.h
libpurple/purple.h.in pidgin/Makefile.am
pidgin/Makefile.mingw pidgin/gtkblist.c pidgin/gtkmain.c
pidgin/plugins/Makefile.am pidgin/plugins/disco/gtkdisco.c
pidgin/plugins/disco/gtkdisco.h
ChangeLog:
Convert the disco browser to a plugin. Refs #556
-------------- next part --------------
============================================================
--- pidgin/plugins/disco/Makefile.am ed31968509b91b8c2481e2f98d93ee289dc56b68
+++ pidgin/plugins/disco/Makefile.am ed31968509b91b8c2481e2f98d93ee289dc56b68
@@ -0,0 +1,23 @@
+plugindir = $(libdir)/pidgin
+
+xmppdisco_la_LDFLAGS = -module -avoid-version
+
+if PLUGINS
+
+plugin_LTLIBRARIES = xmppdisco.la
+
+xmppdisco_la_SOURCES = \
+ gtkdisco.c \
+ xmppdisco.c
+
+xmppdisco_la_LIBADD = $(GTK_LIBS)
+
+endif
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -I$(top_srcdir)/libpurple \
+ -I$(top_builddir)/libpurple \
+ -I$(top_srcdir)/pidgin \
+ $(DEBUG_CFLAGS) \
+ $(GTK_CFLAGS)
============================================================
--- pidgin/plugins/disco/xmppdisco.c 8bf96dcd7b4686983a2190045f0617e3413e35f8
+++ pidgin/plugins/disco/xmppdisco.c 8bf96dcd7b4686983a2190045f0617e3413e35f8
@@ -0,0 +1,647 @@
+/*
+ * Purple - XMPP Service Disco Browser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ */
+
+#include "internal.h"
+#include "pidgin.h"
+
+#include "debug.h"
+#include "signals.h"
+#include "version.h"
+
+#include "gtkconv.h"
+#include "gtkimhtml.h"
+#include "gtkplugin.h"
+
+#include "xmppdisco.h"
+#include "gtkdisco.h"
+
+/* Variables */
+PurplePlugin *my_plugin = NULL;
+static GHashTable *iq_callbacks = NULL;
+static gboolean iq_listening = FALSE;
+
+typedef void (*XmppIqCallback)(PurpleConnection *pc, const char *type,
+ const char *id, const char *from, xmlnode *iq,
+ gpointer data);
+
+struct xmpp_iq_cb_data
+{
+ gpointer context;
+ PurpleConnection *pc;
+ XmppIqCallback cb;
+};
+
+struct item_data {
+ PidginDiscoList *list;
+ XmppDiscoService *parent;
+ char *name;
+ char *node; /* disco#info replies don't always include the node */
+};
+
+static char*
+generate_next_id()
+{
+ static guint32 index = 0;
+
+ if (index == 0) {
+ do {
+ index = g_random_int();
+ } while (index == 0);
+ }
+
+ return g_strdup_printf("purpledisco%x", index++);
+}
+
+static gboolean
+remove_iq_callbacks_by_pc(gpointer key, gpointer value, gpointer user_data)
+{
+ struct xmpp_iq_cb_data *cb_data = value;
+
+ if (cb_data && cb_data->pc == user_data) {
+ /*
+ * This is a hack. All the IQ callback datas in this code are
+ * the same structure so that we can free them here. Ideally they'd
+ * be objects and this would be polymorphic. That's overkill, here.
+ */
+ struct item_data *item_data = cb_data->context;
+
+ if (item_data) {
+ pidgin_disco_list_unref(item_data->list);
+ g_free(item_data->name);
+ g_free(item_data->node);
+ g_free(item_data);
+ }
+
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+static gboolean
+xmpp_iq_received(PurpleConnection *pc, const char *type, const char *id,
+ const char *from, xmlnode *iq)
+{
+ struct xmpp_iq_cb_data *cb_data;
+
+ cb_data = g_hash_table_lookup(iq_callbacks, id);
+ if (!cb_data)
+ return FALSE;
+
+ cb_data->cb(cb_data->pc, type, id, from, iq, cb_data->context);
+
+ g_hash_table_remove(iq_callbacks, id);
+ if (g_hash_table_size(iq_callbacks) == 0) {
+ PurplePlugin *prpl = purple_connection_get_prpl(pc);
+ iq_listening = FALSE;
+ purple_signal_disconnect(prpl, "jabber-receiving-iq", my_plugin,
+ PURPLE_CALLBACK(xmpp_iq_received));
+ }
+
+ /* Om nom nom nom */
+ return TRUE;
+}
+
+static void
+xmpp_iq_register_callback(PurpleConnection *pc, gchar *id, gpointer data,
+ XmppIqCallback cb)
+{
+ struct xmpp_iq_cb_data *cbdata = g_new0(struct xmpp_iq_cb_data, 1);
+
+ cbdata->context = data;
+ cbdata->cb = cb;
+ cbdata->pc = pc;
+
+ g_hash_table_insert(iq_callbacks, id, cbdata);
+
+ if (!iq_listening) {
+ PurplePlugin *prpl = purple_plugins_find_with_id(XMPP_PLUGIN_ID);
+ iq_listening = TRUE;
+ purple_signal_connect(prpl, "jabber-receiving-iq", my_plugin,
+ PURPLE_CALLBACK(xmpp_iq_received), NULL);
+ }
+}
+
+static void
+xmpp_disco_info_do(PurpleConnection *pc, gpointer cbdata, const char *jid,
+ const char *node, XmppIqCallback cb)
+{
+ PurplePlugin *prpl;
+ PurplePluginProtocolInfo *prpl_info;
+ xmlnode *iq, *query;
+ char *id = generate_next_id();
+ char *str;
+
+ iq = xmlnode_new("iq");
+ xmlnode_set_attrib(iq, "type", "get");
+ xmlnode_set_attrib(iq, "to", jid);
+ xmlnode_set_attrib(iq, "id", id);
+
+ query = xmlnode_new_child(iq, "query");
+ xmlnode_set_namespace(query, NS_DISCO_INFO);
+ if (node)
+ xmlnode_set_attrib(query, "node", node);
+
+ xmpp_iq_register_callback(pc, id, cbdata, cb);
+
+ str = xmlnode_to_str(iq, NULL);
+ prpl = purple_connection_get_prpl(pc);
+ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+ prpl_info->send_raw(pc, str, -1);
+ g_free(str);
+}
+
+static void
+xmpp_disco_items_do(PurpleConnection *pc, gpointer cbdata, const char *jid,
+ const char *node, XmppIqCallback cb)
+{
+ PurplePlugin *prpl;
+ PurplePluginProtocolInfo *prpl_info;
+ xmlnode *iq, *query;
+ char *id = generate_next_id();
+ char *str;
+
+ iq = xmlnode_new("iq");
+ xmlnode_set_attrib(iq, "type", "get");
+ xmlnode_set_attrib(iq, "to", jid);
+ xmlnode_set_attrib(iq, "id", id);
+
+ query = xmlnode_new_child(iq, "query");
+ xmlnode_set_namespace(query, NS_DISCO_ITEMS);
+ if (node)
+ xmlnode_set_attrib(query, "node", node);
+
+ xmpp_iq_register_callback(pc, id, cbdata, cb);
+
+ str = xmlnode_to_str(iq, NULL);
+ prpl = purple_connection_get_prpl(pc);
+ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+ prpl_info->send_raw(pc, str, -1);
+ g_free(str);
+}
+
+static XmppDiscoServiceType
+disco_service_type_from_identity(xmlnode *identity)
+{
+ const char *category, *type;
+
+ if (!identity)
+ return XMPP_DISCO_SERVICE_TYPE_OTHER;
+
+ category = xmlnode_get_attrib(identity, "category");
+ type = xmlnode_get_attrib(identity, "type");
+
+ if (!category)
+ return XMPP_DISCO_SERVICE_TYPE_OTHER;
+
+ if (g_str_equal(category, "conference"))
+ return XMPP_DISCO_SERVICE_TYPE_CHAT;
+ else if (g_str_equal(category, "directory"))
+ return XMPP_DISCO_SERVICE_TYPE_DIRECTORY;
+ else if (g_str_equal(category, "gateway"))
+ return XMPP_DISCO_SERVICE_TYPE_GATEWAY;
+ else if (g_str_equal(category, "pubsub")) {
+ if (!type || g_str_equal(type, "collection"))
+ return XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION;
+ else if (g_str_equal(type, "leaf"))
+ return XMPP_DISCO_SERVICE_TYPE_PUBSUB_LEAF;
+ else if (g_str_equal(type, "service")) {
+ purple_debug_error("xmppdisco", "here\n");
+ return XMPP_DISCO_SERVICE_TYPE_OTHER;
+ } else {
+ purple_debug_warning("xmppdisco", "Unknown pubsub type '%s'\n", type);
+ return XMPP_DISCO_SERVICE_TYPE_OTHER;
+ }
+ }
+
+ return XMPP_DISCO_SERVICE_TYPE_OTHER;
+}
+
+static const struct {
+ const char *from;
+ const char *to;
+} disco_type_mappings[] = {
+ { "gadu-gadu", "gadu-gadu" }, /* the prpl is prpl-gg, but list_icon returns "gadu-gadu" */
+ { "sametime", "meanwhile" },
+ { "myspaceim", "myspace" },
+ { "xmpp", "jabber" }, /* prpl-jabber (mentioned in case the prpl is renamed so this line will match) */
+ { NULL, NULL }
+};
+
+static const gchar *
+disco_type_from_string(const gchar *str)
+{
+ int i = 0;
+
+ g_return_val_if_fail(str != NULL, "");
+
+ for ( ; disco_type_mappings[i].from; ++i) {
+ if (!strcasecmp(str, disco_type_mappings[i].from))
+ return disco_type_mappings[i].to;
+ }
+
+ /* fallback to the string itself */
+ return str;
+}
+
+static void
+got_info_cb(PurpleConnection *pc, const char *type, const char *id,
+ const char *from, xmlnode *iq, gpointer data)
+{
+ struct item_data *item_data = data;
+ PidginDiscoList *list = item_data->list;
+ xmlnode *query;
+
+ --list->fetch_count;
+
+ if (!list->in_progress)
+ goto out;
+
+ if (g_str_equal(type, "result") &&
+ (query = xmlnode_get_child(iq, "query"))) {
+ xmlnode *identity = xmlnode_get_child(query, "identity");
+ XmppDiscoService *service;
+ xmlnode *feature;
+
+ service = g_new0(XmppDiscoService, 1);
+ service->list = item_data->list;
+ purple_debug_info("xmppdisco", "parent for %s is %p\n", from, item_data->parent);
+ service->parent = item_data->parent;
+ service->flags = XMPP_DISCO_ADD;
+ service->type = disco_service_type_from_identity(identity);
+
+ if (item_data->node) {
+ if (item_data->name) {
+ service->name = item_data->name;
+ item_data->name = NULL;
+ } else
+ service->name = g_strdup(item_data->node);
+
+ service->node = item_data->node;
+ item_data->node = NULL;
+
+ if (service->type == XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION)
+ service->flags |= XMPP_DISCO_BROWSE;
+ } else
+ service->name = g_strdup(from);
+
+ if (item_data->name) {
+ service->description = item_data->name;
+ item_data->name = NULL;
+ } else if (identity)
+ service->description = g_strdup(xmlnode_get_attrib(identity, "name"));
+
+ /* TODO: Overlap with service->name a bit */
+ service->jid = g_strdup(from);
+
+ for (feature = xmlnode_get_child(query, "feature"); feature;
+ feature = xmlnode_get_next_twin(feature)) {
+ const char *var;
+ if (!(var = xmlnode_get_attrib(feature, "var")))
+ continue;
+
+ if (g_str_equal(var, NS_REGISTER))
+ service->flags |= XMPP_DISCO_REGISTER;
+ else if (g_str_equal(var, NS_DISCO_ITEMS))
+ service->flags |= XMPP_DISCO_BROWSE;
+ else if (g_str_equal(var, NS_MUC)) {
+ service->flags |= XMPP_DISCO_BROWSE;
+ service->type = XMPP_DISCO_SERVICE_TYPE_CHAT;
+ }
+ }
+
+ if (service->type == XMPP_DISCO_SERVICE_TYPE_GATEWAY)
+ service->gateway_type = g_strdup(disco_type_from_string(
+ xmlnode_get_attrib(identity, "type")));
+
+ pidgin_disco_add_service(list, service, service->parent);
+ }
+
+out:
+ if (list->fetch_count == 0)
+ pidgin_disco_list_set_in_progress(list, FALSE);
+
+ g_free(item_data->name);
+ g_free(item_data->node);
+ g_free(item_data);
+ pidgin_disco_list_unref(list);
+}
+
+static void
+got_items_cb(PurpleConnection *pc, const char *type, const char *id,
+ const char *from, xmlnode *iq, gpointer data)
+{
+ struct item_data *item_data = data;
+ PidginDiscoList *list = item_data->list;
+ xmlnode *query;
+
+ --list->fetch_count;
+
+ if (!list->in_progress)
+ goto out;
+
+ if (g_str_equal(type, "result") &&
+ (query = xmlnode_get_child(iq, "query"))) {
+ xmlnode *item;
+
+ for (item = xmlnode_get_child(query, "item"); item;
+ item = xmlnode_get_next_twin(item)) {
+ const char *jid = xmlnode_get_attrib(item, "jid");
+ const char *name = xmlnode_get_attrib(item, "name");
+ const char *node = xmlnode_get_attrib(item, "node");
+
+ if (item_data->parent->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
+ /* This is a hacky first-order approximation. Any MUC
+ * component that has a >1 level hierarchy (a Yahoo MUC
+ * transport component probably does) will violate this.
+ *
+ * On the other hand, this is better than querying all the
+ * chats at conference.jabber.org to enumerate them.
+ */
+ XmppDiscoService *service = g_new0(XmppDiscoService, 1);
+ service->list = item_data->list;
+ service->parent = item_data->parent;
+ service->flags = XMPP_DISCO_ADD;
+ service->type = XMPP_DISCO_SERVICE_TYPE_CHAT;
+
+ service->name = g_strdup(name);
+ service->jid = g_strdup(jid);
+ service->node = g_strdup(node);
+ pidgin_disco_add_service(list, service, item_data->parent);
+ } else {
+ struct item_data *item_data2 = g_new0(struct item_data, 1);
+
+ item_data2->list = item_data->list;
+ item_data2->parent = item_data->parent;
+ item_data2->name = g_strdup(name);
+ item_data2->node = g_strdup(node);
+
+ ++list->fetch_count;
+ pidgin_disco_list_ref(list);
+ xmpp_disco_info_do(pc, item_data2, jid, node, got_info_cb);
+ }
+ }
+ }
+
+out:
+ if (list->fetch_count == 0)
+ pidgin_disco_list_set_in_progress(list, FALSE);
+
+ g_free(item_data);
+ pidgin_disco_list_unref(list);
+}
+
+static void
+server_items_cb(PurpleConnection *pc, const char *type, const char *id,
+ const char *from, xmlnode *iq, gpointer data)
+{
+ struct item_data *cb_data = data;
+ PidginDiscoList *list = cb_data->list;
+ xmlnode *query;
+
+ g_free(cb_data);
+ --list->fetch_count;
+
+ if (g_str_equal(type, "result") &&
+ (query = xmlnode_get_child(iq, "query"))) {
+ xmlnode *item;
+
+ for (item = xmlnode_get_child(query, "item"); item;
+ item = xmlnode_get_next_twin(item)) {
+ const char *jid = xmlnode_get_attrib(item, "jid");
+ struct item_data *item_data;
+
+ if (!jid)
+ continue;
+
+ item_data = g_new0(struct item_data, 1);
+ item_data->list = list;
+
+ ++list->fetch_count;
+ pidgin_disco_list_ref(list);
+ xmpp_disco_info_do(pc, item_data, jid, NULL, got_info_cb);
+ }
+ }
+
+ if (list->fetch_count == 0)
+ pidgin_disco_list_set_in_progress(list, FALSE);
+
+ pidgin_disco_list_unref(list);
+}
+
+static void
+server_info_cb(PurpleConnection *pc, const char *type, const char *id,
+ const char *from, xmlnode *iq, gpointer data)
+{
+ struct item_data *cb_data = data;
+ PidginDiscoList *list = cb_data->list;
+ xmlnode *query;
+ gboolean items = FALSE;
+
+ --list->fetch_count;
+
+ if (g_str_equal(type, "result") &&
+ (query = xmlnode_get_child(iq, "query"))) {
+ xmlnode *feature;
+
+ for (feature = xmlnode_get_child(query, "feature"); feature;
+ feature = xmlnode_get_next_twin(feature)) {
+ const char *var = xmlnode_get_attrib(feature, "var");
+ if (purple_strequal(var, NS_DISCO_ITEMS)) {
+ items = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (items) {
+ xmpp_disco_items_do(pc, cb_data, from, NULL /* node */, server_items_cb);
+ ++list->fetch_count;
+ pidgin_disco_list_ref(list);
+ } else {
+ purple_notify_error(my_plugin, _("Error"),
+ _("Server does not support service discovery"),
+ NULL);
+ pidgin_disco_list_set_in_progress(list, FALSE);
+ g_free(cb_data);
+ }
+
+ pidgin_disco_list_unref(list);
+}
+
+void xmpp_disco_start(PidginDiscoList *list)
+{
+ struct item_data *cb_data;
+
+ g_return_if_fail(list != NULL);
+
+ ++list->fetch_count;
+ pidgin_disco_list_ref(list);
+
+ cb_data = g_new0(struct item_data, 1);
+ cb_data->list = list;
+
+ xmpp_disco_info_do(list->pc, cb_data, list->server, NULL, server_info_cb);
+}
+
+void xmpp_disco_service_expand(XmppDiscoService *service)
+{
+ struct item_data *item_data;
+
+ g_return_if_fail(service != NULL);
+
+ if (service->expanded)
+ return;
+
+ item_data = g_new0(struct item_data, 1);
+ item_data->list = service->list;
+ item_data->parent = service;
+
+ ++service->list->fetch_count;
+ pidgin_disco_list_ref(service->list);
+
+ pidgin_disco_list_set_in_progress(service->list, TRUE);
+
+ xmpp_disco_items_do(service->list->pc, item_data, service->jid, service->node,
+ got_items_cb);
+ service->expanded = TRUE;
+}
+
+void xmpp_disco_service_register(XmppDiscoService *service)
+{
+ PurplePlugin *prpl;
+ PurplePluginProtocolInfo *prpl_info;
+ xmlnode *iq, *query;
+ char *id = generate_next_id();
+ char *str;
+
+ iq = xmlnode_new("iq");
+ xmlnode_set_attrib(iq, "type", "get");
+ xmlnode_set_attrib(iq, "to", service->jid);
+ xmlnode_set_attrib(iq, "id", id);
+
+ query = xmlnode_new_child(iq, "query");
+ xmlnode_set_namespace(query, NS_REGISTER);
+
+ str = xmlnode_to_str(iq, NULL);
+ prpl = purple_connection_get_prpl(service->list->pc);
+ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+ prpl_info->send_raw(service->list->pc, str, -1);
+ g_free(str);
+ g_free(id);
+}
+
+static void
+create_dialog(PurplePluginAction *action)
+{
+ pidgin_disco_dialog_new();
+}
+
+static GList *
+actions(PurplePlugin *plugin, gpointer context)
+{
+ GList *l = NULL;
+ PurplePluginAction *action = NULL;
+
+ action = purple_plugin_action_new(_("XMPP Service Discovery"),
+ create_dialog);
+ l = g_list_prepend(l, action);
+
+ return l;
+}
+
+static void
+signed_off_cb(PurpleConnection *pc, gpointer unused)
+{
+ /* Deal with any dialogs */
+ pidgin_disco_signed_off_cb(pc);
+
+ /* Remove all the IQ callbacks for this connection */
+ g_hash_table_foreach_remove(iq_callbacks, remove_iq_callbacks_by_pc, pc);
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin)
+{
+ PurplePlugin *xmpp_prpl;
+
+ my_plugin = plugin;
+
+ xmpp_prpl = purple_plugins_find_with_id(XMPP_PLUGIN_ID);
+ if (NULL == xmpp_prpl)
+ return FALSE;
+
+ purple_signal_connect(purple_connections_get_handle(), "signing-off",
+ plugin, PURPLE_CALLBACK(signed_off_cb), NULL);
+
+ iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin)
+{
+ g_hash_table_destroy(iq_callbacks);
+ iq_callbacks = NULL;
+
+ purple_signals_disconnect_by_handle(plugin);
+ pidgin_disco_dialogs_destroy_all();
+
+ return TRUE;
+}
+
+static PurplePluginInfo info =
+{
+ PURPLE_PLUGIN_MAGIC,
+ PURPLE_MAJOR_VERSION,
+ PURPLE_MINOR_VERSION,
+ PURPLE_PLUGIN_STANDARD,
+ PIDGIN_PLUGIN_TYPE,
+ 0,
+ NULL,
+ PURPLE_PRIORITY_DEFAULT,
+ "gtk-xmppdisco",
+ N_("XMPP Service Discovery"),
+ DISPLAY_VERSION,
+ N_("Allows browsing and registering services."),
+ N_("This plugin is useful for registering with legacy transports or other "
+ "XMPP services."),
+ "Paul Aurich <paul at darkrain42.org>",
+ PURPLE_WEBSITE,
+ plugin_load,
+ plugin_unload,
+ NULL, /**< destroy */
+ NULL, /**< ui_info */
+ NULL, /**< extra_info */
+ NULL, /**< prefs_info */
+ actions,
+
+ /* padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+init_plugin(PurplePlugin *plugin)
+{
+}
+
+PURPLE_INIT_PLUGIN(xmppdisco, init_plugin, info)
============================================================
--- pidgin/plugins/disco/xmppdisco.h fcd8f465d76cda3ee84334749bbd588b4a2fff93
+++ pidgin/plugins/disco/xmppdisco.h fcd8f465d76cda3ee84334749bbd588b4a2fff93
@@ -0,0 +1,107 @@
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#ifndef PIDGIN_XMPP_DISCO_H
+#define PIDGIN_XMPP_DISCO_H
+
+typedef struct _XmppDiscoService XmppDiscoService;
+
+#include "gtkdisco.h"
+
+#define XMPP_PLUGIN_ID "prpl-jabber"
+#define NS_DISCO_INFO "http://jabber.org/protocol/disco#info"
+#define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items"
+#define NS_MUC "http://jabber.org/protocol/muc"
+#define NS_REGISTER "jabber:iq:register"
+
+#include "plugin.h"
+extern PurplePlugin *my_plugin;
+
+/**
+ * The types of services.
+ */
+typedef enum
+{
+ XMPP_DISCO_SERVICE_TYPE_UNSET,
+ /**
+ * A registerable gateway to another protocol. An example would be
+ * XMPP legacy transports.
+ */
+ XMPP_DISCO_SERVICE_TYPE_GATEWAY,
+
+ /**
+ * A directory (e.g. allows the user to search for other users).
+ */
+ XMPP_DISCO_SERVICE_TYPE_DIRECTORY,
+
+ /**
+ * A chat (multi-user conversation).
+ */
+ XMPP_DISCO_SERVICE_TYPE_CHAT,
+
+ /**
+ * A pubsub collection (contains nodes)
+ */
+ XMPP_DISCO_SERVICE_TYPE_PUBSUB_COLLECTION,
+
+ /**
+ * A pubsub leaf (contains stuff, not nodes).
+ */
+ XMPP_DISCO_SERVICE_TYPE_PUBSUB_LEAF,
+
+ /**
+ * Something else. Do we need more categories?
+ */
+ XMPP_DISCO_SERVICE_TYPE_OTHER
+} XmppDiscoServiceType;
+
+/**
+ * The flags of services.
+ */
+typedef enum
+{
+ XMPP_DISCO_NONE = 0x0000,
+ XMPP_DISCO_ADD = 0x0001, /**< Supports an 'add' operation */
+ XMPP_DISCO_BROWSE = 0x0002, /**< Supports browsing */
+ XMPP_DISCO_REGISTER = 0x0004 /**< Supports a 'register' operation */
+} XmppDiscoServiceFlags;
+
+struct _XmppDiscoService {
+ PidginDiscoList *list;
+ gchar *name;
+ gchar *description;
+
+ gchar *gateway_type;
+ XmppDiscoServiceType type;
+ XmppDiscoServiceFlags flags;
+
+ XmppDiscoService *parent;
+ gchar *jid;
+ gchar *node;
+ gboolean expanded;
+};
+
+void xmpp_disco_start(PidginDiscoList *list);
+
+void xmpp_disco_service_expand(XmppDiscoService *service);
+void xmpp_disco_service_register(XmppDiscoService *service);
+
+#endif /* PIDGIN_XMPP_DISCO_H */
============================================================
--- configure.ac e95474d7657d7bb0c924ba7b66d86ea80d0e2b43
+++ configure.ac a253b422b07bb1503e28342d14202d765effdcdd
@@ -2476,6 +2476,7 @@ AC_OUTPUT([Makefile
pidgin/pixmaps/emotes/small/16/Makefile
pidgin/plugins/Makefile
pidgin/plugins/cap/Makefile
+ pidgin/plugins/disco/Makefile
pidgin/plugins/gestures/Makefile
pidgin/plugins/gevolution/Makefile
pidgin/plugins/musicmessaging/Makefile
============================================================
--- libpurple/Makefile.am d7fd9426a4517d936aa1774f8c00018e458ec0e6
+++ libpurple/Makefile.am 22dfd64715e47d7c86458cd3686d2c7857fce25f
@@ -47,7 +47,6 @@ purple_coresources = \
core.c \
debug.c \
desktopitem.c \
- disco.c \
eventloop.c \
ft.c \
idle.c \
@@ -108,7 +107,6 @@ purple_coreheaders = \
dbus-maybe.h \
debug.h \
desktopitem.h \
- disco.h \
eventloop.h \
ft.h \
gaim-compat.h \
@@ -185,7 +183,7 @@ dbus_exported = dbus-useful.h dbus-defin
dbus_headers = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h
dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h buddyicon.h \
- connection.h conversation.h core.h disco.h ft.h log.h notify.h prefs.h roomlist.h \
+ connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \
savedstatuses.h smiley.h status.h server.h util.h xmlnode.h prpl.h
purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \
============================================================
--- libpurple/Makefile.mingw 7168f4e32cd14f2d730814ebcae90d09e20da4ed
+++ libpurple/Makefile.mingw 6dbe2689684904f93b276a15be868104d0df8aeb
@@ -41,7 +41,6 @@ C_SRC = \
conversation.c \
core.c \
debug.c \
- disco.c \
dnsquery.c \
dnssrv.c \
eventloop.c \
============================================================
--- libpurple/dbus-analyze-functions.py c75be29b0b56219c30ff2cad790ed9bc0423bff5
+++ libpurple/dbus-analyze-functions.py 3169b968af63f89d5e0713a426c79a78824aaf0a
@@ -31,13 +31,6 @@ excluded = [\
"purple_account_unregister",
"purple_connection_new_unregister",
- # Similar to all the above:
- "purple_disco_list_set_service_close_func",
- "purple_disco_list_set_cancel_func",
- "purple_disco_list_set_protocol_data",
- "purple_disco_list_set_expand_func",
- "purple_disco_list_set_register_func",
-
# These functions are excluded because they involve setting arbitrary
# data via pointers for protocols and UIs. This just won't work.
"purple_blist_get_ui_data",
============================================================
--- libpurple/protocols/jabber/disco.c 567ec2ef91a7f9cc0291c7ccb0bbd3e4cb39c041
+++ libpurple/protocols/jabber/disco.c a5a83f86dcad60b0576b1f99e32d40788a87c63d
@@ -51,18 +51,6 @@ struct _jabber_disco_items_cb_data {
xmlnode_set_attrib(feature, "var", x); \
}
-struct jabber_disco_list_data {
- JabberStream *js; /* TODO: Needed? */
- PurpleDiscoList *list;
- char *server;
- int fetch_count;
-};
-
-struct jabber_disco_service_data {
- char *jid;
- char *node;
-};
-
static void
jabber_disco_bytestream_server_cb(JabberStream *js, const char *from,
JabberIqType type, const char *id,
@@ -403,12 +391,6 @@ jabber_disco_finish_server_info_result_c
}
-struct _disco_data {
- struct jabber_disco_list_data *list_data;
- PurpleDiscoService *parent;
- char *node;
-};
-
static void
jabber_disco_server_info_result_cb(JabberStream *js, const char *from,
JabberIqType type, const char *id,
@@ -571,530 +553,3 @@ void jabber_disco_info_do(JabberStream *
jabber_iq_send(iq);
}
-static void
-jabber_disco_list_data_destroy(struct jabber_disco_list_data *data)
-{
- g_free(data->server);
- g_free(data);
-}
-
-static void
-disco_proto_data_destroy_cb(PurpleDiscoList *list)
-{
- struct jabber_disco_list_data *data;
-
- data = purple_disco_list_get_protocol_data(list);
- jabber_disco_list_data_destroy(data);
-}
-
-static PurpleDiscoServiceType
-jabber_disco_category_from_string(const gchar *str)
-{
- if (!g_ascii_strcasecmp(str, "gateway"))
- return PURPLE_DISCO_SERVICE_TYPE_GATEWAY;
- else if (!g_ascii_strcasecmp(str, "directory"))
- return PURPLE_DISCO_SERVICE_TYPE_DIRECTORY;
- else if (!g_ascii_strcasecmp(str, "conference"))
- return PURPLE_DISCO_SERVICE_TYPE_CHAT;
-
- return PURPLE_DISCO_SERVICE_TYPE_OTHER;
-}
-
-static const struct {
- const char *from;
- const char *to;
-} disco_type_mappings[] = {
- { "gadu-gadu", "gg" },
- { "sametime", "meanwhile" },
- { "myspaceim", "myspace" },
- { "xmpp", "jabber" },
- { NULL, NULL }
-};
-
-static const gchar *
-jabber_disco_type_from_string(const gchar *str)
-{
- int i = 0;
-
- g_return_val_if_fail(str != NULL, "");
-
- for ( ; disco_type_mappings[i].from; ++i) {
- if (!strcasecmp(str, disco_type_mappings[i].from))
- return disco_type_mappings[i].to;
- }
-
- /* fallback to the string itself */
- return str;
-}
-
-static void
-jabber_disco_service_info_cb(JabberStream *js, const char *from,
- JabberIqType type, const char *id,
- xmlnode *packet, gpointer data);
-
-static void
-jabber_disco_service_items_cb(JabberStream *js, const char *who, const char *node,
- GSList *items, gpointer data)
-{
- GSList *l;
- struct _disco_data *disco_data;
- struct jabber_disco_list_data *list_data;
- PurpleDiscoList *list;
- PurpleDiscoService *parent;
- PurpleDiscoServiceType parent_type;
- const char *parent_node;
-
- disco_data = data;
- list_data = disco_data->list_data;
- list = list_data->list;
-
- --list_data->fetch_count;
-
- if (list_data->list == NULL) {
- if (list_data->fetch_count == 0)
- jabber_disco_list_data_destroy(list_data);
-
- return;
- }
-
- if (items == NULL) {
- if (list_data->fetch_count == 0)
- purple_disco_list_set_in_progress(list, FALSE);
-
- purple_disco_list_unref(list);
- return;
- }
-
- parent = disco_data->parent;
- parent_type = purple_disco_service_get_type(parent);
- parent_node = disco_data->node;
-
- for (l = items; l; l = l->next) {
- JabberDiscoItem *item = l->data;
-
- if (parent_type & PURPLE_DISCO_SERVICE_TYPE_CHAT) {
- /* A chat server's items are chats. I promise. */
- PurpleDiscoService *service;
- struct jabber_disco_service_data *service_data;
- JabberID *jid = jabber_id_new(item->jid);
-
- if (jid) {
- service_data = g_new0(struct jabber_disco_service_data, 1);
- service_data->jid = g_strdup(item->jid);
-
- service = purple_disco_list_service_new(PURPLE_DISCO_SERVICE_TYPE_CHAT,
- jid->node, item->name, PURPLE_DISCO_ADD, service_data);
-
- purple_disco_list_service_add(list, service, parent);
-
- jabber_id_free(jid);
- }
- } else {
- JabberIq *iq;
- struct _disco_data *req_data;
- char *full_node;
-
- if (parent_node && !item->node)
- continue;
-
- if (parent_node)
- full_node = g_strconcat(parent_node, "/", item->node, NULL);
- else
- full_node = g_strdup(item->node);
-
- req_data = g_new0(struct _disco_data, 1);
- req_data->list_data = list_data;
- req_data->parent = parent;
- req_data->node = full_node;
-
- ++list_data->fetch_count;
- purple_disco_list_ref(list);
-
- iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info");
- xmlnode_set_attrib(iq->node, "to", item->jid);
- if (full_node)
- xmlnode_set_attrib(xmlnode_get_child(iq->node, "query"),
- "node", full_node);
- jabber_iq_set_callback(iq, jabber_disco_service_info_cb, req_data);
-
- jabber_iq_send(iq);
- }
- }
-
- g_slist_foreach(items, (GFunc)jabber_disco_item_free, NULL);
- g_slist_free(items);
-
- if (list_data->fetch_count == 0)
- purple_disco_list_set_in_progress(list, FALSE);
-
- purple_disco_list_unref(list);
-
- g_free(disco_data->node);
- g_free(disco_data);
-}
-
-static void
-jabber_disco_service_info_cb(JabberStream *js, const char *from,
- JabberIqType type, const char *id,
- xmlnode *packet, gpointer data)
-{
- struct _disco_data *disco_data;
- struct jabber_disco_list_data *list_data;
- xmlnode *query, *identity, *child;
- const char *name;
- char *node;
-
- PurpleDiscoList *list;
- PurpleDiscoService *parent, *service;
- PurpleDiscoServiceType service_type;
- PurpleDiscoServiceFlags flags;
- struct jabber_disco_service_data *service_data;
-
- disco_data = data;
- list_data = disco_data->list_data;
- list = list_data->list;
- parent = disco_data->parent;
-
- node = disco_data->node;
- disco_data->node = NULL;
- g_free(disco_data);
-
- --list_data->fetch_count;
-
- if (!purple_disco_list_get_in_progress(list)) {
- purple_disco_list_unref(list);
- return;
- }
-
- if (!from || type == JABBER_IQ_ERROR
- || (!(query = xmlnode_get_child(packet, "query")))
- || (!(identity = xmlnode_get_child(query, "identity")))) {
- if (list_data->fetch_count == 0)
- purple_disco_list_set_in_progress(list, FALSE);
-
- purple_disco_list_unref(list);
- return;
- }
-
- service_type = jabber_disco_category_from_string(
- xmlnode_get_attrib(identity, "category"));
-
- /* Default to allowing things to be add-able */
- flags = PURPLE_DISCO_ADD;
-
- for (child = xmlnode_get_child(query, "feature"); child;
- child = xmlnode_get_next_twin(child)) {
- const char *var;
-
- if (!(var = xmlnode_get_attrib(child, "var")))
- continue;
-
- if (g_str_equal(var, "jabber:iq:register"))
- flags |= PURPLE_DISCO_REGISTER;
-
- if (g_str_equal(var, "http://jabber.org/protocol/disco#items"))
- flags |= PURPLE_DISCO_BROWSE;
-
- if (g_str_equal(var, "http://jabber.org/protocol/muc")) {
- flags |= PURPLE_DISCO_BROWSE;
- service_type = PURPLE_DISCO_SERVICE_TYPE_CHAT;
- }
- }
-
- if (node)
- name = node;
- else
- name = from;
-
- service_data = g_new0(struct jabber_disco_service_data, 1);
- service_data->jid = g_strdup(from);
- service_data->node = node;
-
- service = purple_disco_list_service_new(service_type, name,
- xmlnode_get_attrib(identity, "name"), flags, service_data);
-
- if (service_type == PURPLE_DISCO_SERVICE_TYPE_GATEWAY)
- purple_disco_service_set_gateway_type(service,
- jabber_disco_type_from_string(xmlnode_get_attrib(identity,
- "type")));
-
- purple_disco_list_service_add(list, service, parent);
-
- if (list_data->fetch_count == 0)
- purple_disco_list_set_in_progress(list, FALSE);
-
- purple_disco_list_unref(list);
-}
-
-static void
-jabber_disco_server_items_cb(JabberStream *js, const char *from,
- JabberIqType type, const char *id,
- xmlnode *packet, gpointer data)
-{
- struct jabber_disco_list_data *list_data;
- xmlnode *query, *child;
- gboolean has_items = FALSE;
-
- list_data = data;
- --list_data->fetch_count;
-
- if (!from || type == JABBER_IQ_ERROR ||
- !purple_disco_list_get_in_progress(list_data->list)) {
- purple_disco_list_unref(list_data->list);
- return;
- }
-
- query = xmlnode_get_child(packet, "query");
-
- for(child = xmlnode_get_child(query, "item"); child;
- child = xmlnode_get_next_twin(child)) {
- JabberIq *iq;
- const char *jid;
- struct _disco_data *disco_data;
-
- if(!(jid = xmlnode_get_attrib(child, "jid")))
- continue;
-
- disco_data = g_new0(struct _disco_data, 1);
- disco_data->list_data = list_data;
-
- has_items = TRUE;
- ++list_data->fetch_count;
- purple_disco_list_ref(list_data->list);
- iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info");
- xmlnode_set_attrib(iq->node, "to", jid);
- jabber_iq_set_callback(iq, jabber_disco_service_info_cb, disco_data);
-
- jabber_iq_send(iq);
- }
-
- if (!has_items)
- purple_disco_list_set_in_progress(list_data->list, FALSE);
-
- purple_disco_list_unref(list_data->list);
-}
-
-static void
-jabber_disco_server_info_cb(JabberStream *js, const char *who, JabberCapabilities caps, gpointer data)
-{
- struct jabber_disco_list_data *list_data;
-
- list_data = data;
- --list_data->fetch_count;
-
- if (!list_data->list) {
- purple_disco_list_unref(list_data->list);
-
- if (list_data->fetch_count == 0)
- jabber_disco_list_data_destroy(list_data);
-
- return;
- }
-
- if (caps & JABBER_CAP_ITEMS) {
- JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items");
- xmlnode_set_attrib(iq->node, "to", who);
- jabber_iq_set_callback(iq, jabber_disco_server_items_cb, list_data);
-
- ++list_data->fetch_count;
- purple_disco_list_ref(list_data->list);
-
- jabber_iq_send(iq);
- } else {
- purple_notify_error(NULL, _("Error"), _("Server doesn't support service discovery"), NULL);
- purple_disco_list_set_in_progress(list_data->list, FALSE);
- }
-
- purple_disco_list_unref(list_data->list);
-}
-
-static void discolist_cancel_cb(struct jabber_disco_list_data *list_data, const char *server)
-{
- purple_disco_list_set_in_progress(list_data->list, FALSE);
- purple_disco_list_unref(list_data->list);
-}
-
-static void discolist_ok_cb(struct jabber_disco_list_data *list_data, const char *server)
-{
- JabberStream *js;
-
- js = list_data->js;
-
- if (!server || !*server) {
- purple_notify_error(js->gc, _("Invalid Server"), _("Invalid Server"), NULL);
-
- purple_disco_list_set_in_progress(list_data->list, FALSE);
- purple_disco_list_unref(list_data->list);
- return;
- }
-
- list_data->server = g_strdup(server);
- if (js->last_disco_server)
- g_free(js->last_disco_server);
- js->last_disco_server = g_strdup(server);
-
- purple_disco_list_set_in_progress(list_data->list, TRUE);
-
- ++list_data->fetch_count;
- jabber_disco_info_do(js, list_data->server, jabber_disco_server_info_cb, list_data);
-}
-
-static void
-jabber_disco_service_close(PurpleDiscoService *service)
-{
- struct jabber_disco_service_data *data;
-
- data = purple_disco_service_get_protocol_data(service);
- g_free(data->jid);
- g_free(data->node);
- g_free(data);
-}
-
-#if 0
-static void
-jabber_disco_cancel(PurpleDiscoList *list)
-{
- /* This space intentionally letft blank */
-}
-#endif
-
-static void
-jabber_disco_list_expand(PurpleDiscoList *list, PurpleDiscoService *service)
-{
- PurpleAccount *account;
- PurpleConnection *pc;
- JabberStream *js;
- struct jabber_disco_list_data *list_data;
- struct jabber_disco_service_data *service_data;
- struct _disco_data *disco_data;
-
- account = purple_disco_list_get_account(list);
- pc = purple_account_get_connection(account);
- js = purple_connection_get_protocol_data(pc);
-
- list_data = purple_disco_list_get_protocol_data(list);
-
- ++list_data->fetch_count;
- purple_disco_list_ref(list);
- disco_data = g_new0(struct _disco_data, 1);
- disco_data->list_data = list_data;
- disco_data->parent = service;
-
- service_data = purple_disco_service_get_protocol_data(service);
-
- jabber_disco_items_do(js, service_data->jid, service_data->node,
- jabber_disco_service_items_cb, disco_data);
-}
-
-static void
-jabber_disco_service_register(PurpleConnection *gc, PurpleDiscoService *service)
-{
- JabberStream *js = purple_connection_get_protocol_data(gc);
-
- jabber_register_gateway(js, purple_disco_service_get_name(service));
-}
-
-
-PurpleDiscoList *
-jabber_disco_get_list(PurpleConnection *gc)
-{
- PurpleAccount *account;
- PurpleDiscoList *list;
- JabberStream *js;
- struct jabber_disco_list_data *disco_list_data;
-
- account = purple_connection_get_account(gc);
- js = purple_connection_get_protocol_data(gc);
-
- /* We start with a ref */
- list = purple_disco_list_new(account);
-
- disco_list_data = g_new0(struct jabber_disco_list_data, 1);
- disco_list_data->list = list;
- disco_list_data->js = js;
- purple_disco_list_set_protocol_data(list, disco_list_data,
- disco_proto_data_destroy_cb);
- purple_disco_list_set_service_close_func(list, jabber_disco_service_close);
-#if 0
- purple_disco_list_set_cancel_func(list, jabber_disco_cancel);
-#endif
- purple_disco_list_set_expand_func(list, jabber_disco_list_expand);
- purple_disco_list_set_register_func(list, jabber_disco_service_register);
-
- purple_request_input(gc, _("Server name request"), _("Enter an XMPP Server"),
- _("Select an XMPP server to query"),
- js->last_disco_server ? js->last_disco_server : js->user->domain,
- FALSE, FALSE, NULL,
- _("Find Services"), PURPLE_CALLBACK(discolist_ok_cb),
- _("Cancel"), PURPLE_CALLBACK(discolist_cancel_cb),
- account, NULL, NULL, disco_list_data);
-
- return list;
-}
-
-static void
-jabber_disco_items_cb(JabberStream *js, const char *from, JabberIqType type,
- const char *id, xmlnode *packet, gpointer data)
-{
- struct _jabber_disco_items_cb_data *jdicd;
- xmlnode *query, *child;
- const char *node = NULL;
- GSList *items = NULL;
-
- jdicd = data;
-
- query = xmlnode_get_child(packet, "query");
-
- if (query)
- node = xmlnode_get_attrib(query, "node");
-
- if (!from || !query || type == JABBER_IQ_ERROR) {
- jdicd->callback(js, from, node, NULL, jdicd->data);
- g_free(jdicd);
- return;
- }
-
- for (child = xmlnode_get_child(query, "item"); child;
- child = xmlnode_get_next_twin(child)) {
- JabberDiscoItem *item;
-
- item = g_new0(JabberDiscoItem, 1);
- item->jid = g_strdup(xmlnode_get_attrib(child, "jid"));
- item->node = g_strdup(xmlnode_get_attrib(child, "node"));
- item->name = g_strdup(xmlnode_get_attrib(child, "name"));
-
- items = g_slist_prepend(items, item);
- }
-
- items = g_slist_reverse(items);
- jdicd->callback(js, from, node, items, jdicd->data);
- g_free(jdicd);
-}
-
-void jabber_disco_items_do(JabberStream *js, const char *who, const char *node,
- JabberDiscoItemsCallback *callback, gpointer data)
-{
- struct _jabber_disco_items_cb_data *jdicd;
- JabberIq *iq;
-
- jdicd = g_new0(struct _jabber_disco_items_cb_data, 1);
- jdicd->data = data;
- jdicd->callback = callback;
-
- iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items");
- if (node)
- xmlnode_set_attrib(xmlnode_get_child(iq->node, "query"), "node", node);
-
- xmlnode_set_attrib(iq->node, "to", who);
-
- jabber_iq_set_callback(iq, jabber_disco_items_cb, jdicd);
- jabber_iq_send(iq);
-}
-
-void jabber_disco_item_free(JabberDiscoItem *item)
-{
- g_free((char *)item->jid);
- g_free((char *)item->node);
- g_free((char *)item->name);
- g_free(item);
-}
============================================================
--- libpurple/protocols/jabber/disco.h 44429b3468bdcd156a0323a05c4cccf21ea851ad
+++ libpurple/protocols/jabber/disco.h 086789fea49a484b44cabaafe3cc351b47eee704
@@ -46,10 +46,4 @@ void jabber_disco_info_do(JabberStream *
void jabber_disco_info_do(JabberStream *js, const char *who,
JabberDiscoInfoCallback *callback, gpointer data);
-PurpleDiscoList *jabber_disco_get_list(PurpleConnection *gc);
-
-void jabber_disco_items_do(JabberStream *js, const char *jid, const char *node,
- JabberDiscoItemsCallback *callback, gpointer data);
-void jabber_disco_item_free(JabberDiscoItem *);
-
#endif /* PURPLE_JABBER_DISCO_H_ */
============================================================
--- libpurple/protocols/jabber/jabber.c b8e5bdeec28cac93d62affee6f345b8fa936487f
+++ libpurple/protocols/jabber/jabber.c f42e82659b6b5e994b43e3dfbd41720ce563e5c2
@@ -1554,7 +1554,6 @@ void jabber_close(PurpleConnection *gc)
g_free(js->old_uri);
g_free(js->old_track);
g_free(js->expected_rspauth);
- g_free(js->last_disco_server);
if (js->keepalive_timeout != -1)
purple_timeout_remove(js->keepalive_timeout);
============================================================
--- libpurple/protocols/jabber/jabber.h b6abb13771a38a0b8bfe931c38468819887e697a
+++ libpurple/protocols/jabber/jabber.h 3bc0f4b92e8e8d28ddfcbeabe861401d2cd2fa29
@@ -269,12 +269,6 @@ struct _JabberStream
int stun_port;
PurpleDnsQueryData *stun_query;
/* later add stuff to handle TURN relays... */
-
- /**
- * The last server the user disco'd (or NULL) via the server discovery
- * API.
- */
- char *last_disco_server;
};
typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
============================================================
--- libpurple/protocols/jabber/libxmpp.c 23d90def8ebcc0e7951e812e6aea0fd740bb2bfa
+++ libpurple/protocols/jabber/libxmpp.c 13f181b06cc93a337472a6c8c687fe2896dd1edd
@@ -123,7 +123,6 @@ static PurplePluginProtocolInfo prpl_inf
NULL, /* get_account_text_table */
jabber_initiate_media, /* initiate_media */
jabber_get_media_caps, /* get_media_caps */
- jabber_disco_get_list, /* disco_get_list */
};
static gboolean load_plugin(PurplePlugin *plugin)
============================================================
--- libpurple/prpl.h e830cae278d96260f16981784c77bbb57977b5a0
+++ libpurple/prpl.h 0a8c668f8cec8a3963e25a19f6ffadc3eabcfd83
@@ -70,7 +70,6 @@ typedef struct _PurpleBuddyIconSpec Purp
#include "proxy.h"
#include "plugin.h"
#include "roomlist.h"
-#include "disco.h"
#include "status.h"
#include "whiteboard.h"
@@ -482,11 +481,6 @@ struct _PurplePluginProtocolInfo
*/
PurpleMediaCaps (*get_media_caps)(PurpleAccount *account,
const char *who);
-
- /**
- * Service discovery prpl callbacks
- */
- PurpleDiscoList *(*disco_get_list)(PurpleConnection *gc);
};
#define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
============================================================
--- libpurple/purple.h.in dea46f95559f744f817499d5d4e480c9a8bd4bce
+++ libpurple/purple.h.in 1fa94bd111d8190501cf48321c9b4fd6d2e5261d
@@ -79,7 +79,6 @@
#include <prpl.h>
#include <request.h>
#include <roomlist.h>
-#include <disco.h>
#include <savedstatuses.h>
#include <server.h>
#include <signals.h>
============================================================
--- pidgin/Makefile.am f4e8fd7d1328b41700dd48428fd1f9a6f84a5b73
+++ pidgin/Makefile.am d5a0708ec71d9ea647b71decee4d37fca0daa64d
@@ -90,7 +90,6 @@ pidgin_SOURCES = \
gtkconv.c \
gtkdebug.c \
gtkdialogs.c \
- gtkdisco.c \
gtkdnd-hints.c \
gtkdocklet.c \
gtkdocklet-x11.c \
@@ -148,7 +147,6 @@ pidgin_headers = \
gtkconvwin.h \
gtkdebug.h \
gtkdialogs.h \
- gtkdisco.h \
gtkdnd-hints.h \
gtkdocklet.h \
gtkeventloop.h \
============================================================
--- pidgin/Makefile.mingw dc6f91094fc1986a76642fe8ae8e2c61bcbda5e9
+++ pidgin/Makefile.mingw 7c39b3c4f627c4fad417fc9317032b8f6c3075de
@@ -65,7 +65,6 @@ PIDGIN_C_SRC = \
gtkconv.c \
gtkdebug.c \
gtkdialogs.c \
- gtkdisco.c \
gtkdnd-hints.c \
gtkdocklet.c \
gtkeventloop.c \
============================================================
--- pidgin/gtkblist.c 4a2c8bb77085b35d606c478d050580865efd17ec
+++ pidgin/gtkblist.c 19f888cefb8b4b4b1e17d2545e0f13fa86cd36d6
@@ -49,7 +49,6 @@
#include "gtkconv.h"
#include "gtkdebug.h"
#include "gtkdialogs.h"
-#include "gtkdisco.h"
#include "gtkft.h"
#include "gtklog.h"
#include "gtkmenutray.h"
@@ -3406,7 +3405,6 @@ static GtkItemFactoryEntry blist_menu[]
{ N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "<Item>", NULL },
{ "/Tools/sep2", NULL, NULL, 0, "<Separator>", NULL },
{ N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_TRANSFER },
- { N_("/Tools/Service _Discovery"), NULL, pidgin_disco_dialog_show, 0, "<Item>", NULL },
{ N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
{ N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 3, "<Item>", NULL },
{ "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
@@ -4290,9 +4288,6 @@ update_menu_bar(PidginBuddyList *gtkblis
widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Room List"));
gtk_widget_set_sensitive(widget, pidgin_roomlist_is_showable());
-
- widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Service Discovery"));
- gtk_widget_set_sensitive(widget, pidgin_disco_is_showable());
}
static void
============================================================
--- pidgin/gtkmain.c 4fe17adea044abb391fac00327d5ca24b64cb400
+++ pidgin/gtkmain.c e8b5e9c5fa4c46fef1318293e9c3d96ac583d0c5
@@ -48,7 +48,6 @@
#include "gtkconv.h"
#include "gtkdebug.h"
#include "gtkdialogs.h"
-#include "gtkdisco.h"
#include "gtkdocklet.h"
#include "gtkeventloop.h"
#include "gtkft.h"
@@ -309,7 +308,6 @@ pidgin_ui_init(void)
pidgin_privacy_init();
pidgin_xfers_init();
pidgin_roomlist_init();
- pidgin_disco_init();
pidgin_log_init();
pidgin_docklet_init();
pidgin_smileys_init();
============================================================
--- pidgin/plugins/Makefile.am c9c4453becb1168c12720a61a651b5a6029f6388
+++ pidgin/plugins/Makefile.am f781c9b9509bb4f112643cd9a60265c3e419e75c
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = cap gestures gevolution musicmessaging perl ticker
+DIST_SUBDIRS = cap disco gestures gevolution musicmessaging perl ticker
if BUILD_GEVOLUTION
GEVOLUTION_DIR = gevolution
@@ -26,6 +26,7 @@ SUBDIRS = \
$(GEVOLUTION_DIR) \
$(MUSICMESSAGING_DIR) \
$(PERL_DIR) \
+ disco \
ticker
plugindir = $(libdir)/pidgin
============================================================
--- pidgin/gtkdisco.c dffe789493e75d424451092ff0b77f6a173b7d29
+++ pidgin/plugins/disco/gtkdisco.c 0cd531547c32c0a80e0d453ca20bdda03f68898c
@@ -25,40 +25,19 @@
*/
#include "internal.h"
-#include "pidgin.h"
+#include "debug.h"
#include "gtkutils.h"
-#include "debug.h"
-#include "disco.h"
+#include "pidgin.h"
+#include "request.h"
#include "gtkdisco.h"
+#include "xmppdisco.h"
-typedef struct _PidginDiscoDialog {
- GtkWidget *window;
- GtkWidget *account_widget;
-
- GtkWidget *sw;
- GtkWidget *progress;
+GList *dialogs = NULL;
- GtkWidget *stop_button;
- GtkWidget *list_button;
- GtkWidget *register_button;
- GtkWidget *add_button;
- GtkWidget *close_button;
-
- PurpleAccount *account;
- PurpleDiscoList *discolist;
-} PidginDiscoDialog;
-
-typedef struct _PidginDiscoList {
- PidginDiscoDialog *dialog;
- GtkTreeStore *model;
- GtkWidget *tree;
- GHashTable *services;
-} PidginDiscoList;
-
struct _menu_cb_info {
- PurpleDiscoList *list;
- PurpleDiscoService *service;
+ PidginDiscoList *list;
+ XmppDiscoService *service;
};
enum {
@@ -69,57 +48,147 @@ enum {
NUM_OF_COLUMNS
};
+static void
+pidgin_disco_list_destroy(PidginDiscoList *list)
+{
+ g_hash_table_destroy(list->services);
+ if (list->dialog && list->dialog->discolist == list)
+ list->dialog->discolist = NULL;
+
+ if (list->tree) {
+ gtk_widget_destroy(list->tree);
+ list->tree = NULL;
+ }
+
+ g_free((gchar*)list->server);
+ g_free(list);
+}
+
+PidginDiscoList *pidgin_disco_list_ref(PidginDiscoList *list)
+{
+ g_return_val_if_fail(list != NULL, NULL);
+
+ ++list->ref;
+ purple_debug_misc("xmppdisco", "reffing list, ref count now %d\n", list->ref);
+
+ return list;
+}
+
+void pidgin_disco_list_unref(PidginDiscoList *list)
+{
+ g_return_if_fail(list != NULL);
+
+ --list->ref;
+
+ purple_debug_misc("xmppdisco", "unreffing list, ref count now %d\n", list->ref);
+ if (list->ref == 0)
+ pidgin_disco_list_destroy(list);
+}
+
+void pidgin_disco_list_set_in_progress(PidginDiscoList *list, gboolean in_progress)
+{
+ PidginDiscoDialog *dialog = list->dialog;
+
+ if (!dialog)
+ return;
+
+ list->in_progress = in_progress;
+
+ if (in_progress) {
+ gtk_widget_set_sensitive(dialog->account_widget, FALSE);
+ gtk_widget_set_sensitive(dialog->stop_button, TRUE);
+ gtk_widget_set_sensitive(dialog->browse_button, FALSE);
+ } else {
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dialog->progress), 0.0);
+
+ gtk_widget_set_sensitive(dialog->account_widget, TRUE);
+
+ gtk_widget_set_sensitive(dialog->stop_button, FALSE);
+ gtk_widget_set_sensitive(dialog->browse_button, TRUE);
+/*
+ gtk_widget_set_sensitive(dialog->register_button, FALSE);
+ gtk_widget_set_sensitive(dialog->add_button, FALSE);
+*/
+ }
+}
+
static void pidgin_disco_create_tree(PidginDiscoList *pdl);
static void dialog_select_account_cb(GObject *w, PurpleAccount *account,
PidginDiscoDialog *dialog)
{
dialog->account = account;
+ gtk_widget_set_sensitive(dialog->browse_button, account != NULL);
}
static void register_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
{
struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "disco-info");
- PurpleAccount *account;
- PurpleConnection *gc;
- account = purple_disco_list_get_account(info->list);
- gc = purple_account_get_connection(account);
+ xmpp_disco_service_register(info->service);
+}
- purple_disco_service_register(info->service);
+static void discolist_cancel_cb(PidginDiscoList *pdl, const char *server)
+{
+ pidgin_disco_list_set_in_progress(pdl, FALSE);
+ pidgin_disco_list_unref(pdl);
}
-static void list_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
+static void discolist_ok_cb(PidginDiscoList *pdl, const char *server)
{
- PurpleConnection *gc;
+ gtk_widget_set_sensitive(pdl->dialog->browse_button, TRUE);
+
+ if (!server || !*server) {
+ purple_notify_error(my_plugin, _("Invalid Server"), _("Invalid Server"),
+ NULL);
+
+ pidgin_disco_list_set_in_progress(pdl, FALSE);
+ pidgin_disco_list_unref(pdl);
+ return;
+ }
+
+ pdl->server = g_strdup(server);
+ pidgin_disco_list_set_in_progress(pdl, TRUE);
+ xmpp_disco_start(pdl);
+}
+
+static void browse_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
+{
+ PurpleConnection *pc;
PidginDiscoList *pdl;
- gc = purple_account_get_connection(dialog->account);
- if (!gc)
+ pc = purple_account_get_connection(dialog->account);
+ if (!pc)
return;
+ gtk_widget_set_sensitive(dialog->browse_button, FALSE);
gtk_widget_set_sensitive(dialog->add_button, FALSE);
gtk_widget_set_sensitive(dialog->register_button, FALSE);
if (dialog->discolist != NULL) {
- pdl = purple_disco_list_get_ui_data(dialog->discolist);
- gtk_widget_destroy(pdl->tree);
- purple_disco_list_unref(dialog->discolist);
+ gtk_widget_destroy(dialog->discolist->tree);
+ pidgin_disco_list_unref(dialog->discolist);
}
- dialog->discolist = purple_disco_get_list(gc);
- if (!dialog->discolist)
- return;
+ pdl = dialog->discolist = g_new0(PidginDiscoList, 1);
+ pdl->services = g_hash_table_new_full(NULL, NULL, NULL,
+ (GDestroyNotify)gtk_tree_row_reference_free);
+ pdl->pc = pc;
/* We keep a copy... */
- purple_disco_list_ref(dialog->discolist);
+ pidgin_disco_list_ref(pdl);
- pdl = purple_disco_list_get_ui_data(dialog->discolist);
pdl->dialog = dialog;
-
pidgin_disco_create_tree(pdl);
if (dialog->account_widget)
gtk_widget_set_sensitive(dialog->account_widget, FALSE);
+
+ purple_request_input(my_plugin, _("Server name request"), _("Enter an XMPP Server"),
+ _("Select an XMPP server to query"),
+ "jabber.org" /* FIXME */, FALSE, FALSE, NULL,
+ _("Find Services"), PURPLE_CALLBACK(discolist_ok_cb),
+ _("Cancel"), PURPLE_CALLBACK(discolist_cancel_cb),
+ purple_connection_get_account(pc), NULL, NULL, pdl);
}
static void add_room_to_blist_cb(GtkButton *button, PidginDiscoDialog *dialog)
@@ -130,10 +199,10 @@ static void add_room_to_blist_cb(GtkButt
g_return_if_fail(info != NULL);
- account = purple_disco_list_get_account(info->list);
- name = purple_disco_service_get_name(info->service);
+ account = purple_connection_get_account(info->list->pc);
+ name = info->service->name;
- if (purple_disco_service_get_type(info->service) == PURPLE_DISCO_SERVICE_TYPE_CHAT)
+ if (info->service->type == XMPP_DISCO_SERVICE_TYPE_CHAT)
purple_blist_request_add_chat(account, NULL, NULL, name);
else
purple_blist_request_add_buddy(account, name, NULL, NULL);
@@ -142,8 +211,7 @@ selection_changed_cb(GtkTreeSelection *s
static void
selection_changed_cb(GtkTreeSelection *selection, PidginDiscoList *pdl)
{
- PurpleDiscoService *service;
- PurpleDiscoServiceFlags flags;
+ XmppDiscoService *service;
GtkTreeIter iter;
GValue val;
static struct _menu_cb_info *info;
@@ -167,10 +235,8 @@ selection_changed_cb(GtkTreeSelection *s
info, g_free);
g_object_set_data(G_OBJECT(dialog->register_button), "disco-info", info);
- flags = purple_disco_service_get_flags(service);
-
- gtk_widget_set_sensitive(dialog->add_button, flags & PURPLE_DISCO_ADD);
- gtk_widget_set_sensitive(dialog->register_button, flags & PURPLE_DISCO_REGISTER);
+ gtk_widget_set_sensitive(dialog->add_button, service->flags & XMPP_DISCO_ADD);
+ gtk_widget_set_sensitive(dialog->register_button, service->flags & XMPP_DISCO_REGISTER);
} else {
gtk_widget_set_sensitive(dialog->add_button, FALSE);
gtk_widget_set_sensitive(dialog->register_button, FALSE);
@@ -182,7 +248,7 @@ row_expanded_cb(GtkTreeView *tree, GtkTr
gpointer user_data)
{
PidginDiscoList *pdl;
- PurpleDiscoService *service;
+ XmppDiscoService *service;
GValue val;
pdl = user_data;
@@ -191,77 +257,45 @@ row_expanded_cb(GtkTreeView *tree, GtkTr
gtk_tree_model_get_value(GTK_TREE_MODEL(pdl->model), arg1, SERVICE_COLUMN,
&val);
service = g_value_get_pointer(&val);
- purple_disco_service_expand(service);
+ xmpp_disco_service_expand(service);
}
-static gint
-delete_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d)
+static void
+destroy_win_cb(GtkWidget *window, gpointer d)
{
PidginDiscoDialog *dialog = d;
+ PidginDiscoList *list = dialog->discolist;
- if (dialog->discolist && purple_disco_list_get_in_progress(dialog->discolist))
- purple_disco_cancel_get_list(dialog->discolist);
+ if (list) {
+ list->dialog = NULL;
- if (dialog->discolist) {
- PidginDiscoList *pdl = purple_disco_list_get_ui_data(dialog->discolist);
+ if (list->in_progress)
+ list->in_progress = FALSE;
- if (pdl)
- pdl->dialog = NULL;
- purple_disco_list_unref(dialog->discolist);
+ pidgin_disco_list_unref(list);
}
+ dialogs = g_list_remove(dialogs, d);
g_free(dialog);
-
- return FALSE;
}
static void stop_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
{
- purple_disco_cancel_get_list(dialog->discolist);
-
- if (dialog->account_widget)
- gtk_widget_set_sensitive(dialog->account_widget, TRUE);
-
- gtk_widget_set_sensitive(dialog->stop_button, FALSE);
- gtk_widget_set_sensitive(dialog->list_button, TRUE);
- gtk_widget_set_sensitive(dialog->add_button, FALSE);
+ pidgin_disco_list_set_in_progress(dialog->discolist, FALSE);
}
static void close_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
{
GtkWidget *window = dialog->window;
- delete_win_cb(NULL, NULL, dialog);
gtk_widget_destroy(window);
}
static gboolean account_filter_func(PurpleAccount *account)
{
- PurpleConnection *conn = purple_account_get_connection(account);
- PurplePluginProtocolInfo *prpl_info = NULL;
-
- if (conn)
- prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl);
-
- return (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, disco_get_list));
+ return purple_strequal(purple_account_get_protocol_id(account), XMPP_PLUGIN_ID);
}
-gboolean
-pidgin_disco_is_showable()
-{
- GList *c;
- PurpleConnection *gc;
-
- for (c = purple_connections_get_all(); c != NULL; c = c->next) {
- gc = c->data;
-
- if (account_filter_func(purple_connection_get_account(gc)))
- return TRUE;
- }
-
- return FALSE;
-}
-
static void pidgin_disco_create_tree(PidginDiscoList *pdl)
{
GtkCellRenderer *text_renderer, *pixbuf_renderer;
@@ -289,7 +323,7 @@ static void pidgin_disco_create_tree(Pid
text_renderer = gtk_cell_renderer_text_new();
pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
-
+
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Name"));
@@ -320,20 +354,58 @@ static void pidgin_disco_create_tree(Pid
g_signal_connect(G_OBJECT(pdl->tree), "row-expanded", G_CALLBACK(row_expanded_cb), pdl);
}
-static PidginDiscoDialog*
-pidgin_disco_dialog_new_with_account(PurpleAccount *account)
+void pidgin_disco_signed_off_cb(PurpleConnection *pc)
{
+ GList *node;
+
+ for (node = dialogs; node; node = node->next) {
+ PidginDiscoDialog *dialog = node->data;
+ PidginDiscoList *list = dialog->discolist;
+
+ if (list && list->pc == pc) {
+ if (list->in_progress)
+ pidgin_disco_list_set_in_progress(list, FALSE);
+
+ if (list->tree) {
+ gtk_widget_destroy(list->tree);
+ list->tree = NULL;
+ }
+
+ pidgin_disco_list_unref(list);
+ dialog->discolist = NULL;
+
+ gtk_widget_set_sensitive(dialog->browse_button,
+ pidgin_account_option_menu_get_selected(dialog->account_widget) != NULL);
+
+ gtk_widget_set_sensitive(dialog->register_button, FALSE);
+ gtk_widget_set_sensitive(dialog->add_button, FALSE);
+ }
+ }
+}
+
+void pidgin_disco_dialogs_destroy_all(void)
+{
+ while (dialogs) {
+ PidginDiscoDialog *dialog = dialogs->data;
+
+ gtk_widget_destroy(dialog->window);
+ /* destroy_win_cb removes the dialog from the list */
+ }
+}
+
+PidginDiscoDialog *pidgin_disco_dialog_new(void)
+{
PidginDiscoDialog *dialog;
GtkWidget *window, *vbox, *vbox2, *bbox;
dialog = g_new0(PidginDiscoDialog, 1);
- dialog->account = account;
+ dialogs = g_list_prepend(dialogs, dialog);
/* Create the window. */
dialog->window = window = pidgin_create_dialog(_("Service Discovery"), PIDGIN_HIG_BORDER, "service discovery", TRUE);
- g_signal_connect(G_OBJECT(window), "delete_event",
- G_CALLBACK(delete_win_cb), dialog);
+ g_signal_connect(G_OBJECT(window), "destroy",
+ G_CALLBACK(destroy_win_cb), dialog);
/* Create the parent vbox for everything. */
vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(window), FALSE, PIDGIN_HIG_BORDER);
@@ -343,10 +415,9 @@ pidgin_disco_dialog_new_with_account(Pur
gtk_widget_show(vbox2);
/* accounts dropdown list */
- dialog->account_widget = pidgin_account_option_menu_new(dialog->account, FALSE,
+ dialog->account_widget = pidgin_account_option_menu_new(NULL, FALSE,
G_CALLBACK(dialog_select_account_cb), account_filter_func, dialog);
- if (!dialog->account) /* this is normally null, and we normally don't care what the first selected item is */
- dialog->account = pidgin_account_option_menu_get_selected(dialog->account_widget);
+ dialog->account = pidgin_account_option_menu_get_selected(dialog->account_widget);
pidgin_add_widget_to_vbox(GTK_BOX(vbox2), _("_Account:"), NULL, dialog->account_widget, TRUE, NULL);
/* scrolled window */
@@ -366,7 +437,6 @@ pidgin_disco_dialog_new_with_account(Pur
gtk_box_pack_start(GTK_BOX(vbox2), dialog->progress, FALSE, FALSE, 0);
gtk_widget_show(dialog->progress);
-
/* button box */
bbox = pidgin_dialog_get_action_area(GTK_DIALOG(window));
gtk_box_set_spacing(GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE);
@@ -377,13 +447,14 @@ pidgin_disco_dialog_new_with_account(Pur
G_CALLBACK(stop_button_cb), dialog);
gtk_widget_set_sensitive(dialog->stop_button, FALSE);
- /* list button */
- dialog->list_button = pidgin_pixbuf_button_from_stock(_("_Browse"), GTK_STOCK_REFRESH,
+ /* browse button */
+ dialog->browse_button = pidgin_pixbuf_button_from_stock(_("_Browse"), GTK_STOCK_REFRESH,
PIDGIN_BUTTON_HORIZONTAL);
- gtk_box_pack_start(GTK_BOX(bbox), dialog->list_button, FALSE, FALSE, 0);
- g_signal_connect(G_OBJECT(dialog->list_button), "clicked",
- G_CALLBACK(list_button_cb), dialog);
- gtk_widget_show(dialog->list_button);
+ gtk_box_pack_start(GTK_BOX(bbox), dialog->browse_button, FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(dialog->browse_button), "clicked",
+ G_CALLBACK(browse_button_cb), dialog);
+ gtk_widget_set_sensitive(dialog->browse_button, dialog->account != NULL);
+ gtk_widget_show(dialog->browse_button);
/* register button */
dialog->register_button = pidgin_dialog_add_button(GTK_DIALOG(dialog->window), _("Register"),
@@ -409,90 +480,18 @@ pidgin_disco_dialog_new_with_account(Pur
return dialog;
}
-void
-pidgin_disco_dialog_show(void)
+void pidgin_disco_add_service(PidginDiscoList *pdl, XmppDiscoService *service, XmppDiscoService *parent)
{
- pidgin_disco_dialog_new_with_account(NULL);
-}
-
-void
-pidgin_disco_dialog_show_with_account(PurpleAccount* account)
-{
- PidginDiscoDialog *dialog = pidgin_disco_dialog_new_with_account(account);
-
- if (!dialog)
- return;
-
- list_button_cb(GTK_BUTTON(dialog->list_button), dialog);
-}
-
-static void
-pidgin_disco_create(PurpleDiscoList *list)
-{
- PidginDiscoList *pdl = g_new0(PidginDiscoList, 1);
-
- purple_disco_list_set_ui_data(list, pdl);
-
- pdl->services = g_hash_table_new_full(NULL, NULL, NULL,
- (GDestroyNotify)gtk_tree_row_reference_free);
-}
-
-
-static void
-pidgin_disco_destroy(PurpleDiscoList *list)
-{
- PidginDiscoList *pdl;
-
- pdl = purple_disco_list_get_ui_data(list);
-
- g_hash_table_destroy(pdl->services);
- g_free(pdl);
-
- purple_disco_list_set_ui_data(list, NULL);
-}
-
-static void pidgin_disco_in_progress(PurpleDiscoList *list, gboolean in_progress)
-{
- PidginDiscoList *pdl;
PidginDiscoDialog *dialog;
-
- pdl = purple_disco_list_get_ui_data(list);
- if (!pdl)
- return;
-
- dialog = pdl->dialog;
- if (!dialog)
- return;
-
- if (in_progress) {
- if (dialog->account_widget)
- gtk_widget_set_sensitive(dialog->account_widget, FALSE);
- gtk_widget_set_sensitive(dialog->stop_button, TRUE);
- gtk_widget_set_sensitive(dialog->list_button, FALSE);
- } else {
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dialog->progress), 0.0);
- if (dialog->account_widget)
- gtk_widget_set_sensitive(dialog->account_widget, TRUE);
- gtk_widget_set_sensitive(dialog->stop_button, FALSE);
- gtk_widget_set_sensitive(dialog->list_button, TRUE);
- }
-}
-
-static void pidgin_disco_add_service(PurpleDiscoList *list, PurpleDiscoService *service, PurpleDiscoService *parent)
-{
- PidginDiscoList *pdl;
- PidginDiscoDialog *dialog;
- PurpleDiscoServiceType type;
- const char *gateway_type;
GtkTreeIter iter, parent_iter, child;
char *filename = NULL;
GdkPixbuf *pixbuf = NULL;
gboolean append = TRUE;
- pdl = purple_disco_list_get_ui_data(list);
dialog = pdl->dialog;
+ g_return_if_fail(dialog != NULL);
- purple_debug_info("disco", "Add_service \"%s\"\n", purple_disco_service_get_name(service));
+ purple_debug_info("xmppdisco", "Adding service \"%s\"\n", service->name);
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(dialog->progress));
@@ -508,7 +507,7 @@ static void pidgin_disco_add_service(Pur
if (gtk_tree_model_iter_children(GTK_TREE_MODEL(pdl->model), &child,
&parent_iter)) {
- PurpleDiscoList *tmp;
+ PidginDiscoList *tmp;
gtk_tree_model_get(GTK_TREE_MODEL(pdl->model), &child,
SERVICE_COLUMN, &tmp, -1);
if (!tmp)
@@ -522,7 +521,7 @@ static void pidgin_disco_add_service(Pur
else
iter = child;
- if (purple_disco_service_get_flags(service) & PURPLE_DISCO_BROWSE) {
+ if (service->flags & XMPP_DISCO_BROWSE) {
GtkTreeRowReference *rr;
GtkTreePath *path;
@@ -534,18 +533,15 @@ static void pidgin_disco_add_service(Pur
gtk_tree_path_free(path);
}
- type = purple_disco_service_get_type(service);
- gateway_type = purple_disco_service_get_gateway_type(service);
-
- if (type == PURPLE_DISCO_SERVICE_TYPE_GATEWAY && gateway_type) {
- char *tmp = g_strconcat(gateway_type, ".png", NULL);
+ if (service->type == XMPP_DISCO_SERVICE_TYPE_GATEWAY && service->gateway_type) {
+ char *tmp = g_strconcat(service->gateway_type, ".png", NULL);
filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "22", tmp, NULL);
g_free(tmp);
#if 0
- } else if (type == PURPLE_DISCO_SERVICE_TYPE_USER) {
+ } else if (service->type == XMPP_DISCO_SERVICE_TYPE_USER) {
filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "status", "22", "person.png", NULL);
#endif
- } else if (type == PURPLE_DISCO_SERVICE_TYPE_CHAT)
+ } else if (service->type == XMPP_DISCO_SERVICE_TYPE_CHAT)
filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "status", "22", "chat.png", NULL);
if (filename) {
@@ -555,8 +551,8 @@ static void pidgin_disco_add_service(Pur
gtk_tree_store_set(pdl->model, &iter,
PIXBUF_COLUMN, pixbuf,
- NAME_COLUMN, purple_disco_service_get_name(service),
- DESCRIPTION_COLUMN, purple_disco_service_get_description(service),
+ NAME_COLUMN, service->name,
+ DESCRIPTION_COLUMN, service->description,
SERVICE_COLUMN, service,
-1);
@@ -564,19 +560,3 @@ static void pidgin_disco_add_service(Pur
g_object_unref(pixbuf);
}
-static PurpleDiscoUiOps ops = {
- pidgin_disco_dialog_show_with_account,
- pidgin_disco_create,
- pidgin_disco_destroy,
- pidgin_disco_add_service,
- pidgin_disco_in_progress,
- /* padding */
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-void pidgin_disco_init() {
- purple_disco_set_ui_ops(&ops);
-}
============================================================
--- pidgin/gtkdisco.h 1e643fc20a98b6c11e0038da0d8e9270b56dde33
+++ pidgin/plugins/disco/gtkdisco.h ec9e2a0587c92d85c8adb45f080557fdf075d6e4
@@ -1,8 +1,3 @@
-/**
- * @file gtkdisco.c GTK+ Service Discovery UI
- * @ingroup pidgin
- */
-
/* pidgin
*
* Pidgin is the legal property of its developers, whose names are too numerous
@@ -21,36 +16,64 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
-#ifndef _GTK_DISCO_H_
-#define _GTK_DISCO_H_
+#ifndef PIDGIN_XMPP_DISCO_UI_H
+#define PIDGIN_XMPP_DISCO_UI_H
+typedef struct _PidginDiscoDialog PidginDiscoDialog;
+typedef struct _PidginDiscoList PidginDiscoList;
-/**
- * Initializes the service discovery subsystem.
- */
-void pidgin_disco_init(void);
+#include "xmppdisco.h"
-/**
- * Determines if showing the service discovery dialog is a valid action.
- *
- * @return TRUE if there are accounts online that support service
- * discovery. Otherwise return FALSE.
- */
-gboolean pidgin_disco_is_showable(void);
+struct _PidginDiscoDialog {
+ GtkWidget *window;
+ GtkWidget *account_widget;
+ GtkWidget *sw;
+ GtkWidget *progress;
+
+ GtkWidget *stop_button;
+ GtkWidget *browse_button;
+ GtkWidget *register_button;
+ GtkWidget *add_button;
+ GtkWidget *close_button;
+
+ PurpleAccount *account;
+ PidginDiscoList *discolist;
+};
+
+struct _PidginDiscoList {
+ PurpleConnection *pc;
+ gboolean in_progress;
+ const gchar *server;
+
+ gint ref;
+ guint fetch_count;
+
+ PidginDiscoDialog *dialog;
+ GtkTreeStore *model;
+ GtkWidget *tree;
+ GHashTable *services;
+};
+
/**
* Shows a new service discovery dialog.
*/
-void pidgin_disco_dialog_show(void);
+PidginDiscoDialog *pidgin_disco_dialog_new(void);
/**
- * Shows a new service discovery dialog and fetches the list for the specified account.
- *
- * @param account The account to use.
+ * Destroy all the open dialogs (called when unloading the plugin).
*/
-void pidgin_disco_dialog_show_with_account(PurpleAccount *account);
+void pidgin_disco_dialogs_destroy_all(void);
+void pidgin_disco_signed_off_cb(PurpleConnection *pc);
-#endif /* _GTK_DISCO_H_ */
+void pidgin_disco_add_service(PidginDiscoList *list, XmppDiscoService *service,
+ XmppDiscoService *parent);
+
+PidginDiscoList *pidgin_disco_list_ref(PidginDiscoList *list);
+void pidgin_disco_list_unref(PidginDiscoList *list);
+
+void pidgin_disco_list_set_in_progress(PidginDiscoList *list, gboolean in_progress);
+#endif /* PIDGIN_XMPP_DISCO_UI_H */
More information about the Commits
mailing list