# HG changeset patch # User Tobias Markmann # Date 1246813525 -7200 # Node ID 66f18c18befafa55865cac5d613734cc2aafe864 # Parent 3e04efa8af7e2beba2b1b6e1565dd9b638cb334d# Parent efd19cdda6caab1147eec30d7bf79373f459add0 Merge with main branch. diff -r 3e04efa8af7e -r 66f18c18befa Makefile --- a/Makefile Sun Jul 05 19:05:03 2009 +0200 +++ b/Makefile Sun Jul 05 19:05:25 2009 +0200 @@ -6,6 +6,7 @@ MODULES = $(DESTDIR)$(PREFIX)/lib/prosody/modules SOURCE = $(DESTDIR)$(PREFIX)/lib/prosody DATA = $(DESTDIR)$(DATADIR) +MAN = $(DESTDIR)$(PREFIX)/share/man INSTALLEDSOURCE = $(PREFIX)/lib/prosody INSTALLEDCONFIG = $(SYSCONFDIR) @@ -18,16 +19,19 @@ install: prosody.install prosodyctl.install prosody.cfg.lua.install util/encodings.so util/encodings.so util/pposix.so util/signal.so install -d $(BIN) $(CONFIG) $(MODULES) $(SOURCE) install -m750 -d $(DATA) + install -d $(MAN)/man1 install -d $(CONFIG)/certs - install -d $(SOURCE)/core $(SOURCE)/net $(SOURCE)/util + install -d $(SOURCE)/core $(SOURCE)/net $(SOURCE)/util $(SOURCE)/fallbacks install -m755 ./prosody.install $(BIN)/prosody install -m755 ./prosodyctl.install $(BIN)/prosodyctl install -m644 core/* $(SOURCE)/core install -m644 net/* $(SOURCE)/net install -m644 util/* $(SOURCE)/util + install -m644 fallbacks/* $(SOURCE)/fallbacks install -m644 plugins/* $(MODULES) install -m644 certs/* $(CONFIG)/certs install -m644 plugins/* $(MODULES) + install -m644 man/prosodyctl.man $(MAN)/man1/prosodyctl.1 test -e $(CONFIG)/prosody.cfg.lua || install -m644 prosody.cfg.lua.install $(CONFIG)/prosody.cfg.lua test -e prosody.version && install prosody.version $(SOURCE)/prosody.version || true $(MAKE) install -C util-src diff -r 3e04efa8af7e -r 66f18c18befa core/hostmanager.lua --- a/core/hostmanager.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/core/hostmanager.lua Sun Jul 05 19:05:25 2009 +0200 @@ -27,7 +27,12 @@ eventmanager.add_event_hook("server-starting", load_enabled_hosts); function activate(host, host_config) - hosts[host] = {type = "local", connected = true, sessions = {}, host = host, s2sout = {}, events = events_new() }; + hosts[host] = {type = "local", connected = true, sessions = {}, + host = host, s2sout = {}, events = events_new(), + disallow_s2s = configmanager.get(host, "core", "disallow_s2s") + or (configmanager.get(host, "core", "anonymous_login") + and (configmanager.get(host, "core", "disallow_s2s") ~= false)) + }; log((hosts_loaded_once and "info") or "debug", "Activated host: %s", host); eventmanager.fire_event("host-activated", host, host_config); end diff -r 3e04efa8af7e -r 66f18c18befa core/s2smanager.lua --- a/core/s2smanager.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/core/s2smanager.lua Sun Jul 05 19:05:25 2009 +0200 @@ -238,7 +238,7 @@ conn:settimeout(0); local success, err = conn:connect(connect_host, connect_port); if not success and err ~= "timeout" then - log("warn", "s2s connect() failed: %s", err); + log("warn", "s2s connect() to %s (%s:%d) failed: %s", host_session.to_host, connect_host, connect_port, err); return false; end @@ -253,7 +253,7 @@ local w = conn.write; host_session.sends2s = function (t) log("debug", "sending: %s", tostring(t)); w(tostring(t)); end - conn.write(format([[]], from_host, to_host)); + conn.write(format([[]], from_host, to_host)); log("debug", "Connection attempt in progress..."); return true; end diff -r 3e04efa8af7e -r 66f18c18befa core/sessionmanager.lua --- a/core/sessionmanager.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/core/sessionmanager.lua Sun Jul 05 19:05:25 2009 +0200 @@ -40,7 +40,7 @@ local open_sessions = 0; function new_session(conn) - local session = { conn = conn, priority = 0, type = "c2s_unauthed", conntime = gettime() }; + local session = { conn = conn, type = "c2s_unauthed", conntime = gettime() }; if true then session.trace = newproxy(true); getmetatable(session.trace).__gc = function () open_sessions = open_sessions - 1; end; @@ -56,17 +56,9 @@ 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)"); - -- Send unavailable presence - if session.presence then - local pres = st.presence{ type = "unavailable" }; - if (not err) or err == "closed" then err = "connection closed"; end - pres:tag("status"):text("Disconnected: "..err):up(); - session:dispatch_stanza(pres); - end - -- Remove session/resource from user's session list if session.full_jid then - hosts[session.host].events.fire_event("resource-unbind", session); + hosts[session.host].events.fire_event("resource-unbind", {session=session, error=err}); hosts[session.host].sessions[session.username].sessions[session.resource] = nil; full_sessions[session.full_jid] = nil; @@ -132,6 +124,7 @@ }; if not next(sessions) then hosts[session.host].sessions[session.username] = { sessions = sessions }; + bare_sessions[session.username.."@"..session.host] = hosts[session.host].sessions[session.username]; end end if increment and sessions[resource] then @@ -151,7 +144,7 @@ session.roster = rm_load_roster(session.username, session.host); - hosts[session.host].events.fire_event("resource-bind", session); + hosts[session.host].events.fire_event("resource-bind", {session=session}); return true; end @@ -165,7 +158,7 @@ (session.log or session)("debug", "Client sent opening to %s", session.host); send(""); - send(format("", session.streamid, session.host)); + send(format("", session.streamid, session.host)); if not hosts[session.host] then -- We don't serve this host... diff -r 3e04efa8af7e -r 66f18c18befa core/stanza_router.lua --- a/core/stanza_router.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/core/stanza_router.lua Sun Jul 05 19:05:25 2009 +0200 @@ -173,12 +173,16 @@ core_post_stanza(origin, stanza); elseif origin.type == "c2s" then -- Remote host - local xmlns = stanza.attr.xmlns; - --stanza.attr.xmlns = "jabber:server"; - stanza.attr.xmlns = nil; - log("debug", "sending s2s stanza: %s", tostring(stanza)); - send_s2s(origin.host, host, stanza); -- TODO handle remote routing errors - stanza.attr.xmlns = xmlns; -- reset + if not hosts[from_host].disallow_s2s then + local xmlns = stanza.attr.xmlns; + --stanza.attr.xmlns = "jabber:server"; + stanza.attr.xmlns = nil; + log("debug", "sending s2s stanza: %s", tostring(stanza)); + send_s2s(origin.host, host, stanza); -- TODO handle remote routing errors + stanza.attr.xmlns = xmlns; -- reset + else + core_route_stanza(hosts[from_host], st.error_reply(stanza, "cancel", "not-allowed", "Communication with remote servers is not allowed")); + end elseif origin.type == "component" or origin.type == "local" then -- Route via s2s for components and modules log("debug", "Routing outgoing stanza for %s to %s", from_host, host); diff -r 3e04efa8af7e -r 66f18c18befa man/prosodyctl.man --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/man/prosodyctl.man Sun Jul 05 19:05:25 2009 +0200 @@ -0,0 +1,79 @@ +.TH PROSODYCTL 1 "2009-07-02" + +.SH NAME +prosodyctl \- Manage a Prosody XMPP server + +.SH SYNOPSIS +\fBprosodyctl\fP \fIcommand\fP [\fI--help\fP] + +.SH DESCRIPTION +\fBprosodyctl\fP is the control tool for the Prosody XMPP server. It may be +used to control the server daemon and manage users. + +\fBprosodyctl\fP needs to be executed with sufficient privileges to perform +its commands. This typically means executing \fBprosodyctl\fP as the root user. +If a user named "prosody" is found then \fBprosodyctl\fP will change to that +user before executing its commands. + +.SH COMMANDS +.SS User Management +In the following commands users are identified by a Jabber ID, \fIjid\fP, of the +usual form: user@domain. + +.IP "\fBadduser\fP \fIjid\fP" +Adds a user with Jabber ID, \fIjid\fP, to the server. You will be +prompted to enter the user's password. + +.IP "\fBpasswd\fP \fIjid\fP" +Changes the password of an existing user with Jabber ID, \fIjid\fP. You will be +prompted to enter the user's new password. + +.IP "\fBdeluser\fP \fIjid\fP" +Deletes an existing user with Jabber ID, \fIjid\fP, from the server. + +.SS Daemon Management +Although \fBprosodyctl\fP has commands to manage the \fBprosody\fP daemon it is +recommended that you utilize your distributions daemon management features if +you attained Prosody through a package. + +To perform daemon control commands \fBprosodyctl\fP needs a \fIpidfile\fP value +specified in \fI/etc/prosody/prosody.cfg.lua\fP. Failure to do so will cause +\fBprosodyctl\fP to complain. + +.IP \fBstart\fP +Starts the \fBprosody\fP server daemon. If run as root \fBprosodyctl\fP will +attempt to change to a user named "prosody" before executing. This operation +will block for up to five seconds to wait for the server to execute. + +.IP \fBstop\fP +Stops the \fBprosody\fP server daemon. This operation will block for up to five +seconds to wait for the server to stop executing. + +.IP \fBstatus\fP +Prints the current execution status of the \fBprosody\fP server daemon. + +.SS Ejabberd Compatibility +\fBejabberd\fP is another XMPP server which provides a comparable control tool, +\fBejabberdctl\fP, to control its server's operations. \fBprosodyctl\fP +implements some commands which are compatible with \fBejabberdctl\fP. For +details of how these commands work you should see +.BR ejabberdctl (8). + +.IP "\fBregister\fP \fIuser server password\fP" +.IP "\fBunregister\fP \fIuser server\fP" + +.SH OPTIONS +.IP \fI--help\fP +Display help text for the specified command. + +.SH FILES +.IP \fI/etc/prosody/prosody.cfg.lua\fP +The main \fBprosody\fP configuration file. \fBprosodyctl\fP reads this to +determine the process ID file of the \fBprosody\fP server daemon and to +determine if a host has been configured. + +.SH ONLINE +More information may be found online at: \fIhttp://prosody.im/\fP + +.SH AUTHORS +Dwayne Bent diff -r 3e04efa8af7e -r 66f18c18befa plugins/mod_console.lua --- a/plugins/mod_console.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/plugins/mod_console.lua Sun Jul 05 19:05:25 2009 +0200 @@ -437,6 +437,8 @@ ------------- function printbanner(session) + local option = config.get("*", "core", "console_banner"); +if option == nil or option == "full" or option == "graphic" then session.print [[ ____ \ / _ | _ \ _ __ ___ ___ _-_ __| |_ _ @@ -446,7 +448,18 @@ A study in simplicity |___/ ]] +end +if option == nil or option == "short" or option == "full" then session.print("Welcome to the Prosody administration 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/console\n"); end +if option and option ~= "short" and option ~= "full" and option ~= "graphic" then + if type(option) == "string" then + session.print(option) + elseif type(option) == "function" then + setfenv(option, redirect_output(_G, session)); + pcall(option, session); + end +end +end diff -r 3e04efa8af7e -r 66f18c18befa plugins/mod_offline.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/mod_offline.lua Sun Jul 05 19:05:25 2009 +0200 @@ -0,0 +1,47 @@ + +local datamanager = require "util.datamanager"; +local st = require "util.stanza"; +local datetime = require "util.datetime"; +local ipairs = ipairs; + +module:add_feature("msgoffline"); + +module:hook("message/offline/store", function(event) + local origin, stanza = event.origin, event.stanza; + local to = stanza.attr.to; + local node, host; + if to then + node, host = jid_split(to) + else + node, host = origin.username, origin.host; + end + + stanza.attr.stamp, stanza.attr.stamp_legacy = datetime.datetime(), datetime.legacy(); + local result = datamanager.list_append(node, host, "offline", st.preserialize(stanza)); + stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil; + + return true; +end); + +module:hook("message/offline/broadcast", function(event) + local origin = event.origin; + local node, host = origin.username, origin.host; + + local data = datamanager.list_load(node, host, "offline"); + if not data then return true; end + for _, stanza in ipairs(data) do + stanza = st.deserialize(stanza); + stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = host, stamp = stanza.attr.stamp}):up(); -- XEP-0203 + stanza:tag("x", {xmlns = "jabber:x:delay", from = host, stamp = stanza.attr.stamp_legacy}):up(); -- XEP-0091 (deprecated) + stanza.attr.stamp, stanza.attr.stamp_legacy = nil, nil; + origin.send(stanza); + end + return true; +end); + +module:hook("message/offline/delete", function(event) + local origin = event.origin; + local node, host = origin.username, origin.host; + + return datamanager.list_store(node, host, "offline", nil); +end); diff -r 3e04efa8af7e -r 66f18c18befa plugins/mod_pep.lua --- a/plugins/mod_pep.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/plugins/mod_pep.lua Sun Jul 05 19:05:25 2009 +0200 @@ -54,8 +54,9 @@ local d = data[user]; local notify = recipients[user] and recipients[user][recipient]; if d and notify then - for node, message in pairs(notify) do - if d[node] then + for node in pairs(notify) do + local message = d[node]; + if message then message.attr.to = recipient; session.send(message); end @@ -101,7 +102,7 @@ recipients[user] = recipients[user] or {}; if hash_map[hash] then recipients[user][recipient] = hash_map[hash]; - publish_all(user, recipient); + publish_all(user, recipient, origin); else recipients[user][recipient] = hash; origin.send( @@ -192,7 +193,7 @@ local notify = {}; for _, feature in pairs(disco.tags) do if feature.name == "feature" and feature.attr.var then - local nfeature = feature.attr.var:match("^(.*)+notify$"); + local nfeature = feature.attr.var:match("^(.*)%+notify$"); if nfeature then notify[nfeature] = true; end end end diff -r 3e04efa8af7e -r 66f18c18befa plugins/mod_presence.lua --- a/plugins/mod_presence.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/plugins/mod_presence.lua Sun Jul 05 19:05:25 2009 +0200 @@ -10,7 +10,7 @@ local require = require; local pairs, ipairs = pairs, ipairs; -local t_concat = table.concat; +local t_concat, t_insert = table.concat, table.insert; local s_find = string.find; local tonumber = tonumber; @@ -37,21 +37,6 @@ _core_route_stanza(origin, stanza); end -function handle_presence(origin, stanza, from_bare, to_bare, core_route_stanza, inbound) - local type = stanza.attr.type; - if type and type ~= "unavailable" and type ~= "error" then - if inbound then - handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); - else - handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); - end - elseif not inbound and not stanza.attr.to then - handle_normal_presence(origin, stanza, core_route_stanza); - else - core_route_stanza(origin, stanza); - end -end - local function select_top_resources(user) local priority = 0; local recipients = {}; @@ -76,93 +61,85 @@ end function handle_normal_presence(origin, stanza, core_route_stanza) - if origin.roster then - for jid in pairs(origin.roster) do -- broadcast to all interested contacts - local subscription = origin.roster[jid].subscription; - if subscription == "both" or subscription == "from" then + local roster = origin.roster; + local node, host = origin.username, origin.host; + for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast to all resources + if res ~= origin and res.presence then -- to resource + stanza.attr.to = res.full_jid; + core_route_stanza(origin, stanza); + end + end + for jid, item in pairs(roster) do -- broadcast to all interested contacts + if item.subscription == "both" or item.subscription == "from" then + stanza.attr.to = jid; + core_route_stanza(origin, stanza); + end + end + if stanza.attr.type == nil and not origin.presence then -- initial presence + local probe = st.presence({from = origin.full_jid, type = "probe"}); + for jid, item in pairs(roster) do -- probe all contacts we are subscribed to + if item.subscription == "both" or item.subscription == "to" then + probe.attr.to = jid; + core_route_stanza(origin, probe); + end + end + for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast from all available resources + if res ~= origin and res.presence then + res.presence.attr.to = origin.full_jid; + core_route_stanza(res, res.presence); + res.presence.attr.to = nil; + end + end + if roster.pending then -- resend incoming subscription requests + for jid in pairs(roster.pending) do + origin.send(st.presence({type="subscribe", from=jid})); -- TODO add to attribute? Use original? + end + end + local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); + for jid, item in pairs(roster) do -- resend outgoing subscription requests + if item.ask then + request.attr.to = jid; + core_route_stanza(origin, request); + end + end + local offline = offlinemanager.load(node, host); + if offline then + for _, msg in ipairs(offline) do + origin.send(msg); -- FIXME do we need to modify to/from in any way? + end + offlinemanager.deleteAll(node, host); + end + end + if stanza.attr.type == "unavailable" then + origin.presence = nil; + if origin.priority then + origin.priority = nil; + recalc_resource_map(origin); + end + if origin.directed then + for jid in pairs(origin.directed) do stanza.attr.to = jid; core_route_stanza(origin, stanza); end - end - local node, host = jid_split(stanza.attr.from); - for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast to all resources - if res ~= origin and res.presence then -- to resource - stanza.attr.to = res.full_jid; - core_route_stanza(origin, stanza); - end + origin.directed = nil; end - if stanza.attr.type == nil and not origin.presence then -- initial presence - local probe = st.presence({from = origin.full_jid, type = "probe"}); - for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to - local subscription = origin.roster[jid].subscription; - if subscription == "both" or subscription == "to" then - probe.attr.to = jid; - core_route_stanza(origin, probe); - end - end - for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast from all available resources - if res ~= origin and res.presence then - res.presence.attr.to = origin.full_jid; - core_route_stanza(res, res.presence); - res.presence.attr.to = nil; - end - end - if origin.roster.pending then -- resend incoming subscription requests - for jid in pairs(origin.roster.pending) do - origin.send(st.presence({type="subscribe", from=jid})); -- TODO add to attribute? Use original? - end - end - local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); - for jid, item in pairs(origin.roster) do -- resend outgoing subscription requests - if item.ask then - request.attr.to = jid; - core_route_stanza(origin, request); - end - end - local offline = offlinemanager.load(node, host); - if offline then - for _, msg in ipairs(offline) do - origin.send(msg); -- FIXME do we need to modify to/from in any way? - end - offlinemanager.deleteAll(node, host); - end + else + origin.presence = stanza; + local priority = stanza:child_with_name("priority"); + if priority and #priority > 0 then + priority = t_concat(priority); + if s_find(priority, "^[+-]?[0-9]+$") then + priority = tonumber(priority); + if priority < -128 then priority = -128 end + if priority > 127 then priority = 127 end + else priority = 0; end + else priority = 0; end + if origin.priority ~= priority then + origin.priority = priority; + recalc_resource_map(origin); end - if stanza.attr.type == "unavailable" then - origin.presence = nil; - if origin.priority then - origin.priority = nil; - recalc_resource_map(origin); - end - if origin.directed then - local old_from = stanza.attr.from; - stanza.attr.from = origin.full_jid; - for jid in pairs(origin.directed) do - stanza.attr.to = jid; - core_route_stanza(origin, stanza); - end - stanza.attr.from = old_from; - origin.directed = nil; - end - else - origin.presence = stanza; - local priority = stanza:child_with_name("priority"); - if priority and #priority > 0 then - priority = t_concat(priority); - if s_find(priority, "^[+-]?[0-9]+$") then - priority = tonumber(priority); - if priority < -128 then priority = -128 end - if priority > 127 then priority = 127 end - else priority = 0; end - else priority = 0; end - if origin.priority ~= priority then - origin.priority = priority; - recalc_resource_map(origin); - end - end - stanza.attr.to = nil; -- reset it - else - log("warn", "presence recieved from client with no roster"); end + stanza.attr.to = nil; -- reset it end function send_presence_of_available_resources(user, host, jid, recipient_session, core_route_stanza) @@ -268,39 +245,6 @@ stanza.attr.from, stanza.attr.to = st_from, st_to; end -local function presence_handler(data) - local origin, stanza = data.origin, data.stanza; - local to = stanza.attr.to; - local node, host = jid_split(to); - local to_bare = jid_bare(to); - local from_bare = jid_bare(stanza.attr.from); - if origin.type == "c2s" then - if to ~= nil and not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence - origin.directed = origin.directed or {}; - origin.directed[to] = true; -- FIXME does it make more sense to add to_bare rather than to? - end - if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then - handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); - elseif not to then - handle_normal_presence(origin, stanza, core_route_stanza); - else - core_route_stanza(origin, stanza); - end - elseif (origin.type == "s2sin" or origin.type == "component") and hosts[host] then - if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then - handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); - else - core_route_stanza(origin, stanza); - end - end - return true; -end - -prosody.events.add_handler(module:get_host().."/presence", presence_handler); -module.unload = function() - prosody.events.remove_handler(module:get_host().."/presence", presence_handler); -end - local outbound_presence_handler = function(data) -- outbound presence recieved local origin, stanza = data.origin, data.stanza; @@ -371,3 +315,23 @@ end -- resource not online, discard return true; end); + +module:hook("resource-unbind", function(event) + local session, err = event.session, event.error; + -- Send unavailable presence + if session.presence then + local pres = st.presence{ type = "unavailable" }; + if not(err) or err == "closed" then err = "connection closed"; end + pres:tag("status"):text("Disconnected: "..err):up(); + session:dispatch_stanza(pres); + elseif session.directed then + local pres = st.presence{ type = "unavailable" }; + if not(err) or err == "closed" then err = "connection closed"; end + pres:tag("status"):text("Disconnected: "..err):up(); + for jid in pairs(session.directed) do + pres.attr.to = jid; + core_route_stanza(session, pres); + end + session.directed = nil; + end +end); diff -r 3e04efa8af7e -r 66f18c18befa prosody --- a/prosody Sun Jul 05 19:05:03 2009 +0200 +++ b/prosody Sun Jul 05 19:05:25 2009 +0200 @@ -17,10 +17,13 @@ -- -- -- -- -- -- -- ---- -- -- -- -- -- -- -- -- if CFG_SOURCEDIR then - package.path = CFG_SOURCEDIR.."/?.lua;"..package.path - package.cpath = CFG_SOURCEDIR.."/?.so;"..package.cpath + package.path = CFG_SOURCEDIR.."/?.lua;"..package.path; + package.cpath = CFG_SOURCEDIR.."/?.so;"..package.cpath; end +package.path = package.path..";"..(CFG_SOURCEDIR or ".").."/fallbacks/?.lua"; +package.cpath = package.cpath..";"..(CFG_SOURCEDIR or ".").."/fallbacks/?.so"; + if CFG_DATADIR then if os.getenv("HOME") then CFG_DATADIR = CFG_DATADIR:gsub("^~", os.getenv("HOME")); diff -r 3e04efa8af7e -r 66f18c18befa prosodyctl --- a/prosodyctl Sun Jul 05 19:05:03 2009 +0200 +++ b/prosodyctl Sun Jul 05 19:05:25 2009 +0200 @@ -95,6 +95,7 @@ ["unable-to-save-data"] = "Unable to store, perhaps you don't have permission?"; ["no-pidfile"] = "There is no pidfile option in the configuration file, see http://prosody.im/doc/prosodyctl#pidfile for help"; ["no-such-method"] = "This module has no commands"; + ["not-running"] = "Prosody is not running"; }, { __index = function (t,k) return "Error: "..(tostring(k):gsub("%-", " "):gsub("^.", string.upper)); end }); hosts = {}; @@ -104,6 +105,7 @@ require "core.modulemanager" require "util.prosodyctl" +require "socket" ----------------------- function show_message(msg, ...) @@ -163,6 +165,8 @@ end return password; end + +local prosodyctl_timeout = (config.get("*", "core", "prosodyctl_timeout") or 5) * 2; ----------------------- local commands = {}; local command = arg[1]; @@ -291,7 +295,24 @@ end local ok, ret = prosodyctl.start(); - if ok then return 0; end + if ok then + local i=1; + while true do + local ok, running = prosodyctl.isrunning(); + if ok and running then + break; + elseif i == 5 then + show_message("Still waiting..."); + elseif i >= prosodyctl_timeout then + show_message("Prosody is still not running. Please give it some time or check your log files for errors."); + return 2; + end + socket.sleep(0.5); + i = i + 1; + end + show_message("Started"); + return 0; + end show_message("Failed to start Prosody"); show_message(error_messages[ret]) @@ -344,7 +365,24 @@ end local ok, ret = prosodyctl.stop(); - if ok then return 0; end + if ok then + local i=1; + while true do + local ok, running = prosodyctl.isrunning(); + if ok and not running then + break; + elseif i == 5 then + show_message("Still waiting..."); + elseif i >= prosodyctl_timeout then + show_message("Prosody is still running. Please give it some time or check your log files for errors."); + return 2; + end + socket.sleep(0.5); + i = i + 1; + end + show_message("Stopped"); + return 0; + end show_message(error_messages[ret]); return 1; diff -r 3e04efa8af7e -r 66f18c18befa util/datamanager.lua --- a/util/datamanager.lua Sun Jul 05 19:05:03 2009 +0200 +++ b/util/datamanager.lua Sun Jul 05 19:05:25 2009 +0200 @@ -62,7 +62,7 @@ local function callback(username, host, datastore, data) for _, f in ipairs(callbacks) do username, host, datastore, data = f(username, host, datastore, data); - if not username then break; end + if username == false then break; end end return username, host, datastore, data; @@ -123,7 +123,7 @@ end username, host, datastore, data = callback(username, host, datastore, data); - if not username then + if username == false then return true; -- Don't save this data at all end @@ -147,7 +147,7 @@ function list_append(username, host, datastore, data) if not data then return; end - if callback and callback(username, host, datastore) then return true; end + if callback(username, host, datastore) == false then return true; end -- save the datastore local f, msg = io_open(getpath(username, host, datastore, "list", true), "a+"); if not f then @@ -165,7 +165,7 @@ if not data then data = {}; end - if callback and callback(username, host, datastore) then return true; end + if callback(username, host, datastore) == false then return true; end -- save the datastore local f, msg = io_open(getpath(username, host, datastore, "list", true), "w+"); if not f then diff -r 3e04efa8af7e -r 66f18c18befa util/hmac.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/hmac.lua Sun Jul 05 19:05:25 2009 +0200 @@ -0,0 +1,70 @@ +local hashes = require "util.hashes" +local xor = require "bit".bxor + +local t_insert, t_concat = table.insert, table.concat; +local s_char = string.char; + +module "hmac" + +local function arraystr(array) + local t = {} + for i = 1,#array do + t_insert(t, s_char(array[i])) + end + + return t_concat(t) +end + +--[[ +key + the key to use in the hash +message + the message to hash +hash + the hash function +blocksize + the blocksize for the hash function in bytes +hex + return raw hash or hexadecimal string +--]] +function hmac(key, message, hash, blocksize, hex) + local opad = {} + local ipad = {} + + for i = 1,blocksize do + opad[i] = 0x5c + ipad[i] = 0x36 + end + + if #key > blocksize then + key = hash(key) + end + + for i = 1,#key do + ipad[i] = xor(ipad[i],key:sub(i,i):byte()) + opad[i] = xor(opad[i],key:sub(i,i):byte()) + end + + opad = arraystr(opad) + ipad = arraystr(ipad) + + if hex then + return hash(opad..hash(ipad..message), true) + else + return hash(opad..hash(ipad..message)) + end +end + +function md5(key, message, hex) + return hmac(key, message, hashes.md5, 64, hex) +end + +function sha1(key, message, hex) + return hmac(key, message, hashes.sha1, 64, hex) +end + +function sha256(key, message, hex) + return hmac(key, message, hashes.sha256, 64, hex) +end + +return _M