# HG changeset patch # User Andreas Monitzer # Date 1182798496 0 # Node ID 9a19c46adf663495efb939ae2e14794de5aea9ac # Parent f88b3a093cbaad2cbf0c28c8009fc8642429c584 The server's ad-hoc commands are now listed in the account's action menu. Note that this requires an additional field in the _PurplePluginAction struct. There's no other way, since there was no way to supply user_data, and dynamically created functions are not supported by C. This should be fine, since that struct is only malloced in purple_plugin_action_new, which is part of the core. Applications have to either pass the struct unmodified, or restore the user_data pointer if the action is recreated when necessary (as is the case in Adium). diff -r f88b3a093cba -r 9a19c46adf66 libpurple/plugin.h --- a/libpurple/plugin.h Sat Jun 23 02:57:21 2007 +0000 +++ b/libpurple/plugin.h Mon Jun 25 19:08:16 2007 +0000 @@ -184,6 +184,8 @@ /** NULL for plugin actions menu, set to the PurpleConnection for account actions menu */ gpointer context; + + gpointer user_data; }; #define PURPLE_PLUGIN_HAS_ACTIONS(plugin) \ diff -r f88b3a093cba -r 9a19c46adf66 libpurple/protocols/jabber/adhoccommands.c --- a/libpurple/protocols/jabber/adhoccommands.c Sat Jun 23 02:57:21 2007 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Mon Jun 25 19:08:16 2007 +0000 @@ -199,3 +199,76 @@ } } +static void jabber_adhoc_server_got_list_cb(JabberStream *js, xmlnode *packet, gpointer data) { + xmlnode *query = xmlnode_get_child_with_namespace(packet, "query", "http://jabber.org/protocol/disco#items"); + xmlnode *item; + + if(!query) + return; + + /* clean current list (just in case there is one) */ + while(js->commands) { + JabberAdHocCommands *cmd = js->commands->data; + g_free(cmd->jid); + g_free(cmd->node); + g_free(cmd->node); + g_free(cmd); + js->commands = g_list_delete_link(js->commands, js->commands); + } + + /* re-fill list */ + for(item = query->child; item; item = item->next) { + JabberAdHocCommands *cmd; + if(item->type != XMLNODE_TYPE_TAG) + continue; + if(strcmp(item->name, "item")) + continue; + cmd = g_new0(JabberAdHocCommands, 1); + cmd->jid = g_strdup(xmlnode_get_attrib(item,"jid")); + cmd->node = g_strdup(xmlnode_get_attrib(item,"node")); + cmd->name = g_strdup(xmlnode_get_attrib(item,"name")); + + js->commands = g_list_append(js->commands,cmd); + } +} + +void jabber_adhoc_server_get_list(JabberStream *js) { + JabberIq *iq = jabber_iq_new_query(js,JABBER_IQ_GET,"http://jabber.org/protocol/disco#items"); + xmlnode *query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items"); + + xmlnode_set_attrib(iq->node,"to",js->user->domain); + xmlnode_set_attrib(query,"node","http://jabber.org/protocol/commands"); + + jabber_iq_set_callback(iq,jabber_adhoc_server_got_list_cb,NULL); + jabber_iq_send(iq); +} + +void jabber_adhoc_server_execute(PurplePluginAction *action) { + JabberAdHocCommands *cmd = action->user_data; + if(cmd) { + PurpleConnection *gc = (PurpleConnection *) action->context; + JabberStream *js = gc->proto_data; + + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET); + xmlnode *command = xmlnode_new_child(iq->node,"command"); + xmlnode_set_attrib(iq->node,"to",cmd->jid); + xmlnode_set_namespace(command,"http://jabber.org/protocol/commands"); + xmlnode_set_attrib(command,"node",cmd->node); + xmlnode_set_attrib(command,"action","execute"); + + /* we don't need to set a callback, since jabber_adhoc_parse is run for all replies */ + + jabber_iq_send(iq); + } +} + +void jabber_adhoc_init_server_commands(JabberStream *js, GList **m) { + GList *cmdlst; + + for(cmdlst = js->commands; cmdlst; cmdlst = g_list_next(cmdlst)) { + JabberAdHocCommands *cmd = cmdlst->data; + PurplePluginAction *act = purple_plugin_action_new(cmd->name, jabber_adhoc_server_execute); + act->user_data = cmd; + *m = g_list_append(*m, act); + } +} diff -r f88b3a093cba -r 9a19c46adf66 libpurple/protocols/jabber/adhoccommands.h --- a/libpurple/protocols/jabber/adhoccommands.h Sat Jun 23 02:57:21 2007 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.h Mon Jun 25 19:08:16 2007 +0000 @@ -32,4 +32,8 @@ void jabber_adhoc_execute(PurpleBlistNode *node, gpointer data); +void jabber_adhoc_server_get_list(JabberStream *js); + +void jabber_adhoc_init_server_commands(JabberStream *js, GList **m); + #endif /* _PURPLE_JABBER_ADHOCCOMMANDS_H_ */ diff -r f88b3a093cba -r 9a19c46adf66 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Sat Jun 23 02:57:21 2007 +0000 +++ b/libpurple/protocols/jabber/disco.c Mon Jun 25 19:08:16 2007 +0000 @@ -281,6 +281,11 @@ gpresence = purple_account_get_presence(js->gc->account); status = purple_presence_get_active_status(gpresence); jabber_presence_send(js->gc->account, status); + + if (js->server_caps & JABBER_CAP_ADHOC) { + /* The server supports ad-hoc commands, so let's request the list */ + jabber_adhoc_server_get_list(js); + } } static void @@ -346,6 +351,8 @@ } else if (!strcmp("google:roster", var)) { js->server_caps |= JABBER_CAP_GOOGLE_ROSTER; jabber_google_roster_init(js); + } else if (!strcmp("http://jabber.org/protocol/commands", var)) { + js->server_caps |= JABBER_CAP_ADHOC; } } diff -r f88b3a093cba -r 9a19c46adf66 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sat Jun 23 02:57:21 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Jun 25 19:08:16 2007 +0000 @@ -55,6 +55,7 @@ #include "si.h" #include "xdata.h" #include "pep.h" +#include "adhoccommands.h" #include @@ -1115,6 +1116,14 @@ #endif if(js->serverFQDN) g_free(js->serverFQDN); + while(js->commands) { + JabberAdHocCommands *cmd = js->commands->data; + g_free(cmd->jid); + g_free(cmd->node); + g_free(cmd->node); + g_free(cmd); + js->commands = g_list_delete_link(js->commands, js->commands); + } g_free(js->server_name); g_free(js->gmail_last_time); g_free(js->gmail_last_tid); @@ -1632,6 +1641,9 @@ if(js->pep) jabber_pep_init_actions(&m); + + if(js->commands) + jabber_adhoc_init_server_commands(js, &m); return m; } diff -r f88b3a093cba -r 9a19c46adf66 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Sat Jun 23 02:57:21 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.h Mon Jun 25 19:08:16 2007 +0000 @@ -158,6 +158,9 @@ /* does the local server support PEP? */ gboolean pep; + /* A list of JabberAdHocCommands supported by the server */ + GList *commands; + /* last presence update to check for differences */ JabberBuddyState old_state; char *old_msg;