diff options
-rw-r--r-- | plugins/mod_pubsub.lua | 205 | ||||
-rw-r--r-- | util/pubsub.lua | 84 |
2 files changed, 0 insertions, 289 deletions
diff --git a/plugins/mod_pubsub.lua b/plugins/mod_pubsub.lua deleted file mode 100644 index dc1b1263..00000000 --- a/plugins/mod_pubsub.lua +++ /dev/null @@ -1,205 +0,0 @@ -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 = { - ["conflict"] = { "cancel", "conflict" }; - ["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" }; - ["item-not-found"] = { "cancel", "item-not-found" }; - ["not-subscribed"] = { "modify", "unexpected-request", nil, "not-subscribed" }; -}; -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 = pubsub_error_reply(stanza, "item-not-found"); - end - return origin.send(reply); -end - -function handlers.set_create(origin, stanza, create) - local node = create.attr.node; - local ok, ret, reply; - if node then - ok, ret = service:create(node, stanza.attr.from); - if ok then - reply = st.reply(stanza); - else - reply = pubsub_error_reply(stanza, ret); - end - else - repeat - node = uuid_generate(); - ok, ret = service:create(node, stanza.attr.from); - until ok; - reply = st.reply(stanza) - :tag("pubsub", { xmlns = xmlns_pubsub }) - :tag("create", { node = 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_unsubscribe(origin, stanza, unsubscribe) - local node, jid = unsubscribe.attr.node, unsubscribe.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:remove_subscription(node, stanza.attr.from, jid); - local reply; - if ok then - reply = st.reply(stanza); - 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 handlers.set_retract(origin, stanza, retract) - local node, notify = retract.attr.node, retract.attr.notify; - notify = (notify == "1") or (notify == "true"); - local item = retract:get_child("item"); - local id = item and item.attr.id - local reply, notifier; - if notify then - notifier = st.stanza("retract", { id = id }); - end - local ok, ret = service:retract(node, stanza.attr.from, id, notifier); - if ok then - reply = st.reply(stanza); - else - reply = pubsub_error_reply(stanza, ret); - end - return origin.send(reply); -end - -function simple_broadcast(node, jids, item) - item = st.clone(item); - item.attr.xmlns = nil; -- Clear the pubsub namespace - 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); - -local disco_info = st.stanza("query", { xmlns = "http://jabber.org/protocol/disco#info" }) - :tag("identity", { category = "pubsub", type = "service" }):up() - :tag("feature", { var = "http://jabber.org/protocol/pubsub" }):up(); - -module:hook("iq-get/host/http://jabber.org/protocol/disco#info:query", function (event) - event.origin.send(st.reply(event.stanza):add_child(disco_info)); - return true; -end); - -module:hook("iq-get/host/http://jabber.org/protocol/disco#items:query", function (event) - local ok, ret = service:get_nodes(event.stanza.attr.from); - if not ok then - event.origin.send(pubsub_error_reply(stanza, ret)); - else - local reply = st.reply(event.stanza) - :tag("query", { xmlns = "http://jabber.org/protocol/disco#items" }); - for node, node_obj in pairs(ret) do - reply:tag("item", { jid = module.host, node = node, name = node_obj.config.name }):up(); - end - event.origin.send(reply); - end - return true; -end); - -service = pubsub.new({ - broadcaster = simple_broadcast -}); -module.environment.service = service; - -function module.save() - return { service = service }; -end - -function module.restore(data) - service = data.service; - module.environment.service = service; -end diff --git a/util/pubsub.lua b/util/pubsub.lua deleted file mode 100644 index 811f4a15..00000000 --- a/util/pubsub.lua +++ /dev/null @@ -1,84 +0,0 @@ -module("pubsub", package.seeall); - -local service = {}; -local service_mt = { __index = service }; - -function new(cb) - return setmetatable({ cb = cb or {}, nodes = {} }, service_mt); -end - -function service:add_subscription(node, actor, jid) - local node_obj = self.nodes[node]; - if not node_obj then - return false, "item-not-found"; - end - node_obj.subscribers[jid] = true; - return true; -end - -function service:remove_subscription(node, actor, jid) - local node_obj = self.nodes[node]; - if not node_obj then - return false, "item-not-found"; - end - if not node_obj.subscribers[jid] then - return false, "not-subscribed"; - end - node_obj.subscribers[jid] = nil; - return true; -end - -function service:get_subscription(node, actor, jid) - local node_obj = self.nodes[node]; - if node_obj then - return node_obj.subscribers[jid]; - end -end - -function service:create(node, actor) - if not self.nodes[node] then - self.nodes[node] = { name = node, subscribers = {}, config = {}, data = {} }; - return true; - end - return false, "conflict"; -end - -function service:publish(node, actor, id, item) - local node_obj = self.nodes[node]; - if not node_obj then - node_obj = { name = node, subscribers = {}, config = {}, data = {} }; - self.nodes[node] = node_obj; - end - node_obj.data[id] = item; - self.cb.broadcaster(node, node_obj.subscribers, item); - return true; -end - -function service:retract(node, actor, id, retract) - local node_obj = self.nodes[node]; - if (not node_obj) or (not node_obj.data[id]) then - return false, "item-not-found"; - end - node_obj.data[id] = nil; - if retract then - self.cb.broadcaster(node, node_obj.subscribers, retract); - end - return true -end - -function service:get(node, actor, id) - local node_obj = self.nodes[node]; - if node_obj then - if id then - return { node_obj.data[id] }; - else - return node_obj.data; - end - end -end - -function service:get_nodes(actor) - return true, self.nodes; -end - -return _M; |