Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libfilezilla for openSUSE:Factory 
checked in at 2026-04-11 22:26:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libfilezilla (Old)
 and      /work/SRC/openSUSE:Factory/.libfilezilla.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libfilezilla"

Sat Apr 11 22:26:35 2026 rev:64 rq:1346068 version:0.55.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/libfilezilla/libfilezilla.changes        
2025-11-17 12:22:44.796171364 +0100
+++ /work/SRC/openSUSE:Factory/.libfilezilla.new.21863/libfilezilla.changes     
2026-04-11 22:31:53.073912975 +0200
@@ -1,0 +2,19 @@
+Sat Apr 11 10:33:37 UTC 2026 - ecsos <[email protected]> - 0.55.2
+
+- Update to 0.55.2
+  * New features:
+    - Added fz::buffer::clear_and_free
+    - Added fz::event_handler::remove_events<T>() to remove all
+      events of a given type.
+- Changes from 0.55.1
+  * Bugfixes and minor changes:
+    - Added fz::socket::flag_oobinline
+- Changes from 0.55.0
+  * New features:
+    - MSW: Added functionality to iterate over registry values
+    - Added SHA3 support for fz::hash_accumulator
+  * Bugfixes and minor changes:
+    - Fix handling of certificates without subject due to
+      gnutls_x509_get_dn3 returning an error instead of an empty DN
+
+-------------------------------------------------------------------

Old:
----
  libfilezilla-0.52.0.tar.xz

New:
----
  libfilezilla-0.55.2.tar.xz

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

Other differences:
------------------
++++++ libfilezilla.spec ++++++
--- /var/tmp/diff_new_pack.ADjeZK/_old  2026-04-11 22:31:54.709979890 +0200
+++ /var/tmp/diff_new_pack.ADjeZK/_new  2026-04-11 22:31:54.721980381 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package libfilezilla
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,11 +16,11 @@
 #
 
 
-%define major          50
+%define major          54
 %define libname                %{name}%{major}
 %define develname      %{name}-devel
 Name:           libfilezilla
-Version:        0.52.0
+Version:        0.55.2
 Release:        0
 Summary:        C++ library for filezilla
 License:        GPL-2.0-or-later

++++++ libfilezilla-0.52.0.tar.xz -> libfilezilla-0.55.2.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/NEWS new/libfilezilla-0.55.2/NEWS
--- old/libfilezilla-0.52.0/NEWS        2025-11-10 15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/NEWS        2026-03-23 16:11:18.000000000 +0100
@@ -1,3 +1,39 @@
+0.55.2 (2026-03-23)
+
++ Added fz::buffer::clear_and_free
++ Added fz::event_handler::remove_events<T>() to remove all events of a given 
type.
+
+0.55.1 (2026-03-18)
+
++ Added fz::socket::flag_oobinline
+
+0.55.0 (2026-03-16)
+
++ MSW: Added functionality to iterate over registry values
++ Added SHA3 support for fz::hash_accumulator
+- Fix handling of certificates without subject due to gnutls_x509_get_dn3 
returning an error instead of an empty DN
+
+0.54.1 (2026-02-10)
+
++ Added file_reader::mtime()
+- X.509 certificates with an empty distinguished name as subject are now 
allowed
+- Forwarded socket events now get sent through the event loop to ensure 
destruction safety
+
+0.54.0 (2026-01-16)
+
++ Added fz::processor_count()
++ Added create_tcp_socketpair as alternative to socketpair() which does not 
exist on Windows
+- MSW: If spawning a process fails, close the redirected pipes so that 
subsequent read/write attempts fail immediately
+
+0.53.1 (2025-12-12)
+
+- Fixed an issue with fz::async_task::join() if the underlying pool thread 
gets re-used too quickly
+
+0.53.0 (2025-12-10)
+
++ Added fz::event_with_source and fz::event_handler::remove_events taking 
fz::event_source, as a way to easily remove multiple types of pending events 
from a given source
+- Removing a child event handler was wrongly removing pending events of its 
ancestors
+
 0.52.0 (2025-11-10)
 
 + Event handlers can now be in a hierarchy. If calling remove_handler on a 
handler that has children, they are removed as well.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/README 
new/libfilezilla-0.55.2/README
--- old/libfilezilla-0.52.0/README      2025-03-26 11:13:17.000000000 +0100
+++ new/libfilezilla-0.55.2/README      2026-03-16 16:04:46.000000000 +0100
@@ -1,7 +1,7 @@
                                  libfilezilla
                                  -------------
 
