Hello community, here is the log from the commit of package prosody for openSUSE:Factory checked in at 2018-05-16 18:42:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/prosody (Old) and /work/SRC/openSUSE:Factory/.prosody.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "prosody" Wed May 16 18:42:55 2018 rev:10 rq:609037 version:0.10.1 Changes: -------- --- /work/SRC/openSUSE:Factory/prosody/prosody.changes 2017-12-19 10:57:03.097509257 +0100 +++ /work/SRC/openSUSE:Factory/.prosody.new/prosody.changes 2018-05-16 18:44:45.720423871 +0200 @@ -1,0 +2,32 @@ +Wed May 16 08:05:46 UTC 2018 - mvet...@suse.com + +- Update to 0.10.1: + Security: + * SQL: Ensure user archives are purged when a user account is deleted (fixes #1009[1]) + Fixes and improvements: + * Core: More robust signal handling (fixes #1047[2], #1029[3]) + * MUC: Ensure that elements which match our from are stripped (fixes #1055[4]) + * MUC: More robust handling of storage failures (fixes #1091[5], #1091[5]) + * mod_mam: Ensure a user's archiving preferences apply even when they are offline (fixes #1024[6]) + * Compatibility improvements with LuaSec 0.7, improving curve support + * mod_stanza_debug: New module that logs full stanzas sent and received for debugging purposes + * mod_mam: Implement option to enable MAM implicitly when client support is detected (#867[7]) + * mod_mam: Add an option for whether to include 'total' counts by default in queries (for performance) + * MUC: send muc#stanza_id feature as per XEP-0045 v1.31 (fixes #1097[8]) + Minor changes: + * SQL: Suppress error log if a transaction failed but was retried ok + * core.stanza_router: Verify that xmlns exists for firing stanza/iq/xmlns/name events (fixes #1022[9]) (thanks SamWhited) + * mod_carbons: Synthesize a 'to' attribute for carbons of stanzas to "self" (fixes #956[10]) + * Core: Re-enable timestamps by default when logging to files (fixes #1004[11]) + * HTTP: Report HTML Content-Type on error pages (fixes #1030[12]) + * mod_c2s: Set a default value for c2s_timeout (fixes #1036[13]) + * prosodyctl: Fix traceback with lfs < 1.6.2 and show warning + * Fix incorrect '::' compression of a single 0-group which broke some IPv6 address matching + * mod_dialback: Copy function from mod_s2s instead of depending on it, which made it harder to disable s2s (fixes #1050[14]) + * mod_storage_sql: Add an index to SQL archive stores to improve performance of some queries + * MUC: Don't attempt to reply to errors with more errors (fixes #1122[15]) + * Module API: Fix parameter order to http client callbacks + * mod_blocklist: Allow mod_presence to handle subscription stanzas before bouncing outgoing presence (fixes #575[16]) + * mod_http_files: Fix directory listing cache entries not expiring (fixes #1130[17]) + +------------------------------------------------------------------- Old: ---- prosody-0.10.0.tar.gz prosody-0.10.0.tar.gz.asc New: ---- prosody-0.10.1.tar.gz prosody-0.10.1.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ prosody.spec ++++++ --- /var/tmp/diff_new_pack.y49hm0/_old 2018-05-16 18:44:46.424398431 +0200 +++ /var/tmp/diff_new_pack.y49hm0/_new 2018-05-16 18:44:46.424398431 +0200 @@ -1,7 +1,7 @@ # # spec file for package prosody # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define _piddir /run Name: prosody -Version: 0.10.0 +Version: 0.10.1 Release: 0 Summary: Communications server for Jabber/XMPP License: MIT ++++++ prosody-0.10.0.tar.gz -> prosody-0.10.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/.hg_archival.txt new/prosody-0.10.1/.hg_archival.txt --- old/prosody-0.10.0/.hg_archival.txt 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/.hg_archival.txt 2018-05-11 16:16:15.000000000 +0200 @@ -1,6 +1,6 @@ repo: 3e3171b59028ee70122cfec6ecf98f518f946b59 -node: 39966cbc29f46d7ae9660edca8683d5121c82edf +node: 4ae8dd415e9431924ad4aa0b57bcee8a4a9272f8 branch: default -latesttag: 0.9.12 -latesttagdistance: 365 -changessincelatesttag: 1716 +latesttag: 0.10.0 +latesttagdistance: 72 +changessincelatesttag: 79 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/CHANGES new/prosody-0.10.1/CHANGES --- old/prosody-0.10.0/CHANGES 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/CHANGES 2018-05-11 16:16:15.000000000 +0200 @@ -1,7 +1,7 @@ 0.10.0 -===================== +====== -**2017-09-28** +**2017-10-02** New features ------------ @@ -23,4 +23,3 @@ - mod\_privacy (XEP-0016) - mod\_compression (XEP-0138) - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/core/certmanager.lua new/prosody-0.10.1/core/certmanager.lua --- old/prosody-0.10.0/core/certmanager.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/core/certmanager.lua 2018-05-11 16:16:15.000000000 +0200 @@ -27,6 +27,7 @@ local tonumber, tostring = tonumber, tostring; local pairs = pairs; +local t_remove = table.remove; local type = type; local io_open = io.open; local select = select; @@ -37,13 +38,20 @@ local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)"); local luasec_version = tonumber(luasec_major) * 100 + tonumber(luasec_minor); -local luasec_has = { - -- TODO If LuaSec ever starts exposing these things itself, use that instead - cipher_server_preference = luasec_version >= 2; - no_ticket = luasec_version >= 4; - no_compression = luasec_version >= 5; - single_dh_use = luasec_version >= 2; - single_ecdh_use = luasec_version >= 2; +local luasec_has = softreq"ssl.config" or { + algorithms = { + ec = luasec_version >= 5; + }; + capabilities = { + curves_list = luasec_version >= 7; + }; + options = { + cipher_server_preference = luasec_version >= 2; + no_ticket = luasec_version >= 4; + no_compression = luasec_version >= 5; + single_dh_use = luasec_version >= 2; + single_ecdh_use = luasec_version >= 2; + }; }; local _ENV = nil; @@ -99,14 +107,14 @@ protocol = "tlsv1+"; verify = (ssl_x509 and { "peer", "client_once", }) or "none"; options = { - cipher_server_preference = luasec_has.cipher_server_preference; - no_ticket = luasec_has.no_ticket; - no_compression = luasec_has.no_compression and configmanager.get("*", "ssl_compression") ~= true; - single_dh_use = luasec_has.single_dh_use; - single_ecdh_use = luasec_has.single_ecdh_use; + cipher_server_preference = luasec_has.options.cipher_server_preference; + no_ticket = luasec_has.options.no_ticket; + no_compression = luasec_has.options.no_compression and configmanager.get("*", "ssl_compression") ~= true; + single_dh_use = luasec_has.options.single_dh_use; + single_ecdh_use = luasec_has.options.single_ecdh_use; }; verifyext = { "lsec_continue", "lsec_ignore_purpose" }; - curve = "secp384r1"; + curve = luasec_has.algorithms.ec and not luasec_has.capabilities.curves_list and "secp384r1"; curveslist = { "X25519", "P-384", @@ -124,6 +132,17 @@ "!aNULL", -- Ciphers that does not authenticate the connection }; } + +if luasec_has.curves then + for i = #core_defaults.curveslist, 1, -1 do + if not luasec_has.curves[ core_defaults.curveslist[i] ] then + t_remove(core_defaults.curveslist, i); + end + end +else + core_defaults.curveslist = nil; +end + local path_options = { -- These we pass through resolve_path() key = true, certificate = true, cafile = true, capath = true, dhparam = true } @@ -157,8 +176,8 @@ local user_ssl_config = cfg:final(); if mode == "server" then - if not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end if not user_ssl_config.certificate then return nil, "No certificate present in SSL/TLS configuration for "..host; end + if not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end end for option in pairs(path_options) do @@ -227,7 +246,7 @@ local function reload_ssl_config() global_ssl_config = configmanager.get("*", "ssl"); global_certificates = configmanager.get("*", "certificates") or "certs"; - if luasec_has.no_compression then + if luasec_has.options.no_compression then core_defaults.options.no_compression = configmanager.get("*", "ssl_compression") ~= true; end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/core/hostmanager.lua new/prosody-0.10.1/core/hostmanager.lua --- old/prosody-0.10.0/core/hostmanager.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/core/hostmanager.lua 2018-05-11 16:16:15.000000000 +0200 @@ -92,6 +92,9 @@ send = host_send; modules = {}; }; + function host_session:close(reason) + log("debug", "Attempt to close host session %s with reason: %s", self.host, reason); + end setmetatable(host_session, host_mt); if not host_config.component_module then -- host host_session.type = "local"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/core/loggingmanager.lua new/prosody-0.10.1/core/loggingmanager.lua --- old/prosody-0.10.0/core/loggingmanager.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/core/loggingmanager.lua 2018-05-11 16:16:15.000000000 +0200 @@ -178,7 +178,7 @@ local timestamps = sink_config.timestamps; - if timestamps == true then + if timestamps == true or timestamps == nil then timestamps = default_timestamp; -- Default format elseif timestamps then timestamps = timestamps .. " "; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/core/rostermanager.lua new/prosody-0.10.1/core/rostermanager.lua --- old/prosody-0.10.0/core/rostermanager.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/core/rostermanager.lua 2018-05-11 16:16:15.000000000 +0200 @@ -104,18 +104,29 @@ if user then roster = user.roster; if roster then return roster; end - log("debug", "load_roster: loading for new user: %s@%s", username, host); + log("debug", "load_roster: loading for new user: %s", jid); else -- Attempt to load roster for non-loaded user - log("debug", "load_roster: loading for offline user: %s@%s", username, host); + log("debug", "load_roster: loading for offline user: %s", jid); end local roster_store = storagemanager.open(host, "roster", "keyval"); local data, err = roster_store:get(username); roster = data or {}; if user then user.roster = roster; end + local legacy_pending = roster.pending and type(roster.pending.subscription) ~= "string"; roster_metadata(roster, err); + if legacy_pending then + -- Due to map store use, we need to manually delete this entry + log("debug", "Removing legacy 'pending' entry"); + if not save_roster(username, host, roster, "pending") then + log("warn", "Could not remove legacy 'pendig' entry"); + end + end if roster[jid] then roster[jid] = nil; - log("warn", "roster for %s has a self-contact", jid); + log("debug", "Roster for %s had a self-contact, removing", jid); + if not save_roster(username, host, roster, jid) then + log("warn", "Could not remove self-contact from roster for %s", jid); + end end if not err then hosts[host].events.fire_event("roster-load", { username = username, host = host, roster = roster }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/core/stanza_router.lua new/prosody-0.10.1/core/stanza_router.lua --- old/prosody-0.10.0/core/stanza_router.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/core/stanza_router.lua 2018-05-11 16:16:15.000000000 +0200 @@ -140,7 +140,8 @@ if h then local event; if xmlns == nil then - if stanza.name == "iq" and (stanza.attr.type == "set" or stanza.attr.type == "get") then + if stanza.name == "iq" and (stanza.attr.type == "set" or stanza.attr.type == "get") + and stanza.tags[1] and stanza.tags[1].attr.xmlns then event = "stanza/iq/"..stanza.tags[1].attr.xmlns..":"..stanza.tags[1].name; else event = "stanza/"..stanza.name; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/man/prosodyctl.man new/prosody-0.10.1/man/prosodyctl.man --- old/prosody-0.10.0/man/prosodyctl.man 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/man/prosodyctl.man 2018-05-11 16:16:15.000000000 +0200 @@ -93,33 +93,33 @@ Commands are of the form \f[C]prosodyctl\ cert\ subcommand\f[]. Commands take a list of hosts to be included in the certificate. .TP -.B request hosts +.B \f[C]request\ hosts\f[] Create a certificate request (CSR) file for submission to a certificate authority. Multiple hosts can be given, sub\-domains are automatically included. .RS .RE .TP -.B generate hosts +.B \f[C]generate\ hosts\f[] Generate a self\-signed certificate. .RS .RE .TP -.B key host [size] +.B \f[C]key\ host\ [size]\f[] Generate a private key of \[aq]size\[aq] bits (defaults to 2048). Invoked automatically by \[aq]request\[aq] and \[aq]generate\[aq] if needed. .RS .RE .TP -.B config hosts +.B \f[C]config\ hosts\f[] Produce a config file for the list of hosts. Invoked automatically by \[aq]request\[aq] and \[aq]generate\[aq] if needed. .RS .RE .TP -.B import hosts paths +.B \f[C]import\ hosts\ paths\f[] Copy certificates for hosts into the certificate path and reload prosody. .RS @@ -129,13 +129,13 @@ prosodyctl can also show some information about the environment, dependencies and such to aid in debugging. .TP -.B about +.B \f[C]about\f[] Shows environment, various paths used by Prosody and installed dependencies. .RS .RE .TP -.B check [what] +.B \f[C]check\ [what]\f[] Performs various sanity checks on the configuration, DNS setup and configured TLS certificates. \f[C]what\f[] can be one of \f[C]config\f[], \f[C]dns\f[] and diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/man/prosodyctl.markdown new/prosody-0.10.1/man/prosodyctl.markdown --- old/prosody-0.10.0/man/prosodyctl.markdown 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/man/prosodyctl.markdown 2018-05-11 16:16:15.000000000 +0200 @@ -88,23 +88,23 @@ `prosodyctl cert subcommand`. Commands take a list of hosts to be included in the certificate. -request hosts +`request hosts` : Create a certificate request (CSR) file for submission to a certificate authority. Multiple hosts can be given, sub-domains are automatically included. -generate hosts +`generate hosts` : Generate a self-signed certificate. -key host \[size\] +`key host [size]` : Generate a private key of 'size' bits (defaults to 2048). Invoked automatically by 'request' and 'generate' if needed. -config hosts +`config hosts` : Produce a config file for the list of hosts. Invoked automatically by 'request' and 'generate' if needed. -import hosts paths +`import hosts paths` : Copy certificates for hosts into the certificate path and reload prosody. @@ -114,11 +114,11 @@ prosodyctl can also show some information about the environment, dependencies and such to aid in debugging. -about +`about` : Shows environment, various paths used by Prosody and installed dependencies. -check \[what\] +`check [what]` : Performs various sanity checks on the configuration, DNS setup and configured TLS certificates. `what` can be one of `config`, `dns` and `certs` to run only that check. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/net/dns.lua new/prosody-0.10.1/net/dns.lua --- old/prosody-0.10.0/net/dns.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/net/dns.lua 2018-05-11 16:16:15.000000000 +0200 @@ -390,7 +390,7 @@ end addr = table.concat(addr, ":"):gsub("%f[%x]0+(%x)","%1"); local zeros = {}; - for item in addr:gmatch(":[0:]+:") do + for item in addr:gmatch(":[0:]+:[0:]+:") do table.insert(zeros, item) end if #zeros == 0 then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/net/http/server.lua new/prosody-0.10.1/net/http/server.lua --- old/prosody-0.10.0/net/http/server.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/net/http/server.lua 2018-05-11 16:16:15.000000000 +0200 @@ -229,7 +229,7 @@ if err then response.status_code = err_code; - response:send(events.fire_event("http-error", { code = err_code, message = err })); + response:send(events.fire_event("http-error", { code = err_code, message = err, response = response })); return; end @@ -244,7 +244,8 @@ if result_type == "number" then response.status_code = result; if result >= 400 then - body = events.fire_event("http-error", { code = result }); + payload.code = result; + body = events.fire_event("http-error", payload); end elseif result_type == "string" then body = result; @@ -266,7 +267,8 @@ -- if handler not called, return 404 response.status_code = 404; - response:send(events.fire_event("http-error", { code = 404 })); + payload.code = 404; + response:send(events.fire_event("http-error", payload)); end local function prepare_header(response) local status_line = "HTTP/"..response.request.httpversion.." "..(response.status or codes[response.status_code]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/net/http.lua new/prosody-0.10.1/net/http.lua --- old/prosody-0.10.0/net/http.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/net/http.lua 2018-05-11 16:16:15.000000000 +0200 @@ -22,6 +22,7 @@ local tonumber, tostring, xpcall, traceback = tonumber, tostring, xpcall, debug.traceback; local error = error +local setmetatable = setmetatable; local log = require "util.logger".init("http"); @@ -238,7 +239,7 @@ end log("debug", "Request '%s': Calling callback, status %s", req.id, code or "---"); - return log_if_failed(req.id, xpcall(function () return callback(content, code, request, response) end, handleerr)); + return log_if_failed(req.id, xpcall(function () return callback(content, code, response, request) end, handleerr)); end req.reader = request_reader; req.state = "status"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_admin_telnet.lua new/prosody-0.10.1/plugins/mod_admin_telnet.lua --- old/prosody-0.10.0/plugins/mod_admin_telnet.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_admin_telnet.lua 2018-05-11 16:16:15.000000000 +0200 @@ -1114,7 +1114,7 @@ local http_host = module:context(host):get_option_string("http_host"); print("HTTP endpoints on "..host..(http_host and (" (using "..http_host.."):") or ":")); for _, provider in ipairs(http_apps) do - local url = module:context(host):http_url(provider.name); + local url = module:context(host):http_url(provider.name, provider.default_path); print("", url); end print(""); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_blocklist.lua new/prosody-0.10.1/plugins/mod_blocklist.lua --- old/prosody-0.10.0/plugins/mod_blocklist.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_blocklist.lua 2018-05-11 16:16:15.000000000 +0200 @@ -321,12 +321,9 @@ module:hook("pre-message/full", bounce_outgoing, prio_out); module:hook("pre-message/host", bounce_outgoing, prio_out); --- FIXME See #575 -- We MUST bounce these, but we don't because this --- would produce lots of error replies due to server-generated presence. --- This will likely need changes to mod_presence -module:hook("pre-presence/bare", drop_outgoing, prio_out); -module:hook("pre-presence/full", drop_outgoing, prio_out); -module:hook("pre-presence/host", drop_outgoing, prio_out); +module:hook("pre-presence/bare", bounce_outgoing, -1); +module:hook("pre-presence/host", bounce_outgoing, -1); +module:hook("pre-presence/full", bounce_outgoing, prio_out); module:hook("pre-iq/bare", bounce_outgoing, prio_out); module:hook("pre-iq/full", bounce_outgoing, prio_out); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_c2s.lua new/prosody-0.10.1/plugins/mod_c2s.lua --- old/prosody-0.10.0/plugins/mod_c2s.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_c2s.lua 2018-05-11 16:16:15.000000000 +0200 @@ -23,7 +23,7 @@ local log = module._log; -local c2s_timeout = module:get_option_number("c2s_timeout"); +local c2s_timeout = module:get_option_number("c2s_timeout", 300); local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); local opt_keepalives = module:get_option_boolean("c2s_tcp_keepalives", module:get_option_boolean("tcp_keepalives", true)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_carbons.lua new/prosody-0.10.1/plugins/mod_carbons.lua --- old/prosody-0.10.0/plugins/mod_carbons.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_carbons.lua 2018-05-11 16:16:15.000000000 +0200 @@ -76,6 +76,9 @@ -- Create the carbon copy and wrap it as per the Stanza Forwarding XEP local copy = st.clone(stanza); + if c2s and not orig_to then + stanza.attr.to = bare_from; + end copy.attr.xmlns = "jabber:client"; local carbon = st.message{ from = bare_jid, type = orig_type, } :tag(c2s and "sent" or "received", { xmlns = xmlns_carbons }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_component.lua new/prosody-0.10.1/plugins/mod_component.lua --- old/prosody-0.10.0/plugins/mod_component.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_component.lua 2018-05-11 16:16:15.000000000 +0200 @@ -120,7 +120,8 @@ local name = module:get_option_string("name"); if name then event.origin.send(st.reply(stanza):tag("query", { xmlns = "http://jabber.org/protocol/disco#info" }) - :tag("identity", { category = "component", type = "generic", name = module:get_option_string("name", "Prosody") })) + :tag("identity", { category = "component", type = "generic", name = module:get_option_string("name", "Prosody") })):up() + :tag("feature", { var = "http://jabber.org/protocol/disco#info" }):up() return true; end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_debug_sql.lua new/prosody-0.10.1/plugins/mod_debug_sql.lua --- old/prosody-0.10.0/plugins/mod_debug_sql.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_debug_sql.lua 2018-05-11 16:16:15.000000000 +0200 @@ -2,6 +2,8 @@ -- -- luacheck: ignore 213/uri +module:set_global(); + local engines = module:shared("/*/sql/connections"); for uri, engine in pairs(engines) do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_dialback.lua new/prosody-0.10.1/plugins/mod_dialback.lua --- old/prosody-0.10.0/plugins/mod_dialback.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_dialback.lua 2018-05-11 16:16:15.000000000 +0200 @@ -14,7 +14,6 @@ local sha256_hash = require "util.hashes".sha256; local sha256_hmac = require "util.hashes".hmac_sha256; local nameprep = require "util.encodings".stringprep.nameprep; -local check_cert_status = module:depends"s2s".check_cert_status; local uuid_gen = require"util.uuid".generate; local xmlns_stream = "http://etherx.jabber.org/streams"; @@ -24,6 +23,19 @@ local dialback_secret = sha256_hash(module:get_option_string("dialback_secret", uuid_gen()), true); local dwd = module:get_option_boolean("dialback_without_dialback", false); +--- Helper to check that a session peer's certificate is valid +function check_cert_status(session) + local host = session.direction == "outgoing" and session.to_host or session.from_host + local conn = session.conn:socket() + local cert + if conn.getpeercertificate then + cert = conn:getpeercertificate() + end + + return module:fire_event("s2s-check-certificate", { host = host, session = session, cert = cert }); +end + + function module.save() return { dialback_secret = dialback_secret }; end @@ -141,7 +153,8 @@ valid = "invalid"; end if dialback_verifying.destroyed then - log("warn", "Incoming s2s session %s was closed in the meantime, so we can't notify it of the db result", tostring(dialback_verifying):match("%w+$")); + log("warn", "Incoming s2s session %s was closed in the meantime, so we can't notify it of the dialback result", + tostring(dialback_verifying):match("%w+$")); else dialback_verifying.sends2s( st.stanza("db:result", { from = attr.to, to = attr.from, id = attr.id, type = valid }) @@ -177,7 +190,15 @@ end end); -module:hook_stanza(xmlns_stream, "features", function (origin, stanza) +module:hook_tag("urn:ietf:params:xml:ns:xmpp-sasl", "failure", function (origin, stanza) -- luacheck: ignore 212/stanza + if origin.external_auth == "failed" then + module:log("debug", "SASL EXTERNAL failed, falling back to dialback"); + initiate_dialback(origin); + return true; + end +end, 100); + +module:hook_tag(xmlns_stream, "features", function (origin, stanza) -- luacheck: ignore 212/stanza if not origin.external_auth or origin.external_auth == "failed" then module:log("debug", "Initiating dialback..."); initiate_dialback(origin); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_http_errors.lua new/prosody-0.10.1/plugins/mod_http_errors.lua --- old/prosody-0.10.0/plugins/mod_http_errors.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_http_errors.lua 2018-05-11 16:16:15.000000000 +0200 @@ -2,6 +2,8 @@ local server = require "net.http.server"; local codes = require "net.http.codes"; +local xml_escape = require "util.stanza".xml_escape; +local render = require "util.interpolation".new("%b{}", xml_escape); local show_private = module:get_option_boolean("http_errors_detailed", false); local always_serve = module:get_option_boolean("http_errors_always_show", true); @@ -21,56 +23,52 @@ <!DOCTYPE html> <html> <head> - <meta charset="utf-8"> - <style> - body{ - margin-top:14%; - text-align:center; - background-color:#F8F8F8; - font-family:sans-serif; - } - h1{ - font-size:xx-large; - } - p{ - font-size:x-large; - } - p+p { font-size: large; font-family: courier } - </style> +<meta charset="utf-8"> +<title>{title}</title> +<style> +body{ + margin-top:14%; + text-align:center; + background-color:#F8F8F8; + font-family:sans-serif; +} +h1{ + font-size:xx-large; +} +p{ + font-size:x-large; +} +p+p { + font-size:large; + font-family:courier; +} +</style> </head> <body> - <h1>$title</h1> - <p>$message</p> - <p>$extra</p> +<h1>{title}</h1> +<p>{message}</p> +<p>{extra?}</p> </body> </html> ]]; -html = html:gsub("%s%s+", ""); - -local entities = { - ["<"] = "<", [">"] = ">", ["&"] = "&", - ["'"] = "'", ["\""] = """, ["\n"] = "<br/>", -}; - -local function tohtml(plain) - return (plain:gsub("[<>&'\"\n]", entities)); - -end local function get_page(code, extra) local message = messages[code]; if always_serve or message then message = message or default_message; - return (html:gsub("$(%a+)", { + return render(html, { title = rawget(codes, code) or ("Code "..tostring(code)); message = message[1]:gsub("%%", function () return message[math.random(2, math.max(#message,2))]; end); - extra = tohtml(extra or ""); - })); + extra = extra; + }); end end module:hook_object_event(server, "http-error", function (event) + if event.response then + event.response.headers.content_type = "text/html; charset=utf-8"; + end return get_page(event.code, (show_private and event.private_message) or event.message); end); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_http_files.lua new/prosody-0.10.1/plugins/mod_http_files.lua --- old/prosody-0.10.0/plugins/mod_http_files.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_http_files.lua 2018-05-11 16:16:15.000000000 +0200 @@ -144,7 +144,7 @@ if not data then return 403; end - cache[orig_path] = { data = data, content_type = mime_map.html; etag = etag; }; + cache:set(orig_path, { data = data, content_type = mime_map.html; etag = etag; }); response_headers.content_type = mime_map.html; else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_limits.lua new/prosody-0.10.1/plugins/mod_limits.lua --- old/prosody-0.10.0/plugins/mod_limits.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_limits.lua 2018-05-11 16:16:15.000000000 +0200 @@ -1,4 +1,4 @@ --- Because we deal we pre-authed sessions and streams we can't be host-specific +-- Because we deal with pre-authed sessions and streams we can't be host-specific module:set_global(); local filters = require "util.filters"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_mam/mamprefs.lib.lua new/prosody-0.10.1/plugins/mod_mam/mamprefs.lib.lua --- old/prosody-0.10.0/plugins/mod_mam/mamprefs.lib.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_mam/mamprefs.lib.lua 2018-05-11 16:16:15.000000000 +0200 @@ -14,6 +14,7 @@ if global_default_policy ~= "roster" then global_default_policy = module:get_option_boolean("default_archive_policy", global_default_policy); end +local smart_enable = module:get_option_boolean("mam_smart_enable", false); do -- luacheck: ignore 211/prefs_format @@ -30,15 +31,37 @@ local archive_store = module:get_option_string("archive_store", "archive"); local prefs = module:open_store(archive_store .. "_prefs"); -local function get_prefs(user) +local function get_prefs(user, explicit) local user_sessions = sessions[user]; local user_prefs = user_sessions and user_sessions.archive_prefs - if not user_prefs and user_sessions then + if not user_prefs then + -- prefs not cached user_prefs = prefs:get(user); - user_sessions.archive_prefs = user_prefs; + if not user_prefs then + -- prefs not set + if smart_enable and explicit then + -- a mam-capable client was involved in this action, set defaults + user_prefs = { [false] = global_default_policy }; + prefs:set(user, user_prefs); + end + end + if user_sessions then + -- cache settings if they originate from user action + user_sessions.archive_prefs = user_prefs; + end + if not user_prefs then + if smart_enable then + -- not yet enabled, either explicitly or "smart" + user_prefs = { [false] = false }; + else + -- no explicit settings, return defaults + user_prefs = { [false] = global_default_policy }; + end + end end - return user_prefs or { [false] = global_default_policy }; + return user_prefs; end + local function set_prefs(user, user_prefs) local user_sessions = sessions[user]; if user_sessions then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_mam/mod_mam.lua new/prosody-0.10.1/plugins/mod_mam/mod_mam.lua --- old/prosody-0.10.0/plugins/mod_mam/mod_mam.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_mam/mod_mam.lua 2018-05-11 16:16:15.000000000 +0200 @@ -52,7 +52,7 @@ archive = module:require "fallback_archive"; end -local use_total = true; +local use_total = module:get_option_boolean("mam_include_total", true); local cleanup; @@ -76,7 +76,7 @@ return true; end end - local prefs = prefs_to_stanza(get_prefs(user)); + local prefs = prefs_to_stanza(get_prefs(user, true)); local reply = st.reply(stanza):add_child(prefs); origin.send(reply); return true; @@ -92,6 +92,7 @@ -- Serve form module:hook("iq-get/self/"..xmlns_mam..":query", function(event) local origin, stanza = event.origin, event.stanza; + get_prefs(origin.username, true); origin.send(st.reply(stanza):query(xmlns_mam):add_child(query_form:form())); return true; end); @@ -102,6 +103,7 @@ local query = stanza.tags[1]; local qid = query.attr.queryid; + get_prefs(origin.username, true); schedule_cleanup(origin.username); -- Search query parameters @@ -127,7 +129,7 @@ qstart, qend = vstart, vend; end - module:log("debug", "Archive query, id %s with %s from %s until %s)", + module:log("debug", "Archive query, id %s with %s from %s until %s", tostring(qid), qwith or "anyone", qstart and timestamp(qstart) or "the dawn of time", qend and timestamp(qend) or "now"); @@ -332,9 +334,7 @@ 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 not archive.delete then - module:log("debug", "Selected storage driver does not support deletion, archives will not expire"); -elseif cleanup_after ~= "never" then +if cleanup_after ~= "never" then 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]?)"); @@ -381,9 +381,10 @@ return math.random(cleanup_interval, cleanup_interval * 2); end); else + module:log("debug", "Archive expiry disabled"); -- Don't ask the backend to count the potentially unbounded number of items, -- it'll get slow. - use_total = false; + use_total = module:get_option_boolean("mam_include_total", false); end -- Stanzas sent by local clients diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_saslauth.lua new/prosody-0.10.1/plugins/mod_saslauth.lua --- old/prosody-0.10.0/plugins/mod_saslauth.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_saslauth.lua 2018-05-11 16:16:15.000000000 +0200 @@ -110,10 +110,15 @@ module:log("info", "SASL EXTERNAL with %s failed: %s", session.to_host, condition); session.external_auth = "failed" - session:close(); - return true; + session.external_auth_failure_reason = condition; end, 500) +module:hook_tag(xmlns_sasl, "failure", function (session, stanza) -- luacheck: ignore 212/stanza + session.log("debug", "No fallback from SASL EXTERNAL failure, giving up"); + session:close(nil, session.external_auth_failure_reason); + return true; +end, 90) + module:hook_tag("http://etherx.jabber.org/streams", "features", function (session, stanza) if session.type ~= "s2sout_unauthed" or not session.secure then return; end @@ -263,6 +268,7 @@ elseif not origin.secure and insecure_mechanisms:contains(mechanism) then log("debug", "Not offering mechanism %s on insecure connection", mechanism); else + log("debug", "Offering mechanism %s", mechanism); mechanisms:tag("mechanism"):text(mechanism):up(); end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_stanza_debug.lua new/prosody-0.10.1/plugins/mod_stanza_debug.lua --- old/prosody-0.10.0/plugins/mod_stanza_debug.lua 1970-01-01 01:00:00.000000000 +0100 +++ new/prosody-0.10.1/plugins/mod_stanza_debug.lua 2018-05-11 16:16:15.000000000 +0200 @@ -0,0 +1,29 @@ +module:set_global(); + +local tostring = tostring; +local filters = require "util.filters"; + +local function log_send(t, session) + if t and t ~= "" and t ~= " " then + session.log("debug", "SEND: %s", tostring(t)); + end + return t; +end + +local function log_recv(t, session) + if t and t ~= "" and t ~= " " then + session.log("debug", "RECV: %s", tostring(t)); + end + return t; +end + +local function init_raw_logging(session) + filters.add_filter(session, "stanzas/in", log_recv, -10000); + filters.add_filter(session, "stanzas/out", log_send, 10000); +end + +filters.add_filter_hook(init_raw_logging); + +function module.unload() + filters.remove_filter_hook(init_raw_logging); +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_storage_sql.lua new/prosody-0.10.1/plugins/mod_storage_sql.lua --- old/prosody-0.10.0/plugins/mod_storage_sql.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_storage_sql.lua 2018-05-11 16:16:15.000000000 +0200 @@ -415,8 +415,8 @@ function driver:purge(username) return engine:transaction(function() - local stmt,err = engine:delete("DELETE FROM \"prosody\" WHERE \"host\"=? AND \"user\"=?", host, username); - return true, err; + engine:delete("DELETE FROM \"prosody\" WHERE \"host\"=? AND \"user\"=?", host, username); + engine:delete("DELETE FROM \"prosodyarchive\" WHERE \"host\"=? AND \"user\"=?", host, username); end); end @@ -452,6 +452,8 @@ Column { name="type", type="TEXT", nullable=false }; Column { name="value", type="MEDIUMTEXT", nullable=false }; Index { name="prosodyarchive_index", unique = true, "host", "user", "store", "key" }; + Index { name="prosodyarchive_with_when", "host", "user", "store", "with", "when" }; + Index { name="prosodyarchive_when", "host", "user", "store", "when" }; }; engine:transaction(function() ProsodyArchiveTable:create(engine); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/mod_websocket.lua new/prosody-0.10.1/plugins/mod_websocket.lua --- old/prosody-0.10.0/plugins/mod_websocket.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/mod_websocket.lua 2018-05-11 16:16:15.000000000 +0200 @@ -257,6 +257,7 @@ local session = sessions[conn]; session.secure = consider_websocket_secure or session.secure; + session.websocket_request = request; session.open_stream = session_open_stream; session.close = session_close; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/muc/mod_muc.lua new/prosody-0.10.1/plugins/muc/mod_muc.lua --- old/prosody-0.10.0/plugins/muc/mod_muc.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/muc/mod_muc.lua 2018-05-11 16:16:15.000000000 +0200 @@ -37,7 +37,12 @@ rooms = {}; local rooms = rooms; local persistent_rooms_storage = module:open_store("persistent"); -local persistent_rooms = persistent_rooms_storage:get() or {}; +local persistent_rooms, err = persistent_rooms_storage:get(); +if not persistent_rooms then + module:log("error", "Error loading list of persistent rooms from storage. Reload mod_muc or restart to recover."); + assert(not err, err); + persistent_rooms = {}; +end local room_configs = module:open_store("config"); -- Configurable options @@ -108,15 +113,21 @@ local persistent_errors = false; for jid in pairs(persistent_rooms) do local node = jid_split(jid); - local data = room_configs:get(node); + local data, err = room_configs:get(node); if data then local room = create_room(jid); room._data = data._data; room._affiliations = data._affiliations; - else -- missing room data + elseif not err then -- missing room data persistent_rooms[jid] = nil; module:log("error", "Missing data for room '%s', removing from persistent room list", jid); persistent_errors = true; + else -- error + module:log("error", "Error loading data for room '%s', locking it until service restart. Error was: %s", jid, err); + local room = muc_new_room(jid); + room.locked = true; + room._affiliations = { [muc_host] = "owner" }; -- To prevent unlocking + rooms[jid] = room; end end if persistent_errors then persistent_rooms_storage:set(nil, persistent_rooms); end @@ -160,7 +171,9 @@ local room = rooms[bare]; if not room then if stanza.name ~= "presence" or stanza.attr.type ~= nil then - origin.send(st.error_reply(stanza, "cancel", "item-not-found")); + if stanza.attr.type ~= "error" then + origin.send(st.error_reply(stanza, "cancel", "item-not-found")); + end return true; end if not(restrict_room_creation) or diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/plugins/muc/muc.lib.lua new/prosody-0.10.1/plugins/muc/muc.lib.lua --- old/prosody-0.10.0/plugins/muc/muc.lib.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/plugins/muc/muc.lib.lua 2018-05-11 16:16:15.000000000 +0200 @@ -99,6 +99,22 @@ end function room_mt:broadcast_message(stanza, historic) local to = stanza.attr.to; + local room_jid = self.jid; + + stanza:maptags(function (child) + if child.name == "delay" and child.attr["xmlns"] == "urn:xmpp:delay" then + if child.attr["from"] == room_jid then + return nil; + end + end + if child.name == "x" and child.attr["xmlns"] == "jabber:x:delay" then + if child.attr["from"] == room_jid then + return nil; + end + end + return child; + end) + for occupant, o_data in pairs(self._occupants) do for jid in pairs(o_data.sessions) do stanza.attr.to = jid; @@ -116,8 +132,8 @@ stanza = st.clone(stanza); stanza.attr.to = ""; local stamp = datetime.datetime(); - stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = stamp}):up(); -- XEP-0203 - stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) + stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = self.jid, stamp = stamp}):up(); -- XEP-0203 + stanza:tag("x", {xmlns = "jabber:x:delay", from = self.jid, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) local entry = { stanza = stanza, stamp = stamp }; t_insert(history, entry); while #history > (self._data.history_length or default_history_length) do t_remove(history, 1) end @@ -189,9 +205,7 @@ end end function room_mt:send_subject(to) - if self._data['subject'] then - self:_route_stanza(st.message({type='groupchat', from=self._data['subject_from'] or self.jid, to=to}):tag("subject"):text(self._data['subject'])); - end + self:_route_stanza(st.message({type='groupchat', from=self._data['subject_from'] or self.jid, to=to}):tag("subject"):text(self._data['subject'])); end function room_mt:get_disco_info(stanza) @@ -199,6 +213,7 @@ local reply = st.reply(stanza):query("http://jabber.org/protocol/disco#info") :tag("identity", {category="conference", type="text", name=self:get_name()}):up() :tag("feature", {var="http://jabber.org/protocol/muc"}):up() + :tag("feature", {var="http://jabber.org/protocol/muc#stable_id"}):up() :tag("feature", {var=self:get_password() and "muc_passwordprotected" or "muc_unsecured"}):up() :tag("feature", {var=self:get_moderated() and "muc_moderated" or "muc_unmoderated"}):up() :tag("feature", {var=self:get_members_only() and "muc_membersonly" or "muc_open"}):up() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/prosody.release new/prosody-0.10.1/prosody.release --- old/prosody-0.10.0/prosody.release 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/prosody.release 2018-05-11 16:16:15.000000000 +0200 @@ -1 +1 @@ -0.10.0 +0.10.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/prosodyctl new/prosody-0.10.1/prosodyctl --- old/prosody-0.10.0/prosodyctl 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/prosodyctl 2018-05-11 16:16:15.000000000 +0200 @@ -868,7 +868,7 @@ assert(input:close()); assert(output:close()); if owner and group then - local ok = os.execute(("chown %s.%s %s"):format(sh_esc(owner), sh_esc(group), sh_esc(to))); + local ok = os.execute(("chown %s:%s %s"):format(sh_esc(owner), sh_esc(group), sh_esc(to))); assert(ok == true or ok == 0, "Failed to change ownership of "..to); end if old_umask then pposix.umask(old_umask); end @@ -947,6 +947,9 @@ if pposix.getuid() ~= cert_dir_attrs.uid then show_warning("The directory "..cert_basedir.." is not owned by the current user, won't be able to write files to it"); return 1; + elseif not cert_dir_attrs.permissions then -- COMPAT with LuaFilesystem < 1.6.2 (hey CentOS!) + show_message("Unable to check permissions on "..cert_basedir.." (LuaFilesystem 1.6.2+ required)"); + show_message("Please confirm that Prosody (and only Prosody) can write to this directory)"); elseif cert_dir_attrs.permissions:match("^%.w..%-..%-.$") then show_warning("The directory "..cert_basedir.." not only writable by its owner"); return 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/util/events.lua new/prosody-0.10.1/util/events.lua --- old/prosody-0.10.0/util/events.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/util/events.lua 2018-05-11 16:16:15.000000000 +0200 @@ -125,7 +125,7 @@ w = wrappers[event_name]; end if not w then return; end - for i = #w, 1 do + for i = #w, 1, -1 do if w[i] == wrapper then t_remove(w, i); end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/util/helpers.lua new/prosody-0.10.1/util/helpers.lua --- old/prosody-0.10.0/util/helpers.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/util/helpers.lua 2018-05-11 16:16:15.000000000 +0200 @@ -50,7 +50,7 @@ local handler_strings = {}; for i, handler in ipairs(handlers) do local upvals = debug.string_from_var_table(debug.get_upvalues_table(handler)); - handler_strings[i] = " "..priorities[handler]..": "..tostring(handler)..(upvals and ("\n "..upvals) or ""); + handler_strings[i] = " "..(priorities[handler] or "?")..": "..tostring(handler)..(upvals and ("\n "..upvals) or ""); end event_handler_arrays[event] = handler_strings; end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/util/sql.lua new/prosody-0.10.1/util/sql.lua --- old/prosody-0.10.0/util/sql.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/util/sql.lua 2018-05-11 16:16:15.000000000 +0200 @@ -217,8 +217,9 @@ end end local function handleerr(err) - log("error", "Error in SQL transaction: %s", debug_traceback(err, 3)); - return err; + local trace = debug_traceback(err, 3); + log("debug", "Error in SQL transaction: %s", trace); + return { err = err, traceback = trace }; end function engine:_transaction(func, ...) if not self.conn then @@ -235,12 +236,13 @@ if success then log("debug", "SQL transaction success [%s]", tostring(func)); local ok, err = self.conn:commit(); - if not ok then return ok, err; end -- commit failed + -- LuaDBI doesn't actually return an error message here, just a boolean + if not ok then return ok, err or "commit failed"; end return success, a, b, c; else - log("debug", "SQL transaction failure [%s]: %s", tostring(func), a); + log("debug", "SQL transaction failure [%s]: %s", tostring(func), a.err); if self.conn then self.conn:rollback(); end - return success, a; + return success, a.err; end end function engine:transaction(...) @@ -248,8 +250,16 @@ if not ok then local conn = self.conn; if not conn or not conn:ping() then + log("debug", "Database connection was closed. Will reconnect and retry."); self.conn = nil; + log("debug", "Retrying SQL transaction [%s]", tostring((...))); ok, ret = self:_transaction(...); + log("debug", "SQL transaction retry %s", ok and "succeeded" or "failed"); + else + log("debug", "SQL connection is up, so not retrying"); + end + if not ok then + log("error", "Error in SQL transaction: %s", ret); end end return ok, ret; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/util/termcolours.lua new/prosody-0.10.1/util/termcolours.lua --- old/prosody-0.10.0/util/termcolours.lua 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/util/termcolours.lua 2018-05-11 16:16:15.000000000 +0200 @@ -30,7 +30,8 @@ local stylemap = { reset = 0; bright = 1, dim = 2, underscore = 4, blink = 5, reverse = 7, hidden = 8; black = 30; red = 31; green = 32; yellow = 33; blue = 34; magenta = 35; cyan = 36; white = 37; - ["black background"] = 40; ["red background"] = 41; ["green background"] = 42; ["yellow background"] = 43; ["blue background"] = 44; ["magenta background"] = 45; ["cyan background"] = 46; ["white background"] = 47; + ["black background"] = 40; ["red background"] = 41; ["green background"] = 42; ["yellow background"] = 43; + ["blue background"] = 44; ["magenta background"] = 45; ["cyan background"] = 46; ["white background"] = 47; bold = 1, dark = 2, underline = 4, underlined = 4, normal = 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/util-src/encodings.c new/prosody-0.10.1/util-src/encodings.c --- old/prosody-0.10.0/util-src/encodings.c 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/util-src/encodings.c 2018-05-11 16:16:15.000000000 +0200 @@ -216,7 +216,7 @@ */ const char *check_utf8(lua_State *L, int idx, size_t *l) { size_t pos, len; - const char *s = luaL_checklstring(L, 1, &len); + const char *s = luaL_checklstring(L, idx, &len); pos = 0; while(pos <= len) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/prosody-0.10.0/util-src/signal.c new/prosody-0.10.1/util-src/signal.c --- old/prosody-0.10.0/util-src/signal.c 2017-09-28 15:07:47.000000000 +0200 +++ new/prosody-0.10.1/util-src/signal.c 2018-05-11 16:16:15.000000000 +0200 @@ -49,6 +49,8 @@ #endif +#define MAX_PENDING_SIGNALS 32 + #define LUA_SIGNAL "lua_signal" static const struct lua_signal lua_signals[] = { @@ -160,54 +162,41 @@ static int Hmask = 0; static int Hcount = 0; -static struct signal_event { - int Nsig; - struct signal_event *next_event; -} *signal_queue = NULL; - -static struct signal_event *last_event = NULL; +int signals[MAX_PENDING_SIGNALS]; +int nsig = 0; static void sighook(lua_State *L, lua_Debug *ar) { - struct signal_event *event; /* restore the old hook */ lua_sethook(L, Hsig, Hmask, Hcount); lua_pushstring(L, LUA_SIGNAL); lua_gettable(L, LUA_REGISTRYINDEX); - while((event = signal_queue)) { - lua_pushnumber(L, event->Nsig); + for(int i = 0; i < nsig; i++) { + lua_pushnumber(L, signals[i]); lua_gettable(L, -2); lua_call(L, 0, 0); - signal_queue = event->next_event; - free(event); }; + nsig = 0; + lua_pop(L, 1); /* pop lua_signal table */ } static void handle(int sig) { - if(!signal_queue) { + if(nsig == 0) { /* Store the existing debug hook (if any) and its parameters */ Hsig = lua_gethook(Lsig); Hmask = lua_gethookmask(Lsig); Hcount = lua_gethookcount(Lsig); - signal_queue = malloc(sizeof(struct signal_event)); - signal_queue->Nsig = sig; - signal_queue->next_event = NULL; - - last_event = signal_queue; - /* Set our new debug hook */ lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); - } else { - last_event->next_event = malloc(sizeof(struct signal_event)); - last_event->next_event->Nsig = sig; - last_event->next_event->next_event = NULL; + } - last_event = last_event->next_event; + if(nsig < MAX_PENDING_SIGNALS) { + signals[nsig++] = sig; } }