1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
local pubsub = require "util.pubsub";
local st = require "util.stanza";
local jid_bare = require "util.jid".bare;
local uuid_generate = require "util.uuid".generate;
require "core.modulemanager".load(module.host, "iq");
local xmlns_pubsub = "http://jabber.org/protocol/pubsub";
local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors";
local xmlns_pubsub_event = "http://jabber.org/protocol/pubsub#event";
local service;
local handlers = {};
function handle_pubsub_iq(event)
local origin, stanza = event.origin, event.stanza;
local pubsub = stanza.tags[1];
local action = pubsub.tags[1];
local handler = handlers[stanza.attr.type.."_"..action.name];
if handler then
handler(origin, stanza, action);
return true;
end
end
local pubsub_errors = {
["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" };
["item-not-found"] = { "cancel", "item-not-found" };
};
function pubsub_error_reply(stanza, error)
local e = pubsub_errors[error];
local reply = st.error_reply(stanza, unpack(e, 1, 3));
if e[4] then
reply:tag(e[4], { xmlns = xmlns_pubsub_errors }):up();
end
return reply;
end
function handlers.get_items(origin, stanza, items)
local node = items.attr.node;
local item = items:get_child("item");
local id = item and item.attr.id;
local data = st.stanza("items", { node = node });
for _, entry in pairs(service:get(node, stanza.attr.from, id)) do
data:add_child(entry);
end
if data then
reply = st.reply(stanza)
:tag("pubsub", { xmlns = xmlns_pubsub })
:add_child(data);
else
reply = st.error_reply(stanza, "cancel", "item-not-found", "Item could not be found in this node");
end
return origin.send(reply);
end
function handlers.set_subscribe(origin, stanza, subscribe)
local node, jid = subscribe.attr.node, subscribe.attr.jid;
if jid_bare(jid) ~= jid_bare(stanza.attr.from) then
return origin.send(pubsub_error_reply(stanza, "invalid-jid"));
end
local ok, ret = service:add_subscription(node, stanza.attr.from, jid);
local reply;
if ok then
reply = st.reply(stanza)
:tag("pubsub", { xmlns = xmlns_pubsub })
:tag("subscription", {
node = node,
jid = jid,
subscription = "subscribed"
});
else
reply = pubsub_error_reply(stanza, ret);
end
return origin.send(reply);
end
function handlers.set_publish(origin, stanza, publish)
local node = publish.attr.node;
local item = publish:get_child("item");
local id = (item and item.attr.id) or uuid_generate();
local ok, ret = service:publish(node, stanza.attr.from, id, item);
local reply;
if ok then
reply = st.reply(stanza)
:tag("pubsub", { xmlns = xmlns_pubsub })
:tag("publish", { node = node })
:tag("item", { id = id });
else
reply = pubsub_error_reply(stanza, ret);
end
return origin.send(reply);
end
function simple_broadcast(node, jids, item)
local message = st.message({ from = module.host, type = "headline" })
:tag("event", { xmlns = xmlns_pubsub_event })
:tag("items", { node = node })
:add_child(item);
for jid in pairs(jids) do
module:log("debug", "Sending notification to %s", jid);
message.attr.to = jid;
core_post_stanza(hosts[module.host], message);
end
end
module:hook("iq/host/http://jabber.org/protocol/pubsub:pubsub", handle_pubsub_iq);
service = pubsub.new({
broadcaster = simple_broadcast
});
module.environment.service = service;
|