-                         Copyright (C) 2015-2025  Tim Kosse
+                         Copyright (C) 2015-2026  Tim Kosse
                        https://lib.filezilla-project.org/
 
 Overview
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/configure 
new/libfilezilla-0.55.2/configure
--- old/libfilezilla-0.52.0/configure   2025-11-10 15:14:59.000000000 +0100
+++ new/libfilezilla-0.55.2/configure   2026-03-23 16:11:23.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for libfilezilla 0.52.0.
+# Generated by GNU Autoconf 2.72 for libfilezilla 0.55.2.
 #
 # Report bugs to <[email protected]>.
 #
@@ -614,8 +614,8 @@
 # Identity of this package.
 PACKAGE_NAME='libfilezilla'
 PACKAGE_TARNAME='libfilezilla'
-PACKAGE_VERSION='0.52.0'
-PACKAGE_STRING='libfilezilla 0.52.0'
+PACKAGE_VERSION='0.55.2'
+PACKAGE_STRING='libfilezilla 0.55.2'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL='https://lib.filezilla-project.org/'
 
@@ -1477,7 +1477,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures libfilezilla 0.52.0 to adapt to many kinds of systems.
+'configure' configures libfilezilla 0.55.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1548,7 +1548,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libfilezilla 0.52.0:";;
+     short | recursive ) echo "Configuration of libfilezilla 0.55.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1705,7 +1705,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libfilezilla configure 0.52.0
+libfilezilla configure 0.55.2
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2110,7 +2110,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libfilezilla $as_me 0.52.0, which was
+It was created by libfilezilla $as_me 0.55.2, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3106,7 +3106,7 @@
 # If any interfaces have been added since the last public release, then 
increment age.
 # If any interfaces have been removed or changed since the last public 
release, then set age to 0.
 # CURRENT:REVISION:AGE
-LIBRARY_VERSION=50:0:0
+LIBRARY_VERSION=56:0:2
 
 
 
@@ -3814,7 +3814,7 @@
 
 # Define the identity of the package.
  PACKAGE='libfilezilla'
