Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package prosody for openSUSE:Factory checked 
in at 2026-01-23 17:34:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/prosody (Old)
 and      /work/SRC/openSUSE:Factory/.prosody.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "prosody"

Fri Jan 23 17:34:38 2026 rev:41 rq:1328898 version:13.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/prosody/prosody.changes  2025-11-05 
16:21:29.014096062 +0100
+++ /work/SRC/openSUSE:Factory/.prosody.new.1928/prosody.changes        
2026-01-23 17:34:54.518508111 +0100
@@ -1,0 +2,98 @@
+Fri Jan 23 13:06:26 UTC 2026 - Michael Vetter <[email protected]>
+
+- Update to 13.0.3:
+  Fixes and improvements:
+  * mod_storage_sql: Set configurable wait time for locked SQLite3 database
+  * net.server_event: Port TLS 1.3 channel binding method to libevent backend
+  * mod_roster: Add command for cleaning out invalid contact JIDs
+  * migrator: Allow migrating between different configs of the same driver
+  * mod_admin_shell: Allow pinging any JID with xmpp:ping()
+  * mod_invites: Accept –admin flag as shortcut for –role prosody:admin
+  * mod_mam: Add send_legacy_offline_messages_to_mam_clients config option
+  * mod_limits: Allow configuration of general ‘s2s’ limit, and have s2sout 
inherit from s2sin
+  * mod_storage_internal: Return item-not-found for unknown before/after ids
+  * MUC: Fixes for room avatar caching
+  Minor changes:
+  * core.configmanager: Fix referencing previous config options #1950
+  * MUC: Ensure allow MUC PM setting has valid value (fixes #1933: PM does not 
work on new MUCs)
+  * mod_storage_sql: Assert that serialization of archive:set() payload 
succeeds
+  * mod_smacks: Remove extra optional from sm element
+  * mod_s2s_auth_dane_in: Fix caching SHA2-512 hash
+  * MUC: Fix muc_room_default_presence_broadcast option not working
+  * util.sslconfig: Fix error when applying ssl={[port]=…}
+  * net.server_epoll: Restore idle checks after pause (e.g. rate limits)
+  * util.jid: Validate domainparts using IDNA or as IP literals (fixes #1903: 
Invalid JID in Roster)
+  * util.datamanager: Fix detection of index files created on different 
architectures
+  * util.startup: Inform process manager about failure to reload config
+  * mod_muc: Revert f4e16e6265e6 and invalidate avatar cache only on vcard 
change
+  * mod_http_file_share: Improve debug logging around unexpected file sizes
+  * mod_admin_shell: Ensure JIDs are normalized in xmpp:ping()
+  * mod_invites: Return error when generating password reset for non-existent 
account
+  * util.uuid: Update UUIDv7 to match RFC 9562
+- bsc#1254309: Fix starting prosody
+  Update prodody.service with content from 
https://hg.prosody.im/debian/file/default/prosody.service
+
+-------------------------------------------------------------------
+Fri Jan 23 13:05:40 UTC 2026 - Michael Vetter <[email protected]>
+
+- Update to 13.0.2:
+  Fixes and improvements:
+  * mod_storage_internal: Fix queries with only start returning extra items
+  * mod_invites_register: Stricter validation of registration events
+  Minor changes:
+  * MUC: Ensure allow MUC PM setting has valid value (fixes #1933: PM does not 
work on new MUCs)
+  * mod_storage_sql: Delay showing SQL library error until attempted load
+  * mod_storage_sql: Handle failure to deploy new UNIQUE index
+  * mod_storage_sql: Add shell command to create tables and indices (again)
+  * mod_s2s: Fix log to use formatting instead of concatenation (fixes #1461: 
Logging issues uncovered by mod_log_json)
+  * modulemanager, util.pluginloader: Improve error message when load fails 
but some candidates were filtered
+  * prosodyctl check config: add recommendation to switch from admin_telnet to 
shell
+  * mod_storage_sql: Retrieve all indices to see if the new one exists
+  * prosodyctl check config: List modules which Prosody cannot successfully 
load
+  * net.http.files: Fix issue with caching
+  * util.jsonschema: Fix handling of false as schema
+  * mod_invites: Consider password reset a distinct type wrt invite page
+  * configmanager: Emit config warning when referencing non-existent value
+  * mod_admin_shell: Add role:list() and role:show() commands
+  * MUC: Fix nickname registration form error handling (#1930)
+  * MUC: Fix Error when join stanza sent without resource (#1934)
+  * MUC: Factor out identification of join stanza
+  * mod_invites_register: Don’t restrict username for roster invites (thanks 
lissine)
+  * mod_admin_shell: Fix matching logic in s2s:close (Thanks Menel)
+  * mod_authz_internal: Improve error message when invalid role specified
+  * mod_http_file_share: Add media-src ‘self’ to Content-Security-Policy header
+  * mod_admin_shell: Visual tweaks to the output of debug:cert_index()
+  * mod_http: Log problems parsing IP addresses in X-Forwarded-For (Thanks 
Boris)
+  * mod_http: Fix IP address normalization (Thanks Boris)
+  * util.prosodyctl.check: Improve reporting of DNS lookup problems
+
+-------------------------------------------------------------------
+Fri Jan 23 13:05:01 UTC 2026 - Michael Vetter <[email protected]>
+
+- Update to 13.0.1:
+  Fixes and improvements:
+  * mod_admin_shell: Add debug:cert_index() command to aid debugging of 
automatic certificate selection
+  * mod_tls: Enable Prosody’s certificate checking for incoming s2s 
connections (fixes #1916: Impossible to override certificate verification 
policy in 13.0)
+  * portmanager: Multiple fixes to use correct certificates for direct TLS 
ports (fixes #1915)
+  * net.server_epoll: Use correct connection timeout when initiating Direct TLS
+  * mod_roster: Fix shell commands when a component is involved (fixes #1908: 
error in prosodyctl shell roster attempting to subscribe a component)
+  * mod_http_file_share: Explicitly reject all unsupported ranges
+  * mod_http_file_share: Fix off by one in Range response
+  * mod_admin_shell, prosodyctl shell: Report command failure when no password 
entered (fixes #1907: prosodyctl adduser: unexpected account creation on 
password mismatch)
+  Minor changes:
+  * mod_storage_sql: Drop legacy index without confirmation to ease upgrades
+  * util.adminstream: Fix traceback on double-close (fixes #1913: Prosody 
fails to completely stop while shell watch:log is active)
+  * certmanager: Improve logging for all cases where certs are skipped
+  * mod_tls: Collect full certificate chain validation information
+  * mod_s2s: Fix error detection with newer versions of OpenSSL
+  * portmanager: Add debug log message to state which certificate we end up 
using
+  * prosodyctl check certs: Use correct hostname in warning message about HTTPS
+  * prosodyctl check: Be more robust against invalid disco_items, and show 
warning
+  * spec/tls: Add TLS/certificate integration tests
+  * mod_http_file_share: Improve error reporting by using util.error more
+  * core.storagemanager: Fix tests by removing an assert that upset luarocks
+  * core.usermanager: Fix COMPAT layer for legacy is_admin() function
+  * certmanager: Remove obsolete and verbose index log (replaced by shell 
command)
+  * doap: Add XEP-0333, XEP-0334, XEP-0156 and mod_http_altconnect
+
+-------------------------------------------------------------------

Old:
----
  prosody-13.0.2.tar.gz
  prosody-13.0.2.tar.gz.asc

New:
----
  prosody-13.0.3.tar.gz
  prosody-13.0.3.tar.gz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ prosody.spec ++++++
--- /var/tmp/diff_new_pack.QsNnBD/_old  2026-01-23 17:34:55.150535002 +0100
+++ /var/tmp/diff_new_pack.QsNnBD/_new  2026-01-23 17:34:55.150535002 +0100
@@ -18,7 +18,7 @@
 
 %define _piddir /run
 Name:           prosody
-Version:        13.0.2
+Version:        13.0.3
 Release:        0
 Summary:        Communications server for Jabber/XMPP
 License:        MIT
@@ -119,7 +119,7 @@
 %service_del_postun %{name}.service
 
 %files
-%config(noreplace) %attr(-,root,prosody) %{_sysconfdir}/prosody/
+%config(noreplace) %attr(-,prosody,prosody) %{_sysconfdir}/prosody/
 %{_bindir}/prosody
 %{_bindir}/prosodyctl
 %dir %{_libdir}/prosody

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.QsNnBD/_old  2026-01-23 17:34:55.190536704 +0100
+++ /var/tmp/diff_new_pack.QsNnBD/_new  2026-01-23 17:34:55.194536874 +0100
@@ -1,6 +1,6 @@
-mtime: 1749099187
-commit: 8b088f7c4c922497f156ca88ef7331db5edc246f908aee301bb454731c2ea514
+mtime: 1769175718
+commit: 3d59fd6654890f517cb585f698a258954ef17c3adfa33955795e239a9a162709
 url: https://src.opensuse.org/lua/prosody.git
-revision: 8b088f7c4c922497f156ca88ef7331db5edc246f908aee301bb454731c2ea514
+revision: 3d59fd6654890f517cb585f698a258954ef17c3adfa33955795e239a9a162709
 projectscmsync: https://src.opensuse.org/lua/_ObsPrj.git
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-01-23 14:42:41.000000000 +0100
@@ -0,0 +1 @@
+.osc

++++++ prosody-13.0.2.tar.gz -> prosody-13.0.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/.hg_archival.txt 
new/prosody-13.0.3/.hg_archival.txt
--- old/prosody-13.0.2/.hg_archival.txt 2025-05-29 17:42:58.718566327 +0200
+++ new/prosody-13.0.3/.hg_archival.txt 2026-01-05 13:34:45.144840830 +0100
@@ -1,4 +1,4 @@
 repo: 3e3171b59028ee70122cfec6ecf98f518f946b59
-node: 0dd82a8f19131ed6615cd5287be422e6eb0742bb
+node: f65302ea37b071c3c4bf5fa31f3e4ffd4b4922d1
 branch: 13.0
-tag: 13.0.2
+tag: 13.0.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/core/configmanager.lua 
new/prosody-13.0.3/core/configmanager.lua
--- old/prosody-13.0.2/core/configmanager.lua   2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/core/configmanager.lua   2026-01-05 13:34:45.144840830 
+0100
@@ -7,8 +7,8 @@
 --
 
 local _G = _G;
-local setmetatable, rawget, rawset, io, os, error, dofile, type, pairs, ipairs 
=
-      setmetatable, rawget, rawset, io, os, error, dofile, type, pairs, ipairs;
+local getmetatable, setmetatable, rawget, rawset, io, os, error, dofile, type, 
pairs, ipairs =
+      getmetatable, setmetatable, rawget, rawset, io, os, error, dofile, type, 
pairs, ipairs;
 local format, math_max, t_insert = string.format, math.max, table.insert;
 
 local envload = require"prosody.util.envload".envload;
@@ -169,6 +169,9 @@
                        error("Invalid syntax - missing '=' perhaps?", 2);
                end;
        };
+       local function is_config_option_proxy(v)
+               return getmetatable(v) == config_option_proxy_mt;
+       end
 
        -- For reading config values out of files.
        local function filereader(basepath, defaultmode)
@@ -262,6 +265,9 @@
                                                t_insert(warnings, ("%s:%d: 
Duplicate option '%s'"):format(config_file, get_line_number(config_file), k));
                                        end
                                        set_options[option_path] = true;
+                                       if is_config_option_proxy(v) then
+                                               setmetatable(v, nil);
+                                       end
                                        set(config_table, env.__currenthost or 
"*", k, v);
                                end
                });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/doc/doap.xml 
new/prosody-13.0.3/doc/doap.xml
--- old/prosody-13.0.2/doc/doap.xml     2025-05-29 17:42:58.718566327 +0200
+++ new/prosody-13.0.3/doc/doap.xml     2026-01-05 13:34:45.144840830 +0100
@@ -65,6 +65,7 @@
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc8305"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc9266"/>
     <implements rdf:resource="https://www.rfc-editor.org/info/rfc9525"/>
+    <implements rdf:resource="https://www.rfc-editor.org/info/rfc9562"/>
     <implements 
rdf:resource="https://datatracker.ietf.org/doc/draft-cridland-xmpp-session/";>
       <!-- since=0.6.0 note=Added in hg:0bbbc9042361 -->
     </implements>
@@ -518,7 +519,7 @@
     <implements>
       <xmpp:SupportedXep>
         <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0198.html"/>
-        <xmpp:version>1.6.2</xmpp:version>
+        <xmpp:version>1.6.3</xmpp:version>
         <xmpp:status>complete</xmpp:status>
         <xmpp:since>0.12.0</xmpp:since>
         <xmpp:note>mod_smacks</xmpp:note>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/net/server_epoll.lua 
new/prosody-13.0.3/net/server_epoll.lua
--- old/prosody-13.0.2/net/server_epoll.lua     2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/net/server_epoll.lua     2026-01-05 13:34:45.144840830 
+0100
@@ -966,6 +966,8 @@
                if self.conn and self.conn:dirty() then
                        self:noise("Have buffered incoming data to process");
                        self:onreadable();
+               else
+                       self:setreadtimeout();
                end
        end);
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/net/server_event.lua 
new/prosody-13.0.3/net/server_event.lua
--- old/prosody-13.0.2/net/server_event.lua     2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/net/server_event.lua     2026-01-05 13:34:45.144840830 
+0100
@@ -304,6 +304,14 @@
        return sock:getpeerfinished();
 end
 
+function interface_mt:ssl_exportkeyingmaterial(label, len, context)
+       local sock = self.conn;
+       if not sock then return nil, "not-connected" end
+       if sock.exportkeyingmaterial then
+               return sock:exportkeyingmaterial(label, len, context);
+       end
+end
+
 function interface_mt:resume()
        self:_lock(self.nointerface, false, self.nowriting);
        if self.readcallback and not self.eventread then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_admin_shell.lua 
new/prosody-13.0.3/plugins/mod_admin_shell.lua
--- old/prosody-13.0.2/plugins/mod_admin_shell.lua      2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/mod_admin_shell.lua      2026-01-05 
13:34:45.144840830 +0100
@@ -2051,22 +2051,22 @@
 
 def_env.xmpp = new_section("Commands for sending XMPP stanzas");
 
-describe_command [[xmpp:ping(localhost, remotehost) - Sends a ping to a remote 
XMPP server and reports the response]]
+describe_command [[xmpp:ping(localjid, remotejid) - Sends a ping to an XMPP 
entity and reports the response]]
 local new_id = require "prosody.util.id".medium;
-function def_env.xmpp:ping(localhost, remotehost, timeout)
-       localhost = select(2, jid_split(localhost));
-       remotehost = select(2, jid_split(remotehost));
+function def_env.xmpp:ping(localjid, remotejid, timeout)
+       local localnode, localhost, localresource = jid_split(localjid);
+       local remotenode, remotehost, remoteresource = jid_split(remotejid);
        if not localhost then
-               return nil, "Invalid sender hostname";
+               return nil, "Invalid sender JID";
        elseif not prosody.hosts[localhost] then
                return nil, "No such local host";
+       elseif localresource then
+               return nil, "Server can't send ping from local resource"; -- 
Would require creating a temporary session with bound resource and everything
        end
        if not remotehost then
-               return nil, "Invalid destination hostname";
-       elseif prosody.hosts[remotehost] then
-               return nil, "Both hosts are local";
+               return nil, "Invalid destination JID";
        end
-       local iq = st.iq{ from=localhost, to=remotehost, type="get", 
id=new_id()}
+       local iq = st.iq { from = jid_join(localnode, localhost); to = 
jid_join(remotenode, remotehost, remoteresource); type = "get"; id = new_id() }
                        :tag("ping", {xmlns="urn:xmpp:ping"});
        local time_start = time.now();
        local print = self.session.print;
@@ -2083,6 +2083,12 @@
                        end
                end
        end
+       if localhost == remotehost or prosody.hosts[remotehost] then
+               -- No s2s connections will be triggered
+               return module:context(localhost):send_iq(iq, nil, 
timeout):next(function(pong)
+                       return ("pong from %s in 
%gs"):format(pong.stanza.attr.from, time.now() - time_start);
+               end);
+       end
        local onconnected = onchange("connected");
        local onauthenticated = onchange("authenticated");
        local onestablished = onchange("established");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_http_file_share.lua 
new/prosody-13.0.3/plugins/mod_http_file_share.lua
--- old/prosody-13.0.2/plugins/mod_http_file_share.lua  2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/mod_http_file_share.lua  2026-01-05 
13:34:45.144840830 +0100
@@ -66,7 +66,7 @@
                code = 413;
                type = "modify";
                condition = "not-acceptable";
-               text = "File too large";
+               text = "File too large"; -- also used if file is too small
                extra = {
                        tag = st.stanza("file-too-large", { xmlns = namespace 
}):tag("max-file-size"):text(tostring(file_size_limit));
                };
@@ -293,6 +293,7 @@
                        return upload_errors.new("unauthz", { request = request 
});
                end
                if request.headers.content_length and 
tonumber(request.headers.content_length) ~= authed_upload_info.filesize then
+                       module:log("debug", "Unexpected Content-Length %q, 
expected %s", request.headers.content_length, B(authed_upload_info.filesize));
                        return upload_errors.new("filesize", { request = 
request });
                        -- Note: We don't know the size if the upload is 
streamed in chunked encoding,
                        -- so we also check the final file size on completion.
@@ -351,6 +352,8 @@
                local uploaded, err = errors.coerce(request.body_sink:close());
                if final_size ~= upload_info.filesize then
                        -- Could be too short as well, but we say the same thing
+                       module:log("debug", "Final file size is %s but expected 
%s (%s difference)",
+                               B(final_size), B(upload_info.filesize), 
B(upload_info.filesize - final_size));
                        uploaded, err = false, upload_errors.new("filesize", { 
request = request });
                end
                if uploaded then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_invites.lua 
new/prosody-13.0.3/plugins/mod_invites.lua
--- old/prosody-13.0.2/plugins/mod_invites.lua  2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/plugins/mod_invites.lua  2026-01-05 13:34:45.144840830 
+0100
@@ -1,5 +1,6 @@
 local id = require "prosody.util.id";
 local it = require "prosody.util.iterators";
+local usermanager = require "prosody.core.usermanager";
 local url = require "socket.url";
 local jid_node = require "prosody.util.jid".node;
 local jid_split = require "prosody.util.jid".split;
@@ -260,6 +261,7 @@
        flags = {
                array_params = { role = true, group = have_group_invites };
                value_params = { expires_after = true };
+               kv_params = { admin = true };
        };
 
        handler = function (self, user_jid, opts) --luacheck: ignore 212/self
@@ -301,10 +303,13 @@
        };
 
        handler = function (self, user_jid, opts) --luacheck: ignore 212/self
-               local username = jid_split(user_jid);
+               local username, host = jid_split(user_jid);
                if not username then
                        return nil, "Supply the JID of the account you want to 
generate a password reset for";
                end
+               if not usermanager.user_exists(username, host) then
+                       return nil, "The specified user account does not exist: 
" .. username;
+               end
                local duration_sec = require 
"prosody.util.human.io".parse_duration(opts and opts.expires_after or "1d");
                if not duration_sec then
                        return nil, "Unable to parse duration: 
"..opts.expires_after;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_limits.lua 
new/prosody-13.0.3/plugins/mod_limits.lua
--- old/prosody-13.0.2/plugins/mod_limits.lua   2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/plugins/mod_limits.lua   2026-01-05 13:34:45.144840830 
+0100
@@ -44,7 +44,7 @@
                bytes_per_second = 10 * 1024;
                burst_seconds = 2;
        };
-       s2sin = {
+       s2s = {
                bytes_per_second = 30 * 1024;
                burst_seconds = 2;
        };
@@ -57,6 +57,13 @@
        };
 end
 
+if not limits.s2sin and limits.s2s then
+       limits.s2sin = limits.s2s;
+end
+if not limits.s2sout then
+       limits.s2sout = limits.s2s or limits.s2sin;
+end
+
 local default_filter_set = {};
 
 function default_filter_set.bytes_in(bytes, session)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_mam/mod_mam.lua 
new/prosody-13.0.3/plugins/mod_mam/mod_mam.lua
--- old/prosody-13.0.2/plugins/mod_mam/mod_mam.lua      2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/mod_mam/mod_mam.lua      2026-01-05 
13:34:45.144840830 +0100
@@ -39,6 +39,7 @@
 local timestamp, datestamp = import( "util.datetime", "datetime", "date");
 local default_max_items, max_max_items = 20, 
module:get_option_integer("max_archive_query_results", 50, 0);
 local strip_tags = module:get_option_set("dont_archive_namespaces", { 
"http://jabber.org/protocol/chatstates"; });
+local send_legacy_offline_to_mam_clients = 
module:get_option_boolean("send_legacy_offline_messages_to_mam_clients", false);
 
 local archive_store = module:get_option_string("archive_store", "archive");
 local archive = module:open_store(archive_store, "archive");
@@ -495,12 +496,14 @@
        end
 end, -2);
 
