Merge with backout
authorMatthew Wild <mwild1@gmail.com>
Fri, 21 May 2010 18:45:33 +0000 (19:45 +0100)
committerMatthew Wild <mwild1@gmail.com>
Fri, 21 May 2010 18:45:33 +0000 (19:45 +0100)
118 files changed:
.hgignore
HACKERS
Makefile
README
TODO
configure
core/certmanager.lua
core/componentmanager.lua
core/configmanager.lua
core/eventmanager.lua
core/hostmanager.lua
core/loggingmanager.lua
core/modulemanager.lua
core/offlinemanager.lua
core/rostermanager.lua
core/s2smanager.lua
core/sessionmanager.lua
core/stanza_router.lua
core/usermanager.lua
core/xmlhandlers.lua
fallbacks/bit.lua
man/prosodyctl.man
net/adns.lua
net/connlisteners.lua
net/dns.lua
net/http.lua
net/httpclient_listener.lua
net/httpserver.lua
net/httpserver_listener.lua
net/server.lua
net/server_event.lua
net/server_select.lua
net/xmppclient_listener.lua
net/xmppcomponent_listener.lua
net/xmppserver_listener.lua
plugins/mod_announce.lua
plugins/mod_bosh.lua
plugins/mod_component.lua
plugins/mod_compression.lua
plugins/mod_console.lua
plugins/mod_debug.lua [deleted file]
plugins/mod_dialback.lua
plugins/mod_disco.lua
plugins/mod_groups.lua
plugins/mod_httpserver.lua
plugins/mod_iq.lua
plugins/mod_lastactivity.lua
plugins/mod_legacyauth.lua
plugins/mod_message.lua
plugins/mod_offline.lua [deleted file]
plugins/mod_pep.lua
plugins/mod_ping.lua
plugins/mod_posix.lua
plugins/mod_presence.lua
plugins/mod_privacy.lua
plugins/mod_private.lua
plugins/mod_proxy65.lua
plugins/mod_register.lua
plugins/mod_roster.lua
plugins/mod_saslauth.lua
plugins/mod_selftests.lua [deleted file]
plugins/mod_time.lua
plugins/mod_tls.lua
plugins/mod_uptime.lua
plugins/mod_vcard.lua
plugins/mod_version.lua
plugins/mod_watchregistrations.lua
plugins/mod_welcome.lua
plugins/muc/mod_muc.lua
plugins/muc/muc.lib.lua
prosody
prosody.cfg.lua.dist
prosodyctl
tests/test.lua
tests/test_core_configmanager.lua
tests/test_core_modulemanager.lua
tests/test_core_s2smanager.lua
tests/test_core_stanza_router.lua
tests/test_sasl.lua
tests/test_util_jid.lua
tests/test_util_multitable.lua
tests/test_util_stanza.lua
tests/util/logger.lua
tools/ejabberd2prosody.lua
tools/ejabberdsql2prosody.lua
tools/erlparse.lua
util-src/encodings.c
util-src/hashes.c
util-src/pposix.c
util-src/windows.c
util/array.lua
util/broadcast.lua
util/dataforms.lua
util/datamanager.lua
util/datetime.lua
util/dependencies.lua
util/events.lua
util/helpers.lua
util/hmac.lua
util/import.lua
util/iterators.lua
util/jid.lua
util/logger.lua
util/multitable.lua
util/pluginloader.lua
util/prosodyctl.lua
util/sasl.lua
util/sasl/digest-md5.lua
util/sasl/scram.lua
util/sasl_cyrus.lua
util/serialization.lua
util/set.lua
util/stanza.lua
util/termcolours.lua
util/timer.lua
util/uuid.lua
util/xmlrpc.lua
util/ztact.lua