- VERSION='0.52.0'
+ VERSION='0.55.2'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -25826,7 +25826,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libfilezilla $as_me 0.52.0, which was
+This file was extended by libfilezilla $as_me 0.55.2, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -25895,7 +25895,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-libfilezilla config.status 0.52.0
+libfilezilla config.status 0.55.2
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/configure.ac 
new/libfilezilla-0.55.2/configure.ac
--- old/libfilezilla-0.52.0/configure.ac        2025-11-10 15:14:41.000000000 
+0100
+++ new/libfilezilla-0.55.2/configure.ac        2026-03-23 16:11:18.000000000 
+0100
@@ -1,4 +1,4 @@
-AC_INIT([libfilezilla],[0.52.0],[[email protected]],[],[https://lib.filezilla-project.org/])
+AC_INIT([libfilezilla],[0.55.2],[[email protected]],[],[https://lib.filezilla-project.org/])
 
 # Update the version information only immediately before a public release of 
your software
 # If the library source code has changed at all since the last update, then 
increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
@@ -6,7 +6,7 @@
 # If any interfaces have been added since the last public release, then 
increment age.
 # If any interfaces have been removed or changed since the last public 
release, then set age to 0.
 # CURRENT:REVISION:AGE
-LIBRARY_VERSION=50:0:0
+LIBRARY_VERSION=56:0:2
 
 AH_TOP([
 #ifndef LIBFILEZILLA_CONFIG_HEADER
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/aio/reader.cpp 
new/libfilezilla-0.55.2/lib/aio/reader.cpp
--- old/libfilezilla-0.52.0/lib/aio/reader.cpp  2024-06-26 11:40:18.000000000 
+0200
+++ new/libfilezilla-0.55.2/lib/aio/reader.cpp  2026-02-10 09:52:49.000000000 
+0100
@@ -366,6 +366,11 @@
 }
 
 
+datetime file_reader::mtime() const
+{
+       return file_.get_modification_time();
+}
+
 file_reader_factory::file_reader_factory(std::wstring const& file, thread_pool 
& tpool)
        : reader_factory(file)
        , thread_pool_(tpool)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/buffer.cpp 
new/libfilezilla-0.55.2/lib/buffer.cpp
--- old/libfilezilla-0.52.0/lib/buffer.cpp      2025-07-16 11:21:37.000000000 
+0200
+++ new/libfilezilla-0.55.2/lib/buffer.cpp      2026-03-23 16:11:18.000000000 
+0100
@@ -128,6 +128,15 @@
        pos_ = data_;
 }
 
+void buffer::clear_and_free()
+{
+       size_ = 0;
+       capacity_ = 0;
+       pos_ = nullptr;
+       delete [] data_;
+       data_ = nullptr;
+}
+
 void buffer::append(unsigned char const* data, size_t len)
 {
        if (!len) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/event_handler.cpp 
new/libfilezilla-0.55.2/lib/event_handler.cpp
--- old/libfilezilla-0.52.0/lib/event_handler.cpp       2025-11-10 
15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/event_handler.cpp       2026-03-23 
16:11:18.000000000 +0100
@@ -93,4 +93,24 @@
        return event_loop_.stop_add_timer(id, this, deadline, interval);
 }
 
+void event_handler::remove_events(event_source const* const source)
+{
+       auto event_filter = [&](event_base& ev) -> bool {
+                       auto sev = dynamic_cast<event_with_source_base*>(&ev);
+                       if (sev) {
+                               return sev->source() == source;
+                       }
+                       return false;
+               };
+       filter_events(event_filter);
+}
+
+void event_handler::remove_events_of_type(size_t t)
+{
+       auto event_filter = [&](event_base& ev) -> bool {
+               return ev.derived_type() == t;
+       };
+       filter_events(event_filter);
+}
+
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/event_loop.cpp 
new/libfilezilla-0.55.2/lib/event_loop.cpp
--- old/libfilezilla-0.52.0/lib/event_loop.cpp  2025-11-10 15:14:41.000000000 
+0100
+++ new/libfilezilla-0.55.2/lib/event_loop.cpp  2025-12-10 16:59:22.000000000 
+0100
@@ -73,11 +73,11 @@
        scoped_lock l(sync_);
 
        auto is_part_of_group = [&](event_handler* h, event_handler* group) {
-               while (group) {
+               while (h) {
                        if (h == group) {
                                return true;
                        }
-                       group = group->parent_;
+                       h = h->parent_;
                }
                return false;
        };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/file.cpp 
new/libfilezilla-0.55.2/lib/file.cpp
--- old/libfilezilla-0.52.0/lib/file.cpp        2025-11-10 15:14:41.000000000 
+0100
+++ new/libfilezilla-0.55.2/lib/file.cpp        2026-02-10 09:52:49.000000000 
+0100
@@ -269,7 +269,7 @@
        return SetFileTime(fd_, nullptr, &ft, &ft) == TRUE;
 }
 
-datetime file::get_modification_time()
+datetime file::get_modification_time() const
 {
        FILETIME ft{};
 
@@ -527,7 +527,7 @@
        return futimens(fd_, times) == 0;
 }
 
-datetime file::get_modification_time()
+datetime file::get_modification_time() const
 {
        struct stat buf;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/hash.cpp 
new/libfilezilla-0.55.2/lib/hash.cpp
--- old/libfilezilla-0.52.0/lib/hash.cpp        2025-07-31 13:05:59.000000000 
+0200
+++ new/libfilezilla-0.55.2/lib/hash.cpp        2026-02-25 17:36:43.000000000 
+0100
@@ -8,6 +8,7 @@
 #include <nettle/md5.h>
 #include <nettle/memops.h>
 #include <nettle/pbkdf2.h>
+#include <nettle/sha3.h>
 
 // Undo Nettle's horrible namespace mangling fuckery
 #ifdef pbkdf2_hmac_sha256
@@ -34,10 +35,13 @@
                case hash_algorithm::sha1:
                        return 160/8;
                case hash_algorithm::sha256:
+               case hash_algorithm::sha3_256:
                        return 256/8;
                case hash_algorithm::sha384:
+               case hash_algorithm::sha3_384:
                        return 384/8;
                case hash_algorithm::sha512:
+               case hash_algorithm::sha3_512:
                        return 512/8;
        }
        return {};
@@ -302,6 +306,96 @@
        }
 };
 
+class hash_accumulator_sha3_256 : public hash_accumulator::impl
+{
+public:
+       hash_accumulator_sha3_256()
+       {
+               reinit();
+       }
+
+       virtual size_t digest_size() const override { return 
SHA3_256_DIGEST_SIZE; }
+
+       virtual void update(uint8_t const* data, size_t size) override final
+       {
+               nettle_sha3_256_update(&ctx_, size, data);
+       }
+
+       virtual void reinit() override final
+       {
+               nettle_sha3_256_init(&ctx_);
+       }
+
+       virtual void digest(uint8_t* out) override
+       {
+               nettle_sha3_256_digest(&ctx_, SHA3_256_DIGEST_SIZE, out);
+       }
+
+protected:
+       sha3_256_ctx ctx_;
+};
+
+
+class hash_accumulator_sha3_384 : public hash_accumulator::impl
+{
+public:
+       hash_accumulator_sha3_384()
+       {
+               reinit();
+       }
+
+       virtual size_t digest_size() const override { return 
SHA3_384_DIGEST_SIZE; }
+
+       virtual void update(uint8_t const* data, size_t size) override final
+       {
+               nettle_sha3_384_update(&ctx_, size, data);
+       }
+
+       virtual void reinit() override final
+       {
+               nettle_sha3_384_init(&ctx_);
+       }
+
+       virtual void digest(uint8_t* out) override
+       {
+               nettle_sha3_384_digest(&ctx_, SHA3_384_DIGEST_SIZE, out);
+       }
+
+protected:
+       sha3_384_ctx ctx_;
+};
+
+
+class hash_accumulator_sha3_512 : public hash_accumulator::impl
+{
+public:
+       hash_accumulator_sha3_512()
+       {
+               reinit();
+       }
+
+       virtual size_t digest_size() const override { return 
SHA3_512_DIGEST_SIZE; }
+
+       virtual void update(uint8_t const* data, size_t size) override final
+       {
+               nettle_sha3_512_update(&ctx_, size, data);
+       }
+
+       virtual void reinit() override final
+       {
+               nettle_sha3_512_init(&ctx_);
+       }
+
+       virtual void digest(uint8_t* out) override
+       {
+               nettle_sha3_512_digest(&ctx_, SHA3_512_DIGEST_SIZE, out);
+       }
+
+protected:
+       sha3_512_ctx ctx_;
+};
+
+
 class hash_accumulator_hmac_sha256 final : public hash_accumulator::impl
 {
 public:
@@ -410,6 +504,15 @@
        case hash_algorithm::sha512:
                impl_ = new hash_accumulator_sha512;
                break;
+       case hash_algorithm::sha3_256:
+               impl_ = new hash_accumulator_sha3_256;
+               break;
+       case hash_algorithm::sha3_384:
+               impl_ = new hash_accumulator_sha3_384;
+               break;
+       case hash_algorithm::sha3_512:
+               impl_ = new hash_accumulator_sha3_512;
+               break;
        }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/aio/reader.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/aio/reader.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/aio/reader.hpp     2024-06-26 
11:40:18.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/aio/reader.hpp     2026-02-10 
09:52:49.000000000 +0100
@@ -248,6 +248,8 @@
 
        virtual bool seekable() const override;
 
+       virtual datetime mtime() const override;
+
 private:
        virtual void FZ_PRIVATE_SYMBOL do_close(scoped_lock & l) override;
        virtual bool FZ_PRIVATE_SYMBOL do_seek(scoped_lock & l) override;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/buffer.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/buffer.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/buffer.hpp 2025-11-10 
15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/libfilezilla/buffer.hpp 2026-03-23 
16:11:18.000000000 +0100
@@ -98,6 +98,8 @@
         */
        void clear();
 
+       void clear_and_free();
+
        /** \brief Appends the passed data to the buffer.
         *
         * The number of reallocations as result to repeated append are 
amortized O(1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/event.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/event.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/event.hpp  2023-05-26 
09:44:37.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/event.hpp  2025-12-10 
16:59:22.000000000 +0100
@@ -98,6 +98,56 @@
        mutable tuple_type v_;
 };
 
+class event_source{};
+
+/// \private
+class event_with_source_base : public event_base
+{
+public:
+       using event_base::event_base;
+       virtual event_source* source() const  = 0;
+};
+
+/**
+\brief Events with associated source
+ *
+ * This is similar to simple_event, except that the type of the first event 
value
+ * is derived from event_source.
+ *
+ * Pending events from a given source can easily be removed
+ * using \ref event_handler::remove_events
+ */
+template<typename UniqueType, typename...Values>
+class event_with_source final : public event_with_source_base
+{
+public:
+       typedef UniqueType unique_type;
+       typedef std::tuple<Values...> tuple_type;
+
+       using event_with_source_base::event_with_source_base;
+
+       template<typename First_Value, typename...Remaining_Values>
+       explicit event_with_source(First_Value&& value, Remaining_Values&& 
...values)
+               : v_(std::forward<First_Value>(value), 
std::forward<Remaining_Values>(values)...)
+       {
+       }
+
+       inline static size_t type() {
+               static size_t const v = get_unique_type_id(typeid(UniqueType*));
+               return v;
+       }
+
+       virtual size_t derived_type() const override {
+               return type();
+       }
+
+       virtual event_source* source() const override {
+               return static_cast<event_source*>(std::get<0>(v_));
+       }
+
+       mutable tuple_type v_;
+};
+
 /// Used as lightweight RTTI alternative during \ref dispatch
 /// \return true iff T& t = ...; t.derived_type() == ev.derived_type()
 template<typename T>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libfilezilla-0.52.0/lib/libfilezilla/event_handler.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/event_handler.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/event_handler.hpp  2025-11-10 
15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/libfilezilla/event_handler.hpp  2026-03-23 
16:11:18.000000000 +0100
@@ -183,8 +183,18 @@
                event_loop_.resend_current_event();
        }
 
+       void remove_events(event_source const* const source);
+
+       template<typename T>
+       void remove_events() {
+               remove_events_of_type(T::type());
+       }
+
        event_loop & event_loop_;
+
 private:
+       void remove_events_of_type(size_t t);
+
        friend class event_loop;
        bool removing_{};
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/file.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/file.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/file.hpp   2025-11-10 
15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/libfilezilla/file.hpp   2026-02-10 
09:52:49.000000000 +0100
@@ -218,7 +218,7 @@
         *
         * File must be opened for reading, or the call will fail.
         */
-       datetime get_modification_time();
+       datetime get_modification_time() const;
 
 private:
 #ifdef FZ_WINDOWS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/format.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/format.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/format.hpp 2022-04-01 
14:35:07.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/format.hpp 2026-01-16 
15:41:56.000000000 +0100
@@ -29,7 +29,8 @@
        pad_blank = 2,
        with_width = 4,
        left_align = 8,
-       always_sign = 16
+       always_sign = 16,
+       thousands = 32
 };
 
 struct field final {
@@ -330,6 +331,9 @@
                        f.flags &= ~pad_blank;
                        f.flags |= always_sign;
                }
