Software /
code /
prosody-modules
Changeset
1324:853a382c9bd6
mod_turncredentials: Advertise the XEP-0215 feature (thanks Gryffus)
line wrap: on
line diff
--- a/mod_auth_ccert/mod_auth_ccert.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_auth_ccert/mod_auth_ccert.lua Fri Feb 28 15:36:06 2014 +0100 @@ -60,7 +60,7 @@ function get_sasl_handler(session) return new_sasl(module.host, { external = session.secure and function(authz) - if not session.secure then + if not session.secure or not session.conn:ssl() then -- getpeercertificate() on a TCP connection would be bad, abort! (session.log or log)("error", "How did you manage to select EXTERNAL without TLS?"); return nil, false;
--- a/mod_auth_dovecot/auth_dovecot/sasl_dovecot.lib.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_auth_dovecot/auth_dovecot/sasl_dovecot.lib.lua Fri Feb 28 15:36:06 2014 +0100 @@ -62,8 +62,8 @@ end if not ok then - return false, "error connecting to dovecot "..tostring(socket_type).." socket at '" - ..tostring(socket_path or socket_info).."'. error was '"..tostring(err).."'"; + log("error", "error connecting to dovecot %s socket at '%s'. error was '%s'", socket_type, socket_path or socket_info, err); + return false; end -- Send our handshake @@ -95,6 +95,7 @@ local major_version = parts(); if major_version ~= "1" then + log("error", "dovecot server version is not 1.x. it is %s.x", major_version); conn:close(); return false, "dovecot server version is not 1.x. it is "..tostring(major_version)..".x"; end
--- a/mod_block_strangers/mod_block_strangers.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_block_strangers/mod_block_strangers.lua Fri Feb 28 15:36:06 2014 +0100 @@ -2,6 +2,7 @@ local jid_split = require "util.jid".split; local jid_bare = require "util.jid".bare; local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed; +local error_reply = require "util.stanza".error_reply; function check_subscribed(event) local stanza = event.stanza; @@ -11,7 +12,7 @@ if to_resource and stanza.attr.type == "groupchat" then return nil; -- Pass through end - return true; -- Drop stanza + return error_reply("auth", "forbidden", "Subscription required"); -- Bounce with error end end
--- a/mod_carbons/mod_carbons.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_carbons/mod_carbons.lua Fri Feb 28 15:36:06 2014 +0100 @@ -62,10 +62,11 @@ return -- No use in sending carbons to an offline user end - if stanza:get_child("private", xmlns_carbons) then + local private_tag = stanza:child_with_name("private"); + if private_tag and private.attr.xmlns == xmlns_carbons or private.attr.xmlns == xmlns_carbons_old then if not c2s then stanza:maptags(function(tag) - if not ( tag.attr.xmlns == xmlns_carbons and tag.name == "private" ) then + if tag ~= private_tag then return tag; end end);
--- a/mod_default_bookmarks/mod_default_bookmarks.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_default_bookmarks/mod_default_bookmarks.lua Fri Feb 28 15:36:06 2014 +0100 @@ -13,37 +13,34 @@ local dm_load = require "util.datamanager".load local jid_split = require "util.jid".split -module:hook("iq/self/jabber:iq:private:query", function(event) +local private_bookmarks_ns = "storage:storage:bookmarks"; + +local bookmarks = module:get_option("default_bookmarks"); + +module:hook("iq-get/self/jabber:iq:private:query", function(event) local origin, stanza = event.origin, event.stanza; - local typ = stanza.attr.type; local from = stanza.attr.from; - local query = stanza.tags[1]; - if #query.tags == 1 and typ == "get" then - local tag = query.tags[1]; - local key = tag.name..":"..tag.attr.xmlns; - if key == "storage:storage:bookmarks" then - local data, err = dm_load(origin.username, origin.host, "private"); - if not(data and data[key]) then - local bookmarks = module:get_option("default_bookmarks"); - if bookmarks and #bookmarks > 0 then - local reply = st.reply(stanza):tag("query", {xmlns = "jabber:iq:private"}) - :tag("storage", { xmlns = "storage:bookmarks" }); - local nick = jid_split(from); - for i=1,#bookmarks do - local bookmark = bookmarks[i]; - if type(bookmark) ~= "table" then -- assume it's only a jid - bookmark = { jid = bookmark, name = jid_split(bookmark) }; - end - reply:tag("conference", { - jid = bookmark.jid, - name = bookmark.name, - autojoin = "1", - }):tag("nick"):text(nick):up():up(); - end - origin.send(reply); - return true; - end - end + if not stanza.tags[1]:get_child("storage", "storage:bookmarks") then return end + local data, err = dm_load(origin.username, origin.host, "private"); + if data and data[private_bookmarks_ns] then return end + + local reply = st.reply(stanza):tag("query", {xmlns = "jabber:iq:private"}) + :tag("storage", { xmlns = "storage:bookmarks" }); + + local nick = jid_split(from); + + local bookmark; + for i=1,#bookmarks do + bookmark = bookmarks[i]; + if type(bookmark) ~= "table" then -- assume it's only a jid + bookmark = { jid = bookmark, name = jid_split(bookmark) }; end + reply:tag("conference", { + jid = bookmark.jid, + name = bookmark.name, + autojoin = "1", + }):tag("nick"):text(nick):up():up(); end + origin.send(reply); + return true; end, 1);
--- a/mod_firewall/mod_firewall.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_firewall/mod_firewall.lua Fri Feb 28 15:36:06 2014 +0100 @@ -27,6 +27,10 @@ type = "event"; "route/remote"; priority = 0.1; }; + send_remote = { -- FIXME name + type = "filter"; "s2sout"; + priority = 0.1; + }; }; local function idsafe(name) @@ -372,9 +376,13 @@ module:log("error", "Compilation error for %s: %s", script, err); else local chain_definition = chains[chain]; - if chain_definition and chain_definition.type == "event" then - for _, event_name in ipairs(chain_definition) do - module:hook(event_name, handler, chain_definition.priority); + if chain_definition then + if chain_definition.type == "event" then + for _, event_name in ipairs(chain_definition) do + module:hook(event_name, handler, chain_definition.priority); + end + elseif chain_definition.type == "filter" then + -- TODO end elseif not chain:match("^user/") then module:log("warn", "Unknown chain %q", chain);
--- a/mod_http_altconnect/mod_http_altconnect.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_http_altconnect/mod_http_altconnect.lua Fri Feb 28 15:36:06 2014 +0100 @@ -6,16 +6,20 @@ local json = require"util.json"; local st = require"util.stanza"; local array = require"util.array"; +local it = require"util.iterators"; local host_modules = hosts[module.host].modules; local function get_supported() - local uris = array(); - if host_modules["bosh"] then - uris:push({ rel = "urn:xmpp:alt-connections:xbosh", href = module:http_url("bosh", "/http-bind") }); - end - if host_modules["websocket"] then - uris:push({ rel = "urn:xmpp:alt-connections:websocket", href = module:http_url("websocket", "xmpp-websocket"):gsub("^http", "ws") }); + local uris = array(it.values(module:get_host_items("alt-conn-method"))); + if #uris == 0 then + -- COMPAT for with before item array was added + if host_modules["bosh"] then + uris:push({ rel = "urn:xmpp:alt-connections:xbosh", href = module:http_url("bosh", "/http-bind") }); + end + if host_modules["websocket"] then + uris:push({ rel = "urn:xmpp:alt-connections:websocket", href = module:http_url("websocket", "xmpp-websocket"):gsub("^http", "ws") }); + end end return uris; end
--- a/mod_http_dir_listing/http_dir_listing/resources/style.css Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_http_dir_listing/http_dir_listing/resources/style.css Fri Feb 28 15:36:06 2014 +0100 @@ -5,6 +5,12 @@ a:link:hover,a:visited:hover{color:#3465a4;} .filelist{background-color:white;padding:1em;list-style-position:inside;-moz-column-width:20em;-webkit-column-width:20em;-ms-column-width:20em;column-width:20em;} .file{list-style-image:url(text-x-generic.png);} +.file.image{list-style-image:url(image-x-generic.png);} +.file.video{list-style-image:url(video-x-generic.png);} +.file.audio{list-style-image:url(audio-x-generic.png);} +.file.vcf{list-style-image:url(x-office-address-book.png);} +.file.text.html{list-style-image:url(text-html.png);} +.file.application{list-style-image:url(application-x-executable.png);} .directory{list-style-image:url(folder.png);} .parent{list-style-image:url(user-home.png);} footer{margin-top:1ex;font-size:smaller;color:#babdb6;}
--- a/mod_http_dir_listing/http_dir_listing/resources/template.html Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_http_dir_listing/http_dir_listing/resources/template.html Fri Feb 28 15:36:06 2014 +0100 @@ -6,9 +6,9 @@ </head> <body> <h1>Index of {path}</h1> - - {filelist} - + <article> + {filelist} + </article> <footer>{footer}</footer> </body> </html>
--- a/mod_mam/mod_mam.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_mam/mod_mam.lua Fri Feb 28 15:36:06 2014 +0100 @@ -1,9 +1,9 @@ -- XEP-0313: Message Archive Management for Prosody --- Copyright (C) 2011-2012 Kim Alvefur +-- Copyright (C) 2011-2014 Kim Alvefur -- -- This file is MIT/X11 licensed. -local xmlns_mam = "urn:xmpp:mam:tmp"; +local xmlns_mam = "urn:xmpp:mam:0" or ":1"; local xmlns_delay = "urn:xmpp:delay"; local xmlns_forward = "urn:xmpp:forward:0"; @@ -16,6 +16,7 @@ local jid_bare = require "util.jid".bare; local jid_split = require "util.jid".split; local jid_prep = require "util.jid".prep; +local dataform = require "util.dataforms".new; local host = module.host; local rm_load_roster = require "core.rostermanager".load_roster; @@ -61,18 +62,37 @@ end end); +local query_form = dataform { + { name = "FORM_TYPE"; type = "hidden"; value = "urn:xmpp:mam:0"; }; + { name = "with"; type = "jid-single"; }; + { name = "start"; type = "text-single" }; + { name = "end"; type = "text-single"; }; +}; + +-- Serve form +module:hook("iq-get/self/"..xmlns_mam..":query", function(event) + local origin, stanza = event.origin, event.stanza; + return origin.send(st.reply(stanza):add_child(query_form:form())); +end); + -- Handle archive queries -module:hook("iq-get/self/"..xmlns_mam..":query", function(event) +module:hook("iq-set/self/"..xmlns_mam..":query", function(event) local origin, stanza = event.origin, event.stanza; local query = stanza.tags[1]; local qid = query.attr.queryid; -- Search query parameters - local qwith = query:get_child_text("with"); - local qstart = query:get_child_text("start"); - local qend = query:get_child_text("end"); - module:log("debug", "Archive query, id %s with %s from %s until %s)", - tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); + local qwith, qstart, qend; + local form = query:get_child("x", "jabber:x:data"); + if form then + local err; + form, err = query_form:data(form); + if err then + return origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err)))) + end + qwith, qstart, qend = form["with"], form["start"], form["end"]; + qwith = qwith and jid_bare(qwith); + end if qstart or qend then -- Validate timestamps local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) @@ -83,14 +103,8 @@ qstart, qend = vstart, vend; end - if qwith then -- Validate the 'with' jid - local pwith = qwith and jid_prep(qwith); - if pwith and not qwith then -- it failed prepping - origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID")) - return true - end - qwith = jid_bare(pwith); - end + module:log("debug", "Archive query, id %s with %s from %s until %s)", + tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); -- RSM stuff local qset = rsm.get(query); @@ -116,7 +130,7 @@ local count = err; -- Wrap it in stuff and deliver - local first, last; + local first_id, last_id, first_time, last_time; for id, item, when in data do local fwd_st = st.message{ to = origin.full_jid } :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }) @@ -129,18 +143,27 @@ item.attr.xmlns = "jabber:client"; fwd_st:add_child(item); - if not first then first = id; end - last = id; + if not first_id then + first_id = id; + first_time = when; + end + last_id = id; + last_time = when; origin.send(fwd_st); end -- That's all folks! module:log("debug", "Archive query %s completed", tostring(qid)); - if reverse then first, last = last, first; end + if reverse then + first_id, last_id, first_time, last_time = + last_id, first_id, last_time, first_time; + end return origin.send(st.reply(stanza) - :query(xmlns_mam):add_child(rsm.generate { - first = first, last = last, count = count })); + :query(xmlns_mam) + :add_child(query_form:form({ start = timestamp(first_time), ["end"] = timestamp(last_time), with = qwith })) + :add_child(rsm.generate { + first = first_id, last = last_id, count = count })); end); local function has_in_roster(user, who)
--- a/mod_mam_muc/mod_mam_muc.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_mam_muc/mod_mam_muc.lua Fri Feb 28 15:36:06 2014 +0100 @@ -111,6 +111,36 @@ end); end +module:hook("muc-config-form", function(event) + local room, form = event.room, event.form; + local mam_query = room._data.mam_query or 'anyone'; + table.insert(form, { + name = muc_form_allow_who, + type = 'list-single', + label = 'Who may query the archive?', + value = { + { value = 'moderators', label = 'Moderators Only', default = mam_query == 'moderators' }, + { value = 'members', label = 'Members', default = mam_query == 'members' }, + { value = 'anyone', label = 'Anyone who can join', default = mam_query == 'anyone' }, + } + } + ); +end); + +module:hook("muc-config-submitted", function(event) + local room, fields, changed = event.room, event.fields, event.changed; + local new = fields[muc_form_allow_who]; + if new ~= room._data.mam_query then + room._data.mam_query = new; + if type(changed) == "table" then + changed[muc_form_allow_who] = true; + else + event.changed = true; + end + end +end); + + -- Handle archive queries module:hook("iq-get/bare/"..xmlns_mam..":query", function(event) local origin, stanza = event.origin, event.stanza; @@ -126,8 +156,11 @@ -- Banned or not a member of a members-only room? local from_affiliation = room_obj:get_affiliation(from); + local allowed_to_query = room_obj._data.mam_query or "anyone"; if from_affiliation == "outcast" -- banned - or room_obj:get_members_only() and not from_affiliation then -- members-only, not a member + or room_obj:get_members_only() and not from_affiliation -- members-only, not a member + or allowed_to_query == "moderators" and not (from_affiliation == "owner" or from_affiliation == "admin" ) + or allowed_to_query ~= "anyone" then return origin.send(st.error_reply(stanza, "auth", "forbidden")) end
--- a/mod_manifesto/mod_manifesto.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_manifesto/mod_manifesto.lua Fri Feb 28 15:36:06 2014 +0100 @@ -57,14 +57,18 @@ module:hook("resource-bind", function (event) local session = event.session; + module:log("debug", "mod_%s sees that %s logged in", module.name, session.username); local now = time(); local last_notify = notified[session.username] or 0; if last_notify > ( now - 86400 * 7 ) then + module:log("debug", "Already notified %s", session.username); return end + module:log("debug", "Waiting 15 seconds"); timer.add_task(15, function () + module:log("debug", "15 seconds later... session.type is %q", session.type); if session.type ~= "c2s" then return end -- user quit already local bad_contacts, bad_hosts = {}, {}; for contact_jid, item in pairs(session.roster or {}) do @@ -96,6 +100,7 @@ end end end + module:log("debug", "%s has %d bad contacts", session.username, #bad_contacts); if #bad_contacts > 0 then local vars = { HOST = host; @@ -103,6 +108,7 @@ SERVICES = " "..table.concat(bad_hosts, "\n "); CONTACTVIA = contact_method, CONTACT = contact; }; + module:log("debug", "Sending notification to %s", session.username); session.send(st.message({ type = "headline", from = host }):tag("body"):text(message:gsub("$(%w+)", vars))); notified[session.username] = now; end @@ -159,7 +165,7 @@ config_set(host, "s2s_require_encryption", true); for _, session in pairs(s2s_sessions) do - if not session.secure then + if session.type == "s2sin" or session.type == "s2sout" and not session.secure then (session.close or s2s_destroy_session)(session); end end
--- a/mod_muc_log/mod_muc_log.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_muc_log/mod_muc_log.lua Fri Feb 28 15:36:06 2014 +0100 @@ -96,6 +96,7 @@ end end end + datamanager.getpath(node, host, datastore, nil, true); -- create the datastore dir data_store(node, host, datastore .. "/" .. today, data); end end
--- a/mod_pubsub_feeds/mod_pubsub_feeds.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_pubsub_feeds/mod_pubsub_feeds.lua Fri Feb 28 15:36:06 2014 +0100 @@ -17,8 +17,8 @@ local pubsub = module:depends"pubsub"; -local date, time = os.date, os.time; -local dt_parse, dt_datetime = require "util.datetime".parse, require "util.datetime".datetime; +local date, time = import("os", "date", "time"); +local dt_parse, dt_datetime = import("util.datetime", "parse", "datetime"); local uuid = require "util.uuid".generate; local hmac_sha1 = require "util.hashes".hmac_sha1; local parse_feed = require "feeds".feed_from_string;
--- a/mod_pubsub_hub/mod_pubsub_hub.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_pubsub_hub/mod_pubsub_hub.lua Fri Feb 28 15:36:06 2014 +0100 @@ -2,15 +2,14 @@ -- -- This file is MIT/X11 licensed. -local http = require "net.http"; -local formdecode = http.formdecode; -local formencode = http.formencode; +local http_request, formdecode, formencode = import("net.http", "request", "formdecode", "formencode"); local uuid = require "util.uuid".generate; local hmac_sha1 = require "util.hmac".sha1; local json_encode = require "util.json".encode; local time = os.time; local m_min, m_max = math.min, math.max; local tostring = tostring; + local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; local xmlns_pubsub_event = xmlns_pubsub .. "#event"; local subs_by_topic = module:shared"subscriptions"; @@ -91,7 +90,7 @@ module:log("debug", require"util.serialization".serialize(verify_modes)); if verify_modes["async"] then module:log("debug", "Sending async verification request to %s for %s", tostring(callback_url), tostring(subscription)); - http.request(callback_url, nil, function(body, code) + http_request(callback_url, nil, function(body, code) if body == challenge and code > 199 and code < 300 then if not subscription.want_state then module:log("warn", "Verification of already verified request, probably"); @@ -109,7 +108,7 @@ end) return 202; elseif verify_modes["sync"] then - http.request(callback_url, nil, function(body, code) + http_request(callback_url, nil, function(body, code) if body == challenge and code > 199 and code < 300 then if not subscription.want_state then module:log("warn", "Verification of already verified request, probably"); @@ -161,7 +160,7 @@ ["hub.lease_seconds"] = subscription.lease_seconds, ["hub.verify_token"] = subscription.verify_token, } - http.request(callback_url, nil, function(body, code) + http_request(callback_url, nil, function(body, code) if body == challenge and code > 199 and code < 300 then subscription.expires = now + subscription.lease_seconds; end @@ -201,7 +200,7 @@ if subscription.secret then headers["X-Hub-Signature"] = "sha1="..hmac_sha1(subscription.secret, body, true); end - http.request(subscription.callback, { method = "POST", body = body, headers = headers }, function(body, code) + http_request(subscription.callback, { method = "POST", body = body, headers = headers }, function(body, code) if code >= 200 and code <= 299 then module:log("debug", "Delivered"); else
--- a/mod_s2s_auth_dane/mod_s2s_auth_dane.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_s2s_auth_dane/mod_s2s_auth_dane.lua Fri Feb 28 15:36:06 2014 +0100 @@ -25,6 +25,7 @@ -- TODO Things to test/handle: -- Negative or bogus answers -- No SRV records +-- No encryption offered function s2sout.try_connect(host_session, connect_host, connect_port, err) local srv_hosts = host_session.srv_hosts;
--- a/mod_s2s_auth_fingerprint/mod_s2s_auth_fingerprint.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_s2s_auth_fingerprint/mod_s2s_auth_fingerprint.lua Fri Feb 28 15:36:06 2014 +0100 @@ -5,6 +5,7 @@ local digest_algo = module:get_option_string(module:get_name().."_digest", "sha1"); local must_match = module:get_option_boolean("s2s_pin_fingerprints", false); +local tofu = module:get_option_boolean("s2s_tofu", false); local fingerprints = {}; @@ -38,5 +39,20 @@ session.cert_chain_status = "invalid"; session.cert_identity_status = "invalid"; end + elseif tofu + and ( session.cert_chain_status ~= "valid" + or session.cert_identity_status ~= "valid" ) then + local digest = cert and cert:digest(digest_algo); + fingerprints[host] = { + [digest] = true; + } end end); + +function module.save() + return { fingerprints = fingerprints }; +end + +function module.restore(state) + fingerprints = state.fingerprints; +end
--- a/mod_s2s_blacklist/mod_s2s_blacklist.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_s2s_blacklist/mod_s2s_blacklist.lua Fri Feb 28 15:36:06 2014 +0100 @@ -1,16 +1,16 @@ local st = require "util.stanza"; -local blacklist = module:get_option_inherited_set("s2s_blacklist", {}); +local whitelist = module:get_option_inherited_set("s2s_whitelist", {}); module:hook("route/remote", function (event) - if blacklist:contains(event.to_host) then + if not whitelist:contains(event.to_host) then module:send(st.error_reply(event.stanza, "cancel", "not-allowed", "Communication with this domain is restricted")); return true; end end, 100); module:hook("s2s-stream-features", function (event) - if blacklist:contains(event.origin.from_host) then + if not whitelist:contains(event.origin.from_host) then event.origin:close({ condition = "policy-violation"; text = "Communication with this domain is restricted";
--- a/mod_s2s_keysize_policy/mod_s2s_keysize_policy.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_s2s_keysize_policy/mod_s2s_keysize_policy.lua Fri Feb 28 15:36:06 2014 +0100 @@ -26,9 +26,9 @@ if cert and cert.pubkey then local _, key_type, key_size = cert:pubkey(); if key_size < ( weak_key_size[key_type] or 0 ) then - local issued = parse_x509_datetime(cert:notbefore()); - if issued > weak_key_cutoff then - session.log("error", "%s has a %s-bit %s key issued after 31 December 2013, invalidating trust!", host, key_size, key_type); + local expires = parse_x509_datetime(cert:notafter()); + if expires > weak_key_cutoff then + session.log("error", "%s has a %s-bit %s key valid after 31 December 2013, invalidating trust!", host, key_size, key_type); session.cert_chain_status = "invalid"; session.cert_identity_status = "invalid"; else
--- a/mod_smacks/mod_smacks.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_smacks/mod_smacks.lua Fri Feb 28 15:36:06 2014 +0100 @@ -8,6 +8,7 @@ local add_filter = require "util.filters".add_filter; local timer = require "util.timer"; local datetime = require "util.datetime"; +local tb = require"util.debug".traceback; local xmlns_sm2 = "urn:xmpp:sm:2"; local xmlns_sm3 = "urn:xmpp:sm:3"; @@ -84,6 +85,7 @@ local function new_send(stanza) local attr = stanza.attr; if attr and not attr.xmlns then -- Stanza in default stream namespace + session.log("debug", "Sending stanza %s", stanza:top_tag()); local cached_stanza = st.clone(stanza); if cached_stanza and cached_stanza:get_child("delay", xmlns_delay) == nil then @@ -91,8 +93,10 @@ end queue[#queue+1] = cached_stanza; + session.log("debug", "#queue = %d", #queue); end if session.hibernating then + session.log("debug", "hibernating, stanza queued") -- The session is hibernating, no point in sending the stanza -- over a dead connection. It will be delivered upon resumption. return true; @@ -204,6 +208,7 @@ for i=1,math_min(handled_stanza_count,#queue) do t_remove(origin.outgoing_stanza_queue, 1); end + origin.log("debug", "#queue = %d", #queue); origin.last_acknowledged_stanza = origin.last_acknowledged_stanza + handled_stanza_count; return true; end @@ -333,9 +338,11 @@ -- Ok, we need to re-send any stanzas that the client didn't see -- ...they are what is now left in the outgoing stanza queue local queue = original_session.outgoing_stanza_queue; + session.log("debug", "#queue = %d", #queue); for i=1,#queue do session.send(queue[i]); end + session.log("debug", "#queue = %d -- after send", #queue); else module:log("warn", "Client %s@%s[%s] tried to resume stream for %s@%s[%s]", session.username or "?", session.host or "?", session.type,
--- a/mod_srvinjection/mod_srvinjection.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_srvinjection/mod_srvinjection.lua Fri Feb 28 15:36:06 2014 +0100 @@ -1,3 +1,4 @@ +local s = require"util.serialization".new"oneline".serialize; module:set_global(); @@ -25,8 +26,12 @@ local original_lookup = adns.lookup; function adns.lookup(handler, qname, qtype, qclass) + module:log("debug", "adns.lookup(%s, %s, %s)", s(qname), s(qtype), s(qclass)); if qtype == "SRV" then local host = qname:match("^_xmpp%-server%._tcp%.(.*)%.$"); + module:log("debug", "qname:match(...) → %s", s(host)); + local mapping = map[host] or map["*"]; + module:log("debug", "map[%s] → %s", s(host), s(mapping)); local mapping = map[host] or map["*"]; if mapping then handler(mapping);
--- a/mod_storage_mongodb/mod_storage_mongodb.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_storage_mongodb/mod_storage_mongodb.lua Fri Feb 28 15:36:06 2014 +0100 @@ -1,5 +1,8 @@ local next = next; local setmetatable = setmetatable; +local set = require"util.set"; +local it = require"util.iterators"; +local array = require"util.array"; local params = assert ( module:get_option("mongodb") , "mongodb configuration not found" ); @@ -46,6 +49,75 @@ end; end +local roster_store = {}; +roster_store.__index = roster_store; + +function roster_store:get(username) + local host = module.host or "_global"; + local store = self.store; + + -- The database name can't have a period in it (hence it can't be a host/ip) + local namespace = params.dbname .. "." .. host; + local v = { _id = { store = store ; username = username } }; + + local cursor , err = conn:query ( namespace , v ); + if not cursor then return nil , err end; + + local r , err = cursor:next ( ); + if not r then return nil , err end; + local roster = { + [false] = { + version = r.version; + }; + pending = set.new( r.pending )._items; + }; + local items = r.items; + for i = 1, #items do + local item = items[i]; + roster[item.jid] = { + subscription = item.subscription; + groups = set.new( item.groups )._items; + ask = item.ask; + name = item.name; + } + end + return roster; +end + +function roster_store:set(username, data) + local host = module.host or "_global"; + local store = self.store; + + -- The database name can't have a period in it (hence it can't be a host/ip) + local namespace = params.dbname .. "." .. host; + local v = { _id = { store = store ; username = username } }; + + if data == nil or next(data) == nil then -- delete data + return conn:remove ( namespace , v ); + end + + v.version = data[false].version + if data.pending then + v.pending = array(it.keys(v.pending)) + end + + local items = {} + for jid, item in pairs(data) do + if jid and jid ~= "pending" then + table.insert(items, { + jid = jid; + subscription = item.subscription; + groups = array(it.keys( item.groups )); + name = item.name; + ask = item.ask; + }); + end + end + v.items = items; + + return conn:insert ( namespace , v ); +end + local driver = {}; function driver:open(store, typ) @@ -58,6 +130,9 @@ end if not typ then -- default key-value store + if store == "roster" then + return setmetatable({ store = store }, roster_store); + end return setmetatable({ store = store }, keyval_store); end; return nil, "unsupported-store";
--- a/mod_turncredentials/mod_turncredentials.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_turncredentials/mod_turncredentials.lua Fri Feb 28 15:36:06 2014 +0100 @@ -15,6 +15,8 @@ return; end +module:add_feature("urn:xmpp:extdisco:1"); + module:hook("iq-get/host/urn:xmpp:extdisco:1:services", function(event) local origin, stanza = event.origin, event.stanza; if origin.type ~= "c2s" then
--- a/mod_websocket/mod_websocket.lua Wed Feb 26 13:08:47 2014 -0800 +++ b/mod_websocket/mod_websocket.lua Fri Feb 28 15:36:06 2014 +0100 @@ -242,6 +242,7 @@ c2s_listener.onconnect(conn); local session = sessions[conn]; + session._http_request_headers = request.headers; session.secure = consider_websocket_secure or session.secure; @@ -285,4 +286,11 @@ ["GET /"] = handle_request; }; }); + + module:add_item("alt-conn-method", { + rel = "urn:xmpp:altconnect:websocket"; + href = module:http_url(nil, "xmpp-websocket"):gsub("^http", "ws"); + }); end + +