--- Don't broadcast offline messages to clients that have queried the archive.
-module:hook("message/offline/broadcast", function (event)
-       if event.origin.mam_requested then
-               return true;
-       end
-end);
+if not send_legacy_offline_to_mam_clients then
+       -- Don't broadcast offline messages to clients that have queried the 
archive.
+       module:hook("message/offline/broadcast", function (event)
+               if event.origin.mam_requested then
+                       return true;
+               end
+       end);
+end
 
 if cleanup_after ~= math.huge then
        local cleanup_storage = module:open_store("archive_cleanup");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_roster.lua 
new/prosody-13.0.3/plugins/mod_roster.lua
--- old/prosody-13.0.2/plugins/mod_roster.lua   2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/plugins/mod_roster.lua   2026-01-05 13:34:45.144840830 
+0100
@@ -313,3 +313,36 @@
        end;
 });
 
+module:add_item("shell-command", {
+       section = "roster";
+       section_desc = "View and manage user rosters (contact lists)";
+       name = "clean";
+       desc = "Remove invalid JIDs from roster";
+       args = {
+               { name = "jid", type = "string" };
+       };
+       host_selector = "jid";
+       handler = function(self, jid) -- luacheck: ignore 212/self
+               local function iter(user, host)
+                       if user then return pairs({ [user] = true }); end
+                       local users = require"prosody.core.usermanager".users;
+                       return users(host);
+               end
+
+               local user, host = jid_split(jid);
+               local removed = 0;
+               for user_ in iter(user, host) do
+                       local roster = assert(rm_load_roster(user_, host));
+                       for contact in pairs(roster) do
+                               if type(contact) == "string" then
+                                       if not jid_prep(contact) or 
jid_resource(contact) then
+                                               roster[contact] = nil;
+                                               removed = removed + 1;
+                                       end
+                               end
+                       end
+               end
+               return true, ("%d invalid roster entrie(s) 
removed"):format(removed);
+       end;
+});
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_s2s_auth_dane_in.lua 
new/prosody-13.0.3/plugins/mod_s2s_auth_dane_in.lua
--- old/prosody-13.0.2/plugins/mod_s2s_auth_dane_in.lua 2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/mod_s2s_auth_dane_in.lua 2026-01-05 
13:34:45.144840830 +0100
@@ -51,7 +51,7 @@
                        return h;
                elseif i == 2 then
                        local h = sha512(t[0]);
-                       t[1] = h;
+                       t[2] = h;
                        return h;
                end
        end;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_smacks.lua 
new/prosody-13.0.3/plugins/mod_smacks.lua
--- old/prosody-13.0.2/plugins/mod_smacks.lua   2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/plugins/mod_smacks.lua   2026-01-05 13:34:45.144840830 
+0100
@@ -152,16 +152,16 @@
 module:hook("stream-features",
                function (event)
                        if can_do_smacks(event.origin, true) then
-                               event.features:tag("sm", 
sm2_attr):tag("optional"):up():up();
-                               event.features:tag("sm", 
sm3_attr):tag("optional"):up():up();
+                               event.features:tag("sm", sm2_attr):up();
+                               event.features:tag("sm", sm3_attr):up();
                        end
                end);
 
 module:hook("s2s-stream-features",
                function (event)
                        if can_do_smacks(event.origin, true) then
-                               event.features:tag("sm", 
sm2_attr):tag("optional"):up():up();
-                               event.features:tag("sm", 
sm3_attr):tag("optional"):up():up();
+                               event.features:tag("sm", sm2_attr):up();
+                               event.features:tag("sm", sm3_attr):up();
                        end
                end);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_storage_internal.lua 
new/prosody-13.0.3/plugins/mod_storage_internal.lua
--- old/prosody-13.0.2/plugins/mod_storage_internal.lua 2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/mod_storage_internal.lua 2026-01-05 
13:34:45.144840830 +0100
@@ -173,6 +173,7 @@
                return list[i]
        end
 
+       local after_found;
        if query then
                if query.reverse then
                        i = #list + 1
@@ -231,12 +232,23 @@
                        iter = it.filter(function(item)
                                local found_after = found;
                                if item.key == query.after then
+                                       after_found = true;
                                        found = true
                                end
                                return found_after;
                        end, iter);
                end
                if query.before then
+                       local before_key, before_found = query.before;
+                       for idx = 1, #list do
+                               if list[idx].key == before_key then
+                                       before_found = true;
+                                       break;
+                               end
+                       end
+                       if not before_found then
+                               return nil, "item-not-found";
+                       end
                        local found = false;
                        iter = it.filter(function(item)
                                if item.key == query.before then
@@ -250,8 +262,18 @@
                end
        end
 
+       local first_item = iter();
+       if first_item == nil and query and query.after and not after_found then
+               return nil, "item-not-found";
+       end
+
        return function()
-               local item = iter();
+               local item;
+               if first_item then
+                       item, first_item = first_item, nil;
+               else
+                       item = iter();
+               end
                if item == nil then
                        if list.close then
                                list:close();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/mod_storage_sql.lua 
new/prosody-13.0.3/plugins/mod_storage_sql.lua
--- old/prosody-13.0.2/plugins/mod_storage_sql.lua      2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/mod_storage_sql.lua      2026-01-05 
13:34:45.144840830 +0100
@@ -556,7 +556,7 @@
                if new_value then
                        table.insert(setf, '"type" = ?')
                        table.insert(setf, '"value" = ?')
-                       local t, value = serialize(new_value);
+                       local t, value = assert(serialize(new_value));
                        table.insert(args, 1, t);
                        table.insert(args, 2, value);
                end
@@ -995,6 +995,8 @@
                                        engine:execute("PRAGMA fullfsync=1;")
                                end
 
+                               engine:execute(("PRAGMA 
busy_timeout=%d;"):format(module:get_option_integer("sqlite_busy_timeout_ms", 
1000, 0)));
+
                                for row in engine:select[[PRAGMA 
journal_mode;]] do
                                        journal_mode = row[1];
                                end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/muc/mod_muc.lua 
new/prosody-13.0.3/plugins/muc/mod_muc.lua
--- old/prosody-13.0.2/plugins/muc/mod_muc.lua  2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/plugins/muc/mod_muc.lua  2026-01-05 13:34:45.144840830 
+0100
@@ -302,8 +302,7 @@
        
room:set_changesubject(module:get_option_boolean("muc_room_default_change_subject",
 room:get_changesubject()));
        
room:set_historylength(module:get_option_integer("muc_room_default_history_length",
 room:get_historylength(), 0));
        room:set_language(lang or 
module:get_option_string("muc_room_default_language"));
-       
room:set_presence_broadcast(module:get_option_enum("muc_room_default_presence_broadcast",
 room:get_presence_broadcast(), "visitor", "participant",
-               "moderator"));
+       
room:set_presence_broadcast(module:get_option("muc_room_default_presence_broadcast",
 room:get_presence_broadcast()));
        room:set_allow_pm(module:get_option_enum("muc_room_default_allow_pm", 
room:get_allow_pm(), "visitor", "participant", "moderator"));
        
room:set_allow_modpm(module:get_option_boolean("muc_room_default_always_allow_moderator_pms",
 room:get_allow_modpm()));
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/plugins/muc/vcard.lib.lua 
new/prosody-13.0.3/plugins/muc/vcard.lib.lua
--- old/prosody-13.0.2/plugins/muc/vcard.lib.lua        2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/plugins/muc/vcard.lib.lua        2026-01-05 
13:34:45.144840830 +0100
@@ -62,11 +62,12 @@
 end, 10);
 
 if advertise_hashes ~= "none" then
