Comparison

plugins/mod_pubsub/pubsub.lib.lua @ 5626:8416d4619d80

mod_pubsub: Split out handlers into a module library
author Florian Zeitz <florob@babelmonkeys.de>
date Fri, 17 May 2013 18:33:32 +0200
child 5851:cdcfd93e2f43
comparison
equal deleted inserted replaced
5625:e67891ad18d6 5626:8416d4619d80
1 local st = require "util.stanza";
2 local uuid_generate = require "util.uuid".generate;
3
4 local xmlns_pubsub = "http://jabber.org/protocol/pubsub";
5 local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors";
6
7 local _M = {};
8
9 local handlers = {};
10 _M.handlers = handlers;
11
12 local pubsub_errors = {
13 ["conflict"] = { "cancel", "conflict" };
14 ["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" };
15 ["jid-required"] = { "modify", "bad-request", nil, "jid-required" };
16 ["nodeid-required"] = { "modify", "bad-request", nil, "nodeid-required" };
17 ["item-not-found"] = { "cancel", "item-not-found" };
18 ["not-subscribed"] = { "modify", "unexpected-request", nil, "not-subscribed" };
19 ["forbidden"] = { "cancel", "forbidden" };
20 };
21 local function pubsub_error_reply(stanza, error)
22 local e = pubsub_errors[error];
23 local reply = st.error_reply(stanza, unpack(e, 1, 3));
24 if e[4] then
25 reply:tag(e[4], { xmlns = xmlns_pubsub_errors }):up();
26 end
27 return reply;
28 end
29 _M.pubsub_error_reply = pubsub_error_reply;
30
31 function handlers.get_items(origin, stanza, items, service)
32 local node = items.attr.node;
33 local item = items:get_child("item");
34 local id = item and item.attr.id;
35
36 if not node then
37 return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
38 end
39 local ok, results = service:get_items(node, stanza.attr.from, id);
40 if not ok then
41 return origin.send(pubsub_error_reply(stanza, results));
42 end
43
44 local data = st.stanza("items", { node = node });
45 for _, entry in pairs(results) do
46 data:add_child(entry);
47 end
48 local reply;
49 if data then
50 reply = st.reply(stanza)
51 :tag("pubsub", { xmlns = xmlns_pubsub })
52 :add_child(data);
53 else
54 reply = pubsub_error_reply(stanza, "item-not-found");
55 end
56 return origin.send(reply);
57 end
58
59 function handlers.get_subscriptions(origin, stanza, subscriptions, service)
60 local node = subscriptions.attr.node;
61 local ok, ret = service:get_subscriptions(node, stanza.attr.from, stanza.attr.from);
62 if not ok then
63 return origin.send(pubsub_error_reply(stanza, ret));
64 end
65 local reply = st.reply(stanza)
66 :tag("pubsub", { xmlns = xmlns_pubsub })
67 :tag("subscriptions");
68 for _, sub in ipairs(ret) do
69 reply:tag("subscription", { node = sub.node, jid = sub.jid, subscription = 'subscribed' }):up();
70 end
71 return origin.send(reply);
72 end
73
74 function handlers.set_create(origin, stanza, create, service)
75 local node = create.attr.node;
76 local ok, ret, reply;
77 if node then
78 ok, ret = service:create(node, stanza.attr.from);
79 if ok then
80 reply = st.reply(stanza);
81 else
82 reply = pubsub_error_reply(stanza, ret);
83 end
84 else
85 repeat
86 node = uuid_generate();
87 ok, ret = service:create(node, stanza.attr.from);
88 until ok or ret ~= "conflict";
89 if ok then
90 reply = st.reply(stanza)
91 :tag("pubsub", { xmlns = xmlns_pubsub })
92 :tag("create", { node = node });
93 else
94 reply = pubsub_error_reply(stanza, ret);
95 end
96 end
97 return origin.send(reply);
98 end
99
100 function handlers.set_delete(origin, stanza, delete, service)
101 local node = delete.attr.node;
102
103 local reply, notifier;
104 if not node then
105 return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
106 end
107 local ok, ret = service:delete(node, stanza.attr.from);
108 if ok then
109 reply = st.reply(stanza);
110 else
111 reply = pubsub_error_reply(stanza, ret);
112 end
113 return origin.send(reply);
114 end
115
116 function handlers.set_subscribe(origin, stanza, subscribe, service)
117 local node, jid = subscribe.attr.node, subscribe.attr.jid;
118 if not (node and jid) then
119 return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "invalid-jid"));
120 end
121 --[[
122 local options_tag, options = stanza.tags[1]:get_child("options"), nil;
123 if options_tag then
124 options = options_form:data(options_tag.tags[1]);
125 end
126 --]]
127 local options_tag, options; -- FIXME
128 local ok, ret = service:add_subscription(node, stanza.attr.from, jid, options);
129 local reply;
130 if ok then
131 reply = st.reply(stanza)
132 :tag("pubsub", { xmlns = xmlns_pubsub })
133 :tag("subscription", {
134 node = node,
135 jid = jid,
136 subscription = "subscribed"
137 }):up();
138 if options_tag then
139 reply:add_child(options_tag);
140 end
141 else
142 reply = pubsub_error_reply(stanza, ret);
143 end
144 origin.send(reply);
145 end
146
147 function handlers.set_unsubscribe(origin, stanza, unsubscribe, service)
148 local node, jid = unsubscribe.attr.node, unsubscribe.attr.jid;
149 if not (node and jid) then
150 return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "invalid-jid"));
151 end
152 local ok, ret = service:remove_subscription(node, stanza.attr.from, jid);
153 local reply;
154 if ok then
155 reply = st.reply(stanza);
156 else
157 reply = pubsub_error_reply(stanza, ret);
158 end
159 return origin.send(reply);
160 end
161
162 function handlers.set_publish(origin, stanza, publish, service)
163 local node = publish.attr.node;
164 if not node then
165 return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
166 end
167 local item = publish:get_child("item");
168 local id = (item and item.attr.id);
169 if not id then
170 id = uuid_generate();
171 if item then
172 item.attr.id = id;
173 end
174 end
175 local ok, ret = service:publish(node, stanza.attr.from, id, item);
176 local reply;
177 if ok then
178 reply = st.reply(stanza)
179 :tag("pubsub", { xmlns = xmlns_pubsub })
180 :tag("publish", { node = node })
181 :tag("item", { id = id });
182 else
183 reply = pubsub_error_reply(stanza, ret);
184 end
185 return origin.send(reply);
186 end
187
188 function handlers.set_retract(origin, stanza, retract, service)
189 local node, notify = retract.attr.node, retract.attr.notify;
190 notify = (notify == "1") or (notify == "true");
191 local item = retract:get_child("item");
192 local id = item and item.attr.id
193 if not (node and id) then
194 return origin.send(pubsub_error_reply(stanza, node and "item-not-found" or "nodeid-required"));
195 end
196 local reply, notifier;
197 if notify then
198 notifier = st.stanza("retract", { id = id });
199 end
200 local ok, ret = service:retract(node, stanza.attr.from, id, notifier);
201 if ok then
202 reply = st.reply(stanza);
203 else
204 reply = pubsub_error_reply(stanza, ret);
205 end
206 return origin.send(reply);
207 end
208
209 function handlers.set_purge(origin, stanza, purge, service)
210 local node, notify = purge.attr.node, purge.attr.notify;
211 notify = (notify == "1") or (notify == "true");
212 local reply;
213 if not node then
214 return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
215 end
216 local ok, ret = service:purge(node, stanza.attr.from, notify);
217 if ok then
218 reply = st.reply(stanza);
219 else
220 reply = pubsub_error_reply(stanza, ret);
221 end
222 return origin.send(reply);
223 end
224
225 return _M;