]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | ;; jabber-iq.el - infoquery functions -*- 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-core) | |
23 | (require 'jabber-util) | |
24 | (require 'jabber-keymap) | |
25 | ||
26 | (defvar *jabber-open-info-queries* nil | |
27 | "Alist of open query id and their callback functions.") | |
28 | ||
29 | (defvar jabber-iq-get-xmlns-alist nil | |
30 | "Mapping from XML namespace to handler for IQ GET requests.") | |
31 | ||
32 | (defvar jabber-iq-set-xmlns-alist nil | |
33 | "Mapping from XML namespace to handler for IQ SET requests.") | |
34 | ||
35 | (defvar jabber-browse-mode-map | |
36 | (let ((map (make-sparse-keymap))) | |
37 | (set-keymap-parent map jabber-common-keymap) | |
38 | (define-key map [mouse-2] 'jabber-popup-combined-menu) | |
39 | map)) | |
40 | ||
41 | (defcustom jabber-browse-mode-hook nil | |
42 | "Hook run when entering Browse mode." | |
43 | :group 'jabber | |
44 | :type 'hook) | |
45 | ||
46 | (defgroup jabber-browse nil "browse display options" | |
47 | :group 'jabber) | |
48 | ||
49 | (defcustom jabber-browse-buffer-format "*-jabber-browse:-%n-*" | |
50 | "The format specification for the name of browse buffers. | |
51 | ||
52 | These fields are available at this moment: | |
53 | ||
54 | %n JID to browse" | |
55 | :type 'string | |
56 | :group 'jabber-browse) | |
57 | ||
58 | (defun jabber-browse-mode () | |
59 | "Jabber browse mode. | |
60 | \\{jabber-browse-mode-map}" | |
61 | (kill-all-local-variables) | |
62 | (setq major-mode 'jabber-browse-mode | |
63 | mode-name "jabber-browse") | |
64 | (use-local-map jabber-browse-mode-map) | |
65 | (setq buffer-read-only t) | |
66 | (if (fboundp 'run-mode-hooks) | |
67 | (run-mode-hooks 'jabber-browse-mode-hook) | |
68 | (run-hooks 'jabber-browse-mode-hook))) | |
69 | ||
70 | (put 'jabber-browse-mode 'mode-class 'special) | |
71 | ||
72 | (add-to-list 'jabber-iq-chain 'jabber-process-iq) | |
73 | (defun jabber-process-iq (jc xml-data) | |
74 | "Process an incoming iq stanza. | |
75 | ||
76 | JC is the Jabber Connection. | |
77 | XML-DATA is the parsed tree data from the stream (stanzas) | |
78 | obtained from `xml-parse-region'." | |
79 | (let* ((id (jabber-xml-get-attribute xml-data 'id)) | |
80 | (type (jabber-xml-get-attribute xml-data 'type)) | |
81 | (from (jabber-xml-get-attribute xml-data 'from)) | |
82 | (query (jabber-iq-query xml-data)) | |
83 | (callback (assoc id *jabber-open-info-queries*))) | |
84 | (cond | |
85 | ;; if type is "result" or "error", this is a response to a query we sent. | |
86 | ((or (string= type "result") | |
87 | (string= type "error")) | |
88 | (let ((callback-cons (nth (cdr (assoc type '(("result" . 0) | |
89 | ("error" . 1)))) (cdr callback)))) | |
90 | (if (consp callback-cons) | |
91 | (funcall (car callback-cons) jc xml-data (cdr callback-cons)))) | |
92 | (setq *jabber-open-info-queries* (delq callback *jabber-open-info-queries*))) | |
93 | ||
94 | ;; if type is "get" or "set", correct action depends on namespace of request. | |
95 | ((and (listp query) | |
96 | (or (string= type "get") | |
97 | (string= type "set"))) | |
98 | (let* ((which-alist (eval (cdr (assoc type | |
99 | (list | |
100 | (cons "get" 'jabber-iq-get-xmlns-alist) | |
101 | (cons "set" 'jabber-iq-set-xmlns-alist)))))) | |
102 | (handler (cdr (assoc (jabber-xml-get-attribute query 'xmlns) which-alist)))) | |
103 | (if handler | |
104 | (condition-case error-var | |
105 | (funcall handler jc xml-data) | |
106 | (jabber-error | |
107 | (apply 'jabber-send-iq-error jc from id query (cdr error-var))) | |
108 | (error (jabber-send-iq-error jc from id query "wait" 'internal-server-error (error-message-string error-var)))) | |
109 | (jabber-send-iq-error jc from id query "cancel" 'feature-not-implemented))))))) | |
110 | ||
111 | (defun jabber-send-iq (jc to type query success-callback success-closure-data | |
112 | error-callback error-closure-data &optional result-id) | |
113 | "Send an iq stanza to the specified entity, and optionally set up a callback. | |
114 | JC is the Jabber connection. | |
115 | TO is the addressee. | |
116 | TYPE is one of \"get\", \"set\", \"result\" or \"error\". | |
117 | QUERY is a list containing the child of the iq node in the format | |
118 | `jabber-sexp2xml' accepts. | |
119 | SUCCESS-CALLBACK is the function to be called when a successful result arrives. | |
120 | SUCCESS-CLOSURE-DATA is an extra argument to SUCCESS-CALLBACK. | |
121 | ERROR-CALLBACK is the function to be called when an error arrives. | |
122 | ERROR-CLOSURE-DATA is an extra argument to ERROR-CALLBACK. | |
123 | RESULT-ID is the id to be used for a response to a received iq message. | |
124 | `jabber-report-success' and `jabber-process-data' are common callbacks. | |
125 | ||
126 | The callback functions are called like this: | |
127 | \(funcall CALLBACK JC XML-DATA CLOSURE-DATA) | |
128 | with XML-DATA being the IQ stanza received in response." | |
129 | (let ((id (or result-id (apply 'format "emacs-iq-%d.%d.%d" (current-time))))) | |
130 | (if (or success-callback error-callback) | |
131 | (setq *jabber-open-info-queries* (cons (list id | |
132 | (cons success-callback success-closure-data) | |
133 | (cons error-callback error-closure-data)) | |
134 | ||
135 | *jabber-open-info-queries*))) | |
136 | (jabber-send-sexp jc | |
137 | (list 'iq (append | |
138 | (if to (list (cons 'to to))) | |
139 | (list (cons 'type type)) | |
140 | (list (cons 'id id))) | |
141 | query)))) | |
142 | ||
143 | (defun jabber-send-iq-error (jc to id original-query error-type condition | |
144 | &optional text app-specific) | |
145 | "Send an error iq stanza in response to a previously sent iq stanza. | |
146 | Send an error iq stanza to the specified entity in response to a | |
147 | previously sent iq stanza. | |
148 | TO is the addressee. | |
149 | ID is the id of the iq stanza that caused the error. | |
150 | ORIGINAL-QUERY is the original query, which should be included in the | |
151 | error, or nil. | |
152 | ERROR-TYPE is one of \"cancel\", \"continue\", \"modify\", \"auth\" | |
153 | and \"wait\". | |
154 | CONDITION is a symbol denoting a defined XMPP condition. | |
155 | TEXT is a string to be sent in the error message, or nil for no text. | |
156 | APP-SPECIFIC is a list of extra XML tags. | |
157 | JC is the Jabber connection. | |
158 | ||
159 | See section 9.3 of XMPP Core." | |
160 | (jabber-send-sexp | |
161 | jc | |
162 | `(iq (,@(when to `((to . ,to))) | |
163 | (type . "error") | |
164 | (id . ,(or id ""))) | |
165 | ,original-query | |
166 | (error ((type . ,error-type)) | |
167 | (,condition ((xmlns . "urn:ietf:params:xml:ns:xmpp-stanzas"))) | |
168 | ,(if text | |
169 | `(text ((xmlns . "urn:ietf:params:xml:ns:xmpp-stanzas")) | |
170 | ,text)) | |
171 | ,@app-specific)))) | |
172 | ||
173 | (defun jabber-process-data (jc xml-data closure-data) | |
174 | "Process random results from various requests. | |
175 | ||
176 | JC is the Jabber connection. | |
177 | XML-DATA is the parsed tree data from the stream (stanzas) | |
178 | obtained from `xml-parse-region'." | |
179 | (let ((from (or (jabber-xml-get-attribute xml-data 'from) (plist-get (fsm-get-state-data jc) :server))) | |
180 | (xmlns (jabber-iq-xmlns xml-data)) | |
181 | (type (jabber-xml-get-attribute xml-data 'type))) | |
182 | (with-current-buffer (get-buffer-create (format-spec jabber-browse-buffer-format | |
183 | (list (cons ?n from)))) | |
184 | (if (not (eq major-mode 'jabber-browse-mode)) | |
185 | (jabber-browse-mode)) | |
186 | ||
187 | (setq buffer-read-only nil) | |
188 | (goto-char (point-max)) | |
189 | ||
190 | (insert (jabber-propertize from | |
191 | 'face 'jabber-title-large) "\n\n") | |
192 | ||
193 | ;; Put point at beginning of data | |
194 | (save-excursion | |
195 | ;; If closure-data is a function, call it. If it is a string, | |
196 | ;; output it along with a description of the error. For other | |
197 | ;; values (e.g. nil), just dump the XML. | |
198 | (cond | |
199 | ((functionp closure-data) | |
200 | (funcall closure-data jc xml-data)) | |
201 | ((stringp closure-data) | |
202 | (insert closure-data ": " (jabber-parse-error (jabber-iq-error xml-data)) "\n\n")) | |
203 | (t | |
204 | (insert (format "%S\n\n" xml-data)))) | |
205 | ||
206 | (dolist (hook '(jabber-info-message-hooks jabber-alert-info-message-hooks)) | |
207 | (run-hook-with-args hook 'browse (current-buffer) (funcall jabber-alert-info-message-function 'browse (current-buffer)))))))) | |
208 | ||
209 | (defun jabber-silent-process-data (jc xml-data closure-data) | |
210 | "Process random results from various requests to only alert hooks. | |
211 | ||
212 | JC is the Jabber connection. | |
213 | XML-DATA is the parsed tree data from the stream (stanzas) | |
214 | obtained from `xml-parse-region'." | |
215 | (let ((text (cond | |
216 | ((functionp closure-data) | |
217 | (funcall closure-data jc xml-data)) | |
218 | ((stringp closure-data) | |
219 | (concat closure-data ": " (jabber-parse-error (jabber-iq-error xml-data)))) | |
220 | (t | |
221 | (format "%S" xml-data))))) | |
222 | (dolist (hook '(jabber-info-message-hooks jabber-alert-info-message-hooks)) | |
223 | (run-hook-with-args hook 'browse (current-buffer) | |
224 | text)))) | |
225 | ||
226 | (provide 'jabber-iq) | |
227 | ||
228 | ;;; arch-tag: 5585dfa3-b59a-42ee-9292-803652c85e26 |