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@"
