From: Oskari Rauta <oskari.rauta@gmail.com>
Date: Sat, 7 Jan 2023 20:42:44 +0000 (+0200)
Subject: speedtestpp: drop libxml2 dependency
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=2feedb1e2a62a6f6a9e3405d7f03d968540297ff;p=feed%2Fpackages.git

speedtestpp: drop libxml2 dependency

Co-authored-by: Tianling Shen <cnsztl@gmail.com>
Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
(cherry picked from commit 281d62420383369a145ad41090ff498ee7067727)
---

diff --git a/net/speedtestpp/Makefile b/net/speedtestpp/Makefile
index 06fa629b9f..41cbd1d710 100644
--- a/net/speedtestpp/Makefile
+++ b/net/speedtestpp/Makefile
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=speedtestpp
 PKG_VERSION:=1.14
-PKG_RELEASE:=$(AUTORELEASE)
+PKG_RELEASE:=2
 
 PKG_SOURCE_PROTO:=git
 PKG_SOURCE_URL:=https://github.com/taganaka/SpeedTest.git
@@ -25,7 +25,7 @@ define Package/speedtestpp
   SECTION:=net
   CATEGORY:=Network
   TITLE:=speedtest++
-  DEPENDS:=+libcurl +libxml2 +libopenssl +libstdcpp $(ICONV_DEPENDS)
+  DEPENDS:=+libcurl +libopenssl +libstdcpp $(ICONV_DEPENDS)
   CONFLICTS:=python3-speedtest-cli
   URL:=https://github.com/taganaka/SpeedTest
 endef
