aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/discomanager.lua39
-rw-r--r--core/modulemanager.lua6
-rw-r--r--plugins/mod_disco.lua9
-rw-r--r--plugins/mod_register.lua29
-rw-r--r--util/discohelper.lua79
-rw-r--r--util/jid.lua4
6 files changed, 159 insertions, 7 deletions
diff --git a/core/discomanager.lua b/core/discomanager.lua
new file mode 100644
index 00000000..471f1101
--- /dev/null
+++ b/core/discomanager.lua
@@ -0,0 +1,39 @@
+
+local helper = require "util.discohelper".new();
+local hosts = hosts;
+local jid_split = require "util.jid".split;
+local jid_bare = require "util.jid".bare;
+local usermanager_user_exists = require "core.usermanager".user_exists;
+local rostermanager_is_contact_subscribed = require "core.rostermanager".is_contact_subscribed;
+
+do
+ helper:addDiscoInfoHandler("*host", function(reply, to, from, node)
+ if hosts[to] then
+ reply:tag("identity", {category="server", type="im", name="ejabberd"}):up();
+ return true;
+ end
+ end);
+ helper:addDiscoInfoHandler("*node", function(reply, to, from, node)
+ local node, host = jid_split(to);
+ if hosts[host] and rostermanager_is_contact_subscribed(node, host, jid_bare(from)) then
+ reply:tag("identity", {category="account", type="registered"}):up();
+ return true;
+ end
+ end);
+end
+
+module "discomanager"
+
+function handle(stanza)
+ return helper:handle(stanza);
+end
+
+function addDiscoItemsHandler(jid, func)
+ return helper:addDiscoItemsHandler(jid, func);
+end
+
+function addDiscoInfoHandler(jid, func)
+ return helper:addDiscoInfoHandler(jid, func);
+end
+
+return _M;
diff --git a/core/modulemanager.lua b/core/modulemanager.lua
index 783fea55..f4893089 100644
--- a/core/modulemanager.lua
+++ b/core/modulemanager.lua
@@ -92,15 +92,15 @@ function handle_stanza(origin, stanza)
if child then
local xmlns = child.attr.xmlns or xmlns;
log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns);
- local handler = handlers[origin_type][name][xmlns];
- if handler then
+ local handler = handlers[origin_type][name] and handlers[origin_type][name][xmlns];
+ if handler then
log("debug", "Passing stanza to mod_%s", handler_info[handler].name);
return handler(origin, stanza) or true;
end
end
elseif handlers[origin_type] then
local handler = handlers[origin_type][name];
- if handler then
+ if handler then
handler = handler[xmlns];
if handler then
log("debug", "Passing stanza to mod_%s", handler_info[handler].name);
diff --git a/plugins/mod_disco.lua b/plugins/mod_disco.lua
new file mode 100644
index 00000000..261650ce
--- /dev/null
+++ b/plugins/mod_disco.lua
@@ -0,0 +1,9 @@
+
+local discomanager_handle = require "core.discomanager".handle;
+
+add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#info", function (session, stanza)
+ session.send(discomanager_handle(stanza));
+end);
+add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#items", function (session, stanza)
+ session.send(discomanager_handle(stanza));
+end);
diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index fb001392..c2b85bae 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -2,6 +2,7 @@
local st = require "util.stanza";
local usermanager_user_exists = require "core.usermanager".user_exists;
local usermanager_create_user = require "core.usermanager".create_user;
+local datamanager_store = require "util.datamanager".store;
add_iq_handler("c2s", "jabber:iq:register", function (session, stanza)
if stanza.tags[1].name == "query" then
@@ -16,7 +17,33 @@ add_iq_handler("c2s", "jabber:iq:register", function (session, stanza)
elseif stanza.attr.type == "set" then
if query.tags[1] and query.tags[1].name == "remove" then
-- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data
- session.send(st.error_reply(stanza, "cancel", "not-allowed"));
+ --session.send(st.error_reply(stanza, "cancel", "not-allowed"));
+ --return;
+ usermanager_create_user(session.username, nil, session.host); -- Disable account
+ -- FIXME the disabling currently allows a different user to recreate the account
+ -- we should add an in-memory account block mode when we have threading
+ session.send(st.reply(stanza));
+ local roster = session.roster;
+ for _, session in pairs(hosts[session.host].sessions[session.username].sessions) do -- disconnect all resources
+ session:disconnect({condition = "not-authorized", text = "Account deleted"});
+ end
+ -- TODO datamanager should be able to delete all user data itself
+ datamanager.store(session.username, session.host, "roster", nil);
+ datamanager.store(session.username, session.host, "vCard", nil);
+ datamanager.store(session.username, session.host, "private", nil);
+ datamanager.store(session.username, session.host, "offline", nil);
+ local bare = session.username.."@"..session.host;
+ for jid, item in pairs(roster) do
+ if jid ~= "pending" then
+ if item.subscription == "both" or item.subscription == "to" then
+ -- TODO unsubscribe
+ end
+ if item.subscription == "both" or item.subscription == "from" then
+ -- TODO unsubscribe
+ end
+ end
+ end
+ datamanager.store(session.username, session.host, "accounts", nil); -- delete accounts datastore at the end
else
local username = query:child_with_name("username");
local password = query:child_with_name("password");
diff --git a/util/discohelper.lua b/util/discohelper.lua
new file mode 100644
index 00000000..4ac8f227
--- /dev/null
+++ b/util/discohelper.lua
@@ -0,0 +1,79 @@
+
+local t_insert = table.insert;
+local jid_split = require "util.jid".split;
+local ipairs = ipairs;
+local st = require "util.stanza";
+
+module "discohelper";
+
+local function addDiscoItemsHandler(self, jid, func)
+ if self.item_handlers[jid] then
+ t_insert(self.item_handlers[jid], func);
+ else
+ self.item_handlers[jid] = {func};
+ end
+end
+
+local function addDiscoInfoHandler(self, jid, func)
+ if self.info_handlers[jid] then
+ t_insert(self.info_handlers[jid], func);
+ else
+ self.info_handlers[jid] = {func};
+ end
+end
+
+local function handle(self, stanza)
+ if stanza.name == "iq" and stanza.tags[1].name == "query" then
+ local query = stanza.tags[1];
+ local to = stanza.attr.to;
+ local from = stanza.attr.from
+ local node = query.attr.node or "";
+ local to_node, to_host = jid_split(to);
+
+ local reply = st.reply(stanza):query(query.attr.xmlns);
+ local handlers;
+ if query.attr.xmlns == "http://jabber.org/protocol/disco#info" then -- select handler set
+ handlers = self.info_handlers;
+ elseif query.attr.xmlns == "http://jabber.org/protocol/disco#items" then
+ handlers = self.item_handlers;
+ end
+ local handler = handlers[to]; -- get the handler
+ if not handler then -- if not found then use default handler
+ if to_node then
+ handler = handlers["*defaultnode"];
+ else
+ handler = handlers["*defaulthost"];
+ end
+ end
+ local found; -- to keep track of any handlers found
+ if handler then
+ for _, h in ipairs(handler) do
+ if h(reply, to, from, node) then found = true; end
+ end
+ end
+ if to_node then -- handlers which get called always
+ handler = handlers["*node"];
+ else
+ handler = handlers["*host"];
+ end
+ if handler then -- call always called handler
+ for _, h in ipairs(handler) do
+ if h(reply, to, from, node) then found = true; end
+ end
+ end
+ if found then return reply; end -- return the reply if there was one
+ return st.error_reply(stanza, "cancel", "service-unavailable");
+ end
+end
+
+function new()
+ return {
+ item_handlers = {};
+ info_handlers = {};
+ addDiscoItemsHandler = addDiscoItemsHandler;
+ addDiscoInfoHandler = addDiscoInfoHandler;
+ handle = handle;
+ };
+end
+
+return _M;
diff --git a/util/jid.lua b/util/jid.lua
index 2e40a338..065f176f 100644
--- a/util/jid.lua
+++ b/util/jid.lua
@@ -17,10 +17,8 @@ function bare(jid)
local node, host = split(jid);
if node and host then
return node.."@"..host;
- elseif host then
- return host;
end
- return nil;
+ return host;
end
return _M;