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