-       module:hook("muc-occupant-joined", function (event)
+       module:hook("muc-occupant-session-new", function (event)
                send_avatar_hash(event.room, event.stanza.attr.from);
        end);
        module:hook("vcard-updated", function (event)
                local room = get_room_from_jid(event.stanza.attr.to);
+               room.avatar_hash = nil;
                send_avatar_hash(room, nil);
        end);
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/prosody.release 
new/prosody-13.0.3/prosody.release
--- old/prosody-13.0.2/prosody.release  2025-05-29 17:42:58.718566327 +0200
+++ new/prosody-13.0.3/prosody.release  2026-01-05 13:34:45.144840830 +0100
@@ -1 +1 @@
-13.0.2
+13.0.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/spec/core_storagemanager_spec.lua 
new/prosody-13.0.3/spec/core_storagemanager_spec.lua
--- old/prosody-13.0.2/spec/core_storagemanager_spec.lua        2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/spec/core_storagemanager_spec.lua        2026-01-05 
13:34:45.144840830 +0100
@@ -621,7 +621,44 @@
                                                assert.equal(2, count);
                                        end);
 
+                                       it("for non-existent after id returning 
error", function ()
+                                               do
+                                                       local data, err = 
archive:find("user", {
+                                                               ["after"] = 
"non-existent-id";
+                                                       });
+                                                       assert.is_falsy(data);
+                                                       
assert.is_equal("item-not-found", err);
+                                               end
+
+                                               do
+                                                       local data, err = 
archive:find("user", {
+                                                               ["after"] = 
"non-existent-id";
+                                                               ["reverse"] = 
true;
+                                                       });
+                                                       assert.is_falsy(data);
+                                                       
assert.is_equal("item-not-found", err);
+                                               end
+                                       end);
+
+                                       it("for non-existent before id 
returning error", function ()
+                                               do
+                                                       local data, err = 
archive:find("user", {
+                                                               ["before"] = 
"non-existent-id";
+                                                       });
+                                                       assert.is_falsy(data);
+                                                       
assert.is_equal("item-not-found", err);
+                                               end
 
+                                               do
+                                                       local data, err = 
archive:find("user", {
+                                                               ["before"] = 
"non-existent-id";
+                                                               ["reverse"] = 
true;
+                                                       });
+                                                       assert.is_falsy(data);
+                                                       
assert.is_equal("item-not-found", err);
+                                               end
+
+                                       end);
 
                                end);
 
