Software /
code /
prosody
Changeset
941:13ebec89b568
Automated merge with ssh://hg@prosody.im/prosody-hg
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 30 Mar 2009 20:04:31 +0100 |
parents | 939:b832f786af62 (diff) 940:776cb8c847c5 (current diff) |
children | 942:dae54304967d |
files | prosody |
diffstat | 14 files changed, 189 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/core/componentmanager.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/core/componentmanager.lua Mon Mar 30 20:04:31 2009 +0100 @@ -20,6 +20,18 @@ local components = {}; +local disco_items = require "util.multitable".new(); +local NULL = {}; +require "core.discomanager".addDiscoItemsHandler("*host", function(reply, to, from, node) + if #node == 0 and hosts[to] then + for jid in pairs(disco_items:get(to) or NULL) do + reply:tag("item", {jid = jid}):up(); + end + return true; + end +end); + + module "componentmanager" function load_enabled_components(config) @@ -64,7 +76,10 @@ if not hosts[host] or (hosts[host].type == 'component' and not hosts[host].connected) then components[host] = component; hosts[host] = session or create_component(host, component); - + -- add to disco_items + if not(host:find("@", 1, true) or host:find("/", 1, true)) and host:find(".", 1, true) then + disco_items:set(host:sub(host:find(".", 1, true)+1), host, true); + end -- FIXME only load for a.b.c if b.c has dialback, and/or check in config modulemanager.load(host, "dialback"); log("debug", "component added: "..host); @@ -79,6 +94,10 @@ modulemanager.unload(host, "dialback"); components[host] = nil; hosts[host] = nil; + -- remove from disco_items + if not(host:find("@", 1, true) or host:find("/", 1, true)) and host:find(".", 1, true) then + disco_items:remove(host:sub(host:find(".", 1, true)+1), host); + end log("debug", "component removed: "..host); return true; else
--- a/core/modulemanager.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/core/modulemanager.lua Mon Mar 30 20:04:31 2009 +0100 @@ -204,7 +204,7 @@ local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; if name == "iq" and xmlns == "jabber:client" then if stanza.attr.type == "get" or stanza.attr.type == "set" then - xmlns = stanza.tags[1].attr.xmlns; + xmlns = stanza.tags[1].attr.xmlns or "jabber:client"; log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns); else log("debug", "Discarding %s from %s of type: %s", name, origin_type, stanza.attr.type);
--- a/core/rostermanager.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/core/rostermanager.lua Mon Mar 30 20:04:31 2009 +0100 @@ -224,6 +224,10 @@ if is_contact_pending_in(username, host, jid) then local roster = load_roster(username, host); local item = roster[jid]; + if not item then -- FIXME should roster item be auto-created? + item = {subscription = "none", groups = {}}; + roster[jid] = item; + end if item.subscription == "none" then item.subscription = "from"; else -- subscription == to
--- a/core/s2smanager.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/core/s2smanager.lua Mon Mar 30 20:04:31 2009 +0100 @@ -24,6 +24,7 @@ local modulemanager = require "core.modulemanager"; local st = require "stanza"; local stanza = st.stanza; +local nameprep = require "util.encodings".stringprep.nameprep; local uuid_gen = require "util.uuid".generate; @@ -211,8 +212,8 @@ if session.direction == "incoming" then -- Send a reply stream header - session.to_host = attr.to; - session.from_host = attr.from; + session.to_host = attr.to and nameprep(attr.to); + session.from_host = attr.from and nameprep(attr.from); session.streamid = uuid_gen(); (session.log or log)("debug", "incoming s2s received <stream:stream>");
--- a/core/sessionmanager.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/core/sessionmanager.lua Mon Mar 30 20:04:31 2009 +0100 @@ -23,6 +23,7 @@ local uuid_generate = require "util.uuid".generate; local rm_load_roster = require "core.rostermanager".load_roster; local config_get = require "core.configmanager".get; +local nameprep = require "util.encodings".stringprep.nameprep; local fire_event = require "core.eventmanager".fire_event; @@ -156,6 +157,7 @@ function streamopened(session, attr) local send = session.send; session.host = attr.to or error("Client failed to specify destination hostname"); + session.host = nameprep(session.host); session.version = tonumber(attr.version) or 0; session.streamid = m_random(1000000, 99999999); (session.log or session)("debug", "Client sent opening <stream:stream> to %s", session.host);
--- a/core/stanza_router.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/core/stanza_router.lua Mon Mar 30 20:04:31 2009 +0100 @@ -51,9 +51,11 @@ if not stanza.attr.xmlns then stanza.attr.xmlns = "jabber:client"; end -- FIXME Hack. This should be removed when we fix namespace handling. -- TODO verify validity of stanza (as well as JID validity) - if stanza.name == "iq" and #stanza.tags > 1 then - if stanza.attr.type == "set" or stanza.attr.type == "get" then - error("Invalid IQ"); + if stanza.attr.xmlns == "error" and #stanza.tags == 0 then return; end -- TODO invalid stanza, log + if stanza.name == "iq" then + if (stanza.attr.type == "set" or stanza.attr.type == "get") and #stanza.tags ~= 1 then + origin.send(st.error_reply(stanza, "modify", "bad-request")); + return; end end
--- a/net/http.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/net/http.lua Mon Mar 30 20:04:31 2009 +0100 @@ -115,6 +115,7 @@ local req = url.parse(u); if not (req and req.host) then + callback(nil, 0, req); return nil, "invalid-url"; end
--- a/plugins/mod_muc.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/plugins/mod_muc.lua Mon Mar 30 20:04:31 2009 +0100 @@ -369,6 +369,16 @@ elseif type ~= "error" and type ~= "result" then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end + elseif stanza.name == "message" and not stanza.attr.type and #stanza.tags == 1 and jid_nick:get(stanza.attr.from, stanza.attr.to) + and stanza.tags[1].name == "x" and stanza.tags[1].attr.xmlns == "http://jabber.org/protocol/muc#user" and #stanza.tags[1].tags == 1 + and stanza.tags[1].tags[1].name == "invite" and stanza.tags[1].tags[1].attr.to then + local _from, _to = stanza.attr.from, stanza.attr.to; + local _invitee = stanza.tags[1].tags[1].attr.to; + stanza.attr.from, stanza.attr.to = _to, _invitee; + stanza.tags[1].tags[1].attr.from, stanza.tags[1].tags[1].attr.to = _from, nil; + core_route_stanza(component, stanza); + stanza.tags[1].tags[1].attr.from, stanza.tags[1].tags[1].attr.to = nil, _invitee; + stanza.attr.from, stanza.attr.to = _from, _to; else if type == "error" or type == "result" then return; end origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
--- a/plugins/mod_register.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/plugins/mod_register.lua Mon Mar 30 20:04:31 2009 +0100 @@ -13,6 +13,7 @@ local usermanager_create_user = require "core.usermanager".create_user; local datamanager_store = require "util.datamanager".store; local os_time = os.time; +local nodeprep = require "util.encodings".stringprep.nodeprep; module:add_feature("jabber:iq:register"); @@ -29,22 +30,23 @@ 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 + local username, host = session.username, session.host; --session.send(st.error_reply(stanza, "cancel", "not-allowed")); --return; - usermanager_create_user(session.username, nil, session.host); -- Disable account + usermanager_create_user(username, nil, 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 + for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources session:close({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; + datamanager.store(username, host, "roster", nil); + datamanager.store(username, host, "vcard", nil); + datamanager.store(username, host, "private", nil); + datamanager.store(username, host, "offline", nil); + --local bare = username.."@"..host; for jid, item in pairs(roster) do if jid ~= "pending" then if item.subscription == "both" or item.subscription == "to" then @@ -55,13 +57,13 @@ end end end - datamanager.store(session.username, session.host, "accounts", nil); -- delete accounts datastore at the end + datamanager.store(username, host, "accounts", nil); -- delete accounts datastore at the end else local username = query:child_with_name("username"); local password = query:child_with_name("password"); if username and password then -- FIXME shouldn't use table.concat - username = table.concat(username); + username = nodeprep(table.concat(username)); password = table.concat(password); if username == session.username then if usermanager_create_user(username, password, session.host) then -- password change -- TODO is this the right way? @@ -132,7 +134,7 @@ end end -- FIXME shouldn't use table.concat - username = table.concat(username); + username = nodeprep(table.concat(username)); password = table.concat(password); if usermanager_user_exists(username, session.host) then session.send(st.error_reply(stanza, "cancel", "conflict"));
--- a/plugins/mod_roster.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/plugins/mod_roster.lua Mon Mar 30 20:04:31 2009 +0100 @@ -11,6 +11,7 @@ local st = require "util.stanza" local jid_split = require "util.jid".split; +local jid_prep = require "util.jid".prep; local t_concat = table.concat; local tostring = tostring; @@ -61,17 +62,18 @@ local item = query.tags[1]; local from_node, from_host = jid_split(stanza.attr.from); local from_bare = from_node and (from_node.."@"..from_host) or from_host; -- bare JID - local node, host, resource = jid_split(item.attr.jid); - local to_bare = node and (node.."@"..host) or host; -- bare JID + local jid = jid_prep(item.attr.jid); + local node, host, resource = jid_split(jid); if not resource and host then - if item.attr.jid ~= from_node.."@"..from_host then + if jid ~= from_node.."@"..from_host then if item.attr.subscription == "remove" then - local r_item = session.roster[item.attr.jid]; + local r_item = session.roster[jid]; if r_item then - local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, item.attr.jid); + local success, err_type, err_cond, err_msg = rm_remove_from_roster(session, jid); if success then session.send(st.reply(stanza)); - rm_roster_push(from_node, from_host, item.attr.jid); + rm_roster_push(from_node, from_host, jid); + local to_bare = node and (node.."@"..host) or host; -- bare JID if r_item.subscription == "both" or r_item.subscription == "from" then handle_presence(session, st.presence({type="unsubscribed"}), from_bare, to_bare, core_route_stanza, false); @@ -88,9 +90,9 @@ else local r_item = {name = item.attr.name, groups = {}}; if r_item.name == "" then r_item.name = nil; end - if session.roster[item.attr.jid] then - r_item.subscription = session.roster[item.attr.jid].subscription; - r_item.ask = session.roster[item.attr.jid].ask; + if session.roster[jid] then + r_item.subscription = session.roster[jid].subscription; + r_item.ask = session.roster[jid].ask; else r_item.subscription = "none"; end @@ -102,10 +104,10 @@ end end end - local success, err_type, err_cond, err_msg = rm_add_to_roster(session, item.attr.jid, r_item); + local success, err_type, err_cond, err_msg = rm_add_to_roster(session, jid, r_item); if success then session.send(st.reply(stanza)); - rm_roster_push(from_node, from_host, item.attr.jid); + rm_roster_push(from_node, from_host, jid); else session.send(st.error_reply(stanza, err_type, err_cond, err_msg)); end
--- a/plugins/mod_saslauth.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/plugins/mod_saslauth.lua Mon Mar 30 20:04:31 2009 +0100 @@ -72,7 +72,15 @@ local function sasl_handler(session, stanza) if stanza.name == "auth" then -- FIXME ignoring duplicates because ejabberd does + if config.get(session.host or "*", "core", "anonymous_login") and stanza.attr.mechanism ~= "ANONYMOUS" then + return session.send(build_reply("failure", "invalid-mechanism")); + elseif stanza.attr.mechanism == "ANONYMOUS" then + return session.send(build_reply("failure", "mechanism-too-weak")); + end session.sasl_handler = new_sasl(stanza.attr.mechanism, session.host, password_callback); + if not session.sasl_handler then + return session.send(build_reply("failure", "invalid-mechanism")); + end elseif not session.sasl_handler then return; -- FIXME ignoring out of order stanzas because ejabberd does end @@ -105,10 +113,11 @@ if not session.username then features:tag("mechanisms", mechanisms_attr); -- TODO: Provide PLAIN only if TLS is active, this is a SHOULD from the introduction of RFC 4616. This behavior could be overridden via configuration but will issuing a warning or so. - features:tag("mechanism"):text("PLAIN"):up(); - features:tag("mechanism"):text("DIGEST-MD5"):up(); - if config.get(session.host or "*", "core", "sasl_anonymous") then + if config.get(session.host or "*", "core", "anonymous_login") then features:tag("mechanism"):text("ANONYMOUS"):up(); + else + features:tag("mechanism"):text("DIGEST-MD5"):up(); + features:tag("mechanism"):text("PLAIN"):up(); end features:up(); else
--- a/prosody Mon Mar 30 20:04:11 2009 +0100 +++ b/prosody Mon Mar 30 20:04:31 2009 +0100 @@ -104,6 +104,9 @@ local data_path = config.get("*", "core", "data_path") or CFG_DATADIR or "data"; require "util.datamanager".set_data_path(data_path); +require "util.datamanager".set_callback(function(username, host, datastore) + return config.get(host, "core", "anonymous_login"); +end); ----------- End of out-of-place code --------------
--- a/util/datamanager.lua Mon Mar 30 20:04:11 2009 +0100 +++ b/util/datamanager.lua Mon Mar 30 20:04:31 2009 +0100 @@ -50,6 +50,7 @@ end local data_path = "data"; +local callback; ------- API ------------- @@ -57,6 +58,9 @@ log("info", "Setting data path to: %s", path); data_path = path; end +function set_callback(func) + callback = func; +end function getpath(username, host, datastore, ext, create) ext = ext or "dat"; @@ -93,6 +97,7 @@ if not data then data = {}; end + if callback and callback(username, host, datastore) then return true; end -- save the datastore local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+"); if not f then @@ -113,6 +118,7 @@ function list_append(username, host, datastore, data) if not data then return; end + if callback and callback(username, host, datastore) then return true; end -- save the datastore local f, msg = io_open(getpath(username, host, datastore, "list", true), "a+"); if not f then @@ -130,6 +136,7 @@ if not data then data = {}; end + if callback and callback(username, host, datastore) then return true; end -- save the datastore local f, msg = io_open(getpath(username, host, datastore, "list", true), "w+"); if not f then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/events.lua Mon Mar 30 20:04:31 2009 +0100 @@ -0,0 +1,96 @@ + +local ipairs = ipairs; +local pairs = pairs; +local t_insert = table.insert; +local select = select; + +module "events" + +function new() + local dispatchers = {}; + local handlers = {}; + local event_map = {}; + local function _rebuild_index() -- TODO optimize index rebuilding + for event, _handlers in pairs(event_map) do + local index = handlers[event]; + if index then + for i=#index,1,-1 do index[i] = nil; end + else index = {}; handlers[event] = index; end + for handler in pairs(_handlers) do + t_insert(index, handler); + end + end + end; + local function add_handler(event, handler) + local map = event_map[event]; + if map then + map[handler] = true; + else + map = {[handler] = true}; + event_map[event] = map; + end + _rebuild_index(); + end; + local function remove_handler(event, handler) + local map = event_map[event]; + if map then + map[handler] = nil; + _rebuild_index(); + end + end; + local function add_plugin(plugin) + for event, handler in pairs(plugin) do + add_handler(event, handler); + end + end; + local function remove_plugin(plugin) + for event, handler in pairs(plugin) do + remove_handler(event, handler); + end + end; + local function _create_dispatcher(event) -- FIXME duplicate code in fire_event + local h = handlers[event]; + if not h then h = {}; handlers[event] = h; end + local dispatcher = function(data) + for _, handler in ipairs(h) do + handler(data); + end + end; + dispatchers[event] = dispatcher; + return dispatcher; + end; + local function get_dispatcher(event) + return dispatchers[event] or _create_dispatcher(event); + end; + local function fire_event(event, data) -- FIXME duplicates dispatcher code + local h = handlers[event]; + if h then + for _, handler in ipairs(h) do + handler(data); + end + end + end; + local function get_named_arg_dispatcher(event, ...) + local dispatcher = get_dispatcher(event); + local keys = {...}; + local data = {}; + return function(...) + for i, key in ipairs(keys) do data[key] = select(i, ...); end + dispatcher(data); + end; + end; + return { + add_handler = add_handler; + remove_handler = remove_handler; + add_plugin = add_plugin; + remove_plugin = remove_plugin; + get_dispatcher = get_dispatcher; + fire_event = fire_event; + get_named_arg_dispatcher = get_named_arg_dispatcher; + _dispatchers = dispatchers; + _handlers = handlers; + _event_map = event_map; + }; +end + +return _M;