2 * purple - Jabber Protocol Plugin
4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include "adhoccommands.h"
33 static void do_adhoc_ignoreme(JabberStream
*js
, ...) {
34 /* we don't have to do anything */
42 } JabberAdHocActionInfo
;
45 jabber_adhoc_got_buddy_list(JabberStream
*js
, const char *from
, PurpleXmlNode
*query
)
49 JabberBuddyResource
*jbr
= NULL
;
52 if ((jid
= jabber_id_new(from
))) {
53 if (jid
->resource
&& (jb
= jabber_buddy_find(js
, from
, TRUE
)))
54 jbr
= jabber_buddy_find_resource(jb
, jid
->resource
);
62 /* since the list we just received is complete, wipe the old one */
63 while(jbr
->commands
) {
64 JabberAdHocCommands
*cmd
= jbr
->commands
->data
;
69 jbr
->commands
= g_list_delete_link(jbr
->commands
, jbr
->commands
);
73 for(item
= query
->child
; item
; item
= item
->next
) {
74 JabberAdHocCommands
*cmd
;
75 if(item
->type
!= PURPLE_XMLNODE_TYPE_TAG
)
77 if(!purple_strequal(item
->name
, "item"))
79 cmd
= g_new0(JabberAdHocCommands
, 1);
81 cmd
->jid
= g_strdup(purple_xmlnode_get_attrib(item
,"jid"));
82 cmd
->node
= g_strdup(purple_xmlnode_get_attrib(item
,"node"));
83 cmd
->name
= g_strdup(purple_xmlnode_get_attrib(item
,"name"));
85 jbr
->commands
= g_list_append(jbr
->commands
,cmd
);
90 jabber_adhoc_disco_result_cb(JabberStream
*js
, const char *from
,
91 JabberIqType type
, const char *id
,
92 PurpleXmlNode
*packet
, gpointer data
)
97 if (type
== JABBER_IQ_ERROR
)
100 query
= purple_xmlnode_get_child_with_namespace(packet
, "query", NS_DISCO_ITEMS
);
103 node
= purple_xmlnode_get_attrib(query
, "node");
104 if (!purple_strequal(node
, "http://jabber.org/protocol/commands"))
107 jabber_adhoc_got_buddy_list(js
, from
, query
);
110 static void jabber_adhoc_parse(JabberStream
*js
, const char *from
,
111 JabberIqType type
, const char *id
,
112 PurpleXmlNode
*packet
, gpointer data
);
114 static void do_adhoc_action_cb(JabberStream
*js
, PurpleXmlNode
*result
, const char *actionhandle
, gpointer user_data
) {
115 PurpleXmlNode
*command
;
116 JabberAdHocActionInfo
*actionInfo
= user_data
;
117 JabberIq
*iq
= jabber_iq_new(js
, JABBER_IQ_SET
);
118 jabber_iq_set_callback(iq
, jabber_adhoc_parse
, NULL
);
120 purple_xmlnode_set_attrib(iq
->node
, "to", actionInfo
->who
);
121 command
= purple_xmlnode_new_child(iq
->node
,"command");
122 purple_xmlnode_set_namespace(command
,"http://jabber.org/protocol/commands");
123 purple_xmlnode_set_attrib(command
,"sessionid",actionInfo
->sessionid
);
124 purple_xmlnode_set_attrib(command
,"node",actionInfo
->node
);
126 /* cancel is handled differently on ad-hoc commands than regular forms */
127 if (purple_strequal(purple_xmlnode_get_namespace(result
), "jabber:x:data") &&
128 purple_strequal(purple_xmlnode_get_attrib(result
, "type"), "cancel")) {
129 purple_xmlnode_set_attrib(command
,"action","cancel");
132 purple_xmlnode_set_attrib(command
,"action",actionhandle
);
133 purple_xmlnode_insert_child(command
,result
);
136 g_list_free_full(actionInfo
->actionslist
, g_free
);
137 g_free(actionInfo
->sessionid
);
138 g_free(actionInfo
->who
);
139 g_free(actionInfo
->node
);
145 jabber_adhoc_parse(JabberStream
*js
, const char *from
,
146 JabberIqType type
, const char *id
,
147 PurpleXmlNode
*packet
, gpointer data
)
149 PurpleXmlNode
*command
= purple_xmlnode_get_child_with_namespace(packet
, "command", "http://jabber.org/protocol/commands");
150 const char *status
= purple_xmlnode_get_attrib(command
,"status");
151 PurpleXmlNode
*xdata
= purple_xmlnode_get_child_with_namespace(command
,"x","jabber:x:data");
153 if (type
== JABBER_IQ_ERROR
) {
154 char *msg
= jabber_parse_error(js
, packet
, NULL
);
156 msg
= g_strdup(_("Unknown Error"));
158 purple_notify_error(NULL
, _("Ad-Hoc Command Failed"),
159 _("Ad-Hoc Command Failed"), msg
,
160 purple_request_cpar_from_connection(js
->gc
));
168 if(purple_strequal(status
,"completed")) {
170 PurpleXmlNode
*note
= purple_xmlnode_get_child(command
,"note");
173 char *data
= purple_xmlnode_get_data(note
);
174 purple_notify_info(NULL
, from
, data
, NULL
,
175 purple_request_cpar_from_connection(js
->gc
));
180 jabber_x_data_request(js
, xdata
, (jabber_x_data_cb
)do_adhoc_ignoreme
, NULL
);
183 if(purple_strequal(status
,"executing")) {
184 /* this command needs more steps */
185 PurpleXmlNode
*actions
, *action
;
187 GList
*actionslist
= NULL
;
188 JabberAdHocActionInfo
*actionInfo
;
190 return; /* shouldn't happen */
192 actions
= purple_xmlnode_get_child(command
,"actions");
194 JabberXDataAction
*defaultaction
= g_new0(JabberXDataAction
, 1);
195 defaultaction
->name
= g_strdup(_("execute"));
196 defaultaction
->handle
= g_strdup("execute");
197 actionslist
= g_list_append(actionslist
, defaultaction
);
199 const char *defaultactionhandle
= purple_xmlnode_get_attrib(actions
, "execute");
201 for(action
= actions
->child
; action
; action
= action
->next
, ++index
) {
202 if(action
->type
== PURPLE_XMLNODE_TYPE_TAG
) {
203 JabberXDataAction
*newaction
= g_new0(JabberXDataAction
, 1);
204 newaction
->name
= g_strdup(_(action
->name
));
205 newaction
->handle
= g_strdup(action
->name
);
206 actionslist
= g_list_append(actionslist
, newaction
);
207 if(defaultactionhandle
&& purple_strequal(defaultactionhandle
, action
->name
))
213 actionInfo
= g_new0(JabberAdHocActionInfo
, 1);
214 actionInfo
->sessionid
= g_strdup(purple_xmlnode_get_attrib(command
,"sessionid"));
215 actionInfo
->who
= g_strdup(from
);
216 actionInfo
->node
= g_strdup(purple_xmlnode_get_attrib(command
,"node"));
217 actionInfo
->actionslist
= actionslist
;
219 jabber_x_data_request_with_actions(js
,xdata
,actionslist
,actionindex
,do_adhoc_action_cb
,actionInfo
);
223 void jabber_adhoc_execute_action(PurpleBlistNode
*node
, gpointer data
) {
224 if (PURPLE_IS_BUDDY(node
)) {
225 JabberAdHocCommands
*cmd
= data
;
226 PurpleBuddy
*buddy
= (PurpleBuddy
*) node
;
227 PurpleAccount
*account
= purple_buddy_get_account(buddy
);
228 PurpleConnection
*gc
= purple_account_get_connection(account
);
229 JabberStream
*js
= purple_connection_get_protocol_data(gc
);
231 jabber_adhoc_execute(js
, cmd
);
236 jabber_adhoc_got_server_list(JabberStream
*js
, const char *from
, PurpleXmlNode
*query
)
243 /* clean current list (just in case there is one) */
244 while(js
->commands
) {
245 JabberAdHocCommands
*cmd
= js
->commands
->data
;
250 js
->commands
= g_list_delete_link(js
->commands
, js
->commands
);
254 for(item
= query
->child
; item
; item
= item
->next
) {
255 JabberAdHocCommands
*cmd
;
256 if(item
->type
!= PURPLE_XMLNODE_TYPE_TAG
)
258 if(!purple_strequal(item
->name
, "item"))
260 cmd
= g_new0(JabberAdHocCommands
, 1);
261 cmd
->jid
= g_strdup(purple_xmlnode_get_attrib(item
,"jid"));
262 cmd
->node
= g_strdup(purple_xmlnode_get_attrib(item
,"node"));
263 cmd
->name
= g_strdup(purple_xmlnode_get_attrib(item
,"name"));
265 js
->commands
= g_list_append(js
->commands
,cmd
);
268 if (js
->state
== JABBER_STREAM_CONNECTED
)
269 purple_protocol_got_account_actions(purple_connection_get_account(js
->gc
));
273 jabber_adhoc_server_got_list_cb(JabberStream
*js
, const char *from
,
274 JabberIqType type
, const char *id
,
275 PurpleXmlNode
*packet
, gpointer data
)
277 PurpleXmlNode
*query
= purple_xmlnode_get_child_with_namespace(packet
, "query",
280 jabber_adhoc_got_server_list(js
, from
, query
);
284 void jabber_adhoc_got_list(JabberStream
*js
, const char *from
, PurpleXmlNode
*query
)
286 if (purple_strequal(from
, js
->user
->domain
)) {
287 jabber_adhoc_got_server_list(js
, from
, query
);
289 jabber_adhoc_got_buddy_list(js
, from
, query
);
293 void jabber_adhoc_server_get_list(JabberStream
*js
) {
294 JabberIq
*iq
= jabber_iq_new_query(js
, JABBER_IQ_GET
, NS_DISCO_ITEMS
);
295 PurpleXmlNode
*query
= purple_xmlnode_get_child_with_namespace(iq
->node
, "query",
298 purple_xmlnode_set_attrib(iq
->node
,"to",js
->user
->domain
);
299 purple_xmlnode_set_attrib(query
,"node","http://jabber.org/protocol/commands");
301 jabber_iq_set_callback(iq
,jabber_adhoc_server_got_list_cb
,NULL
);
305 void jabber_adhoc_execute(JabberStream
*js
, JabberAdHocCommands
*cmd
) {
306 JabberIq
*iq
= jabber_iq_new(js
, JABBER_IQ_SET
);
307 PurpleXmlNode
*command
= purple_xmlnode_new_child(iq
->node
,"command");
308 purple_xmlnode_set_attrib(iq
->node
,"to",cmd
->jid
);
309 purple_xmlnode_set_namespace(command
,"http://jabber.org/protocol/commands");
310 purple_xmlnode_set_attrib(command
,"node",cmd
->node
);
311 purple_xmlnode_set_attrib(command
,"action","execute");
313 jabber_iq_set_callback(iq
,jabber_adhoc_parse
,NULL
);
318 static void jabber_adhoc_server_execute(PurpleProtocolAction
*action
) {
319 JabberAdHocCommands
*cmd
= action
->user_data
;
321 PurpleConnection
*gc
= (PurpleConnection
*) action
->connection
;
322 JabberStream
*js
= purple_connection_get_protocol_data(gc
);
324 jabber_adhoc_execute(js
, cmd
);
328 void jabber_adhoc_init_server_commands(JabberStream
*js
, GList
**m
) {
332 /* also add commands for other clients connected to the same account on another resource */
333 char *accountname
= g_strdup_printf("%s@%s", js
->user
->node
, js
->user
->domain
);
334 if((jb
= jabber_buddy_find(js
, accountname
, TRUE
))) {
336 for(iter
= jb
->resources
; iter
; iter
= g_list_next(iter
)) {
337 JabberBuddyResource
*jbr
= iter
->data
;
339 for(riter
= jbr
->commands
; riter
; riter
= g_list_next(riter
)) {
340 JabberAdHocCommands
*cmd
= riter
->data
;
341 char *cmdname
= g_strdup_printf("%s (%s)",cmd
->name
,jbr
->name
);
342 PurpleProtocolAction
*act
= purple_protocol_action_new(cmdname
, jabber_adhoc_server_execute
);
343 act
->user_data
= cmd
;
344 *m
= g_list_append(*m
, act
);
351 /* now add server commands */
352 for(cmdlst
= js
->commands
; cmdlst
; cmdlst
= g_list_next(cmdlst
)) {
353 JabberAdHocCommands
*cmd
= cmdlst
->data
;
354 PurpleProtocolAction
*act
= purple_protocol_action_new(cmd
->name
, jabber_adhoc_server_execute
);
355 act
->user_data
= cmd
;
356 *m
= g_list_append(*m
, act
);