Mercurial > psgxs
annotate psgxs.js @ 11:0ed3c06c5191
Add an uncaught exceptions caughter to prevent the server from crashing.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 27 Aug 2010 01:09:09 +0200 |
parents | 44889cfb2f8c |
children | 9a6b8b3357c6 |
rev | line source |
---|---|
0 | 1 #!/usr/bin/env node |
2 | |
3 /* | |
4 * Copyright (C) 2010 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | |
5 * | |
6 * This file is part of PSĜS, a PubSub server written in JavaScript. | |
7 * | |
8 * PSĜS is free software: you can redistribute it and/or modify | |
9 * it under the terms of the GNU Affero General Public License as | |
10 * published by the Free Software Foundation, either version 3 of the | |
11 * License. | |
12 * | |
13 * PSĜS 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 Affero General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Affero General Public License | |
19 * along with PSĜS. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 var sys = require('sys'); | |
23 var xmpp = require('xmpp'); | |
24 var sha1 = require('sha1'); | |
25 require('./iso8601'); | |
26 var storage = require('./storage'); | |
27 var errors = require('./errors'); | |
28 var utils = require('./util'); | |
29 var toBareJID = utils.toBareJID; | |
30 var config = require('./configuration'); | |
31 var forms = require('./forms'); | |
32 var conn = new xmpp.Connection(); | |
33 | |
34 var service_configuration = config.service_configuration; | |
35 var componentJID = config.jid; | |
36 var componentPassword = config.password; | |
37 | |
38 conn.log = function (_, m) { sys.puts(m); }; | |
39 | |
40 function _(m, c) { | |
41 if (c) | |
42 sys.print('\033[1;'+c+'m'); | |
43 sys.print(sys.inspect(m, false, null)); | |
44 if (c) | |
45 sys.print('\033[0m'); | |
46 sys.puts(''); | |
47 }; | |
48 | |
11
0ed3c06c5191
Add an uncaught exceptions caughter to prevent the server from crashing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
10
diff
changeset
|
49 process.addListener('uncaughtException', function (err) { |
0ed3c06c5191
Add an uncaught exceptions caughter to prevent the server from crashing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
10
diff
changeset
|
50 console.log('\033[41;1mUncaught exception, this should never happen: ' + err + '.\033[0m'); |
0ed3c06c5191
Add an uncaught exceptions caughter to prevent the server from crashing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
10
diff
changeset
|
51 }); |
0ed3c06c5191
Add an uncaught exceptions caughter to prevent the server from crashing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
10
diff
changeset
|
52 |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
53 if (typeof xmpp.StanzaBuilder.cnode != 'function' || typeof xmpp.StanzaBuilder.prototype.cnode != 'function') { |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
54 xmpp.StanzaBuilder.prototype.cnode = function (stanza) |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
55 { |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
56 var parent = this; |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
57 parent.tags.push(stanza); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
58 parent.children.push(stanza); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
59 return this; |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
60 }; |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
61 } |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
62 |
0 | 63 function onIq(stanza) { |
64 var type = stanza.getAttribute('type'); | |
65 var from = stanza.getAttribute('to'); | |
66 var to = stanza.getAttribute('from'); | |
67 var id = stanza.getAttribute('id'); | |
68 | |
69 var response; | |
70 if (id) | |
71 response = xmpp.iq({to: to, from: from, type: 'result', id: id}); | |
72 else | |
73 response = xmpp.iq({to: to, from: from, type: 'result'}); | |
74 | |
75 if (type == 'get') { | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
76 |
9
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
77 // XEP-0092: Software Version |
0 | 78 if (stanza.getChild('query', 'jabber:iq:version')) { |
79 var query = xmpp.stanza('query', {xmlns: 'jabber:iq:version'}) | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
80 .s('name').t('PSĜS') |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
81 .s('version').t(config.version) |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
82 .s('os').t(config.os); |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
83 response.cnode(query); |
0 | 84 |
85 // SECTION 5.1 | |
86 } else if (stanza.getChild('query', 'http://jabber.org/protocol/disco#info')) { | |
87 var query = stanza.getChild('query', 'http://jabber.org/protocol/disco#info'); | |
88 var nodeID = query.getAttribute('node'); | |
89 | |
90 // SECTION 5.3 | |
91 if (nodeID && nodeID != '') { | |
92 if (!storage.existsNode(nodeID)) | |
93 return makeError(response, errors.node_does_not_exist.n); | |
94 | |
95 var conf = storage.getConfiguration(nodeID); | |
96 if (typeof conf == 'number') | |
97 return makeError(response, conf); | |
98 | |
99 var type = 'leaf' | |
100 if (conf['pubsub#node_type']) | |
101 type = conf['pubsub#node_type']; | |
102 | |
6 | 103 var q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#info', node: nodeID}) |
0 | 104 q.s('identity', {category: 'pubsub', type: type}); |
105 q.s('feature', {'var': 'http://jabber.org/protocol/pubsub'}); | |
106 | |
107 // SECTION 5.4 | |
108 if (config.enabled('meta-data')) { | |
4
4c93e76fa371
Ensure that the creator of a node is the default owner; don’t crash
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
109 var x = forms.build('result', 'node_metadata', storage.getMetadata(nodeID), true); |
0 | 110 if (x) |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
111 q.cnode(x); |
0 | 112 } |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
113 response.cnode(q); |
0 | 114 |
115 // SECTION 5.1 | |
116 } else { | |
117 var q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#info'}) | |
118 .s('identity', {category: 'pubsub', type: 'service', name: 'PubSub JavaScript Server'}) | |
119 .s('feature', {'var': 'http://jabber.org/protocol/disco#info'}) | |
120 .s('feature', {'var': 'http://jabber.org/protocol/disco#items'}) | |
121 .s('feature', {'var': 'http://jabber.org/protocol/pubsub'}) | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
122 .s('feature', {'var': 'jabber:iq:version'}) |
9
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
123 .s('feature', {'var': 'http://jabber.org/protocol/commands'}); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
124 |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
125 for (var i in config.activated) |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
126 if (typeof i == 'string') |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
127 q.s('feature', {'var': 'http://jabber.org/protocol/pubsub#' + config.activated[i]}); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
128 |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
129 response.cnode(q); |
0 | 130 } |
131 | |
132 // SECTION 5.2 | |
133 } else if (stanza.getChild('query', 'http://jabber.org/protocol/disco#items')) { | |
134 var query = stanza.getChild('query', 'http://jabber.org/protocol/disco#items'); | |
135 var q; | |
136 var children; | |
137 var nodeID = query.getAttribute('node'); | |
138 if (nodeID && nodeID != '') { | |
9
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
139 if (nodeID == 'http://jabber.org/protocol/commands') { |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
140 // XEP-0050: Ad-Hoc Commands |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
141 |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
142 q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#items', node: nodeID}) |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
143 .s('item', {jid: componentJID, node: 'ping', name: 'Ping'}) |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
144 .s('item', {jid: componentJID, node: 'reload', name: 'Reload'}); |
0 | 145 |
9
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
146 response.cnode(q); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
147 return conn.send(response); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
148 } else { |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
149 if (!storage.existsNode(nodeID)) |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
150 return makeError(response, errors.node_does_not_exist.n); |
0 | 151 |
9
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
152 q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#items', node: nodeID}); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
153 |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
154 children = storage.getChildren(nodeID); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
155 if (typeof children == 'number') |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
156 return makeError(response, children); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
157 } |
0 | 158 } else { |
159 q = xmpp.stanza('query', {xmlns: 'http://jabber.org/protocol/disco#items'}); | |
160 | |
161 children = storage.getChildren(); | |
162 if (typeof children == 'number') | |
163 return makeError(response, children); | |
164 } | |
165 | |
166 for (var i in children) { | |
167 var attr = {jid: componentJID}; | |
168 if (children[i] == 'node') { | |
169 if (config.enabled('meta-data')) { | |
170 var metadata = storage.getMetadata(i); | |
171 if (metadata['pubsub#title']) | |
172 attr.name = metadata['pubsub#title']; | |
173 } | |
174 attr.node = i; | |
175 | |
176 // SECTION 5.5 | |
177 } else | |
178 attr.name = i; | |
179 | |
180 q.s('item', attr); | |
181 } | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
182 response.cnode(q); |
0 | 183 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub')) { |
184 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub'); | |
185 | |
186 // SECTION 5.6 | |
187 if (pubsub.getChild('subscriptions')) { | |
188 if (!config.enabled('retrieve-subscriptions')) | |
189 return makeError(response, errors.subscriptions_retrieval_not_supported.n); | |
190 | |
191 var subscriptions = pubsub.getChild('subscriptions'); | |
192 var subs; | |
193 | |
194 var nodeID = subscriptions.getAttribute('node'); | |
195 if (nodeID && nodeID != '') { | |
196 if (!storage.existsNode(nodeID)) | |
197 return makeError(response, errors.node_does_not_exist.n); | |
198 subs = storage.getSubscription(toBareJID(to), node); | |
199 } else | |
200 subs = storage.getSubscription(toBareJID(to)); | |
201 | |
202 var s = xmpp.stanza('subscriptions'); | |
203 for (i in subs) | |
204 s.s('subscription', {node: i, jid: to, subscription: subs[i].type, subid: subs[i].subid}); | |
205 | |
206 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
207 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
208 response.cnode(p); |
0 | 209 |
210 // SECTION 5.7 | |
211 } else if (pubsub.getChild('affiliations')) { | |
212 if (!config.enabled('retrieve-affiliations')) | |
213 return makeError(response, errors.affiliations_retrieval_not_supported.n); | |
214 | |
215 var affiliations = pubsub.getChild('affiliations'); | |
216 var nodeID = affiliations.getAttribute('node'); | |
217 var affils; | |
218 if (nodeID && nodeID != '') { | |
219 if (!storage.existsNode(nodeID)) | |
220 return makeError(response, errors.node_does_not_exist.n); | |
6 | 221 affils = {}; |
222 affils[nodeID] = storage.getAffiliation(toBareJID(to), nodeID); | |
0 | 223 } else |
224 affils = storage.getAffiliationsFromJID(toBareJID(to)); | |
6 | 225 |
0 | 226 var s = xmpp.stanza('affiliations'); |
227 for (i in affils) | |
228 s.s('affiliation', {node: i, affiliation: affils[i]}); | |
6 | 229 |
0 | 230 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}); |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
231 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
232 response.cnode(p); |
0 | 233 |
234 // SECTION 6.3.2 | |
235 } else if (pubsub.getChild('options')) { | |
236 if (!config.enabled('subscription-options')) | |
237 return makeError(response, errors.sub.configure.subscription_options_not_supported.n); | |
238 | |
239 var options = pubsub.getChild('options'); | |
240 | |
241 var nodeID = options.getAttribute('node'); | |
242 if (!nodeID || nodeID == '') | |
243 return makeError(response, errors.nodeid_required.n); | |
244 if (!storage.existsNode(nodeID)) | |
245 return makeError(response, errors.node_does_not_exist.n); | |
246 | |
247 var jid = options.getAttribute('jid'); | |
248 if (!jid) | |
249 return makeError(response, errors.sub.configure.subscriber_jid_required.n); | |
250 if (toBareJID(jid) != toBareJID(to)) | |
251 return makeError(response, errors.sub.configure.insufficient_privileges.n); | |
252 | |
253 var subs = storage.getSubscription(jid, nodeID); | |
254 if (subs == {}) | |
255 return makeError(response, errors.sub.configure.no_such_subscriber.n); | |
256 | |
257 var s = xmpp.stanza('options', {node: nodeID, jid: jid}); | |
258 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}); | |
259 var form = forms.build('form', 'subscribe_options', subs.options, true); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
260 s.cnode(form); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
261 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
262 response.cnode(p); |
0 | 263 |
264 // SECTION 6.4 | |
265 } else if (pubsub.getChild('default')) { | |
266 if (!config.enabled('retrieve-default-sub')) | |
267 return makeError(response, errors.sub.default_options.default_subscription_configuration_retrieval_not_supported.n); | |
268 | |
269 var def = pubsub.getChild('default'); | |
270 | |
271 var nodeID = def.getAttribute('node'); | |
272 if (nodeID && !storage.existsNode(nodeID)) | |
273 return makeError(response, errors.node_does_not_exist.n); | |
274 | |
275 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}); | |
276 var s; | |
277 if (nodeID) | |
278 s = xmpp.stanza('default', {node: nodeID}); | |
279 else | |
280 s = xmpp.stanza('default'); | |
281 | |
282 var form = forms.build('form', 'subscribe_options', 'default', false); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
283 s.cnode(form); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
284 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
285 response.cnode(p); |
0 | 286 |
287 // SECTION 6.5 | |
288 } else if (pubsub.getChild('items')) { | |
289 if (!config.enabled('retrieve-items')) | |
290 return makeError(response, errors.sub.default_options.node_configuration_not_supported.n); | |
291 | |
292 var items = pubsub.getChild('items'); | |
293 | |
294 var nodeID = items.getAttribute('node'); | |
295 if (!nodeID || nodeID == '') | |
296 return makeError(response, errors.nodeid_required.n); | |
297 if (!storage.existsNode(nodeID)) | |
298 return makeError(response, errors.node_does_not_exist.n); | |
299 | |
6 | 300 var configuration = storage.getConfiguration(nodeID); |
301 if (configuration['pubsub#access_model'] == 'whitelist') { | |
302 var affil = storage.getAffiliation(toBareJID(to), nodeID); | |
303 if (affil != 'super-owner' && affil != 'owner' && affil != 'publisher' && affil != 'member') | |
304 return makeError(response, errors.pub.publish.insufficient_privileges.n); | |
305 } | |
0 | 306 |
307 var item = []; | |
308 for (var i=0; i<items.children.length; i++) { | |
309 var j = items.children[i]; | |
310 if (j.name == 'item' && j.attr['id'] && j.attr['id'] != '') | |
311 item.push(j.attr['id']); | |
312 } | |
313 | |
314 var max_items = items.getAttribute('max_items'); | |
315 if (max_items) | |
316 max_items = Number (max_items); | |
317 | |
318 if (item.length) { | |
319 var s = xmpp.stanza('items', {node: nodeID}); | |
320 | |
321 for (var i=0; i<item.length; i++) { | |
322 var j = storage.getItem(nodeID, item[i]); | |
323 if (typeof j == 'number') | |
324 return makeError(response, j); | |
10
44889cfb2f8c
Fix getItem method.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
9
diff
changeset
|
325 if (j == errors.success) |
44889cfb2f8c
Fix getItem method.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
9
diff
changeset
|
326 continue; |
0 | 327 |
328 var k = xmpp.stanza('item', {id: item[i]}) | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
329 k.cnode(j); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
330 s.cnode(k); |
0 | 331 } |
332 } else { | |
333 var s = xmpp.stanza('items', {node: nodeID}); | |
334 | |
335 var j; | |
336 if (max_items) | |
337 j = storage.getLastItem(nodeID, max_items); | |
338 else | |
339 j = storage.getItems(nodeID); | |
340 if (typeof j == 'number') | |
341 return makeError(response, j); | |
342 | |
343 var k = 0; | |
344 for (var i in j) { | |
345 var contentItem = xmpp.stanza('item', {id: i}).t(j[i].content); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
346 s.cnode(contentItem); |
0 | 347 } |
348 } | |
349 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
350 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
351 response.cnode(p); |
0 | 352 } else |
353 return makeError(response, errors.feature_not_implemented.n); | |
354 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner')) { | |
355 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner'); | |
356 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
357 // SECTION 8.2 |
0 | 358 if (pubsub.getChild('configure')) { |
359 if (!config.enabled('config-node')) | |
360 return makeError(response, errors.owner.configure.node_configuration_not_supported.n); | |
361 | |
362 var nodeID = pubsub.getChild('configure').getAttribute('node'); | |
363 if (!nodeID || nodeID == '') | |
364 return makeError(response, errors.nodeid_required.n); | |
365 if (!storage.existsNode(nodeID)) | |
366 return makeError(response, errors.node_does_not_exist.n); | |
367 | |
368 var affil = storage.getAffiliation(toBareJID(to), nodeID); | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
369 if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only') |
0 | 370 return makeError(response, errors.pub.publish.insufficient_privileges.n); |
371 | |
372 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); | |
373 var s = xmpp.stanza('configure', {node: nodeID}); | |
374 var form = forms.build('form', 'node_config', 'default', true); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
375 s.cnode(form); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
376 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
377 response.cnode(p); |
0 | 378 |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
379 // SECTION 8.3 |
0 | 380 } else if (pubsub.getChild('default')) { |
381 if (!config.enabled('config-node')) | |
382 return makeError(response, errors.owner.default_options.node_configuration_not_supported.n); | |
383 | |
384 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); | |
385 var s = xmpp.stanza('default'); | |
386 var form = forms.build('node_config', service_configuration.node_config, null, true); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
387 s.cnode(form); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
388 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
389 response.cnode(p); |
0 | 390 |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
391 // SECTION 8.8 |
0 | 392 } else if (pubsub.getChild('subscriptions')) { |
393 if (!config.enabled('manage-subscriptions')) | |
394 return makeError(response, errors.owner.manage_subscriptions.not_supported.n); | |
395 | |
396 var subscriptions = pubsub.getChild('subscriptions'); | |
397 | |
398 var nodeID = subscriptions.getAttribute('node'); | |
399 if (!nodeID || nodeID == '') | |
400 return makeError(response, errors.nodeid_required.n); | |
401 if (!storage.existsNode(nodeID)) | |
402 return makeError(response, errors.node_does_not_exist.n); | |
403 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
404 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
405 if (affil != 'super-owner' && affil != 'owner') |
0 | 406 return makeError(response, errors.forbidden.n); |
407 | |
408 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); | |
409 var s = xmpp.stanza('subscriptions', {node: nodeID}); | |
410 | |
411 var subs = storage.getSubscriptionsFromNodeID(nodeID) | |
412 for (var jid in subs) | |
413 s.s('subscription', {jid: jid, subscription: subs[jid].type, subid: subs[jid].subid}) | |
414 | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
415 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
416 response.cnode(p); |
0 | 417 |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
418 // SECTION 8.9 |
0 | 419 } else if (pubsub.getChild('affiliations')) { |
420 if (!config.enabled('modify-affiliations')) | |
421 return makeError(response, errors.owner.manage_affiliations.not_supported.n); | |
422 | |
423 var affiliations = pubsub.getChild('affiliations'); | |
424 | |
425 var nodeID = affiliations.getAttribute('node'); | |
426 if (!nodeID || nodeID == '') | |
427 return makeError(response, errors.nodeid_required.n); | |
428 if (!storage.existsNode(nodeID)) | |
429 return makeError(response, errors.node_does_not_exist.n); | |
430 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
431 var affils = storage.getAffiliationsFromNodeID(nodeID); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
432 var affil = affils[toBareJID(to)]; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
433 if (affil != 'super-owner' && affil != 'owner') |
0 | 434 return makeError(response, errors.owner.manage_affiliations.retrieve_list.entity_is_not_an_owner.n); |
435 | |
436 var p = xmpp.stanza('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}); | |
437 var s = xmpp.stanza('affiliations', {node: nodeID}); | |
438 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
439 for (var jid in affils) |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
440 s.s('affiliation', {jid: jid, affiliation: affils[jid]}) |
0 | 441 |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
442 p.cnode(s); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
443 response.cnode(p); |
0 | 444 } else |
445 return makeError(response, errors.feature_not_implemented.n); | |
446 } else | |
447 return makeError(response, errors.feature_not_implemented.n); | |
448 } else if (type == 'set') { | |
9
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
449 if (stanza.getChild('command', 'http://jabber.org/protocol/commands')) { |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
450 // XEP-0050: Ad-Hoc Commands |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
451 var command = stanza.getChild('command', 'http://jabber.org/protocol/commands'); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
452 |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
453 var action = command.getAttribute('action'); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
454 if (action != 'execute') |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
455 return makeError(response, errors.bad_request.n); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
456 |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
457 var node = command.getAttribute('node'); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
458 if (node == 'ping') { |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
459 var cmd = xmpp.stanza('command', {xmlns: 'http://jabber.org/protocol/commands', |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
460 // sessionid: 'list:20020923T213616Z-700', |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
461 node: node, |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
462 'status': 'completed'}) |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
463 .c('note', {type: 'info'}).t('pong'); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
464 response.cnode(cmd); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
465 } else if (node == 'reload') { |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
466 storage.load(); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
467 response.c('command', {xmlns: 'http://jabber.org/protocol/commands', |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
468 node: node, |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
469 'status': 'completed'}) |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
470 .c('note', {type: 'info'}).t('The server has correctly reloaded.'); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
471 } else |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
472 return makeError(response, errors.bad_request.n); |
a6429f48e403
First implementation of XEP-0050 (ad-hoc commands).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8
diff
changeset
|
473 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub')) { |
0 | 474 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub'); |
475 | |
476 // SECTION 6.1 | |
477 if (pubsub.getChild('subscribe')) { | |
478 if (!config.enabled('subscribe')) | |
479 return makeError(response, errors.sub.subscribe.not_supported.n); | |
480 | |
481 var subscribe = pubsub.getChild('subscribe'); | |
482 | |
483 var nodeID = subscribe.getAttribute('node'); | |
484 if (!nodeID || nodeID == '') | |
485 return makeError(response, errors.nodeid_required.n); | |
486 if (!storage.existsNode(nodeID)) | |
487 return makeError(response, errors.node_does_not_exist.n); | |
488 | |
489 var configuration = storage.getConfiguration(nodeID); | |
490 if (!configuration['pubsub#subscribe']) | |
491 return makeError(response, errors.sub.subscribe.not_supported.n); | |
492 | |
493 var affil = storage.getAffiliation(toBareJID(to), nodeID); | |
494 if (affil == 'publish-only' || affil == 'outcast') | |
495 return makeError(response, errors.pub.publish.insufficient_privileges.n); | |
496 | |
497 var jid = subscribe.getAttribute('jid'); | |
498 if (!jid || toBareJID(jid) != toBareJID(to)) | |
499 return makeError(response, errors.sub.subscribe.jids_do_not_match.n); | |
500 | |
501 // SECTION 6.3.7 | |
502 var options = pubsub.getChild('options'); | |
503 if (options && config.enabled('subscription-options')) { | |
504 if (options.getAttribute('node') || options.getAttribute('jid')) | |
505 return makeError(response, errors.bad_request.n); | |
506 | |
507 var x = options.getChild('x', 'jabber:x:data'); | |
508 if (!x || x.getAttribute('type') != 'submit') | |
509 return makeError(response, errors.bad_request.n); | |
510 | |
511 var form = forms.parse(x, true); | |
512 if (typeof form == 'number') | |
513 return makeError(response, form); | |
514 | |
515 var conf = form; | |
516 } | |
517 | |
518 var subID; | |
519 if (configuration['pubsub#access_model'] == 'open') { | |
520 subID = storage.subscribe(nodeID, jid, 'subscribe', conf); | |
521 if (typeof subID == 'number') | |
522 return makeError(response, subID); | |
523 } else if (configuration['pubsub#access_model'] == 'authorize') { | |
524 subID = storage.subscribe(nodeID, jid, 'pending', conf); | |
525 if (typeof subID == 'number') | |
526 return makeError(response, subID); | |
527 } else if (configuration['pubsub#access_model'] == 'whitelist') { | |
528 var affil = storage.getAffiliation(jid, nodeID); | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
529 if (affil != 'super-owner' && affil != 'owner' && affil != 'publisher' && affil != 'member') |
0 | 530 return makeError(response, errors.sub.subscribe.not_on_whitelist.n); |
531 | |
532 subID = storage.subscribe(nodeID, jid, conf); | |
533 if (typeof subID == 'number') | |
534 return makeError(response, subID); | |
535 } | |
536 | |
537 response.c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}) | |
538 .c('subscription', {node: nodeID, jid: jid, subid: subID.subid, subscription: subID.type}); | |
539 | |
540 if (conf) | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
541 response.cnode(options); |
0 | 542 |
543 if (config.enabled('get-pending')) { | |
544 var affiliates = storage.getAffiliationsFromNodeID(nodeID); | |
545 var form = forms.build('form', 'subscribe_authorization', {allow: false, node: nodeID, subscriber_jid: jid}, true); //168 | |
546 for (var i in affiliates) { | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
547 if (affiliates[i] == 'super-owner' || affiliates[i] == 'owner') { |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
548 var message = xmpp.message({to: i}).cnode(form); |
0 | 549 conn.send(message); |
550 } | |
551 } | |
552 } | |
553 | |
554 if (config.enabled('last-published')) { | |
555 var last = storage.getLastItem(nodeID); | |
556 if (typeof last != 'number') { | |
557 var item = storage.getItem(nodeID, last); | |
558 if (typeof item != 'number') { | |
559 var attr = {}; | |
560 attr[last] = {content: item}; | |
561 sendNotifs(jid, 'items', nodeID, attr); | |
562 } | |
563 } | |
564 } | |
565 | |
566 // SECTION 6.2 | |
567 } else if (pubsub.getChild('unsubscribe')) { | |
568 if (!config.enabled('subscribe')) | |
569 return makeError(response, errors.sub.subscribe.not_supported.n); | |
570 | |
571 var unsubscribe = pubsub.getChild('unsubscribe'); | |
572 var nodeID = unsubscribe.getAttribute('node'); | |
573 if (!nodeID || nodeID == '') | |
574 return makeError(response, errors.nodeid_required.n); | |
575 if (!storage.existsNode(nodeID)) | |
576 return makeError(response, errors.node_does_not_exist.n); | |
577 | |
578 var jid = unsubscribe.getAttribute('jid'); | |
579 if (!jid || toBareJID(jid) != toBareJID(to)) | |
580 return makeError(response, errors.sub.unsubscribe.insufficient_privileges.n); | |
581 | |
582 var subID = storage.subscribe(nodeID, jid, 'none'); | |
583 if (typeof subID == 'number') | |
584 return makeError(response, subID); | |
585 | |
586 // SECTIONS 6.3.5 | |
587 } else if (pubsub.getChild('options')) { | |
588 if (!config.enabled('subscription-options')) | |
589 return makeError(response, errors.sub.subscribe.not_supported.n); | |
590 | |
591 var options = pubsub.getChild('options'); | |
592 | |
593 var nodeID = unsubscribe.getAttribute('node'); | |
594 if (!nodeID || nodeID == '') | |
595 return makeError(response, errors.nodeid_required.n); | |
596 if (!storage.existsNode(nodeID)) | |
597 return makeError(response, errors.node_does_not_exist.n); | |
598 | |
599 var jid = unsubscribe.getAttribute('jid'); | |
600 if (!jid || toBareJID(jid) != toBareJID(to)) | |
601 return makeError(response, errors.sub.unsubscribe.insufficient_privileges.n); | |
602 | |
603 var x = options.getChild('x', 'jabber:x:data'); | |
604 if (!x || x.getAttribute(type) != 'submit') | |
605 return makeError(response, errors.bad_request); | |
606 | |
607 var form = forms.parse(x, true); | |
608 if (typeof form == 'number') | |
609 return makeError(response, form); | |
610 | |
611 var set = storage.configureSubscription(nodeID, jid, form); | |
612 if (typeof form == 'number') | |
613 return makeError(response, form); | |
614 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
615 // SECTION 7.1 |
0 | 616 } else if (pubsub.getChild('publish')) { |
617 if (!config.enabled('publish')) | |
618 return makeError(response, errors.pub.publish.item_publication_not_supported.n); | |
619 | |
620 var publish = pubsub.getChild('publish'); | |
621 var nodeID = publish.getAttribute('node'); | |
622 if (!nodeID || nodeID == '') | |
623 return makeError(response, errors.nodeid_required.n); | |
624 | |
6 | 625 var autocreate = false; |
626 if (!storage.existsNode(nodeID)) { | |
627 if (config.enabled('auto-create')) | |
628 autocreate = true; | |
629 else | |
630 return makeError(response, errors.node_does_not_exist.n); | |
631 } | |
632 | |
0 | 633 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
6 | 634 if (typeof affil == 'number' && affil != errors.node_does_not_exist.n) |
0 | 635 return makeError(response, affil); |
6 | 636 if (!autocreate && affil != 'super-owner' && affil != 'owner' && affil != 'publisher' && affil != 'publish-only') |
0 | 637 return makeError(response, errors.forbidden.n); |
638 | |
639 var item = publish.getChild('item'); | |
640 var itemID = item.getAttribute('id'); | |
641 if (!config.enabled('item-ids') && itemID) | |
642 return makeError(response, errors.itemid_required.n); | |
643 itemID = itemID? itemID: utils.makeRandomId(); | |
644 | |
645 if (item.tags.length != 1) | |
646 return makeError(response, errors.pub.publish.bad_payload.n); | |
647 | |
648 var conf = storage.getConfiguration(nodeID); | |
649 var publishOptions = pubsub.getChild('publish-options'); | |
650 if (publishOptions && config.enabled('publish-options')) { | |
651 var x = publishOptions.getChild('x', 'jabber:x:data'); | |
652 if (!x || x.getAttribute('type') != 'submit') | |
653 return makeError(response, errors.bad_request.n); | |
654 | |
655 var form = forms.parse(x, true); | |
656 if (form.access_model != conf['pubsub#access_model'] && !autocreate) | |
657 return makeError(response, errors.pub.configuration.precondition.n); | |
658 } | |
659 | |
660 if (!config.enabled('persistent-items')) { | |
661 var notifs = storage.purgeNode(nodeID); | |
662 if (typeof notifs == 'number') | |
663 return makeError(response, r); | |
664 } | |
665 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
666 if (autocreate) { |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
667 if (!form) |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
668 form = {}; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
669 form['pubsub#creator'] = toBareJID(to); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
670 |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
671 var r = storage.createNode(nodeID, form); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
672 if (typeof r == 'number') |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
673 return makeError(response, r); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
674 } |
0 | 675 |
676 var content = item.getChild(); | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
677 |
0 | 678 subscribers = storage.setItem(nodeID, itemID, content); |
679 if (typeof subscribers == 'number') | |
680 return makeError(response, subscribers); | |
681 | |
682 var attrs = {}; | |
683 if (content) | |
684 attrs[itemID] = {content: content}; | |
685 else | |
686 attrs[itemID] = {}; | |
687 sendNotifs(subscribers, 'items', nodeID, attrs); | |
688 | |
689 response.c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}) | |
690 .c('publish', {node: nodeID}) | |
691 .c('item', {id: itemID}); | |
692 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
693 // SECTION 7.2 |
0 | 694 } else if (pubsub.getChild('retract')) { |
695 if (!config.enabled('retract-items')) | |
696 return makeError(response, errors.pub.retract.item_deletion_not_supported.n); | |
697 | |
698 var retract = pubsub.getChild('retract'); | |
699 | |
700 var nodeID = retract.getAttribute('node'); | |
701 if (!nodeID || nodeID == '') | |
702 return makeError(response, errors.nodeid_required.n); | |
703 if (!storage.existsNode(nodeID)) | |
704 return makeError(response, errors.node_does_not_exist.n); | |
705 | |
706 var item = retract.getChild('item'); | |
707 if (!item) | |
708 return makeError(response, errors.pub.retract.item_or_itemid_required.n); | |
709 | |
710 var itemID = item.getAttribute('id') | |
711 if (!itemID || itemID == '') | |
712 return makeError(response, errors.pub.retract.item_or_itemid_required.n); | |
713 | |
6 | 714 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
715 if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only') | |
716 return makeError(response, errors.forbidden.n); | |
717 | |
0 | 718 var subscribers = storage.deleteItem(nodeID, itemID); |
719 if (typeof subscribers == 'number') | |
720 return makeError(response, subscribers); | |
721 | |
722 var attrs = {}; | |
723 attrs[itemID] = {}; | |
724 sendNotifs(subscribers, 'items', nodeID, attrs, 'retract') | |
725 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
726 // SECTION 8.1 |
0 | 727 } else if (pubsub.getChild('create')) { |
728 if (!config.enabled('create-nodes')) | |
729 return makeError(response, errors.owner.create.node_creation_not_supported.n); | |
730 | |
731 var instant = false; | |
732 | |
733 var nodeID = pubsub.getChild('create').getAttribute('node'); | |
734 if (!nodeID || nodeID == '') { | |
4
4c93e76fa371
Ensure that the creator of a node is the default owner; don’t crash
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
735 if (!config.enabled('instant-nodes')) |
0 | 736 return makeError(response, errors.owner.create.instant_nodes_not_supported.n); |
737 nodeID = utils.makeRandomId(); | |
738 instant = true; | |
739 } | |
740 if (storage.existsNode(nodeID)) | |
741 return makeError(response, errors.nodeid_already_exists.n); | |
742 | |
2
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
743 var bare = toBareJID(to); |
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
744 var right = false; |
7
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
745 |
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
746 // Check for super-owner |
2
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
747 for (var i in config.owner) |
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
748 if (config.owner[i] == bare) |
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
749 right = true; |
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
750 |
7
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
751 // Check for authorized user |
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
752 for (var i in config.allowCreateNode) |
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
753 if (config.allowCreateNode[i].exec(bare)) |
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
754 right = true; |
781ac4f1e304
Allow others JIDs than super-owners to create nodes.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
6
diff
changeset
|
755 |
2
d3ae2f8b685d
Make create node working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
1
diff
changeset
|
756 if (!right) |
0 | 757 return makeError(response, errors.forbidden.n); |
758 | |
759 var configure = pubsub.getChild('configure'); | |
760 if (configure && config.enabled('create-and-configure')) { | |
761 if (!config.enabled('config-node')) | |
762 return makeError(response, errors.owner.configure.node_configuration_not_supported.n); | |
763 | |
764 if (configure.getAttribute('node')) | |
765 return makeError(response, errors.bad_request.n); | |
766 | |
767 var x = configure.getChild('x', 'jabber:x:data'); | |
768 if (!x || x.getAttribute('type') != 'submit') | |
769 return makeError(response, errors.bad_request.n); | |
770 | |
771 var form = forms.parse(x, true); | |
772 if (typeof form == 'number') | |
773 return makeError(response, form); | |
774 | |
775 var conf = form; | |
776 } | |
777 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
778 if (!conf) |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
779 conf = {}; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
780 conf['pubsub#creator'] = toBareJID(to); |
0 | 781 var r = storage.createNode(nodeID, conf); |
782 if (typeof r == 'number') | |
783 return makeError(response, r); | |
784 | |
785 if (instant) | |
786 response.c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub'}) | |
787 .c('create', {node: nodeID}); | |
788 } else | |
789 return makeError(response, errors.feature_not_implemented.n); | |
790 } else if (stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner')) { | |
791 var pubsub = stanza.getChild('pubsub', 'http://jabber.org/protocol/pubsub#owner'); | |
792 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
793 // SECTION 8.2.4 |
0 | 794 if (pubsub.getChild('configure')) { |
795 if (!config.enabled('config-node')) | |
796 return makeError(response, errors.owner.configure.node_configuration_not_supported.n); | |
797 | |
798 var nodeID = configure.getAttribute('node'); | |
799 if (!nodeID) | |
800 return makeError(response, errors.nodeid_required.n); | |
801 if (!storage.existsNode(nodeID)) | |
802 return makeError(response, errors.node_does_not_exist.n); | |
803 | |
804 var affil = storage.getAffiliation(toBareJID(to), nodeID); | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
805 if (affil != 'super-owner' && affil != 'owner' && affil != 'publish-only') |
0 | 806 return makeError(response, errors.forbidden.n); |
807 | |
808 var x = configure.getChild('x', 'jabber:x:data'); | |
809 if (!x || x.getAttribute(type) != 'submit') | |
810 return makeError(response, errors.bad_request.n); | |
811 | |
812 var form = forms.parse(x, true); | |
813 if (typeof form == 'number') | |
814 return makeError(response, form); | |
815 | |
816 var conf = form; | |
817 | |
818 var set = storage.configure(nodeID, conf); | |
819 if (typeof set == 'number') | |
820 return makeError(response, set); | |
821 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
822 // SECTION 8.4 |
0 | 823 } else if (pubsub.getChild('delete')) { |
824 if (!config.enabled('delete-nodes')) | |
825 return makeError(response, errors.feature_not_implemented.n); //XXX | |
826 | |
827 var del = pubsub.getChild('delete'); | |
828 | |
829 var nodeID = del.getAttribute('node'); | |
830 if (!nodeID) | |
831 return makeError(response, errors.nodeid_required.n); | |
832 if (!storage.existsNode(nodeID)) | |
833 return makeError(response, errors.node_does_not_exist.n); | |
834 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
835 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
836 if (affil != 'super-owner' && affil != 'owner') |
0 | 837 return makeError(response, errors.forbidden.n); |
838 | |
839 var notifs = storage.deleteNode(nodeID); | |
840 if (typeof notifs == 'number') | |
841 return makeError(response, r); | |
842 | |
843 sendNotifs(notifs, 'delete', nodeID); | |
844 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
845 // SECTION 8.5 |
0 | 846 } else if (pubsub.getChild('purge')) { |
847 if (!config.enabled('purge-nodes')) | |
848 return makeError(response, errors.owner.purge.node_purging_not_supported.n); //XXX | |
849 | |
850 var purge = pubsub.getChild('purge'); | |
851 | |
852 var nodeID = purge.getAttribute('node'); | |
853 if (!nodeID) | |
854 return makeError(response, errors.nodeid_required.n); | |
855 if (!storage.existsNode(nodeID)) | |
856 return makeError(response, errors.node_does_not_exist.n); | |
857 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
858 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
859 if (affil != 'super-owner' && affil != 'owner') |
0 | 860 return makeError(response, errors.forbidden.n); |
861 | |
862 if (!config.enabled('persistent-items')) //FIXME: autre condition, supporté par le node | |
863 return makeError(response, errors.owner.purge.node_does_not_persist_items.n); | |
864 | |
865 var notifs = storage.purgeNode(nodeID); | |
866 if (typeof notifs == 'number') | |
867 return makeError(response, r); | |
868 | |
869 sendNotifs(notifs, 'purge', nodeID); | |
870 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
871 // SECTION 8.8.2 |
0 | 872 } else if (pubsub.getChild('subscriptions')) { |
873 if (!config.enabled('manage-subscriptions')) | |
874 return makeError(response, errors.owner.manage_subscriptions.not_supported.n); //XXX | |
875 | |
876 var subscriptions = pubsub.getChild('subscriptions'); | |
877 | |
878 var nodeID = subscriptions.getAttribute('node'); | |
879 if (!nodeID) | |
880 return makeError(response, errors.nodeid_required.n); | |
881 if (!storage.existsNode(nodeID)) | |
882 return makeError(response, errors.node_does_not_exist.n); | |
883 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
884 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
885 if (affil != 'super-owner' && affil != 'owner') |
0 | 886 return makeError(response, errors.forbidden.n); |
887 | |
888 var e = false; | |
889 for (i in subscriptions.tags) { | |
890 var jid = subscriptions.tags[i].getAttribute('jid'); | |
891 var subscription = subscriptions.tags[i].getAttribute('subscription'); | |
892 | |
893 var set = storage.subscribe(nodeID, jid, subscription); | |
894 if (typeof set == 'number') | |
895 e = true; | |
896 else { | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
897 // SECTION 8.8.4 |
0 | 898 sendNotifs(jid, 'subscription', nodeID, {jid: jid, subscription: subscription}); |
899 subscriptions.tags.splice(i, 1); | |
900 } | |
901 } | |
902 | |
903 if (e) | |
904 return makeError(response, errors.owner.manage_subscriptions.modify.multiple_simultaneous_modifications.n, pubsub); | |
905 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
906 // SECTION 8.9.2 |
0 | 907 } else if (pubsub.getChild('affiliations')) { |
908 if (!config.enabled('modify-affiliations')) | |
909 return makeError(response, errors.owner.manage_affiliations.not_supported.n); //XXX | |
910 | |
911 var affiliations = pubsub.getChild('affiliations'); | |
912 | |
913 var nodeID = affiliations.getAttribute('node'); | |
914 if (!nodeID) | |
915 return makeError(response, errors.nodeid_required.n); | |
916 if (!storage.existsNode(nodeID)) | |
917 return makeError(response, errors.node_does_not_exist.n); | |
918 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
919 var affil = storage.getAffiliation(toBareJID(to), nodeID); |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
920 if (affil != 'super-owner' && affil != 'owner') |
0 | 921 return makeError(response, errors.forbidden.n); |
922 | |
923 var e = false; | |
924 for (i in affiliations.children) { | |
925 var jid = affiliations.children[i].getAttribute('jid'); | |
926 var affiliation = affiliations.children[i].getAttribute('affiliation'); | |
927 | |
928 var set = storage.setAffiliation(nodeID, jid, affiliation); | |
929 if (typeof set == 'number') | |
930 e = true; | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
931 else { |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
932 // SECTION 8.9.4 |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
933 sendNotifs(jid, 'affiliations', nodeID, {jid: jid, affiliation: affiliation}); |
0 | 934 affiliations.children.splice(i, 1); |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
935 } |
0 | 936 } |
937 | |
938 if (e) | |
939 return makeError(response, errors.owner.manage_affiliations.modify.multiple_simultaneous_modifications.n, pubsub); | |
940 } else | |
941 return makeError(response, errors.feature_not_implemented.n); | |
942 } else | |
943 return makeError(response, errors.feature_not_implemented.n); | |
944 } else | |
945 return makeError(response, errors.feature_not_implemented.n); | |
946 conn.send(response); | |
947 } | |
948 | |
949 function onMessage(stanza) { | |
950 var from = stanza.getAttribute('to'); | |
951 var to = stanza.getAttribute('from'); | |
952 var id = stanza.getAttribute('id'); | |
953 | |
954 var response; | |
955 if (id) | |
956 response = xmpp.message({to: to, from: from, id: id}); | |
957 else | |
958 response = xmpp.message({to: to, from: from}); | |
959 | |
960 var x = stanza.getChild('x', 'jabber:x:data'); | |
961 if (x) { | |
962 var form = forms.parse(x); | |
963 if (form.type == 'submit' && form.fields.FORM_TYPE.value == 'subscribe_authorization') { | |
964 if (form.fields.subid && form.fields.subid.value) | |
965 var subID = form.fields.subid.value; | |
966 if (form.fields.node && form.fields.node.value) | |
967 var nodeID = form.fields.node.value; | |
968 if (form.fields.subscriber_jid && form.fields.subscriber_jid.value) | |
969 var jid = form.fields.subscriber_jid.value; | |
970 if (form.fields.allow && form.fields.allow.value) | |
971 var allow = form.fields.allow.value; | |
972 | |
973 var type = allow? 'subscribed': 'none'; | |
974 var set = storage.subscribe(nodeID, jid, type) | |
975 //if (set.subid != subID) //TODO: support the multi-subscribe feature | |
976 sendNotifs(jid, 'subscription', nodeID, {jid: jid, subscription: type}); | |
977 } else | |
978 return makeError(response, errors.feature_not_implemented.n); | |
979 } else | |
980 return makeError(response, errors.feature_not_implemented.n); | |
981 conn.send(response) | |
982 } | |
983 | |
984 function onPresence(stanza) { | |
985 var from = stanza.getAttribute('to'); | |
986 var to = stanza.getAttribute('from'); | |
987 var id = stanza.getAttribute('id'); | |
988 | |
989 var response; | |
990 if (id) | |
991 response = xmpp.presence({to: to, from: from, id: id}); | |
992 else | |
993 response = xmpp.presence({to: to, from: from}); | |
994 | |
995 makeError(response, errors.feature_not_implemented.n); | |
996 } | |
997 | |
998 function makeError(response, errorNumber, payload) { | |
999 response.attr.type = 'error'; | |
1000 if (payload) | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1001 response.cnode(payload); |
0 | 1002 |
1003 var e = errors.reverse[errorNumber]; | |
1004 var error = xmpp.stanza('error', {type: e.type}); | |
1005 | |
1006 error.s(e.error, {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}) | |
1007 | |
1008 if (e.reason) { | |
1009 if (e.feature) | |
1010 error.s(e.reason, {xmlns: 'http://jabber.org/protocol/pubsub#errors', feature: e.feature}); | |
1011 else | |
1012 error.s(e.reason, {xmlns: 'http://jabber.org/protocol/pubsub#errors'}); | |
1013 } | |
1014 | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1015 response.cnode(error); |
0 | 1016 conn.send(response); |
1017 } | |
1018 | |
1019 function sendNotifs(notifs, type, nodeID, a1, a2) { | |
1020 var ev = xmpp.stanza('event', {xmlns: 'http://jabber.org/protocol/pubsub#event'}); | |
1021 | |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1022 if (type == 'affiliations') { |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1023 ev.attr.xmlns = 'http://jabber.org/protocol/pubsub'; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1024 |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1025 var args = {}; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1026 for (i in a1) { |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1027 var attr = a1[i]; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1028 if (i == 'affiliation') |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1029 args.affiliation = attr; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1030 else if (i == 'jid') |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1031 args.jid = attr; |
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1032 } |
3
80e607c0b39e
Make affiliation notifications working.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
2
diff
changeset
|
1033 var affiliations = xmpp.stanza('affiliations', {node: nodeID}) |
4
4c93e76fa371
Ensure that the creator of a node is the default owner; don’t crash
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
3
diff
changeset
|
1034 .c('affiliation', args); |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1035 ev.cnode(affiliations); |
1
c2954a9e5665
Add a super-owner that has power over all nodes; add support for
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
0
diff
changeset
|
1036 } else if (type == 'collection') { |
0 | 1037 var collection = xmpp.stanza('collection', {node: nodeID}); |
1038 if (a1 == 'associate') | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1039 collection.cnode('associate', {node: nodeID}); |
0 | 1040 else |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1041 collection.cnode('disassociate', {node: nodeID}); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1042 ev.cnode(collection); |
0 | 1043 } else if (type == 'configuration') { |
1044 if (!config.enabled('config-node')) { | |
1045 _('Error #4', 41) | |
1046 return; | |
1047 } | |
1048 | |
1049 var configuration = xmpp.stanza('configuration', {node: nodeID}); | |
1050 if (a1) { | |
1051 var x = forms.build('node_config', service_configuration.node_config, storage.getConfiguration(nodeID)); | |
1052 if (x) | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1053 configuration.cnode(x); //TODO: voir exemple 150 |
0 | 1054 } |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1055 ev.cnode(configuration); |
0 | 1056 } else if (type == 'delete') { |
1057 var del = xmpp.stanza('delete', {node: nodeID}); | |
1058 if (a1) | |
1059 del.c('redirect', {uri: a1}); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1060 ev.cnode(del); |
0 | 1061 } else if (type == 'items') { |
1062 var items = xmpp.stanza(type, {node: nodeID}); | |
1063 if (a2 == 'retract') | |
1064 for (var i in a1) | |
1065 items.s('retract', {id: i}); | |
1066 else { | |
1067 for (var i in a1) { | |
1068 var item = a1[i]; | |
1069 var args = {}; | |
1070 if (i != '') | |
1071 args.id = i; | |
1072 if (item.node) | |
1073 args.node = item.node; | |
1074 if (item.publisher) | |
1075 args.publisher = item.publisher; | |
1076 var it = xmpp.stanza('item', args); | |
1077 if (item.content) | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1078 it.cnode(item.content); |
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1079 items.cnode(it); |
0 | 1080 } |
1081 } | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1082 ev.cnode(items); |
0 | 1083 } else if (type == 'purge') { |
1084 ev.c('purge', {node: nodeID}); | |
1085 } else if (type == 'subscription') { | |
1086 if (!config.enabled('subscription-notifications')) | |
1087 return; | |
1088 | |
1089 var args = {node: nodeID}; | |
1090 for (i in a1) { | |
1091 var attr = a1[i]; | |
1092 if (i == 'subscription') { | |
1093 if (attr == 'none' || attr == 'pending' || attr == 'subscribed' || attr == 'unconfigured') | |
1094 args[i] = attr; | |
1095 else { | |
1096 _('Error #3', 41) | |
1097 return; | |
1098 } | |
1099 } else if (i == 'jid' || i == 'subid') | |
1100 args[i] = attr; | |
1101 else if (i == 'expiry') | |
1102 args[i] = attr.toString(); | |
1103 } | |
1104 if (!args.jid || args.jid == '') { | |
1105 _('Error #2', 41) | |
1106 return; | |
1107 } | |
1108 var sub = xmpp.stanza('subscription', args); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1109 ev.cnode(sub); |
0 | 1110 } else { |
1111 _('Error #1', 41) | |
1112 return; | |
1113 } | |
1114 | |
1115 var subs; | |
1116 if (typeof notifs == 'string') { | |
1117 subs = {}; | |
1118 subs[notifs] = storage.getSubscription(notifs, nodeID); | |
1119 } else | |
1120 subs = notifs; | |
1121 | |
1122 for (var i in subs) { | |
1123 var sub = subs[i]; | |
1124 | |
1125 if (sub.options) { | |
1126 if (typeof sub.options['pubsub#deliver'] != 'undefined' && !sub.options['pubsub#deliver']) | |
1127 continue; | |
1128 | |
1129 if (typeof sub.options['pubsub#digest'] != 'undefined' && sub.options['pubsub#digest']) { | |
1130 if (!sub.digest) | |
1131 sub.digest = []; | |
1132 sub.digest.push(ev) | |
1133 | |
1134 if (sub.digestTimeout) | |
1135 continue; | |
1136 | |
1137 var freq; | |
1138 if (typeof sub.options['pubsub#digest_frequency'] == 'undefined') | |
1139 freq = 0; | |
1140 else | |
1141 freq = parseInt(sub.options['pubsub#digest_frequency']); | |
1142 | |
1143 if (freq == 0) | |
1144 freq = 24*60*60*1000; | |
1145 | |
1146 setTimeout(sendDigest, freq, notifs[i], nodeID); | |
1147 sub.digestTimeout = true; | |
1148 continue; | |
1149 } | |
1150 } | |
1151 | |
1152 var message = xmpp.message({to: i, from: componentJID, id: conn.getUniqueId()}); | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1153 message.cnode(ev); |
0 | 1154 conn.send(message); |
1155 } | |
1156 } | |
1157 | |
1158 function sendDigest(jid, nodeID) { | |
1159 var sub = storage.getSubscription(jid, nodeID); | |
1160 if (sub.digestTimeout) | |
1161 sub.digestTimeout = false; | |
1162 | |
1163 var message = xmpp.message({to: jid, from: componentJID, id: conn.getUniqueId()}); | |
1164 for (var i in sub.digest) | |
8
efe8dbd34780
Rename cx method to cnode and define it if xmpp.js didn’t.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
7
diff
changeset
|
1165 message.cnode(sub.digest[i]); |
0 | 1166 conn.send(message); |
1167 } | |
1168 | |
1169 conn.connect(componentJID, componentPassword, function (status, condition) { | |
1170 if (status == xmpp.Status.CONNECTED) { | |
1171 conn.addHandler(onMessage, null, 'message', null, null, null); | |
1172 conn.addHandler(onIq, null, 'iq', null, null, null); | |
1173 conn.addHandler(onPresence, null, 'presence', null, null, null); | |
1174 | |
1175 if (process.argv.length >= 3) | |
1176 storage.load(process.argv[2]); | |
1177 else | |
1178 storage.load(); | |
1179 | |
1180 var stdin = process.openStdin(); | |
1181 stdin.setEncoding('utf8'); | |
1182 stdin.addListener('data', storage.debug); | |
1183 } else | |
1184 conn.log(xmpp.LogLevel.DEBUG, 'New connection status: ' + status + (condition? (' ('+condition+')'): '')); | |
1185 }); |