From 2a701f2d8b5b024bccbe10ebfcb0e4f1f3ffddf2 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 1 Nov 2018 23:58:41 +0100 Subject: mod_pep: Remove incorrect features advertised on the bare host --- plugins/mod_pep.lua | 3 --- 1 file changed, 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 1d8c55bf..cb775fb5 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -250,9 +250,6 @@ end module:hook("iq/bare/"..xmlns_pubsub..":pubsub", handle_pubsub_iq); module:hook("iq/bare/"..xmlns_pubsub_owner..":pubsub", handle_pubsub_iq); -module:add_identity("pubsub", "pep", module:get_option_string("name", "Prosody")); -module:add_feature("http://jabber.org/protocol/pubsub#publish"); - local function get_caps_hash_from_presence(stanza, current) local t = stanza.attr.type; if not t then -- cgit v1.2.3 From eb0947ba4f77172073a21be7c20e17e5f016c203 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 10 Nov 2018 15:50:32 +0100 Subject: MUC: Fix spelling in comments --- plugins/muc/muc.lib.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 4060535a..d9fa37f5 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -39,7 +39,7 @@ function room_mt:__tostring() end function room_mt.save() - -- overriden by mod_muc.lua + -- overridden by mod_muc.lua end function room_mt:get_occupant_jid(real_jid) @@ -279,7 +279,7 @@ function room_mt:publicise_occupant_status(occupant, x, nick, actor, reason) self_p = st.clone(base_presence):add_child(self_x); end - -- General populance + -- General populace for occupant_nick, n_occupant in self:each_occupant() do if occupant_nick ~= occupant.nick then local pr; @@ -609,7 +609,7 @@ function room_mt:handle_normal_presence(origin, stanza) x:tag("status", {code = "303";}):up(); x:tag("status", {code = "110";}):up(); self:route_stanza(generated_unavail:add_child(x)); - dest_nick = nil; -- set dest_nick to nil; so general populance doesn't see it for whole orig_occupant + dest_nick = nil; -- set dest_nick to nil; so general populace doesn't see it for whole orig_occupant end end @@ -966,7 +966,7 @@ function room_mt:handle_admin_query_get_command(origin, stanza) local _aff_rank = valid_affiliations[_aff or "none"]; local _rol = item.attr.role; if _aff and _aff_rank and not _rol then - -- You need to be at least an admin, and be requesting info about your affifiliation or lower + -- You need to be at least an admin, and be requesting info about your affiliation or lower -- e.g. an admin can't ask for a list of owners local affiliation_rank = valid_affiliations[affiliation or "none"]; if (affiliation_rank >= valid_affiliations.admin and affiliation_rank >= _aff_rank) @@ -1291,7 +1291,7 @@ function room_mt:set_affiliation(actor, jid, affiliation, reason, data) -- Outcast can be by host. is_host_only and affiliation == "outcast" and select(2, jid_split(occupant.bare_jid)) == host ) then - -- need to publcize in all cases; as affiliation in has changed. + -- need to publicize in all cases; as affiliation in has changed. occupants_updated[occupant] = occupant.role; if occupant.role ~= role and ( is_downgrade or -- cgit v1.2.3 From cf22878c983c7ebd6cf2a6bef90ed44b7295298d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 27 Nov 2018 17:01:47 +0100 Subject: MUC: Move check for explicit room join earlier in room creation flow --- plugins/muc/mod_muc.lua | 2 +- plugins/muc/muc.lib.lua | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) (limited to 'plugins') diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua index 954bae92..89e67744 100644 --- a/plugins/muc/mod_muc.lua +++ b/plugins/muc/mod_muc.lua @@ -453,7 +453,7 @@ for event_name, method in pairs { if room == nil then -- Watch presence to create rooms - if stanza.attr.type == nil and stanza.name == "presence" then + if stanza.attr.type == nil and stanza.name == "presence" and stanza:get_child("x", "http://jabber.org/protocol/muc") then room = muclib.new_room(room_jid); return room:handle_first_presence(origin, stanza); elseif stanza.attr.type ~= "error" then diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 96f58023..0009e9b2 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -428,13 +428,6 @@ module:hook("muc-occupant-pre-change", function(event) end, 1); function room_mt:handle_first_presence(origin, stanza) - if not stanza:get_child("x", "http://jabber.org/protocol/muc") then - module:log("debug", "Room creation without , possibly desynced"); - - origin.send(st.error_reply(stanza, "cancel", "item-not-found")); - return true; - end - local real_jid = stanza.attr.from; local dest_jid = stanza.attr.to; local bare_jid = jid_bare(real_jid); -- cgit v1.2.3 From 3836d03c37dbd7f3dcd07eb68dab3ca5f0290329 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 1 Dec 2018 22:13:24 +0000 Subject: rostermanager, mod_presence: Store stanza for incoming subscription requests (fixes #689) (thanks Zash, Ge0rG) --- plugins/mod_presence.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 5056a3a3..51254c63 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -80,8 +80,10 @@ function handle_normal_presence(origin, stanza) res.presence.attr.to = nil; end end - for jid in pairs(roster[false].pending) do -- resend incoming subscription requests - origin.send(st.presence({type="subscribe", from=jid})); -- TODO add to attribute? Use original? + for jid, pending_request in pairs(roster[false].pending) do -- resend incoming subscription requests + local subscribe = st.clone(st.deserialize(pending_request)); + subscribe.attr.type, subscribe.attr.from = "subscribe", jid; + origin.send(subscribe); end local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); for jid, item in pairs(roster) do -- resend outgoing subscription requests @@ -225,7 +227,7 @@ function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_b else core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"}), true); -- acknowledging receipt if not rostermanager.is_contact_pending_in(node, host, from_bare) then - if rostermanager.set_contact_pending_in(node, host, from_bare) then + if rostermanager.set_contact_pending_in(node, host, from_bare, stanza) then sessionmanager.send_to_available_resources(node, host, stanza); end -- TODO else return error, unable to save end -- cgit v1.2.3 From c083a55ca54508f51320cc412c544c481ba25fd1 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 2 Dec 2018 17:20:44 +0100 Subject: mod_presence: Remove unnecessary stanza clone call --- plugins/mod_presence.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 51254c63..1ea837e8 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -81,7 +81,7 @@ function handle_normal_presence(origin, stanza) end end for jid, pending_request in pairs(roster[false].pending) do -- resend incoming subscription requests - local subscribe = st.clone(st.deserialize(pending_request)); + local subscribe = st.deserialize(pending_request); subscribe.attr.type, subscribe.attr.from = "subscribe", jid; origin.send(subscribe); end -- cgit v1.2.3 From e3d678dd679de143a9dd46fa77360f4874ecdf60 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 2 Dec 2018 17:22:26 +0100 Subject: mod_presence: Handle older boolean subscription request data (thanks Martin) --- plugins/mod_presence.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 1ea837e8..5aed5854 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -81,9 +81,13 @@ function handle_normal_presence(origin, stanza) end end for jid, pending_request in pairs(roster[false].pending) do -- resend incoming subscription requests - local subscribe = st.deserialize(pending_request); - subscribe.attr.type, subscribe.attr.from = "subscribe", jid; - origin.send(subscribe); + if type(pending_request) == "table" then + local subscribe = st.deserialize(pending_request); + subscribe.attr.type, subscribe.attr.from = "subscribe", jid; + origin.send(subscribe); + else + origin.send(st.presence({type="subscribe", from=jid})); + end end local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); for jid, item in pairs(roster) do -- resend outgoing subscription requests -- cgit v1.2.3 From c250892998c3734ed355b60ff3975279eaef7a9d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 4 Dec 2018 19:49:31 +0100 Subject: MUC/subject: Don't consider messages with or (fixes #667) --- plugins/muc/subject.lib.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'plugins') diff --git a/plugins/muc/subject.lib.lua b/plugins/muc/subject.lib.lua index 938abf61..c8b99cc7 100644 --- a/plugins/muc/subject.lib.lua +++ b/plugins/muc/subject.lib.lua @@ -94,6 +94,12 @@ module:hook("muc-occupant-groupchat", function(event) local stanza = event.stanza; local subject = stanza:get_child("subject"); if subject then + if stanza:get_child("body") or stanza:get_child("thread") then + -- Note: A message with a and a or a and + -- a is a legitimate message, but it SHALL NOT be interpreted + -- as a subject change. + return; + end local room = event.room; local occupant = event.occupant; -- Role check for subject changes -- cgit v1.2.3 From 2b289f34f929a69424a22bb0de3b668a58ba80cd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 8 Dec 2018 17:09:55 +0100 Subject: various: Don't rely on _G.unpack existing --- plugins/mod_admin_telnet.lua | 1 + plugins/mod_pep_simple.lua | 1 + plugins/mod_storage_sql.lua | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 1cbe27a4..8a3508db 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -22,6 +22,7 @@ local prosody = _G.prosody; local console_listener = { default_port = 5582; default_mode = "*a"; interface = "127.0.0.1" }; +local unpack = table.unpack or unpack; -- luacheck: ignore 113 local iterators = require "util.iterators"; local keys, values = iterators.keys, iterators.values; local jid_bare, jid_split, jid_join = import("util.jid", "bare", "prepped_split", "join"); diff --git a/plugins/mod_pep_simple.lua b/plugins/mod_pep_simple.lua index f0b5d7ef..f91e5448 100644 --- a/plugins/mod_pep_simple.lua +++ b/plugins/mod_pep_simple.lua @@ -14,6 +14,7 @@ local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed local pairs = pairs; local next = next; local type = type; +local unpack = table.unpack or unpack; -- luacheck: ignore 113 local calculate_hash = require "util.caps".calculate_hash; local core_post_stanza = prosody.core_post_stanza; local bare_sessions = prosody.bare_sessions; diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 56cef569..5c0c0208 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -11,7 +11,7 @@ local is_stanza = require"util.stanza".is_stanza; local t_concat = table.concat; local noop = function() end -local unpack = table.unpack or unpack; +local unpack = table.unpack or unpack; -- luacheck: ignore 113 local function iterator(result) return function(result_) local row = result_(); -- cgit v1.2.3 From 738a1171dc1415544b2289591578670333250d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Tue, 18 Dec 2018 20:23:33 +0000 Subject: admin_telnet: show when bidi is used on s2s --- plugins/mod_admin_telnet.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 8a3508db..63136d63 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -521,6 +521,9 @@ local function session_flags(session, line) if session.remote then line[#line+1] = "(remote)"; end + if session.is_bidi then + line[#line+1] = "(bidi)"; + end return table.concat(line, " "); end -- cgit v1.2.3 From 5b8df5ea61bf95400c856a65a9e7e24c45bbc17b Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Dec 2018 02:50:22 +0100 Subject: mod_pubsub: Add semicolon (code style) --- plugins/mod_pubsub/mod_pubsub.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_pubsub/mod_pubsub.lua b/plugins/mod_pubsub/mod_pubsub.lua index 40adcafe..1edc721b 100644 --- a/plugins/mod_pubsub/mod_pubsub.lua +++ b/plugins/mod_pubsub/mod_pubsub.lua @@ -73,7 +73,7 @@ function simple_broadcast(kind, node, jids, item, actor, node_obj) local msg_type = node_obj and node_obj.config.message_type or "headline"; local message = st.message({ from = module.host, type = msg_type, id = id }) :tag("event", { xmlns = xmlns_pubsub_event }) - :tag(kind, { node = node }) + :tag(kind, { node = node }); if item then message:add_child(item); -- cgit v1.2.3 From 41426ee8d8bb478eb08840412359e4f1e1464832 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Dec 2018 02:53:12 +0100 Subject: mod_pep: Move broadcaster code around to be more like in mod_pubsub This eases comparing and contrasting these two modules. --- plugins/mod_pep.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index cb775fb5..40385616 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -136,9 +136,6 @@ local function get_broadcaster(username) if kind == "retract" then kind = "items"; -- XEP-0060 signals retraction in an container end - local message = st.message({ from = user_bare, type = "headline" }) - :tag("event", { xmlns = xmlns_pubsub_event }) - :tag(kind, { node = node }); if item then item = st.clone(item); item.attr.xmlns = nil; -- Clear the pubsub namespace @@ -147,6 +144,12 @@ local function get_broadcaster(username) item:maptags(function () return nil; end); end end + end + + local message = st.message({ from = user_bare, type = "headline" }) + :tag("event", { xmlns = xmlns_pubsub_event }) + :tag(kind, { node = node }); + if item then message:add_child(item); end for jid in pairs(jids) do -- cgit v1.2.3 From aef3d7a500f54e8d44303b082ade3f5a14883efd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Dec 2018 02:54:39 +0100 Subject: mod_pep: Add some spacing between blocks in broadcaster to improve readability --- plugins/mod_pep.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 40385616..6275d47c 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -136,6 +136,7 @@ local function get_broadcaster(username) if kind == "retract" then kind = "items"; -- XEP-0060 signals retraction in an container end + if item then item = st.clone(item); item.attr.xmlns = nil; -- Clear the pubsub namespace @@ -149,9 +150,11 @@ local function get_broadcaster(username) local message = st.message({ from = user_bare, type = "headline" }) :tag("event", { xmlns = xmlns_pubsub_event }) :tag(kind, { node = node }); + if item then message:add_child(item); end + for jid in pairs(jids) do module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item)); message.attr.to = jid; -- cgit v1.2.3 From 6eb576e9d9282dc9cb27b0a44472183280abaafd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Dec 2018 02:56:10 +0100 Subject: mod_pep: Set an 'id' on notifications mod_pubsub got this in f2d35eee69c9 --- plugins/mod_pep.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 6275d47c..5e3f43f2 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -8,6 +8,7 @@ local calculate_hash = require "util.caps".calculate_hash; local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed; local cache = require "util.cache"; local set = require "util.set"; +local new_id = require "util.id".medium; local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; local xmlns_pubsub_event = "http://jabber.org/protocol/pubsub#event"; @@ -147,7 +148,8 @@ local function get_broadcaster(username) end end - local message = st.message({ from = user_bare, type = "headline" }) + local id = new_id(); + local message = st.message({ from = user_bare, type = "headline", id = id }) :tag("event", { xmlns = xmlns_pubsub_event }) :tag(kind, { node = node }); -- cgit v1.2.3 From 27112c0d94020fc1e24ed2b8c1673042f7a02798 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Dec 2018 03:05:58 +0100 Subject: mod_pubsub: Change order of luacheck directives to match arguments they apply to --- plugins/mod_pubsub/mod_pubsub.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_pubsub/mod_pubsub.lua b/plugins/mod_pubsub/mod_pubsub.lua index 1edc721b..abc4fee8 100644 --- a/plugins/mod_pubsub/mod_pubsub.lua +++ b/plugins/mod_pubsub/mod_pubsub.lua @@ -99,7 +99,7 @@ function simple_broadcast(kind, node, jids, item, actor, node_obj) end local max_max_items = module:get_option_number("pubsub_max_items", 256); -function check_node_config(node, actor, new_config) -- luacheck: ignore 212/actor 212/node +function check_node_config(node, actor, new_config) -- luacheck: ignore 212/node 212/actor if (new_config["max_items"] or 1) > max_max_items then return false; end -- cgit v1.2.3 From 1900ae8261698d59245f589289b88a384bf743cb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Dec 2018 03:06:35 +0100 Subject: mod_pubsub: Split line in config check to improve readability Also makes it easier to compare with mod_pep --- plugins/mod_pubsub/mod_pubsub.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_pubsub/mod_pubsub.lua b/plugins/mod_pubsub/mod_pubsub.lua index abc4fee8..0036b48f 100644 --- a/plugins/mod_pubsub/mod_pubsub.lua +++ b/plugins/mod_pubsub/mod_pubsub.lua @@ -103,7 +103,8 @@ function check_node_config(node, actor, new_config) -- luacheck: ignore 212/node if (new_config["max_items"] or 1) > max_max_items then return false; end - if new_config["access_model"] ~= "whitelist" and new_config["access_model"] ~= "open" then + if new_config["access_model"] ~= "whitelist" + and new_config["access_model"] ~= "open" then return false; end return true; -- cgit v1.2.3 From 9a412b02e9ab54e2201986bae39e5c7c1d664d3d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 28 Dec 2018 20:56:01 +0100 Subject: mod_admin_telnet: Invert host existence check Simplifies and reduces indentation --- plugins/mod_admin_telnet.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 63136d63..5ba88b84 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1067,13 +1067,12 @@ def_env.xmpp = {}; local st = require "util.stanza"; function def_env.xmpp:ping(localhost, remotehost) - if prosody.hosts[localhost] then - module:send(st.iq{ from=localhost, to=remotehost, type="get", id="ping" } - :tag("ping", {xmlns="urn:xmpp:ping"}), prosody.hosts[localhost]); - return true, "Sent ping"; - else + if not prosody.hosts[localhost] then return nil, "No such host"; end + module:send(st.iq{ from=localhost, to=remotehost, type="get", id="ping" } + :tag("ping", {xmlns="urn:xmpp:ping"}), prosody.hosts[localhost]); + return true, "Sent ping"; end def_env.dns = {}; -- cgit v1.2.3 From 851f33034886b3d25d698497139cb51bf40ed506 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 27 Dec 2018 02:53:34 +0100 Subject: mod_admin_telnet: Enable async processing using util.async --- plugins/mod_admin_telnet.lua | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 5ba88b84..bb97a09b 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -31,6 +31,7 @@ local cert_verify_identity = require "util.x509".verify_identity; local envload = require "util.envload".envload; local envloadfile = require "util.envload".envloadfile; local has_pposix, pposix = pcall(require, "util.pposix"); +local async = require "util.async"; local commands = module:shared("commands") local def_env = module:shared("env"); @@ -48,6 +49,21 @@ end console = {}; +local runner_callbacks = {}; + +function runner_callbacks:ready() + self.data.conn:resume(); +end + +function runner_callbacks:waiting() + self.data.conn:pause(); +end + +function runner_callbacks:error(err) + module:log("error", "Traceback[telnet]: %s", err); +end + + function console:new_session(conn) local w = function(s) conn:write(s:gsub("\n", "\r\n")); end; local session = { conn = conn; @@ -63,6 +79,11 @@ function console:new_session(conn) }; session.env = setmetatable({}, default_env_mt); + session.thread = async.runner(function (line) + console:process_line(session, line); + session.send(string.char(0)); + end, runner_callbacks, session); + -- Load up environment with helper objects for name, t in pairs(def_env) do if type(t) == "table" then @@ -151,8 +172,7 @@ function console_listener.onincoming(conn, data) for line in data:gmatch("[^\n]*[\n\004]") do if session.closed then return end - console:process_line(session, line); - session.send(string.char(0)); + session.thread:run(line); end session.partial_data = data:match("[^\n]+$"); end -- cgit v1.2.3 From f1f0c276bc41aa4290f06a7b308671d88ee54050 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 28 Dec 2018 20:59:10 +0100 Subject: mod_admin_telnet: Make xmpp:ping command wait and report the reply --- plugins/mod_admin_telnet.lua | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index bb97a09b..ee6a4176 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1086,13 +1086,28 @@ end def_env.xmpp = {}; local st = require "util.stanza"; -function def_env.xmpp:ping(localhost, remotehost) +local new_id = require "util.id".medium; +function def_env.xmpp:ping(localhost, remotehost, timeout) if not prosody.hosts[localhost] then return nil, "No such host"; end - module:send(st.iq{ from=localhost, to=remotehost, type="get", id="ping" } - :tag("ping", {xmlns="urn:xmpp:ping"}), prosody.hosts[localhost]); - return true, "Sent ping"; + local iq = st.iq{ from=localhost, to=remotehost, type="get", id=new_id()} + :tag("ping", {xmlns="urn:xmpp:ping"}); + local ret, err; + local wait, done = async.waiter(); + module:context(localhost):send_iq(iq, nil, timeout) + :next(function (ret_) ret = ret_; end, + function (err_) err = err_; end) + :finally(done); + wait(); + if ret then + return true, "pong from " .. ret.stanza.attr.from; + elseif type(err) == "table" and st.is_stanza(err.stanza) then + local t, cond, text = err.stanza:get_error(); + return false, text or cond or t; + else + return false, tostring(err); + end end def_env.dns = {}; -- cgit v1.2.3 From 4fd11623ddc55ce3bbdaf1984834455afef78279 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 24 Nov 2018 02:24:48 +0100 Subject: mod_saslauth: Improve log message when no SASL mechanisms offered (thanks hexa) --- plugins/mod_saslauth.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua index fba84ef8..ba30b9e6 100644 --- a/plugins/mod_saslauth.lua +++ b/plugins/mod_saslauth.lua @@ -275,7 +275,8 @@ module:hook("stream-features", function(event) if mechanisms[1] then features:add_child(mechanisms); elseif not next(sasl_mechanisms) then - log("warn", "No available SASL mechanisms, verify that the configured authentication module is working"); + local authmod = module:get_option_string("authentication", "internal_plain"); + log("error", "No available SASL mechanisms, verify that the configured authentication module '%s' is loaded and configured correctly", authmod); else log("warn", "All available authentication mechanisms are either disabled or not suitable for an insecure connection"); end -- cgit v1.2.3 From b9cac1a3fff4d900c66635d7e5bdcf902f52a34c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 28 Dec 2018 00:13:03 +0100 Subject: mod_c2s: Improve log message in case there are no stream features on offer (thanks hexa) --- plugins/mod_c2s.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua index 8e31a968..36e6a152 100644 --- a/plugins/mod_c2s.lua +++ b/plugins/mod_c2s.lua @@ -106,7 +106,13 @@ function stream_callbacks.streamopened(session, attr) if features.tags[1] or session.full_jid then send(features); else - (session.log or log)("warn", "No stream features to offer"); + if session.secure then + -- Normally STARTTLS would be offered + (session.log or log)("warn", "No stream features to offer on secure session. Check authentication settings."); + else + -- Here SASL should be offered + (session.log or log)("warn", "No stream features to offer on insecure session. Check encryption and security settings."); + end session:close{ condition = "undefined-condition", text = "No stream features to proceed with" }; end end -- cgit v1.2.3 From e6b7c91ebc9484c268fd5f0632abf4eb475ad7d6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 28 Dec 2018 00:04:26 +0100 Subject: mod_tls: Keep TLS context errors and repeat them again for each session --- plugins/mod_tls.lua | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_tls.lua b/plugins/mod_tls.lua index 029ddd1d..4ead60dc 100644 --- a/plugins/mod_tls.lua +++ b/plugins/mod_tls.lua @@ -35,9 +35,10 @@ local host = hosts[module.host]; local ssl_ctx_c2s, ssl_ctx_s2sout, ssl_ctx_s2sin; local ssl_cfg_c2s, ssl_cfg_s2sout, ssl_cfg_s2sin; +local err_c2s, err_s2sin, err_s2sout; function module.load() - local NULL, err = {}; + local NULL = {}; local modhost = module.host; local parent = modhost:match("%.(.*)$"); @@ -52,14 +53,14 @@ function module.load() local parent_s2s = rawgetopt(parent, "s2s_ssl") or NULL; local host_s2s = rawgetopt(modhost, "s2s_ssl") or parent_s2s; - ssl_ctx_c2s, err, ssl_cfg_c2s = create_context(host.host, "server", host_c2s, host_ssl, global_c2s); -- for incoming client connections - if not ssl_ctx_c2s then module:log("error", "Error creating context for c2s: %s", err); end + ssl_ctx_c2s, err_c2s, ssl_cfg_c2s = create_context(host.host, "server", host_c2s, host_ssl, global_c2s); -- for incoming client connections + if not ssl_ctx_c2s then module:log("error", "Error creating context for c2s: %s", err_c2s); end - ssl_ctx_s2sout, err, ssl_cfg_s2sout = create_context(host.host, "client", host_s2s, host_ssl, global_s2s); -- for outgoing server connections - if not ssl_ctx_s2sout then module:log("error", "Error creating contexts for s2sout: %s", err); end + ssl_ctx_s2sout, err_s2sout, ssl_cfg_s2sout = create_context(host.host, "client", host_s2s, host_ssl, global_s2s); -- for outgoing server connections + if not ssl_ctx_s2sout then module:log("error", "Error creating contexts for s2sout: %s", err_s2sout); end - ssl_ctx_s2sin, err, ssl_cfg_s2sin = create_context(host.host, "server", host_s2s, host_ssl, global_s2s); -- for incoming server connections - if not ssl_ctx_s2sin then module:log("error", "Error creating contexts for s2sin: %s", err); end + ssl_ctx_s2sin, err_s2sin, ssl_cfg_s2sin = create_context(host.host, "server", host_s2s, host_ssl, global_s2s); -- for incoming server connections + if not ssl_ctx_s2sin then module:log("error", "Error creating contexts for s2sin: %s", err_s2sin); end end module:hook_global("config-reloaded", module.load); @@ -74,12 +75,21 @@ local function can_do_tls(session) return session.ssl_ctx; end if session.type == "c2s_unauthed" then + if not ssl_ctx_c2s and c2s_require_encryption then + session.log("error", "No TLS context available for c2s. Earlier error was: %s", err_c2s); + end session.ssl_ctx = ssl_ctx_c2s; session.ssl_cfg = ssl_cfg_c2s; elseif session.type == "s2sin_unauthed" and allow_s2s_tls then + if not ssl_ctx_s2sin and s2s_require_encryption then + session.log("error", "No TLS context available for s2sin. Earlier error was: %s", err_s2sin); + end session.ssl_ctx = ssl_ctx_s2sin; session.ssl_cfg = ssl_cfg_s2sin; elseif session.direction == "outgoing" and allow_s2s_tls then + if not ssl_ctx_s2sout and s2s_require_encryption then + session.log("error", "No TLS context available for s2sout. Earlier error was: %s", err_s2sout); + end session.ssl_ctx = ssl_ctx_s2sout; session.ssl_cfg = ssl_cfg_s2sout; else -- cgit v1.2.3 From 5eb327274aa1ab27ec45b49e419943c264bd237d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 29 Dec 2018 03:21:13 +0100 Subject: mod_admin_telnet: Validate hostnames in xmpp:ping command Attempt to ping some invalid hostnames cause weird behavior --- plugins/mod_admin_telnet.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index ee6a4176..f3731c8a 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1088,8 +1088,17 @@ def_env.xmpp = {}; local st = require "util.stanza"; local new_id = require "util.id".medium; function def_env.xmpp:ping(localhost, remotehost, timeout) - if not prosody.hosts[localhost] then - return nil, "No such host"; + localhost = select(2, jid_split(localhost)); + remotehost = select(2, jid_split(remotehost)); + if not localhost then + return nil, "Invalid sender hostname"; + elseif not prosody.hosts[localhost] then + return nil, "No such local host"; + end + if not remotehost then + return nil, "Invalid destination hostname"; + elseif prosody.hosts[remotehost] then + return nil, "Both hosts are local"; end local iq = st.iq{ from=localhost, to=remotehost, type="get", id=new_id()} :tag("ping", {xmlns="urn:xmpp:ping"}); -- cgit v1.2.3 From f102941562aa2228e1949261c91045ecbf71c18d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 30 Dec 2018 16:03:15 +0100 Subject: core.moduleapi: Use util.error for :send_iq errors --- plugins/mod_admin_telnet.lua | 3 --- 1 file changed, 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index f3731c8a..5bb9361e 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1111,9 +1111,6 @@ function def_env.xmpp:ping(localhost, remotehost, timeout) wait(); if ret then return true, "pong from " .. ret.stanza.attr.from; - elseif type(err) == "table" and st.is_stanza(err.stanza) then - local t, cond, text = err.stanza:get_error(); - return false, text or cond or t; else return false, tostring(err); end -- cgit v1.2.3 From c68690726162f0ab0efb62f1cb455001c06b0fa7 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 3 Jan 2019 17:25:43 +0100 Subject: mod_mam: Perform message expiry based on building an index by date For each day, store a set of users that have new messages. To expire messages, we collect the union of sets of users from dates that fall outside the cleanup range. The previous algoritm did not work well with many users, especially with the default settings. --- plugins/mod_mam/mod_mam.lua | 70 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 94bedbb1..18f84752 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -33,7 +33,7 @@ local is_stanza = st.is_stanza; local tostring = tostring; local time_now = os.time; local m_min = math.min; -local timestamp, timestamp_parse = require "util.datetime".datetime, require "util.datetime".parse; +local timestamp, timestamp_parse, datestamp = import( "util.datetime", "datetime", "parse", "date"); local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50); local strip_tags = module:get_option_set("dont_archive_namespaces", { "http://jabber.org/protocol/chatstates" }); @@ -46,13 +46,8 @@ if not archive.find then end local use_total = module:get_option_boolean("mam_include_total", true); -local cleanup; - -local function schedule_cleanup(username) - if cleanup and not cleanup[username] then - table.insert(cleanup, username); - cleanup[username] = true; - end +function schedule_cleanup() + -- replaced by non-noop later if cleanup is enabled end -- Handle prefs. @@ -96,7 +91,6 @@ module:hook("iq-set/self/"..xmlns_mam..":query", function(event) local qid = query.attr.queryid; get_prefs(origin.username, true); - schedule_cleanup(origin.username); -- Search query parameters local qwith, qstart, qend; @@ -212,6 +206,7 @@ end local function shall_store(user, who) -- TODO Cache this? if not um.user_exists(user, host) then + module:log("debug", "%s@%s does not exist", user, host) return false; end local prefs = get_prefs(user); @@ -329,6 +324,9 @@ module:hook("pre-message/full", strip_stanza_id_after_other_events, -1); local cleanup_after = module:get_option_string("archive_expires_after", "1w"); local cleanup_interval = module:get_option_number("archive_cleanup_interval", 4 * 60 * 60); if cleanup_after ~= "never" then + local cleanup_storage = module:open_store("archive_cleanup"); + local cleanup_map = module:open_store("archive_cleanup", "map"); + local day = 86400; local multipliers = { d = day, w = day * 7, m = 31 * day, y = 365.2425 * day }; local n, m = cleanup_after:lower():match("(%d+)%s*([dwmy]?)"); @@ -346,33 +344,43 @@ if cleanup_after ~= "never" then return false; end - -- Set of known users to do message expiry for - -- Populated either below or when new messages are added - cleanup = {}; + -- For each day, store a set of users that have new messages. To expire + -- messages, we collect the union of sets of users from dates that fall + -- outside the cleanup range. - -- Iterating over users is not supported by all authentication modules - -- Catch and ignore error if not supported - pcall(function () - -- If this works, then we schedule cleanup for all known users on startup - for user in um.users(module.host) do - schedule_cleanup(user); - end - end); + function schedule_cleanup(username, date) + cleanup_map:set(date or datestamp(), username, true); + end - -- At odd intervals, delete old messages for one user - module:add_timer(math.random(10, 60), function() - local user = table.remove(cleanup, 1); - if user then - module:log("debug", "Removing old messages for user %q", user); + cleanup_runner = require "util.async".runner(function () + local users = {}; + local cut_off = datestamp(os.time() - cleanup_after); + for date in cleanup_storage:users() do + if date < cut_off then + module:log("debug", "Messages from %q should be expired", date); + local messages_this_day = cleanup_storage:get(date); + if messages_this_day then + for user in pairs(messages_this_day) do + users[user] = true; + end + cleanup_storage:set(date, nil); + end + end + end + local sum, num_users = 0, 0; + for user in pairs(users) do local ok, err = archive:delete(user, { ["end"] = os.time() - cleanup_after; }) - if not ok then - module:log("warn", "Could not expire archives for user %s: %s", user, err); - elseif type(ok) == "number" then - module:log("debug", "Removed %d messages", ok); + if ok then + num_users = num_users + 1; + sum = sum + tonumber(ok) or 0; end - cleanup[user] = nil; end - return math.random(cleanup_interval, cleanup_interval * 2); + module:log("info", "Deleted expired %d messages for %d users", sum, num_users); + end); + + cleanup_task = module:add_timer(1, function () + cleanup_runner:run(true); + return cleanup_interval; end); else module:log("debug", "Archive expiry disabled"); -- cgit v1.2.3 From 3738686f06f0156da85df269050f3f754c7603cd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 4 Jan 2019 10:14:55 +0100 Subject: mod_mam: Fix word order in log message --- plugins/mod_mam/mod_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 18f84752..35a4b9a0 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -375,7 +375,7 @@ if cleanup_after ~= "never" then sum = sum + tonumber(ok) or 0; end end - module:log("info", "Deleted expired %d messages for %d users", sum, num_users); + module:log("info", "Deleted %d expired messages for %d users", sum, num_users); end); cleanup_task = module:add_timer(1, function () -- cgit v1.2.3 From 11b2a79872902ae26905c006a2171aaecbcb4300 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 4 Jan 2019 13:38:30 +0100 Subject: mod_admin_telnet: Remove the long gone 'section' argument in the undocumented config:get command --- plugins/mod_admin_telnet.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 5bb9361e..4c049b95 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -495,9 +495,9 @@ function def_env.config:load(filename, format) return true, "Config loaded"; end -function def_env.config:get(host, section, key) +function def_env.config:get(host, key) local config_get = require "core.configmanager".get - return true, tostring(config_get(host, section, key)); + return true, tostring(config_get(host, key)); end function def_env.config:reload() -- cgit v1.2.3 From 5fb717bbcec4af6aee2bc709f97fbea7b88f3fe6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 4 Jan 2019 13:39:13 +0100 Subject: mod_admin_telnet: config:get: Assume the global section if only one argument is given --- plugins/mod_admin_telnet.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 4c049b95..c6b67b95 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -496,6 +496,9 @@ function def_env.config:load(filename, format) end function def_env.config:get(host, key) + if key == nil then + host, key = "*", host; + end local config_get = require "core.configmanager".get return true, tostring(config_get(host, key)); end -- cgit v1.2.3 From d020a0b57782846653d6145d388143df5b616c64 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 4 Jan 2019 13:41:39 +0100 Subject: mod_admin_telnet: Serialize config values (table: 0x123abc isn't useful) --- plugins/mod_admin_telnet.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index c6b67b95..cd9f8078 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -32,6 +32,7 @@ local envload = require "util.envload".envload; local envloadfile = require "util.envload".envloadfile; local has_pposix, pposix = pcall(require, "util.pposix"); local async = require "util.async"; +local serialize = require "util.serialization".new({ fatal = false, unquoted = true}); local commands = module:shared("commands") local def_env = module:shared("env"); @@ -500,7 +501,7 @@ function def_env.config:get(host, key) host, key = "*", host; end local config_get = require "core.configmanager".get - return true, tostring(config_get(host, key)); + return true, serialize(config_get(host, key)); end function def_env.config:reload() -- cgit v1.2.3 From 51c4d0a0e4d0b1d83bdcfc779bcc9e83be4f3d08 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 4 Jan 2019 15:13:52 +0100 Subject: mod_admin_telnet: Sort stats by name --- plugins/mod_admin_telnet.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index cd9f8078..5ce504f8 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1543,7 +1543,7 @@ function def_env.stats:show(filter) local stats, changed, extra = require "core.statsmanager".get_stats(); local available, displayed = 0, 0; local displayed_stats = new_stats_context(self); - for name, value in pairs(stats) do + for name, value in iterators.sorted_pairs(stats) do available = available + 1; if not filter or name:match(filter) then displayed = displayed + 1; -- cgit v1.2.3 From 2ac699495592895c1cde86cb0ba2dc25c254a4eb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Jan 2019 09:34:59 +0100 Subject: mod_mam: Measure how long it takes to run the message expiry job job --- plugins/mod_mam/mod_mam.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 35a4b9a0..5ba04d68 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -351,8 +351,10 @@ if cleanup_after ~= "never" then function schedule_cleanup(username, date) cleanup_map:set(date or datestamp(), username, true); end + local cleanup_time = module:measure("cleanup", "times"); cleanup_runner = require "util.async".runner(function () + local cleanup_done = cleanup_time(); local users = {}; local cut_off = datestamp(os.time() - cleanup_after); for date in cleanup_storage:users() do @@ -376,6 +378,7 @@ if cleanup_after ~= "never" then end end module:log("info", "Deleted %d expired messages for %d users", sum, num_users); + cleanup_done(); end); cleanup_task = module:add_timer(1, function () -- cgit v1.2.3 From bdfc36fc8caa83c2919c0df1f46b91232af09096 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Jan 2019 09:44:55 +0100 Subject: mod_mam: Handle expiry of messages that expire in the middle of the cut-off day --- plugins/mod_mam/mod_mam.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 5ba04d68..d2ca709b 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -358,14 +358,18 @@ if cleanup_after ~= "never" then local users = {}; local cut_off = datestamp(os.time() - cleanup_after); for date in cleanup_storage:users() do - if date < cut_off then + if date <= cut_off then module:log("debug", "Messages from %q should be expired", date); local messages_this_day = cleanup_storage:get(date); if messages_this_day then for user in pairs(messages_this_day) do users[user] = true; end - cleanup_storage:set(date, nil); + if date < cut_off then + -- Messages from the same day as the cut-off might not have expired yet, + -- but all earlier will have, so clear storage for those days. + cleanup_storage:set(date, nil); + end end end end -- cgit v1.2.3 From c3c38cd2b33d37dfe980c4e21c9b369c138f20c5 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Jan 2019 10:42:45 +0100 Subject: mod_http_errors: Normalize CSS --- plugins/mod_http_errors.lua | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_http_errors.lua b/plugins/mod_http_errors.lua index 13473219..2bb13298 100644 --- a/plugins/mod_http_errors.lua +++ b/plugins/mod_http_errors.lua @@ -26,21 +26,24 @@ local html = [[ {title} -- cgit v1.2.3 From 90f8c75467e26c7a9dc74a55c615304ee4a3569e Mon Sep 17 00:00:00 2001 From: Jonas Wielicki Date: Sun, 6 Jan 2019 11:28:54 +0100 Subject: MUC: add ID to message if no ID is present --- plugins/muc/muc.lib.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index bb79cda6..a34e912b 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -23,6 +23,7 @@ local resourceprep = require "util.encodings".stringprep.resourceprep; local st = require "util.stanza"; local base64 = require "util.encodings".base64; local md5 = require "util.hashes".md5; +local id = require "util.id"; local log = module._log; @@ -1037,6 +1038,9 @@ end function room_mt:handle_groupchat_to_room(origin, stanza) local from = stanza.attr.from; local occupant = self:get_occupant_by_real_jid(from); + if not stanza.attr.id then + stanza.attr.id = id.medium() + end if module:fire_event("muc-occupant-groupchat", { room = self; origin = origin; stanza = stanza; from = from; occupant = occupant; }) then return true; end -- cgit v1.2.3 From f0550233fa24e17773e0c7cc21885cd195ad8c1f Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Jan 2019 12:20:57 +0100 Subject: MUC: Rename import to avoid name clash [luacheck] --- plugins/muc/muc.lib.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index a34e912b..7259dde2 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -23,7 +23,7 @@ local resourceprep = require "util.encodings".stringprep.resourceprep; local st = require "util.stanza"; local base64 = require "util.encodings".base64; local md5 = require "util.hashes".md5; -local id = require "util.id"; +local new_id = require "util.id".medium; local log = module._log; @@ -1039,7 +1039,7 @@ function room_mt:handle_groupchat_to_room(origin, stanza) local from = stanza.attr.from; local occupant = self:get_occupant_by_real_jid(from); if not stanza.attr.id then - stanza.attr.id = id.medium() + stanza.attr.id = new_id() end if module:fire_event("muc-occupant-groupchat", { room = self; origin = origin; stanza = stanza; from = from; occupant = occupant; -- cgit v1.2.3 From 4b6a1153f46fbb1c14ca7a67cc82701572227811 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 14 Jan 2019 00:17:02 +0100 Subject: mod_storage_memory: Implement :user iteration API --- plugins/mod_storage_memory.lua | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index ed04a5fb..3a9de1cc 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -22,6 +22,10 @@ local function _purge_store(self, username) return true; end +local function _users(self) + return next, self.store, nil; +end + local keyval_store = {}; keyval_store.__index = keyval_store; @@ -39,9 +43,13 @@ end keyval_store.purge = _purge_store; +keyval_store.users = _users; + local archive_store = {}; archive_store.__index = archive_store; +archive_store.users = _users; + function archive_store:append(username, key, value, when, with) if is_stanza(value) then value = st.preserialize(value); -- cgit v1.2.3 From cf984835d120a714e2ed4337f8522e935cf85498 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 15 Jan 2019 20:08:30 +0100 Subject: mod_c2s, mod_s2s, mod_component: Log invalid XML escaped (fixes #734) See 6ed0d6224d64 --- plugins/mod_c2s.lua | 2 +- plugins/mod_component.lua | 2 +- plugins/mod_s2s/mod_s2s.lua | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua index 36e6a152..8d7b92fe 100644 --- a/plugins/mod_c2s.lua +++ b/plugins/mod_c2s.lua @@ -290,7 +290,7 @@ function listener.onconnect(conn) if data then local ok, err = stream:feed(data); if not ok then - log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_")); + log("debug", "Received invalid XML (%s) %d bytes: %q", tostring(err), #data, data:sub(1, 300)); session:close("not-well-formed"); end end diff --git a/plugins/mod_component.lua b/plugins/mod_component.lua index b41204a2..b8c87dee 100644 --- a/plugins/mod_component.lua +++ b/plugins/mod_component.lua @@ -310,7 +310,7 @@ function listener.onconnect(conn) function session.data(_, data) local ok, err = stream:feed(data); if ok then return; end - module:log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_")); + log("debug", "Received invalid XML (%s) %d bytes: %q", tostring(err), #data, data:sub(1, 300)); session:close("not-well-formed"); end diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index aae37b7f..79308847 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -595,8 +595,7 @@ local function initialize_session(session) if data then local ok, err = stream:feed(data); if ok then return; end - log("warn", "Received invalid XML: %s", data); - log("warn", "Problem was: %s", err); + log("debug", "Received invalid XML (%s) %d bytes: %q", tostring(err), #data, data:sub(1, 300)); session:close("not-well-formed"); end end -- cgit v1.2.3 From b2c3b2f740d777f1e04df40494f2be0637f946a6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 16 Jan 2019 14:20:16 +0100 Subject: mod_admin_telnet: sttas:show: Use format option that allows float numbers string.format("%d", 0.5) causes an error on Lua 5.3 --- plugins/mod_admin_telnet.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 5ce504f8..7fae8983 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1255,7 +1255,7 @@ local function format_stat(type, value, ref_value) --do return tostring(value) end if type == "duration" then if ref_value < 0.001 then - return ("%d µs"):format(value*1000000); + return ("%g µs"):format(value*1000000); elseif ref_value < 0.9 then return ("%0.2f ms"):format(value*1000); end -- cgit v1.2.3 From 87639540e4ea43c57eb3d31b78e0b5acaf68f97a Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 4 Oct 2018 12:22:12 +0200 Subject: mod_http: Solve CORS problems once and for all This blindly allows any cross-site requests. Future work should add an API to allow each HTTP app some influence over this for each HTTP path --- plugins/mod_http.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index a1d409bd..07d1094b 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -22,6 +22,11 @@ server.set_default_host(module:get_option_string("http_default_host")); server.set_option("body_size_limit", module:get_option_number("http_max_content_size")); server.set_option("buffer_size_limit", module:get_option_number("http_max_buffer_size")); +-- CORS settigs +local opt_methods = module:get_option_set("access_control_allow_methods", { "GET", "POST", "PUT", "OPTIONS" }); +local opt_headers = module:get_option_set("access_control_allow_headers", { "Content-Type" }); +local opt_max_age = module:get_option_number("access_control_max_age", 2 * 60 * 60); + local function get_http_event(host, app_path, key) local method, path = key:match("^(%S+)%s+(.+)$"); if not method then -- No path specified, default to "" (base path) @@ -83,6 +88,13 @@ function moduleapi.http_url(module, app_name, default_path) return "http://disabled.invalid/"; end +local function apply_cors_headers(response, methods, headers, max_age, origin) + response.headers.access_control_allow_methods = tostring(methods); + response.headers.access_control_allow_headers = tostring(headers); + response.headers.access_control_max_age = tostring(max_age) + response.headers.access_control_allow_origin = origin or "*"; +end + function module.add_host(module) local host = module.host; if host ~= "*" then @@ -101,6 +113,12 @@ function module.add_host(module) end apps[app_name] = apps[app_name] or {}; local app_handlers = apps[app_name]; + + local function cors_handler(event_data) + local request, response = event_data.request, event_data.response; + apply_cors_headers(response, opt_methods, opt_headers, opt_max_age, request.headers.origin); + end + for key, handler in pairs(event.item.route or {}) do local event_name = get_http_event(host, app_path, key); if event_name then @@ -121,6 +139,7 @@ function module.add_host(module) if not app_handlers[event_name] then app_handlers[event_name] = handler; module:hook_object_event(server, event_name, handler); + module:hook_object_event(server, event_name, cors_handler, 1); else module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name); end -- cgit v1.2.3 From 467260e6f51942bc4a113bc0ca23808002289147 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 4 Oct 2018 12:23:06 +0200 Subject: mod_bosh: Drop CORS code in favor of than in mod_http This deprecates the cross_domain_bosh setting. As a compat measure, if it is set, mod_http_crossdomain is loaded. --- plugins/mod_bosh.lua | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua index d4701148..82615161 100644 --- a/plugins/mod_bosh.lua +++ b/plugins/mod_bosh.lua @@ -44,10 +44,12 @@ local bosh_max_polling = module:get_option_number("bosh_max_polling", 5); local bosh_max_wait = module:get_option_number("bosh_max_wait", 120); local consider_bosh_secure = module:get_option_boolean("consider_bosh_secure"); -local cross_domain = module:get_option("cross_domain_bosh", false); +local cross_domain = module:get_option("cross_domain_bosh"); -if cross_domain == true then cross_domain = "*"; end -if type(cross_domain) == "table" then cross_domain = table.concat(cross_domain, ", "); end +if cross_domain ~= nil then + module:log("info", "The 'cross_domain_bosh' option has been deprecated"); + module:depends("http_crossdomain"); +end local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; @@ -91,22 +93,6 @@ function check_inactive(now, session, context, reason) -- luacheck: ignore 212/n end end -local function set_cross_domain_headers(response) - local headers = response.headers; - headers.access_control_allow_methods = "GET, POST, OPTIONS"; - headers.access_control_allow_headers = "Content-Type"; - headers.access_control_max_age = "7200"; - headers.access_control_allow_origin = cross_domain; - return response; -end - -function handle_OPTIONS(event) - if cross_domain and event.request.headers.origin then - set_cross_domain_headers(event.response); - end - return ""; -end - function handle_POST(event) log("debug", "Handling new request %s: %s\n----------", tostring(event.request), tostring(event.request.body)); @@ -121,10 +107,6 @@ function handle_POST(event) local headers = response.headers; headers.content_type = "text/xml; charset=utf-8"; - if cross_domain and request.headers.origin then - set_cross_domain_headers(response); - end - -- stream:feed() calls the stream_callbacks, so all stanzas in -- the body are processed in this next line before it returns. -- In particular, the streamopened() stream callback is where @@ -511,8 +493,6 @@ module:provides("http", { route = { ["GET"] = GET_response; ["GET /"] = GET_response; - ["OPTIONS"] = handle_OPTIONS; - ["OPTIONS /"] = handle_OPTIONS; ["POST"] = handle_POST; ["POST /"] = handle_POST; }; -- cgit v1.2.3 From 7fefafa8f6cc312b41f69d8149d5a926657bc9fb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 4 Oct 2018 12:24:08 +0200 Subject: mod_websocket: Drop CORS code in favor of that in mod_http Like for mod_bosh, deprecates consider_websocket_secure and depend on mod_http_crossdomain if it is set. --- plugins/mod_websocket.lua | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index a668b4fa..da0ce8a6 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -29,18 +29,11 @@ local t_concat = table.concat; local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure"); -local cross_domain = module:get_option_set("cross_domain_websocket", {}); -if cross_domain:contains("*") or cross_domain:contains(true) then - cross_domain = true; +local cross_domain = module:get_option("cross_domain_websocket"); +if cross_domain ~= nil then + module:log("info", "The 'cross_domain_websocket' option has been deprecated"); + module:depends("http_crossdomain"); end - -local function check_origin(origin) - if cross_domain == true then - return true; - end - return cross_domain:contains(origin); -end - local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing"; local xmlns_streams = "http://etherx.jabber.org/streams"; local xmlns_client = "jabber:client"; @@ -158,11 +151,6 @@ function handle_request(event) return 501; end - if not check_origin(request.headers.origin or "") then - module:log("debug", "Origin %s is not allowed by 'cross_domain_websocket'", request.headers.origin or "(missing header)"); - return 403; - end - local function websocket_close(code, message) conn:write(build_close(code, message)); conn:close(); @@ -329,22 +317,4 @@ module:provides("http", { function module.add_host(module) module:hook("c2s-read-timeout", keepalive, -0.9); - - if cross_domain ~= true then - local url = require "socket.url"; - local ws_url = module:http_url("websocket", "xmpp-websocket"); - local url_components = url.parse(ws_url); - -- The 'Origin' consists of the base URL without path - url_components.path = nil; - local this_origin = url.build(url_components); - local local_cross_domain = module:get_option_set("cross_domain_websocket", { this_origin }); - -- Don't add / remove something added by another host - -- This might be weird with random load order - local_cross_domain:exclude(cross_domain); - cross_domain:include(local_cross_domain); - module:log("debug", "cross_domain = %s", tostring(cross_domain)); - function module.unload() - cross_domain:exclude(local_cross_domain); - end - end end -- cgit v1.2.3 From 19d344e092421bd84cd52de74bcd6b7b1e9a0a13 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 18 Jan 2019 02:03:40 +0100 Subject: mod_http: Set up to handle OPTIONS Lower priority to allow http modules to handle it themselves, should they wish to --- plugins/mod_http.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 07d1094b..01f20f76 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -119,9 +119,15 @@ function module.add_host(module) apply_cors_headers(response, opt_methods, opt_headers, opt_max_age, request.headers.origin); end + local function options_handler(event_data) + cors_handler(event_data); + return ""; + end + for key, handler in pairs(event.item.route or {}) do local event_name = get_http_event(host, app_path, key); if event_name then + local options_event_name = event_name:gsub("^%S+", "OPTIONS"); if type(handler) ~= "function" then local data = handler; handler = function () return data; end @@ -140,6 +146,7 @@ function module.add_host(module) app_handlers[event_name] = handler; module:hook_object_event(server, event_name, handler); module:hook_object_event(server, event_name, cors_handler, 1); + module:hook_object_event(server, options_event_name, options_handler, -1); else module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name); end -- cgit v1.2.3 From 3434e4560f79c834411e0c1d117a96e8b94ff4db Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 17 Jan 2019 20:42:38 +0100 Subject: mod_http: Determine CORS methods to whitelist from actual methods used --- plugins/mod_http.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 01f20f76..829c2d02 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -14,6 +14,7 @@ local moduleapi = require "core.moduleapi"; local url_parse = require "socket.url".parse; local url_build = require "socket.url".build; local normalize_path = require "util.http".normalize_path; +local set = require "util.set"; local server = require "net.http.server"; @@ -23,7 +24,7 @@ server.set_option("body_size_limit", module:get_option_number("http_max_content_ server.set_option("buffer_size_limit", module:get_option_number("http_max_buffer_size")); -- CORS settigs -local opt_methods = module:get_option_set("access_control_allow_methods", { "GET", "POST", "PUT", "OPTIONS" }); +local opt_methods = module:get_option_set("access_control_allow_methods", { "GET", "OPTIONS" }); local opt_headers = module:get_option_set("access_control_allow_headers", { "Content-Type" }); local opt_max_age = module:get_option_number("access_control_max_age", 2 * 60 * 60); @@ -114,9 +115,11 @@ function module.add_host(module) apps[app_name] = apps[app_name] or {}; local app_handlers = apps[app_name]; + local app_methods = opt_methods; + local function cors_handler(event_data) local request, response = event_data.request, event_data.response; - apply_cors_headers(response, opt_methods, opt_headers, opt_max_age, request.headers.origin); + apply_cors_headers(response, app_methods, opt_headers, opt_max_age, request.headers.origin); end local function options_handler(event_data) @@ -127,6 +130,10 @@ function module.add_host(module) for key, handler in pairs(event.item.route or {}) do local event_name = get_http_event(host, app_path, key); if event_name then + local method = event_name:match("^%S+"); + if not app_methods:contains(method) then + app_methods = app_methods + set.new{ method }; + end local options_event_name = event_name:gsub("^%S+", "OPTIONS"); if type(handler) ~= "function" then local data = handler; -- cgit v1.2.3 From 2612e75c8a206c174071c66a6fe938b07349e55a Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 19 Jan 2019 20:03:04 +0100 Subject: mod_bosh, mod_websocket: Remove accidentally included dependency on non-existant module --- plugins/mod_bosh.lua | 1 - plugins/mod_websocket.lua | 1 - 2 files changed, 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua index 82615161..082ed961 100644 --- a/plugins/mod_bosh.lua +++ b/plugins/mod_bosh.lua @@ -48,7 +48,6 @@ local cross_domain = module:get_option("cross_domain_bosh"); if cross_domain ~= nil then module:log("info", "The 'cross_domain_bosh' option has been deprecated"); - module:depends("http_crossdomain"); end local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index da0ce8a6..008f6823 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -32,7 +32,6 @@ local consider_websocket_secure = module:get_option_boolean("consider_websocket_ local cross_domain = module:get_option("cross_domain_websocket"); if cross_domain ~= nil then module:log("info", "The 'cross_domain_websocket' option has been deprecated"); - module:depends("http_crossdomain"); end local xmlns_framing = "urn:ietf:params:xml:ns:xmpp-framing"; local xmlns_streams = "http://etherx.jabber.org/streams"; -- cgit v1.2.3 From de09c462e53b412b30463d55400328b4316a4c45 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 20 Jan 2019 20:24:17 +0100 Subject: mod_mam: Fix operator precedence (thanks mimi89999) --- plugins/mod_mam/mod_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index d2ca709b..67bf177e 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -378,7 +378,7 @@ if cleanup_after ~= "never" then local ok, err = archive:delete(user, { ["end"] = os.time() - cleanup_after; }) if ok then num_users = num_users + 1; - sum = sum + tonumber(ok) or 0; + sum = sum + (tonumber(ok) or 0); end end module:log("info", "Deleted %d expired messages for %d users", sum, num_users); -- cgit v1.2.3 From 10e58af1abd74cd1bb668fc75b506b57fd77d86f Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Feb 2019 16:18:30 +0100 Subject: MUC: Factor out role change permission check into its own method I would like to invert this logic so that it checks if the role change is allowed instead of checking if it is not allowed as it does now, in order to make it easier to understand. --- plugins/muc/muc.lib.lua | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 9b168e93..2b6a7d76 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -1368,6 +1368,30 @@ function room_mt:get_role(nick) return occupant and occupant.role or nil; end +function room_mt:may_set_role(actor, occupant, role) + -- Can't do anything to other owners or admins + local occupant_affiliation = self:get_affiliation(occupant.bare_jid); + if occupant_affiliation == "owner" or occupant_affiliation == "admin" then + return nil, "cancel", "not-allowed"; + end + + -- If you are trying to give or take moderator role you need to be an owner or admin + if occupant.role == "moderator" or role == "moderator" then + local actor_affiliation = self:get_affiliation(actor); + if actor_affiliation ~= "owner" and actor_affiliation ~= "admin" then + return nil, "cancel", "not-allowed"; + end + end + + -- Need to be in the room and a moderator + local actor_occupant = self:get_occupant_by_real_jid(actor); + if not actor_occupant or actor_occupant.role ~= "moderator" then + return nil, "cancel", "not-allowed"; + end + + return true; +end + function room_mt:set_role(actor, occupant_jid, role, reason) if not actor then return nil, "modify", "not-acceptable"; end @@ -1382,24 +1406,9 @@ function room_mt:set_role(actor, occupant_jid, role, reason) if actor == true then actor = nil -- So we can pass it safely to 'publicise_occupant_status' below else - -- Can't do anything to other owners or admins - local occupant_affiliation = self:get_affiliation(occupant.bare_jid); - if occupant_affiliation == "owner" or occupant_affiliation == "admin" then - return nil, "cancel", "not-allowed"; - end - - -- If you are trying to give or take moderator role you need to be an owner or admin - if occupant.role == "moderator" or role == "moderator" then - local actor_affiliation = self:get_affiliation(actor); - if actor_affiliation ~= "owner" and actor_affiliation ~= "admin" then - return nil, "cancel", "not-allowed"; - end - end - - -- Need to be in the room and a moderator - local actor_occupant = self:get_occupant_by_real_jid(actor); - if not actor_occupant or actor_occupant.role ~= "moderator" then - return nil, "cancel", "not-allowed"; + local allowed, err, condition = self:may_set_role(actor, occupant, role) + if not allowed then + return allowed, err, condition; end end -- cgit v1.2.3 From 8518868d4192e48f1f7529970dca3bae4364f43b Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Feb 2019 16:30:11 +0100 Subject: MUC: Fire an event to allow affecting decision of whether to allow a role change --- plugins/muc/muc.lib.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 2b6a7d76..a8d3d790 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -1369,6 +1369,18 @@ function room_mt:get_role(nick) end function room_mt:may_set_role(actor, occupant, role) + local event = { + room = self, + actor = actor, + occupant = occupant, + role = role, + }; + + module:fire_event("muc-pre-set-role", event); + if event.allowed ~= nil then + return event.allowed, event.error, event.condition; + end + -- Can't do anything to other owners or admins local occupant_affiliation = self:get_affiliation(occupant.bare_jid); if occupant_affiliation == "owner" or occupant_affiliation == "admin" then -- cgit v1.2.3 From 9c9d32e7e69af9aa59c1937b91bc41525d584144 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 4 Mar 2019 13:13:37 +0100 Subject: mod_muc_mam: Validate that the FORM_TYPE of a query is as expected --- plugins/mod_muc_mam.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 166a5c71..963e5255 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -21,6 +21,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 get_form_type = require "util.dataforms".get_type; local mod_muc = module:depends"muc"; local get_room_from_jid = mod_muc.get_room_from_jid; @@ -131,7 +132,11 @@ module:hook("iq-set/bare/"..xmlns_mam..":query", function(event) local qstart, qend; local form = query:get_child("x", "jabber:x:data"); if form then - local err; + local form_type, err = get_form_type(form); + if form_type ~= xmlns_mam then + origin.send(st.error_reply(stanza, "modify", "bad-request", "Unexpected FORM_TYPE, expected '"..xmlns_mam.."'")); + return true; + end form, err = query_form:data(form); if err then origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err)))); -- cgit v1.2.3 From 9f65ce71893ef10485442ee209472a38865da081 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 10 Mar 2019 19:58:28 +0100 Subject: core.certmanager: Do not ask for client certificates by default Since it's mostly only mod_s2s that needs to request client certificates it makes some sense to have mod_s2s ask for this, instead of having eg mod_http ask to disable it. --- plugins/mod_http.lua | 3 --- plugins/mod_s2s/mod_s2s.lua | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 829c2d02..17ea27e1 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -228,9 +228,6 @@ module:provides("net", { listener = server.listener; default_port = 5281; encryption = "ssl"; - ssl_config = { - verify = "none"; - }; multiplex = { pattern = "^[A-Z]"; }; diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 79308847..b0d551fe 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -738,6 +738,9 @@ module:provides("net", { listener = listener; default_port = 5269; encryption = "starttls"; + ssl_config = { + verify = { "peer", "client_once", }; + }; multiplex = { pattern = "^<.*:stream.*%sxmlns%s*=%s*(['\"])jabber:server%1.*>"; }; -- cgit v1.2.3 From b246b00f85b1973058f8b607190a72168380dbc3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 11 Mar 2019 13:07:59 +0100 Subject: mod_tls: Restore querying for certificates on s2s The 'ssl_config' setting in the mod_s2s network service is not used. Only direct TLS ports use this currently. --- plugins/mod_s2s/mod_s2s.lua | 2 +- plugins/mod_tls.lua | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index b0d551fe..f0fdc5fb 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -738,7 +738,7 @@ module:provides("net", { listener = listener; default_port = 5269; encryption = "starttls"; - ssl_config = { + ssl_config = { -- FIXME This is not used atm, see mod_tls verify = { "peer", "client_once", }; }; multiplex = { diff --git a/plugins/mod_tls.lua b/plugins/mod_tls.lua index 4ead60dc..d8bf02c4 100644 --- a/plugins/mod_tls.lua +++ b/plugins/mod_tls.lua @@ -53,13 +53,17 @@ function module.load() local parent_s2s = rawgetopt(parent, "s2s_ssl") or NULL; local host_s2s = rawgetopt(modhost, "s2s_ssl") or parent_s2s; + local request_client_certs = { verify = { "peer", "client_once", }; }; + ssl_ctx_c2s, err_c2s, ssl_cfg_c2s = create_context(host.host, "server", host_c2s, host_ssl, global_c2s); -- for incoming client connections if not ssl_ctx_c2s then module:log("error", "Error creating context for c2s: %s", err_c2s); end - ssl_ctx_s2sout, err_s2sout, ssl_cfg_s2sout = create_context(host.host, "client", host_s2s, host_ssl, global_s2s); -- for outgoing server connections + -- for outgoing server connections + ssl_ctx_s2sout, err_s2sout, ssl_cfg_s2sout = create_context(host.host, "client", host_s2s, host_ssl, global_s2s, request_client_certs); if not ssl_ctx_s2sout then module:log("error", "Error creating contexts for s2sout: %s", err_s2sout); end - ssl_ctx_s2sin, err_s2sin, ssl_cfg_s2sin = create_context(host.host, "server", host_s2s, host_ssl, global_s2s); -- for incoming server connections + -- for incoming server connections + ssl_ctx_s2sin, err_s2sin, ssl_cfg_s2sin = create_context(host.host, "server", host_s2s, host_ssl, global_s2s, request_client_certs); if not ssl_ctx_s2sin then module:log("error", "Error creating contexts for s2sin: %s", err_s2sin); end end -- cgit v1.2.3 From 62f33cd891e824a8d9c5a99c5d1a51af6c23835d Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 18 Mar 2019 09:50:23 +0000 Subject: MUC: Update error message for consistency --- plugins/muc/muc.lib.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index a8d3d790..c828d17d 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -498,7 +498,7 @@ function room_mt:handle_normal_presence(origin, stanza) if orig_occupant == nil and not muc_x and stanza.attr.type == nil then module:log("debug", "Attempted join without , possibly desynced"); origin.send(st.error_reply(stanza, "cancel", "item-not-found", - "You must join the room before sending presence updates")); + "You are not currently connected to this chat")); return true; end -- cgit v1.2.3 From ab545f19a339c76afe6d24912a79e05ee5f4d94c Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 19 Mar 2019 09:05:37 +0000 Subject: mod_admin_telnet: Show module status in module:list() --- plugins/mod_admin_telnet.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 7fae8983..34cc4dc6 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -480,7 +480,12 @@ function def_env.module:list(hosts) end else for _, name in ipairs(modules) do - print(" "..name); + local status, status_text = modulemanager.get_module(host, name).module:get_status(); + local status_summary = ""; + if status == "warn" or status == "error" then + status_summary = (" (%s: %s)"):format(status, status_text); + end + print((" %s%s"):format(name, status_summary)); end end end -- cgit v1.2.3 From c6efcf09bec3f89c768ebab216c69ce116b091e6 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 19 Mar 2019 09:08:06 +0000 Subject: mod_component: Set module status to indicate whether component is connected --- plugins/mod_component.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_component.lua b/plugins/mod_component.lua index b8c87dee..b1ffc81d 100644 --- a/plugins/mod_component.lua +++ b/plugins/mod_component.lua @@ -49,6 +49,7 @@ function module.add_host(module) local send; local function on_destroy(session, err) --luacheck: ignore 212/err + module:set_status("warn", err and ("Disconnected: "..err) or "Disconnected"); env.connected = false; env.session = false; send = nil; @@ -102,6 +103,7 @@ function module.add_host(module) module:log("info", "External component successfully authenticated"); session.send(st.stanza("handshake")); module:fire_event("component-authenticated", { session = session }); + module:set_status("info", "Connected"); return true; end -- cgit v1.2.3 From 755b5076441531a8c8b6f2b2ab831800768402ef Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 19 Mar 2019 09:08:33 +0000 Subject: mod_s2s: Set warning status if not listening on any ports --- plugins/mod_s2s/s2sout.lib.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_s2s/s2sout.lib.lua b/plugins/mod_s2s/s2sout.lib.lua index 5f765da8..34e322d2 100644 --- a/plugins/mod_s2s/s2sout.lib.lua +++ b/plugins/mod_s2s/s2sout.lib.lua @@ -318,7 +318,7 @@ module:hook_global("service-added", function (event) local s2s_sources = portmanager.get_active_services():get("s2s"); if not s2s_sources then - module:log("warn", "s2s not listening on any ports, outgoing connections may fail"); + module:log_status("warn", "s2s not listening on any ports, outgoing connections may fail"); return; end for source, _ in pairs(s2s_sources) do -- cgit v1.2.3 From 992497531e9000cc9139a159cd21ea808e1b636e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 19 Mar 2019 09:08:56 +0000 Subject: mod_muc_mam: Set error status if loaded on incorrect host type --- plugins/mod_muc_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index d414a449..7d429482 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -4,7 +4,7 @@ -- This file is MIT/X11 licensed. if module:get_host_type() ~= "component" then - module:log("error", "mod_%s should be loaded only on a MUC component, not normal hosts", module.name); + module:log_status("error", "mod_%s should be loaded only on a MUC component, not normal hosts", module.name); return; end -- cgit v1.2.3 From d7761bd914bd38e43de12c248196bc81307c71c5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 20 Oct 2017 12:53:53 +0200 Subject: mod_storage_internal,_sql: Add limit to number of items in an archive store (fixes #733) --- plugins/mod_storage_internal.lua | 35 +++++++++++++++++++++++++++++++++++ plugins/mod_storage_sql.lua | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index 42b451bd..d812c0e9 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -1,3 +1,4 @@ +local cache = require "util.cache"; local datamanager = require "core.storagemanager".olddm; local array = require "util.array"; local datetime = require "util.datetime"; @@ -7,6 +8,9 @@ local id = require "util.id".medium; local host = module.host; +local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000); +local archive_item_count_cache = cache.new(module:get_option("storage_archive_item_limit_cache_size", 1000)); + local driver = {}; function driver:open(store, typ) @@ -54,28 +58,56 @@ function archive:append(username, key, value, when, with) value.attr.stamp = datetime.datetime(when); value.attr.stamp_legacy = datetime.legacy(when); + local item_count = archive_item_count_cache:get(username); + if key then local items, err = datamanager.list_load(username, host, self.store); if not items and err then return items, err; end + + -- Check the quota + item_count = items and #items or 0; + archive_item_count_cache:set(username, item_count); + if item_count >= archive_item_limit then + module:log("debug", "%s reached or over quota, not adding to store", username); + return nil, "quota-limit"; + end + if items then + -- Filter out any item with the same key as the one being added items = array(items); items:filter(function (item) return item.key ~= key; end); + value.key = key; items:push(value); local ok, err = datamanager.list_store(username, host, self.store, items); if not ok then return ok, err; end + archive_item_count_cache:set(username, #items); return key; end else + if not item_count then -- Item count not cached? + -- We need to load the list to get the number of items currently stored + local items, err = datamanager.list_load(username, host, self.store); + if not items and err then return items, err; end + item_count = items and #items or 0; + archive_item_count_cache:set(username, item_count); + end + if item_count >= archive_item_limit then + module:log("debug", "%s reached or over quota, not adding to store", username); + return nil, "quota-limit"; + end key = id(); end + module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); + value.key = key; local ok, err = datamanager.list_append(username, host, self.store, value); if not ok then return ok, err; end + archive_item_count_cache:set(username, item_count+1); return key; end @@ -158,6 +190,7 @@ end function archive:delete(username, query) if not query or next(query) == nil then + archive_item_count_cache:set(username, nil); return datamanager.list_store(username, host, self.store, nil); end local items, err = datamanager.list_load(username, host, self.store); @@ -165,6 +198,7 @@ function archive:delete(username, query) if err then return items, err; end + archive_item_count_cache:set(username, 0); -- Store is empty return 0; end @@ -214,6 +248,7 @@ function archive:delete(username, query) end local ok, err = datamanager.list_store(username, host, self.store, items); if not ok then return ok, err; end + archive_item_count_cache:set(username, #items); return count; end diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 5c0c0208..4fe2a262 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -1,6 +1,7 @@ -- luacheck: ignore 212/self +local cache = require "util.cache"; local json = require "util.json"; local sql = require "util.sql"; local xml_parse = require "util.xml".parse; @@ -148,6 +149,9 @@ end --- Archive store API +local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000); +local archive_item_count_cache = cache.new(module:get_option("storage_archive_item_limit_cache_size", 1000)); + -- luacheck: ignore 512 431/user 431/store local map_store = {}; map_store.__index = map_store; @@ -231,6 +235,32 @@ archive_store.caps = { }; archive_store.__index = archive_store function archive_store:append(username, key, value, when, with) + local item_count = archive_item_count_cache:get(username); + if not item_count then + local ok, ret = engine:transaction(function() + local count_sql = [[ + SELECT COUNT(*) FROM "prosodyarchive" + WHERE "host"=? AND "user"=? AND "store"=?; + ]]; + local result = engine:select(count_sql, host, user, store); + if result then + for row in result do + item_count = row[1]; + end + end + end); + if not ok or not item_count then + module:log("error", "Failed while checking quota for %s: %s", username, ret); + return nil, "Failure while checking quota"; + end + archive_item_count_cache:set(username, item_count); + end + + module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); + if item_count >= archive_item_limit then + return nil, "quota-limit"; + end + local user,store = username,self.store; when = when or os.time(); with = with or ""; @@ -245,12 +275,18 @@ function archive_store:append(username, key, value, when, with) VALUES (?,?,?,?,?,?,?,?); ]]; if key then - engine:delete(delete_sql, host, user or "", store, key); + local result, err = engine:delete(delete_sql, host, user or "", store, key); + if result then + item_count = item_count - result:affected(); + archive_item_count_cache:set(username, item_count); + end else + item_count = item_count + 1; key = uuid.generate(); end local t, encoded_value = assert(serialize(value)); engine:insert(insert_sql, host, user or "", store, when, with, key, t, encoded_value); + archive_item_count_cache:set(username, item_count+1); return key; end); if not ok then return ok, ret; end @@ -422,6 +458,7 @@ function archive_store:delete(username, query) end return engine:delete(sql_query, unpack(args)); end); + archive_item_count_cache:set(username, nil); return ok and stmt:affected(), stmt; end -- cgit v1.2.3 From 0028ea46e2aed1e0522da59b3d31912afea2c54a Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 18:01:24 +0100 Subject: mod_storage_internal,_sql: Expose archive capabilities feature set This was planned to be added long ago but was forgotten. --- plugins/mod_storage_internal.lua | 6 ++++++ plugins/mod_storage_sql.lua | 2 ++ 2 files changed, 8 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index d812c0e9..c21fe0dc 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -47,6 +47,12 @@ end local archive = {}; driver.archive = { __index = archive }; +archive.caps = { + total = true; + quota = archive_item_limit; + truncate = true; +}; + function archive:append(username, key, value, when, with) when = when or now(); if not st.is_stanza(value) then diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 4fe2a262..82c5c3fe 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -232,6 +232,8 @@ end local archive_store = {} archive_store.caps = { total = true; + quota = archive_item_limit; + truncate = true; }; archive_store.__index = archive_store function archive_store:append(username, key, value, when, with) -- cgit v1.2.3 From 9eb4885f38891261621cd18aa206883851acbaab Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 18:02:27 +0100 Subject: mod_storage_internal,_sql: Key item count cache on both username and store --- plugins/mod_storage_internal.lua | 19 +++++++++++-------- plugins/mod_storage_sql.lua | 13 ++++++++----- 2 files changed, 19 insertions(+), 13 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index c21fe0dc..52ca4da8 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -5,6 +5,7 @@ local datetime = require "util.datetime"; local st = require "util.stanza"; local now = require "util.time".now; local id = require "util.id".medium; +local jid_join = require "util.jid".join; local host = module.host; @@ -64,7 +65,8 @@ function archive:append(username, key, value, when, with) value.attr.stamp = datetime.datetime(when); value.attr.stamp_legacy = datetime.legacy(when); - local item_count = archive_item_count_cache:get(username); + local cache_key = jid_join(username, host, self.store); + local item_count = archive_item_count_cache:get(cache_key); if key then local items, err = datamanager.list_load(username, host, self.store); @@ -72,7 +74,7 @@ function archive:append(username, key, value, when, with) -- Check the quota item_count = items and #items or 0; - archive_item_count_cache:set(username, item_count); + archive_item_count_cache:set(cache_key, item_count); if item_count >= archive_item_limit then module:log("debug", "%s reached or over quota, not adding to store", username); return nil, "quota-limit"; @@ -89,7 +91,7 @@ function archive:append(username, key, value, when, with) items:push(value); local ok, err = datamanager.list_store(username, host, self.store, items); if not ok then return ok, err; end - archive_item_count_cache:set(username, #items); + archive_item_count_cache:set(cache_key, #items); return key; end else @@ -98,7 +100,7 @@ function archive:append(username, key, value, when, with) local items, err = datamanager.list_load(username, host, self.store); if not items and err then return items, err; end item_count = items and #items or 0; - archive_item_count_cache:set(username, item_count); + archive_item_count_cache:set(cache_key, item_count); end if item_count >= archive_item_limit then module:log("debug", "%s reached or over quota, not adding to store", username); @@ -113,7 +115,7 @@ function archive:append(username, key, value, when, with) local ok, err = datamanager.list_append(username, host, self.store, value); if not ok then return ok, err; end - archive_item_count_cache:set(username, item_count+1); + archive_item_count_cache:set(cache_key, item_count+1); return key; end @@ -195,8 +197,9 @@ function archive:dates(username) end function archive:delete(username, query) + local cache_key = jid_join(username, host, self.store); if not query or next(query) == nil then - archive_item_count_cache:set(username, nil); + archive_item_count_cache:set(cache_key, nil); return datamanager.list_store(username, host, self.store, nil); end local items, err = datamanager.list_load(username, host, self.store); @@ -204,7 +207,7 @@ function archive:delete(username, query) if err then return items, err; end - archive_item_count_cache:set(username, 0); + archive_item_count_cache:set(cache_key, 0); -- Store is empty return 0; end @@ -254,7 +257,7 @@ function archive:delete(username, query) end local ok, err = datamanager.list_store(username, host, self.store, items); if not ok then return ok, err; end - archive_item_count_cache:set(username, #items); + archive_item_count_cache:set(cache_key, #items); return count; end diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 82c5c3fe..3028bb72 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -7,6 +7,7 @@ local sql = require "util.sql"; local xml_parse = require "util.xml".parse; local uuid = require "util.uuid"; local resolve_relative_path = require "util.paths".resolve_relative_path; +local jid_join = require "util.jid".join; local is_stanza = require"util.stanza".is_stanza; local t_concat = table.concat; @@ -237,7 +238,8 @@ archive_store.caps = { }; archive_store.__index = archive_store function archive_store:append(username, key, value, when, with) - local item_count = archive_item_count_cache:get(username); + local cache_key = jid_join(username, host, self.store); + local item_count = archive_item_count_cache:get(cache_key); if not item_count then local ok, ret = engine:transaction(function() local count_sql = [[ @@ -255,7 +257,7 @@ function archive_store:append(username, key, value, when, with) module:log("error", "Failed while checking quota for %s: %s", username, ret); return nil, "Failure while checking quota"; end - archive_item_count_cache:set(username, item_count); + archive_item_count_cache:set(cache_key, item_count); end module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); @@ -280,7 +282,7 @@ function archive_store:append(username, key, value, when, with) local result, err = engine:delete(delete_sql, host, user or "", store, key); if result then item_count = item_count - result:affected(); - archive_item_count_cache:set(username, item_count); + archive_item_count_cache:set(cache_key, item_count); end else item_count = item_count + 1; @@ -288,7 +290,7 @@ function archive_store:append(username, key, value, when, with) end local t, encoded_value = assert(serialize(value)); engine:insert(insert_sql, host, user or "", store, when, with, key, t, encoded_value); - archive_item_count_cache:set(username, item_count+1); + archive_item_count_cache:set(cache_key, item_count+1); return key; end); if not ok then return ok, ret; end @@ -460,7 +462,8 @@ function archive_store:delete(username, query) end return engine:delete(sql_query, unpack(args)); end); - archive_item_count_cache:set(username, nil); + local cache_key = jid_join(username, host, self.store); + archive_item_count_cache:set(cache_key, nil); return ok and stmt:affected(), stmt; end -- cgit v1.2.3 From 9dce1de7674543e1daa3664c75a709845b1330fb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 7 Nov 2017 18:58:52 +0100 Subject: mod_mam: Trim archive when quota has been exceeded --- plugins/mod_mam/mod_mam.lua | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 88cbaa08..5be4bc24 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -40,6 +40,10 @@ local strip_tags = module:get_option_set("dont_archive_namespaces", { "http://ja local archive_store = module:get_option_string("archive_store", "archive"); local archive = module:open_store(archive_store, "archive"); +local cleanup_after = module:get_option_string("archive_expires_after", "1w"); +local cleanup_interval = module:get_option_number("archive_cleanup_interval", 4 * 60 * 60); +local archive_item_limit = module:get_option_number("storage_archive_item_limit", archive.caps and archive.caps.quota or 1000); + if not archive.find then error("mod_"..(archive._provided_by or archive.name and "storage_"..archive.name).." does not support archiving\n" .."See https://prosody.im/doc/storage and https://prosody.im/doc/archiving for more information"); @@ -295,7 +299,20 @@ local function message_handler(event, c2s) log("debug", "Archiving stanza: %s", stanza:top_tag()); -- And stash it - local ok = archive:append(store_user, nil, clone_for_storage, time_now(), with); + local time = time_now(); + local ok, err = archive:append(store_user, nil, clone_for_storage, time, with); + if not ok and err == "quota-limit" then + if archive.caps and archive.caps.truncate then + module:log("debug", "User '%s' over quota, trimming archive", store_user); + local truncated = archive:delete(store_user, { + truncate = archive_item_limit - 1; + ["end"] = type(cleanup_after) == "number" and (os.time() - cleanup_after) or nil; + }); + if truncated then + ok, err = archive:append(store_user, nil, clone_for_storage, time, with); + end + end + end if ok then local clone_for_other_handlers = st.clone(stanza); local id = ok; @@ -321,8 +338,6 @@ end module:hook("pre-message/bare", strip_stanza_id_after_other_events, -1); module:hook("pre-message/full", strip_stanza_id_after_other_events, -1); -local cleanup_after = module:get_option_string("archive_expires_after", "1w"); -local cleanup_interval = module:get_option_number("archive_cleanup_interval", 4 * 60 * 60); if cleanup_after ~= "never" then local cleanup_storage = module:open_store("archive_cleanup"); local cleanup_map = module:open_store("archive_cleanup", "map"); -- cgit v1.2.3 From 0681ffe60631d573ad8529de7eaa187cb21a20b1 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 20 Mar 2019 12:14:45 +0100 Subject: mod_storage_memory: Add support for archive item limits --- plugins/mod_storage_memory.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index 745e394b..8e1cf879 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -8,6 +8,8 @@ local new_id = require "util.id".medium; local auto_purge_enabled = module:get_option_boolean("storage_memory_temporary", false); local auto_purge_stores = module:get_option_set("storage_memory_temporary_stores", {}); +local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000); + local memory = setmetatable({}, { __index = function(t, k) local store = module:shared(k) @@ -51,6 +53,12 @@ archive_store.__index = archive_store; archive_store.users = _users; +archive_store.caps = { + total = true; + quota = archive_item_limit; + truncate = true; +}; + function archive_store:append(username, key, value, when, with) if is_stanza(value) then value = st.preserialize(value); @@ -70,6 +78,8 @@ function archive_store:append(username, key, value, when, with) end if a[key] then table.remove(a, a[key]); + elseif #a >= archive_item_limit then + return nil, "quota-limit"; end local i = #a+1; a[i] = v; -- cgit v1.2.3 From c4b5bfdc5f2da4cdbe085a5a95c6418f802ec56e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:04:34 +0100 Subject: mod_storage_internal: Increase default quota to 10 000 Performance doesn't seem great but 10k should be far enough from limits inherited by the Lua parser. 1000 messages seemed pretty close to what an active user might produce in one week. --- plugins/mod_storage_internal.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index 52ca4da8..cb88f10f 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -9,7 +9,7 @@ local jid_join = require "util.jid".join; local host = module.host; -local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000); +local archive_item_limit = module:get_option_number("storage_archive_item_limit", 10000); local archive_item_count_cache = cache.new(module:get_option("storage_archive_item_limit_cache_size", 1000)); local driver = {}; -- cgit v1.2.3 From 3e5243f2d2df3e4933a9bd7fdaf13c848265178e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:09:38 +0100 Subject: mod_storage_sql: Don't increment counter twice (fixes accounting error) --- plugins/mod_storage_sql.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 3028bb72..154daf06 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -285,7 +285,6 @@ function archive_store:append(username, key, value, when, with) archive_item_count_cache:set(cache_key, item_count); end else - item_count = item_count + 1; key = uuid.generate(); end local t, encoded_value = assert(serialize(value)); -- cgit v1.2.3 From 61edbdb90f50b71c6a13f24e7621b561fef9b3ac Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:10:46 +0100 Subject: mod_storage_sql: Fix to use currently queried store Was using the previously queried store due to this being cached in an upvalue. --- plugins/mod_storage_sql.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 154daf06..325fab94 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -238,7 +238,8 @@ archive_store.caps = { }; archive_store.__index = archive_store function archive_store:append(username, key, value, when, with) - local cache_key = jid_join(username, host, self.store); + local user,store = username,self.store; + local cache_key = jid_join(username, host, store); local item_count = archive_item_count_cache:get(cache_key); if not item_count then local ok, ret = engine:transaction(function() @@ -265,7 +266,6 @@ function archive_store:append(username, key, value, when, with) return nil, "quota-limit"; end - local user,store = username,self.store; when = when or os.time(); with = with or ""; local ok, ret = engine:transaction(function() -- cgit v1.2.3 From 56a9e395ade713122fd2251a64232abd270cadbe Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:12:02 +0100 Subject: mod_storage_sql: Skip cache write This would cause the cache to be wrong in case the the later INSERT fails and the transaction is aborted. --- plugins/mod_storage_sql.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 325fab94..35a16870 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -282,7 +282,6 @@ function archive_store:append(username, key, value, when, with) local result, err = engine:delete(delete_sql, host, user or "", store, key); if result then item_count = item_count - result:affected(); - archive_item_count_cache:set(cache_key, item_count); end else key = uuid.generate(); -- cgit v1.2.3 From 5029870d3eee5bbe50c012fe1e7f4ee62e62ee24 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:13:27 +0100 Subject: mod_storage_sql: Cache total count if it's calculated as part of the current query --- plugins/mod_storage_sql.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 35a16870..b3bd5171 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -384,6 +384,9 @@ function archive_store:find(username, query) total = row[1]; end end + if query.start == nil and query.with == nil and query["end"] == nil and query.key == nil then + archive_item_count_cache:set(cache_key, total); + end if query.limit == 0 then -- Skip the real query return noop, total; end -- cgit v1.2.3 From 9393931a25367390465b480b8dbaa38e9f199b54 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:18:54 +0100 Subject: mod_storage_sql: Return cached count if only this is queried for --- plugins/mod_storage_sql.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index b3bd5171..8c03da01 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -362,7 +362,11 @@ end function archive_store:find(username, query) query = query or {}; local user,store = username,self.store; - local total; + local cache_key = jid_join(username, host, self.store); + local total = archive_item_count_cache:get(cache_key); + if total ~= nil and query.limit == 0 and query.start == nil and query.with == nil and query["end"] == nil and query.key == nil then + return noop, total; + end local ok, result = engine:transaction(function() local sql_query = [[ SELECT "key", "type", "value", "when", "with" -- cgit v1.2.3 From 2fed4a88c282ca6aa62d9641f3360a021ec0cebe Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:22:21 +0100 Subject: mod_mam: On quota hit, separately delete by time and by item count This is to work around a possible SQL issue where offsets and time stamps don't interact correctly. --- plugins/mod_mam/mod_mam.lua | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 5be4bc24..632de9ea 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -302,11 +302,19 @@ local function message_handler(event, c2s) local time = time_now(); local ok, err = archive:append(store_user, nil, clone_for_storage, time, with); if not ok and err == "quota-limit" then - if archive.caps and archive.caps.truncate then - module:log("debug", "User '%s' over quota, trimming archive", store_user); + if type(cleanup_after) == "number" then + module:log("debug", "User '%s' over quota, cleaning archive", store_user); + local cleaned = archive:delete(store_user, { + ["end"] = (os.time() - cleanup_after); + }); + if cleaned then + ok, err = archive:append(store_user, nil, clone_for_storage, time, with); + end + end + if not ok and (archive.caps and archive.caps.truncate) then + module:log("debug", "User '%s' over quota, truncating archive", store_user); local truncated = archive:delete(store_user, { truncate = archive_item_limit - 1; - ["end"] = type(cleanup_after) == "number" and (os.time() - cleanup_after) or nil; }); if truncated then ok, err = archive:append(store_user, nil, clone_for_storage, time, with); -- cgit v1.2.3 From 5bb703f07f52906b1280daaac164a3886f09a373 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 02:24:48 +0100 Subject: mod_storage_internal: Include store name when reporting quota status --- plugins/mod_storage_internal.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index cb88f10f..c87d01be 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -109,7 +109,7 @@ function archive:append(username, key, value, when, with) key = id(); end - module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); + module:log("debug", "%s has %d items out of %d limit in store %s", username, item_count, archive_item_limit, self.store); value.key = key; -- cgit v1.2.3 From 8cc789c7968e0f578eba70be1be13b1645e52914 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 22 Mar 2019 16:30:53 +0100 Subject: mod_storage_sql: No archive item limit by default --- plugins/mod_storage_sql.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 8c03da01..6b26759f 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -150,7 +150,7 @@ end --- Archive store API -local archive_item_limit = module:get_option_number("storage_archive_item_limit", 1000); +local archive_item_limit = module:get_option_number("storage_archive_item_limit"); local archive_item_count_cache = cache.new(module:get_option("storage_archive_item_limit_cache_size", 1000)); -- luacheck: ignore 512 431/user 431/store @@ -261,9 +261,11 @@ function archive_store:append(username, key, value, when, with) archive_item_count_cache:set(cache_key, item_count); end - module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); - if item_count >= archive_item_limit then - return nil, "quota-limit"; + if archive_item_limit then + module:log("debug", "%s has %d items out of %d limit", username, item_count, archive_item_limit); + if item_count >= archive_item_limit then + return nil, "quota-limit"; + end end when = when or os.time(); -- cgit v1.2.3 From 582fa3f46f105fe55447d607dceb43b5ac61d440 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 25 Feb 2019 15:48:28 +0100 Subject: mod_storage_internal: Implement a summary API returning message counts per contact --- plugins/mod_storage_internal.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index c87d01be..aa5c3c8a 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -196,6 +196,16 @@ function archive:dates(username) return array(items):pluck("when"):map(datetime.date):unique(); end +function archive:summary(username, query) + local iter, err = self:find(username, query) + if not iter then return iter, err; end + local summary = {}; + for _, _, _, with in iter do + summary[with] = (summary[with] or 0) + 1; + end + return summary; +end + function archive:delete(username, query) local cache_key = jid_join(username, host, self.store); if not query or next(query) == nil then -- cgit v1.2.3 From a32b5ceb4576f8fefeea0f68aae1f81dd942125d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 25 Feb 2019 15:51:55 +0100 Subject: mod_storage_sql: Implement archive summary API --- plugins/mod_storage_sql.lua | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 6b26759f..ffe48ab8 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -419,6 +419,41 @@ function archive_store:find(username, query) end, total; end +function archive_store:summary(username, query) + query = query or {}; + local user,store = username,self.store; + local ok, result = engine:transaction(function() + local sql_query = [[ + SELECT DISTINCT "with", COUNT(*) + FROM "prosodyarchive" + WHERE %s + GROUP BY "with" + ORDER BY "sort_id" %s%s; + ]]; + local args = { host, user or "", store, }; + local where = { "\"host\" = ?", "\"user\" = ?", "\"store\" = ?", }; + + archive_where(query, args, where); + + archive_where_id_range(query, args, where); + + if query.limit then + args[#args+1] = query.limit; + end + + sql_query = sql_query:format(t_concat(where, " AND "), query.reverse + and "DESC" or "ASC", query.limit and " LIMIT ?" or ""); + return engine:select(sql_query, unpack(args)); + end); + if not ok then return ok, result end + local summary = {}; + for row in result do + local with, count = row[1], row[2]; + summary[with] = count; + end + return summary; +end + function archive_store:delete(username, query) query = query or {}; local user,store = username,self.store; -- cgit v1.2.3 From 9b96017ca92a16719c614484e7c314bcd7b0ba80 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 Mar 2019 22:05:08 +0100 Subject: mod_storage_memory: Implement archive summary API --- plugins/mod_storage_memory.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index 8e1cf879..41180aba 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -147,6 +147,16 @@ function archive_store:find(username, query) end, count; end +function archive:summary(username, query) + local iter, err = self:find(username, query) + if not iter then return iter, err; end + local summary = {}; + for _, _, _, with in iter do + summary[with] = (summary[with] or 0) + 1; + end + return summary; +end + function archive_store:delete(username, query) if not query or next(query) == nil then -- cgit v1.2.3 From 170c49b52dec97673c1cb473038e0c538e239b2c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 Mar 2019 22:05:42 +0100 Subject: mod_storage_memory: Fix copypaste mistake --- plugins/mod_storage_memory.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index 41180aba..dde2d571 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -147,7 +147,7 @@ function archive_store:find(username, query) end, count; end -function archive:summary(username, query) +function archive_store:summary(username, query) local iter, err = self:find(username, query) if not iter then return iter, err; end local summary = {}; -- cgit v1.2.3 From 8e68b0dd1adfcd7932f368a0b00dd2019c95db38 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 24 Nov 2018 02:25:44 +0100 Subject: mod_csi_simple: Use write locks in net.server if available --- plugins/mod_csi_simple.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index da2dd953..abe65fce 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -86,7 +86,9 @@ end, -1); module:hook("csi-client-inactive", function (event) local session = event.origin; - if session.pump then + if session.conn and session.conn and session.conn.pause_writes then + session.conn:pause_writes(); + elseif session.pump then session.pump:pause(); else local bare_jid = jid.join(session.username, session.host); @@ -115,6 +117,8 @@ module:hook("csi-client-active", function (event) local session = event.origin; if session.pump then session.pump:resume(); + elseif session.conn and session.conn and session.conn.resume_writes then + session.conn:resume_writes(); end end); -- cgit v1.2.3 From 9e7035be7282a7902989904cec6aeec879814f49 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 18:30:51 +0100 Subject: mod_c2s: Fire an event when outgoing buffers have been emptied --- plugins/mod_c2s.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua index 8d7b92fe..7c6d95f7 100644 --- a/plugins/mod_c2s.lua +++ b/plugins/mod_c2s.lua @@ -332,6 +332,13 @@ function listener.onreadtimeout(conn) end end +function listener.ondrain(conn) + local session = sessions[conn]; + if session then + return (hosts[session.host] or prosody).events.fire_event("c2s-ondrain", { session = session }); + end +end + local function keepalive(event) local session = event.session; if not session.notopen then -- cgit v1.2.3 From e5885c928a79604dea999d24cf57104150b55898 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 18:32:50 +0100 Subject: mod_csi_simple: Break out stanza timestamping into a function for future reuse --- plugins/mod_csi_simple.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index abe65fce..6bd6c0bf 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -84,6 +84,14 @@ module:hook("csi-is-stanza-important", function (event) return true; end, -1); +local function with_timestamp(stanza, from) + if st.is_stanza(stanza) and stanza.attr.xmlns == nil and stanza.name ~= "iq" then + stanza = st.clone(stanza); + stanza:add_direct_child(st.stanza("delay", {xmlns = "urn:xmpp:delay", from = from, stamp = dt.datetime()})); + end + return stanza; +end + module:hook("csi-client-inactive", function (event) local session = event.origin; if session.conn and session.conn and session.conn.pause_writes then @@ -102,11 +110,7 @@ module:hook("csi-client-inactive", function (event) pump:flush(); send(stanza); else - if st.is_stanza(stanza) and stanza.attr.xmlns == nil and stanza.name ~= "iq" then - stanza = st.clone(stanza); - stanza:add_direct_child(st.stanza("delay", {xmlns = "urn:xmpp:delay", from = bare_jid, stamp = dt.datetime()})); - end - pump:push(stanza); + pump:push(with_timestamp(stanza, bare_jid)); end return true; end -- cgit v1.2.3 From 643c317b1627da95e839bab0e397d89ab6f6a589 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 18:33:38 +0100 Subject: mod_csi_simple: Count buffered items and flush when it reaches configured limit In this mode, stanzas have been serialized to strings in the internal net.server buffer, so it is difficult to count them after the fact. --- plugins/mod_csi_simple.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index 6bd6c0bf..5c829179 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -10,6 +10,7 @@ local jid = require "util.jid"; local st = require "util.stanza"; local dt = require "util.datetime"; local new_queue = require "util.queue".new; +local filters = require "util.filters"; local function new_pump(output, ...) -- luacheck: ignore 212/self @@ -92,10 +93,22 @@ local function with_timestamp(stanza, from) return stanza; end +local function manage_buffer(stanza, session) + local ctr = session.csi_counter or 0; + if ctr >= queue_size or module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then + session.conn:resume_writes(); + else + stanza = with_timestamp(stanza, jid.join(session.username, session.host)) + end + session.csi_counter = ctr + 1; + return stanza; +end + module:hook("csi-client-inactive", function (event) local session = event.origin; if session.conn and session.conn and session.conn.pause_writes then session.conn:pause_writes(); + filters.add_filter(session, "stanzas/out", manage_buffer); elseif session.pump then session.pump:pause(); else @@ -122,7 +135,16 @@ module:hook("csi-client-active", function (event) if session.pump then session.pump:resume(); elseif session.conn and session.conn and session.conn.resume_writes then + filters.remove_filter(session, "stanzas/out", manage_buffer); session.conn:resume_writes(); end end); + +module:hook("c2s-ondrain", function (event) + local session = event.session; + if session.state == "inactive" and session.conn and session.conn and session.conn.pause_writes then + session.csi_counter = 0; + session.conn:pause_writes(); + end +end); -- cgit v1.2.3 From 141c5d3fbe257cf63249eeec528dd36b3266b25e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 18:58:53 +0100 Subject: mod_csi_simple: Trigger buffer flush on seeing incoming data I.e. the client sent us something, which means its network / radio is active. --- plugins/mod_csi_simple.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index 5c829179..07a8cfb3 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -104,11 +104,17 @@ local function manage_buffer(stanza, session) return stanza; end +local function flush_buffer(data, session) + session.conn:resume_writes(); + return data; +end + module:hook("csi-client-inactive", function (event) local session = event.origin; if session.conn and session.conn and session.conn.pause_writes then session.conn:pause_writes(); filters.add_filter(session, "stanzas/out", manage_buffer); + filters.add_filter(session, "bytes/in", flush_buffer); elseif session.pump then session.pump:pause(); else @@ -136,6 +142,7 @@ module:hook("csi-client-active", function (event) session.pump:resume(); elseif session.conn and session.conn and session.conn.resume_writes then filters.remove_filter(session, "stanzas/out", manage_buffer); + filters.remove_filter(session, "bytes/in", flush_buffer); session.conn:resume_writes(); end end); -- cgit v1.2.3 From 3a1498ebd335a15a987e3087f84089620b5507c5 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 19:02:40 +0100 Subject: mod_csi_simple: Also flush buffer in "pump" mode --- plugins/mod_csi_simple.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index 07a8cfb3..ee7e01c9 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -109,9 +109,15 @@ local function flush_buffer(data, session) return data; end +local function flush_pump(data, session) + session.pump:flush(); + return data; +end + module:hook("csi-client-inactive", function (event) local session = event.origin; if session.conn and session.conn and session.conn.pause_writes then + session.log("info", "Native net.server buffer management mode"); session.conn:pause_writes(); filters.add_filter(session, "stanzas/out", manage_buffer); filters.add_filter(session, "bytes/in", flush_buffer); @@ -124,6 +130,7 @@ module:hook("csi-client-inactive", function (event) local pump = new_pump(session.send, queue_size); pump:pause(); session.pump = pump; + filters.add_filter(session, "bytes/in", flush_pump); function session.send(stanza) if session.state == "active" or module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then pump:flush(); -- cgit v1.2.3 From 6c89a86e0df62c51e0fb12596d3999324245c9fe Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 20:22:01 +0100 Subject: mod_csi_simple: Remove old "pump" queue/buffer method, handled in net.server now --- plugins/mod_csi_simple.lua | 63 ++-------------------------------------------- 1 file changed, 2 insertions(+), 61 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index ee7e01c9..0fa0d083 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -9,42 +9,8 @@ module:depends"csi" local jid = require "util.jid"; local st = require "util.stanza"; local dt = require "util.datetime"; -local new_queue = require "util.queue".new; local filters = require "util.filters"; -local function new_pump(output, ...) - -- luacheck: ignore 212/self - local q = new_queue(...); - local flush = true; - function q:pause() - flush = false; - end - function q:resume() - flush = true; - return q:flush(); - end - local push = q.push; - function q:push(item) - local ok = push(self, item); - if not ok then - q:flush(); - output(item, self); - elseif flush then - return q:flush(); - end - return true; - end - function q:flush() - local item = self:pop(); - while item do - output(item, self); - item = self:pop(); - end - return true; - end - return q; -end - local queue_size = module:get_option_number("csi_queue_size", 256); module:hook("csi-is-stanza-important", function (event) @@ -109,45 +75,20 @@ local function flush_buffer(data, session) return data; end -local function flush_pump(data, session) - session.pump:flush(); - return data; -end - module:hook("csi-client-inactive", function (event) local session = event.origin; if session.conn and session.conn and session.conn.pause_writes then - session.log("info", "Native net.server buffer management mode"); session.conn:pause_writes(); filters.add_filter(session, "stanzas/out", manage_buffer); filters.add_filter(session, "bytes/in", flush_buffer); - elseif session.pump then - session.pump:pause(); else - local bare_jid = jid.join(session.username, session.host); - local send = session.send; - session._orig_send = send; - local pump = new_pump(session.send, queue_size); - pump:pause(); - session.pump = pump; - filters.add_filter(session, "bytes/in", flush_pump); - function session.send(stanza) - if session.state == "active" or module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then - pump:flush(); - send(stanza); - else - pump:push(with_timestamp(stanza, bare_jid)); - end - return true; - end + session.log("warn", "Session connection does not support write pausing"); end end); module:hook("csi-client-active", function (event) local session = event.origin; - if session.pump then - session.pump:resume(); - elseif session.conn and session.conn and session.conn.resume_writes then + if session.conn and session.conn and session.conn.resume_writes then filters.remove_filter(session, "stanzas/out", manage_buffer); filters.remove_filter(session, "bytes/in", flush_buffer); session.conn:resume_writes(); -- cgit v1.2.3 From 1e77bb6ed2ac00b1e5f64f39da41ec140fe425ce Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 20:41:25 +0100 Subject: mod_csi_simple: Separate out functions to enable/disable optimizations This allows reusing this logic outside the events. Letting the functions be module globals makes it easier to access from eg the telnet console. --- plugins/mod_csi_simple.lua | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index 0fa0d083..14abbc68 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -75,8 +75,7 @@ local function flush_buffer(data, session) return data; end -module:hook("csi-client-inactive", function (event) - local session = event.origin; +function enable_optimizations(session) if session.conn and session.conn and session.conn.pause_writes then session.conn:pause_writes(); filters.add_filter(session, "stanzas/out", manage_buffer); @@ -84,15 +83,24 @@ module:hook("csi-client-inactive", function (event) else session.log("warn", "Session connection does not support write pausing"); end -end); +end -module:hook("csi-client-active", function (event) - local session = event.origin; +function disble_optimizations(session) if session.conn and session.conn and session.conn.resume_writes then filters.remove_filter(session, "stanzas/out", manage_buffer); filters.remove_filter(session, "bytes/in", flush_buffer); session.conn:resume_writes(); end +end + +module:hook("csi-client-inactive", function (event) + local session = event.origin; + enable_optimizations(session); +end); + +module:hook("csi-client-active", function (event) + local session = event.origin; + disble_optimizations(session); end); -- cgit v1.2.3 From e887ed5cad52d2853ba66dfe1a7ec0762f4624df Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 20:43:15 +0100 Subject: mod_csi_simple: Disable optimizations on unload and re-enable on load --- plugins/mod_csi_simple.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index 14abbc68..d0de222e 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -111,3 +111,24 @@ module:hook("c2s-ondrain", function (event) session.conn:pause_writes(); end end); + +function module.load() + for _, user_session in pairs(prosody.hosts[module.host].sessions) do + for _, session in pairs(user_session.sessions) do + if session.state == "inactive" then + enable_optimizations(session); + end + end + end +end + +function module.unload() + for _, user_session in pairs(prosody.hosts[module.host].sessions) do + for _, session in pairs(user_session.sessions) do + if session.state == "inactive" then + disble_optimizations(session); + end + end + end +end + -- cgit v1.2.3 From 684a26f5be5a29e4d8eb82af0f9b2d9a87f98267 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 20:53:49 +0100 Subject: mod_csi_simple: Add some debug logging --- plugins/mod_csi_simple.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index d0de222e..ff1fa86c 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -71,6 +71,7 @@ local function manage_buffer(stanza, session) end local function flush_buffer(data, session) + session.log("debug", "Client sent something, flushing buffer once"); session.conn:resume_writes(); return data; end @@ -109,6 +110,7 @@ module:hook("c2s-ondrain", function (event) if session.state == "inactive" and session.conn and session.conn and session.conn.pause_writes then session.csi_counter = 0; session.conn:pause_writes(); + session.log("debug", "Buffer flushed, resuming inactive mode"); end end); -- cgit v1.2.3 From ba9e50592452854fe03cc12b1c376c17b8091c80 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 24 Mar 2019 22:01:36 +0100 Subject: mod_csi_simple: Improve debug logs by mentioing why the buffer gets flushed --- plugins/mod_csi_simple.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index ff1fa86c..2dda1c42 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -61,7 +61,11 @@ end local function manage_buffer(stanza, session) local ctr = session.csi_counter or 0; - if ctr >= queue_size or module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then + if ctr >= queue_size then + session.log("debug", "Queue size limit hit, flushing buffer"); + session.conn:resume_writes(); + elseif module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then + session.log("debug", "Important stanza, flushing buffer"); session.conn:resume_writes(); else stanza = with_timestamp(stanza, jid.join(session.username, session.host)) -- cgit v1.2.3 From 5074566d79830e5a6ecba2b13fd9cdad2e1fb902 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 25 Mar 2019 10:32:39 +0000 Subject: mod_csi_simple: Fix type in function name --- plugins/mod_csi_simple.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index 2dda1c42..c79c56fc 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -90,7 +90,7 @@ function enable_optimizations(session) end end -function disble_optimizations(session) +function disable_optimizations(session) if session.conn and session.conn and session.conn.resume_writes then filters.remove_filter(session, "stanzas/out", manage_buffer); filters.remove_filter(session, "bytes/in", flush_buffer); @@ -105,7 +105,7 @@ end); module:hook("csi-client-active", function (event) local session = event.origin; - disble_optimizations(session); + disable_optimizations(session); end); @@ -132,9 +132,8 @@ function module.unload() for _, user_session in pairs(prosody.hosts[module.host].sessions) do for _, session in pairs(user_session.sessions) do if session.state == "inactive" then - disble_optimizations(session); + disable_optimizations(session); end end end end - -- cgit v1.2.3 From 096ebc3bcfde419b5c9c387f08d9c41c4d65b847 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 25 Mar 2019 15:20:28 +0100 Subject: mod_csi_simple: Include queue size in debug messages --- plugins/mod_csi_simple.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index c79c56fc..a9148618 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -62,10 +62,10 @@ end local function manage_buffer(stanza, session) local ctr = session.csi_counter or 0; if ctr >= queue_size then - session.log("debug", "Queue size limit hit, flushing buffer"); + session.log("debug", "Queue size limit hit, flushing buffer (queue size is %d)", session.csi_counter); session.conn:resume_writes(); elseif module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then - session.log("debug", "Important stanza, flushing buffer"); + session.log("debug", "Important stanza, flushing buffer (queue size is %d)", session.csi_counter); session.conn:resume_writes(); else stanza = with_timestamp(stanza, jid.join(session.username, session.host)) @@ -75,7 +75,7 @@ local function manage_buffer(stanza, session) end local function flush_buffer(data, session) - session.log("debug", "Client sent something, flushing buffer once"); + session.log("debug", "Client sent something, flushing buffer once (queue size is %d)", session.csi_counter); session.conn:resume_writes(); return data; end @@ -112,9 +112,9 @@ end); module:hook("c2s-ondrain", function (event) local session = event.session; if session.state == "inactive" and session.conn and session.conn and session.conn.pause_writes then - session.csi_counter = 0; session.conn:pause_writes(); - session.log("debug", "Buffer flushed, resuming inactive mode"); + session.log("debug", "Buffer flushed, resuming inactive mode (queue size was %d)", session.csi_counter); + session.csi_counter = 0; end end); -- cgit v1.2.3 From 2ab785fd9fc6d669b6bd0c24333dc27af86153af Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 26 Mar 2019 14:48:21 +0000 Subject: loggingmanager, mod_posix: Move syslog to core, fixes #541 (in a way) --- plugins/mod_posix.lua | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_posix.lua b/plugins/mod_posix.lua index 23df4d23..8367ae9e 100644 --- a/plugins/mod_posix.lua +++ b/plugins/mod_posix.lua @@ -113,19 +113,6 @@ local function write_pidfile() end end -local syslog_opened; -function syslog_sink_maker(config) -- luacheck: ignore 212/config - if not syslog_opened then - pposix.syslog_open("prosody", module:get_option_string("syslog_facility")); - syslog_opened = true; - end - local syslog = pposix.syslog_log; - return function (name, level, message, ...) - syslog(level, name, format(message, ...)); - end; -end -require "core.loggingmanager".register_sink_type("syslog", syslog_sink_maker); - local daemonize = module:get_option("daemonize", prosody.installed); local function remove_log_sinks() -- cgit v1.2.3 From 28322869e86df2d2d094acfe83a09d6dc81732c4 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 26 Mar 2019 14:59:42 +0000 Subject: mod_posix: Remove unnecessary import of util.format (thanks luacheck and buildbot) --- plugins/mod_posix.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_posix.lua b/plugins/mod_posix.lua index 8367ae9e..a2a60dd0 100644 --- a/plugins/mod_posix.lua +++ b/plugins/mod_posix.lua @@ -20,7 +20,6 @@ if not have_signal then module:log("warn", "Couldn't load signal library, won't respond to SIGTERM"); end -local format = require "util.format".format; local lfs = require "lfs"; local stat = lfs.attributes; -- cgit v1.2.3 From a6571e3ef33936cb4f2b99b582148accc60af846 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 2 Apr 2019 21:17:28 +0200 Subject: mod_limits: Fix indentation Appears to have been messed up in 60e113f3682f --- plugins/mod_limits.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_limits.lua b/plugins/mod_limits.lua index 914d5c44..32bc75a9 100644 --- a/plugins/mod_limits.lua +++ b/plugins/mod_limits.lua @@ -51,18 +51,18 @@ end local default_filter_set = {}; function default_filter_set.bytes_in(bytes, session) - local sess_throttle = session.throttle; - if sess_throttle then - local ok, balance, outstanding = sess_throttle:poll(#bytes, true); + local sess_throttle = session.throttle; + if sess_throttle then + local ok, balance, outstanding = sess_throttle:poll(#bytes, true); if not ok then - session.log("debug", "Session over rate limit (%d) with %d (by %d), pausing", sess_throttle.max, #bytes, outstanding); + session.log("debug", "Session over rate limit (%d) with %d (by %d), pausing", sess_throttle.max, #bytes, outstanding); outstanding = ceil(outstanding); session.conn:pause(); -- Read no more data from the connection until there is no outstanding data local outstanding_data = bytes:sub(-outstanding); bytes = bytes:sub(1, #bytes-outstanding); timer.add_task(limits_resolution, function () if not session.conn then return; end - if sess_throttle:peek(#outstanding_data) then + if sess_throttle:peek(#outstanding_data) then session.log("debug", "Resuming paused session"); session.conn:resume(); end -- cgit v1.2.3 From 1b534392de5c8430ee88417c5f6fff8acce1da62 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 2 Apr 2019 20:38:51 +0200 Subject: mod_limits: Allow configuring a list of unrestricted JIDs (fixes #1323) --- plugins/mod_limits.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_limits.lua b/plugins/mod_limits.lua index 32bc75a9..56e3faaf 100644 --- a/plugins/mod_limits.lua +++ b/plugins/mod_limits.lua @@ -96,3 +96,20 @@ end function module.unload() filters.remove_filter_hook(filter_hook); end + +function module.add_host(module) + local unlimited_jids = module:get_option_inherited_set("unlimited_jids", {}); + + if not unlimited_jids:empy() then + module:hook("authentication-success", function (event) + local session = event.session; + local session_type = session.type:match("^[^_]+"); + local jid = session.username .. "@" .. session.host; + if unlimited_jids:contains(jid) then + local filter_set = type_filters[session_type]; + filters.remove_filter(session, "bytes/in", filter_set.bytes_in); + session.throttle = nil; + end + end); + end +end -- cgit v1.2.3 From e632119ffa88909b7f3be5b59e47373204e75aa8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 2 Apr 2019 21:22:20 +0200 Subject: mod_limits: Fix typo --- plugins/mod_limits.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_limits.lua b/plugins/mod_limits.lua index 56e3faaf..7ae8bb34 100644 --- a/plugins/mod_limits.lua +++ b/plugins/mod_limits.lua @@ -100,7 +100,7 @@ end function module.add_host(module) local unlimited_jids = module:get_option_inherited_set("unlimited_jids", {}); - if not unlimited_jids:empy() then + if not unlimited_jids:empty() then module:hook("authentication-success", function (event) local session = event.session; local session_type = session.type:match("^[^_]+"); -- cgit v1.2.3 From cb2eedde50f919165117c8dba312ba820db77f73 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 5 Apr 2019 17:12:19 +0200 Subject: mod_http_files: Use net.http.files --- plugins/mod_http_files.lua | 169 +++++++++------------------------------------ 1 file changed, 33 insertions(+), 136 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua index 1dae0d6d..acb99501 100644 --- a/plugins/mod_http_files.lua +++ b/plugins/mod_http_files.lua @@ -7,14 +7,9 @@ -- module:depends("http"); -local server = require"net.http.server"; -local lfs = require "lfs"; -local os_date = os.date; local open = io.open; -local stat = lfs.attributes; -local build_path = require"socket.url".build_path; -local path_sep = package.config:sub(1,1); +local fileserver = require"net.http.files"; local base_path = module:get_option_path("http_files_dir", module:get_option_path("http_path")); local cache_size = module:get_option_number("http_files_cache_size", 128); @@ -51,148 +46,50 @@ if not mime_map then end end -local forbidden_chars_pattern = "[/%z]"; -if prosody.platform == "windows" then - forbidden_chars_pattern = "[/%z\001-\031\127\"*:<>?|]" -end - -local urldecode = require "util.http".urldecode; -function sanitize_path(path) - if not path then return end - local out = {}; - - local c = 0; - for component in path:gmatch("([^/]+)") do - component = urldecode(component); - if component:find(forbidden_chars_pattern) then - return nil; - elseif component == ".." then - if c <= 0 then - return nil; - end - out[c] = nil; - c = c - 1; - elseif component ~= "." then - c = c + 1; - out[c] = component; - end - end - if path:sub(-1,-1) == "/" then - out[c+1] = ""; - end - return "/"..table.concat(out, "/"); -end - -local cache = require "util.cache".new(cache_size); - +-- COMPAT -- TODO deprecate function serve(opts) if type(opts) ~= "table" then -- assume path string opts = { path = opts }; end - -- luacheck: ignore 431 - local base_path = opts.path; - local dir_indices = opts.index_files or dir_indices; - local directory_index = opts.directory_index; - local function serve_file(event, path) - local request, response = event.request, event.response; - local sanitized_path = sanitize_path(path); - if path and not sanitized_path then - return 400; - end - path = sanitized_path; - local orig_path = sanitize_path(request.path); - local full_path = base_path .. (path or ""):gsub("/", path_sep); - local attr = stat(full_path:match("^.*[^\\/]")); -- Strip trailing path separator because Windows - if not attr then - return 404; - end - - local request_headers, response_headers = request.headers, response.headers; - - local last_modified = os_date('!%a, %d %b %Y %H:%M:%S GMT', attr.modification); - response_headers.last_modified = last_modified; - - local etag = ('"%02x-%x-%x-%x"'):format(attr.dev or 0, attr.ino or 0, attr.size or 0, attr.modification or 0); - response_headers.etag = etag; - - local if_none_match = request_headers.if_none_match - local if_modified_since = request_headers.if_modified_since; - if etag == if_none_match - or (not if_none_match and last_modified == if_modified_since) then - return 304; - end - - local data = cache:get(orig_path); - if data and data.etag == etag then - response_headers.content_type = data.content_type; - data = data.data; - elseif attr.mode == "directory" and path then - if full_path:sub(-1) ~= "/" then - local dir_path = { is_absolute = true, is_directory = true }; - for dir in orig_path:gmatch("[^/]+") do dir_path[#dir_path+1]=dir; end - response_headers.location = build_path(dir_path); - return 301; - end - for i=1,#dir_indices do - if stat(full_path..dir_indices[i], "mode") == "file" then - return serve_file(event, path..dir_indices[i]); - end - end - - if directory_index then - data = server._events.fire_event("directory-index", { path = request.path, full_path = full_path }); - end - if not data then - return 403; - end - cache:set(orig_path, { data = data, content_type = mime_map.html; etag = etag; }); - response_headers.content_type = mime_map.html; - - else - local f, err = open(full_path, "rb"); - if not f then - module:log("debug", "Could not open %s. Error was %s", full_path, err); - return 403; - end - local ext = full_path:match("%.([^./]+)$"); - local content_type = ext and mime_map[ext]; - response_headers.content_type = content_type; - if attr.size > cache_max_file_size then - response_headers.content_length = attr.size; - module:log("debug", "%d > cache_max_file_size", attr.size); - return response:send_file(f); - else - data = f:read("*a"); - f:close(); - end - cache:set(orig_path, { data = data; content_type = content_type; etag = etag }); - end - - return response:send(data); + if opts.directory_index == nil then + opts.directory_index = directory_index; end - - return serve_file; + if opts.mime_map == nil then + opts.mime_map = mime_map; + end + if opts.cache_size == nil then + opts.cache_size = cache_size; + end + if opts.cache_max_file_size == nil then + opts.cache_max_file_size = cache_max_file_size; + end + if opts.index_files == nil then + opts.index_files = dir_indices; + end + -- TODO Crank up to warning + module:log("debug", "Use of mod_http_files.serve() should be updated to use net.http.files"); + return fileserver.serve(opts); end function wrap_route(routes) + module:log("debug", "Use of mod_http_files.wrap_route() should be updated to use net.http.files"); for route,handler in pairs(routes) do if type(handler) ~= "function" then - routes[route] = serve(handler); + routes[route] = fileserver.serve(handler); end end return routes; end -if base_path then - module:provides("http", { - route = { - ["GET /*"] = serve { - path = base_path; - directory_index = directory_index; - } - }; - }); -else - module:log("debug", "http_files_dir not set, assuming use by some other module"); -end - +module:provides("http", { + route = { + ["GET /*"] = fileserver.serve({ + path = base_path; + directory_index = directory_index; + mime_map = mime_map; + cache_size = cache_size; + cache_max_file_size = cache_max_file_size; + index_files = dir_indices; + }); + }; +}); -- cgit v1.2.3 From 92bb509c8afff767492044972a29000e3e4cbfbd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 5 Apr 2019 18:18:23 +0200 Subject: mod_http_files: Try to determine which module using serve() needs updating --- plugins/mod_http_files.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua index acb99501..c357ddfc 100644 --- a/plugins/mod_http_files.lua +++ b/plugins/mod_http_files.lua @@ -46,6 +46,12 @@ if not mime_map then end end +local function get_calling_module() + local info = debug.getinfo(3, "S"); + if not info then return "An unknown module"; end + return info.source:match"mod_[^/\\.]+" or info.short_src; +end + -- COMPAT -- TODO deprecate function serve(opts) if type(opts) ~= "table" then -- assume path string @@ -67,12 +73,12 @@ function serve(opts) opts.index_files = dir_indices; end -- TODO Crank up to warning - module:log("debug", "Use of mod_http_files.serve() should be updated to use net.http.files"); + module:log("debug", "%s should be updated to use 'net.http.files' insead of mod_http_files", get_calling_module()); return fileserver.serve(opts); end function wrap_route(routes) - module:log("debug", "Use of mod_http_files.wrap_route() should be updated to use net.http.files"); + module:log("debug", "%s should be updated to use 'net.http.files' insead of mod_http_files", get_calling_module()); for route,handler in pairs(routes) do if type(handler) ~= "function" then routes[route] = fileserver.serve(handler); -- cgit v1.2.3 From 196ac28ab5b002063f2b25dc60bd809c707b8ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Duarte?= Date: Wed, 17 Apr 2019 10:11:22 -0700 Subject: mod_admin_telnet: Adds c2s:closeall() (Fixes #1315) --- plugins/mod_admin_telnet.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 34cc4dc6..c66630ca 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -250,6 +250,7 @@ function commands.help(session, data) print [[c2s:show_secure() - Show all encrypted client connections]] print [[c2s:show_tls() - Show TLS cipher info for encrypted sessions]] print [[c2s:close(jid) - Close all sessions for the specified JID]] + print [[c2s:closeall() - Close all active c2s connections ]] elseif section == "s2s" then print [[s2s:show(domain) - Show all s2s connections for the given domain (or all if no domain given)]] print [[s2s:show_tls(domain) - Show TLS cipher info for encrypted sessions]] @@ -661,6 +662,16 @@ function def_env.c2s:close(match_jid) return true, "Total: "..count.." sessions closed"; end +function def_env.c2s:closeall() + local count = 0; + --luacheck: ignore 212/jid + show_c2s(function (jid, session) + count = count + 1; + session:close(); + end); + return true, "Total: "..count.." sessions closed"; +end + def_env.s2s = {}; function def_env.s2s:show(match_jid, annotate) -- cgit v1.2.3 From e40cf146149c412e17d789d1b0a0132117494747 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 6 Aug 2012 15:35:27 +0200 Subject: mod_mimicking: Prevents registration of confusable usernames (by Florob) (fixes #1347) --- plugins/mod_mimicking.lua | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 plugins/mod_mimicking.lua (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua new file mode 100644 index 00000000..9004957a --- /dev/null +++ b/plugins/mod_mimicking.lua @@ -0,0 +1,49 @@ +-- Prosody IM +-- Copyright (C) 2012 Florian Zeitz +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +local skeleton = require "util.confusable".skeleton; +local datamanager = require "util.datamanager"; +local usage = require "util.prosodyctl".show_usage; +local warn = require "util.prosodyctl".show_warning; +local users = require "usermanager".users; + +module:hook("user-registered", function(user) + datamanager.store(skeleton(user.username), user.host, "skeletons", {username = user.username}); +end); + +module:hook("user-deregistered", function(user) + datamanager.store(skeleton(user.username), user.host, "skeletons", nil); +end); + +module:hook("registration-attempt", function(user) + if datamanager.load(skeleton(user.username), user.host, "skeletons") then + user.allowed = false; + end +end); + +function module.command(arg) + if (arg[1] ~= "bootstrap" or not arg[2]) then + usage("mod_mimicking bootstrap ", "Initialize skeleton database"); + return; + end + + local host = arg[2]; + + local host_session = prosody.hosts[host]; + if not host_session then + return "No such host"; + end + local provider = host_session.users; + if not(provider) or provider.name == "null" then + usermanager.initialize_host(host); + end + storagemanager.initialize_host(host); + + for user in users(host) do + datamanager.store(skeleton(user), host, "skeletons", {username = user}); + end +end -- cgit v1.2.3 From 5da92eb0973e60d13b3240dee2ec9f09335923d0 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 29 Apr 2019 02:40:39 +0200 Subject: mod_mimicking: Import skeleton() from current location --- plugins/mod_mimicking.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua index 9004957a..da03967f 100644 --- a/plugins/mod_mimicking.lua +++ b/plugins/mod_mimicking.lua @@ -1,11 +1,15 @@ -- Prosody IM -- Copyright (C) 2012 Florian Zeitz +-- Copyright (C) 2019 Kim Alvefur -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -local skeleton = require "util.confusable".skeleton; +local encodings = require "util.encodings"; +assert(encodings.confusable, "This module requires that Prosody be built with ICU"); +local skeleton = encodings.confusable.skeleton; + local datamanager = require "util.datamanager"; local usage = require "util.prosodyctl".show_usage; local warn = require "util.prosodyctl".show_warning; -- cgit v1.2.3 From 0ec982877caed14891aa11b308ae7fb3cb032acd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 29 Apr 2019 02:37:35 +0200 Subject: mod_mimicking: Hook the correct event names --- plugins/mod_mimicking.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua index da03967f..8b8d6ee3 100644 --- a/plugins/mod_mimicking.lua +++ b/plugins/mod_mimicking.lua @@ -19,11 +19,11 @@ module:hook("user-registered", function(user) datamanager.store(skeleton(user.username), user.host, "skeletons", {username = user.username}); end); -module:hook("user-deregistered", function(user) +module:hook("user-deleted", function(user) datamanager.store(skeleton(user.username), user.host, "skeletons", nil); end); -module:hook("registration-attempt", function(user) +module:hook("user-registering", function(user) if datamanager.load(skeleton(user.username), user.host, "skeletons") then user.allowed = false; end -- cgit v1.2.3 From fe0ba7ac7ce6f9696d4b94c07676a279920758f8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 29 Apr 2019 02:38:55 +0200 Subject: mod_mimicking: Use new storage API --- plugins/mod_mimicking.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua index 8b8d6ee3..0da68059 100644 --- a/plugins/mod_mimicking.lua +++ b/plugins/mod_mimicking.lua @@ -10,21 +10,22 @@ local encodings = require "util.encodings"; assert(encodings.confusable, "This module requires that Prosody be built with ICU"); local skeleton = encodings.confusable.skeleton; -local datamanager = require "util.datamanager"; local usage = require "util.prosodyctl".show_usage; local warn = require "util.prosodyctl".show_warning; local users = require "usermanager".users; +local skeletons = module:open_store("skeletons"); + module:hook("user-registered", function(user) - datamanager.store(skeleton(user.username), user.host, "skeletons", {username = user.username}); + skeletons:set(skeleton(user.username), { username = user.username }); end); module:hook("user-deleted", function(user) - datamanager.store(skeleton(user.username), user.host, "skeletons", nil); + skeletons:set(skeleton(user.username), nil); end); module:hook("user-registering", function(user) - if datamanager.load(skeleton(user.username), user.host, "skeletons") then + if skeletons:get(skeleton(user.username)) then user.allowed = false; end end); -- cgit v1.2.3 From 7e8621d4b5918ef20d00ba87f79fb895d3dff448 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 29 Apr 2019 02:40:14 +0200 Subject: mod_mimicking: Update command to work with current code --- plugins/mod_mimicking.lua | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua index 0da68059..a8d6803e 100644 --- a/plugins/mod_mimicking.lua +++ b/plugins/mod_mimicking.lua @@ -11,10 +11,15 @@ assert(encodings.confusable, "This module requires that Prosody be built with IC local skeleton = encodings.confusable.skeleton; local usage = require "util.prosodyctl".show_usage; -local warn = require "util.prosodyctl".show_warning; -local users = require "usermanager".users; +local usermanager = require "core.usermanager"; +local storagemanager = require "core.storagemanager"; -local skeletons = module:open_store("skeletons"); +local skeletons +function module.load() + if module.host ~= "*" then + skeletons = module:open_store("skeletons"); + end +end module:hook("user-registered", function(user) skeletons:set(skeleton(user.username), { username = user.username }); @@ -42,13 +47,13 @@ function module.command(arg) if not host_session then return "No such host"; end - local provider = host_session.users; - if not(provider) or provider.name == "null" then - usermanager.initialize_host(host); - end + storagemanager.initialize_host(host); + usermanager.initialize_host(host); + + skeletons = storagemanager.open(host, "skeletons"); - for user in users(host) do - datamanager.store(skeleton(user), host, "skeletons", {username = user}); + for user in usermanager.users(host) do + skeletons:set(skeleton(user), { username = user }); end end -- cgit v1.2.3 From d9d997c8619b47534f0a18ce67cc9a90621e43b9 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 29 Apr 2019 17:26:56 +0200 Subject: mod_mimicking: Use more intuitive term "mimicry index" for skeletons Fits better with the module name too. --- plugins/mod_mimicking.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua index a8d6803e..43d165d2 100644 --- a/plugins/mod_mimicking.lua +++ b/plugins/mod_mimicking.lua @@ -37,7 +37,7 @@ end); function module.command(arg) if (arg[1] ~= "bootstrap" or not arg[2]) then - usage("mod_mimicking bootstrap ", "Initialize skeleton database"); + usage("mod_mimicking bootstrap ", "Initialize username mimicry index"); return; end -- cgit v1.2.3 From cdea7586e4fc49b4a16b972f69adeeea1dd9136e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 29 Apr 2019 17:27:08 +0200 Subject: mod_mimicking: Improve error handling --- plugins/mod_mimicking.lua | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mimicking.lua b/plugins/mod_mimicking.lua index 43d165d2..b586a70c 100644 --- a/plugins/mod_mimicking.lua +++ b/plugins/mod_mimicking.lua @@ -22,22 +22,34 @@ function module.load() end module:hook("user-registered", function(user) - skeletons:set(skeleton(user.username), { username = user.username }); + local skel = skeleton(user.username); + local ok, err = skeletons:set(skel, { username = user.username }); + if not ok then + module:log("error", "Unable to store mimicry data (%q => %q): %s", user.username, skel, err); + end end); module:hook("user-deleted", function(user) - skeletons:set(skeleton(user.username), nil); + local skel = skeleton(user.username); + local ok, err = skeletons:set(skel, nil); + if not ok and err then + module:log("error", "Unable to clear mimicry data (%q): %s", skel, err); + end end); module:hook("user-registering", function(user) - if skeletons:get(skeleton(user.username)) then + local existing, err = skeletons:get(skeleton(user.username)); + if existing then + module:log("debug", "Attempt to register username '%s' which could be confused with '%s'", user.username, existing.username); user.allowed = false; + elseif err then + module:log("error", "Unable to check if new username '%s' can be confused with any existing user: %s", err); end end); function module.command(arg) if (arg[1] ~= "bootstrap" or not arg[2]) then - usage("mod_mimicking bootstrap ", "Initialize username mimicry index"); + usage("mod_mimicking bootstrap ", "Initialize username mimicry database"); return; end @@ -53,7 +65,21 @@ function module.command(arg) skeletons = storagemanager.open(host, "skeletons"); + local count = 0; for user in usermanager.users(host) do - skeletons:set(skeleton(user), { username = user }); + local skel = skeleton(user); + local existing, err = skeletons:get(skel); + if existing and existing.username ~= user then + module:log("warn", "Existing usernames '%s' and '%s' are confusable", existing.username, user); + elseif err then + module:log("error", "Error checking for existing mimicry data (%q = %q): %s", user, skel, err); + end + local ok, err = skeletons:set(skel, { username = user }); + if ok then + count = count + 1; + elseif err then + module:log("error", "Unable to store mimicry data (%q => %q): %s", user, skel, err); + end end + module:log("info", "%d usernames indexed", count); end -- cgit v1.2.3 From bbc0bd0b8aa6cca380e0e4b81a9ebc6051224b20 Mon Sep 17 00:00:00 2001 From: Arc Riley Date: Thu, 2 May 2019 16:33:14 -0700 Subject: mod_admin_telnet: include BOSH connections in c2s session commands (#998) --- plugins/mod_admin_telnet.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index c66630ca..5ee25771 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -591,6 +591,7 @@ end local function show_c2s(callback) local c2s = array.collect(values(module:shared"/*/c2s/sessions")); + c2s:append(values(module:shared"/*/bosh/sessions")); c2s:sort(function(a, b) if a.host == b.host then if a.username == b.username then -- cgit v1.2.3 From ed8b36a84b47e6ab21347d6cf9c616a69e0b3f7d Mon Sep 17 00:00:00 2001 From: Arc Riley Date: Thu, 2 May 2019 17:28:49 -0700 Subject: mod_admin_telnet: added "(bosh)" and "(websocket)" connection flags (#998) --- plugins/mod_admin_telnet.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 5ee25771..248d6b07 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -554,6 +554,12 @@ local function session_flags(session, line) if session.is_bidi then line[#line+1] = "(bidi)"; end + if session.bosh_version then + line[#line+1] = "(bosh)"; + end + if session.websocket_request then + line[#line+1] = "(websocket)"; + end return table.concat(line, " "); end -- cgit v1.2.3 From a16b70c96df75d562734f84e5dbda7bae2d41eed Mon Sep 17 00:00:00 2001 From: Arc Riley Date: Thu, 2 May 2019 17:44:21 -0700 Subject: mod_admin_telnet: include BOSH connections in c2s:count (#998) --- plugins/mod_admin_telnet.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 248d6b07..0fbd3ff9 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -612,7 +612,9 @@ local function show_c2s(callback) end function def_env.c2s:count() - return true, "Total: ".. iterators.count(values(module:shared"/*/c2s/sessions")) .." clients"; + local c2s_count = iterators.count(values(module:shared"/*/c2s/sessions")) + local bosh_count = iterators.count(values(module:shared"/*/bosh/sessions")) + return true, "Total: ".. c2s_count + bosh_count .." clients"; end function def_env.c2s:show(match_jid, annotate) -- cgit v1.2.3 From 5b40b117152aaf7f5a55e2dab65a5cdf98910726 Mon Sep 17 00:00:00 2001 From: Arc Riley Date: Fri, 3 May 2019 04:10:31 -0700 Subject: mod_bosh: Added metrics for active/inactive sessions, new BOSH sessions, BOSH errors, and timeouts (finishes #998) --- plugins/mod_bosh.lua | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua index 082ed961..d4e980f2 100644 --- a/plugins/mod_bosh.lua +++ b/plugins/mod_bosh.lua @@ -55,6 +55,27 @@ local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; -- All sessions, and sessions that have no requests open local sessions = module:shared("sessions"); +local measure_active = module:measure("active_sessions", "amount"); +local measure_inactive = module:measure("inactive_sessions", "amount"); +local report_bad_host = module:measure("bad_host", "rate"); +local report_bad_sid = module:measure("bad_sid", "rate"); +local report_new_sid = module:measure("new_sid", "rate"); +local report_timeout = module:measure("timeout", "rate"); + +module:hook("stats-update", function () + local active = 0; + local inactive = 0; + for _, session in pairs(sessions) do + if #session.requests > 0 then + active = active + 1; + else + inactive = inactive + 1; + end + end + measure_active(active); + measure_inactive(inactive); +end); + -- Used to respond to idle sessions (those with waiting requests) function on_destroy_request(request) log("debug", "Request destroyed: %s", tostring(request)); @@ -74,7 +95,7 @@ function on_destroy_request(request) if session.inactive_timer then session.inactive_timer:stop(); end - session.inactive_timer = module:add_timer(max_inactive, check_inactive, session, request.context, + session.inactive_timer = module:add_timer(max_inactive, session_timeout, session, request.context, "BOSH client silent for over "..max_inactive.." seconds"); (session.log or log)("debug", "BOSH session marked as inactive (for %ds)", max_inactive); end @@ -85,8 +106,9 @@ function on_destroy_request(request) end end -function check_inactive(now, session, context, reason) -- luacheck: ignore 212/now +function session_timeout(now, session, context, reason) -- luacheck: ignore 212/now if not session.destroyed then + report_timeout(); sessions[context.sid] = nil; sm_destroy_session(session, reason); end @@ -186,6 +208,7 @@ function handle_POST(event) return; end module:log("warn", "Unable to associate request with a session (incomplete request?)"); + report_bad_sid(); local close_reply = st.stanza("body", { xmlns = xmlns_bosh, type = "terminate", ["xmlns:stream"] = xmlns_streams, condition = "item-not-found" }); return tostring(close_reply) .. "\n"; @@ -253,6 +276,7 @@ function stream_callbacks.streamopened(context, attr) local wait = tonumber(attr.wait); if not to_host then log("debug", "BOSH client tried to connect to invalid host: %s", tostring(attr.to)); + report_bad_host(); local close_reply = st.stanza("body", { xmlns = xmlns_bosh, type = "terminate", ["xmlns:stream"] = xmlns_streams, condition = "improper-addressing" }); response:send(tostring(close_reply)); @@ -290,6 +314,7 @@ function stream_callbacks.streamopened(context, attr) session.log("debug", "BOSH session created for request from %s", session.ip); log("info", "New BOSH session, assigned it sid '%s'", sid); + report_new_sid(); module:fire_event("bosh-session", { session = session, request = request }); @@ -344,6 +369,7 @@ function stream_callbacks.streamopened(context, attr) if not session then -- Unknown sid log("info", "Client tried to use sid '%s' which we don't know about", sid); + report_bad_sid(); response:send(tostring(st.stanza("body", { xmlns = xmlns_bosh, type = "terminate", condition = "item-not-found" }))); context.notopen = nil; return; -- cgit v1.2.3 From f65c017ee107f86b353d5931e85a70e8c6067f1f Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 3 May 2019 20:54:24 +0200 Subject: Fix various spelling mistakes [codespell] --- plugins/mod_blocklist.lua | 2 +- plugins/mod_saslauth.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index 8aca7332..2193a093 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -159,7 +159,7 @@ local function edit_blocklist(event) local blocklist = cache[username] or get_blocklist(username); local new_blocklist = { - -- We set the [false] key to someting as a signal not to migrate privacy lists + -- We set the [false] key to something as a signal not to migrate privacy lists [false] = blocklist[false] or { created = now; }; }; if type(blocklist[false]) == "table" then diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua index ba30b9e6..3145cf9b 100644 --- a/plugins/mod_saslauth.lua +++ b/plugins/mod_saslauth.lua @@ -248,7 +248,7 @@ module:hook("stream-features", function(event) local sasl_handler = usermanager_get_sasl_handler(module.host, origin) origin.sasl_handler = sasl_handler; if origin.encrypted then - -- check wether LuaSec has the nifty binding to the function needed for tls-unique + -- check whether LuaSec has the nifty binding to the function needed for tls-unique -- FIXME: would be nice to have this check only once and not for every socket if sasl_handler.add_cb_handler then local socket = origin.conn:socket(); -- cgit v1.2.3 From 637b52a13e2c9e655a2595a4d8e274280e2fd612 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 08:12:16 +0200 Subject: mod_storage_internal,memory: Only return total count if requested --- plugins/mod_storage_internal.lua | 17 +++++++++++------ plugins/mod_storage_memory.lua | 17 ++++++++++++----- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index aa5c3c8a..f921747e 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -124,11 +124,14 @@ function archive:find(username, query) if not items then if err then return items, err; - else - return function () end, 0; + elseif query then + if query.total then + return function () end, 0; + end end + return function () end; end - local count = #items; + local count = nil; local i = 0; if query then items = array(items); @@ -152,11 +155,13 @@ function archive:find(username, query) return item.when <= query["end"]; end); end - count = #items; + if query.total then + count = #items; + end if query.reverse then items:reverse(); if query.before then - for j = 1, count do + for j = 1, #items do if (items[j].key or tostring(j)) == query.before then i = j; break; @@ -164,7 +169,7 @@ function archive:find(username, query) end end elseif query.after then - for j = 1, count do + for j = 1, #items do if (items[j].key or tostring(j)) == query.after then i = j; break; diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index dde2d571..4655cb3a 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -90,9 +90,14 @@ end function archive_store:find(username, query) local items = self.store[username or NULL]; if not items then - return function () end, 0; + if query then + if query.total then + return function () end, 0; + end + end + return function () end; end - local count = #items; + local count = nil; local i = 0; if query then items = array():append(items); @@ -116,11 +121,13 @@ function archive_store:find(username, query) return item.when <= query["end"]; end); end - count = #items; + if query.total then + count = #items; + end if query.reverse then items:reverse(); if query.before then - for j = 1, count do + for j = 1, #items do if (items[j].key or tostring(j)) == query.before then i = j; break; @@ -128,7 +135,7 @@ function archive_store:find(username, query) end end elseif query.after then - for j = 1, count do + for j = 1, #items do if (items[j].key or tostring(j)) == query.after then i = j; break; -- cgit v1.2.3 From e6706dee7ff715d50e8ec03762bbf6f8625cb8a8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 14:52:34 +0200 Subject: mod_muc_mam: Handle archive quotas Same as in mod_mam --- plugins/mod_muc_mam.lua | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 35eabd3b..fffe23e7 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -33,6 +33,9 @@ local m_min = math.min; local timestamp, timestamp_parse, datestamp = import( "util.datetime", "datetime", "parse", "date"); local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50); +local cleanup_after = module:get_option_string("muc_log_expires_after", "1w"); +local cleanup_interval = module:get_option_number("muc_log_cleanup_interval", 4 * 60 * 60); + local default_history_length = 20; local max_history_length = module:get_option_number("max_history_messages", math.huge); @@ -50,6 +53,8 @@ local log_by_default = module:get_option_boolean("muc_log_by_default", true); local archive_store = "muc_log"; local archive = module:open_store(archive_store, "archive"); +local archive_item_limit = module:get_option_number("storage_archive_item_limit", archive.caps and archive.caps.quota or 1000); + if archive.name == "null" or not archive.find then if not archive.find then module:log("error", "Attempt to open archive storage returned a driver without archive API support"); @@ -64,12 +69,15 @@ end local function archiving_enabled(room) if log_all_rooms then + module:log("debug", "Archiving all rooms"); return true; end local enabled = room._data.archiving; if enabled == nil then + module:log("debug", "Default is %s (for %s)", log_by_default, room.jid); return log_by_default; end + module:log("debug", "Logging in room %s is %s", room.jid, enabled); return enabled; end @@ -357,7 +365,29 @@ local function save_to_history(self, stanza) end -- And stash it - local id = archive:append(room_node, nil, stored_stanza, time_now(), with); + local time = time_now(); + local id, err = archive:append(room_node, nil, stored_stanza, time, with); + + if not id and err == "quota-limit" then + if type(cleanup_after) == "number" then + module:log("debug", "Room '%s' over quota, cleaning archive", room_node); + local cleaned = archive:delete(room_node, { + ["end"] = (os.time() - cleanup_after); + }); + if cleaned then + id, err = archive:append(room_node, nil, stored_stanza, time, with); + end + end + if not id and (archive.caps and archive.caps.truncate) then + module:log("debug", "User '%s' over quota, truncating archive", room_node); + local truncated = archive:delete(room_node, { + truncate = archive_item_limit - 1; + }); + if truncated then + id, err = archive:append(room_node, nil, stored_stanza, time, with); + end + end + end if id then schedule_cleanup(room_node); @@ -399,9 +429,6 @@ end); -- Cleanup -local cleanup_after = module:get_option_string("muc_log_expires_after", "1w"); -local cleanup_interval = module:get_option_number("muc_log_cleanup_interval", 4 * 60 * 60); - if cleanup_after ~= "never" then local cleanup_storage = module:open_store("muc_log_cleanup"); local cleanup_map = module:open_store("muc_log_cleanup", "map"); -- cgit v1.2.3 From ef95de88710184351f130090685c5bc7ae7fbcaf Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 16:07:16 +0200 Subject: mod_storage_internal: Add support for iterating over users in archive stores May help with writing a better migrator --- plugins/mod_storage_internal.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index f921747e..96780b33 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -211,6 +211,10 @@ function archive:summary(username, query) return summary; end +function archive:users() + return datamanager.users(host, self.store, "list"); +end + function archive:delete(username, query) local cache_key = jid_join(username, host, self.store); if not query or next(query) == nil then -- cgit v1.2.3 From 40040cdfbca7a934bb5e1256a9fdd403350eeaae Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 16:26:01 +0200 Subject: mod_storage_sql: Add support for iterating over users in archive stores --- plugins/mod_storage_sql.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index ffe48ab8..596687ae 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -509,6 +509,19 @@ function archive_store:delete(username, query) return ok and stmt:affected(), stmt; end +function archive_store:users() + local ok, result = engine:transaction(function() + local select_sql = [[ + SELECT DISTINCT "user" + FROM "prosodyarchive" + WHERE "host"=? AND "store"=?; + ]]; + return engine:select(select_sql, host, self.store); + end); + if not ok then error(result); end + return iterator(result); +end + local stores = { keyval = keyval_store; map = map_store; -- cgit v1.2.3 From b772308c93a1c78995a073964ebf963f759ef81c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 5 Mar 2019 00:12:30 +0100 Subject: mod_storage_internal: Return error if 'before' or 'after' are not found (partial fix for #1325) --- plugins/mod_storage_internal.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index 96780b33..fdce3c98 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -161,20 +161,30 @@ function archive:find(username, query) if query.reverse then items:reverse(); if query.before then + local found = false; for j = 1, #items do if (items[j].key or tostring(j)) == query.before then + found = true; i = j; break; end end + if not found then + return nil, "item-not-found"; + end end elseif query.after then + local found = false; for j = 1, #items do if (items[j].key or tostring(j)) == query.after then + found = true; i = j; break; end end + if not found then + return nil, "item-not-found"; + end end if query.limit and #items - i > query.limit then items[i+query.limit+1] = nil; -- cgit v1.2.3 From f456f0c03e519a3e53caaf233f7c9f1a54e2ade8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 5 Mar 2019 00:16:41 +0100 Subject: mod_storage_memory: Return error if 'before' or 'after' are not found (partial fix for #1325) --- plugins/mod_storage_memory.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index 4655cb3a..2fae8828 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -127,20 +127,30 @@ function archive_store:find(username, query) if query.reverse then items:reverse(); if query.before then + local found = false; for j = 1, #items do if (items[j].key or tostring(j)) == query.before then + found = true; i = j; break; end end + if not found then + return nil, "item-not-found"; + end end elseif query.after then + local found = false; for j = 1, #items do if (items[j].key or tostring(j)) == query.after then + found = true; i = j; break; end end + if not found then + return nil, "item-not-found"; + end end if query.limit and #items - i > query.limit then items[i+query.limit+1] = nil; -- cgit v1.2.3 From a770a8430662ca624d81bdf4e23e8da5356c82ac Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 Mar 2019 00:51:10 +0100 Subject: mod_storage_sql: Look up archive IDs in separate queries (fixes #1325) This is probably not good for performance. --- plugins/mod_storage_sql.lua | 58 ++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index f0a8fee0..5da5e448 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -327,38 +327,36 @@ local function archive_where(query, args, where) end end local function archive_where_id_range(query, args, where) - local args_len = #args -- Before or after specific item, exclusive + local id_lookup_sql = [[ + SELECT "sort_id" + FROM "prosodyarchive" + WHERE "key" = ? AND "host" = ? AND "user" = ? AND "store" = ? + LIMIT 1; + ]]; if query.after then -- keys better be unique! - where[#where+1] = [[ - "sort_id" > COALESCE( - ( - SELECT "sort_id" - FROM "prosodyarchive" - WHERE "key" = ? AND "host" = ? AND "user" = ? AND "store" = ? - LIMIT 1 - ), 0) - ]]; - args[args_len+1], args[args_len+2], args[args_len+3], args[args_len+4] = query.after, args[1], args[2], args[3]; - args_len = args_len + 4 + local after_id = nil; + for row in engine:select(id_lookup_sql, query.after, host, user or "", store) do + after_id = row[1]; + end + if not after_id then + return nil, "item-not-found"; + end + where[#where+1] = '"sort_id" > ?'; + args[#args+1] = after_id; end if query.before then - where[#where+1] = [[ - "sort_id" < COALESCE( - ( - SELECT "sort_id" - FROM "prosodyarchive" - WHERE "key" = ? AND "host" = ? AND "user" = ? AND "store" = ? - LIMIT 1 - ), - ( - SELECT MAX("sort_id")+1 - FROM "prosodyarchive" - ) - ) - ]] - args[args_len+1], args[args_len+2], args[args_len+3], args[args_len+4] = query.before, args[1], args[2], args[3]; + local before_id = nil; + for row in engine:select(id_lookup_sql, query.after, host, user or "", store) do + before_id = row[1]; + end + if not before_id then + return nil, "item-not-found"; + end + where[#where+1] = '"sort_id" < ?'; + args[#args+1] = before_id; end + return true; end function archive_store:find(username, query) @@ -398,7 +396,8 @@ function archive_store:find(username, query) end end - archive_where_id_range(query, args, where); + local ok, err = archive_where_id_range(query, args, where); + if not ok then return ok, err; end if query.limit then args[#args+1] = query.limit; @@ -466,7 +465,8 @@ function archive_store:delete(username, query) table.remove(where, 2); end archive_where(query, args, where); - archive_where_id_range(query, args, where); + local ok, err = archive_where_id_range(query, args, where); + if not ok then return ok, err; end if query.truncate == nil then sql_query = sql_query:format(t_concat(where, " AND ")); else -- cgit v1.2.3 From fcda870911ff3a9ae66a3051c0e1a281f7b99772 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 07:16:05 +0200 Subject: mod_mam: Propagate item-not-found to client (fixes #1325) --- plugins/mod_mam/mod_mam.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 632de9ea..317ddac1 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -142,7 +142,11 @@ module:hook("iq-set/self/"..xmlns_mam..":query", function(event) }); if not data then - origin.send(st.error_reply(stanza, "cancel", "internal-server-error", err)); + if err == "item-not-found" then + origin.send(st.error_reply(stanza, "modify", "item-not-found")); + else + origin.send(st.error_reply(stanza, "cancel", "internal-server-error")); + end return true; end local total = tonumber(err); -- cgit v1.2.3 From d88db76a0669d3613fc6ce1123943e9bd8927395 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 07:16:03 +0200 Subject: mod_muc_mam: Propagate item-not-found to client (fixes #1325) --- plugins/mod_muc_mam.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index fffe23e7..bba7f422 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -189,7 +189,11 @@ module:hook("iq-set/bare/"..xmlns_mam..":query", function(event) }); if not data then - origin.send(st.error_reply(stanza, "cancel", "internal-server-error")); + if err == "item-not-found" then + origin.send(st.error_reply(stanza, "modify", "item-not-found")); + else + origin.send(st.error_reply(stanza, "cancel", "internal-server-error")); + end return true; end local total = tonumber(err); -- cgit v1.2.3 From 63333b90631e5b3d7c955ec3c0c2e9eae204faf7 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 07:22:18 +0200 Subject: mod_storage_memory: Return correct error even if no archive data available --- plugins/mod_storage_memory.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_memory.lua b/plugins/mod_storage_memory.lua index 2fae8828..376ae277 100644 --- a/plugins/mod_storage_memory.lua +++ b/plugins/mod_storage_memory.lua @@ -91,6 +91,9 @@ function archive_store:find(username, query) local items = self.store[username or NULL]; if not items then if query then + if query.before or query.after then + return nil, "item-not-found"; + end if query.total then return function () end, 0; end -- cgit v1.2.3 From 99f6c695075dc4a93deb5aea4e8acaf635d48fdb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 5 May 2019 07:24:12 +0200 Subject: mod_storage_internal: Return appropriate error even with empty archive --- plugins/mod_storage_internal.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index fdce3c98..2556224d 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -125,6 +125,9 @@ function archive:find(username, query) if err then return items, err; elseif query then + if query.before or query.after then + return nil, "item-not-found"; + end if query.total then return function () end, 0; end -- cgit v1.2.3 From 6fcaa64f6139a5093a328b2458ea4ac74a153d51 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 26 May 2019 15:04:16 +0200 Subject: mod_csi_simple: Disable optimizations on disconnect (fixes #1358) The connection becomes invalid here, regardless of 3rd party modules that might keep the session alive. --- plugins/mod_csi_simple.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index a9148618..13002ea8 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -108,6 +108,10 @@ module:hook("csi-client-active", function (event) disable_optimizations(session); end); +module:hook("pre-resource-unbind", function (event) + local session = event.session; + disable_optimizations(session); +end); module:hook("c2s-ondrain", function (event) local session = event.session; -- cgit v1.2.3 From 5a2a81bfe97c366e6da39442534b4e58ba64ae71 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 28 May 2019 00:46:24 +0200 Subject: mod_storage_sql: Correctly return item-not-found error `return ok, err` comes out as `transaction_ok, ok, err` --- plugins/mod_storage_sql.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 5da5e448..cfc8450c 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -367,7 +367,7 @@ function archive_store:find(username, query) if total ~= nil and query.limit == 0 and query.start == nil and query.with == nil and query["end"] == nil and query.key == nil then return noop, total; end - local ok, result = engine:transaction(function() + local ok, result, err = engine:transaction(function() local sql_query = [[ SELECT "key", "type", "value", "when", "with" FROM "prosodyarchive" @@ -407,7 +407,8 @@ function archive_store:find(username, query) and "DESC" or "ASC", query.limit and " LIMIT ?" or ""); return engine:select(sql_query, unpack(args)); end); - if not ok then return ok, result end + if not ok then return ok, result; end + if not result then return nil, err; end return function() local row = result(); if row ~= nil then -- cgit v1.2.3 From 7b63f8d95dcc99df5508a05c60fe472dfc2a4282 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 28 May 2019 00:47:50 +0200 Subject: mod_storage_sql: Fix to use correct arguments to archive id lookup --- plugins/mod_storage_sql.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index cfc8450c..ad2de840 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -336,7 +336,7 @@ local function archive_where_id_range(query, args, where) ]]; if query.after then -- keys better be unique! local after_id = nil; - for row in engine:select(id_lookup_sql, query.after, host, user or "", store) do + for row in engine:select(id_lookup_sql, query.after, args[1], args[2], args[3]) do after_id = row[1]; end if not after_id then @@ -347,7 +347,7 @@ local function archive_where_id_range(query, args, where) end if query.before then local before_id = nil; - for row in engine:select(id_lookup_sql, query.after, host, user or "", store) do + for row in engine:select(id_lookup_sql, query.after, args[1], args[2], args[3]) do before_id = row[1]; end if not before_id then -- cgit v1.2.3 From 2a65eae651302a17c925e0340e59e73976aa07fb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 28 May 2019 00:56:30 +0200 Subject: mod_storage_sql: Ignore shadowed error variable [luacheck] --- plugins/mod_storage_sql.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index ad2de840..518e2654 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -153,7 +153,7 @@ end local archive_item_limit = module:get_option_number("storage_archive_item_limit"); local archive_item_count_cache = cache.new(module:get_option("storage_archive_item_limit_cache_size", 1000)); --- luacheck: ignore 512 431/user 431/store +-- luacheck: ignore 512 431/user 431/store 431/err local map_store = {}; map_store.__index = map_store; map_store.remove = {}; -- cgit v1.2.3 From 2bb05d010d9b237a088bd9b4c997451407191d3f Mon Sep 17 00:00:00 2001 From: Michel Le Bihan Date: Mon, 3 Jun 2019 20:51:15 +0200 Subject: mod_admin_telnet: Collect array from Bosh connections when appending to connection list Fixes #1356 --- plugins/mod_admin_telnet.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 0fbd3ff9..fa03840b 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -597,7 +597,7 @@ end local function show_c2s(callback) local c2s = array.collect(values(module:shared"/*/c2s/sessions")); - c2s:append(values(module:shared"/*/bosh/sessions")); + c2s:append(array.collect(values(module:shared"/*/bosh/sessions"))); c2s:sort(function(a, b) if a.host == b.host then if a.username == b.username then -- cgit v1.2.3