diff --git a/net/speedtestpp/patches/01-remove-libxml-dependency.patch b/net/speedtestpp/patches/01-remove-libxml-dependency.patch
new file mode 100644
index 0000000000..c7ef9f7639
--- /dev/null
+++ b/net/speedtestpp/patches/01-remove-libxml-dependency.patch
@@ -0,0 +1,239 @@
+From b7db370449cfe2b453c22b74a660701f78bd7ce3 Mon Sep 17 00:00:00 2001
+From: Anatolii Lapytskyi <ala@allunite.com>
+Date: Tue, 6 Sep 2022 15:59:27 +0200
+Subject: [PATCH] Remove dependency on libxml2
+
+---
+ CMakeLists.txt |   5 +-
+ README.md      |   5 +-
+ SpeedTest.cpp  | 136 ++++++++++++++-----------------------------------
+ SpeedTest.h    |   2 -
+ 4 files changed, 41 insertions(+), 107 deletions(-)
+ 
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -44,7 +44,6 @@ add_executable(SpeedTest ${SOURCE_FILES}
+ 
+ INCLUDE (CheckIncludeFiles)
+ find_package(CURL REQUIRED)
+-find_package(LibXml2 REQUIRED)
+ 
+ if (NOT (APPLE))
+     find_package(OpenSSL REQUIRED)
+@@ -52,7 +51,7 @@ else()
+     CHECK_INCLUDE_FILES("CommonCrypto/CommonDigest.h" HAVE_COMMON_DIGEST_H)
+ endif()
+ 
+-include_directories(${CURL_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIR})
+-target_link_libraries(SpeedTest ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} -lpthread ${OPENSSL_LIBRARIES})
++include_directories(${CURL_INCLUDE_DIRS})
++target_link_libraries(SpeedTest ${CURL_LIBRARIES} -lpthread ${OPENSSL_LIBRARIES})
+ 
+ install(TARGETS SpeedTest RUNTIME DESTINATION bin)
+--- a/README.md
++++ b/README.md
+@@ -26,7 +26,6 @@ It supports the new (undocumented) raw T
+ 2. cmake
+ 3. libcurl
+ 4. libssl
+-5. libxml2
+ 
+ ### On Mac OS X
+ 
+@@ -40,7 +39,7 @@ $ make install
+ ### On Ubuntu/Debian
+ 
+ ```
+-$ sudo apt-get install build-essential libcurl4-openssl-dev libxml2-dev libssl-dev cmake
++$ sudo apt-get install build-essential libcurl4-openssl-dev libssl-dev cmake
+ $ git clone https://github.com/taganaka/SpeedTest
+ $ cd SpeedTest
+ $ cmake -DCMAKE_BUILD_TYPE=Release .
+@@ -50,7 +49,7 @@ $ sudo make install
+ ### On OpenSuse
+ 
+ ```
+-$ sudo zypper install cmake gcc-c++ libcurl-devel libxml2-devel libopenssl-devel git
++$ sudo zypper install cmake gcc-c++ libcurl-devel libopenssl-devel git
+ $ git clone https://github.com/taganaka/SpeedTest
+ $ cd SpeedTest
+ $ cmake -DCMAKE_BUILD_TYPE=Release .
+--- a/SpeedTest.cpp
++++ b/SpeedTest.cpp
+@@ -353,67 +353,16 @@ std::vector<std::string> SpeedTest::spli
+ 
+ }
+ 
+-ServerInfo SpeedTest::processServerXMLNode(xmlTextReaderPtr reader) {
+-
+-    auto name = xmlTextReaderConstName(reader);
+-    auto nodeName = std::string((char*)name);
+-
+-    if (!name || nodeName != "server"){
+-        return ServerInfo();
+-    }
+-
+-    if (xmlTextReaderAttributeCount(reader) > 0){
+-        auto info = ServerInfo();
+-        auto server_url         = xmlTextReaderGetAttribute(reader, BAD_CAST "url");
+-        auto server_lat         = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
+-        auto server_lon         = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
+-        auto server_name        = xmlTextReaderGetAttribute(reader, BAD_CAST "name");
+-        auto server_county      = xmlTextReaderGetAttribute(reader, BAD_CAST "country");
+-        auto server_cc          = xmlTextReaderGetAttribute(reader, BAD_CAST "cc");
+-        auto server_host        = xmlTextReaderGetAttribute(reader, BAD_CAST "host");
+-        auto server_id          = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
+-        auto server_sponsor     = xmlTextReaderGetAttribute(reader, BAD_CAST "sponsor");
+-
+-        if (server_name)
+-            info.name.append((char*)server_name);
+-
+-        if (server_url)
+-            info.url.append((char*)server_url);
+-
+-        if (server_county)
+-            info.country.append((char*)server_county);
+-
+-        if (server_cc)
+-            info.country_code.append((char*)server_cc);
+-
+-        if (server_host)
+-            info.host.append((char*)server_host);
+-
+-        if (server_sponsor)
+-            info.sponsor.append((char*)server_sponsor);
+-
+-        if (server_id)
+-            info.id  = std::atoi((char*)server_id);
+-
+-        if (server_lat)
+-            info.lat = std::stof((char*)server_lat);
+-
+-        if (server_lon)
+-            info.lon = std::stof((char*)server_lon);
+-
+-        xmlFree(server_url);
+-        xmlFree(server_lat);
+-        xmlFree(server_lon);
+-        xmlFree(server_name);
+-        xmlFree(server_county);
+-        xmlFree(server_cc);
+-        xmlFree(server_host);
+-        xmlFree(server_id);
+-        xmlFree(server_sponsor);
+-        return info;
+-    }
+-
+-    return ServerInfo();
++std::string getAttributeValue(const std::string& data, const size_t offset, const size_t max_pos, const std::string& attribute_name) {
++    size_t pos = data.find(attribute_name + "=\"", offset);
++    if (pos == std::string::npos)
++        return "";
++    if (pos >= max_pos)
++        return "";
++    size_t value_pos = pos + attribute_name.length() + 2;
++    size_t end = data.find("\"", value_pos);
++    std::string s = data.substr(pos + attribute_name.length() + 2, end - value_pos);
++    return s;
+ }
+ 
+ bool SpeedTest::fetchServers(const std::string& url, std::vector<ServerInfo>& target, int &http_code) {
+@@ -441,53 +390,42 @@ bool SpeedTest::fetchServers(const std::
+         http_code = 200;
+     }
+ 
+-    size_t len = oss.str().length();
+-    auto *xmlbuff = (char*)calloc(len + 1, sizeof(char));
+-    if (!xmlbuff){
+-        std::cerr << "Unable to calloc" << std::endl;
++    IPInfo ipInfo;
++    if (!SpeedTest::ipInfo(ipInfo)){
+         curl_easy_cleanup(curl);
++        std::cerr << "OOPS!" <<std::endl;
+         return false;
+     }
+-    memcpy(xmlbuff, oss.str().c_str(), len);
+-    oss.str("");
+ 
+-    xmlTextReaderPtr reader = xmlReaderForMemory(xmlbuff, static_cast<int>(len), nullptr, nullptr, 0);
++    std::string data = oss.str();
+ 
+-    if (reader != nullptr) {
+-        IPInfo ipInfo;
+-        if (!SpeedTest::ipInfo(ipInfo)){
+-            curl_easy_cleanup(curl);
+-            free(xmlbuff);
+-            xmlFreeTextReader(reader);
+-            std::cerr << "OOPS!" <<std::endl;
+-            return false;
+-        }
+-        auto ret = xmlTextReaderRead(reader);
+-        while (ret == 1) {
+-            ServerInfo info = processServerXMLNode(reader);
+-            if (!info.url.empty()){
+-                info.distance = harversine(std::make_pair(ipInfo.lat, ipInfo.lon), std::make_pair(info.lat, info.lon));
+-                target.push_back(info);
+-            }
+-            ret = xmlTextReaderRead(reader);
+-        }
+-        xmlFreeTextReader(reader);
+-        if (ret != 0) {
+-            curl_easy_cleanup(curl);
+-            free(xmlbuff);
+-            std::cerr << "Failed to parse" << std::endl;
+-            return false;
++    const std::string server_tag_start = "<server ";
++
++    size_t server_tag_begin = data.find(server_tag_start);
++    while (server_tag_begin != std::string::npos) {
++        size_t server_tag_end = data.find("/>", server_tag_begin);
++
++        auto info = ServerInfo();
++        info.name         = getAttributeValue(data, server_tag_begin, server_tag_end, "name");
++        info.url          = getAttributeValue(data, server_tag_begin, server_tag_end, "url");
++        info.country      = getAttributeValue(data, server_tag_begin, server_tag_end, "country");
++        info.country_code = getAttributeValue(data, server_tag_begin, server_tag_end, "cc");
++        info.host         = getAttributeValue(data, server_tag_begin, server_tag_end, "host");
++        info.sponsor      = getAttributeValue(data, server_tag_begin, server_tag_end, "sponsor");
++        info.id           = atoi(getAttributeValue(data, server_tag_begin, server_tag_end, "id").c_str());
++        info.lat          = std::stof(getAttributeValue(data, server_tag_begin, server_tag_end, "lat"));
++        info.lon          = std::stof(getAttributeValue(data, server_tag_begin, server_tag_end, "lon"));
++
++        if (!info.url.empty()){
++            info.distance = harversine(std::make_pair(ipInfo.lat, ipInfo.lon), std::make_pair(info.lat, info.lon));
++            target.push_back(info);
+         }
+-    } else {
+-        std::cerr << "Unable to initialize xml parser" << std::endl;
+-        curl_easy_cleanup(curl);
+-        free(xmlbuff);
+-        return false;
++
++        server_tag_begin = data.find(server_tag_start, server_tag_begin + 1);
+     }
+ 
++
+     curl_easy_cleanup(curl);
+-    free(xmlbuff);
+-    xmlCleanupParser();
+     std::sort(target.begin(), target.end(), [](const ServerInfo &a, const ServerInfo &b) -> bool {
+         return a.distance < b.distance;
+     });
+--- a/SpeedTest.h
++++ b/SpeedTest.h
+@@ -7,7 +7,6 @@
+ 
+ #include "SpeedTestConfig.h"
+ #include "SpeedTestClient.h"
+-#include <libxml/xmlreader.h>
+ #include <functional>
+ #include <cmath>
+ #include <curl/curl.h>
+@@ -50,7 +49,6 @@ private:
+     const ServerInfo findBestServerWithin(const std::vector<ServerInfo>& serverList, long& latency, int sample_size = 5, std::function<void(bool)> cb = nullptr);
+     static CURL* curl_setup(CURL* curl = nullptr);
+     static size_t writeFunc(void* buf, size_t size, size_t nmemb, void* userp);
+-    static ServerInfo processServerXMLNode(xmlTextReaderPtr reader);
+     double execute(const ServerInfo &server, const TestConfig &config, const opFn &fnc, std::function<void(bool)> cb = nullptr);
+     template <typename T>
+         static T deg2rad(T n);