From e3af01effd82d75c8c9b6f3e535c9d52601f84d4 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 22 Jun 2020 13:28:17 -0700 Subject: [PATCH 1/2] libnpupnp: update to 4.0.7 Fixes CVE-2020-12695. Signed-off-by: Rosen Penev --- libs/libnpupnp/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/libnpupnp/Makefile b/libs/libnpupnp/Makefile index 1d7818dff7..54aca93ff8 100644 --- a/libs/libnpupnp/Makefile +++ b/libs/libnpupnp/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libnpupnp -PKG_VERSION:=4.0.5 +PKG_VERSION:=4.0.7 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://www.lesbonscomptes.com/upmpdcli/downloads -PKG_HASH:=af9b35e26c9733343c0075cd33d05e86771fe999cc01618295d486cc522fdbff +PKG_HASH:=30f15caa67dc83f76b0976438165aa4704a50c7e3e5444c50bb8cbad874877ca PKG_MAINTAINER:= PKG_LICENSE:=LGPL-2.1-or-later From 1619ec812b0cc9a3f633a6545da97ef5038bf493 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 21 Jun 2020 21:05:43 -0700 Subject: [PATCH 2/2] gerbera: use npupnp This is on track to replace libupnp in the next version. Since libupnp is not building with GCC10, do this now. Also backported needed header patch. Replace other patches with the upstream versions. Signed-off-by: Rosen Penev --- multimedia/gerbera/Makefile | 10 +- multimedia/gerbera/patches/010-iconv.patch | 21 +- multimedia/gerbera/patches/020-pid.patch | 19 + multimedia/gerbera/patches/030-unistd.patch | 74 +++ multimedia/gerbera/patches/040-npupnp.patch | 485 ++++++++++++++++++++ 5 files changed, 603 insertions(+), 6 deletions(-) create mode 100644 multimedia/gerbera/patches/030-unistd.patch create mode 100644 multimedia/gerbera/patches/040-npupnp.patch diff --git a/multimedia/gerbera/Makefile b/multimedia/gerbera/Makefile index f5039c1253..851464c9cf 100644 --- a/multimedia/gerbera/Makefile +++ b/multimedia/gerbera/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gerbera PKG_VERSION:=1.5.0 -PKG_RELEASE:=7 +PKG_RELEASE:=8 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/gerbera/gerbera/tar.gz/v$(PKG_VERSION)? @@ -29,7 +29,7 @@ include $(INCLUDE_DIR)/nls.mk define Package/gerbera SECTION:=multimedia CATEGORY:=Multimedia - DEPENDS:=+file +libupnp +libsqlite3 +libexif +libuuid +libfmt $(ICONV_DEPENDS) + DEPENDS:=+file +libnpupnp +libsqlite3 +libexif +libuuid +libfmt $(ICONV_DEPENDS) TITLE:=A free media server URL:=https://gerbera.io USERID:=gerbera:gerbera @@ -64,7 +64,11 @@ CMAKE_OPTIONS += \ -DWITH_DEBUG=OFF \ -DWITH_TESTS=OFF -TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto +TARGET_CFLAGS += \ + -ffunction-sections \ + -fdata-sections \ + -flto \ + -I$(STAGING_DIR)/usr/include/npupnp/upnp TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed define Package/gerbera/install diff --git a/multimedia/gerbera/patches/010-iconv.patch b/multimedia/gerbera/patches/010-iconv.patch index e93746d332..9145f76fd9 100644 --- a/multimedia/gerbera/patches/010-iconv.patch +++ b/multimedia/gerbera/patches/010-iconv.patch @@ -1,3 +1,18 @@ +From 77cae5ff9b8dff22bfebac905f1579562609dd35 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Mon, 4 May 2020 12:44:34 -0700 +Subject: [PATCH] remove iconv casting + +iconv_t is sometimes a pointer and other times an int. Remove casting +to make it work with the latter. + +Signed-off-by: Rosen Penev +--- + src/util/string_converter.cc | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/util/string_converter.cc b/src/util/string_converter.cc +index 272787ad..e1724b39 100644 --- a/src/util/string_converter.cc +++ b/src/util/string_converter.cc @@ -41,15 +41,15 @@ StringConverter::StringConverter(const std::string& from, const std::string& to) @@ -6,8 +21,8 @@ cd = iconv_open(to.c_str(), from.c_str()); - if (cd == reinterpret_cast(-1)) { - cd = static_cast(nullptr); -+ if (cd == (iconv_t)(-1)) { -+ cd = (iconv_t)(nullptr); ++ if (!cd) { ++ cd = {}; throw_std_runtime_error(std::string("iconv: ") + strerror(errno)); } } @@ -15,7 +30,7 @@ StringConverter::~StringConverter() { - if (cd != static_cast(nullptr)) -+ if (cd != (iconv_t)(nullptr)) ++ if (cd) iconv_close(cd); } diff --git a/multimedia/gerbera/patches/020-pid.patch b/multimedia/gerbera/patches/020-pid.patch index 23c5885112..7ce75c70b1 100644 --- a/multimedia/gerbera/patches/020-pid.patch +++ b/multimedia/gerbera/patches/020-pid.patch @@ -1,3 +1,20 @@ +From 59d37af2d6afd3d0ab6e8c5f3ea099435150c349 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 2 Jun 2020 15:55:25 -0700 +Subject: [PATCH] add missing unistd header + +Error with pid_t. + +Found with musl + libcxx. + +Signed-off-by: Rosen Penev +--- + src/util/process.h | 2 ++ + src/util/process_executor.h | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/src/util/process.h b/src/util/process.h +index e79e016c..8778aa34 100644 --- a/src/util/process.h +++ b/src/util/process.h @@ -35,6 +35,8 @@ @@ -9,6 +26,8 @@ // forward declaration class Config; +diff --git a/src/util/process_executor.h b/src/util/process_executor.h +index eaccf451..2a724087 100644 --- a/src/util/process_executor.h +++ b/src/util/process_executor.h @@ -35,6 +35,8 @@ diff --git a/multimedia/gerbera/patches/030-unistd.patch b/multimedia/gerbera/patches/030-unistd.patch new file mode 100644 index 0000000000..5b50f03d78 --- /dev/null +++ b/multimedia/gerbera/patches/030-unistd.patch @@ -0,0 +1,74 @@ +From 89b289cde29c731f995642a341dc5fd3b47ec7a0 Mon Sep 17 00:00:00 2001 +From: Jean-Francois Dockes +Date: Mon, 4 May 2020 16:32:23 +0200 +Subject: [PATCH] The access() system call needs unistd.h, at least on Focal + +--- + src/file_request_handler.cc | 2 +- + src/iohandler/io_handler_chainer.cc | 2 +- + src/serve_request_handler.cc | 2 +- + src/util/upnp_quirks.cc | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/file_request_handler.cc b/src/file_request_handler.cc +index e8579b06..cfa3eaed 100644 +--- a/src/file_request_handler.cc ++++ b/src/file_request_handler.cc +@@ -30,9 +30,9 @@ + /// \file file_request_handler.cc + + #include "file_request_handler.h" // API +- + #include + #include ++#include + #include + + #include "config/config_manager.h" +diff --git a/src/iohandler/io_handler_chainer.cc b/src/iohandler/io_handler_chainer.cc +index e8701cd7..beaa9d03 100644 +--- a/src/iohandler/io_handler_chainer.cc ++++ b/src/iohandler/io_handler_chainer.cc +@@ -30,8 +30,8 @@ + /// \file io_handler_chainer.cc + + #include "io_handler_chainer.h" // API +- + #include ++#include + + #include "exceptions.h" + +diff --git a/src/serve_request_handler.cc b/src/serve_request_handler.cc +index 8eaf46af..210140a3 100644 +--- a/src/serve_request_handler.cc ++++ b/src/serve_request_handler.cc +@@ -30,8 +30,8 @@ + /// \file serve_request_handler.cc + + #include "serve_request_handler.h" +- + #include ++#include + #include + + #include "config/config_manager.h" +diff --git a/src/util/upnp_quirks.cc b/src/util/upnp_quirks.cc +index df137370..e6f510b4 100644 +--- a/src/util/upnp_quirks.cc ++++ b/src/util/upnp_quirks.cc +@@ -24,13 +24,13 @@ + /// \file upnp_quirks.cc + + #include "upnp_quirks.h" // API +- + #include "cds_objects.h" + #include "config/config_manager.h" + #include "server.h" + #include "util/tools.h" + #include "util/upnp_clients.h" + #include "util/upnp_headers.h" ++#include + + Quirks::Quirks(std::shared_ptr config, const struct sockaddr_storage* addr, const std::string& userAgent) + : config(std::move(config)) diff --git a/multimedia/gerbera/patches/040-npupnp.patch b/multimedia/gerbera/patches/040-npupnp.patch new file mode 100644 index 0000000000..b82a4db4e0 --- /dev/null +++ b/multimedia/gerbera/patches/040-npupnp.patch @@ -0,0 +1,485 @@ +From 2ebccbb993dca41674de295f2d513abd568f971a Mon Sep 17 00:00:00 2001 +From: Jean-Francois Dockes +Date: Fri, 13 Mar 2020 09:19:04 +0100 +Subject: [PATCH] Quick changes for working with NPUPNP + +--- + CMakeLists.txt | 12 +++++------- + src/action_request.cc | 11 +++++++++++ + src/device_description_handler.cc | 4 ++++ + src/file_request_handler.cc | 4 ++++ + src/iohandler/file_io_handler.cc | 2 ++ + src/iohandler/io_handler.cc | 2 ++ + src/iohandler/mem_io_handler.cc | 2 ++ + src/serve_request_handler.cc | 9 ++++++++- + src/server.cc | 8 ++++++++ + src/transcoding/transcode_ext_handler.cc | 2 ++ + src/upnp_cds.cc | 12 +++++++++++- + src/upnp_cm.cc | 11 +++++++++++ + src/upnp_mrreg.cc | 10 +++++++++- + src/url_request_handler.cc | 6 ++++++ + src/util/upnp_clients.cc | 12 ++++++++++++ + src/util/upnp_headers.cc | 14 +++++++++++++- + src/util/upnp_headers.h | 2 ++ + src/web/web_request_handler.cc | 4 ++++ + 18 files changed, 116 insertions(+), 11 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 46f2ca5c..b51300d9 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -293,13 +293,11 @@ if (LFS_FOUND) + target_link_libraries(gerbera ${LFS_LIBRARIES}) + endif() + +-find_package (LibUpnp REQUIRED) +-include_directories(${UPNP_INCLUDE_DIRS}) +-target_link_libraries (gerbera ${UPNP_LIBRARIES}) +- +-if (UPNP_VERSION_STRING VERSION_LESS "1.12.1") +- message(FATAL_ERROR "gerbera requires libupnp 1.12.1 or above.") +-endif() ++#### Hard-coded NPUPNP defs for now, just for testing ++add_definitions(-DUSING_NPUPNP) ++include_directories(/usr/include/npupnp/upnp) ++target_link_libraries (gerbera -lnpupnp) ++set (UPNP_HAS_IPV6 1) + + if (NOT UPNP_HAS_IPV6) + message(FATAL_ERROR "Gerbera requires libupnp with IPv6 support.") +diff --git a/src/action_request.cc b/src/action_request.cc +index 3aa4a991..29be6aaf 100644 +--- a/src/action_request.cc ++++ b/src/action_request.cc +@@ -65,11 +65,17 @@ std::string ActionRequest::getServiceID() const + + std::unique_ptr ActionRequest::getRequest() const + { ++#if !defined(USING_NPUPNP) + DOMString cxml = ixmlPrintDocument(UpnpActionRequest_get_ActionRequest(upnp_request)); ++#endif + auto request = std::make_unique(); ++#if defined(USING_NPUPNP) ++ auto ret = request->load_string(upnp_request->xmlAction.c_str()); ++#else + auto ret = request->load_string(cxml); + ixmlFreeDOMString(cxml); + ++#endif + if (ret.status != pugi::xml_parse_status::status_ok) + throw_std_runtime_error("Unable to parse ixml"); + +@@ -94,6 +100,7 @@ void ActionRequest::update() + std::string xml = buf.str(); + log_debug("ActionRequest::update(): {}", xml.c_str()); + ++#if !defined(USING_NPUPNP) + IXML_Document* result = nullptr; + int err = ixmlParseBufferEx(xml.c_str(), &result); + +@@ -105,6 +112,10 @@ void ActionRequest::update() + UpnpActionRequest_set_ActionResult(upnp_request, result); + UpnpActionRequest_set_ErrCode(upnp_request, errCode); + } ++#else ++ UpnpActionRequest_set_xmlResponse(upnp_request, xml); ++ UpnpActionRequest_set_ErrCode(upnp_request, errCode); ++#endif + } else { + // ok, here there can be two cases + // either the function below already did set an error code, +diff --git a/src/device_description_handler.cc b/src/device_description_handler.cc +index 6aca745e..cf2e8015 100644 +--- a/src/device_description_handler.cc ++++ b/src/device_description_handler.cc +@@ -45,7 +45,11 @@ void DeviceDescriptionHandler::getInfo(const char* filename, UpnpFileInfo* info) + { + // We should be able to do the generation here, but libupnp doesnt support the request cookies yet + UpnpFileInfo_set_FileLength(info, -1); ++#if defined(USING_NPUPNP) + UpnpFileInfo_set_ContentType(info, "application/xml"); ++#else ++ UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString("application/xml")); ++#endif + UpnpFileInfo_set_IsReadable(info, 1); + UpnpFileInfo_set_IsDirectory(info, 0); + } +diff --git a/src/file_request_handler.cc b/src/file_request_handler.cc +index e8579b06..615f7e85 100644 +--- a/src/file_request_handler.cc ++++ b/src/file_request_handler.cc +@@ -238,7 +238,11 @@ void FileRequestHandler::getInfo(const char* filename, UpnpFileInfo* info) + + UpnpFileInfo_set_LastModified(info, statbuf.st_mtime); + UpnpFileInfo_set_IsDirectory(info, S_ISDIR(statbuf.st_mode)); ++#if defined(USING_NPUPNP) ++ UpnpFileInfo_set_ContentType(info, mimeType); ++#else + UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimeType.c_str())); ++#endif + + headers->writeHeaders(info); + +diff --git a/src/iohandler/file_io_handler.cc b/src/iohandler/file_io_handler.cc +index 7e239250..ab5155ec 100644 +--- a/src/iohandler/file_io_handler.cc ++++ b/src/iohandler/file_io_handler.cc +@@ -32,7 +32,9 @@ + #include "file_io_handler.h" // API + + #include ++#ifndef USING_NPUPNP + #include ++#endif + #include + + #include "cds_objects.h" +diff --git a/src/iohandler/io_handler.cc b/src/iohandler/io_handler.cc +index f9789425..75a36130 100644 +--- a/src/iohandler/io_handler.cc ++++ b/src/iohandler/io_handler.cc +@@ -31,7 +31,9 @@ + + #include "io_handler.h" // API + ++#ifndef USING_NPUPNP + #include ++#endif + #include + + #include "server.h" +diff --git a/src/iohandler/mem_io_handler.cc b/src/iohandler/mem_io_handler.cc +index 5574a16d..2916fd12 100644 +--- a/src/iohandler/mem_io_handler.cc ++++ b/src/iohandler/mem_io_handler.cc +@@ -35,7 +35,9 @@ + #include + #include + #include ++#ifndef USING_NPUPNP + #include ++#endif + #include + #include + #include +diff --git a/src/serve_request_handler.cc b/src/serve_request_handler.cc +index 8eaf46af..b9bd7b25 100644 +--- a/src/serve_request_handler.cc ++++ b/src/serve_request_handler.cc +@@ -94,7 +94,11 @@ void ServeRequestHandler::getInfo(const char* filename, UpnpFileInfo* info) + UpnpFileInfo_set_IsReadable(info, 0); + } + ++#if defined(USING_NPUPNP) ++ UpnpFileInfo_set_ContentType(info, mimetype); ++#else + UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimetype.c_str())); ++#endif + } else { + throw_std_runtime_error("Not a regular file: " + path); + } +@@ -157,8 +161,11 @@ std::unique_ptr ServeRequestHandler::open(const char* filename, + info->is_readable = 0; + } + +- ++#if defined(USING_NPUPNP) ++ info->content_type = mimetype; ++#else + info->content_type = ixmlCloneDOMString(mimetype.c_str()); ++#endif + */ + } else { + throw_std_runtime_error("Not a regular file: " + path); +diff --git a/src/server.cc b/src/server.cc +index 913a4913..7cbabc71 100644 +--- a/src/server.cc ++++ b/src/server.cc +@@ -398,9 +398,17 @@ int Server::handleUpnpClientEvent(Upnp_EventType eventType, const void* event) + case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: + case UPNP_DISCOVERY_SEARCH_RESULT: { + auto d_event = reinterpret_cast(event); ++#if defined(USING_NPUPNP) ++ const char* userAgent = UpnpDiscovery_get_Os_cstr(d_event); ++#else + const char* userAgent = UpnpString_get_String(UpnpDiscovery_get_Os(d_event)); ++#endif + const struct sockaddr_storage* destAddr = UpnpDiscovery_get_DestAddr(d_event); ++#if defined(USING_NPUPNP) ++ const char* location = UpnpDiscovery_get_Location_cstr(d_event); ++#else + const char* location = UpnpString_get_String(UpnpDiscovery_get_Location(d_event)); ++#endif + + Clients::addClientByDiscovery(destAddr, userAgent, location); + break; +diff --git a/src/transcoding/transcode_ext_handler.cc b/src/transcoding/transcode_ext_handler.cc +index 4dad0e3f..412c1370 100644 +--- a/src/transcoding/transcode_ext_handler.cc ++++ b/src/transcoding/transcode_ext_handler.cc +@@ -37,7 +37,9 @@ + #include + #include + #include ++#ifndef USING_NPUPNP + #include ++#endif + #include + #include + #include +diff --git a/src/upnp_cds.cc b/src/upnp_cds.cc +index 6491fa78..a758655c 100644 +--- a/src/upnp_cds.cc ++++ b/src/upnp_cds.cc +@@ -284,6 +284,7 @@ void ContentDirectoryService::processSubscriptionRequest(const std::unique_ptrprint(buf, "", 0); + std::string xml = buf.str(); + ++#if !defined(USING_NPUPNP) + IXML_Document* event = nullptr; + int err = ixmlParseBufferEx(xml.c_str(), &event); + if (err != IXML_SUCCESS) { +@@ -295,6 +296,11 @@ void ContentDirectoryService::processSubscriptionRequest(const std::unique_ptrgetSubscriptionID().c_str()); + + ixmlDocument_free(event); ++#else ++ UpnpAcceptSubscriptionXML( ++ deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(), ++ DESC_CDS_SERVICE_ID, xml, request->getSubscriptionID().c_str()); ++#endif + log_debug("end"); + } + +@@ -313,6 +319,7 @@ void ContentDirectoryService::sendSubscriptionUpdate(const std::string& containe + propset->print(buf, "", 0); + std::string xml = buf.str(); + ++#if !defined(USING_NPUPNP) + IXML_Document* event = nullptr; + int err = ixmlParseBufferEx(xml.c_str(), &event); + if (err != IXML_SUCCESS) { +@@ -323,8 +330,11 @@ void ContentDirectoryService::sendSubscriptionUpdate(const std::string& containe + UpnpNotifyExt(deviceHandle, + config->getOption(CFG_SERVER_UDN).c_str(), + DESC_CDS_SERVICE_ID, event); +- + ixmlDocument_free(event); ++#else ++ UpnpNotifyXML(deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(), ++ DESC_CDS_SERVICE_ID, xml); ++#endif + + log_debug("end"); + } +diff --git a/src/upnp_cm.cc b/src/upnp_cm.cc +index aa608480..33f86bd2 100644 +--- a/src/upnp_cm.cc ++++ b/src/upnp_cm.cc +@@ -127,6 +127,7 @@ void ConnectionManagerService::processSubscriptionRequest(const std::unique_ptr< + propset->print(buf, "", 0); + std::string xml = buf.str(); + ++#if !defined(USING_NPUPNP) + IXML_Document* event = nullptr; + int err = ixmlParseBufferEx(xml.c_str(), &event); + if (err != IXML_SUCCESS) { +@@ -138,6 +139,11 @@ void ConnectionManagerService::processSubscriptionRequest(const std::unique_ptr< + DESC_CM_SERVICE_ID, event, request->getSubscriptionID().c_str()); + + ixmlDocument_free(event); ++#else ++ UpnpAcceptSubscriptionXML( ++ deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(), ++ DESC_CM_SERVICE_ID, xml, request->getSubscriptionID().c_str()); ++#endif + } + + void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceProtocol_CSV) +@@ -150,6 +156,7 @@ void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceP + propset->print(buf, "", 0); + std::string xml = buf.str(); + ++#if !defined(USING_NPUPNP) + IXML_Document* event = nullptr; + int err = ixmlParseBufferEx(xml.c_str(), &event); + if (err != IXML_SUCCESS) { +@@ -162,4 +169,8 @@ void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceP + DESC_CM_SERVICE_ID, event); + + ixmlDocument_free(event); ++#else ++ UpnpNotifyXML(deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(), ++ DESC_CM_SERVICE_ID, xml); ++#endif + } +diff --git a/src/upnp_mrreg.cc b/src/upnp_mrreg.cc +index 16eefaed..f993f452 100644 +--- a/src/upnp_mrreg.cc ++++ b/src/upnp_mrreg.cc +@@ -34,7 +34,9 @@ + #include + + #include "config/config_manager.h" +-#include "ixml.h" ++#ifndef USING_NPUPNP ++#include ++#endif + #include "server.h" + #include "storage/storage.h" + #include "upnp_xml.h" +@@ -120,6 +122,7 @@ void MRRegistrarService::processSubscriptionRequest(const std::unique_ptrprint(buf, "", 0); + std::string xml = buf.str(); + ++#if !defined(USING_NPUPNP) + IXML_Document* event = nullptr; + int err = ixmlParseBufferEx(xml.c_str(), &event); + if (err != IXML_SUCCESS) { +@@ -131,6 +134,11 @@ void MRRegistrarService::processSubscriptionRequest(const std::unique_ptrgetSubscriptionID().c_str()); + + ixmlDocument_free(event); ++#else ++ UpnpAcceptSubscriptionXML( ++ deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(), ++ DESC_MRREG_SERVICE_ID, xml, request->getSubscriptionID().c_str()); ++#endif + } + + // TODO: FIXME +diff --git a/src/url_request_handler.cc b/src/url_request_handler.cc +index f2a99c94..66af027b 100644 +--- a/src/url_request_handler.cc ++++ b/src/url_request_handler.cc +@@ -32,7 +32,9 @@ + #ifdef HAVE_CURL + #include "url_request_handler.h" // API + ++#ifndef USING_NPUPNP + #include ++#endif + #include + + #include "config/config_manager.h" +@@ -138,7 +140,11 @@ void URLRequestHandler::getInfo(const char* filename, UpnpFileInfo* info) + // ixmlCloneDOMString(header.c_str())); + // } + ++#if defined(USING_NPUPNP) ++ UpnpFileInfo_set_ContentType(info, mimeType); ++#else + UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimeType.c_str())); ++#endif + log_debug("web_get_info(): end"); + + /// \todo transcoding for get_info +diff --git a/src/util/upnp_clients.cc b/src/util/upnp_clients.cc +index ab02b58d..7bc85d77 100644 +--- a/src/util/upnp_clients.cc ++++ b/src/util/upnp_clients.cc +@@ -203,6 +203,15 @@ bool Clients::getInfoByType(const std::string& match, ClientMatchType type, cons + + bool Clients::downloadDescription(const std::string& location, std::unique_ptr& xml) + { ++#if defined(USING_NPUPNP) ++ std::string description, ct; ++ int errCode = UpnpDownloadUrlItem(location, description, ct); ++ if (errCode != UPNP_E_SUCCESS) { ++ log_debug("Error obtaining client description from {} -- error = {}", location, errCode); ++ return false; ++ } ++ const char *cxml = description.c_str(); ++#else + IXML_Document* descDoc = nullptr; + int errCode = UpnpDownloadXmlDoc(location.c_str(), &descDoc); + if (errCode != UPNP_E_SUCCESS) { +@@ -211,12 +220,15 @@ bool Clients::downloadDescription(const std::string& location, std::unique_ptr