+               else if (fmt[pos] == '\'') {
+                       f.flags |= thousands;
+               }
                else {
                        break;
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/fsresult.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/fsresult.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/fsresult.hpp       2025-03-26 
11:07:26.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/libfilezilla/fsresult.hpp       2026-02-25 
17:36:43.000000000 +0100
@@ -107,6 +107,7 @@
            : error_(e)
            , raw_(raw)
        {}
+       explicit rwresult(error e) = delete;
 
        explicit rwresult(size_t value)
            : value_(value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libfilezilla-0.52.0/lib/libfilezilla/glue/registry.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/glue/registry.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/glue/registry.hpp  2023-10-11 
10:26:52.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/glue/registry.hpp  2026-03-16 
16:04:46.000000000 +0100
@@ -67,6 +67,88 @@
 
        bool delete_value(std::wstring const& name);
 
+       struct iterator final
+       {
+               struct value final
+               {
+                       std::wstring name;
+                       DWORD type{};
+               };
+
+               iterator() = default;
+
+               iterator &operator++()
+               {
+                       if (key_ && key_->key_) {
+                               DWORD len{16383};
+                               v_.name.resize(len);
+
+                               DWORD res = RegEnumValueW(*key_->key_, 
++index_, v_.name.data(), &len, nullptr, &v_.type, nullptr, nullptr);
+                               if (res != ERROR_SUCCESS || !len) {
+                                       index_ = DWORD(-1);
+                               }
+                               else {
+                                       v_.name.resize(len);
+                               }
+                       }
+                       return *this;
+               }
+
+               bool operator==(iterator const& op) const
+               {
+                       return index_ == op.index_;
+               }
+
+               bool operator!=(iterator const& op) const
+               {
+                       return !(*this == op);
+               }
+
+               value const& operator*() const
+               {
+                       return v_;
+               }
+
+               value const* operator->() const
+               {
+                       return &v_;
+               }
+
+       private:
+               friend regkey;
+
+               iterator(regkey const* key)
+                       : key_(key)
+               {
+                       operator++();
+               }
+
+               regkey const* key_{};
+               DWORD index_{DWORD(-1)};
+               value v_;
+       };
+       using const_iterator = iterator;
+
+       iterator begin() const
+       {
+               return { this };
+       }
+
+       iterator end() const
+       {
+               return {};
+       }
+
+       const_iterator cbegin() const
+       {
+               return { this };
+       }
+
+       const_iterator cend() const
+       {
+               return {};
+       }
+
 private:
        mutable std::optional<HKEY> key_;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/hash.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/hash.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/hash.hpp   2025-07-31 
13:05:59.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/hash.hpp   2026-02-25 
17:36:43.000000000 +0100
@@ -19,7 +19,10 @@
        sha1, // insecure
        sha256,
        sha384,
-       sha512
+       sha512,
+       sha3_256,
+       sha3_384,
+       sha3_512
 };
 
 enum class hmac_algorithm
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libfilezilla-0.52.0/lib/libfilezilla/local_filesys.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/local_filesys.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/local_filesys.hpp  2025-11-10 
15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/libfilezilla/local_filesys.hpp  2025-12-10 
16:59:22.000000000 +0100
@@ -4,6 +4,7 @@
 #include "fsresult.hpp"
 #include "libfilezilla.hpp"
 #include "time.hpp"
+#include "file.hpp"
 
 #ifdef FZ_WINDOWS
 #include "glue/windows.hpp"
@@ -89,21 +90,12 @@
        /// \param dirs_only If true, only directories are enumerated.
        result begin_find_files(native_string path, bool dirs_only = false, 
bool query_symlink_targets = true);
 
-#if FZ_WINDOWS
        /**
-        * \brief Begin enumerating a directory represented by a HANDLE
+        * \brief Begin enumerating a directory represented by a descriptor.
         *
-        * Takes ownership of the HANDLE.
+        * Takes ownership of descriptor/handle.
         */
-       result begin_find_files(HANDLE dir, bool dirs_only = false, bool 
query_symlink_targets = true);
-#else
-       /**
-        * \brief Begin enumerating a directory represented by a file 
descriptor.
-        *
-        * Takes ownership of the descriptor.
-        */
-       result begin_find_files(int fd, bool dirs_only = false, bool 
query_symlink_targets = true);
-#endif
+       result begin_find_files(file::file_t fd, bool dirs_only = false, bool 
query_symlink_targets = true);
 
        /// Gets the next file in the directory. Call until it returns false.
        bool get_next_file(native_string& name);
@@ -136,6 +128,9 @@
         */
        static native_string get_final_link_target(native_string const& path);
 
+       /// Returns the raw descriptor/handle, but retains ownership.
+       file::file_t fd();
+
 private:
 #ifdef FZ_WINDOWS
        bool FZ_PRIVATE_SYMBOL check_buffer();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/socket.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/socket.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/socket.hpp 2025-07-16 
11:21:37.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/socket.hpp 2026-03-18 
16:44:03.000000000 +0100
@@ -572,7 +572,10 @@
                flag_nodelay = 0x01,
 
                /// flag_keepalive enables TCP keepalive.
-               flag_keepalive = 0x02
+               flag_keepalive = 0x02,
+
+               /// Inline delivery of OOB data
+               flag_oobinline = 0x04
        };
 
        int flags() const { return flags_; }