@@ -791,3 +828,4 @@
                end);
        end
 end);
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/spec/util_jid_spec.lua 
new/prosody-13.0.3/spec/util_jid_spec.lua
--- old/prosody-13.0.2/spec/util_jid_spec.lua   2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/spec/util_jid_spec.lua   2026-01-05 13:34:45.144840830 
+0100
@@ -64,6 +64,8 @@
                        test("server/resource",         nil,    "server", 
"resource"        );
                        test("server/resource@foo",     nil,    "server", 
"resource@foo"    );
                        test("server/resource@foo/bar", nil,    "server", 
"resource@foo/bar");
+                       test("[email protected]", "node", "203.0.113.80", nil);
+                       test("node@[2001:db8::50:726f:736f:6479]/foo", "node", 
"[2001:db8::50:726f:736f:6479]", "foo")
 
                        -- Always invalid JIDs
                        test(nil,                nil, nil, nil);
@@ -74,6 +76,9 @@
                        test("@server/", nil, nil, nil);
                        test("server/", nil, nil, nil);
                        test("/resource", nil, nil, nil);
+                       test("xmpp:[email protected]", nil, nil, nil);
+                       test("xmpp:example.com", nil, nil, nil);
+                       test("[email protected])", nil, nil, nil);
                end);
                it("should reject invalid arguments", function ()
                        assert.has_error(function () jid.prepped_split(false) 
end)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/spec/util_roles_spec.lua 
new/prosody-13.0.3/spec/util_roles_spec.lua
--- old/prosody-13.0.2/spec/util_roles_spec.lua 2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/spec/util_roles_spec.lua 2026-01-05 13:34:45.144840830 
+0100
@@ -80,8 +80,8 @@
                                
assert.truthy(grandchild_role:may("inherited-permission"));
                        end);
                        describe("supports ordered inheritance from multiple 
roles", function ()
-                               local parent_role = roles.new();
-                               local final_role = roles.new({
+                               local parent_role = roles and roles.new();
+                               local final_role = roles and roles.new({
                                        -- Yes, the names are getting confusing.
                                        -- btw, test_role is inherited through 
child_role.
                                        inherits = { parent_role, child_role };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/tools/migration/prosody-migrator.lua 
new/prosody-13.0.3/tools/migration/prosody-migrator.lua
--- old/prosody-13.0.2/tools/migration/prosody-migrator.lua     2025-05-29 
17:42:58.718566327 +0200
+++ new/prosody-13.0.3/tools/migration/prosody-migrator.lua     2026-01-05 
13:34:45.144840830 +0100
@@ -149,6 +149,7 @@
 
 local cm = require "prosody.core.configmanager";
 local hm = require "prosody.core.hostmanager";
+local mm = require "prosody.core.modulemanager";
 local sm = require "prosody.core.storagemanager";
 local um = require "prosody.core.usermanager";
 
@@ -177,6 +178,7 @@
 
 local function get_driver(host, conf)
        prepare_config(host, conf);
+       mm.unload(host, "storage_" .. conf.type);
        return assert(sm.load_driver(host, conf.type));
 end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/util/datamanager.lua 
new/prosody-13.0.3/util/datamanager.lua
--- old/prosody-13.0.2/util/datamanager.lua     2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/util/datamanager.lua     2026-01-05 13:34:45.144840830 
+0100
@@ -274,7 +274,7 @@
 if string.packsize then
        index_fmt = "T"; -- offset to the end of the item, length can be 
derived from two index items
        index_item_size = string.packsize(index_fmt);
-       index_magic = string.pack(index_fmt, 7767639 + 1); -- Magic string: T9 
for "prosody", version number
+       index_magic = string.pack(index_fmt, 7767639 + 2 + index_item_size); -- 
Magic string: T9 for "prosody", version number
 end
 
 local function list_append(username, host, datastore, data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/util/jid.lua 
new/prosody-13.0.3/util/jid.lua
--- old/prosody-13.0.2/util/jid.lua     2025-05-29 17:42:58.718566327 +0200
+++ new/prosody-13.0.3/util/jid.lua     2026-01-05 13:34:45.144840830 +0100
@@ -13,6 +13,8 @@
 local nodeprep = require "prosody.util.encodings".stringprep.nodeprep;
 local nameprep = require "prosody.util.encodings".stringprep.nameprep;
 local resourceprep = require "prosody.util.encodings".stringprep.resourceprep;
+local idna_to_ascii = require "prosody.util.encodings".idna.to_ascii;
+local net = require "prosody.util.net";
 
 local escapes = {
        [" "] = "\\20"; ['"'] = "\\22";
@@ -48,6 +50,11 @@
        return host;
 end
 
+local function valid_ip(ip)
+       local v6 = match(ip, "^%[([%x:.]+)%]$");
+       return net.pton(v6 or ip);
+end
+
 local function prepped_split(jid, strict)
        local node, host, resource = split(jid);
        if host ~= nil and host ~= "." then
@@ -56,6 +63,7 @@
                end
                host = nameprep(host, strict);
                if host == nil then return; end
+               if not (valid_ip(host) or idna_to_ascii(host)) then return; end
                if node ~= nil then
                        node = nodeprep(node, strict);
                        if node == nil then return; end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/util/sslconfig.lua 
new/prosody-13.0.3/util/sslconfig.lua
--- old/prosody-13.0.2/util/sslconfig.lua       2025-05-29 17:42:58.718566327 
+0200
+++ new/prosody-13.0.3/util/sslconfig.lua       2026-01-05 13:34:45.144840830 
+0100
@@ -120,7 +120,7 @@
        if type(new) == "table" then
                for field, value in pairs(new) do
                        -- exclude keys which are internal to the config builder
-                       if field:sub(1, 1) ~= "_" then
+                       if type(field) == "string" and field:sub(1, 1) ~= "_" 
then
                                (handlers[field] or rawset)(config, field, 
value);
                        end
                end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/util/startup.lua 
new/prosody-13.0.3/util/startup.lua
--- old/prosody-13.0.2/util/startup.lua 2025-05-29 17:42:58.718566327 +0200
+++ new/prosody-13.0.3/util/startup.lua 2026-01-05 13:34:45.144840830 +0100
@@ -347,6 +347,10 @@
                        elseif level == "file" then
                                log("error", "Couldn't read the config file 
when trying to reload: %s", err);
                        end
+                       prosody.events.fire_event("config-reload-failed", {
+                               filename = prosody.config_file;
+                               level = level; error = err;
+                       });
                else
                        prosody.events.fire_event("config-reloaded", {
                                filename = prosody.config_file,
@@ -859,6 +863,15 @@
        prosody.events.add_handler("reloading-config", function()
                
notify_socket:send(string.format("RELOADING=1\nMONOTONIC_USEC=%d", 
math.floor(time.monotonic() * 1000000)));
        end);
+       prosody.events.add_handler("config-reload-failed", function(event)
+               if event and event.level == "parser" then
+                       notify_socket:send(string.format("READY=1\nSTATUS=Error 
parsing configuration file: %s", tostring(event.error)));
+               elseif event and event.level == "file" then
+                       notify_socket:send(string.format("READY=1\nSTATUS=Could 
not read configuration file: %s", tostring(event.error)));
+               else
+                       notify_socket:send("READY=1\nSTATUS=Could not read 
configuration file");
+               end
+       end);
        prosody.events.add_handler("config-reloaded", function()
                notify_socket:send("READY=1");
        end);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/prosody-13.0.2/util/uuid.lua 
new/prosody-13.0.3/util/uuid.lua
--- old/prosody-13.0.2/util/uuid.lua    2025-05-29 17:42:58.718566327 +0200
+++ new/prosody-13.0.3/util/uuid.lua    2026-01-05 13:34:45.144840830 +0100
@@ -28,15 +28,11 @@
 
 local function generate_v7()
        -- Sortable based on time and random
-       -- 
https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-01#section-4.4
-       local t = time.now();
-       local unixts = m_floor(t);
-       local unixts_a = m_floor(unixts / 16);
-       local unixts_b = m_floor(unixts % 16);
-       local subsec = t % 1;
-       local subsec_a = m_floor(subsec * 0x1000);
-       local subsec_b = m_floor(subsec * 0x1000000) % 0x1000;
-       return ("%08x-%x%03x-7%03x-%4s-%12s"):format(unixts_a, unixts_b, 
subsec_a, subsec_b, get_twobits() .. get_nibbles(3), get_nibbles(12));
+       -- https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-7
+       local unix_ts_ms = m_floor(time.now()*1000);
+       local unix_ts_ms_a = m_floor(unix_ts_ms / 0x10000);
+       local unix_ts_ms_b = unix_ts_ms % 0x10000;
+       return ("%08x-%4x-7%3s-%1s%3s-%12s"):format(unix_ts_ms_a, unix_ts_ms_b, 
get_nibbles(3), get_twobits(), get_nibbles(3), get_nibbles(12));
 end
 
 return {


++++++ prosody.service ++++++
--- /var/tmp/diff_new_pack.QsNnBD/_old  2026-01-23 17:34:55.770561382 +0100
+++ /var/tmp/diff_new_pack.QsNnBD/_new  2026-01-23 17:34:55.774561552 +0100
@@ -1,6 +1,9 @@
 [Unit]
-Description=Jabber/XMPP Server
-After=network-online.target mysql.service
+Description=Prosody XMPP Server
+Documentation=https://prosody.im/doc
+
+Requires=network-online.target
+After=network-online.target network.target mariadb.service mysql.service 
postgresql.service
 
 [Service]
 # added automatically, for details please see
@@ -16,12 +19,37 @@
 ProtectControlGroups=true
 RestrictRealtime=true
 # end of automatic additions 
-Type=forking
-PIDFile=/run/prosody/prosody.pid
-ExecStart=/usr/bin/prosodyctl start
-ExecStop=/usr/bin/prosodyctl stop
+Type=notify
+
+# Start by executing the main executable
+ExecStart=/usr/bin/prosody -F
+ExecReload=/bin/kill -HUP $MAINPID
+Restart=on-abnormal
+
+User=prosody
+Group=prosody
+UMask=0027
+
+RuntimeDirectory=prosody
+ConfigurationDirectory=prosody
+StateDirectory=prosody
+StateDirectoryMode=0750
+LogsDirectory=prosody
+WorkingDirectory=~
+
+# Set stdin to /dev/null since Prosody does not need it
+StandardInput=null
+
+# Direct stdout/-err to journald for use with log = "*stdout"
+StandardOutput=journal
+StandardError=inherit
+
+# Allow binding low ports
+AmbientCapabilities=CAP_NET_BIND_SERVICE
 
 [Install]
 WantedBy=multi-user.target
 Alias=org.prosody.service
 
+# vim: filetype=systemd
+

Reply via email to