(); + auto ret = xml->load_string(cxml); + ++#if !defined(USING_NPUPNP) + ixmlFreeDOMString(cxml); + ixmlDocument_free(descDoc); + ++#endif + if (ret.status != pugi::xml_parse_status::status_ok) { + log_debug("Unable to parse xml client description from {}", location); + return false; +diff --git a/src/util/upnp_headers.cc b/src/util/upnp_headers.cc +index c05cffe6..19ba88ca 100644 +--- a/src/util/upnp_headers.cc ++++ b/src/util/upnp_headers.cc +@@ -96,18 +96,29 @@ void Headers::writeHeaders(UpnpFileInfo* fileInfo) const + if (headers == nullptr) + return; + ++#if defined(USING_NPUPNP) ++ for (auto iter : *headers) { ++ fileInfo->response_headers.push_back(iter); ++ } ++#else + auto head = const_cast(UpnpFileInfo_get_ExtraHeadersList(fileInfo)); + for (auto iter : *headers) { + UpnpExtraHeaders* h = UpnpExtraHeaders_new(); + UpnpExtraHeaders_set_resp(h, formatHeader(iter, false).c_str()); + UpnpListInsert(head, UpnpListEnd(head), const_cast(UpnpExtraHeaders_get_node(h))); + } ++#endif + } + + std::unique_ptr> Headers::readHeaders(UpnpFileInfo* fileInfo) + { + auto ret = std::make_unique>(); + ++#if defined(USING_NPUPNP) ++ for (const auto& entry : fileInfo->request_headers) { ++ ret->insert(entry); ++ } ++#else + auto head = const_cast(UpnpFileInfo_get_ExtraHeadersList(fileInfo)); + UpnpListIter pos; + for (pos = UpnpListBegin(head); pos != UpnpListEnd(head); pos = UpnpListNext(head, pos)) { +@@ -116,6 +127,7 @@ std::unique_ptr> Headers::readHeaders(UpnpFil + auto add = parseHeader(header); + ret->insert(add); + } +- ++#endif ++ + return ret; + } +diff --git a/src/util/upnp_headers.h b/src/util/upnp_headers.h +index 9677d6e4..dd839236 100644 +--- a/src/util/upnp_headers.h ++++ b/src/util/upnp_headers.h +@@ -26,7 +26,9 @@ + #ifndef GERBERA_HEADERS_H + #define GERBERA_HEADERS_H + ++#if !defined(USING_NPUPNP) + #include ++#endif + #include + #include + #include +diff --git a/src/web/web_request_handler.cc b/src/web/web_request_handler.cc +index 71fc9fd5..2ca6601b 100644 +--- a/src/web/web_request_handler.cc ++++ b/src/web/web_request_handler.cc +@@ -120,7 +120,11 @@ void WebRequestHandler::getInfo(const char* filename, UpnpFileInfo* info) + + contentType = mimetype + "; charset=" + DEFAULT_INTERNAL_CHARSET; + ++#if defined(USING_NPUPNP) ++ UpnpFileInfo_set_ContentType(info, contentType); ++#else + UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(contentType.c_str())); ++#endif + Headers headers; + headers.addHeader(std::string { "Cache-Control" }, std::string { "no-cache, must-revalidate" }); + headers.writeHeaders(info);