@@ -755,6 +758,19 @@
  */
 native_string FZ_PUBLIC_SYMBOL socket_error_description(int error);
 
+/**
+ * \brief Creates a pair of connected TCP sockets
+ *
+ * Unfortunately Windows lacks POSIX' socketpair(). While some support for
+ * Unix Domain Sockets has been added to Windows, it omits socketpair, and
+ * abstract AF_UNIX cannot be connected to (WSAEINVAL).
+ *
+ * This function creates a listen socket on localhost, connects to it,
+ * accepts the connection, closes the listen socket again and returns
+ * the connected TCP socket pair.
+ */
+std::optional<std::pair<std::unique_ptr<fz::socket>, 
std::unique_ptr<fz::socket>>> FZ_PUBLIC_SYMBOL 
create_tcp_socketpair(fz::thread_pool & pool);
+
 
 #ifdef FZ_WINDOWS
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/libfilezilla/thread.hpp 
new/libfilezilla-0.55.2/lib/libfilezilla/thread.hpp
--- old/libfilezilla-0.52.0/lib/libfilezilla/thread.hpp 2020-07-07 
14:06:31.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/libfilezilla/thread.hpp 2026-01-16 
15:41:56.000000000 +0100
@@ -73,6 +73,9 @@
        friend class impl;
        impl* impl_{};
 };
