]> crepu.dev Git - config.git/blame_incremental - djavu-asus/emacs/elpa/jabber-20230715.456/jabber-ahc.el
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpa / jabber-20230715.456 / jabber-ahc.el
... / ...
CommitLineData
1;; jabber-ahc.el - Ad-Hoc Commands by JEP-0050 -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2003, 2004, 2007, 2008 - Magnus Henoch - mange@freemail.hu
4;; Copyright (C) 2002, 2003, 2004 - tom berger - object@intelectronica.net
5
6;; This file is a part of jabber.el.
7
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.
12
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.
17
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22(require 'jabber-disco)
23(require 'jabber-widget)
24
25(defvar jabber-ahc-sessionid nil
26 "Session ID of Ad-Hoc Command session.")
27
28(defvar jabber-ahc-node nil
29 "Node to send commands to.")
30
31(defvar jabber-ahc-commands nil
32 "Alist of ad-hoc commands provided.
33
34The keys are node names as strings (which means that they must
35not conflict). The values are plists having the following properties -
36
37acl - function taking connection object and JID of requester,
38 returning non-nil for access allowed. No function means
39 open for everyone.
40name - name of command
41func - function taking connection object and entire IQ stanza as
42 arguments and returning a <command/> node
43
44Use the function `jabber-ahc-add' to add a command to this list.")
45
46
47;;; SERVER
48(add-to-list 'jabber-disco-info-nodes
49 (list "http://jabber.org/protocol/commands"
50 '((identity ((category . "automation")
51 (type . "command-list")
52 (name . "Ad-Hoc Command list")))
53 (feature ((var . "http://jabber.org/protocol/commands")))
54 (feature ((var . "http://jabber.org/protocol/disco#items")))
55 (feature
56 ((var . "http://jabber.org/protocol/disco#info"))))))
57
58(defun jabber-ahc-add (node name func acl)
59 "Add a command to internal lists.
60NODE is the node name to be used. It must be unique.
61NAME is the natural-language name of the command.
62FUNC is a function taking the entire IQ stanza as single argument when
63this command is invoked, and returns a <command/> node.
64ACL is a function taking JID as single argument, returning non-nil for
65access allowed. nil means open for everyone."
66 (add-to-list 'jabber-ahc-commands (cons node (list 'name name
67 'func func
68 'acl acl)))
69 (add-to-list 'jabber-disco-info-nodes
70 (list node `((identity ((category . "automation")
71 (type . "command-node")
72 (name . ,name)))
73 (feature ((var . "http://jabber.org/protocol/commands")))
74 (feature ((var . "http://jabber.org/protocol/disco#info")))
75 (feature ((var . "jabber:x:data")))))))
76
77(jabber-disco-advertise-feature "http://jabber.org/protocol/commands")
78(add-to-list 'jabber-disco-items-nodes
79 (list "http://jabber.org/protocol/commands" #'jabber-ahc-disco-items nil))
80(defun jabber-ahc-disco-items (jc xml-data)
81 "Return commands in response to disco#items request.
82
83JC is the Jabber connection.
84XML-DATA is the parsed tree data from the stream (stanzas)
85obtained from `xml-parse-region'."
86 (let ((jid (jabber-xml-get-attribute xml-data 'from)))
87 (mapcar (function
88 (lambda (command)
89 (let ((node (car command))
90 (plist (cdr command)))
91 (let ((acl (plist-get plist 'acl))
92 (name (plist-get plist 'name))
93 (func (plist-get plist 'func)))
94 (when (or (not (functionp acl))
95 (funcall acl jc jid))
96 `(item ((name . ,name)
97 (jid . ,(jabber-connection-jid jc))
98 (node . ,node))))))))
99 jabber-ahc-commands)))
100
101(add-to-list 'jabber-iq-set-xmlns-alist
102 (cons "http://jabber.org/protocol/commands" 'jabber-ahc-process))
103(defun jabber-ahc-process (jc xml-data)
104
105 (let ((to (jabber-xml-get-attribute xml-data 'from))
106 (id (jabber-xml-get-attribute xml-data 'id))
107 (node (jabber-xml-get-attribute (jabber-iq-query xml-data) 'node)))
108 ;; find command
109 (let* ((plist (cdr (assoc node jabber-ahc-commands)))
110 (acl (plist-get plist 'acl))
111 (func (plist-get plist 'func)))
112 (if plist
113 ;; found
114 (if (or (not (functionp acl))
115 (funcall acl jc to))
116 ;; access control passed
117 (jabber-send-iq jc to "result"
118 (funcall func jc xml-data)
119 nil nil nil nil id)
120 ;; ...or failed
121 (jabber-signal-error "Cancel" 'not-allowed))
122 ;; No such node
123 (jabber-signal-error "Cancel" 'item-not-found)))))
124
125;;; CLIENT
126(add-to-list 'jabber-jid-service-menu
127 (cons "Request command list" 'jabber-ahc-get-list))
128(defun jabber-ahc-get-list (jc to)
129 "Request list of ad-hoc commands.
130
131See XEP-0050.
132JC is the Jabber connection."
133 (interactive (list (jabber-read-account)
134 (jabber-read-jid-completing "Request command list from: " nil nil nil nil nil)))
135 (jabber-get-disco-items jc to "http://jabber.org/protocol/commands"))
136
137(add-to-list 'jabber-jid-service-menu
138 (cons "Execute command" 'jabber-ahc-execute-command))
139(defun jabber-ahc-execute-command (jc to node)
140 "Execute ad-hoc command.
141
142See XEP-0050.
143JC is the Jabber connection."
144 (interactive (list (jabber-read-account)
145 (jabber-read-jid-completing "Execute command of: " nil nil nil nil nil)
146 (jabber-read-node "Node of command: ")))
147 (jabber-send-iq jc to
148 "set"
149 `(command ((xmlns . "http://jabber.org/protocol/commands")
150 (node . ,node)
151 (action . "execute")))
152 #'jabber-process-data #'jabber-ahc-display
153 #'jabber-process-data "Command execution failed"))
154
155(defun jabber-ahc-display (jc xml-data)
156 (let* ((from (jabber-xml-get-attribute xml-data 'from))
157 (query (jabber-iq-query xml-data))
158 (node (jabber-xml-get-attribute query 'node))
159 (notes (jabber-xml-get-children query 'note))
160 (sessionid (jabber-xml-get-attribute query 'sessionid))
161 (status (jabber-xml-get-attribute query 'status))
162 (actions (car (jabber-xml-get-children query 'actions)))
163 xdata
164 (inhibit-read-only t))
165
166 (make-local-variable 'jabber-ahc-sessionid)
167 (setq jabber-ahc-sessionid sessionid)
168 (make-local-variable 'jabber-ahc-node)
169 (setq jabber-ahc-node node)
170 (make-local-variable 'jabber-buffer-connection)
171 (setq jabber-buffer-connection jc)
172
173 (dolist (x (jabber-xml-get-children query 'x))
174 (when (string= (jabber-xml-get-attribute x 'xmlns) "jabber:x:data")
175 (setq xdata x)))
176
177 (cond
178 ((string= status "executing")
179 (insert "Executing command\n\n"))
180 ((string= status "completed")
181 (insert "Command completed\n\n"))
182 ((string= status "canceled")
183 (insert "Command canceled\n\n")))
184
185 (dolist (note notes)
186 (let ((note-type (jabber-xml-get-attribute note 'type)))
187 (cond
188 ((string= note-type "warn")
189 (insert "Warning: "))
190 ((string= note-type "error")
191 (insert "Error: ")))
192 (insert (car (jabber-xml-node-children note)) "\n")))
193 (insert "\n")
194
195 (when xdata
196 (jabber-init-widget-buffer from)
197
198 (let ((formtype (jabber-xml-get-attribute xdata 'type)))
199 (if (string= formtype "result")
200 (jabber-render-xdata-search-results xdata)
201 (jabber-render-xdata-form xdata)
202
203 (when (string= status "executing")
204 (let ((button-titles
205 (cond
206 ((null actions)
207 '(complete cancel))
208 (t
209 (let ((children (mapcar #'jabber-xml-node-name (jabber-xml-node-children actions)))
210 (default-action (jabber-xml-get-attribute actions 'execute)))
211 (if (or (null default-action) (memq (intern default-action) children))
212 children
213 (cons (intern default-action) children)))))))
214 (dolist (button-title button-titles)
215 (widget-create 'push-button :notify `(lambda (&rest ignore) (jabber-ahc-submit (quote ,button-title))) (symbol-name button-title))
216 (widget-insert "\t")))
217 (widget-insert "\n"))))
218
219 (widget-setup)
220 (widget-minor-mode 1))))
221
222(defun jabber-ahc-submit (action)
223 "Submit Ad-Hoc Command."
224
225 (jabber-send-iq jabber-buffer-connection jabber-submit-to
226 "set"
227 `(command ((xmlns . "http://jabber.org/protocol/commands")
228 (sessionid . ,jabber-ahc-sessionid)
229 (node . ,jabber-ahc-node)
230 (action . ,(symbol-name action)))
231 ,(if (and (not (eq action 'cancel))
232 (eq jabber-form-type 'xdata))
233 (jabber-parse-xdata-form)))
234
235 #'jabber-process-data #'jabber-ahc-display
236 #'jabber-process-data "Command execution failed"))
237
238(provide 'jabber-ahc)
239
240;;; arch-tag: c0d5ed8c-50cb-44e1-8e0f-4058b79ee353