diff options
118 files changed, 1135 insertions, 1034 deletions
@@ -6,6 +6,7 @@ www_files html/* prosody.lua prosody.cfg.lua +prosody.version config.unix *.patch *.orig @@ -5,6 +5,8 @@ involved you can join us on our mailing list and discussion rooms. More information on these at http://prosody.im/discuss Patches are welcome, though before sending we would appreciate if you read -docs/coding_style.txt for guidelines on how to format your code, and are -comfortable with copyright of contributions being assigned to the core -developers. +docs/coding_style.txt for guidelines on how to format your code, and other tips. + +Documentation for developers can be found at http://prosody.im/doc/developers + +Have fun :) @@ -21,7 +21,7 @@ install: prosody.install prosodyctl.install prosody.cfg.lua.install util/encodin install -m750 -d $(DATA) install -d $(MAN)/man1 install -d $(CONFIG)/certs - install -d $(SOURCE)/core $(SOURCE)/net $(SOURCE)/util $(SOURCE)/fallbacks + install -d $(SOURCE)/core $(SOURCE)/net $(SOURCE)/util install -m755 ./prosody.install $(BIN)/prosody install -m755 ./prosodyctl.install $(BIN)/prosodyctl install -m644 core/* $(SOURCE)/core @@ -30,7 +30,6 @@ install: prosody.install prosodyctl.install prosody.cfg.lua.install util/encodin install -m644 util/*.so $(SOURCE)/util install -d $(SOURCE)/util/sasl install -m644 util/sasl/* $(SOURCE)/util/sasl - install -m644 fallbacks/* $(SOURCE)/fallbacks install -m644 plugins/*.lua $(MODULES) install -d $(MODULES)/muc install -m644 plugins/muc/* $(MODULES)/muc @@ -32,6 +32,6 @@ Mailing lists: ## Installation See the accompanying INSTALL file for help on building Prosody from source. Alternatively -see our guide at http://prosody.im/install +see our guide at http://prosody.im/doc/install @@ -1,5 +1,16 @@ -- Ad-hoc commands -- Clustering +== 0.8 == +- Ad-hoc commands: + http://code.google.com/p/prosody-modules/wiki/mod_adhoc + http://code.google.com/p/prosody-modules/wiki/mod_adhoc_cmd_admin + http://code.google.com/p/prosody-modules/wiki/mod_adhoc_cmd_ping + http://code.google.com/p/prosody-modules/wiki/mod_adhoc_cmd_uptime + - Pubsub +- Data storage backend abstraction +== 0.9 == +- Clustering +== 1.0 == +- Web interface? +- World domination @@ -61,7 +61,7 @@ EOF while [ "$1" ] do - value="`echo $1 | sed 's/.*=\(.*\)/\1/'`" + value="`echo $1 | sed 's/[^=]*=\(.*\)/\1/'`" if echo "$value" | grep -q "~" then echo diff --git a/core/certmanager.lua b/core/certmanager.lua index 5794ba6e..fa920b91 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -3,7 +3,7 @@ local log = require "util.logger".init("certmanager"); local ssl = ssl; local ssl_newcontext = ssl and ssl.newcontext; -local setmetatable = setmetatable; +local setmetatable, tostring = setmetatable, tostring; local prosody = prosody; @@ -39,8 +39,10 @@ function create_context(host, mode, config) reason = "Check that the path is correct, and the file exists."; elseif reason == "system lib" then reason = "Previous error (see logs), or other system error."; + elseif reason == "(null)" or not reason then + reason = "Check that the file exists and the permissions are correct"; else - reason = "Reason: "..tostring(reason or "unknown"):lower(); + reason = "Reason: "..tostring(reason):lower(); end log("error", "SSL/TLS: Failed to load %s: %s", file, reason); else @@ -54,7 +56,7 @@ function create_context(host, mode, config) end function reload_ssl_config() - default_ssl_config = config.get("*", "core", "ssl"); + default_ssl_config = configmanager.get("*", "core", "ssl"); end prosody.events.add_handler("config-reloaded", reload_ssl_config); diff --git a/core/componentmanager.lua b/core/componentmanager.lua index cc505894..48e27984 100644 --- a/core/componentmanager.lua +++ b/core/componentmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/core/configmanager.lua b/core/configmanager.lua index 0f20fd3e..54fb0a9a 100644 --- a/core/configmanager.lua +++ b/core/configmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -112,7 +112,7 @@ do function parsers.lua.load(data, filename) local env; -- The ' = true' are needed so as not to set off __newindex when we assign the functions below - env = setmetatable({ Host = true; host = true; Component = true, component = true, + env = setmetatable({ Host = true, host = true, VirtualHost = true, Component = true, component = true, Include = true, include = true, RunScript = dofile }, { __index = function (t, k) return rawget(_G, k) or function (settings_table) @@ -124,7 +124,7 @@ do end}); rawset(env, "__currenthost", "*") -- Default is global - function env.Host(name) + function env.VirtualHost(name) if rawget(config, name) and rawget(config[name].core, "component_module") then error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s", name, config[name].core.component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0); @@ -133,7 +133,7 @@ do -- Needs at least one setting to logically exist :) set(name or "*", "core", "defined", true); end - env.host = env.Host; + env.Host, env.host = env.VirtualHost, env.VirtualHost; function env.Component(name) if rawget(config, name) and rawget(config[name].core, "defined") and not rawget(config[name].core, "component_module") then diff --git a/core/eventmanager.lua b/core/eventmanager.lua index e1cc9d2e..0e766c30 100644 --- a/core/eventmanager.lua +++ b/core/eventmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 7071296f..c8928b27 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -42,7 +42,7 @@ local function load_enabled_hosts(config) end if not activated_any_host then - log("error", "No hosts defined in the config file. This may cause unexpected behaviour as no modules will be loaded."); + log("error", "No active VirtualHost entries in the config file. This may cause unexpected behaviour as no modules will be loaded."); end eventmanager.fire_event("hosts-activated", defined_hosts); @@ -60,8 +60,8 @@ function activate(host, host_config) dialback_secret = configmanager.get(host, "core", "dialback_secret") or uuid_gen(); }; for option_name in pairs(host_config.core) do - if option_name:match("_ports$") then - log("warn", "%s: Option '%s' has no effect for virtual hosts - put it in global Host \"*\" instead", host, option_name); + if option_name:match("_ports$") or option_name:match("_interface$") then + log("warn", "%s: Option '%s' has no effect for virtual hosts - put it in the server-wide section instead", host, option_name); end end diff --git a/core/loggingmanager.lua b/core/loggingmanager.lua index 1bf90db1..3ec696d5 100644 --- a/core/loggingmanager.lua +++ b/core/loggingmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -33,9 +33,9 @@ _G.log = logger.init("general"); module "loggingmanager" -- The log config used if none specified in the config file -local default_logging = { { to = "console" } }; +local default_logging = { { to = "console" , levels = { min = (debug_mode and "debug") or "info" } } }; local default_file_logging = { { to = "file", levels = { min = (debug_mode and "debug") or "info" }, timestamps = true } }; -local default_timestamp = "%b %d %T"; +local default_timestamp = "%b %d %H:%M:%S"; -- The actual config loggingmanager is using local logging_config = config.get("*", "core", "log") or default_logging; diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 6b2260f5..8e62aecb 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -19,7 +19,7 @@ local pluginloader = require "util.pluginloader"; local hosts = hosts; local prosody = prosody; -local loadfile, pcall = loadfile, pcall; +local loadfile, pcall, xpcall = loadfile, pcall, xpcall; local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; local pairs, ipairs = pairs, ipairs; local t_insert, t_concat = table.insert, table.concat; @@ -29,6 +29,14 @@ local rawget = rawget; local error = error; local tostring, tonumber = tostring, tonumber; +local debug_traceback = debug.traceback; +local unpack, select = unpack, select; +pcall = function(f, ...) + local n = select("#", ...); + local params = {...}; + return xpcall(function() f(unpack(params, 1, n)) end, function(e) return tostring(e).."\n"..debug_traceback(); end); +end + local array, set = require "util.array", require "util.set"; local autoload_modules = {"presence", "message", "iq"}; @@ -158,7 +166,7 @@ function load(host, module_name, config) log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); end if success then - hosts[host].events.fire_event("module-loaded", { module = module_name, host = host }); + (hosts[api_instance.host] or prosody).events.fire_event("module-loaded", { module = module_name, host = host }); return true; else -- load failed, unloading unload(api_instance.host, module_name); @@ -210,7 +218,7 @@ function unload(host, name, ...) end end modulemap[host][name] = nil; - hosts[host].events.fire_event("module-unloaded", { module = name, host = host }); + (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); return true; end @@ -274,7 +282,7 @@ function handle_stanza(host, origin, stanza) (handlers[1])(origin, stanza); return true; else - if stanza.attr.xmlns == "jabber:client" then + if stanza.attr.xmlns == nil then log("debug", "Unhandled %s stanza: %s; xmlns=%s", origin.type, stanza.name, xmlns); -- we didn't handle it if stanza.attr.type ~= "error" and stanza.attr.type ~= "result" then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); diff --git a/core/offlinemanager.lua b/core/offlinemanager.lua index 37e93777..97781e82 100644 --- a/core/offlinemanager.lua +++ b/core/offlinemanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/core/rostermanager.lua b/core/rostermanager.lua index 516983a9..e2a92696 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -114,8 +114,14 @@ function save_roster(username, host, roster) --end end if roster then - if not roster[false] then roster[false] = {}; end - roster[false].version = (roster[false].version or 0) + 1; + local metadata = roster[false]; + if not metadata then + metadata = {}; + roster[false] = metadata; + end + if metadata.version ~= true then + metadata.version = (metadata.version or 0) + 1; + end return datamanager.store(username, host, "roster", roster); end log("warn", "save_roster: user had no roster to save"); diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 602d6837..ca87670a 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -16,8 +16,10 @@ local socket = require "socket"; local format = string.format; local t_insert, t_sort = table.insert, table.sort; local get_traceback = debug.traceback; -local tostring, pairs, ipairs, getmetatable, newproxy, error, tonumber - = tostring, pairs, ipairs, getmetatable, newproxy, error, tonumber; +local tostring, pairs, ipairs, getmetatable, newproxy, error, tonumber, + setmetatable + = tostring, pairs, ipairs, getmetatable, newproxy, error, tonumber, + setmetatable; local idna_to_ascii = require "util.encodings".idna.to_ascii; local connlisteners_get = require "net.connlisteners".get; @@ -48,7 +50,9 @@ local incoming_s2s = incoming_s2s; module "s2smanager" -local function compare_srv_priorities(a,b) return a.priority < b.priority or a.weight < b.weight; end +function compare_srv_priorities(a,b) + return a.priority < b.priority or (a.priority == b.priority and a.weight > b.weight); +end local function bounce_sendq(session, reason) local sendq = session.sendq; @@ -64,7 +68,7 @@ local function bounce_sendq(session, reason) for i, data in ipairs(sendq) do local reply = data[2]; local xmlns = reply.attr.xmlns; - if not xmlns or xmlns == "jabber:client" or xmlns == "jabber:server" then + if not xmlns then reply.attr.type = "error"; reply:tag("error", {type = "cancel"}) :tag("remote-server-not-found", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); @@ -87,7 +91,7 @@ function send_to_host(from_host, to_host, data) local host = hosts[from_host].s2sout[to_host]; if host then -- We have a connection to this host already - if host.type == "s2sout_unauthed" and (data.name ~= "db:verify" or not host.dialback_key) and ((not data.xmlns) or data.xmlns == "jabber:client" or data.xmlns == "jabber:server") then + if host.type == "s2sout_unauthed" and (data.name ~= "db:verify" or not host.dialback_key) then (host.log or log)("debug", "trying to send over unauthed s2sout to "..to_host); -- Queue stanza until we are able to send it @@ -301,7 +305,7 @@ function try_connect(host_session, connect_host, connect_port) end function make_connect(host_session, connect_host, connect_port) - host_session.log("info", "Beginning new connection attempt to %s (%s:%d)", host_session.to_host, connect_host, connect_port); + (host_session.log or log)("info", "Beginning new connection attempt to %s (%s:%d)", host_session.to_host, connect_host, connect_port); -- Ok, we're going to try to connect local from_host, to_host = host_session.from_host, host_session.to_host; @@ -365,11 +369,6 @@ function streamopened(session, attr) session.secure = true; end - if session.version >= 1.0 and not (attr.to and attr.from) then - (session.log or log)("warn", "Remote of stream "..(session.from_host or "(unknown)").."->"..(session.to_host or "(unknown)") - .." failed to specify to (%s) and/or from (%s) hostname as per RFC", tostring(attr.to), tostring(attr.from)); - end - if session.direction == "incoming" then -- Send a reply stream header session.to_host = attr.to and nameprep(attr.to); @@ -430,11 +429,8 @@ function streamopened(session, attr) end function streamclosed(session) - (session.log or log)("debug", "</stream:stream>"); - if session.sends2s then - session.sends2s("</stream:stream>"); - end - session.notopen = true; + (session.log or log)("debug", "Received </stream:stream>"); + session:close(); end function initiate_dialback(session) @@ -508,9 +504,32 @@ function mark_connected(session) end end -local function null_data_handler(conn, data) log("debug", "Discarding data from destroyed s2s session: %s", data); end +local resting_session = { -- Resting, not dead + destroyed = true; + type = "s2s_destroyed"; + open_stream = function (session) + session.log("debug", "Attempt to open stream on resting session"); + end; + close = function (session) + session.log("debug", "Attempt to close already-closed session"); + end; + }; resting_session.__index = resting_session; + +function retire_session(session) + local log = session.log or log; + for k in pairs(session) do + if k ~= "trace" and k ~= "log" and k ~= "id" then + session[k] = nil; + end + end + + function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); end + function session.data(data) log("debug", "Discarding data received from resting session: %s", tostring(data)); end + return setmetatable(session, resting_session); +end function destroy_session(session, reason) + if session.destroyed then return; end (session.log or log)("info", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host)); if session.direction == "outgoing" then @@ -520,12 +539,7 @@ function destroy_session(session, reason) incoming_s2s[session] = nil; end - for k in pairs(session) do - if k ~= "trace" then - session[k] = nil; - end - end - session.data = null_data_handler; + retire_session(session); -- Clean session until it is GC'd end return _M; diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 29adcfbb..6e771a84 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -8,7 +8,7 @@ -local tonumber, tostring = tonumber, tostring; +local tonumber, tostring, setmetatable = tonumber, tostring, setmetatable; local ipairs, pairs, print, next= ipairs, pairs, print, next; local format = import("string", "format"); @@ -66,10 +66,30 @@ function new_session(conn) return session; end -local function null_data_handler(conn, data) log("debug", "Discarding data from destroyed c2s session: %s", data); end +local resting_session = { -- Resting, not dead + destroyed = true; + type = "c2s_destroyed"; + close = function (session) + session.log("debug", "Attempt to close already-closed session"); + end; + }; resting_session.__index = resting_session; + +function retire_session(session) + local log = session.log or log; + for k in pairs(session) do + if k ~= "trace" and k ~= "log" and k ~= "id" then + session[k] = nil; + end + end + + function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); end + function session.data(data) log("debug", "Discarding data received from resting session: %s", tostring(data)); end + return setmetatable(session, resting_session); +end function destroy_session(session, err) (session.log or log)("info", "Destroying session for %s (%s@%s)", session.full_jid or "(unknown)", session.username or "(unknown)", session.host or "(unknown)"); + if session.destroyed then return; end -- Remove session/resource from user's session list if session.full_jid then @@ -85,12 +105,7 @@ function destroy_session(session, err) hosts[session.host].events.fire_event("resource-unbind", {session=session, error=err}); end - for k in pairs(session) do - if k ~= "trace" then - session[k] = nil; - end - end - session.data = null_data_handler; + retire_session(session); end function make_authenticated(session, username) @@ -168,7 +183,12 @@ end function streamopened(session, attr) local send = session.send; - session.host = attr.to or error("Client failed to specify destination hostname"); + session.host = attr.to; + if not session.host then + session:close{ condition = "improper-addressing", + text = "A 'to' attribute is required on stream headers" }; + return; + end session.host = nameprep(session.host); session.version = tonumber(attr.version) or 0; session.streamid = uuid_generate(); @@ -201,8 +221,8 @@ function streamopened(session, attr) end function streamclosed(session) - session.send("</stream:stream>"); - session.notopen = true; + session.log("debug", "Received </stream:stream>"); + session:close(); end function send_to_available_resources(user, host, stanza) diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 71e40681..d6dd5306 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -23,9 +23,6 @@ local bare_sessions = _G.prosody.bare_sessions; function core_process_stanza(origin, stanza) (origin.log or log)("debug", "Received[%s]: %s", origin.type, stanza:top_tag()) - -- Currently we guarantee every stanza to have an xmlns, should we keep this rule? - if not stanza.attr.xmlns then stanza.attr.xmlns = "jabber:client"; end - -- TODO verify validity of stanza (as well as JID validity) if stanza.attr.type == "error" and #stanza.tags == 0 then return; end -- TODO invalid stanza, log if stanza.name == "iq" then @@ -36,12 +33,14 @@ function core_process_stanza(origin, stanza) end end - if origin.type == "c2s" then + if origin.type == "c2s" and not stanza.attr.xmlns then if not origin.full_jid and not(stanza.name == "iq" and stanza.attr.type == "set" and stanza.tags[1] and stanza.tags[1].name == "bind" and stanza.tags[1].attr.xmlns == "urn:ietf:params:xml:ns:xmpp-bind") then -- authenticated client isn't bound and current stanza is not a bind request - origin.send(st.error_reply(stanza, "auth", "not-authorized")); -- FIXME maybe allow stanzas to account or server + if stanza.attr.type ~= "result" and stanza.attr.type ~= "error" then + origin.send(st.error_reply(stanza, "auth", "not-authorized")); -- FIXME maybe allow stanzas to account or server + end return; end @@ -90,7 +89,7 @@ function core_process_stanza(origin, stanza) return; -- FIXME what should we do here? end]] -- FIXME - if (origin.type == "s2sin" or origin.type == "c2s" or origin.type == "component") and xmlns == "jabber:client" then + if (origin.type == "s2sin" or origin.type == "c2s" or origin.type == "component") and xmlns == nil then if origin.type == "s2sin" and not origin.dummy then local host_status = origin.hosts[from_host]; if not host_status or not host_status.authed then -- remote server trying to impersonate some other server? @@ -103,14 +102,14 @@ function core_process_stanza(origin, stanza) local h = hosts[stanza.attr.to or origin.host or origin.to_host]; if h then local event; - if stanza.attr.xmlns == "jabber:client" then + if xmlns == nil then if stanza.name == "iq" and (stanza.attr.type == "set" or stanza.attr.type == "get") then event = "stanza/iq/"..stanza.tags[1].attr.xmlns..":"..stanza.tags[1].name; else event = "stanza/"..stanza.name; end else - event = "stanza/"..stanza.attr.xmlns..":"..stanza.name; + event = "stanza/"..xmlns..":"..stanza.name; end if h.events.fire_event(event, {origin = origin, stanza = stanza}) then return; end end @@ -140,6 +139,7 @@ function core_post_stanza(origin, stanza, preevents) to_type = '/host'; else to_type = '/bare'; + to_self = true; end end diff --git a/core/usermanager.lua b/core/usermanager.lua index 925ac774..42e49d38 100644 --- a/core/usermanager.lua +++ b/core/usermanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -14,11 +14,17 @@ local ipairs = ipairs; local hashes = require "util.hashes"; local jid_bare = require "util.jid".bare; local config = require "core.configmanager"; +local hosts = hosts; + +local require_provisioning = config.get("*", "core", "cyrus_require_provisioning") or false; module "usermanager" +local function is_cyrus(host) return config.get(host, "core", "sasl_backend") == "cyrus"; end + function validate_credentials(host, username, password, method) log("debug", "User '%s' is being validated", username); + if is_cyrus(host) then return nil, "Legacy auth not supported with Cyrus SASL."; end local credentials = datamanager.load(username, host, "accounts") or {}; if method == nil then method = "PLAIN"; end @@ -48,14 +54,26 @@ function validate_credentials(host, username, password, method) end function get_password(username, host) - return (datamanager.load(username, host, "accounts") or {}).password + if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end + return (datamanager.load(username, host, "accounts") or {}).password +end +function set_password(username, host, password) + if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end + local account = datamanager.load(username, host, "accounts"); + if account then + account.password = password; + return datamanager.store(username, host, "accounts", account); + end + return nil, "Account not available."; end function user_exists(username, host) + if not(require_provisioning) and is_cyrus(host) then return true; end return datamanager.load(username, host, "accounts") ~= nil; -- FIXME also check for empty credentials end function create_user(username, password, host) + if not(require_provisioning) and is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end return datamanager.store(username, host, "accounts", {password = password}); end diff --git a/core/xmlhandlers.lua b/core/xmlhandlers.lua index 77f00bea..b7992f77 100644 --- a/core/xmlhandlers.lua +++ b/core/xmlhandlers.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/fallbacks/bit.lua b/fallbacks/bit.lua index 75109d40..2482c473 100644 --- a/fallbacks/bit.lua +++ b/fallbacks/bit.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/man/prosodyctl.man b/man/prosodyctl.man index e677443f..6dcb04cd 100644 --- a/man/prosodyctl.man +++ b/man/prosodyctl.man @@ -49,6 +49,10 @@ will block for up to five seconds to wait for the server to execute. Stops the \fBprosody\fP server daemon. This operation will block for up to five seconds to wait for the server to stop executing. +.IP \fBrestart\fP +Restarts the \fBprosody\fP server daemon. Equivalent to running \fBprosodyctl +stop\fP followed by \fBprosodyctl start\fP. + .IP \fBstatus\fP Prints the current execution status of the \fBprosody\fP server daemon. @@ -76,4 +80,4 @@ determine if a host has been configured. More information may be found online at: \fIhttp://prosody.im/\fP .SH AUTHORS -Dwayne Bent <dbb.0@liqd.org> +Dwayne Bent <dbb.1@liqd.org> diff --git a/net/adns.lua b/net/adns.lua index 4341ffb5..88d4b4b3 100644 --- a/net/adns.lua +++ b/net/adns.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -49,16 +49,20 @@ function new_async_socket(sock, resolver) local listener = {}; local handler = {}; function listener.onincoming(conn, data) - dns.feed(handler, data); + if data then + dns.feed(handler, data); + end end function listener.ondisconnect(conn, err) - log("warn", "DNS socket for %s disconnected: %s", peername, err); - local servers = resolver.server; - if resolver.socketset[conn] == resolver.best_server and resolver.best_server == #servers then - log("error", "Exhausted all %d configured DNS servers, next lookup will try %s again", #servers, servers[1]); - end + if err then + log("warn", "DNS socket for %s disconnected: %s", peername, err); + local servers = resolver.server; + if resolver.socketset[conn] == resolver.best_server and resolver.best_server == #servers then + log("error", "Exhausted all %d configured DNS servers, next lookup will try %s again", #servers, servers[1]); + end - resolver:servfail(conn); -- Let the magic commence + resolver:servfail(conn); -- Let the magic commence + end end handler = server.wrapclient(sock, "dns", 53, listener); if not handler then diff --git a/net/connlisteners.lua b/net/connlisteners.lua index ee54f049..93dce8b3 100644 --- a/net/connlisteners.lua +++ b/net/connlisteners.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/net/dns.lua b/net/dns.lua index ca5f3c62..c0de97fd 100644 --- a/net/dns.lua +++ b/net/dns.lua @@ -532,14 +532,19 @@ function resolver:adddefaultnameservers() -- - - - - adddefaultnameservers if not self.server or #self.server == 0 then -- TODO log warning about no nameservers, adding opendns servers as fallback self:addnameserver("208.67.222.222"); - self:addnameserver("208.67.220.220") ; + self:addnameserver("208.67.220.220"); end else -- posix local resolv_conf = io.open("/etc/resolv.conf"); if resolv_conf then for line in resolv_conf:lines() do - local address = line:gsub("#.*$", ""):match('^%s*nameserver%s+(%d+%.%d+%.%d+%.%d+)%s*$'); - if address then self:addnameserver(address) end + line = line:gsub("#.*$", "") + :match('^%s*nameserver%s+(.*)%s*$'); + if line then + line:gsub("%f[%d.](%d+%.%d+%.%d+%.%d+)%f[^%d.]", function (address) + self:addnameserver(address) + end); + end end end if not self.server or #self.server == 0 then @@ -796,7 +801,7 @@ function resolver:feed(sock, packet) set(self.wanted, q.class, q.type, q.name, nil); end end - end + end return response; end @@ -846,7 +851,13 @@ end function resolver:lookup(qname, qtype, qclass) -- - - - - - - - - - lookup self:query (qname, qtype, qclass) - while self:pulse() do socket.select(self.socket, nil, 4); end + while self:pulse() do + local recvt = {} + for i, s in ipairs(self.socket) do + recvt[i] = s + end + socket.select(recvt, nil, 4) + end --print(self.cache); return self:peek(qname, qtype, qclass); end diff --git a/net/http.lua b/net/http.lua index 9b1954da..0634d773 100644 --- a/net/http.lua +++ b/net/http.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -17,11 +17,10 @@ local connlisteners_get = require "net.connlisteners".get; local listener = connlisteners_get("httpclient") or error("No httpclient listener!"); local t_insert, t_concat = table.insert, table.concat; -local tonumber, tostring, pairs, xpcall, select, debug_traceback, char, format = +local tonumber, tostring, pairs, xpcall, select, debug_traceback, char, format = tonumber, tostring, pairs, xpcall, select, debug.traceback, string.char, string.format; local log = require "util.logger".init("http"); -local print = function () end module "http" @@ -43,6 +42,7 @@ local function request_reader(request, data, startpos) elseif request.state ~= "completed" then -- Error.. connection was closed prematurely request.callback("connection-closed", 0, request); + return; end destroy_request(request); request.body = nil; @@ -50,7 +50,7 @@ local function request_reader(request, data, startpos) return; end if request.state == "body" and request.state ~= "completed" then - print("Reading body...") + log("debug", "Reading body...") if not request.body then request.body = {}; request.havebodylength, request.bodylength = 0, tonumber(request.responseheaders["content-length"]); end if startpos then data = data:sub(startpos, -1) @@ -67,42 +67,54 @@ local function request_reader(request, data, startpos) request.body = nil; request.state = "completed"; else - print("", "Have "..request.havebodylength.." bytes out of "..request.bodylength); + log("debug", "Have "..request.havebodylength.." bytes out of "..request.bodylength); end end elseif request.state == "headers" then - print("Reading headers...") + log("debug", "Reading headers...") local pos = startpos; - local headers = request.responseheaders or {}; + local headers, headers_complete = request.responseheaders; + if not headers then + headers = {}; + request.responseheaders = headers; + end for line in data:sub(startpos, -1):gmatch("(.-)\r\n") do startpos = startpos + #line + 2; local k, v = line:match("(%S+): (.+)"); if k and v then headers[k:lower()] = v; - print("Header: "..k:lower().." = "..v); + --log("debug", "Header: "..k:lower().." = "..v); elseif #line == 0 then - request.responseheaders = headers; + headers_complete = true; break; else - print("Unhandled header line: "..line); + log("warn", "Unhandled header line: "..line); end end + if not headers_complete then return; end -- Reached the end of the headers - request.state = "body"; + if not expectbody(request, request.code) then + request.callback(nil, request.code, request); + return; + end + request.state = "body"; if #data > startpos then return request_reader(request, data, startpos); end elseif request.state == "status" then - print("Reading status...") + log("debug", "Reading status...") local http, code, text, linelen = data:match("^HTTP/(%S+) (%d+) (.-)\r\n()", startpos); code = tonumber(code); if not code then - return request.callback("invalid-status-line", 0, request); + log("warn", "Invalid HTTP status line, telling callback then closing"); + local ret = request.callback("invalid-status-line", 0, request); + destroy_request(request); + return ret; end request.code, request.responseversion = code, http; - if request.onlystatus or not expectbody(request, code) then + if request.onlystatus then if request.callback then request.callback(nil, code, request); end @@ -199,8 +211,9 @@ end function destroy_request(request) if request.conn then - request.handler.close() - listener.ondisconnect(request.conn, "closed"); + request.conn = nil; + request.handler:close() + listener.ondisconnect(request.handler, "closed"); end end diff --git a/net/httpclient_listener.lua b/net/httpclient_listener.lua index 6517de44..dfa25062 100644 --- a/net/httpclient_listener.lua +++ b/net/httpclient_listener.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -30,7 +30,7 @@ end function httpclient.ondisconnect(conn, err) local request = requests[conn]; - if request then + if request and err ~= "closed" then request:reader(nil); end requests[conn] = nil; diff --git a/net/httpserver.lua b/net/httpserver.lua index 79705e6f..59ddbb12 100644 --- a/net/httpserver.lua +++ b/net/httpserver.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/net/httpserver_listener.lua b/net/httpserver_listener.lua index 6933b4fe..dd14b43c 100644 --- a/net/httpserver_listener.lua +++ b/net/httpserver_listener.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -29,7 +29,7 @@ function httpserver.onincoming(conn, data) end end - if data then + if data and data ~= "" then request_reader(request, data); end end diff --git a/net/server.lua b/net/server.lua index 0102cee6..e0d4b85a 100644 --- a/net/server.lua +++ b/net/server.lua @@ -1,3 +1,10 @@ +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- local use_luaevent = require "core.configmanager".get("*", "core", "use_libevent"); @@ -36,7 +43,6 @@ if use_luaevent then if type(signal_id) ~= "number" then return false, "invalid-signal"; end - --_signal_signal(signal_id, handler); return server.hook_signal(signal_id, handler); end end @@ -47,4 +53,4 @@ end -- require "net.server" shall now forever return this, -- ie. server_select or server_event as chosen above. -return server; +return server; diff --git a/net/server_event.lua b/net/server_event.lua index 8243a8a1..43e70a0f 100644 --- a/net/server_event.lua +++ b/net/server_event.lua @@ -20,14 +20,14 @@ local LAST_MODIFIED = "2009/11/20" local cfg = { MAX_CONNECTIONS = 100000, -- max per server connections (use "ulimit -n" on *nix) - MAX_HANDSHAKE_ATTEMPS = 10, -- attemps to finish ssl handshake - HANDSHAKE_TIMEOUT = 1, -- timout in seconds per handshake attemp + MAX_HANDSHAKE_ATTEMPS = 1000, -- attempts to finish ssl handshake + HANDSHAKE_TIMEOUT = 60, -- timout in seconds per handshake attempt MAX_READ_LENGTH = 1024 * 1024 * 1024 * 1024, -- max bytes allowed to read from sockets MAX_SEND_LENGTH = 1024 * 1024 * 1024 * 1024, -- max bytes size of write buffer (for writing on sockets) - ACCEPT_DELAY = 10, -- seconds to wait until the next attemp of a full server to accept - READ_TIMEOUT = 60 * 30, -- timeout in seconds for read data from socket - WRITE_TIMEOUT = 30, -- timeout in seconds for write data on socket - CONNECT_TIMEOUT = 10, -- timeout in seconds for connection attemps + ACCEPT_DELAY = 10, -- seconds to wait until the next attempt of a full server to accept + READ_TIMEOUT = 60 * 60 * 6, -- timeout in seconds for read data from socket + WRITE_TIMEOUT = 180, -- timeout in seconds for write data on socket + CONNECT_TIMEOUT = 20, -- timeout in seconds for connection attempts CLEAR_DELAY = 5, -- seconds to wait for clearing interface list (and calling ondisconnect listeners) DEBUG = true, -- show debug messages } @@ -160,8 +160,8 @@ do local callback = function( ) self:_lock( false, false, false ) --vdebug( "start listening on client socket with id:", self.id ) - self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ) -- register callback - self:onincoming() + self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ); -- register callback + self:onconnect() self.eventsession = nil return -1 end @@ -197,7 +197,7 @@ do local _, err local attempt = 0 local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPS - while attempt < 1000 do -- no endless loop + while attempt < maxattempt do -- no endless loop attempt = attempt + 1 debug( "ssl handshake of client with id:"..tostring(self).."attemp:"..attempt ) if attempt > maxattempt then @@ -262,7 +262,7 @@ do _ = self.eventsession and self.eventsession:close( ) _ = self.eventwritetimeout and self.eventwritetimeout:close( ) _ = self.eventreadtimeout and self.eventreadtimeout:close( ) - _ = self.ondisconnect and self:ondisconnect( self.fatalerror ) -- call ondisconnect listener (wont be the case if handshake failed on connect) + _ = self.ondisconnect and self:ondisconnect( self.fatalerror ~= "client to close" and self.fatalerror) -- call ondisconnect listener (wont be the case if handshake failed on connect) _ = self.conn and self.conn:close( ) -- close connection, must also be called outside of any socket registered events! _ = self._server and self._server:counter(-1); self.eventread, self.eventwrite = nil, nil @@ -281,6 +281,23 @@ do self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting return nointerface, noreading, nowriting end + + --TODO: Deprecate + function interface_mt:lock_read(switch) + if switch then + return self:pause(); + else + return self:resume(); + end + end + + function interface_mt:pause() + return self:_lock(self.nointerface, true, self.nowriting); + end + + function interface_mt:resume() + return self:_lock(self.nointerface, false, self.nowriting); + end function interface_mt:counter(c) if c then @@ -385,6 +402,13 @@ do self.starttls = false; -- prevent starttls() end end + + function interface_mt:set_mode(pattern) + if pattern then + self._pattern = pattern; + end + return self._pattern; + end function interface_mt:set_send(new_send) -- No-op, we always use the underlying connection's send @@ -433,6 +457,7 @@ do -- Stub handlers function interface_mt:onconnect() + return self:onincoming(nil); end function interface_mt:onincoming() end @@ -440,6 +465,8 @@ do end function interface_mt:ontimeout() end + function interface_mt:ondrain() + end function interface_mt:onstatus() debug("server.lua: Dummy onstatus()") end @@ -520,6 +547,7 @@ do if succ then -- writing succesful interface.writebuffer = "" interface.writebufferlen = 0 + interface:ondrain(); if interface.fatalerror then debug "closing client after writing" interface:_close() -- close interface if needed @@ -531,7 +559,7 @@ do end interface.eventwrite = nil return -1 - elseif byte then -- want write again + elseif byte and (err == "timeout" or err == "wantwrite") then -- want write again --vdebug( "writebuffer is not empty:", err ) interface.writebuffer = string_sub( interface.writebuffer, byte + 1, interface.writebufferlen ) -- new buffer interface.writebufferlen = interface.writebufferlen - byte @@ -539,7 +567,7 @@ do local callback = function( ) interface:_close() interface.eventwritetimeout = nil - return evreturn, evtimeout + return -1; end interface.eventwritetimeout = addevent( base, nil, EV_TIMEOUT, callback, cfg.WRITE_TIMEOUT ) -- reg a new timeout event debug( "wantread during write attemp, reg it in readcallback but dont know what really happens next..." ) @@ -581,7 +609,7 @@ do interface.eventreadtimeout = nil end end - local buffer, err, part = interface.conn:receive( pattern ) -- receive buffer with "pattern" + local buffer, err, part = interface.conn:receive( interface._pattern ) -- receive buffer with "pattern" --vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) ) buffer = buffer or part or "" local len = string_len( buffer ) @@ -667,16 +695,16 @@ do debug( "maximal connections reached, refuse client connection; accept delay:", delay ) return EV_TIMEOUT, delay -- delay for next accept attemp end - local ip, port = client:getpeername( ) + local client_ip, client_port = client:getpeername( ) interface._connections = interface._connections + 1 -- increase connection count - local clientinterface = handleclient( client, ip, port, interface, pattern, listener, nil, sslctx ) + local clientinterface = handleclient( client, client_ip, client_port, interface, pattern, listener, nil, sslctx ) --vdebug( "client id:", clientinterface, "startssl:", startssl ) if ssl and sslctx then clientinterface:starttls(sslctx) else clientinterface:_start_session( clientinterface.onconnect ) end - debug( "accepted incoming client connection from:", ip, port ) + debug( "accepted incoming client connection from:", client_ip or "<unknown IP>", client_port or "<unknown port>", "to", port or "<unknown port>"); client, err = server:accept() -- try to accept again end @@ -758,7 +786,7 @@ do local server = function( ) return nil, "this is a dummy server interface" end - local interface = wrapclient( client, ip, serverport, listeners, pattern, sslctx, startssl ) + local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx, startssl ) interface:_start_connection( startssl ) debug( "new connection id:", interface.id ) return interface, err @@ -817,11 +845,32 @@ function hook_signal(signal_num, handler) return signal_events[signal_num]; end +local function link(sender, receiver, buffersize) + sender:set_mode(buffersize); + local sender_locked; + + function receiver:ondrain() + if sender_locked then + sender:resume(); + sender_locked = nil; + end + end + + function sender:onincoming(data) + receiver:write(data); + if receiver.writebufferlen >= buffersize then + sender_locked = true; + sender:pause(); + end + end +end + return { cfg = cfg, base = base, loop = loop, + link = link, event = event, event_base = base, addevent = newevent, diff --git a/net/server_select.lua b/net/server_select.lua index 685cd13e..e3a389a8 100644 --- a/net/server_select.lua +++ b/net/server_select.lua @@ -2,7 +2,7 @@ -- server.lua by blastbeat of the luadch project -- Re-used here under the MIT/X Consortium License -- --- Modifications (C) 2008-2009 Matthew Wild, Waqas Hussain +-- Modifications (C) 2008-2010 Matthew Wild, Waqas Hussain -- -- // wrapping luadch stuff // -- @@ -252,6 +252,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local dispatch = listeners.onincoming local status = listeners.onstatus local disconnect = listeners.ondisconnect + local drain = listeners.ondrain local bufferqueue = { } -- buffer array local bufferqueuelen = 0 -- end of buffer array @@ -284,6 +285,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport dispatch = listeners.onincoming disconnect = listeners.ondisconnect status = listeners.onstatus + drain = listeners.ondrain end handler.getstats = function( ) return readtraffic, sendtraffic @@ -379,7 +381,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport handler.socket = function( self ) return socket end - handler.pattern = function( self, new ) + handler.set_mode = function( self, new ) pattern = new or pattern return pattern end @@ -392,6 +394,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport maxreadlen = readlen or maxreadlen return bufferlen, maxreadlen, maxsendlen end + --TODO: Deprecate handler.lock_read = function (self, switch) if switch == true then local tmp = _readlistlen @@ -409,6 +412,12 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport end return noread end + handler.pause = function (self) + return self:lock_read(true); + end + handler.resume = function (self) + return self:lock_read(false); + end handler.lock = function( self, switch ) handler.lock_read (switch) if switch == true then @@ -430,12 +439,12 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport end local _readbuffer = function( ) -- this function reads data local buffer, err, part = receive( socket, pattern ) -- receive buffer with "pattern" - if not err or (err == "wantread" or err == "timeout") or string_len(part) > 0 then -- received something + if not err or (err == "wantread" or err == "timeout") then -- received something local buffer = buffer or part or "" local len = string_len( buffer ) if len > maxreadlen then disconnect( handler, "receive buffer exceeded" ) - handler.close( true ) + handler:close( true ) return false end local count = len * STAT_UNIT @@ -448,7 +457,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) - _ = handler and handler.close( ) + _ = handler and handler:close( ) return false end end @@ -472,7 +481,10 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) -- delete socket from writelist _ = needtls and handler:starttls(nil, true) _writetimes[ handler ] = nil - _ = toclose and handler.close( ) + if drain then + drain(handler) + end + _ = toclose and handler:close( ) return true elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer @@ -485,7 +497,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) - _ = handler and handler.close( ) + _ = handler and handler:close( ) return false end end @@ -611,7 +623,16 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport _socketlist[ socket ] = handler _readlistlen = addsocket(_readlist, socket, _readlistlen) - + if listeners.onconnect then + _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) + handler.sendbuffer = function () + listeners.onconnect(handler); + handler.sendbuffer = _sendbuffer; + if bufferqueuelen > 0 then + return _sendbuffer(); + end + end + end return handler, socket end @@ -654,6 +675,28 @@ closesocket = function( socket ) --mem_free( ) end +local function link(sender, receiver, buffersize) + sender:set_mode(buffersize); + local sender_locked; + local _sendbuffer = receiver.sendbuffer; + function receiver.sendbuffer() + _sendbuffer(); + if sender_locked and receiver.bufferlen() < buffersize then + sender:lock_read(false); -- Unlock now + sender_locked = nil; + end + end + + local _readbuffer = sender.readbuffer; + function sender.readbuffer() + _readbuffer(); + if not sender_locked and receiver.bufferlen() >= buffersize then + sender_locked = true; + sender:lock_read(true); + end + end +end + ----------------------------------// PUBLIC //-- addserver = function( addr, port, listeners, pattern, sslctx ) -- this function provides a way for other scripts to reg a server @@ -661,7 +704,7 @@ addserver = function( addr, port, listeners, pattern, sslctx ) -- this function if type( listeners ) ~= "table" then err = "invalid listener table" end - if not type( port ) == "number" or not ( port >= 0 and port <= 65535 ) then + if type( port ) ~= "number" or not ( port >= 0 and port <= 65535 ) then err = "invalid port" elseif _server[ port ] then err = "listeners on port '" .. port .. "' already exist" @@ -877,6 +920,7 @@ return { wrapclient = wrapclient, loop = loop, + link = link, stats = stats, closeall = closeall, addtimer = addtimer, diff --git a/net/xmppclient_listener.lua b/net/xmppclient_listener.lua index 3a0c65be..94daa2b2 100644 --- a/net/xmppclient_listener.lua +++ b/net/xmppclient_listener.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -33,13 +33,32 @@ local opt_keepalives = config.get("*", "core", "tcp_keepalives"); local stream_callbacks = { default_ns = "jabber:client", streamopened = sm_streamopened, streamclosed = sm_streamclosed, handlestanza = core_process_stanza }; +local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams"; + function stream_callbacks.error(session, error, data) if error == "no-stream" then session.log("debug", "Invalid opening stream header"); session:close("invalid-namespace"); - elseif session.close then - (session.log or log)("debug", "Client XML parse error: %s", tostring(error)); + elseif error == "parse-error" then + (session.log or log)("debug", "Client XML parse error: %s", tostring(data)); session:close("xml-not-well-formed"); + elseif error == "stream-error" then + local condition, text = "undefined-condition"; + for child in data:children() do + if child.attr.xmlns == xmlns_xmpp_streams then + if child.name ~= "text" then + condition = child.name; + else + text = child:get_text(); + end + if condition ~= "undefined-condition" and text then + break; + end + end + end + text = condition .. (text and (" ("..text..")") or ""); + session.log("info", "Session closed by remote with error: %s", text); + session:close(nil, text); end end diff --git a/net/xmppcomponent_listener.lua b/net/xmppcomponent_listener.lua index 0b98b6bc..b87f7c96 100644 --- a/net/xmppcomponent_listener.lua +++ b/net/xmppcomponent_listener.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -34,16 +34,33 @@ local xmlns_component = 'jabber:component:accept'; local stream_callbacks = { default_ns = xmlns_component }; +local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams"; + function stream_callbacks.error(session, error, data, data2) + if session.destroyed then return; end log("warn", "Error processing component stream: "..tostring(error)); if error == "no-stream" then session:close("invalid-namespace"); - elseif error == "xml-parse-error" and data == "unexpected-element-close" then - session.log("warn", "Unexpected close of '%s' tag", data2); - session:close("xml-not-well-formed"); - else - session.log("warn", "External component %s XML parse error: %s", tostring(session.host), tostring(error)); + elseif error == "parse-error" then + session.log("warn", "External component %s XML parse error: %s", tostring(session.host), tostring(data)); session:close("xml-not-well-formed"); + elseif error == "stream-error" then + local condition, text = "undefined-condition"; + for child in data:children() do + if child.attr.xmlns == xmlns_xmpp_streams then + if child.name ~= "text" then + condition = child.name; + else + text = child:get_text(); + end + if condition ~= "undefined-condition" and text then + break; + end + end + end + text = condition .. (text and (" ("..text..")") or ""); + session.log("info", "Session closed by remote with error: %s", text); + session:close(nil, text); end end @@ -71,8 +88,8 @@ function stream_callbacks.streamopened(session, attr) end function stream_callbacks.streamclosed(session) - session.send("</stream:stream>"); - session.notopen = true; + session.log("Received </stream:stream>"); + session:close(); end local core_process_stanza = core_process_stanza; @@ -89,6 +106,7 @@ end local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'}; local default_stream_attr = { ["xmlns:stream"] = "http://etherx.jabber.org/streams", xmlns = stream_callbacks.default_ns, version = "1.0", id = "" }; local function session_close(session, reason) + if session.destroyed then return; end local log = session.log or log; if session.conn then if session.notopen then @@ -146,6 +164,7 @@ function component_listener.onincoming(conn, data) function session.data(conn, data) local ok, err = parser:parse(data); if ok then return; end + log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_")); session:close("xml-not-well-formed"); end @@ -167,7 +186,12 @@ function component_listener.ondisconnect(conn, err) hosts[session.host].connected = nil; end sessions[conn] = nil; - for k in pairs(session) do session[k] = nil; end + for k in pairs(session) do + if k ~= "log" and k ~= "close" then + session[k] = nil; + end + end + session.destroyed = true; session = nil; end end diff --git a/net/xmppserver_listener.lua b/net/xmppserver_listener.lua index c9746ee1..d1272edb 100644 --- a/net/xmppserver_listener.lua +++ b/net/xmppserver_listener.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -50,6 +50,9 @@ end local function handleerr(err) log("error", "Traceback[s2s]: %s: %s", tostring(err), debug.traceback()); end function stream_callbacks.handlestanza(a, b) + if b.attr.xmlns == "jabber:client" then --COMPAT: Prosody pre-0.6.2 may send jabber:client + b.attr.xmlns = nil; + end xpcall(function () core_process_stanza(a, b) end, handleerr); end @@ -176,7 +179,7 @@ function xmppserver.ondisconnect(conn, err) return; -- Session lives for now end end - (session.log or log)("info", "s2s disconnected: %s->%s (%s)", tostring(session.from_host), tostring(session.to_host), tostring(err)); + (session.log or log)("info", "s2s disconnected: %s->%s (%s)", tostring(session.from_host), tostring(session.to_host), tostring(err or "closed")); s2s_destroy_session(session, err); sessions[conn] = nil; session = nil; diff --git a/plugins/mod_announce.lua b/plugins/mod_announce.lua index 118ba13d..7f08a6e0 100644 --- a/plugins/mod_announce.lua +++ b/plugins/mod_announce.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua index 2cb3100e..66a79785 100644 --- a/plugins/mod_bosh.lua +++ b/plugins/mod_bosh.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -23,7 +23,7 @@ local logger = require "util.logger"; local log = logger.init("mod_bosh"); local xmlns_bosh = "http://jabber.org/protocol/httpbind"; -- (hard-coded into a literal in session.send) -local stream_callbacks = { stream_ns = "http://jabber.org/protocol/httpbind", stream_tag = "body", default_ns = xmlns_bosh }; +local stream_callbacks = { stream_ns = "http://jabber.org/protocol/httpbind", stream_tag = "body", default_ns = "jabber:client" }; local BOSH_DEFAULT_HOLD = tonumber(module:get_option("bosh_default_hold")) or 1; local BOSH_DEFAULT_INACTIVITY = tonumber(module:get_option("bosh_max_inactivity")) or 60; @@ -31,6 +31,8 @@ local BOSH_DEFAULT_POLLING = tonumber(module:get_option("bosh_max_polling")) or local BOSH_DEFAULT_REQUESTS = tonumber(module:get_option("bosh_max_requests")) or 2; local BOSH_DEFAULT_MAXPAUSE = tonumber(module:get_option("bosh_max_pause")) or 300; +local consider_bosh_secure = module:get_option_boolean("consider_bosh_secure"); + local default_headers = { ["Content-Type"] = "text/xml; charset=utf-8" }; local session_close_reply = { headers = default_headers, body = st.stanza("body", { xmlns = xmlns_bosh, type = "terminate" }), attr = {} }; @@ -63,8 +65,11 @@ function on_destroy_request(request) local session = sessions[request.sid]; if session then local requests = session.requests; - for i,r in pairs(requests) do - if r == request then requests[i] = nil; break; end + for i,r in ipairs(requests) do + if r == request then + t_remove(requests, i); + break; + end end -- If this session now has no requests open, mark it as inactive @@ -90,6 +95,8 @@ function handle_request(method, body, request) --log("debug", "Handling new request %s: %s\n----------", request.id, tostring(body)); request.notopen = true; request.log = log; + request.on_destroy = on_destroy_request; + local parser = lxp.new(init_xmlhandlers(request, stream_callbacks), "\1"); parser:parse(body); @@ -118,14 +125,21 @@ function handle_request(method, body, request) session.send(resp); end - if not request.destroyed and session.bosh_wait then - request.reply_before = os_time() + session.bosh_wait; - request.on_destroy = on_destroy_request; - waiting_requests[request] = true; + if not request.destroyed then + -- We're keeping this request open, to respond later + log("debug", "Have nothing to say, so leaving request unanswered for now"); + if session.bosh_wait then + request.reply_before = os_time() + session.bosh_wait; + waiting_requests[request] = true; + end + if inactive_sessions[session] then + -- Session was marked as inactive, since we have + -- a request open now, unmark it + inactive_sessions[session] = nil; + end end - log("debug", "Have nothing to say, so leaving request unanswered for now"); - return true; + return true; -- Inform httpserver we shall reply later end end @@ -162,10 +176,14 @@ function stream_callbacks.streamopened(request, attr) -- New session sid = new_uuid(); - local session = { type = "c2s_unauthed", conn = {}, sid = sid, rid = tonumber(attr.rid), host = attr.to, bosh_version = attr.ver, bosh_wait = attr.wait, streamid = sid, - bosh_hold = BOSH_DEFAULT_HOLD, bosh_max_inactive = BOSH_DEFAULT_INACTIVITY, - requests = { }, send_buffer = {}, reset_stream = bosh_reset_stream, close = bosh_close_stream, - dispatch_stanza = core_process_stanza, log = logger.init("bosh"..sid), secure = request.secure }; + local session = { + type = "c2s_unauthed", conn = {}, sid = sid, rid = tonumber(attr.rid)-1, host = attr.to, + bosh_version = attr.ver, bosh_wait = attr.wait, streamid = sid, + bosh_hold = BOSH_DEFAULT_HOLD, bosh_max_inactive = BOSH_DEFAULT_INACTIVITY, + requests = { }, send_buffer = {}, reset_stream = bosh_reset_stream, + close = bosh_close_stream, dispatch_stanza = core_process_stanza, + log = logger.init("bosh"..sid), secure = consider_bosh_secure or request.secure + }; sessions[sid] = session; log("info", "New BOSH session, assigned it sid '%s'", sid); @@ -174,11 +192,6 @@ function stream_callbacks.streamopened(request, attr) function session.send(s) --log("debug", "Sending BOSH data: %s", tostring(s)); local oldest_request = r[1]; - while oldest_request and oldest_request.destroyed do - t_remove(r, 1); - waiting_requests[oldest_request] = nil; - oldest_request = r[1]; - end if oldest_request then log("debug", "We have an open request, so sending on that"); response.body = t_concat{"<body xmlns='http://jabber.org/protocol/httpbind' sid='", sid, "' xmlns:stream = 'http://etherx.jabber.org/streams'>", tostring(s), "</body>" }; @@ -193,7 +206,6 @@ function stream_callbacks.streamopened(request, attr) else log("debug", "Destroying the request now..."); oldest_request:destroy(); - t_remove(r, 1); end elseif s ~= "" then log("debug", "Saved to send buffer because there are %d open requests", #r); @@ -235,8 +247,9 @@ function stream_callbacks.streamopened(request, attr) session.log("warn", "rid too large (means a request was lost). Last rid: %d New rid: %s", session.rid, attr.rid); elseif diff <= 0 then -- Repeated, ignore - session.log("debug", "rid repeated (on request %s), ignoring: %d", request.id, session.rid); + session.log("debug", "rid repeated (on request %s), ignoring: %s (diff %d)", request.id, session.rid, diff); request.notopen = nil; + request.sid = sid; t_insert(session.requests, request); return; end @@ -250,12 +263,6 @@ function stream_callbacks.streamopened(request, attr) return; end - -- If session was inactive, make sure it is now marked as not - if #session.requests == 0 then - (session.log or log)("debug", "BOSH client now active again at %d", os_time()); - inactive_sessions[session] = nil; - end - if session.notopen then local features = st.stanza("stream:features"); hosts[session.host].events.fire_event("stream-features", { origin = session, features = features }); @@ -274,7 +281,7 @@ function stream_callbacks.handlestanza(request, stanza) local session = sessions[request.sid]; if session then if stanza.attr.xmlns == xmlns_bosh then - stanza.attr.xmlns = "jabber:client"; + stanza.attr.xmlns = nil; end session.ip = request.handler:ip(); core_process_stanza(session, stanza); diff --git a/plugins/mod_component.lua b/plugins/mod_component.lua index d9783b0c..7efb4f9c 100644 --- a/plugins/mod_component.lua +++ b/plugins/mod_component.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_compression.lua b/plugins/mod_compression.lua index 4b1fa79f..c2e84f2b 100644 --- a/plugins/mod_compression.lua +++ b/plugins/mod_compression.lua @@ -8,6 +8,8 @@ local st = require "util.stanza"; local zlib = require "zlib"; local pcall = pcall; +local tostring = tostring; + local xmlns_compression_feature = "http://jabber.org/features/compress" local xmlns_compression_protocol = "http://jabber.org/protocol/compress" local xmlns_stream = "http://etherx.jabber.org/streams"; @@ -71,7 +73,7 @@ local function get_deflate_stream(session) local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"); (session.sends2s or session.send)(error_st); session.log("error", "Failed to create zlib.deflate filter."); - module:log("error", deflate_stream); + module:log("error", "%s", tostring(deflate_stream)); return end return deflate_stream @@ -83,8 +85,8 @@ local function get_inflate_stream(session) if status == false then local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"); (session.sends2s or session.send)(error_st); - session.log("error", "Failed to create zlib.deflate filter."); - module:log("error", inflate_stream); + session.log("error", "Failed to create zlib.inflate filter."); + module:log("error", "%s", tostring(inflate_stream)); return end return inflate_stream @@ -104,7 +106,7 @@ local function setup_compression(session, deflate_stream) text = compressed; extra = st.stanza("failure", {xmlns="http://jabber.org/protocol/compress"}):tag("processing-failed"); }); - module:log("warn", compressed); + module:log("warn", "%s", tostring(compressed)); return; end session.conn:write(compressed); @@ -125,7 +127,7 @@ local function setup_decompression(session, inflate_stream) text = decompressed; extra = st.stanza("failure", {xmlns="http://jabber.org/protocol/compress"}):tag("processing-failed"); }); - module:log("warn", decompressed); + module:log("warn", "%s", tostring(decompressed)); return; end old_data(conn, decompressed); @@ -166,15 +168,17 @@ module:add_handler({"c2s_unauthed", "c2s", "s2sin_unauthed", "s2sin"}, "compress function(session, stanza) -- fail if we are already compressed if session.compressed then - local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("unsupported-method"); + local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"); (session.sends2s or session.send)(error_st); - session.log("warn", "Tried to establish another compression layer."); + session.log("debug", "Client tried to establish another compression layer."); + return; end -- checking if the compression method is supported - local method = stanza:child_with_name("method")[1]; + local method = stanza:child_with_name("method"); + method = method and (method[1] or ""); if method == "zlib" then - session.log("debug", method.." compression selected."); + session.log("debug", "zlib compression enabled."); -- create deflate and inflate streams local deflate_stream = get_deflate_stream(session); @@ -199,10 +203,12 @@ module:add_handler({"c2s_unauthed", "c2s", "s2sin_unauthed", "s2sin"}, "compress return true; end; session.compressed = true; - else - session.log("warn", method.." compression selected. But we don't support it."); + elseif method then + session.log("debug", "%s compression selected, but we don't support it.", tostring(method)); local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("unsupported-method"); (session.sends2s or session.send)(error_st); + else + (session.sends2s or session.send)(st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed")); end end ); diff --git a/plugins/mod_console.lua b/plugins/mod_console.lua index 6d387b0e..e87ef536 100644 --- a/plugins/mod_console.lua +++ b/plugins/mod_console.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -53,76 +53,78 @@ end local sessions = {}; +function console_listener.onconnect(conn) + -- Handle new connection + local session = console:new_session(conn); + sessions[conn] = session; + printbanner(session); + session.send(string.char(0)); +end + function console_listener.onincoming(conn, data) local session = sessions[conn]; - - if not session then - -- Handle new connection - session = console:new_session(conn); - sessions[conn] = session; - printbanner(session); - end - if data then - -- Handle data - (function(session, data) - local useglobalenv; - - if data:match("^>") then - data = data:gsub("^>", ""); - useglobalenv = true; - elseif data == "\004" then - commands["bye"](session, data); + + -- Handle data + (function(session, data) + local useglobalenv; + + if data:match("^>") then + data = data:gsub("^>", ""); + useglobalenv = true; + elseif data == "\004" then + commands["bye"](session, data); + return; + else + local command = data:lower(); + command = data:match("^%w+") or data:match("%p"); + if commands[command] then + commands[command](session, data); return; - else - local command = data:lower(); - command = data:match("^%w+") or data:match("%p"); - if commands[command] then - commands[command](session, data); - return; - end end + end - session.env._ = data; - - local chunk, err = loadstring("return "..data); + session.env._ = data; + + local chunkname = "=console"; + local chunk, err = loadstring("return "..data, chunkname); + if not chunk then + chunk, err = loadstring(data, chunkname); if not chunk then - chunk, err = loadstring(data); - if not chunk then - err = err:gsub("^%[string .-%]:%d+: ", ""); - err = err:gsub("^:%d+: ", ""); - err = err:gsub("'<eof>'", "the end of the line"); - session.print("Sorry, I couldn't understand that... "..err); - return; - end - end - - setfenv(chunk, (useglobalenv and redirect_output(_G, session)) or session.env or nil); - - local ranok, taskok, message = pcall(chunk); - - if not (ranok or message or useglobalenv) and commands[data:lower()] then - commands[data:lower()](session, data); - return; - end - - if not ranok then - session.print("Fatal error while running command, it did not complete"); - session.print("Error: "..taskok); - return; - end - - if not message then - session.print("Result: "..tostring(taskok)); - return; - elseif (not taskok) and message then - session.print("Command completed with a problem"); - session.print("Message: "..tostring(message)); + err = err:gsub("^%[string .-%]:%d+: ", ""); + err = err:gsub("^:%d+: ", ""); + err = err:gsub("'<eof>'", "the end of the line"); + session.print("Sorry, I couldn't understand that... "..err); return; end - - session.print("OK: "..tostring(message)); - end)(session, data); - end + end + + setfenv(chunk, (useglobalenv and redirect_output(_G, session)) or session.env or nil); + + local ranok, taskok, message = pcall(chunk); + + if not (ranok or message or useglobalenv) and commands[data:lower()] then + commands[data:lower()](session, data); + return; + end + + if not ranok then + session.print("Fatal error while running command, it did not complete"); + session.print("Error: "..taskok); + return; + end + + if not message then + session.print("Result: "..tostring(taskok)); + return; + elseif (not taskok) and message then + session.print("Command completed with a problem"); + session.print("Message: "..tostring(message)); + return; + end + + session.print("OK: "..tostring(message)); + end)(session, data); + session.send(string.char(0)); end @@ -192,7 +194,7 @@ function commands.help(session, data) elseif section == "server" then print [[server:version() - Show the server's version number]] print [[server:uptime() - Show how long the server has been running]] - --print [[server:shutdown(reason) - Shut down the server, with an optional reason to be broadcast to all connections]] + print [[server:shutdown(reason) - Shut down the server, with an optional reason to be broadcast to all connections]] elseif section == "config" then print [[config:reload() - Reload the server configuration. Modules may need to be reloaded for changes to take effect.]] elseif section == "console" then diff --git a/plugins/mod_debug.lua b/plugins/mod_debug.lua deleted file mode 100644 index 9f80202f..00000000 --- a/plugins/mod_debug.lua +++ /dev/null @@ -1,191 +0,0 @@ --- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain --- --- This project is MIT/X11 licensed. Please see the --- COPYING file in the source package for more information. --- - -module.host = "*"; - -local connlisteners_register = require "net.connlisteners".register; - -local console_listener = { default_port = 5583; default_mode = "*l"; default_interface = "127.0.0.1" }; - -local sha256, missingglobal = require "util.hashes".sha256; - -local commands = {}; -local debug_env = {}; -local debug_env_mt = { __index = function (t, k) return rawget(_G, k) or missingglobal(k); end, __newindex = function (t, k, v) rawset(_G, k, v); end }; - -local t_insert, t_concat = table.insert, table.concat; -local t_concatall = function (t, sep) local tt = {}; for k, s in pairs(t) do tt[k] = tostring(s); end return t_concat(tt, sep); end - - -setmetatable(debug_env, debug_env_mt); - -console = {}; - -function console:new_session(conn) - local w = function(s) conn.write(s:gsub("\n", "\r\n")); end; - local session = { conn = conn; - send = function (t) w(tostring(t)); end; - print = function (t) w("| "..tostring(t).."\n"); end; - disconnect = function () conn.close(); end; - }; - - return session; -end - -local sessions = {}; - -function console_listener.listener(conn, data) - local session = sessions[conn]; - - if not session then - -- Handle new connection - session = console:new_session(conn); - sessions[conn] = session; - printbanner(session); - end - if data then - -- Handle data - (function(session, data) - if data:match("[!.]$") then - local command = data:lower(); - command = data:match("^%w+") or data:match("%p"); - if commands[command] then - commands[command](session, data); - return; - end - end - - local chunk, err = loadstring("return "..data); - if not chunk then - chunk, err = loadstring(data); - if not chunk then - err = err:gsub("^%[string .-%]:%d+: ", ""); - err = err:gsub("^:%d+: ", ""); - err = err:gsub("'<eof>'", "the end of the line"); - session.print("Sorry, I couldn't understand that... "..err); - return; - end - end - - debug_env.print = session.print; - - setfenv(chunk, debug_env); - - local ret = { pcall(chunk) }; - - if not ret[1] then - session.print("Fatal error while running command, it did not complete"); - session.print("Error: "..ret[2]); - return; - end - - table.remove(ret, 1); - - local retstr = t_concatall(ret, ", "); - if retstr ~= "" then - session.print("Result: "..retstr); - else - session.print("No result, or nil"); - return; - end - end)(session, data); - end - session.send(string.char(0)); -end - -function console_listener.disconnect(conn, err) - -end - -connlisteners_register('debug', console_listener); -require "net.connlisteners".start("debug"); - --- Console commands -- --- These are simple commands, not valid standalone in Lua - -function commands.bye(session) - session.print("See you! :)"); - session.disconnect(); -end - -commands["!"] = function (session, data) - if data:match("^!!") then - session.print("!> "..session.env._); - return console_listener.listener(session.conn, session.env._); - end - local old, new = data:match("^!(.-[^\\])!(.-)!$"); - if old and new then - local ok, res = pcall(string.gsub, session.env._, old, new); - if not ok then - session.print(res) - return; - end - session.print("!> "..res); - return console_listener.listener(session.conn, res); - end - session.print("Sorry, not sure what you want"); -end - -function printbanner(session) -session.print [[ - ____ \ / _ - | _ \ _ __ ___ ___ _-_ __| |_ _ - | |_) | '__/ _ \/ __|/ _ \ / _` | | | | - | __/| | | (_) \__ \ |_| | (_| | |_| | - |_| |_| \___/|___/\___/ \__,_|\__, | - A study in simplicity |___/ - -]] -session.print("Welcome to the Prosody debug console. For a list of commands, type: help"); -session.print("You may find more help on using this console in our online documentation at "); -session.print("http://prosody.im/doc/debugconsole\n"); -end - -local byte, char = string.byte, string.char; -local gmatch, gsub = string.gmatch, string.gsub; - -local function vdecode(text, key) - local keyarr = {}; - for l in gmatch(key, ".") do t_insert(keyarr, byte(l) - 32) end - local pos, keylen = 0, #keyarr; - return (gsub(text, ".", function (letter) - if byte(letter) < 32 then return ""; end - pos = (pos%keylen)+1; - return char(((byte(letter) - 32 - keyarr[pos]) % 94) + 32); - end)); -end - -local subst = { - ["f880c08056ba7dbecb1ccfe5d7728bd6dcd654e94f7a9b21788c43397bae0bc5"] = - [=[nRYeKR$l'5Ix%u*1Mc-K}*bwv*\ $1KLMBd$KH R38`$[6}VQ@,6Qn]=]; - ["92f718858322157202ec740698c1390e47bc819e52b6a099c54c378a9f7529d6"] = - [=[V\Z5`WZ5,T$<)7LM'w3Z}M(7V'{pa) &'>0+{v)O(0M*V5K$$LL$|2wT}6 - 1as*")e!>]=]; - ["467b65edcc7c7cd70abf2136cc56abd037216a6cd9e17291a2219645be2e2216"] = - [=[i#'Z,E1-"YaHW(j/0xs]I4x&%(Jx1h&18'(exNWT D3b+K{*8}w(%D {]=]; - ["f73729d7f2fbe686243a25ac088c7e6aead3d535e081329f2817438a5c78bee5"] = - [=[,3+(Q{3+W\ftQ%wvv/C0z-l%f>ABc(vkp<bb8]=]; - ["6afa189489b096742890d0c5bd17d5bb8af8ac460c7026984b64e8f14a40404e"] = - [=[9N{)5j34gd*}&]H&dy"I&7(",a F1v6jY+IY7&S+86)1z(Vo]=]; - ["cc5e5293ef8a1acbd9dd2bcda092c5c77ef46d3ec5aea65024fca7ed4b3c94a9"] = - [=[_]Rc}IF'Kfa&))Ry+6|x!K2|T*Vze)%4Hwz'L3uI|OwIa)|q#uq2+Qu u7 - [V3(z(*TYY|T\1_W'2] Dwr{-{@df#W.H5^x(ydtr{c){UuV@]=]; - ["b3df231fd7ddf73f72f39cb2510b1fe39318f4724728ed58948a180663184d3e"] = - [=[iH!"9NLS'%geYw3^R*fvWM1)MwxLS!d[zP(p0sQ|8tX{dWO{9w!+W)b"MU - W)V8&(2Wx"'dTL9*PP%1"JV(I|Jr1^f'-Hc3U\2H3Z='K#,)dPm]=]; - } - -function missingglobal(name) - if sha256 then - local hash = sha256(name.."|"..name:reverse(), true); - - if subst[hash] then - return vdecode(subst[hash], sha256(name:reverse(), true)); - end - end -end diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua index 469044cd..189aeb36 100644 --- a/plugins/mod_dialback.lua +++ b/plugins/mod_dialback.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_disco.lua b/plugins/mod_disco.lua index f7e51b83..ee0043f1 100644 --- a/plugins/mod_disco.lua +++ b/plugins/mod_disco.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_groups.lua b/plugins/mod_groups.lua index f31bb1a8..de7b8302 100644 --- a/plugins/mod_groups.lua +++ b/plugins/mod_groups.lua @@ -1,14 +1,14 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -local groups = { default = {} }; -local members = { [false] = {} }; +local groups; +local members; local groups_file; @@ -18,9 +18,9 @@ local jid_bare, jid_prep = jid.bare, jid.prep; local module_host = module:get_host(); function inject_roster_contacts(username, host, roster) - module:log("warn", "Injecting group members to roster"); + --module:log("debug", "Injecting group members to roster"); local bare_jid = username.."@"..host; - if not members[bare_jid] then return; end -- Not a member of any groups + if not members[bare_jid] and not members[false] then return; end -- Not a member of any groups local function import_jids_to_roster(group_name) for jid in pairs(groups[group_name]) do @@ -39,13 +39,23 @@ function inject_roster_contacts(username, host, roster) end -- Find groups this JID is a member of - for _, group_name in ipairs(members[bare_jid]) do - import_jids_to_roster(group_name); + if members[bare_jid] then + for _, group_name in ipairs(members[bare_jid]) do + --module:log("debug", "Importing group %s", group_name); + import_jids_to_roster(group_name); + end end -- Import public groups - for _, group_name in ipairs(members[false]) do - import_jids_to_roster(group_name); + if members[false] then + for _, group_name in ipairs(members[false]) do + --module:log("debug", "Importing group %s", group_name); + import_jids_to_roster(group_name); + end + end + + if roster[false] then + roster[false].version = true; end end @@ -57,6 +67,7 @@ function remove_virtual_contacts(username, host, datastore, data) new_roster[jid] = contact; end end + new_roster[false].version = nil; -- Version is void return username, host, datastore, new_roster; end @@ -71,20 +82,23 @@ function module.load() datamanager.add_callback(remove_virtual_contacts); groups = { default = {} }; - members = { [false] = {} }; + members = { }; local curr_group = "default"; for line in io.lines(groups_file) do if line:match("^%s*%[.-%]%s*$") then curr_group = line:match("^%s*%[(.-)%]%s*$"); if curr_group:match("^%+") then curr_group = curr_group:gsub("^%+", ""); + if not members[false] then + members[false] = {}; + end members[false][#members[false]+1] = curr_group; -- Is a public group end module:log("debug", "New group: %s", tostring(curr_group)); groups[curr_group] = groups[curr_group] or {}; else -- Add JID - local jid = jid_prep(line); + local jid = jid_prep(line:match("%S+")); if jid then module:log("debug", "New member of %s: %s", tostring(curr_group), tostring(jid)); groups[curr_group][jid] = true; diff --git a/plugins/mod_httpserver.lua b/plugins/mod_httpserver.lua index 07c7f315..c55bd20f 100644 --- a/plugins/mod_httpserver.lua +++ b/plugins/mod_httpserver.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_iq.lua b/plugins/mod_iq.lua index 5be04533..b3001fe5 100644 --- a/plugins/mod_iq.lua +++ b/plugins/mod_iq.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -53,6 +53,18 @@ module:hook("iq/bare", function(data) end end); +module:hook("iq/self", function(data) + -- IQ to bare JID recieved + local origin, stanza = data.origin, data.stanza; + + if stanza.attr.type == "get" or stanza.attr.type == "set" then + return module:fire_event("iq/self/"..stanza.tags[1].attr.xmlns..":"..stanza.tags[1].name, data); + else + module:fire_event("iq/self/"..stanza.attr.id, data); + return true; + end +end); + module:hook("iq/host", function(data) -- IQ to a local host recieved local origin, stanza = data.origin, data.stanza; diff --git a/plugins/mod_lastactivity.lua b/plugins/mod_lastactivity.lua index a0da9829..11053709 100644 --- a/plugins/mod_lastactivity.lua +++ b/plugins/mod_lastactivity.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_legacyauth.lua b/plugins/mod_legacyauth.lua index 9837920b..0134d736 100644 --- a/plugins/mod_legacyauth.lua +++ b/plugins/mod_legacyauth.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_message.lua b/plugins/mod_message.lua index 395307ba..d5b40ed5 100644 --- a/plugins/mod_message.lua +++ b/plugins/mod_message.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_offline.lua b/plugins/mod_offline.lua deleted file mode 100644 index c74d011e..00000000 --- a/plugins/mod_offline.lua +++ /dev/null @@ -1,56 +0,0 @@ --- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain --- --- This project is MIT/X11 licensed. Please see the --- COPYING file in the source package for more information. --- - -
-local datamanager = require "util.datamanager";
-local st = require "util.stanza";
-local datetime = require "util.datetime";
-local ipairs = ipairs; -local jid_split = require "util.jid".split;
-
-module:add_feature("msgoffline");
-
-module:hook("message/offline/store", function(event)
- local origin, stanza = event.origin, event.stanza;
- local to = stanza.attr.to;
- local node, host;
- if to then
- node, host = jid_split(to)
- else
- node, host = origin.username, origin.host;
- end
-
- stanza.attr.stamp, stanza.attr.stamp_legacy = datetime.datetime(), datetime.legacy();
- local result = datamanager.list_append(node, host, "offline", st.preserialize(stanza));
- stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
-
- return true;
-end);
-
-module:hook("message/offline/broadcast", function(event)
- local origin = event.origin;
- local node, host = origin.username, origin.host;
-
- local data = datamanager.list_load(node, host, "offline");
- if not data then return true; end
- for _, stanza in ipairs(data) do
- stanza = st.deserialize(stanza);
- stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = host, stamp = stanza.attr.stamp}):up(); -- XEP-0203
- stanza:tag("x", {xmlns = "jabber:x:delay", from = host, stamp = stanza.attr.stamp_legacy}):up(); -- XEP-0091 (deprecated)
- stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;
- origin.send(stanza);
- end
- return true;
-end);
-
-module:hook("message/offline/delete", function(event)
- local origin = event.origin;
- local node, host = origin.username, origin.host;
-
- return datamanager.list_store(node, host, "offline", nil);
-end);
diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index c42876b8..aa46d2d3 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_ping.lua b/plugins/mod_ping.lua index 1dc9fbec..61b717a2 100644 --- a/plugins/mod_ping.lua +++ b/plugins/mod_ping.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_posix.lua b/plugins/mod_posix.lua index 55d52ccd..c38f7eba 100644 --- a/plugins/mod_posix.lua +++ b/plugins/mod_posix.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -82,6 +82,7 @@ local function write_pidfile() end pidfile = module:get_option("pidfile"); if pidfile then + local err; local mode = stat(pidfile) and "r+" or "w+"; pidfile_handle, err = io.open(pidfile, mode); if not pidfile_handle then diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index a39d9c19..108ab0d3 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_privacy.lua b/plugins/mod_privacy.lua index d3043d69..3e9dbe49 100644 --- a/plugins/mod_privacy.lua +++ b/plugins/mod_privacy.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2009-2010 Matthew Wild +-- Copyright (C) 2009-2010 Waqas Hussain -- Copyright (C) 2009 Thilo Cestonaro -- -- This project is MIT/X11 licensed. Please see the @@ -13,7 +13,7 @@ local datamanager = require "util.datamanager"; local bare_sessions, full_sessions = bare_sessions, full_sessions; local util_Jid = require "util.jid"; local jid_bare = util_Jid.bare; -local jid_split = util_Jid.split; +local jid_split, jid_join = util_Jid.split, util_Jid.join; local load_roster = require "core.rostermanager".load_roster; local to_number = tonumber; @@ -160,26 +160,7 @@ function createOrReplaceList (privacy_lists, origin, stanza, name, entries, rost end end - if tmp.type == "group" then - local found = false; - local roster = load_roster(origin.username, origin.host); - for jid,item in pairs(roster) do - if item.groups ~= nil then - for group in pairs(item.groups) do - if group == tmp.value then - found = true; - break; - end - end - if found == true then - break; - end - end - end - if found == false then - return {"cancel", "item-not-found", "Specifed roster group not existing."}; - end - elseif tmp.type == "subscription" then + if tmp.type == "subscription" then if tmp.value ~= "both" and tmp.value ~= "to" and tmp.value ~= "from" and @@ -379,17 +360,22 @@ function checkIfNeedToBeBlocked(e, session) block = (item.action == "deny"); elseif item.type == "group" then local roster = load_roster(session.username, session.host); - local groups = roster[evilJid.node .. "@" .. evilJid.host].groups; - for group in pairs(groups) do - if group == item.value then - apply = true; - block = (item.action == "deny"); - break; + local roster_entry = roster[jid_join(evilJid.node, evilJid.host)]; + if roster_entry then + local groups = roster_entry.groups; + for group in pairs(groups) do + if group == item.value then + apply = true; + block = (item.action == "deny"); + break; + end end end - elseif item.type == "subscription" and evilJid.node ~= nil and evilJid.host ~= nil then -- we need a valid bare evil jid + elseif item.type == "subscription" then -- we need a valid bare evil jid local roster = load_roster(session.username, session.host); - if roster[evilJid.node .. "@" .. evilJid.host].subscription == item.value then + local roster_entry = roster[jid_join(evilJid.node, evilJid.host)]; + if (not(roster_entry) and item.value == "none") + or (roster_entry and roster_entry.subscription == item.value) then apply = true; block = (item.action == "deny"); end diff --git a/plugins/mod_private.lua b/plugins/mod_private.lua index 098dbba1..859bf45a 100644 --- a/plugins/mod_private.lua +++ b/plugins/mod_private.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_proxy65.lua b/plugins/mod_proxy65.lua index 2cfbe7b6..190d30be 100644 --- a/plugins/mod_proxy65.lua +++ b/plugins/mod_proxy65.lua @@ -20,6 +20,7 @@ local componentmanager = require "core.componentmanager"; local config_get = require "core.configmanager".get; local connlisteners = require "net.connlisteners"; local sha1 = require "util.hashes".sha1; +local server = require "net.server"; local host, name = module:get_host(), "SOCKS5 Bytestreams Service"; local sessions, transfers, component, replies_cache = {}, {}, nil, {}; @@ -28,6 +29,7 @@ local proxy_port = config_get(host, "core", "proxy65_port") or 5000; local proxy_interface = config_get(host, "core", "proxy65_interface") or "*"; local proxy_address = config_get(host, "core", "proxy65_address") or (proxy_interface ~= "*" and proxy_interface) or host; local proxy_acl = config_get(host, "core", "proxy65_acl"); +local max_buffer_size = 4096; local connlistener = { default_port = proxy_port, default_interface = proxy_interface, default_mode = "*a" }; @@ -84,19 +86,19 @@ function connlistener.onincoming(conn, data) transfers[sha].initiator = conn; session.sha = sha; module:log("debug", "initiator connected ... "); - throttle_sending(conn, transfers[sha].target); - throttle_sending(transfers[sha].target, conn); + server.link(conn, transfers[sha].target, max_buffer_size); + server.link(transfers[sha].target, conn, max_buffer_size); end conn:write(string.char(5, 0, 0, 3, sha:len()) .. sha .. string.char(0, 0)); -- VER, REP, RSV, ATYP, BND.ADDR (sha), BND.PORT (2 Byte) conn:lock_read(true) else module:log("warn", "Neither data transfer nor initial connect of a participator of a transfer.") - conn.close(); + conn:close(); end else if data ~= nil then module:log("warn", "unknown connection with no authentication data -> closing it"); - conn.close(); + conn:close(); end end end @@ -107,9 +109,9 @@ function connlistener.ondisconnect(conn, err) if session.sha and transfers[session.sha] then local initiator, target = transfers[session.sha].initiator, transfers[session.sha].target; if initiator == conn and target ~= nil then - target.close(); + target:close(); elseif target == conn and initiator ~= nil then - initiator.close(); + initiator:close(); end transfers[session.sha] = nil; end @@ -234,8 +236,12 @@ function handle_to_domain(origin, stanza) elseif xmlns == "http://jabber.org/protocol/bytestreams" then origin.send(get_stream_host(origin, stanza)); return true; + else + origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); + return true; end elseif stanza.name == "iq" and type == "set" then + module:log("debug", "Received activation request from %s", stanza.attr.from); local reply, from, to, sid = set_activation(stanza); if reply ~= nil and from ~= nil and to ~= nil and sid ~= nil then local sha = sha1(sid .. from .. to, true); @@ -246,6 +252,15 @@ function handle_to_domain(origin, stanza) transfers[sha].activated = true; transfers[sha].target:lock_read(false); transfers[sha].initiator:lock_read(false); + else + module:log("debug", "Both parties were not yet connected"); + local message = "Neither party is connected to the proxy"; + if transfers[sha].initiator then + message = "The recipient is not connected to the proxy"; + elseif transfers[sha].target then + message = "The sender (you) is not connected to the proxy"; + end + origin.send(st.error_reply(stanza, "cancel", "not-allowed", message)); end else module:log("error", "activation failed: sid: %s, initiator: %s, target: %s", tostring(sid), tostring(from), tostring(to)); @@ -262,25 +277,3 @@ end connlisteners.start(module.host .. ':proxy65'); component = componentmanager.register_component(host, handle_to_domain); -local sender_lock_threshold = 4096; -function throttle_sending(sender, receiver) - sender:pattern(sender_lock_threshold); - local sender_locked; - local _sendbuffer = receiver.sendbuffer; - function receiver.sendbuffer() - _sendbuffer(); - if sender_locked and receiver.bufferlen() < sender_lock_threshold then - sender:lock_read(false); -- Unlock now - sender_locked = nil; - end - end - - local _readbuffer = sender.readbuffer; - function sender.readbuffer() - _readbuffer(); - if not sender_locked and receiver.bufferlen() >= sender_lock_threshold then - sender_locked = true; - sender:lock_read(true); - end - end -end diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua index be1be0ae..b8d142f7 100644 --- a/plugins/mod_register.lua +++ b/plugins/mod_register.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -12,6 +12,7 @@ local st = require "util.stanza"; local datamanager = require "util.datamanager"; local usermanager_user_exists = require "core.usermanager".user_exists; local usermanager_create_user = require "core.usermanager".create_user; +local usermanager_set_password = require "core.usermanager".set_password; local datamanager_store = require "util.datamanager".store; local os_time = os.time; local nodeprep = require "util.encodings".stringprep.nodeprep; @@ -34,7 +35,7 @@ module:add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) local username, host = session.username, session.host; --session.send(st.error_reply(stanza, "cancel", "not-allowed")); --return; - usermanager_create_user(username, nil, host); -- Disable account + usermanager_set_password(username, host, nil); -- 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)); @@ -69,7 +70,7 @@ module:add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) 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? + if usermanager_set_password(username, session.host, password) then session.send(st.reply(stanza)); else -- TODO unable to write file, file may be locked, etc, what's the correct error? diff --git a/plugins/mod_roster.lua b/plugins/mod_roster.lua index 4362dca2..ddf02f2f 100644 --- a/plugins/mod_roster.lua +++ b/plugins/mod_roster.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -36,9 +36,10 @@ module:add_iq_handler("c2s", "jabber:iq:roster", if stanza.attr.type == "get" then local roster = st.reply(stanza); - local ver = stanza.tags[1].attr.ver + local client_ver = tonumber(stanza.tags[1].attr.ver); + local server_ver = tonumber(session.roster[false].version or 1); - if (not ver) or tonumber(ver) ~= (session.roster[false].version or 1) then + if not (client_ver and server_ver) or client_ver ~= server_ver then roster:query("jabber:iq:roster"); -- Client does not support versioning, or has stale roster for jid in pairs(session.roster) do @@ -55,7 +56,7 @@ module:add_iq_handler("c2s", "jabber:iq:roster", roster:up(); -- move out from item end end - roster.tags[1].attr.ver = tostring(session.roster[false].version or "1"); + roster.tags[1].attr.ver = server_ver; end session.send(roster); session.interested = true; -- resource is interested in roster updates diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua index 398ae9f8..9f940c37 100644 --- a/plugins/mod_saslauth.lua +++ b/plugins/mod_saslauth.lua @@ -1,7 +1,7 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain --- +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- @@ -28,6 +28,12 @@ local config = require "core.configmanager"; local secure_auth_only = module:get_option("c2s_require_encryption") or module:get_option("require_encryption"); local sasl_backend = module:get_option("sasl_backend") or "builtin"; +-- Cyrus config options +local require_provisioning = module:get_option("cyrus_require_provisioning") or false; +local cyrus_service_realm = module:get_option("cyrus_service_realm"); +local cyrus_service_name = module:get_option("cyrus_service_name"); +local cyrus_application_name = module:get_option("cyrus_application_name"); + local log = module._log; local xmlns_sasl ='urn:ietf:params:xml:ns:xmpp-sasl'; @@ -35,21 +41,29 @@ local xmlns_bind ='urn:ietf:params:xml:ns:xmpp-bind'; local xmlns_stanzas ='urn:ietf:params:xml:ns:xmpp-stanzas'; local new_sasl; -if sasl_backend == "cyrus" then - local cyrus, err = pcall(require, "util.sasl_cyrus"); - if cyrus then +if sasl_backend == "builtin" then + new_sasl = require "util.sasl".new; +elseif sasl_backend == "cyrus" then + prosody.unlock_globals(); --FIXME: Figure out why this is needed and + -- why cyrussasl isn't caught by the sandbox + local ok, cyrus = pcall(require, "util.sasl_cyrus"); + prosody.lock_globals(); + if ok then local cyrus_new = cyrus.new; new_sasl = function(realm) - return cyrus_new(realm, module:get_option("cyrus_service_name") or "xmpp"); + return cyrus_new( + cyrus_service_realm or realm, + cyrus_service_name or "xmpp", + cyrus_application_name or "prosody" + ); end else - sasl_backend = "builtin"; - module:log("warn", "Failed to load Cyrus SASL, falling back to builtin auth mechanisms"); + module:log("error", "Failed to load Cyrus SASL because: %s", cyrus); + error("Failed to load Cyrus SASL"); end -end -if not new_sasl then - if sasl_backend ~= "builtin" then module:log("warn", "Unknown SASL backend %s", sasl_backend); end; - new_sasl = require "util.sasl".new; +else + module:log("error", "Unknown SASL backend: %s", sasl_backend); + error("Unknown SASL backend"); end local default_authentication_profile = { @@ -90,7 +104,7 @@ local function build_reply(status, ret, err_msg) return reply; end -local function handle_status(session, status) +local function handle_status(session, status, ret, err_msg) if status == "failure" then session.sasl_handler = session.sasl_handler:clean_clone(); elseif status == "success" then @@ -99,12 +113,20 @@ local function handle_status(session, status) module:log("warn", "SASL succeeded but we didn't get a username!"); session.sasl_handler = nil; session:reset_stream(); - return; + return status, ret, err_msg; + end + + if not(require_provisioning) or usermanager_user_exists(username, session.host) then + sm_make_authenticated(session, session.sasl_handler.username); + session.sasl_handler = nil; + session:reset_stream(); + else + module:log("warn", "SASL succeeded but we don't have an account provisioned for %s", username); + session.sasl_handler = session.sasl_handler:clean_clone(); + return "failure", "not-authorized", "User authenticated successfully, but not provisioned for XMPP"; end - sm_make_authenticated(session, session.sasl_handler.username); - session.sasl_handler = nil; - session:reset_stream(); end + return status, ret, err_msg; end local function sasl_handler(session, stanza) @@ -138,7 +160,7 @@ local function sasl_handler(session, stanza) end end local status, ret, err_msg = session.sasl_handler:process(text); - handle_status(session, status); + status, ret, err_msg = handle_status(session, status, ret, err_msg); local s = build_reply(status, ret, err_msg); log("debug", "sasl reply: %s", tostring(s)); session.send(s); @@ -157,10 +179,11 @@ module:hook("stream-features", function(event) if secure_auth_only and not origin.secure then return; end + local realm = module:get_option("sasl_realm") or origin.host; if module:get_option("anonymous_login") then - origin.sasl_handler = new_sasl(origin.host, anonymous_authentication_profile); + origin.sasl_handler = new_sasl(realm, anonymous_authentication_profile); else - origin.sasl_handler = new_sasl(origin.host, default_authentication_profile); + origin.sasl_handler = new_sasl(realm, default_authentication_profile); if not (module:get_option("allow_unencrypted_plain_auth")) and not origin.secure then origin.sasl_handler:forbidden({"PLAIN"}); end diff --git a/plugins/mod_selftests.lua b/plugins/mod_selftests.lua deleted file mode 100644 index 1f413634..00000000 --- a/plugins/mod_selftests.lua +++ /dev/null @@ -1,61 +0,0 @@ --- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain --- --- This project is MIT/X11 licensed. Please see the --- COPYING file in the source package for more information. --- - -module.host = "*" -- Global module - -local st = require "util.stanza"; -local register_component = require "core.componentmanager".register_component; -local core_route_stanza = core_route_stanza; -local socket = require "socket"; -local ping_hosts = module:get_option("ping_hosts") or { "coversant.interop.xmpp.org", "djabberd.interop.xmpp.org", "djabberd-trunk.interop.xmpp.org", "ejabberd.interop.xmpp.org", "openfire.interop.xmpp.org" }; - -local open_pings = {}; - -local t_insert = table.insert; - -local log = require "util.logger".init("mod_selftests"); - -local tests_jid = "self_tests@getjabber.ath.cx"; -local host = "getjabber.ath.cx"; - -if not (tests_jid and host) then - for currhost in pairs(host) do - if currhost ~= "localhost" then - tests_jid, host = "self_tests@"..currhost, currhost; - end - end -end - -if tests_jid and host then - local bot = register_component(tests_jid, function(origin, stanza, ourhost) - local time = open_pings[stanza.attr.id]; - - if time then - log("info", "Ping reply from %s in %fs", tostring(stanza.attr.from), socket.gettime() - time); - else - log("info", "Unexpected reply: %s", stanza:pretty_print()); - end - end); - - - local our_origin = hosts[host]; - module:add_event_hook("server-started", - function () - local id = st.new_id(); - local ping_attr = { xmlns = 'urn:xmpp:ping' }; - local function send_ping(to) - log("info", "Sending ping to %s", to); - core_route_stanza(our_origin, st.iq{ to = to, from = tests_jid, id = id, type = "get" }:tag("ping", ping_attr)); - open_pings[id] = socket.gettime(); - end - - for _, host in ipairs(ping_hosts) do - send_ping(host); - end - end); -end diff --git a/plugins/mod_time.lua b/plugins/mod_time.lua index 7d900ae9..cb69ebe7 100644 --- a/plugins/mod_time.lua +++ b/plugins/mod_time.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_tls.lua b/plugins/mod_tls.lua index 1a00c36e..8b96aa15 100644 --- a/plugins/mod_tls.lua +++ b/plugins/mod_tls.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -10,6 +10,7 @@ local st = require "util.stanza"; local secure_auth_only = module:get_option("c2s_require_encryption") or module:get_option("require_encryption"); local secure_s2s_only = module:get_option("s2s_require_encryption"); +local allow_s2s_tls = module:get_option("s2s_allow_encryption") ~= false; local xmlns_starttls = 'urn:ietf:params:xml:ns:xmpp-tls'; local starttls_attr = { xmlns = xmlns_starttls }; @@ -27,8 +28,10 @@ local host = hosts[module.host]; local function can_do_tls(session) if session.type == "c2s_unauthed" then return session.conn.starttls and host.ssl_ctx_in; - elseif session.type == "s2sin_unauthed" then + elseif session.type == "s2sin_unauthed" and allow_s2s_tls then return session.conn.starttls and host.ssl_ctx_in; + elseif session.direction == "outgoing" and allow_s2s_tls then + return session.conn.starttls and host.ssl_ctx; end return false; end @@ -69,7 +72,7 @@ end); -- For s2sout connections, start TLS if we can module:hook_stanza("http://etherx.jabber.org/streams", "features", function (session, stanza) module:log("debug", "Received features element"); - if session.conn.starttls and stanza:child_with_ns(xmlns_starttls) then + if can_do_tls(session) and stanza:child_with_ns(xmlns_starttls) then module:log("%s is offering TLS, taking up the offer...", session.to_host); session.sends2s("<starttls xmlns='"..xmlns_starttls.."'/>"); return true; diff --git a/plugins/mod_uptime.lua b/plugins/mod_uptime.lua index cf6c6b64..24d10180 100644 --- a/plugins/mod_uptime.lua +++ b/plugins/mod_uptime.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_vcard.lua b/plugins/mod_vcard.lua index 6bf82ee7..e2f1dfb8 100644 --- a/plugins/mod_vcard.lua +++ b/plugins/mod_vcard.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_version.lua b/plugins/mod_version.lua index 9af830f8..69e914c0 100644 --- a/plugins/mod_version.lua +++ b/plugins/mod_version.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_watchregistrations.lua b/plugins/mod_watchregistrations.lua index 6a2af853..f006818e 100644 --- a/plugins/mod_watchregistrations.lua +++ b/plugins/mod_watchregistrations.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/mod_welcome.lua b/plugins/mod_welcome.lua index edcfbd8c..8f92010a 100644 --- a/plugins/mod_welcome.lua +++ b/plugins/mod_welcome.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua index d23e2474..de23aebb 100644 --- a/plugins/muc/mod_muc.lua +++ b/plugins/muc/mod_muc.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index ad45bbfd..18c80325 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -319,6 +319,11 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc :tag("item", {affiliation=affiliation or "none", role=role or "none"}):up() :tag("status", {code='110'})); end + if self._data.whois == 'anyone' then -- non-anonymous? + self:_route_stanza(st.stanza("message", {from=to, to=from, type='groupchat'}) + :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + :tag("status", {code='100'})); + end self:send_history(from); else -- banned local reply = st.error_reply(stanza, "auth", "forbidden"):up(); @@ -514,6 +519,9 @@ function room_mt:handle_to_room(origin, stanza) -- presence changes and groupcha if not item.attr.jid and item.attr.nick then -- COMPAT Workaround for Miranda sending 'nick' instead of 'jid' when changing affiliation local occupant = self._occupants[self.jid.."/"..item.attr.nick]; if occupant then item.attr.jid = occupant.jid; end + elseif not item.attr.nick and item.attr.jid then + local nick = self._jid_nick[item.attr.jid]; + if nick then item.attr.nick = select(3, jid_split(nick)); end end local reason = item.tags[1] and item.tags[1].name == "reason" and #item.tags[1] == 1 and item.tags[1][1]; if item.attr.affiliation and item.attr.jid and not item.attr.role then @@ -743,7 +751,7 @@ end function room_mt:set_role(actor, occupant_jid, role, callback, reason) if role == "none" then role = nil; end if role and role ~= "moderator" and role ~= "participant" and role ~= "visitor" then return nil, "modify", "not-acceptable"; end - if self:get_affiliation(actor) ~= "owner" then return nil, "cancel", "not-allowed"; end + if self:get_role(self._jid_nick[actor]) ~= "moderator" then return nil, "cancel", "not-allowed"; end local occupant = self._occupants[occupant_jid]; if not occupant then return nil, "modify", "not-acceptable"; end if occupant.affiliation == "owner" or occupant.affiliation == "admin" then return nil, "cancel", "not-allowed"; end @@ -796,9 +804,6 @@ function room_mt:_route_stanza(stanza) end end end - if self._data.whois == 'anyone' then - muc_child:tag('status', { code = '100' }); - end end self:route_stanza(stanza); if muc_child then @@ -1,7 +1,7 @@ #!/usr/bin/env lua -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -123,6 +123,33 @@ function sandbox_require() end end +function set_function_metatable() + local mt = {}; + function mt.__index(f, upvalue) + local i, name, value = 0; + repeat + i = i + 1; + name, value = debug.getupvalue(f, i); + until name == upvalue or name == nil; + return value; + end + function mt.__newindex(f, upvalue, value) + local i, name = 0; + repeat + i = i + 1; + name = debug.getupvalue(f, i); + until name == upvalue or name == nil; + if name then + debug.setupvalue(f, i, value); + end + end + function mt.__tostring(f) + local info = debug.getinfo(f); + return ("function(%s:%d)"):format(info.short_src:match("[^\\/]*$"), info.linedefined); + end + debug.setmetatable(function() end, mt); +end + function init_global_state() bare_sessions = {}; full_sessions = {}; @@ -418,6 +445,7 @@ read_config(); init_logging(); check_dependencies(); sandbox_require(); +set_function_metatable(); load_libraries(); init_global_state(); read_version(); diff --git a/prosody.cfg.lua.dist b/prosody.cfg.lua.dist index de07d7c5..a17eb877 100644 --- a/prosody.cfg.lua.dist +++ b/prosody.cfg.lua.dist @@ -1,110 +1,127 @@ -- Prosody Example Configuration File -- --- If it wasn't already obvious, -- starts a comment, and all --- text after it on a line is ignored by Prosody. --- --- The config is split into sections, a global section, and one --- for each defined host that we serve. You can add as many host --- sections as you like. --- --- Lists are written { "like", "this", "one" } --- Lists can also be of { 1, 2, 3 } numbers, and other things. --- Either commas, or semi-colons; may be used --- as seperators. --- --- A table is a list of values, except each value has a name. An --- example table would be: --- --- ssl = { key = "keyfile.key", certificate = "certificate.cert" } --- --- Whitespace (that is tabs, spaces, line breaks) is mostly insignificant, so --- can --- be placed anywhere that you deem fitting. --- --- Tip: You can check that the syntax of this file is correct when you have finished --- by running: luac -p prosody.cfg.lua --- If there are any errors, it will let you know what and where they are, otherwise it --- will keep quiet. +-- Information on configuring Prosody can be found on our +-- website at http://prosody.im/doc/configure +-- +-- Tip: You can check that the syntax of this file is correct +-- when you have finished by running: luac -p prosody.cfg.lua +-- If there are any errors, it will let you know what and where +-- they are, otherwise it will keep quiet. -- -- The only thing left to do is rename this file to remove the .dist ending, and fill in the -- blanks. Good luck, and happy Jabbering! --- Server-wide settings go in this section -Host "*" - - -- This is a (by default, empty) list of accounts that are admins - -- for the server. Note that you must create the accounts separately - -- (see http://prosody.im/doc/creating_accounts for info) - -- Example: admins = { "user1@example.com", "user2@example.net" } - admins = { } - - -- This is the list of modules Prosody will load on startup. - -- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. - modules_enabled = { - -- Generally required - "roster"; -- Allow users to have a roster. Recommended ;) - "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. - "tls"; -- Add support for secure TLS on c2s/s2s connections - "dialback"; -- s2s dialback support - "disco"; -- Service discovery - - -- Not essential, but recommended - "private"; -- Private XML storage (for room bookmarks, etc.) - "vcard"; -- Allow users to set vCards - - -- Nice to have - "legacyauth"; -- Legacy authentication. Only used by some old clients and bots. - "version"; -- Replies to server version requests - "uptime"; -- Report how long server has been running - "time"; -- Let others know the time here on this server - "ping"; -- Replies to XMPP pings with pongs - "pep"; -- Enables users to publish their mood, activity, playing music and more - "register"; -- Allow users to register on this server using a client and change passwords - - -- Other specific functionality - --"posix"; -- POSIX functionality, sends server to background, enables syslog, etc. - --"console"; -- Opens admin telnet interface on localhost port 5582 - --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" - --"httpserver"; -- Serve static files from a directory over HTTP - }; - - -- These modules are auto-loaded, should you - -- for (for some mad reason) want to disable - -- them then uncomment them below - modules_disabled = { - -- "presence"; - -- "message"; - -- "iq"; - }; - - -- Disable account creation by default, for security - -- For more information see http://prosody.im/doc/creating_accounts - allow_registration = false; + +---------- Server-wide settings ---------- +-- Settings in this section apply to the whole server and are the default settings +-- for any virtual hosts + +-- This is a (by default, empty) list of accounts that are admins +-- for the server. Note that you must create the accounts separately +-- (see http://prosody.im/doc/creating_accounts for info) +-- Example: admins = { "user1@example.com", "user2@example.net" } +admins = { } + +-- Enable use of libevent for better performance under high load +-- For more information see: http://prosody.im/doc/libevent +--use_libevent = true; + +-- This is the list of modules Prosody will load on startup. +-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. +-- Documentation on modules can be found at: http://prosody.im/doc/modules +modules_enabled = { + + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + + -- Not essential, but recommended + "private"; -- Private XML storage (for room bookmarks, etc.) + "vcard"; -- Allow users to set vCards + --"privacy"; -- Support privacy lists + --"compression"; -- Stream compression + + -- Nice to have + "legacyauth"; -- Legacy authentication. Only used by some old clients and bots. + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + "pep"; -- Enables users to publish their mood, activity, playing music and more + "register"; -- Allow users to register on this server using a client and change passwords + + -- Other specific functionality + --"posix"; -- POSIX functionality, sends server to background, enables syslog, etc. + --"console"; -- Opens admin telnet interface on localhost port 5582 + --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + --"httpserver"; -- Serve static files from a directory over HTTP + --"groups"; -- Shared roster support + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations +}; + +-- These modules are auto-loaded, should you +-- for (for some mad reason) want to disable +-- them then uncomment them below +modules_disabled = { + -- "presence"; + -- "message"; + -- "iq"; +}; + +-- Disable account creation by default, for security +-- For more information see http://prosody.im/doc/creating_accounts +allow_registration = false; - -- These are the SSL/TLS-related settings. If you don't want - -- to use SSL/TLS, you may comment or remove this - ssl = { - key = "certs/localhost.key"; - certificate = "certs/localhost.cert"; - } +-- These are the SSL/TLS-related settings. If you don't want +-- to use SSL/TLS, you may comment or remove this +ssl = { + key = "certs/localhost.key"; + certificate = "certs/localhost.cert"; +} + +-- Require encryption on client/server connections? +--c2s_require_encryption = false +--s2s_require_encryption = false + +-- Logging configuration +-- For advanced logging see http://prosody.im/doc/logging +log = "prosody.log"; +debug = false; -- Log debug messages? --- This allows clients to connect to localhost. No harm in it. -Host "localhost" +----------- Virtual hosts ----------- +-- You need to add a VirtualHost entry for each domain you wish Prosody to serve. +-- Settings under each VirtualHost entry apply *only* to that host. --- Section for example.com --- (replace example.com with your domain name) -Host "example.com" +VirtualHost "localhost" - enabled = false -- This will disable the host, preserving the config, but denying connections +VirtualHost "example.com" + enabled = false -- Remove this line to enable this host -- Assign this host a certificate for TLS, otherwise it would use the one -- set in the global section (if any). -- Note that old-style SSL on port 5223 only supports one certificate, and will always -- use the global one. - ssl = { + ssl = { key = "certs/example.com.key"; certificate = "certs/example.com.crt"; - } + } + +------ Components ------ +-- You can specify components to add hosts that provide special services, +-- like multi-user conferences, and transports. +-- For more information on components, see http://prosody.im/doc/components + +---Set up a MUC (multi-user chat) room server on conference.example.com: +--Component "conference.example.com" "muc" + +-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers: +--Component "proxy.example.com" "proxy65" --- Set up a MUC (multi-user chat) room server on conference.example.com: -Component "conference.example.com" "muc" +---Set up an external component (default component port is 5347) +--Component "gateway.example.com" +-- component_secret = "password" @@ -433,6 +433,19 @@ function commands.stop(arg) return 1; end +function commands.restart(arg) + if arg[1] == "--help" then + show_usage([[restart]], [[Restart a running Prosody server]]); + return 1; + end + + local ret = commands.stop(arg); + if ret == 0 then + ret = commands.start(arg); + end + return ret; +end + -- ejabberdctl compatibility function commands.register(arg) @@ -491,6 +504,10 @@ local http_errors = { }; function commands.addplugin(arg) + if not arg[1] or arg[1] == "--help" then + show_usage("addplugin URL", "Download and install a plugin from a URL"); + return 1; + end local url = arg[1]; if url:match("^http://") then local http = require "socket.http"; @@ -562,8 +579,8 @@ if not commands[command] then -- Show help for all commands print(""); print("Where COMMAND may be one of:\n"); - local hidden_commands = require "util.set".new{ "register", "unregister" }; - local commands_order = { "adduser", "passwd", "deluser" }; + local hidden_commands = require "util.set".new{ "register", "unregister", "addplugin" }; + local commands_order = { "adduser", "passwd", "deluser", "start", "stop", "restart" }; local done = {}; diff --git a/tests/test.lua b/tests/test.lua index b71ccc1f..38ef6191 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_core_configmanager.lua b/tests/test_core_configmanager.lua index 533845b3..c4ed746f 100644 --- a/tests/test_core_configmanager.lua +++ b/tests/test_core_configmanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_core_modulemanager.lua b/tests/test_core_modulemanager.lua index 82e9aa45..9498875a 100644 --- a/tests/test_core_modulemanager.lua +++ b/tests/test_core_modulemanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_core_s2smanager.lua b/tests/test_core_s2smanager.lua index 8635ed24..b49c7da6 100644 --- a/tests/test_core_s2smanager.lua +++ b/tests/test_core_s2smanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -30,18 +30,18 @@ function compare_srv_priorities(csp) assert_equal(csp(r3, r2), false); assert_equal(csp(r3, r3), false); assert_equal(csp(r3, r4), false); - assert_equal(csp(r3, r5), true); + assert_equal(csp(r3, r5), false); assert_equal(csp(r4, r1), false); assert_equal(csp(r4, r2), false); assert_equal(csp(r4, r3), false); assert_equal(csp(r4, r4), false); - assert_equal(csp(r4, r5), true); + assert_equal(csp(r4, r5), false); assert_equal(csp(r5, r1), false); assert_equal(csp(r5, r2), false); - assert_equal(csp(r5, r3), false); - assert_equal(csp(r5, r4), false); + assert_equal(csp(r5, r3), true); + assert_equal(csp(r5, r4), true); assert_equal(csp(r5, r5), false); end diff --git a/tests/test_core_stanza_router.lua b/tests/test_core_stanza_router.lua index 59e68b91..97dc2e19 100644 --- a/tests/test_core_stanza_router.lua +++ b/tests/test_core_stanza_router.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_sasl.lua b/tests/test_sasl.lua index e279a975..7c0b02f8 100644 --- a/tests/test_sasl.lua +++ b/tests/test_sasl.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_util_jid.lua b/tests/test_util_jid.lua index f579e597..5cc1390b 100644 --- a/tests/test_util_jid.lua +++ b/tests/test_util_jid.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_util_multitable.lua b/tests/test_util_multitable.lua index b8437bf5..4b7e4fcc 100644 --- a/tests/test_util_multitable.lua +++ b/tests/test_util_multitable.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/test_util_stanza.lua b/tests/test_util_stanza.lua index 0819f2c7..7916a0c1 100644 --- a/tests/test_util_stanza.lua +++ b/tests/test_util_stanza.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tests/util/logger.lua b/tests/util/logger.lua index 003c5946..e62a1aa8 100644 --- a/tests/util/logger.lua +++ b/tests/util/logger.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/tools/ejabberd2prosody.lua b/tools/ejabberd2prosody.lua index 7b19260d..a231abd8 100755 --- a/tools/ejabberd2prosody.lua +++ b/tools/ejabberd2prosody.lua @@ -1,7 +1,7 @@ #!/usr/bin/env lua -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -17,6 +17,8 @@ end require "erlparse"; +prosody = {}; + local serialize = require "util.serialization".serialize; local st = require "util.stanza"; package.loaded["util.logger"] = {init = function() return function() end; end} @@ -49,7 +51,7 @@ function vcard(node, host, stanza) end function password(node, host, password) local ret, err = dm.store(node, host, "accounts", {password = password}); - print("["..(err or "success").."] accounts: "..node.."@"..host.." = "..password); + print("["..(err or "success").."] accounts: "..node.."@"..host); end function roster(node, host, jid, item) local roster = dm.load(node, host, "roster") or {}; diff --git a/tools/ejabberdsql2prosody.lua b/tools/ejabberdsql2prosody.lua index f652af5b..ef4706ce 100644 --- a/tools/ejabberdsql2prosody.lua +++ b/tools/ejabberdsql2prosody.lua @@ -1,7 +1,7 @@ #!/usr/bin/env lua -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -254,7 +254,7 @@ end for i, row in ipairs(t["users"] or NULL) do local node, password = row.username, row.password; local ret, err = dm.store(node, host, "accounts", {password = password}); - print("["..(err or "success").."] accounts: "..node.."@"..host.." = "..password); + print("["..(err or "success").."] accounts: "..node.."@"..host); end function roster(node, host, jid, item) diff --git a/tools/erlparse.lua b/tools/erlparse.lua index bfec3b4d..dc3a2f94 100644 --- a/tools/erlparse.lua +++ b/tools/erlparse.lua @@ -1,21 +1,27 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- - +local string_byte, string_char = string.byte, string.char; +local t_concat, t_insert = table.concat, table.insert; +local type, tonumber, tostring = type, tonumber, tostring; local file = nil; local last = nil; +local line = 1; local function read(expected) local ch; if last then ch = last; last = nil; - else ch = file:read(1); end - if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil")); end + else + ch = file:read(1); + if ch == "\n" then line = line + 1; end + end + if expected and ch ~= expected then error("expected: "..expected.."; got: "..(ch or "nil").." on line "..line); end return ch; end local function pushback(ch) @@ -27,21 +33,21 @@ local function peek() return last; end -local _A, _a, _Z, _z, _0, _9, __, _at, _space = string.byte("AaZz09@_ ", 1, 9); +local _A, _a, _Z, _z, _0, _9, __, _at, _space, _minus = string_byte("AaZz09@_ -", 1, 10); local function isLowerAlpha(ch) - ch = string.byte(ch) or 0; + ch = string_byte(ch) or 0; return (ch >= _a and ch <= _z); end local function isNumeric(ch) - ch = string.byte(ch) or 0; - return (ch >= _0 and ch <= _9); + ch = string_byte(ch) or 0; + return (ch >= _0 and ch <= _9) or ch == _minus; end local function isAtom(ch) - ch = string.byte(ch) or 0; + ch = string_byte(ch) or 0; return (ch >= _A and ch <= _Z) or (ch >= _a and ch <= _z) or (ch >= _0 and ch <= _9) or ch == __ or ch == _at; end local function isSpace(ch) - ch = string.byte(ch) or "x"; + ch = string_byte(ch) or "x"; return ch <= _space; end @@ -49,79 +55,85 @@ local escapes = {["\\b"]="\b", ["\\d"]="\d", ["\\e"]="\e", ["\\f"]="\f", ["\\n"] local function readString() read("\""); -- skip quote local slash = nil; - local str = ""; + local str = {}; while true do local ch = read(); if slash then slash = slash..ch; if not escapes[slash] then error("Unknown escape sequence: "..slash); end - str = str..escapes[slash]; + str[#str+1] = escapes[slash]; slash = nil; elseif ch == "\"" then break; elseif ch == "\\" then slash = ch; else - str = str..ch; + str[#str+1] = ch; end end - return str; + return t_concat(str); end local function readAtom1() - local var = read(); + local var = { read() }; while isAtom(peek()) do - var = var..read(); + var[#var+1] = read(); end - return var; + return t_concat(var); end local function readAtom2() - local str = read("'"); + local str = { read("'") }; local slash = nil; while true do local ch = read(); - str = str..ch; + str[#str+1] = ch; if ch == "'" and not slash then break; end end - return str; + return t_concat(str); end local function readNumber() - local num = read(); + local num = { read() }; while isNumeric(peek()) do - num = num..read(); + num[#num+1] = read(); end - return tonumber(num); + return tonumber(t_concat(num)); end local readItem = nil; local function readTuple() local t = {}; - local s = ""; -- string representation + local s = {}; -- string representation read(); -- read {, or [, or < while true do local item = readItem(); if not item then break; end - if type(item) ~= type(0) or item > 255 then + if type(item) ~= "number" or item > 255 then s = nil; elseif s then - s = s..string.char(item); + s[#s+1] = string_char(item); end - table.insert(t, item); + t_insert(t, item); end read(); -- read }, or ], or > - if s and s ~= "" then - return s + if s and #s > 0 then + return t_concat(s) else return t end; end local function readBinary() read("<"); -- read < + -- Discard PIDs + if isNumeric(peek()) then + while peek() ~= ">" do read(); end + read(">"); + return {}; + end local t = readTuple(); read(">") -- read > local ch = peek(); - if type(t) == type("") then + if type(t) == "string" then -- binary is a list of integers return t; - elseif type(t) == type({}) then + elseif type(t) == "table" then if t[1] then -- binary contains string return t[1]; diff --git a/util-src/encodings.c b/util-src/encodings.c index c573a330..f2109d0c 100644 --- a/util-src/encodings.c +++ b/util-src/encodings.c @@ -1,6 +1,6 @@ -/* Prosody IM v0.4 --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +/* Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util-src/hashes.c b/util-src/hashes.c index 907167e2..33a9be89 100644 --- a/util-src/hashes.c +++ b/util-src/hashes.c @@ -1,6 +1,6 @@ -/* Prosody IM v0.4 --- Copyright (C) 2008 Matthew Wild --- Copyright (C) 2008 Waqas Hussain +/* Prosody IM +-- Copyright (C) 2009-2010 Matthew Wild +-- Copyright (C) 2009-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util-src/pposix.c b/util-src/pposix.c index 8c1dbcc6..9f16f178 100644 --- a/util-src/pposix.c +++ b/util-src/pposix.c @@ -1,6 +1,6 @@ -/* Prosody IM v0.4 --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +/* Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- Copyright (C) 2009 Tobias Markmann -- -- This project is MIT/X11 licensed. Please see the diff --git a/util-src/windows.c b/util-src/windows.c index 7fb96312..12bd7ce9 100644 --- a/util-src/windows.c +++ b/util-src/windows.c @@ -1,45 +1,58 @@ -
-#include <stdio.h>
-#include <windows.h>
-#include <windns.h>
-
-#include "lua.h"
-#include "lauxlib.h"
-
-static int Lget_nameservers(lua_State *L) {
- char stack_buffer[1024]; // stack allocated buffer
- IP4_ARRAY* ips = (IP4_ARRAY*) stack_buffer;
- DWORD len = sizeof(stack_buffer);
- DNS_STATUS status;
-
- status = DnsQueryConfig(DnsConfigDnsServerList, FALSE, NULL, NULL, ips, &len);
- if (status == 0) {
- DWORD i;
- lua_createtable(L, ips->AddrCount, 0);
- for (i = 0; i < ips->AddrCount; i++) {
- DWORD ip = ips->AddrArray[i];
- char ip_str[16] = "";
- sprintf_s(ip_str, sizeof(ip_str), "%d.%d.%d.%d", (ip >> 0) & 255, (ip >> 8) & 255, (ip >> 16) & 255, (ip >> 24) & 255);
- lua_pushstring(L, ip_str);
- lua_rawseti(L, -2, i+1);
- }
- return 1;
- } else {
- luaL_error(L, "DnsQueryConfig returned %d", status);
- return 0; // unreachable, but prevents a compiler warning
- }
-}
-
-static const luaL_Reg Reg[] =
-{
- { "get_nameservers", Lget_nameservers },
- { NULL, NULL }
-};
-
-LUALIB_API int luaopen_util_windows(lua_State *L) {
- luaL_register(L, "windows", Reg);
- lua_pushliteral(L, "version"); /** version */
- lua_pushliteral(L, "-3.14");
- lua_settable(L,-3);
- return 1;
-}
+/* Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- +*/ + +/* +* windows.c +* Windows support functions for Lua +*/ + +#include <stdio.h> +#include <windows.h> +#include <windns.h> + +#include "lua.h" +#include "lauxlib.h" + +static int Lget_nameservers(lua_State *L) { + char stack_buffer[1024]; // stack allocated buffer + IP4_ARRAY* ips = (IP4_ARRAY*) stack_buffer; + DWORD len = sizeof(stack_buffer); + DNS_STATUS status; + + status = DnsQueryConfig(DnsConfigDnsServerList, FALSE, NULL, NULL, ips, &len); + if (status == 0) { + DWORD i; + lua_createtable(L, ips->AddrCount, 0); + for (i = 0; i < ips->AddrCount; i++) { + DWORD ip = ips->AddrArray[i]; + char ip_str[16] = ""; + sprintf_s(ip_str, sizeof(ip_str), "%d.%d.%d.%d", (ip >> 0) & 255, (ip >> 8) & 255, (ip >> 16) & 255, (ip >> 24) & 255); + lua_pushstring(L, ip_str); + lua_rawseti(L, -2, i+1); + } + return 1; + } else { + luaL_error(L, "DnsQueryConfig returned %d", status); + return 0; // unreachable, but prevents a compiler warning + } +} + +static const luaL_Reg Reg[] = +{ + { "get_nameservers", Lget_nameservers }, + { NULL, NULL } +}; + +LUALIB_API int luaopen_util_windows(lua_State *L) { + luaL_register(L, "windows", Reg); + lua_pushliteral(L, "version"); /** version */ + lua_pushliteral(L, "-3.14"); + lua_settable(L,-3); + return 1; +} diff --git a/util/array.lua b/util/array.lua index 686f55b1..98c0ebe8 100644 --- a/util/array.lua +++ b/util/array.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/broadcast.lua b/util/broadcast.lua index 8f6af2fd..c74bf4e1 100644 --- a/util/broadcast.lua +++ b/util/broadcast.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/dataforms.lua b/util/dataforms.lua index 56671347..5a3b1fb5 100644 --- a/util/dataforms.lua +++ b/util/dataforms.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/datamanager.lua b/util/datamanager.lua index a2da0aa3..01c7aab2 100644 --- a/util/datamanager.lua +++ b/util/datamanager.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/datetime.lua b/util/datetime.lua index c582a424..cf00e4c3 100644 --- a/util/datetime.lua +++ b/util/datetime.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/dependencies.lua b/util/dependencies.lua index baa0cee2..6024dd63 100644 --- a/util/dependencies.lua +++ b/util/dependencies.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/events.lua b/util/events.lua index ef8fc30a..363d2ac6 100644 --- a/util/events.lua +++ b/util/events.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/helpers.lua b/util/helpers.lua index e69f1d98..11356176 100644 --- a/util/helpers.lua +++ b/util/helpers.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/hmac.lua b/util/hmac.lua index 18c559b2..66dd41d8 100644 --- a/util/hmac.lua +++ b/util/hmac.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/import.lua b/util/import.lua index d5e72eb9..81401e8b 100644 --- a/util/import.lua +++ b/util/import.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/iterators.lua b/util/iterators.lua index ba33bc80..318c1a96 100644 --- a/util/iterators.lua +++ b/util/iterators.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/jid.lua b/util/jid.lua index b43247cc..ba9730fa 100644 --- a/util/jid.lua +++ b/util/jid.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/logger.lua b/util/logger.lua index a73c7eec..fb0bc37b 100644 --- a/util/logger.lua +++ b/util/logger.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/multitable.lua b/util/multitable.lua index 49659605..66b9bd8a 100644 --- a/util/multitable.lua +++ b/util/multitable.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/pluginloader.lua b/util/pluginloader.lua index 8c22c204..90138a3e 100644 --- a/util/pluginloader.lua +++ b/util/pluginloader.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/prosodyctl.lua b/util/prosodyctl.lua index 0776fc76..04d58d1d 100644 --- a/util/prosodyctl.lua +++ b/util/prosodyctl.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/sasl.lua b/util/sasl.lua index 9c8fff78..eb71956b 100644 --- a/util/sasl.lua +++ b/util/sasl.lua @@ -1,5 +1,5 @@ -- sasl.lua v0.4 --- Copyright (C) 2008-2009 Tobias Markmann +-- Copyright (C) 2008-2010 Tobias Markmann -- -- All rights reserved. -- @@ -143,7 +143,7 @@ function method:process(message) end -- load the mechanisms -load_mechs = {"plain", "digest-md5", "anonymous", "scram"} +local load_mechs = {"plain", "digest-md5", "anonymous", "scram"} for _, mech in ipairs(load_mechs) do local name = "util.sasl."..mech; local m = require(name); diff --git a/util/sasl/digest-md5.lua b/util/sasl/digest-md5.lua index 5b8f5c8a..04acf04d 100644 --- a/util/sasl/digest-md5.lua +++ b/util/sasl/digest-md5.lua @@ -35,8 +35,6 @@ local function digest(self, message) local function serialize(message) local data = "" - if type(message) ~= "table" then error("serialize needs an argument of type table.") end - -- testing all possible values if message["realm"] then data = data..[[realm="]]..message.realm..[[",]] end if message["nonce"] then data = data..[[nonce="]]..message.nonce..[[",]] end diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 4f800529..103e8a90 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -15,7 +15,6 @@ local s_match = string.match; local type = type local string = string local base64 = require "util.encodings".base64; -local xor = require "bit".bxor local hmac_sha1 = require "util.hmac".sha1; local sha1 = require "util.hashes".sha1; local generate_uuid = require "util.uuid".generate; diff --git a/util/sasl_cyrus.lua b/util/sasl_cyrus.lua index 57c6ba3c..b5f505eb 100644 --- a/util/sasl_cyrus.lua +++ b/util/sasl_cyrus.lua @@ -39,24 +39,37 @@ local function init(service_name) if st then initialized = true; else - log("error", "Failed to initialize CyrusSASL: %s", errmsg); + log("error", "Failed to initialize Cyrus SASL: %s", errmsg); end end end -- create a new SASL object which can be used to authenticate clients -function new(realm, service_name) +function new(realm, service_name, app_name) local sasl_i = {}; - init(service_name); + init(app_name or service_name); sasl_i.realm = realm; sasl_i.service_name = service_name; - sasl_i.cyrus = cyrussasl.server_new(service_name, nil, nil, nil, nil) - if sasl_i.cyrus == 0 then - log("error", "got NULL return value from server_new") + + local st, ret = pcall(cyrussasl.server_new, service_name, nil, realm, nil, nil) + if st then + sasl_i.cyrus = ret; + else + log("error", "Creating SASL server connection failed: %s", ret); return nil; end + + if cyrussasl.set_canon_cb then + local c14n_cb = function (user) + local node = s_match(user, "^([^@]+)"); + log("debug", "Canonicalizing username %s to %s", user, node) + return node + end + cyrussasl.set_canon_cb(sasl_i.cyrus, c14n_cb); + end + cyrussasl.setssf(sasl_i.cyrus, 0, 0xffffffff) local s = setmetatable(sasl_i, method); return s; @@ -69,7 +82,7 @@ end -- set the forbidden mechanisms function method:forbidden( restrict ) - log("debug", "Called method:forbidden. NOT IMPLEMENTED.") + log("warn", "Called method:forbidden. NOT IMPLEMENTED.") return {} end @@ -87,6 +100,7 @@ end -- select a mechanism to use function method:select(mechanism) self.mechanism = mechanism; + if not self.mechs then self:mechanisms(); end return self.mechs[mechanism]; end @@ -109,16 +123,12 @@ function method:process(message) return "challenge", data elseif (err == -4) then -- SASL_NOMECH log("debug", "SASL mechanism not available from remote end") - return "failure", - "undefined-condition", - "SASL mechanism not available" + return "failure", "invalid-mechanism", "SASL mechanism not available" elseif (err == -13) then -- SASL_BADAUTH return "failure", "not-authorized", cyrussasl.get_message( self.cyrus ) else log("debug", "Got SASL error condition %d", err) - return "failure", - "undefined-condition", - cyrussasl.get_message( self.cyrus ) + return "failure", "undefined-condition", cyrussasl.get_message( self.cyrus ) end end diff --git a/util/serialization.lua b/util/serialization.lua index 7071d3f7..bad2fe43 100644 --- a/util/serialization.lua +++ b/util/serialization.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/set.lua b/util/set.lua index 5f7a9ae2..ee154ece 100644 --- a/util/set.lua +++ b/util/set.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/stanza.lua b/util/stanza.lua index 065888d0..08ef2c9a 100644 --- a/util/stanza.lua +++ b/util/stanza.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -247,14 +247,14 @@ function deserialize(stanza) for i=1,#attr do attr[i] = nil; end local attrx = {}; for att in pairs(attr) do - if s_find(att, "|", 1, true) and not s_find(k, "\1", 1, true) then - local ns,na = s_match(k, "^([^|]+)|(.+)$"); + if s_find(att, "|", 1, true) and not s_find(att, "\1", 1, true) then + local ns,na = s_match(att, "^([^|]+)|(.+)$"); attrx[ns.."\1"..na] = attr[att]; attr[att] = nil; end end for a,v in pairs(attrx) do - attr[x] = v; + attr[a] = v; end setmetatable(stanza, stanza_mt); for _, child in ipairs(stanza) do diff --git a/util/termcolours.lua b/util/termcolours.lua index 905b70a6..4e267bee 100644 --- a/util/termcolours.lua +++ b/util/termcolours.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/timer.lua b/util/timer.lua index c52d9c68..fa1dd7c5 100644 --- a/util/timer.lua +++ b/util/timer.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -55,11 +55,12 @@ if not event then else local EVENT_LEAVE = (event.core and event.core.LEAVE) or -1; function _add_task(delay, func) - event_base:addevent(nil, 0, function () + local event_handle; + event_handle = event_base:addevent(nil, 0, function () local ret = func(); if ret then return 0, ret; - else + elseif event_handle then return EVENT_LEAVE; end end diff --git a/util/uuid.lua b/util/uuid.lua index 19bf2234..796c8ee4 100644 --- a/util/uuid.lua +++ b/util/uuid.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -32,7 +32,7 @@ local function _seed(x) buffer = new_random(buffer..x); end local function get_nibbles(n) - if #buffer < n then seed(uniq_time()); end + if #buffer < n then _seed(uniq_time()); end local r = buffer:sub(0, n); buffer = buffer:sub(n+1); return r; diff --git a/util/xmlrpc.lua b/util/xmlrpc.lua index 4855b323..29815b0d 100644 --- a/util/xmlrpc.lua +++ b/util/xmlrpc.lua @@ -1,6 +1,6 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. diff --git a/util/ztact.lua b/util/ztact.lua index 35902ba1..2507bf8e 100644 --- a/util/ztact.lua +++ b/util/ztact.lua @@ -114,7 +114,7 @@ function tohex (s) -- - - - - - - - - - - - - - - - - - - - - - - - - tohex function tostring_r (d, indent, tab0) -- - - - - - - - - - - - - tostring_r - tab1 = tab0 or {} + local tab1 = tab0 or {} local rep = string.rep (' ', indent or 0) if type (d) == 'table' then for k,v in pairs (d) do @@ -210,7 +210,7 @@ function enqueue (queue, element) -- - - - - - - - - - - - - - - - - enqueue local function test_queue () - t = {} + local t = {} enqueue (t, 1) enqueue (t, 2) enqueue (t, 3) |