+
+size_t FZ_PUBLIC_SYMBOL processor_count();
+
 }
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/local_filesys.cpp 
new/libfilezilla-0.55.2/lib/local_filesys.cpp
--- old/libfilezilla-0.52.0/lib/local_filesys.cpp       2025-08-13 
19:10:42.000000000 +0200
+++ new/libfilezilla-0.55.2/lib/local_filesys.cpp       2025-12-10 
16:59:22.000000000 +0100
@@ -1071,6 +1071,15 @@
        return target;
 }
 
+file::file_t local_filesys::fd()
+{
+#ifdef FZ_WINDOWS
+       return dir_;
+#else
+       return dir_ ? dirfd(dir_) : -1;
+#endif
+}
+
 native_string local_filesys::get_link_target(native_string const& path)
 {
        native_string target;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/process.cpp 
new/libfilezilla-0.55.2/lib/process.cpp
--- old/libfilezilla-0.52.0/lib/process.cpp     2025-11-10 15:14:41.000000000 
+0100
+++ new/libfilezilla-0.55.2/lib/process.cpp     2026-02-25 17:36:43.000000000 
+0100
@@ -257,6 +257,7 @@
                }
 
                if (!res) {
+                       kill();
                        return false;
                }
 
@@ -953,12 +954,12 @@
 
 rwresult process::read(void* buffer, size_t len)
 {
-       return impl_ ? impl_->read(buffer, len) : rwresult{rwresult::invalid};
+       return impl_ ? impl_->read(buffer, len) : rwresult{rwresult::invalid, 
0};
 }
 
 rwresult process::write(void const* buffer, size_t len)
 {
-       return impl_ ? impl_->write(buffer, len) : rwresult{rwresult::invalid};
+       return impl_ ? impl_->write(buffer, len) : rwresult{rwresult::invalid, 
0};
 }
 
 #if FZ_WINDOWS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/socket.cpp 
