Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libupnp for openSUSE:Factory checked 
in at 2023-05-02 16:18:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libupnp (Old)
 and      /work/SRC/openSUSE:Factory/.libupnp.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libupnp"

Tue May  2 16:18:31 2023 rev:34 rq:1083840 version:1.14.17

Changes:
--------
--- /work/SRC/openSUSE:Factory/libupnp/libupnp.changes  2023-03-31 
21:15:11.702301675 +0200
+++ /work/SRC/openSUSE:Factory/.libupnp.new.1533/libupnp.changes        
2023-05-02 16:18:33.449643690 +0200
@@ -1,0 +2,7 @@
+Mon May  1 07:55:25 UTC 2023 - Jan Engelhardt <jeng...@inai.de>
+
+- Update to release 1.14.17
+  * No user-visible changes
+  * Include fuzzer and gtest in the tarball
+
+-------------------------------------------------------------------

Old:
----
  libupnp-1.14.16.tar.bz2

New:
----
  libupnp-1.14.17.tar.bz2

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

Other differences:
------------------
++++++ libupnp.spec ++++++
--- /var/tmp/diff_new_pack.rGKLnQ/_old  2023-05-02 16:18:34.001646964 +0200
+++ /var/tmp/diff_new_pack.rGKLnQ/_new  2023-05-02 16:18:34.005646987 +0200
@@ -20,7 +20,7 @@
 %define pnpver 17
 %define ixmlver 11
 Name:           libupnp
-Version:        1.14.16
+Version:        1.14.17
 Release:        0
 Summary:        An implementation of Universal Plug and Play (UPnP)
 License:        BSD-3-Clause

++++++ libupnp-1.14.16.tar.bz2 -> libupnp-1.14.17.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/ChangeLog 
new/libupnp-1.14.17/ChangeLog
--- old/libupnp-1.14.16/ChangeLog       2023-03-30 14:55:23.000000000 +0200
+++ new/libupnp-1.14.17/ChangeLog       2023-03-30 15:00:55.000000000 +0200
@@ -9,6 +9,10 @@
         Aborted.
 
 *******************************************************************************
+Version 1.14.17
+*******************************************************************************
+
+*******************************************************************************
 Version 1.14.16
 *******************************************************************************
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/Makefile.am 
new/libupnp-1.14.17/Makefile.am
--- old/libupnp-1.14.16/Makefile.am     2022-11-19 02:51:58.000000000 +0100
+++ new/libupnp-1.14.17/Makefile.am     2023-05-01 00:24:51.000000000 +0200
@@ -20,6 +20,20 @@
        cmake/options.cmake \
        cmake/post-test.cmake \
        cmake/test-functions.cmake \
+       fuzzer/FuzzIxml.c \
+       fuzzer/build.sh \
+       fuzzer/CMakeLists.txt \
+       gtest/README.md \
+       gtest/CMakeLists.txt \
+       gtest/tools \
+       gtest/tools/compile.sh \
+       gtest/tools/README \
+       gtest/tools/test_tools.cpp \
+       gtest/tools/tools.cpp \
+       gtest/test_UpnpHttpHeaderList.cpp \
+       gtest/test_template.cpp \
+       gtest/test_upnpapi.cpp \
+       gtest/TODO \
        IXML.cmake.in \
        UPNP.cmake.in \
        ixml/CMakeLists.txt \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/Makefile.in 
new/libupnp-1.14.17/Makefile.in
--- old/libupnp-1.14.16/Makefile.in     2023-03-30 14:57:59.000000000 +0200
+++ new/libupnp-1.14.17/Makefile.in     2023-05-01 00:26:48.000000000 +0200
@@ -210,7 +210,7 @@
        $(top_srcdir)/upnp/inc/upnpconfig.h.in \
        $(top_srcdir)/upnp/sample/common/config_sample.h.in COPYING \
        ChangeLog README.md THANKS build-aux/ar-lib build-aux/compile \
-       build-aux/config.guess build-aux/config.sub \
+       build-aux/config.guess build-aux/config.sub build-aux/depcomp \
        build-aux/install-sh build-aux/ltmain.sh build-aux/missing
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
@@ -401,6 +401,20 @@
        cmake/options.cmake \
        cmake/post-test.cmake \
        cmake/test-functions.cmake \
+       fuzzer/FuzzIxml.c \
+       fuzzer/build.sh \
+       fuzzer/CMakeLists.txt \
+       gtest/README.md \
+       gtest/CMakeLists.txt \
+       gtest/tools \
+       gtest/tools/compile.sh \
+       gtest/tools/README \
+       gtest/tools/test_tools.cpp \
+       gtest/tools/tools.cpp \
+       gtest/test_UpnpHttpHeaderList.cpp \
+       gtest/test_template.cpp \
+       gtest/test_upnpapi.cpp \
+       gtest/TODO \
        IXML.cmake.in \
        UPNP.cmake.in \
        ixml/CMakeLists.txt \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/configure 
new/libupnp-1.14.17/configure
--- old/libupnp-1.14.16/configure       2023-03-30 14:57:58.000000000 +0200
+++ new/libupnp-1.14.17/configure       2023-05-01 00:26:48.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for libupnp 1.14.16.
+# Generated by GNU Autoconf 2.71 for libupnp 1.14.17.
 #
 # Report bugs to <mrobe...@users.sourceforge.net>.
 #
@@ -621,8 +621,8 @@
 # Identity of this package.
 PACKAGE_NAME='libupnp'
 PACKAGE_TARNAME='libupnp'
-PACKAGE_VERSION='1.14.16'
-PACKAGE_STRING='libupnp 1.14.16'
+PACKAGE_VERSION='1.14.17'
+PACKAGE_STRING='libupnp 1.14.17'
 PACKAGE_BUGREPORT='mrobe...@users.sourceforge.net'
 PACKAGE_URL=''
 