index b7f3c20ce2d65d163e93cbd63d6fa161a5df9fbe..3449e6efa67efe5ab904a905b6b73d08e3e63431 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -6,6 +6,7 @@ www_files
 html/*
 prosody.lua
 prosody.cfg.lua
+prosody.version
 config.unix
 *.patch
 *.orig
diff --git a/HACKERS b/HACKERS
index a8585af0fb095dac4548e50419b2c392e7c1ec36..40cbd8aa5e7a8007ee5cef1264f979da59ae764c 100644 (file)
--- a/HACKERS
+++ b/HACKERS
@@ -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 :)
index 46dddfdb7768ce770b01010525b1d26c0a0d76c7..4090d554336b46cddeffc63423452e077bac2602 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/README b/README
index a28f135d80bb08383d3a24b7902ef54b357880ac..3cffea4912e082a0e84db34328f8e82f3d2504ce 100644 (file)
--- a/README
+++ b/README
@@ -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
 
 
diff --git a/TODO b/TODO
index a3266d82492e0b210da1a8f6db3750c27a93890d..c0d2b959cffd937db3954ef4c42d5b476822713c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -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
index 207fd0c1a6d2c96ddd0dfddda9425c7bda3ac251..f2d8fc098624b48a289510e73285cdf9a0ecfa12 100755 (executable)
--- a/configure
+++ b/configure
@@ -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
index 5794ba6ecf2b9c94784e301fd5e4e553bc48e534..fa920b91db15e2404e3a53378de46836f2175843 100644 (file)
@@ -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);
index cc505894ad9f5fd11a502b04234e8885b0159d3d..48e279846ce2d800a6726337bcb84f3336cf7ccc 100644 (file)
@@ -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.
index 0f20fd3ee124f8fc2b2a7c14b1cef243535d107f..54fb0a9ae82fdb61d22f4d1600f27855f84a3d46 100644 (file)
@@ -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
index e1cc9d2e81a54db9f081aee704bbcee80fc85d9e..0e766c30881ffcee78a6a361ac08346b0fbec6b2 100644 (file)
@@ -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.
index 7071296ffecc69dd635e847ad81dba9227ed5f1a..c8928b27e3aaa6dfcb1575f84f65fe432e2e0f73 100644 (file)
@@ -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
        
index 1bf90db10c07e2044f2190daf6e4bd3d5d0a04f5..3ec696d50049d1c67f17bbff30f8ecab3afda2dc 100644 (file)
@@ -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;
 
index 6b2260f5728bf21a4cb58a4c3e26cb8ba0df8f57..8e62aecb8231ee8e6e50b8f2a071b4197b44b33d 100644 (file)
@@ -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"));
index 37e9377713de9cfc024393b77292a21ad5ee30dd..97781e829386ac6989ba0875a621b85a198132b7 100644 (file)
@@ -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.
index 516983a9dfcb934af9f0b8837bb42f7aa41180ea..e2a92696391063c72c55026e47db68d1871602e5 100644 (file)
@@ -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");
index 602d6837bc1a9bd23471921dd09cdb8f7d1cbaf8..ca87670a766f38a357ddfde21df266955e88640f 100644 (file)
@@ -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;
index 29adcfbb732779cfc21e66af7605028b9c70a9a4..6e771a8444819c261e114f7dbd0d8461b1efbf24 100644 (file)
@@ -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)
index 71e40681a4db34e022cca6e61d9571f294b57ff4..d6dd53062d655ae59768b097a0c9b71d7c6d1a5e 100644 (file)
@@ -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
 
index 925ac774071489eedae3dfae20bd3547d23f9452..42e49d389ad5f00115492a45f9ccc61bd9e72188 100644 (file)
@@ -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
 
index 77f00beaab8b54fa17cc58fa9b8f710d3945995b..b7992f77a817cdf8e7bc279ec4f92a3a3c2768cb 100644 (file)
@@ -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.
index 75109d40471ef0b9ed4d058ef882523cbdd4c3e3..2482c473e8cab4f7fd0b6a58dc0e2bd0d0d518e8 100644 (file)
@@ -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.
index e677443fa6d14e8b5f3142ee28908db583f799f9..6dcb04cda678feb9d403844d79df32ef346c87bb 100644 (file)
@@ -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>
index 4341ffb52535a7fa7e900eddd9f2995f79949813..88d4b4b39c4c1e2b71e0b9c36424f2b998ad1700 100644 (file)
@@ -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
index ee54f0494e9a9b4ef92149f737172f19256daf30..93dce8b3aecb5c179c2bb09e7ee6a41c325af6ef 100644 (file)
@@ -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.
index ca5f3c621d150bc9367ab65d3bc95e11786ad73e..c0de97fd426db6f3573332cda332072028bedc7c 100644 (file)
@@ -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
index 9b1954da5dc113b87e8c45ee2fe7a377d7f90b28..0634d77391b72015f90e40571a60844c0776d776 100644 (file)
@@ -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
 
index 6517de442f9e90aad7d8abb4914cad433847c16d..dfa250623af523d18c4950608c42cfe043afd78f 100644 (file)
@@ -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;
index 79705e6f5920234fcc4db87f89241b01fe855acc..59ddbb12494d915ec1d39e52c9ed89799028cb1d 100644 (file)
@@ -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.
index 6933b4fe95f94a62683259414aa4cb28851a8d63..dd14b43c9926f845197090edd8be626911757d0b 100644 (file)
@@ -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
index 0102cee65a13daaf546bcf8e5a55ed37430f15f2..e0d4b85a971e6131c74d7fd7d872d95c917eb180 100644 (file)
@@ -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;
index 8243a8a12231936e14d73cf70b6242f09df70c73..43e70a0f7f135a0e1e7d4eb9915ad5ca7f18df2b 100644 (file)
@@ -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,
index 685cd13e978503f6bdc310399b5acca8e13c771d..e3a389a878864aa959d40fd3338170aa5be1c5c4 100644 (file)
@@ -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,
index 3a0c65beaa98dfcbdf0a2a902edbe1b83465fb16..94daa2b2f7c95f8f846cf451da31ebe85620288a 100644 (file)
@@ -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
 
index 0b98b6bce9cd7da66572f6194e3904ee955a8ecb..b87f7c96cf500e285bfbdda8552b1df35c916ad9 100644 (file)
@@ -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
index c9746ee1281fe91c4921c7c88646b5576738a14c..d1272edb117917270c8c02ef550d2a5d61da8f6f 100644 (file)
@@ -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;
index 118ba13d3a56e50243ab1bf8f184526c359afbb3..7f08a6e0ecad85980e7b87a2c3fa8f6dbde96ade 100644 (file)
@@ -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.
index 2cb3100ee1243d6b8bfbb80802b068b3589eee14..66a79785dea936ba77779028c768039ccdb8fcb0 100644 (file)
@@ -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);
index d9783b0cebd7c6926abada667c1bb4302f5fa07e..7efb4f9c3e94c2c4076854445103ed2267f7b065 100644 (file)
@@ -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.
index 4b1fa79f12f24b9b1aa347912473bc190dac4149..c2e84f2b022b73892cf062997caac8ae488678d1 100644 (file)
@@ -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
 );
index 6d387b0eb77e5221d76d4fc9e2a87c37c6a8857a..e87ef536158cf39afb295406fcd929cdcc6dfa5a 100644 (file)
@@ -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 (file)
index 9f80202..0000000
+++ /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
index 469044cd34f347cf5666c6f9156b9ba0037d9c50..189aeb363c5f30a95ade745334dcac28500038ac 100644 (file)
@@ -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.
index f7e51b83e3dbadaa1a5714fab2b3a3bf76d5d1da..ee0043f1d223455e9637c8aac00b0792e73dfe83 100644 (file)
@@ -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.
index f31bb1a883d9e1ae331c4b30a50f34f55df7340f..de7b8302267dc52f90a63c139eb8fc6fb2cff2bb 100644 (file)
@@ -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;
index 07c7f3154b4d08a92c7a00acfd8f7dc9ff1f6365..c55bd20f9b5b56c5c6e1c7ced8f32bc585fd3228 100644 (file)
@@ -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.
index 5be045335c478e256913228207d31fc76b6f3719..b3001fe5139b633c0f8edec60fa3fc0bb1429b80 100644 (file)
@@ -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;
index a0da98299720831df90bb98f79c0ecabac4fc4c1..11053709bc0b99239ab21ce3bd7d080541a48a79 100644 (file)
@@ -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.
index 9837920b43c96947b4c9398eddd3fded5dab814e..0134d736d831440479573d42e5a5b91d046af44a 100644 (file)
@@ -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.
index 395307ba582221ff4c7b4df02dc108876a1f0070..d5b40ed52f7600ef9ef5e5a54b67bb488e34e5e2 100644 (file)
@@ -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 (file)
index c74d011..0000000
+++ /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.
---
-
-\r
-local datamanager = require "util.datamanager";\r
-local st = require "util.stanza";\r
-local datetime = require "util.datetime";\r
-local ipairs = ipairs;
-local jid_split = require "util.jid".split;\r
-\r
-module:add_feature("msgoffline");\r
-\r
-module:hook("message/offline/store", function(event)\r
-       local origin, stanza = event.origin, event.stanza;\r
-       local to = stanza.attr.to;\r
-       local node, host;\r
-       if to then\r
-               node, host = jid_split(to)\r
-       else\r
-               node, host = origin.username, origin.host;\r
-       end\r
-       \r
-       stanza.attr.stamp, stanza.attr.stamp_legacy = datetime.datetime(), datetime.legacy();\r
-       local result = datamanager.list_append(node, host, "offline", st.preserialize(stanza));\r
-       stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;\r
-       \r
-       return true;\r
-end);\r
-\r
-module:hook("message/offline/broadcast", function(event)\r
-       local origin = event.origin;\r
-       local node, host = origin.username, origin.host;\r
-       \r
-       local data = datamanager.list_load(node, host, "offline");\r
-       if not data then return true; end\r
-       for _, stanza in ipairs(data) do\r
-               stanza = st.deserialize(stanza);\r
-               stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = host, stamp = stanza.attr.stamp}):up(); -- XEP-0203\r
-               stanza:tag("x", {xmlns = "jabber:x:delay", from = host, stamp = stanza.attr.stamp_legacy}):up(); -- XEP-0091 (deprecated)\r
-               stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil;\r
-               origin.send(stanza);\r
-       end\r
-       return true;\r
-end);\r
-\r
-module:hook("message/offline/delete", function(event)\r
-       local origin = event.origin;\r
-       local node, host = origin.username, origin.host;\r
-\r
-       return datamanager.list_store(node, host, "offline", nil);\r
-end);\r
index c42876b85d360c767f11440491d2e0087933392f..aa46d2d31807bb526a595b4e6d4da1fd756141c6 100644 (file)
@@ -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.
index 1dc9fbec901069e63023043248f9ef87dee30b5b..61b717a211476773d47520a0a2ad5722e1dc5bce 100644 (file)
@@ -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.
index 55d52ccda1e09419a2d92b88e391b421de463562..c38f7eba75399bb9d9e421595f278454c77ec573 100644 (file)
@@ -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
index a39d9c19cd87d2de3b5d0e5ccb09e0cc17d4ca5b..108ab0d309cc355a034c7e14ebe1516a308d7722 100644 (file)
@@ -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.
index d3043d6963d34387b9eb9fb54caceb99530ba81c..3e9dbe49b88f27566816dc42ab8b2ddf5947bbcf 100644 (file)
@@ -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
index 098dbba18421439ec5f6679a8f583befa918a8fa..859bf45a6ec12bc5dbc406a59b48c4279f9175b5 100644 (file)
@@ -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.
index 2cfbe7b632addec9207c8ae7810daade953127a4..190d30bef5a9d9fae1b41be3bf1c6c937b3e5776 100644 (file)
@@ -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
index be1be0aebecb1dca7c28a74df66e74af49ff8c90..b8d142f7c5b0c865e8d0ffa65371dd7a284386ba 100644 (file)
@@ -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?
index 4362dca29d8a937cfff3006648707c01bfd5063a..ddf02f2f808f4715694517e13f52cd2fe89b77dc 100644 (file)
@@ -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
index 398ae9f850a2a3777a908b0b7d959a731365fc48..9f940c37fcc60a2dfac4da684d6fe85a14848caf 100644 (file)
@@ -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 (file)
index 1f41363..0000000
+++ /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
index 7d900ae9cee4526a91bd8e10a9ea664d9eaa661f..cb69ebe791d1d1d1920e24a8d291fe9a6a22adad 100644 (file)
@@ -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.
index 1a00c36e06736a2f877355f7e7e119c352741c05..8b96aa157922c7bf1f63613a0e000e3baf72851f 100644 (file)
@@ -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;
index cf6c6b64785480f6a5251ab7ecd69b53ccffb479..24d101803b860712a03e707624d476f03adfb6d0 100644 (file)
@@ -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.
index 6bf82ee7e484d6afa9cfc5632758096ba8789cec..e2f1dfb84cca78c504fdf1c3b39b1375c2e623f7 100644 (file)
@@ -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.
index 9af830f8b3a2f39b5d2b6626d3c5fca54a064320..69e914c0c0aca904e1e51e0a7573d4936f9fb522 100644 (file)
@@ -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.
index 6a2af8532cc8f20abddb18a6d9a466eba87f9ce0..f006818e7c06dafabe17513dd62738433ccf8a4e 100644 (file)
@@ -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.
index edcfbd8c0f134306b45cef949bba672f4e0f7d56..8f92010a013d7279bac927f178f4651ce0901820 100644 (file)
@@ -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.
index d23e2474bec9ec09d272461dc8d0f45c3fda9c83..de23aebba736752959bc92a93e4e77a19b3fc911 100644 (file)
@@ -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.
index ad45bbfd462caed12d70937cd0d173a646c98765..18c80325bbd1bce5db492b36643407d4d1b4bf65 100644 (file)
@@ -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
diff --git a/prosody b/prosody
index 49580bd91deafd9b36a0eac4acaf6cb8a0319f48..e4e821050d60829c9b8c652d33e003ec7bde470c 100755 (executable)
--- a/prosody
+++ b/prosody
@@ -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();
index de07d7c52b64e102d1a99317f5d577646b71a298..a17eb8773aaaababdb3cffe49ecb5419f61860f7 100644 (file)
 -- 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"
index 9d2df69ede44490de53a6b36dca856aa04595638..ccc1e2f9cfe5d86f8d3d55353d3842911aad35be 100755 (executable)
@@ -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 = {};
 
index b71ccc1f1d8c889af6d50be2936270add712f505..38ef6191ad4191a2ae49a88fd24a6513e9478f19 100644 (file)
@@ -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.
index 533845b353b1ee62b5013a8449a373a8d18a64dd..c4ed746faf888438b2c0679ccf91b8942a860490 100644 (file)
@@ -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.
index 82e9aa45c98894222e25073f8b41ab0274e667f0..9498875aeef65607bf828c4f87986449a5f63bc8 100644 (file)
@@ -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.
index 8635ed24c1982f909d601d6d9ba124def9c7d518..b49c7da6cd2827790d538ee66c40e6dabbf30c2c 100644 (file)
@@ -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
index 59e68b910189c6e8deb24af94f7a4ca57809f4c3..97dc2e19358c88c9504e988e958d4d5eef473fda 100644 (file)
@@ -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.
index e279a975ab780bd92a77e0d5c22ec44ca1969da2..7c0b02f871a1e49030c8f0224fde0e32f8df6374 100644 (file)
@@ -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.
index f579e59789dcff2947fe457d70fb2b24bc336e58..5cc1390b6c96508c69cfea2f980a5862be853ea6 100644 (file)
@@ -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.
index b8437bf5c5da94b9eefb192e60b90a65d3f4d4d2..4b7e4fccff88bbb073f824d724edcffb5fb4ef1c 100644 (file)
@@ -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.
index 0819f2c75a3690d3f10b127d8ea452ea07446db5..7916a0c10dac87127f788674bdac7d37f39f79fc 100644 (file)
@@ -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.
index 003c5946a391ce11872db6093d7a9ae8cb41376f..e62a1aa8ccca4c991e60d09b4ddea2b099886eca 100644 (file)
@@ -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.
index 7b19260d749fc2cc74fc0e9bc8eb2bda401a68a6..a231abd8c0505b7e1b5dae196cd7741e67fd5140 100755 (executable)
@@ -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 {};
index f652af5ba034a4caa0c20a3a142826c8acc9d291..ef4706ce81382ae854083d530e615c45c4ba6848 100644 (file)
@@ -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)
index bfec3b4da2c17bdfd6fe0e07be0f74ee386282f7..dc3a2f94e6d44c3d03fa20d09dc57c94bec31d69 100644 (file)
@@ -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];
index c573a330b6709ba4a8feb4b69771944309f49ab6..f2109d0c1a2433e2b0f88afd5b9e5f5a00046576 100644 (file)
@@ -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.
index 907167e2c297abdc132d27f8dd30b2700d30fede..33a9be891c4467f119ab0e32e9082496c6dd4d24 100644 (file)
@@ -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.
index 8c1dbcc6f9a754c5626ecebc2a3cd5eb4e506597..9f16f178b6cffd34e529babf1ad8674a60988a7e 100644 (file)
@@ -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
index 7fb963121c7bd309aa055026e2ebb082364c078b..12bd7ce9623259a05ddd83bbcc9f66f69f9fe966 100644 (file)
@@ -1,45 +1,58 @@
-\r
-#include <stdio.h>\r
-#include <windows.h>\r
-#include <windns.h>\r
-\r
-#include "lua.h"\r
-#include "lauxlib.h"\r
-\r
-static int Lget_nameservers(lua_State *L) {\r
-       char stack_buffer[1024]; // stack allocated buffer\r
-       IP4_ARRAY* ips = (IP4_ARRAY*) stack_buffer;\r
-       DWORD len = sizeof(stack_buffer);\r
-       DNS_STATUS status;\r
-\r
-       status = DnsQueryConfig(DnsConfigDnsServerList, FALSE, NULL, NULL, ips, &len);\r
-       if (status == 0) {\r
-               DWORD i;\r
-               lua_createtable(L, ips->AddrCount, 0);\r
-               for (i = 0; i < ips->AddrCount; i++) {\r
-                       DWORD ip = ips->AddrArray[i];\r
-                       char ip_str[16] = "";\r
-                       sprintf_s(ip_str, sizeof(ip_str), "%d.%d.%d.%d", (ip >> 0) & 255, (ip >> 8) & 255, (ip >> 16) & 255, (ip >> 24) & 255);\r
-                       lua_pushstring(L, ip_str);\r
-                       lua_rawseti(L, -2, i+1);\r
-               }\r
-               return 1;\r
-       } else {\r
-               luaL_error(L, "DnsQueryConfig returned %d", status);\r
-               return 0; // unreachable, but prevents a compiler warning\r
-       }\r
-}\r
-\r
-static const luaL_Reg Reg[] =\r
-{\r
-       { "get_nameservers",    Lget_nameservers        },\r
-       { NULL,         NULL    }\r
-};\r
-\r
-LUALIB_API int luaopen_util_windows(lua_State *L) {\r
-       luaL_register(L, "windows", Reg);\r
-       lua_pushliteral(L, "version");                  /** version */\r
-       lua_pushliteral(L, "-3.14");\r
-       lua_settable(L,-3);\r
-       return 1;\r
-}\r
+/* 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;
+}
index 686f55b1ef2f0b855039dc3cf89630b4388a708e..98c0ebe8a4586669bdeae53f3d99b008047dd81a 100644 (file)
@@ -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.
index 8f6af2fdd2f65bb633e648ce774d4dcde1d774d5..c74bf4e1b9e2b721961eb8c3243468b424874a63 100644 (file)
@@ -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.
index 56671347a86eb4b6fe96cef917f66e5b6c8f90a8..5a3b1fb5652c969fb1cc5e329dcae8dbca04613d 100644 (file)
@@ -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.
index a2da0aa344c50859001904beb43ce58f284e8ad1..01c7aab2210f85f817f7e6c63620d5d37cab7937 100644 (file)
@@ -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.
index c582a424f8bfafec6e05e6b9b5452034f2d71720..cf00e4c320323a03d137742bb2dd0fd5143df2a2 100644 (file)
@@ -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.
index baa0cee213148c98594de74041bb95a8e3a4f1c7..6024dd63e6b5154fe7ac7f4cd7914be48da00631 100644 (file)
@@ -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.
index ef8fc30ab5bab24300851a8269a10682c05b97a0..363d2ac6b0907977e862e281fb84756a6f03de91 100644 (file)
@@ -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.
index e69f1d98c3540032d7bcca9bb8cd77c01ada1a9b..1135617606210d4419d1567dd9e10ea65d1a640a 100644 (file)
@@ -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.
index 18c559b220d17fe0afbeaf0eaebd51e8dc3a621d..66dd41d81d8978796d371bc64ed080f8a35da4c4 100644 (file)
@@ -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.
index d5e72eb9d725f99192f7f15e6b0feaa307bb0c88..81401e8b503a0433c7382cd99cda9e13342cf2ae 100644 (file)
@@ -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.
index ba33bc80b1e5ebb417dc6513ff5eaa9317a46390..318c1a96b8fad3b45f1d7111ef130d98ab34e8f0 100644 (file)
@@ -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.
index b43247ccbbd0d055bbeca6ff6e5c78a8e8ab2ccf..ba9730fa3c57d3a85eb3aa8b22d19199ea256d4f 100644 (file)
@@ -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.
index a73c7eec90c156903f06bb71a6288a62284868f9..fb0bc37b8a1edb923397b786863d66aa86b751c9 100644 (file)
@@ -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.
index 49659605bd117bf9c8175359a104911bcf9538dd..66b9bd8aba1a90481d80efcaa056773552a61f60 100644 (file)
@@ -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.
index 8c22c2049c2bbc8f89b46b94a83d4cb3279a2758..90138a3eff86b895e6d719bb5a8cddd2a6096d7c 100644 (file)
@@ -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.
index 0776fc76e825f44b7f53015c067e5c966d502eb5..04d58d1d3af33d5775aafc241e37afcfcb206a72 100644 (file)
@@ -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.
index 9c8fff7804a28edd6b7e4e430b846d3d23093696..eb71956b692aa5942bf0690b4787865132f588ce 100644 (file)
@@ -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);
index 5b8f5c8a6ab4f6b28a73caee6f0981a79fb94964..04acf04dcde50bbc9735c4c16eb78df5aceff663 100644 (file)
@@ -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
index 4f80052908cd7148b8d123edfaa5e61f36d02a48..103e8a905d65373efb062cdd5020495773760e75 100644 (file)
@@ -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;
index 57c6ba3cbb3b68c3ad6d1ef9f1b75e123ad94011..b5f505ebbc2f5cd99ab85cdb34bae24ba1ec07d2 100644 (file)
@@ -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
 
index 7071d3f75e03f4af116919ff53f29fbf9b1578f6..bad2fe43dddf7cc0b7ec17da6892f10dffe4f646 100644 (file)
@@ -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.
index 5f7a9ae243cef7d92bc13c63e1d32aed62bb3cb0..ee154ece11e1f5977be607735fa197acf10de4e4 100644 (file)
@@ -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.
index 065888d060caadeb71fc92ccc9a48cfce946e506..08ef2c9aa1649deac35eca8fd38488e7982a5372 100644 (file)
@@ -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
index 905b70a627fc593962466b94c85a88efff086ef1..4e267bee438fe2e7b4970b2c750d3d340001db36 100644 (file)
@@ -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.
index c52d9c68bb2ff81e2d093f9d55a0e6a3baa10f47..fa1dd7c54cadde12e4bac4aa8a23304ba167bc96 100644 (file)
@@ -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
index 19bf2234d04e223c985c24c651ca44f417379c33..796c8ee4c47247dd049e6bb3561ab5223ced74bc 100644 (file)
@@ -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;
index 4855b323f4740375f8ec59fc4569701d836b0918..29815b0d94fc3a427642475fdc2185b486de0b5c 100644 (file)
@@ -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.
index 35902ba14710d61df50188722628e6ab0637829e..2507bf8e0107fadc90c93cf23de6a522503f7fee 100644 (file)
@@ -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)