new/libfilezilla-0.55.2/lib/socket.cpp
--- old/libfilezilla-0.52.0/lib/socket.cpp      2025-11-10 15:14:41.000000000 
+0100
+++ new/libfilezilla-0.55.2/lib/socket.cpp      2026-03-18 16:44:03.000000000 
+0100
@@ -309,6 +309,13 @@
 #endif
 #endif
        }
+       if (flags_mask & socket::flag_oobinline) {
+               const int value = (flags & socket::flag_oobinline) ? 1 : 0;;
+               int res = setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (const 
char*)&value, sizeof(value));
+               if (res != 0) {
+                       return last_socket_error();
+               }
+       }
 
        return 0;
 }
@@ -963,7 +970,9 @@
                }
                else {
                        l.unlock();
-                       delete this;
+                       if (detached_) {
+                               delete this;
+                       }
                }
                return;
        }
@@ -990,6 +999,7 @@
        int triggered_errors_[WAIT_EVENTCOUNT];
 
        bool quit_{};
+       bool detached_{};
        bool in_blocking_call_{};
 };
 
@@ -1014,6 +1024,7 @@
        socket_thread_->set_socket(nullptr, l);
        if (socket_thread_->in_blocking_call_) {
                socket_thread_->quit_ = true;
+               socket_thread_->detached_ = true;
                socket_thread_->wakeup_thread(l);
                socket_thread_->thread_.detach();
                socket_thread_ = nullptr;
@@ -1977,14 +1988,14 @@
 void socket_layer::forward_socket_event(socket_event_source* source, 
socket_event_flag t, int error)
 {
        if (event_handler_) {
-               (*event_handler_)(socket_event(source, t, error));
+               event_handler_->send_event<socket_event>(source, t, error);
        }
 }
 
 void socket_layer::forward_hostaddress_event(socket_event_source* source, 
std::string const& address)
 {
        if (event_handler_) {
-               (*event_handler_)(hostaddress_event(source, address));
+               event_handler_->send_event<hostaddress_event>(source, address);
        }
 }
 
@@ -2008,4 +2019,89 @@
        scoped_lock l(socket_thread_->mutex_);
        return fd_; // Mutex as fd_ might change during connect
 }
+
+
+
+
+namespace {
+class acceptor final : public fz::event_handler
+{
+public:
+       acceptor(fz::thread_pool & pool, fz::event_loop & loop)
+               : fz::event_handler(loop)
+       {
+               l_ = std::make_unique<fz::listen_socket>(pool, this);
+               l_->bind("127.0.0.1");
+               if (l_->listen(fz::address_type::unknown)) {
+                       event_loop_.stop();
+                       return;
+               }
+
+               c_ = std::make_unique<fz::socket>(pool, this);
+               int err{};
+               if (c_->connect(fz::to_native(l_->local_ip()), 
l_->local_port(err), l_->address_family())) {
+                       event_loop_.stop();
+                       return;
+               }
+
+               add_timer(fz::duration::from_milliseconds(100), true);
+       }
+
+       ~acceptor()
+       {
+               remove_handler();
+       }
+
+       void operator()(fz::event_base const& ev)
+       {
+               fz::dispatch<fz::socket_event, fz::timer_event>(ev, this, 
&acceptor::on_socket_event, &acceptor::on_timer);
+       }
+
+       void on_socket_event(fz::socket_event_source* s, fz::socket_event_flag 
f, int err)
+       {
+               if (err) {
+                       event_loop_.stop();
+                       return;
+               }
+
+               if (s == l_.get() && f == fz::socket_event_flag::connection) {
+                       s_ = l_->accept(err, nullptr);
+                       if (connected_) {
+                               event_loop_.stop();
+                       }
+               }
+               else if (s == c_.get() && f == 
fz::socket_event_flag::connection) {
+                       connected_ = true;
+                       if (s_) {
+                               event_loop_.stop();
+                       }
+               }
+       }
+
+       void on_timer(fz::timer_id)
+       {
+               event_loop_.stop();
+       }
+
+       std::unique_ptr<fz::listen_socket> l_;
+       std::unique_ptr<fz::socket> c_;
+       std::unique_ptr<fz::socket> s_;
+       bool connected_{};
+};
+}
+
+std::optional<std::pair<std::unique_ptr<fz::socket>, 
std::unique_ptr<fz::socket>>> create_tcp_socketpair(fz::thread_pool & pool)
+{
+       fz::event_loop loop(fz::event_loop::threadless);
+       acceptor a(pool, loop);
+       loop.run();
+
+       if (a.s_ && a.connected_) {
+               a.c_->set_event_handler(nullptr);
+               return {std::make_pair(std::move(a.c_), std::move(a.s_))};
+       }
+
+       return {};
+}
+
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/thread.cpp 
new/libfilezilla-0.55.2/lib/thread.cpp
--- old/libfilezilla-0.52.0/lib/thread.cpp      2021-07-02 11:04:19.000000000 
+0200
+++ new/libfilezilla-0.55.2/lib/thread.cpp      2026-01-16 15:41:56.000000000 
+0100
@@ -3,9 +3,14 @@
 #include <cstdlib>
 #include <thread>
 