@@ -1434,7 +1434,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 libupnp 1.14.16 to adapt to many kinds of systems.
+\`configure' configures libupnp 1.14.17 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1505,7 +1505,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libupnp 1.14.16:";;
+     short | recursive ) echo "Configuration of libupnp 1.14.17:";;
    esac
   cat <<\_ACEOF
 
@@ -1652,7 +1652,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libupnp configure 1.14.16
+libupnp configure 1.14.17
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2008,7 +2008,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libupnp $as_me 1.14.16, which was
+It was created by libupnp $as_me 1.14.17, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -2766,7 +2766,7 @@
 
 LT_VERSION_IXML=12:2:1
 
-LT_VERSION_UPNP=18:7:1
+LT_VERSION_UPNP=18:8:1
 
 
 
@@ -3288,7 +3288,7 @@
 
 # Define the identity of the package.
  PACKAGE='libupnp'
- VERSION='1.14.16'
+ VERSION='1.14.17'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -17722,7 +17722,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libupnp $as_me 1.14.16, which was
+This file was extended by libupnp $as_me 1.14.17, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -17790,7 +17790,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-libupnp config.status 1.14.16
+libupnp config.status 1.14.17
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/configure.ac 
new/libupnp-1.14.17/configure.ac
--- old/libupnp-1.14.16/configure.ac    2022-11-19 03:28:44.000000000 +0100
+++ new/libupnp-1.14.17/configure.ac    2023-03-30 15:02:26.000000000 +0200
@@ -9,7 +9,7 @@
 
 AC_PREREQ(2.60)
 
-AC_INIT([libupnp], [1.14.16], [mrobe...@users.sourceforge.net])
+AC_INIT([libupnp], [1.14.17], [mrobe...@users.sourceforge.net])
 dnl 
############################################################################
 dnl # *Independently* of the above libupnp package version, the libtool version
 dnl # of the 3 libraries need to be updated whenever there is a change 
released:
@@ -219,8 +219,18 @@
 dnl #AC_SUBST([LT_VERSION_UPNP],       [18:7:1])
 dnl #
 dnl 
############################################################################
+dnl # Release 1.14.17
+dnl # "current:revision:age"
+dnl #
+dnl # - Code has changed in upnp
+dnl #   revision: 7 -> 8
+dnl #
+dnl #AC_SUBST([LT_VERSION_IXML],       [12:2:1])
+dnl #AC_SUBST([LT_VERSION_UPNP],       [18:8:1])
+dnl #
+dnl 
############################################################################
 AC_SUBST([LT_VERSION_IXML],       [12:2:1])
-AC_SUBST([LT_VERSION_UPNP],       [18:7:1])
+AC_SUBST([LT_VERSION_UPNP],       [18:8:1])
 dnl 
############################################################################
 dnl # Repeating the algorithm to place it closer to the modificatin place:
 dnl #  - library code modified:                revision++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/docs/Doxyfile 
new/libupnp-1.14.17/docs/Doxyfile
--- old/libupnp-1.14.16/docs/Doxyfile   2022-11-19 03:29:29.000000000 +0100
+++ new/libupnp-1.14.17/docs/Doxyfile   2023-03-30 15:03:01.000000000 +0200
@@ -38,7 +38,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.14.16
+PROJECT_NUMBER         = 1.14.17
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/fuzzer/CMakeLists.txt 
new/libupnp-1.14.17/fuzzer/CMakeLists.txt
--- old/libupnp-1.14.16/fuzzer/CMakeLists.txt   1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/fuzzer/CMakeLists.txt   2022-10-08 18:11:49.000000000 
+0200
@@ -0,0 +1,2 @@
+add_executable(FuzzIxml FuzzIxml.c)
+target_link_libraries(FuzzIxml ixml_static ${LIB_FUZZING_ENGINE})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/fuzzer/FuzzIxml.c 
new/libupnp-1.14.17/fuzzer/FuzzIxml.c
--- old/libupnp-1.14.16/fuzzer/FuzzIxml.c       1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/fuzzer/FuzzIxml.c       2022-10-08 18:11:49.000000000 
+0200
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ixml.h"
+
+#define kMinInputLength 10
+#define kMaxInputLength 5120
+
+int CheckXML(char *filename){
+
+    int rc;
+    DOMString s;
+    IXML_Document *doc = NULL;
+
+    rc = ixmlLoadDocumentEx(filename, &doc);
+    if (rc != IXML_SUCCESS) {
+        return rc;
+    }
+
+    s = ixmlPrintDocument(doc);
+    if (s == NULL || s[0] == '\0') {
+        ixmlDocument_free(doc);
+        return 1;
+    }
+
+    ixmlFreeDOMString(s);
+    ixmlDocument_free(doc);
+
+    return 0;
+}
+
+extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+
+    if (Size < kMinInputLength || Size > kMaxInputLength){
+        return 1;
+    }
+    
+    int ret;
+    char filename[256];
+
+    sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+    FILE *fp = fopen(filename, "wb");
+    if (!fp) {
+        return 0;
+    }
+
+    fwrite(Data, Size, 1, fp);
+    fclose(fp);
+
+    ret = CheckXML(filename);
+    unlink(filename);
+    return ret;
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/fuzzer/build.sh 
new/libupnp-1.14.17/fuzzer/build.sh
--- old/libupnp-1.14.16/fuzzer/build.sh 1970-01-01 01:00:00.000000000 +0100
+++ new/libupnp-1.14.17/fuzzer/build.sh 2022-10-08 18:11:49.000000000 +0200
@@ -0,0 +1,39 @@
+#!/bin/bash -eu
+
+build(){
+    export CFLAGS="$1"
+    export CXXFLAGS="$1"
+    export LIB_FUZZING_ENGINE=-fsanitize=fuzzer
+
+    mkdir build && cd build/
+    cmake -DFUZZER=ON -DLIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" ../../.
+    make -j$(nproc)
+
+    cd fuzzer/
+
+    mkdir FuzzIxml_corpus
+    mkdir FuzzIxml_seed_corpus
+
+    cp ../../../ixml/test/testdata/empty_attribute.xml FuzzIxml_seed_corpus/
+}
+
+run(){
+    DIR=build/fuzzer
+    ./$DIR/FuzzIxml   $DIR/FuzzIxml_corpus/   $DIR/FuzzIxml_seed_corpus/
+}
+
+if [ $1 == "ASan" ]
+then
+   build "-O1 -fno-omit-frame-pointer -gline-tables-only 
-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address 
-fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link"
+elif [ "$1" == "UBSan" ]
+then
+   build "-O1 -fno-omit-frame-pointer -gline-tables-only 
-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 
-fsanitize=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr
 
-fno-sanitize-recover=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr
 -fsanitize=fuzzer-no-link"
+elif [ "$1" == "MSan" ]
+then
+   build "-O1 -fno-omit-frame-pointer -gline-tables-only 
-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory 
-fsanitize-memory-track-origins -fsanitize=fuzzer-no-link"
+elif [ "$1" == "Run" ]
+then
+   run
+else
+  echo "use: ./$0 ASan | UBSan | MSan | Run"
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/CMakeLists.txt 
new/libupnp-1.14.17/gtest/CMakeLists.txt
--- old/libupnp-1.14.16/gtest/CMakeLists.txt    1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/gtest/CMakeLists.txt    2022-08-03 16:14:24.000000000 
+0200
@@ -0,0 +1,15 @@
+include (GoogleTest)
+
+UPNP_addGTest (test_template test_template.cpp
+       ADDITIONAL_INCLUDE_DIRS 
${CMAKE_CURRENT_SOURCE_DIR}/../upnp/src/threadutil/
+)
+
+#UPNP_addGTest (test_UpnpHttpHeaderList test_UpnpHttpHeaderList.cpp
+#      ADDITIONAL_INCLUDE_DIRS 
${CMAKE_CURRENT_SOURCE_DIR}/../upnp/src/threadutil/
+#)
+
+#if (NOT WIN32)
+#      UPNP_addGTest (test_upnpapi test_upnpapi.cpp
+#              ADDITIONAL_INCLUDE_DIRS 
${CMAKE_CURRENT_SOURCE_DIR}/../upnp/src/threadutil/
+#      )
+#endif()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/README.md 
new/libupnp-1.14.17/gtest/README.md
--- old/libupnp-1.14.16/gtest/README.md 1970-01-01 01:00:00.000000000 +0100
+++ new/libupnp-1.14.17/gtest/README.md 2022-08-03 16:14:24.000000000 +0200
@@ -0,0 +1,32 @@
+## Compile and run tests
+
+To be able to compile a test you have to add an entry in the local
+`./CMakeLists.txt`. You can copy the entry for the `test_template.cpp` and
+modify the filenames to your test files. Then you can compile the tests in the
+local gtest directory with:
+
+    cmake --build .
+
+Then you can run the tests, for example with:
+
+    ./test_template-static
+
+If the output is messed up with logging information from the library,
+redirect stderr to /dev/null:
+
+    ./test_upnpapi-static 2>/dev/null
+
+## Skip tests on Github Workflow Actions
+
+It is possible that you have tests which are failing because fixing the bug it
+is showing takes some time. To be able to push bug fixes and create pull
+requests you can skip tests if they run on the Github Workflow as Action. The
+test checks if the environment variable `GITHUB_ACTIONS` exists and will then
+skip the test. An example for this conditional check you can find in the
+test_template.cpp. If you want to see what tests are skipped on Github Actions
+you can execute the test for example with:
+
+    GITHUB_ACTIONS="true" ./test_template-static
+
+<br />
+// Last modified: 2021-04-06
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/TODO 
new/libupnp-1.14.17/gtest/TODO
--- old/libupnp-1.14.16/gtest/TODO      1970-01-01 01:00:00.000000000 +0100
+++ new/libupnp-1.14.17/gtest/TODO      2022-08-03 16:14:24.000000000 +0200
@@ -0,0 +1,33 @@
+// Author: 2021-03-26 - Ingo Höft
+
+General
+-------
+* Make tests running on new library interface with UpnpLib structure
+    finished 2021-03-25
+* Running tests on the shared libupnp library
+    finished 2021-04-02
+* Replace compile.sh scripts with scripts for cmake if useful
+    finished 2021-04-02
+* Make available tests more specific with Matchers and Actions
+
+IPv4 Gtests for the Unix platform
+---------------------------------
+* First gtest for UpnpGetIfInfo
+    finished 2021-03-07
+* First gtest for UpnpInit2
+    finished 2021-03-16
+* First gtest for StartMiniServer
+* First gtest for StopMiniServer
+* First gtest for UpnpEnableWebserver
+
+Gtests for other platforms
+--------------------------
+* Make IPv4 tests running for MS Windows
+
+IPv6 Gtests for the Unix platform
+---------------------------------
+* First gtest for UpnpGetIfInfo
+* First gtest for UpnpInit2
+* First gtest for StartMiniServer
+* First gtest for StopMiniServer
+* First gtest for UpnpEnableWebserver
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/test_UpnpHttpHeaderList.cpp 
new/libupnp-1.14.17/gtest/test_UpnpHttpHeaderList.cpp
--- old/libupnp-1.14.16/gtest/test_UpnpHttpHeaderList.cpp       1970-01-01 
01:00:00.000000000 +0100
+++ new/libupnp-1.14.17/gtest/test_UpnpHttpHeaderList.cpp       2022-08-03 
16:14:24.000000000 +0200
@@ -0,0 +1,157 @@
+#include "LinkedList.h"
+#include "UpnpHttpHeaders.h"
+#include "httpparser.h"
+#include "list.h"
+
+#include "gtest/gtest.h"
+#include <array>
+#include <utility>
+
+class HttpHeaderList : public ::testing::Test
+{
+protected:
+        http_message_t msg;
+        UpnpListHead header_list;
+
+        HttpHeaderList()
+        {
+                UpnpListInit(&header_list);
+                ListInit(&msg.headers, nullptr, [](void *elem) {
+                        auto *hdr = static_cast<http_header_t *>(elem);
+
+                        membuffer_destroy(&hdr->name_buf);
+                        membuffer_destroy(&hdr->value);
+                        free(hdr);
+                });
+        }
+
+        ~HttpHeaderList() override
+        {
+                free_http_headers_list(&header_list);
+                ListDestroy(&msg.headers, true);
+        }
+
+        void AddHeader(const char name[], const char value[]) noexcept
+        {
+                auto *hdr = static_cast<http_header_t *>(
+                        calloc(1, sizeof(http_header_t)));
+
+                membuffer_assign_str(&hdr->name_buf, name);
+                hdr->name = memptr{hdr->name_buf.buf, hdr->name_buf.length};
+
+                membuffer_assign_str(&hdr->value, value);
+
+                ListAddTail(&msg.headers, hdr);
+        }
+
+        using HttpHeadersPtr = std::unique_ptr<UpnpHttpHeaders,
+                decltype(&UpnpHttpHeaders_delete)>;
+        static HttpHeadersPtr MakeUpnpHttpHeaderList()
+        {
+                return {UpnpHttpHeaders_new(), &UpnpHttpHeaders_delete};
+        }
+};
+
+TEST_F(HttpHeaderList, Empty)
+{
+        httpmsg_list_headers(&msg, &header_list);
+
+        const UpnpListIter begin = UpnpListBegin(&header_list);
+        ASSERT_EQ(UpnpListNext(&header_list, begin), 
UpnpListEnd(&header_list));
+}
+
+TEST_F(HttpHeaderList, OneElement)
+{
+        AddHeader("foo", "bar");
+
+        httpmsg_list_headers(&msg, &header_list);
+
+        const UpnpListIter begin = UpnpListBegin(&header_list);
+
+        const auto *header = reinterpret_cast<UpnpHttpHeaders *>(begin);
+        ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "foo");
+        ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "bar");
+        ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr);
+
+        ASSERT_EQ(UpnpListNext(&header_list, begin), 
UpnpListEnd(&header_list));
+}
+
+TEST_F(HttpHeaderList, OneElementMixedCase)
+{
+        AddHeader("USER-AGENT", "Linux");
+
+        httpmsg_list_headers(&msg, &header_list);
+
+        const UpnpListIter begin = UpnpListBegin(&header_list);
+
+        const auto *header = reinterpret_cast<UpnpHttpHeaders *>(begin);
+        ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "USER-AGENT");
+        ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "Linux");
+        ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr);
+
+        ASSERT_EQ(UpnpListNext(&header_list, begin), 
UpnpListEnd(&header_list));
+}
+
+TEST_F(HttpHeaderList, TwoElements)
+{
+        AddHeader("USER-AGENT", "Darwin");
+        AddHeader("Connection", "close");
+
+        httpmsg_list_headers(&msg, &header_list);
+
+        const UpnpListIter first = UpnpListBegin(&header_list);
+
+        const auto *header = reinterpret_cast<UpnpHttpHeaders *>(first);
+        ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "USER-AGENT");
+        ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "Darwin");
+        ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr);
+
+        const UpnpListIter second = UpnpListNext(&header_list, first);
+        ASSERT_NE(second, UpnpListEnd(&header_list));
+
+        header = reinterpret_cast<UpnpHttpHeaders *>(second);
+        ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "Connection");
+        ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "close");
+        ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr);
+}
+
+TEST_F(HttpHeaderList, PlentyElements)
+{
+        /* clang-format off */
+        static const std::array<std::pair<const char *, const char *>, 7> 
elems{{
+                {"USER-AGENT", "Darwin"},
+                {"Connection", "close"},
+                {"content-type", "text"},
+                {"pragma", "no-cache"},
+                {"pragma", "no-cache"},
+                {"CACHE-control", "no-CACHE"},
+                {"Accept-Encoding", "gzip"}
+        }};
+        /* clang-format on */
+
+        for (const auto &elem : elems) {
+                AddHeader(elem.first, elem.second);
+        }
+
+        httpmsg_list_headers(&msg, &header_list);
+
+        const UpnpListIter begin = UpnpListBegin(&header_list);
+
+        auto idx = 0;
+        for (auto it = begin; it != UpnpListEnd(&header_list);
+                it = UpnpListNext(begin, it), ++idx) {
+                const auto *header = reinterpret_cast<UpnpHttpHeaders *>(it);
+                ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header),
+                        elems[idx].first);
+                ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header),
+                        elems[idx].second);
+                ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr);
+        }
+        ASSERT_EQ(idx, elems.size());
+}
+
+int main(int argc, char **argv)
+{
+        ::testing::InitGoogleTest(&argc, argv);
+        return RUN_ALL_TESTS();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/test_template.cpp 
new/libupnp-1.14.17/gtest/test_template.cpp
--- old/libupnp-1.14.16/gtest/test_template.cpp 1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/gtest/test_template.cpp 2022-08-03 16:14:24.000000000 
+0200
@@ -0,0 +1,88 @@
+// This test should always run, reporting no failure
+// Author: 2021-03-06 - Ingo Höft
+// Last modified: 2021-04-06
+
+#include "gtest/gtest.h"
+
+// for TestSuites linked against the static C library
+extern "C" {
+       //#include "upnp.h"
+}
+
+// two macros to compare values in a range
+#define EXPECT_IN_RANGE(VAL, MIN, MAX) \
+       EXPECT_GE((VAL), (MIN));                        \
+       EXPECT_LE((VAL), (MAX))
+
+#define ASSERT_IN_RANGE(VAL, MIN, MAX) \
+       ASSERT_GE((VAL), (MIN));                        \
+       ASSERT_LE((VAL), (MAX))
+
+
+// simple testsuite without fixtures
+//----------------------------------
+TEST(EmptyTestSuite, empty_gtest)
+{
+       //GTEST_SKIP();
+       //GTEST_SKIP_("to show this feature");
+
+       // SKIP on Github Actions
+#ifdef _WIN32
+       char* github_action;
+       size_t len;
+       _dupenv_s(&github_action, &len, "GITHUB_ACTIONS");
+#else
+       char *github_action = std::getenv("GITHUB_ACTIONS");
+#endif
+       if(github_action) { GTEST_SKIP()
+               << "  to show this feature";
+       }
+}
+
+
+// testsuite with fixtures
+//------------------------
+class EmptyFixtureTestSuite : public ::testing::Test
+{
+       protected:
+       // You can remove any or all of the following functions if their bodies 
would
+       // be empty.
+
+       EmptyFixtureTestSuite()
+       {
+               // You can do set-up work for each test here.
+       }
+
+       ~EmptyFixtureTestSuite() override
+       {
+               // You can do clean-up work that doesn't throw exceptions here.
+       }
+
+               // If the constructor and destructor are not enough for setting 
up
+               // and cleaning up each test, you can define the following 
methods:
+
+       void SetUp() override
+       {
+               // Code here will be called immediately after the constructor 
(right
+               // before each test). Have attention to the uppercase 'U' of 
SetUp().
+       }
+
+       void TearDown() override
+       {
+               // Code here will be called immediately after each test (right
+               // before the destructor).
+       }
+
+       // Class members declared here can be used by all tests in the test 
suite
+       // for Foo.
+};
+
+TEST_F(EmptyFixtureTestSuite, empty_gtest_with_fixture)
+{
+}
+
+
+int main(int argc, char **argv) {
+       ::testing::InitGoogleTest(&argc, argv);
+       return RUN_ALL_TESTS();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/test_upnpapi.cpp 
new/libupnp-1.14.17/gtest/test_upnpapi.cpp
--- old/libupnp-1.14.16/gtest/test_upnpapi.cpp  1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/gtest/test_upnpapi.cpp  2022-08-03 16:14:24.000000000 
+0200
@@ -0,0 +1,326 @@
+// Mock network interfaces
+// For further information look at https://stackoverflow.com/a/66498073/5014688
+// Author: 2021-03-06 - Ingo Höft
+// Last modified: 2021-04-06
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "upnpapi.h"
+#include "upnptools.h"
+#include "tools/tools.cpp"
+#include "UpnpLib.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::SetArgPointee;
+using ::testing::AtLeast;
+
+
+// --- mock getifaddrs -------------------------------------
+class MockGetifaddrs {
+public:
+    MOCK_METHOD(int, getifaddrs, (struct ifaddrs**));
+};
+
+MockGetifaddrs* ptrMockGetifaddrsObj = nullptr;
+int getifaddrs(struct ifaddrs** ifap) {
+    return ptrMockGetifaddrsObj->getifaddrs(ifap);
+}
+
+// --- mock freeifaddrs ------------------------------------
+class MockFreeifaddrs {
+public:
+    MOCK_METHOD(void, freeifaddrs, (struct ifaddrs*));
+};
+
+MockFreeifaddrs* ptrMockFreeifaddrObj = nullptr;
+void freeifaddrs(struct ifaddrs* ifap) {
+    return ptrMockFreeifaddrObj->freeifaddrs(ifap);
+}
+
+// --- mock bind -------------------------------------------
+class MockBind {
+public:
+    MOCK_METHOD(int, bind, (int, const struct sockaddr*, socklen_t));
+};
+
+MockBind* ptrMockBindObj = nullptr;
+int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen) {
+    return ptrMockBindObj->bind(sockfd, addr, addrlen);
+}
+
+// --- mock if_nametoindex ---------------------------------
+class MockIf_nametoindex {
+public:
+    MOCK_METHOD(unsigned int, if_nametoindex, (const char*));
+};
+
+MockIf_nametoindex* ptrMockIf_nametoindexObj = nullptr;
+unsigned int if_nametoindex(const char* ifname) {
+    return ptrMockIf_nametoindexObj->if_nametoindex(ifname);
+}
+
+// --- mock listen -----------------------------------------
+class MockListen {
+public:
+    MOCK_METHOD(int, listen, (int, int));
+};
+
+MockListen* ptrMockListenObj = nullptr;
+int listen(int sockfd, int backlog) {
+    return ptrMockListenObj->listen(sockfd, backlog);
+}
+
+// --- mock select -----------------------------------------
+class MockSelect {
+public:
+    MOCK_METHOD(int, select, (int nfds, fd_set* readfds, fd_set* writefds,
+                              fd_set *exceptfds, struct timeval* timeout));
+};
+
+MockSelect* ptrMockSelectObj = nullptr;
+int select(int nfds, fd_set* readfds, fd_set* writefds,
+           fd_set* exceptfds, struct timeval* timeout) {
+    return ptrMockSelectObj->select(nfds, readfds, writefds,
+                                    exceptfds, timeout);
+}
+
+// --- mock accept -----------------------------------------
+class MockAccept {
+public:
+    MOCK_METHOD(int, accept, (int sockfd, struct sockaddr* addr,
+                              socklen_t* addrlen));
+};
+
+MockAccept* ptrMockAcceptObj = nullptr;
+int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen) {
+    return ptrMockAcceptObj->accept(sockfd, addr, addrlen);
+}
+
+// --- mock getsockname ------------------------------------
+// If needed
+
+
+// --- mock setsockopt--------------------------------------
+class MockSetsockopt {
+public:
+    MOCK_METHOD(int, setsockopt, (int sockfd, int level, int optname,
+                                  const void* optval, socklen_t optlen));
+};
+
+MockSetsockopt* ptrMockSetsockoptObj = nullptr;
+int setsockopt(int sockfd, int level, int optname, const void* optval,
+               socklen_t optlen) {
+    return ptrMockSetsockoptObj->setsockopt(sockfd, level, optname,
+                                            optval, optlen);
+}
+
+
+// UpnpApi Testsuite for IP4
+//==========================
+class UpnpApiIPv4TestSuite: public ::testing::Test
+// Fixtures for this Testsuite
+{
+protected:
+    unsigned short PORT = 51515;
+
+    // Instantiate the mock objects.
+    // The global pointer to them are set in the constructor below.
+    MockGetifaddrs mockGetifaddrsObj;
+    MockFreeifaddrs mockFreeifaddrsObj;
+    MockBind mockBindObj;
+    MockIf_nametoindex mockIf_nametoindexObj;
+    MockListen mockListenObj;
+    MockSelect mockSelectObj;
+    MockAccept mockAcceptObj;
+    MockSetsockopt mockSetsockoptObj;
+
+    UpnpApiIPv4TestSuite()
+    {
+        // set the global pointer to the mock objects
+        ptrMockGetifaddrsObj = &mockGetifaddrsObj;
+        ptrMockFreeifaddrObj = &mockFreeifaddrsObj;
+        ptrMockBindObj = &mockBindObj;
+        ptrMockIf_nametoindexObj = &mockIf_nametoindexObj;
+        ptrMockListenObj = &mockListenObj;
+        ptrMockSelectObj = &mockSelectObj;
+        ptrMockAcceptObj = &mockAcceptObj;
+        ptrMockSetsockoptObj = &mockSetsockoptObj;
+    }
+};
+
+
+TEST_F(UpnpApiIPv4TestSuite, UpnpGetIfInfo_called_with_valid_interface)
+{
+    // SKIP on Github Actions
+    char* github_action = std::getenv("GITHUB_ACTIONS");
+    if(github_action) { GTEST_SKIP()
+        << "  due to issues with googlemock";
+    }
+
+    // provide a network interface
+    struct ifaddrs* ifaddr = nullptr;
+    CIfaddr4 ifaddr4Obj;
+    ifaddr4Obj.set("if0v4", "192.168.99.3/11");
+    ifaddr = ifaddr4Obj.get();
+
+    EXPECT_CALL(mockGetifaddrsObj, getifaddrs(_))
+        .WillOnce(DoAll(SetArgPointee<0>(ifaddr), Return(0)));
+    EXPECT_CALL(mockFreeifaddrsObj, freeifaddrs(ifaddr))
+        .Times(1);
+    EXPECT_CALL(mockIf_nametoindexObj, if_nametoindex(_))
+        .WillOnce(Return(2));
+
+    UpnpLib* p = UpnpLib_new();
+
+    EXPECT_STREQ(UpnpGetErrorMessage(
+                  UpnpGetIfInfo(p, "if0v4")),
+                  "UPNP_E_SUCCESS");
+
+    // gIF_NAME mocked with getifaddrs above
+    EXPECT_EQ(*UpnpLib_get_gIF_NAME(p), *&"if0v4");
+    // gIF_IPV4 mocked with getifaddrs above
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV4(p), *&"192.168.99.3");
+    //EXPECT_THAT(gIF_IPV4, 
MatchesRegex("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"));
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV4_NETMASK(p), *&"255.224.0.0");
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV6(p), *&"");
+    EXPECT_EQ(UpnpLib_get_gIF_IPV6_PREFIX_LENGTH(p), (unsigned)0);
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV6_ULA_GUA(p), *&"");
+    EXPECT_EQ(UpnpLib_get_gIF_IPV6_ULA_GUA_PREFIX_LENGTH(p), (unsigned)0);
+    // index mocked with if_nametoindex above
+    EXPECT_EQ(UpnpLib_get_gIF_INDEX(p), (unsigned)2);
+    EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V4(p), (unsigned short)0);
+    EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6(p), (unsigned short)0);
+    EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6_ULA_GUA(p), (unsigned short)0);
+
+    UpnpLib_delete(p);
+}
+
+
+TEST_F(UpnpApiIPv4TestSuite, UpnpGetIfInfo_called_with_unknown_interface)
+{
+    // SKIP on Github Actions
+    char* github_action = std::getenv("GITHUB_ACTIONS");
+    if(github_action) { GTEST_SKIP()
+        << "  due to issues with googlemock";
+    }
+
+//    GTEST_SKIP() << "due to failed github sanity check because of issue 
#247.\n"
+//                 << "Comment GTEST_SKIP() in the TestSuite to enable this 
test.";
+
+    // provide a network interface
+    struct ifaddrs* ifaddr = nullptr;
+    CIfaddr4 ifaddr4Obj;
+    ifaddr4Obj.set("eth0", "192.168.77.48/22");
+    ifaddr = ifaddr4Obj.get();
+
+    EXPECT_CALL(mockGetifaddrsObj, getifaddrs(_))
+        .WillOnce(DoAll(SetArgPointee<0>(ifaddr), Return(0)));
+    EXPECT_CALL(mockFreeifaddrsObj, freeifaddrs(ifaddr))
+        .Times(1);
+    EXPECT_CALL(mockIf_nametoindexObj, if_nametoindex(_))
+        .Times(0);
+
+    UpnpLib* p = UpnpLib_new();
+
+    EXPECT_STREQ(UpnpGetErrorMessage(
+                  UpnpGetIfInfo(p, "ethO")),
+                  "UPNP_E_INVALID_INTERFACE");
+
+    // gIF_NAME mocked with getifaddrs above
+    EXPECT_EQ(*UpnpLib_get_gIF_NAME(p), *&"")
+        << "ATTENTION! There is a wrong upper case 'O', not zero in \"ethO\"";
+    // gIF_IPV4 mocked with getifaddrs above
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV4(p), *&"");
+    //EXPECT_THAT(gIF_IPV4, 
MatchesRegex("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"));
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV4_NETMASK(p), *&"");
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV6(p), *&"");
+    EXPECT_EQ(UpnpLib_get_gIF_IPV6_PREFIX_LENGTH(p), (unsigned)0);
+    EXPECT_EQ(*UpnpLib_get_gIF_IPV6_ULA_GUA(p), *&"");
+    EXPECT_EQ(UpnpLib_get_gIF_IPV6_ULA_GUA_PREFIX_LENGTH(p), (unsigned)0);
+    // index mocked with if_nametoindex above
+    EXPECT_EQ(UpnpLib_get_gIF_INDEX(p), (unsigned)4294967295)
+                          << "    Which is: (unsigned)-1";
+    EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V4(p), (unsigned short)0);
+    EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6(p), (unsigned short)0);
+    EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6_ULA_GUA(p), (unsigned short)0);
+
+    UpnpLib_delete(p);
+}
+
+
+TEST_F(UpnpApiIPv4TestSuite, initialize_default_UpnpInit2)
+{
+    // SKIP on Github Actions
+    char* github_action = std::getenv("GITHUB_ACTIONS");
+    if(github_action) { GTEST_SKIP()
+        << "  due to failed github sanity check because of issue #272";
+    }
+
+    // provide a network interface
+    struct ifaddrs* ifaddr = nullptr;
+    CIfaddr4 ifaddr4Obj;
+    ifaddr4Obj.set("if0v4", "192.168.99.3/20");
+    ifaddr = ifaddr4Obj.get();
+
+    // expect calls to system functions (which are mocked)
+    EXPECT_CALL(mockGetifaddrsObj, getifaddrs(_))
+        .WillOnce(DoAll(SetArgPointee<0>(ifaddr), Return(0)));
+    EXPECT_CALL(mockFreeifaddrsObj, freeifaddrs(ifaddr))
+        .Times(1); EXPECT_CALL(mockBindObj, bind(_,_,_))
+        .Times(5);
+    EXPECT_CALL(mockIf_nametoindexObj, if_nametoindex(_))
+        .Times(1);
+    EXPECT_CALL(mockListenObj, listen(_,_))
+        .Times(3);
+    EXPECT_CALL(mockSelectObj, select(_,_,_,_,_))
+//        .Times(7);
+        .Times(AtLeast(1));
+    EXPECT_CALL(mockAcceptObj, accept(_,_,_))
+        .Times(3);
+    EXPECT_CALL(mockSetsockoptObj, setsockopt(_,_,_,_,_))
+        .Times(11);
+
+    UpnpLib* libStruct = nullptr;
+
+    // Initialize capturing of the stderr output
+    CCaptureFd captFdObj;
+    captFdObj.capture(2);   // 1 = stdout, 2 = stderr
+
+    EXPECT_STREQ(UpnpGetErrorMessage(
+                  UpnpInit2(&libStruct, NULL, 0, NULL)),
+                  "UPNP_E_SUCCESS");
+
+    EXPECT_FALSE(captFdObj.print(std::cerr))
+        << "Output to stderr is true. There should not be any output to 
stderr";
+
+    UpnpLib_delete(libStruct);
+}
+
+
+// UpnpApi common Testsuite
+//-------------------------
+TEST(UpnpApiTestSuite, get_handle_info)
+{
+    UpnpLib* p = UpnpLib_new();
+
+    Handle_Info **HndInfo = 0;
+    EXPECT_EQ(GetHandleInfo(p, 0, HndInfo), HND_INVALID);
+    EXPECT_EQ(GetHandleInfo(p, 1, HndInfo), HND_INVALID);
+
+    UpnpLib_delete(p);
+}
+
+TEST(UpnpApiTestSuite, get_error_message)
+{
+    EXPECT_STREQ(UpnpGetErrorMessage(0), "UPNP_E_SUCCESS");
+    EXPECT_STREQ(UpnpGetErrorMessage(-121), "UPNP_E_INVALID_INTERFACE");
+    EXPECT_STREQ(UpnpGetErrorMessage(1), "Unknown error code");
+}
+
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/README 
new/libupnp-1.14.17/gtest/tools/README
--- old/libupnp-1.14.16/gtest/tools/README      1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/gtest/tools/README      2022-08-03 16:14:24.000000000 
+0200
@@ -0,0 +1,4 @@
+// Author: 2021-03-17 - Ingo Höft
+
+Additional helper programs to initialize and improve tests.
+You can compile it with ./compile.sh test_tools.cpp.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/compile.sh 
new/libupnp-1.14.17/gtest/tools/compile.sh
--- old/libupnp-1.14.16/gtest/tools/compile.sh  1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/gtest/tools/compile.sh  2022-08-03 16:14:24.000000000 
+0200
@@ -0,0 +1,27 @@
+#!/usr/bin/bash
+
+if [ "$#" -ne 1 ]; then
+    >&2 echo "Compile with: $0 test_tools.cpp"
+    >&2 echo 'Set BUILD_DIR to point to the pupnp build directory'
+fi
+
+BUILD_DIR="../.."
+
+TESTNAME=$(/usr/bin/basename -s.cpp "$1")
+/usr/bin/g++ -std=c++11 -pedantic-errors -Wall \
+-o"$TESTNAME".a \
+-I"$BUILD_DIR"/_deps/googletest-src/googletest/include \
+-I"$BUILD_DIR"/_deps/googletest-src/googlemock/include \
+-I"$BUILD_DIR" \
+-I"$BUILD_DIR"/upnp/src \
+-I"$BUILD_DIR"/upnp/inc \
+-I"$BUILD_DIR"/upnp/src/inc \
+-I"$BUILD_DIR"/upnp/src/threadutil \
+-I"$BUILD_DIR"/ixml/inc \
+-DUPNP_ENABLE_IPV6 \
+"$1" \
+"$BUILD_DIR"/lib/libgtestd.a \
+"$BUILD_DIR"/lib/libgmockd.a \
+"$BUILD_DIR"/upnp/libupnp.a \
+"$BUILD_DIR"/ixml/libixml.a \
+-lpthread
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/test_tools.cpp 
new/libupnp-1.14.17/gtest/tools/test_tools.cpp
--- old/libupnp-1.14.16/gtest/tools/test_tools.cpp      1970-01-01 
01:00:00.000000000 +0100
+++ new/libupnp-1.14.17/gtest/tools/test_tools.cpp      2022-08-03 
16:14:24.000000000 +0200
@@ -0,0 +1,77 @@
+// Testing the tools, of course ;-)
+// Author: 2021-03-12 - Ingo Höft
+
+#include "gtest/gtest.h"
+#include "tools.cpp"
+
+TEST(ToolsTestSuite, initializing_interface_addresses)
+{
+       struct ifaddrs* ifaddr = nullptr;
+       struct sockaddr_in* ifa_addr_in = nullptr;
+       struct sockaddr_in* ifa_netmask_in = nullptr;
+       struct sockaddr_in* ifa_ifu_in = nullptr;
+
+       CIfaddr4 ifaddr4Obj;
+       ifaddr = ifaddr4Obj.get();
+
+       EXPECT_EQ(ifaddr->ifa_next, nullptr);
+       EXPECT_STREQ(ifaddr->ifa_name, "lo");
+       EXPECT_EQ(ifaddr->ifa_flags, (const unsigned int)0 | IFF_LOOPBACK | 
IFF_UP);
+       ifa_addr_in = (sockaddr_in*)ifaddr->ifa_addr;
+       EXPECT_EQ(ifa_addr_in->sin_family, AF_INET);
+       EXPECT_EQ(ifa_addr_in->sin_addr.s_addr, (const unsigned int)16777343);
+       ifa_netmask_in = (sockaddr_in*)ifaddr->ifa_netmask;
+       EXPECT_EQ(ifa_netmask_in->sin_family, AF_INET);
+       EXPECT_EQ(ifa_netmask_in->sin_addr.s_addr, (const unsigned int)255);
+       ifa_ifu_in = (sockaddr_in*)ifaddr->ifa_broadaddr;
+       EXPECT_EQ(ifa_ifu_in->sin_family, AF_INET);
+       EXPECT_EQ(ifa_ifu_in->sin_addr.s_addr, (const unsigned int)0);
+       EXPECT_EQ(ifaddr->ifa_data, nullptr);
+
+       EXPECT_TRUE(ifaddr4Obj.set("if0v4", "192.168.168.168/20"));
+       EXPECT_STREQ(ifaddr->ifa_name, "if0v4");
+       EXPECT_EQ(ifa_addr_in->sin_addr.s_addr, (const unsigned int)2829625536);
+       EXPECT_EQ(ifa_netmask_in->sin_addr.s_addr, (const unsigned 
int)15794175);
+       EXPECT_EQ(ifaddr->ifa_flags, (const unsigned int)0 | IFF_UP | 
IFF_BROADCAST | IFF_MULTICAST);
+       char broadcast_address[INET_ADDRSTRLEN];
+       inet_ntop(AF_INET, &ifa_ifu_in->sin_addr.s_addr, broadcast_address, 
INET_ADDRSTRLEN);
+       EXPECT_STREQ(broadcast_address, "192.168.175.255");
+
+       EXPECT_TRUE(ifaddr4Obj.set("if1v4", "10.168.168.200"));
+       EXPECT_EQ(ifa_addr_in->sin_addr.s_addr, (const unsigned int)3366496266);
+       EXPECT_EQ(ifa_netmask_in->sin_addr.s_addr, (const unsigned 
int)4294967295);
+       EXPECT_EQ(ifaddr->ifa_flags, (const unsigned int)0 | IFF_UP | 
IFF_BROADCAST | IFF_MULTICAST);
+       inet_ntop(AF_INET, &ifa_ifu_in->sin_addr.s_addr, broadcast_address, 
INET_ADDRSTRLEN);
+       EXPECT_STREQ(broadcast_address, "10.168.168.200");
+
+       //EXPECT_TRUE(ifaddr4Obj.set("if0v4", "10.168.168.200/"));
+       //EXPECT_ANY_THROW(std::__cxx11::stoi(""));
+}
+
+
+TEST(ToolsTestSuite, capture_output)
+{
+       CCaptureFd captFdObj;
+       captFdObj.capture(2);   // 1 = stdout, 2 = stderr
+       std::cerr << "1: output 1 to stderr captured\n";
+       std::cerr << "2: output 1 to stderr captured\n";
+       EXPECT_TRUE(captFdObj.print(std::cerr));
+       std::cerr << "output 1 to stderr\n";
+
+       captFdObj.capture(2);
+       EXPECT_FALSE(captFdObj.print(std::cerr));
+       captFdObj.capture(2);
+       std::cerr << "1: output 2 to stderr captured\n";
+       EXPECT_TRUE(captFdObj.print(std::cout));
+       std::cerr << "output 2 to stderr\n";
+       captFdObj.capture(2);
+       // nothing captured
+       EXPECT_FALSE(captFdObj.print(std::cerr));
+       std::cerr << "output 3 to stderr\n";
+}
+
+
+int main(int argc, char **argv) {
+       ::testing::InitGoogleTest(&argc, argv);
+       return RUN_ALL_TESTS();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/tools.cpp 
new/libupnp-1.14.17/gtest/tools/tools.cpp
--- old/libupnp-1.14.16/gtest/tools/tools.cpp   1970-01-01 01:00:00.000000000 
+0100
+++ new/libupnp-1.14.17/gtest/tools/tools.cpp   2022-08-03 16:14:24.000000000 
+0200
@@ -0,0 +1,178 @@
+// Tools and helper classes to manage gtests
+// Author: 2021-03-12 - Ingo Höft
+
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <iostream>
+#include <fstream>
+#include <fcntl.h>
+
+
+class CIfaddr4
+// Tool to manage and fill a socket address structure. This is needed
+// for mocked network interfaces.
+{
+       struct sockaddr_in ifa_addr;    // network address
+       struct sockaddr_in ifa_netmask; // netmask
+       struct sockaddr_in ifa_ifu;             // broadcast addr or 
point-to-point dest addr
+       struct ifaddrs ifaddr;
+
+       // the bitmask is the offset in the netmasks array.
+       std::string netmasks[33] = {"0.0.0.0",
+                       "128.0.0.0", "192.0.0.0", "224.0.0.0", "240.0.0.0",
+                       "248.0.0.0", "252.0.0.0", "254.0.0.0", "255.0.0.0",
+                       "255.128.0.0", "255.192.0.0", "255.224.0.0", 
"255.240.0.0",
+                       "255.248.0.0", "255.252.0.0", "255.254.0.0", 
"255.255.0.0",
+                       "255.255.128.0", "255.255.192.0", "255.255.224.0", 
"255.255.240.0",
+                       "255.255.248.0", "255.255.252.0", "255.255.254.0", 
"255.255.255.0",
+                       "255.255.255.128", "255.255.255.192", 
"255.255.255.224", "255.255.255.240",
+                       "255.255.255.248", "255.255.255.252", 
"255.255.255.254", "255.255.255.255"};
+public:
+       CIfaddr4()
+       // With constructing the object you get a loopback device by default.
+       {
+               // loopback interface
+               //-------------------
+               // set network address
+               ifa_addr.sin_family = AF_INET;
+               //ifa_addr.sin_port = htons(MYPORT);
+               inet_aton("127.0.0.1", &(ifa_addr.sin_addr));
+
+               // set netmask
+               ifa_netmask.sin_family = AF_INET;
+               //ifa_netmask.sin_port = htons(MYPORT);
+               inet_aton("255.0.0.0", &(ifa_netmask.sin_addr));
+
+               // set broadcast address or Point-to-point destination address
+               ifa_ifu.sin_family = AF_INET;
+               //ifa_ifu.sin_port = htons(MYPORT);
+               inet_aton("0.0.0.0", &(ifa_ifu.sin_addr));
+
+               ifaddr.ifa_next = nullptr;      // pointer to next ifaddrs 
structure
+               ifaddr.ifa_name = (char*)"lo";
+               // v-- Flags from SIOCGIFFLAGS, man 7 netdevice
+               ifaddr.ifa_flags = 0 | IFF_LOOPBACK | IFF_UP;
+               ifaddr.ifa_addr = (struct sockaddr*)&ifa_addr;
+               ifaddr.ifa_netmask = (struct sockaddr*)&ifa_netmask;
+               ifaddr.ifa_broadaddr = (struct sockaddr*)&ifa_ifu;
+               ifaddr.ifa_data = nullptr;
+       }
+
+
+       ifaddrs* get()
+       // Return the pointer to the ifaddr structure
+       {
+               return &ifaddr;
+       }
+
+
+       bool set(std::string pIfname, std::string pIfaddress)
+       // Set the interface name and the ipv4 address with bitmask. Properties 
are
+       // set to an ipv4 UP interface, supporting broadcast and multicast.
+       // Returns true if successful.
+       {
+               ifaddr.ifa_name = (char*)pIfname.c_str();
+
+               // get the netmask from the bitmask
+               // the bitmask is the offset in the netmasks array.
+               std::size_t slashpos = pIfaddress.find_first_of("/");
+               std::string address = pIfaddress;
+               std::string bitmask = "32";
+               if (slashpos != std::string::npos) {
+                       address = pIfaddress.substr(0,slashpos);
+                       bitmask = pIfaddress.substr(slashpos+1);
+               }
+               //std::cout << "address: '" << address << "', bitmask: '" << 
bitmask << "', netmask: "
+               //                      << netmasks[std::stoi(bitmask)] << ", 
slashpos: " << slashpos << "\n";
+
+               // convert address strings to numbers and store them
+               inet_aton(address.c_str(), &(ifa_addr.sin_addr));
+               std::string netmask = netmasks[std::stoi(bitmask)];
+               inet_aton(netmask.c_str(), &(ifa_netmask.sin_addr));
+               ifaddr.ifa_flags = 0 | IFF_UP | IFF_BROADCAST | IFF_MULTICAST;
+
+               // calculate broadcast address as follows: broadcast = ip | ( ~ 
subnet )
+               // broadcast = ip-addr or the inverted subnet-mask
+               ifa_ifu.sin_addr.s_addr = ifa_addr.sin_addr.s_addr | ~ 
ifa_netmask.sin_addr.s_addr;
+
+               return true;
+       }
+};
+
+class CCaptureFd
+// Tool to capture output to a file descriptor, mainly used to capture program
+// output to stdout or stderr.
+// When printing the captured output, all opened file descriptor will be closed
+// to avoid confusing output loops. For a new capture after print(..) you have
+// to call capture(..) again.
+{
+       int mFd;
+       int mFd_old;
+       int mFd_log;
+       bool mErr = true;
+       char mCaptFname[16] = ".captfd.log";
+
+public:
+       void capture(int fd)
+       {
+               mFd = fd;
+               mFd_old = dup(fd);
+               if (mFd_old < 0) {
+                       return;
+               }
+               mFd_log = ::open(mCaptFname, O_WRONLY|O_CREAT|O_TRUNC, 0660);
+               if (mFd_log < 0) {
+                       ::close(mFd_old);
+                       return;
+               }
+               if (dup2(mFd_log, fd) < 0) {
+                       ::close(mFd_old);
+                       ::close(mFd_log);
+                       return;
+               }
+               mErr = false;
+       }
+
+       ~CCaptureFd()
+       {
+               this->closeFds();
+               remove(mCaptFname);
+       }
+
+       bool print(std::ostream &pOut)
+       // Close all file descriptors and print captured file content.
+       // If nothing was captured, then the return value is false.
+       {
+               if (mErr) return false;
+               this->closeFds();
+
+               std::ifstream readFileObj(mCaptFname);
+               std::string lineBuf = "";
+
+               std::getline(readFileObj, lineBuf);
+               if (lineBuf == "") {
+                       readFileObj.close();
+                       remove(mCaptFname);
+                       return false;
+               }
+
+               pOut << lineBuf << "\n";
+               while (std::getline(readFileObj, lineBuf))
+                               pOut << lineBuf << "\n";
+
+               readFileObj.close();
+               remove(mCaptFname);
+               return true;
+       }
+
+private:
+       void closeFds()
+       {
+               // restore old fd
+               dup2(mFd_old, mFd);
+               ::close(mFd_old);
+               ::close(mFd_log);
+               mErr = true;
+       }
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libupnp-1.14.16/libupnp.spec 
new/libupnp-1.14.17/libupnp.spec
--- old/libupnp-1.14.16/libupnp.spec    2022-11-19 03:29:49.000000000 +0100
+++ new/libupnp-1.14.17/libupnp.spec    2023-03-30 15:00:35.000000000 +0200
@@ -1,4 +1,4 @@
-Version: 1.14.16
+Version: 1.14.17
 Summary: Universal Plug and Play (UPnP) SDK
 Name: libupnp-1.14
 Release: 1%{?dist}

Reply via email to