aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/mod_pubsub/mod_pubsub.lua (renamed from plugins/mod_pubsub.lua)258
-rw-r--r--plugins/mod_pubsub/pubsub.lib.lua225
2 files changed, 248 insertions, 235 deletions
diff --git a/plugins/mod_pubsub.lua b/plugins/mod_pubsub/mod_pubsub.lua
index 926ed4f2..ad20c6a7 100644
--- a/plugins/mod_pubsub.lua
+++ b/plugins/mod_pubsub/mod_pubsub.lua
@@ -1,11 +1,9 @@
local pubsub = require "util.pubsub";
local st = require "util.stanza";
local jid_bare = require "util.jid".bare;
-local uuid_generate = require "util.uuid".generate;
local usermanager = require "core.usermanager";
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 xmlns_pubsub_owner = "http://jabber.org/protocol/pubsub#owner";
@@ -16,7 +14,9 @@ if type(pubsub_disco_name) ~= "string" then pubsub_disco_name = "Prosody PubSub
local service;
-local handlers = {};
+local lib_pubsub = module:require "pubsub";
+local handlers = lib_pubsub.handlers;
+local pubsub_error_reply = lib_pubsub.pubsub_error_reply;
function handle_pubsub_iq(event)
local origin, stanza = event.origin, event.stanza;
@@ -27,223 +27,11 @@ function handle_pubsub_iq(event)
end
local handler = handlers[stanza.attr.type.."_"..action.name];
if handler then
- handler(origin, stanza, action);
+ handler(origin, stanza, action, service);
return true;
end
end
-local pubsub_errors = {
- ["conflict"] = { "cancel", "conflict" };
- ["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" };
- ["jid-required"] = { "modify", "bad-request", nil, "jid-required" };
- ["nodeid-required"] = { "modify", "bad-request", nil, "nodeid-required" };
- ["item-not-found"] = { "cancel", "item-not-found" };
- ["not-subscribed"] = { "modify", "unexpected-request", nil, "not-subscribed" };
- ["forbidden"] = { "cancel", "forbidden" };
-};
-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;
-
- if not node then
- return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
- end
- local ok, results = service:get_items(node, stanza.attr.from, id);
- if not ok then
- return origin.send(pubsub_error_reply(stanza, results));
- end
-
- local data = st.stanza("items", { node = node });
- for _, entry in pairs(results) do
- data:add_child(entry);
- end
- local reply;
- 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.get_subscriptions(origin, stanza, subscriptions)
- local node = subscriptions.attr.node;
- local ok, ret = service:get_subscriptions(node, stanza.attr.from, stanza.attr.from);
- if not ok then
- return origin.send(pubsub_error_reply(stanza, ret));
- end
- local reply = st.reply(stanza)
- :tag("pubsub", { xmlns = xmlns_pubsub })
- :tag("subscriptions");
- for _, sub in ipairs(ret) do
- reply:tag("subscription", { node = sub.node, jid = sub.jid, subscription = 'subscribed' }):up();
- 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 or ret ~= "conflict";
- if ok then
- reply = st.reply(stanza)
- :tag("pubsub", { xmlns = xmlns_pubsub })
- :tag("create", { node = node });
- else
- reply = pubsub_error_reply(stanza, ret);
- end
- end
- return origin.send(reply);
-end
-
-function handlers.set_delete(origin, stanza, delete)
- local node = delete.attr.node;
-
- local reply, notifier;
- if not node then
- return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
- end
- local ok, ret = service:delete(node, stanza.attr.from);
- if ok then
- reply = st.reply(stanza);
- else
- reply = pubsub_error_reply(stanza, ret);
- end
- return origin.send(reply);
-end
-
-function handlers.set_subscribe(origin, stanza, subscribe)
- local node, jid = subscribe.attr.node, subscribe.attr.jid;
- if not (node and jid) then
- return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "invalid-jid"));
- end
- --[[
- local options_tag, options = stanza.tags[1]:get_child("options"), nil;
- if options_tag then
- options = options_form:data(options_tag.tags[1]);
- end
- --]]
- local options_tag, options; -- FIXME
- local ok, ret = service:add_subscription(node, stanza.attr.from, jid, options);
- local reply;
- if ok then
- reply = st.reply(stanza)
- :tag("pubsub", { xmlns = xmlns_pubsub })
- :tag("subscription", {
- node = node,
- jid = jid,
- subscription = "subscribed"
- }):up();
- if options_tag then
- reply:add_child(options_tag);
- end
- else
- reply = pubsub_error_reply(stanza, ret);
- end
- origin.send(reply);
-end
-
-function handlers.set_unsubscribe(origin, stanza, unsubscribe)
- local node, jid = unsubscribe.attr.node, unsubscribe.attr.jid;
- if not (node and jid) then
- return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "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;
- if not node then
- return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
- end
- local item = publish:get_child("item");
- local id = (item and item.attr.id);
- if not id then
- id = uuid_generate();
- if item then
- item.attr.id = id;
- end
- end
- 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
- if not (node and id) then
- return origin.send(pubsub_error_reply(stanza, node and "item-not-found" or "nodeid-required"));
- end
- 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 handlers.set_purge(origin, stanza, purge)
- local node, notify = purge.attr.node, purge.attr.notify;
- notify = (notify == "1") or (notify == "true");
- local reply;
- if not node then
- return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
- end
- local ok, ret = service:purge(node, stanza.attr.from, notify);
- if ok then
- reply = st.reply(stanza);
- else
- reply = pubsub_error_reply(stanza, ret);
- end
- return origin.send(reply);
-end
-
function simple_broadcast(kind, node, jids, item)
if item then
item = st.clone(item);
@@ -329,14 +117,14 @@ local function handle_disco_items_on_node(event)
if not ok then
return origin.send(pubsub_error_reply(stanza, ret));
end
-
+
local reply = st.reply(stanza)
:tag("query", { xmlns = "http://jabber.org/protocol/disco#items", node = node });
-
+
for id, item in pairs(ret) do
reply:tag("item", { jid = module.host, name = id }):up();
end
-
+
return origin.send(reply);
end
@@ -388,21 +176,21 @@ set_service(pubsub.new({
publish = false;
retract = false;
get_nodes = true;
-
+
subscribe = true;
unsubscribe = true;
get_subscription = true;
get_subscriptions = true;
get_items = true;
-
+
subscribe_other = false;
unsubscribe_other = false;
get_subscription_other = false;
get_subscriptions_other = false;
-
+
be_subscribed = true;
be_unsubscribed = true;
-
+
set_affiliation = false;
};
publisher = {
@@ -410,21 +198,21 @@ set_service(pubsub.new({
publish = true;
retract = true;
get_nodes = true;
-
+
subscribe = true;
unsubscribe = true;
get_subscription = true;
get_subscriptions = true;
get_items = true;
-
+
subscribe_other = false;
unsubscribe_other = false;
get_subscription_other = false;
get_subscriptions_other = false;
-
+
be_subscribed = true;
be_unsubscribed = true;
-
+
set_affiliation = false;
};
owner = {
@@ -433,31 +221,31 @@ set_service(pubsub.new({
retract = true;
delete = true;
get_nodes = true;
-
+
subscribe = true;
unsubscribe = true;
get_subscription = true;
get_subscriptions = true;
get_items = true;
-
-
+
+
subscribe_other = true;
unsubscribe_other = true;
get_subscription_other = true;
get_subscriptions_other = true;
-
+
be_subscribed = true;
be_unsubscribed = true;
-
+
set_affiliation = true;
};
};
-
+
autocreate_on_publish = autocreate_on_publish;
autocreate_on_subscribe = autocreate_on_subscribe;
-
+
broadcaster = simple_broadcast;
get_affiliation = get_affiliation;
-
+
normalize_jid = jid_bare;
}));
diff --git a/plugins/mod_pubsub/pubsub.lib.lua b/plugins/mod_pubsub/pubsub.lib.lua
new file mode 100644
index 00000000..2b015e34
--- /dev/null
+++ b/plugins/mod_pubsub/pubsub.lib.lua
@@ -0,0 +1,225 @@
+local st = require "util.stanza";
+local uuid_generate = require "util.uuid".generate;
+
+local xmlns_pubsub = "http://jabber.org/protocol/pubsub";
+local xmlns_pubsub_errors = "http://jabber.org/protocol/pubsub#errors";
+
+local _M = {};
+
+local handlers = {};
+_M.handlers = handlers;
+
+local pubsub_errors = {
+ ["conflict"] = { "cancel", "conflict" };
+ ["invalid-jid"] = { "modify", "bad-request", nil, "invalid-jid" };
+ ["jid-required"] = { "modify", "bad-request", nil, "jid-required" };
+ ["nodeid-required"] = { "modify", "bad-request", nil, "nodeid-required" };
+ ["item-not-found"] = { "cancel", "item-not-found" };
+ ["not-subscribed"] = { "modify", "unexpected-request", nil, "not-subscribed" };
+ ["forbidden"] = { "cancel", "forbidden" };
+};
+local 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
+_M.pubsub_error_reply = pubsub_error_reply;
+
+function handlers.get_items(origin, stanza, items, service)
+ local node = items.attr.node;
+ local item = items:get_child("item");
+ local id = item and item.attr.id;
+
+ if not node then
+ return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
+ end
+ local ok, results = service:get_items(node, stanza.attr.from, id);
+ if not ok then
+ return origin.send(pubsub_error_reply(stanza, results));
+ end
+
+ local data = st.stanza("items", { node = node });
+ for _, entry in pairs(results) do
+ data:add_child(entry);
+ end
+ local reply;
+ 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.get_subscriptions(origin, stanza, subscriptions, service)
+ local node = subscriptions.attr.node;
+ local ok, ret = service:get_subscriptions(node, stanza.attr.from, stanza.attr.from);
+ if not ok then
+ return origin.send(pubsub_error_reply(stanza, ret));
+ end
+ local reply = st.reply(stanza)
+ :tag("pubsub", { xmlns = xmlns_pubsub })
+ :tag("subscriptions");
+ for _, sub in ipairs(ret) do
+ reply:tag("subscription", { node = sub.node, jid = sub.jid, subscription = 'subscribed' }):up();
+ end
+ return origin.send(reply);
+end
+
+function handlers.set_create(origin, stanza, create, service)
+ 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 or ret ~= "conflict";
+ if ok then
+ reply = st.reply(stanza)
+ :tag("pubsub", { xmlns = xmlns_pubsub })
+ :tag("create", { node = node });
+ else
+ reply = pubsub_error_reply(stanza, ret);
+ end
+ end
+ return origin.send(reply);
+end
+
+function handlers.set_delete(origin, stanza, delete, service)
+ local node = delete.attr.node;
+
+ local reply, notifier;
+ if not node then
+ return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
+ end
+ local ok, ret = service:delete(node, stanza.attr.from);
+ if ok then
+ reply = st.reply(stanza);
+ else
+ reply = pubsub_error_reply(stanza, ret);
+ end
+ return origin.send(reply);
+end
+
+function handlers.set_subscribe(origin, stanza, subscribe, service)
+ local node, jid = subscribe.attr.node, subscribe.attr.jid;
+ if not (node and jid) then
+ return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "invalid-jid"));
+ end
+ --[[
+ local options_tag, options = stanza.tags[1]:get_child("options"), nil;
+ if options_tag then
+ options = options_form:data(options_tag.tags[1]);
+ end
+ --]]
+ local options_tag, options; -- FIXME
+ local ok, ret = service:add_subscription(node, stanza.attr.from, jid, options);
+ local reply;
+ if ok then
+ reply = st.reply(stanza)
+ :tag("pubsub", { xmlns = xmlns_pubsub })
+ :tag("subscription", {
+ node = node,
+ jid = jid,
+ subscription = "subscribed"
+ }):up();
+ if options_tag then
+ reply:add_child(options_tag);
+ end
+ else
+ reply = pubsub_error_reply(stanza, ret);
+ end
+ origin.send(reply);
+end
+
+function handlers.set_unsubscribe(origin, stanza, unsubscribe, service)
+ local node, jid = unsubscribe.attr.node, unsubscribe.attr.jid;
+ if not (node and jid) then
+ return origin.send(pubsub_error_reply(stanza, jid and "nodeid-required" or "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, service)
+ local node = publish.attr.node;
+ if not node then
+ return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
+ end
+ local item = publish:get_child("item");
+ local id = (item and item.attr.id);
+ if not id then
+ id = uuid_generate();
+ if item then
+ item.attr.id = id;
+ end
+ end
+ 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, service)
+ 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
+ if not (node and id) then
+ return origin.send(pubsub_error_reply(stanza, node and "item-not-found" or "nodeid-required"));
+ end
+ 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 handlers.set_purge(origin, stanza, purge, service)
+ local node, notify = purge.attr.node, purge.attr.notify;
+ notify = (notify == "1") or (notify == "true");
+ local reply;
+ if not node then
+ return origin.send(pubsub_error_reply(stanza, "nodeid-required"));
+ end
+ local ok, ret = service:purge(node, stanza.attr.from, notify);
+ if ok then
+ reply = st.reply(stanza);
+ else
+ reply = pubsub_error_reply(stanza, ret);
+ end
+ return origin.send(reply);
+end
+
+return _M;