-#if defined(FZ_WINDOWS) && (defined(__MINGW32__) || defined(__MINGW64__))
-#define USE_CUSTOM_THREADS 1
+#if FZ_WINDOWS
 #include "libfilezilla/glue/windows.hpp"
+#else
+#include <unistd.h>
+#endif
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define USE_CUSTOM_THREADS 1
 #include <process.h>
 #endif
 
@@ -130,4 +135,14 @@
        delete impl_;
 }
 
+size_t processor_count()
+{
+#if FZ_WINDOWS
+       DWORD n = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
+#else
+       int n = sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+       return (n > 0) ? static_cast<size_t>(n) : size_t(1);
+}
+
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/thread_pool.cpp 
new/libfilezilla-0.55.2/lib/thread_pool.cpp
--- old/libfilezilla-0.52.0/lib/thread_pool.cpp 2022-04-01 14:35:07.000000000 
+0200
+++ new/libfilezilla-0.55.2/lib/thread_pool.cpp 2025-12-12 15:14:30.000000000 
+0100
@@ -10,6 +10,7 @@
 {
 public:
        pooled_thread_impl * thread_{};
+       condition task_cond_;
 };
 
 class pooled_thread_impl final
@@ -39,13 +40,12 @@
                                l.unlock();
                                f_();
                                l.lock();
-                               task_ = nullptr;
+                               if (task_) {
+                                       task_->task_cond_.signal(l);
+                                       task_ = nullptr;
+                               }
                                f_ = std::function<void()>();
                                pool_.idle_.emplace_back(this);
-                               if (task_waiting_) {
-                                       task_waiting_ = false;
-                                       task_cond_.signal(l);
-                               }
                        }
                }
        }
@@ -62,11 +62,8 @@
        mutex & m_;
        condition thread_cond_;
 
-       condition task_cond_;
-
        thread_pool& pool_;
 
-       bool task_waiting_{};
 private:
        bool quit_{};
 };
@@ -93,8 +90,7 @@
        if (impl_) {
                scoped_lock l(impl_->thread_->m_);
                if (impl_->thread_->task_ == impl_) {
-                       impl_->thread_->task_waiting_ = true;
-                       impl_->thread_->task_cond_.wait(l);
+                       impl_->task_cond_.wait(l);
                }
                delete impl_;
                impl_ = nullptr;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/tls_layer_impl.cpp 
new/libfilezilla-0.55.2/lib/tls_layer_impl.cpp
--- old/libfilezilla-0.52.0/lib/tls_layer_impl.cpp      2025-11-10 
15:14:41.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/tls_layer_impl.cpp      2026-03-16 
16:04:46.000000000 +0100
@@ -1626,13 +1626,9 @@
        if (!res) {
                subject = raw_subject.to_string_view();
        }
-       else {
+       else if (res != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
                if (logger) {
                        logger->log(logmsg::debug_warning, 
"gnutls_x509_crt_get_dn3 failed with %d", res);
-               }
-       }
-       if (subject.empty()) {
-               if (logger) {
                        logger->log(logmsg::error, fztranslate("Could not get 
distinguished name of certificate subject, gnutls_x509_get_dn failed"));
                }
                return false;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.52.0/lib/windows/version.rc.in 
new/libfilezilla-0.55.2/lib/windows/version.rc.in
--- old/libfilezilla-0.52.0/lib/windows/version.rc.in   2025-03-26 
11:13:17.000000000 +0100
+++ new/libfilezilla-0.55.2/lib/windows/version.rc.in   2026-03-16 
16:04:46.000000000 +0100
@@ -15,7 +15,7 @@
             VALUE "FileDescription", "libfilezilla"
             VALUE "FileVersion", "@PACKAGE_VERSION_MAJOR@, 
@PACKAGE_VERSION_MINOR@, @PACKAGE_VERSION_MICRO@, @PACKAGE_VERSION_NANO@"
             VALUE "InternalName", "libfilezilla"
-            VALUE "LegalCopyright", "Copyright (C) 2015-2025 Tim Kosse"
+            VALUE "LegalCopyright", "Copyright (C) 2015-2026 Tim Kosse"
             VALUE "OriginalFilename", "libfilezilla.dll"
             VALUE "ProductName", "libfilezilla"
             VALUE "ProductVersion", "@PACKAGE_VERSION_MAJOR@, 
@PACKAGE_VERSION_MINOR@, @PACKAGE_VERSION_MICRO@, @PACKAGE_VERSION_NANO@"

Reply via email to