diff --git a/.drone.yml b/.drone.yml index 21793c5..d4506e6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,3 +1,4 @@ +# -*- fill-column: 1000 -*- kind: pipeline name: on_push @@ -30,7 +31,7 @@ steps: - gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add - - apt-get update -q - apt-get install -qy -t xenial g++-5 - - apt-get install -qy cmake pkg-config libpoco-dev libjsoncpp-dev asciidoc + - apt-get install -qy cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev asciidoc - rm -rf build && mkdir -p build && cd build - cmake .. - make VERBOSE=1 @@ -56,7 +57,7 @@ steps: - gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add - - apt-get update -q - apt-get install -qy -t xenial g++-9 - - apt-get install -qy cmake pkg-config libpoco-dev libjsoncpp-dev asciidoc + - apt-get install -qy cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev asciidoc - rm -rf build && mkdir -p build && cd build - cmake .. - make VERBOSE=1 @@ -75,7 +76,7 @@ steps: - rm /etc/apt/apt.conf.d/docker-clean - alias apt-get='rm -f /var/cache/apt/archives/lock && apt-get' - apt-get update -q - - apt-get install -qy clang cmake pkg-config libpoco-dev libjsoncpp-dev asciidoc + - apt-get install -qy clang cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev asciidoc - rm -rf build && mkdir -p build && cd build - cmake .. - make VERBOSE=1 @@ -94,7 +95,7 @@ steps: - rm /etc/apt/apt.conf.d/docker-clean - alias apt-get='rm -f /var/cache/apt/archives/lock && apt-get' - apt-get update -q - - apt-get install -qy clang cmake pkg-config libpoco-dev libjsoncpp-dev asciidoc + - apt-get install -qy clang cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev asciidoc - rm -rf build && mkdir -p build && cd build - cmake .. - make VERBOSE=1 @@ -106,7 +107,7 @@ steps: image: drillster/drone-email pull: always settings: - host: cryptoparty-celle.de + host: mail.tzend.de from: drone@tzend.de username: from_secret: email_username diff --git a/CMakeLists.txt b/CMakeLists.txt index 84bae83..b473e82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,7 @@ include(cmake/debug_flags.cmake) find_package(PkgConfig REQUIRED) pkg_check_modules(jsoncpp REQUIRED IMPORTED_TARGET jsoncpp) -# Some distributions do not contain Poco*Config.cmake recipes. -find_package(Poco COMPONENTS Foundation Net NetSSL CONFIG) +find_package(CURL 7.56 REQUIRED) add_subdirectory(src) diff --git a/README.adoc b/README.adoc index 13599cf..87f9d18 100644 --- a/README.adoc +++ b/README.adoc @@ -31,7 +31,7 @@ emerge -a dev-util/gitea2rss * C++ compiler (tested: https://gcc.gnu.org/[gcc] 5/8/9, https://llvm.org/[clang] 3/7) * https://cmake.org/[cmake] (at least: 3.6) -* https://pocoproject.org/[POCO] (tested: 1.9 / 1.7) +* https://curl.haxx.se/libcurl/[libcurl] (at least: 7.56) * https://github.com/open-source-parsers/jsoncpp[jsoncpp] (tested: 1.8) * Optional: ** Manpage: http://asciidoc.org/[asciidoc] (tested: 8.6) @@ -40,7 +40,7 @@ emerge -a dev-util/gitea2rss [source,shell] ---- -apt-get install build-essential cmake libpoco-dev libjsoncpp-dev asciidoc +apt-get install build-essential cmake libcurl4-openssl-dev libjsoncpp-dev asciidoc ---- ==== Get sourcecode diff --git a/man/gitea2rss.1.adoc b/man/gitea2rss.1.adoc index fb98367..16c7fe2 100644 --- a/man/gitea2rss.1.adoc +++ b/man/gitea2rss.1.adoc @@ -2,7 +2,7 @@ :doctype: manpage :Author: tastytea :Email: tastytea@tastytea.de -:Date: 2019-08-09 +:Date: 2020-10-24 :Revision: 0.0.0 :man source: gitea2rss :man version: {revision} @@ -57,8 +57,8 @@ this in it: == PROXY SERVERS -*gitea2rss* supports HTTP proxies set via the environment variable -_http_proxy_. Accepted formats are _http://host:port/_ or _host:port_. +Since *gitea2rss* is built on libcurl, it respects the same proxy environment +variables. See *curl*(1), section _ENVIRONMENT_. == EXAMPLES @@ -95,7 +95,7 @@ _http_proxy_. Accepted formats are _http://host:port/_ or _host:port_. == SEE ALSO -*crontab*(1), *crontab*(5) +*crontab*(1), *crontab*(5), *curl*(1) == REPORTING BUGS diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2efd0ae..fdede2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,26 +11,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE "$") target_link_libraries(${PROJECT_NAME} - PRIVATE PkgConfig::jsoncpp) - -# If no Poco*Config.cmake recipes are found, look for headers in standard dirs. -if(PocoNetSSL_FOUND) - target_link_libraries(${PROJECT_NAME} - PRIVATE Poco::Foundation Poco::Net Poco::NetSSL) -else() - find_file(Poco_h NAMES "Poco/Poco.h" - PATHS "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") - - if("${Poco_h}" STREQUAL "Poco_h-NOTFOUND") - message(FATAL_ERROR "Could not find POCO.") - else() - message(WARNING - "Your distribution of POCO doesn't contain the *Config.cmake recipes, " - "but the files seem to be in the standard directories. " - "Let's hope this works.") - target_link_libraries(${PROJECT_NAME} - PRIVATE PocoFoundation PocoNet PocoNetSSL) - endif() -endif() + PRIVATE PkgConfig::jsoncpp CURL::libcurl) install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/gitea2rss.hpp b/src/gitea2rss.hpp index aed98fc..2d88761 100644 --- a/src/gitea2rss.hpp +++ b/src/gitea2rss.hpp @@ -1,5 +1,5 @@ /* This file is part of gitea2rss. - * Copyright © 2019 tastytea + * Copyright © 2019, 2020 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,22 +17,22 @@ #ifndef GITEA2RSS_HPP #define GITEA2RSS_HPP -#include #include -#include #include +#include +#include using std::string; -using std::chrono::system_clock; using std::uint8_t; +using std::chrono::system_clock; extern bool cgi; -//! Set proxy from environment variable `http_proxy`. -void set_proxy(); - //! Fetch HTTP document. -const string get_http(const string &url); +string get_http(const string &url); + +// CURL receive function. +size_t writer_body(char *data, size_t size, size_t nmemb); //! Convert time_point to RFC 822 compliant time string. const string strtime(const system_clock::time_point &timepoint); @@ -41,7 +41,7 @@ const string strtime(const system_clock::time_point &timepoint); const string strtime(const string &time); //! Write line of XML. -void write_line(const uint8_t spaces, const string &tag, const string &value); +void write_line(uint8_t spaces, const string &tag, const string &value); //! Write the RSS preamble and channel data. void write_preamble(const string &url, const string &type); @@ -67,4 +67,7 @@ const string get_project(const string &url); //! Escape some characters to named HTML entities. const string escape_some_html(string html); -#endif // GITEA2RSS_HPP +//! Return environment variable or "" if it is not set. +string get_env_var(const string &variable); + +#endif // GITEA2RSS_HPP diff --git a/src/http.cpp b/src/http.cpp index 71cbdc1..69d0376 100644 --- a/src/http.cpp +++ b/src/http.cpp @@ -1,5 +1,5 @@ /* This file is part of gitea2rss. - * Copyright © 2019 tastytea + * Copyright © 2019, 2020 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,142 +14,105 @@ * along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.hpp" #include "gitea2rss.hpp" +#include "version.hpp" +#include +#include +#include +#include +#include -using std::cout; using std::cerr; +using std::cout; using std::endl; -using std::istream; -using std::unique_ptr; -using std::make_unique; -using std::regex; -using std::regex_search; -using std::smatch; -using Poco::Net::HTTPClientSession; -using Poco::Net::HTTPSClientSession; -using Poco::Net::HTTPRequest; -using Poco::Net::HTTPResponse; -using Poco::Net::HTTPMessage; -using Poco::StreamCopier; -using Poco::Environment; +using std::runtime_error; +using std::to_string; -void set_proxy() +string buffer_body; + +string get_http(const string &url) { try { - HTTPSClientSession::ProxyConfig proxyconfig; - string env_proxy = Environment::get("http_proxy"); - regex re_proxy("^(?:https?://)?(?:([^:]+):?([^@]*)@)?" // user:password - "([^:]+):([[:digit:]]+/?)"); // host:port - smatch match; - - if (regex_search(env_proxy, match, re_proxy)) + curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise) + CURL *connection{curl_easy_init()}; + if (connection == nullptr) { - string username, password; - Poco::URI::decode(match[1].str(), username); - Poco::URI::decode(match[2].str(), password); - - proxyconfig.host = match[3].str(); - proxyconfig.port = std::stoi(match[4].str()); - proxyconfig.username = username; - proxyconfig.password = password; - - HTTPSClientSession::setGlobalProxyConfig(proxyconfig); + throw runtime_error{"Failed to initialize curl."}; } + + char buffer_error[256]; + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(connection, CURLOPT_ERRORBUFFER, buffer_error); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(connection, CURLOPT_WRITEFUNCTION, writer_body); + + CURLcode code{curl_easy_setopt(connection, CURLOPT_FOLLOWLOCATION, 1L)}; + if (code != CURLE_OK) + { + throw runtime_error{"HTTP is not supported."}; + } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(connection, CURLOPT_MAXREDIRS, 5L); + + code = + curl_easy_setopt(connection, CURLOPT_USERAGENT, + (string("gitea2rss/") += global::version).c_str()); + if (code != CURLE_OK) + { + throw runtime_error{"Failed to set User-Agent."}; + } + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(connection, CURLOPT_HTTPGET, 1L); + + code = curl_easy_setopt(connection, CURLOPT_URL, url.c_str()); + if (code != CURLE_OK) + { + throw runtime_error{"Couldn't set URL: " + to_string(code)}; + } + + code = curl_easy_perform(connection); + if (code != CURLE_OK) + { + throw runtime_error{"libcurl error: " + to_string(code)}; + } + + long http_status{0}; // NOLINT(google-runtime-int) + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_getinfo(connection, CURLINFO_RESPONSE_CODE, &http_status); + + curl_easy_cleanup(connection); + + if (http_status == 200) + { + return buffer_body; + } + + if (cgi) + { + cout << "Status: " << http_status << endl; + } + throw runtime_error{"HTTP error: " + to_string(http_status)}; } - catch (const std::exception &) + catch (const runtime_error &e) { - // No proxy found, no problem. - } -} - -const string get_http(const string &url) -{ - try - { - Poco::URI poco_uri(url); - string path = poco_uri.getPathAndQuery(); - if (path.empty()) - { - path = "/"; - } - - unique_ptr session; - if (poco_uri.getScheme() == "https") - { - session = make_unique(poco_uri.getHost(), - poco_uri.getPort()); - } - else if (poco_uri.getScheme() == "http") - { - session = make_unique(poco_uri.getHost(), - poco_uri.getPort()); - } - else - { - throw Poco::Exception("Protocol not supported."); - } - - HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); - request.set("User-Agent", string("gitea2rss/") + global::version); - - HTTPResponse response; - - session->sendRequest(request); - istream &rs = session->receiveResponse(response); - - // Not using the constants because some are too new for Debian stretch. - switch (response.getStatus()) - { - case 301: // HTTPResponse::HTTP_MOVED_PERMANENTLY - case 308: // HTTPResponse::HTTP_PERMANENT_REDIRECT - case 302: // HTTPResponse::HTTP_FOUND - case 303: // HTTPResponse::HTTP_SEE_OTHER - case 307: // HTTPResponse::HTTP_TEMPORARY_REDIRECT - { - string location = response.get("Location"); - if (location.substr(0, 4) != "http") - { - location = poco_uri.getScheme() + "://" + poco_uri.getHost() - + location; - } - return get_http(location); - } - case HTTPResponse::HTTP_OK: - { - string answer; - StreamCopier::copyToString(rs, answer); - return answer; - } - default: - { - if (cgi) - { - cout << "Status: " << response.getStatus() << endl; - } - cerr << "HTTP Error: " << response.getStatus() << endl; - - return ""; - } - } - } - catch (const Poco::Exception &e) - { - cerr << "Error: " << e.displayText() << endl; + cerr << "Error: " << e.what() << endl; } return ""; } + +size_t writer_body(char *data, size_t size, size_t nmemb) +{ + if (data == nullptr) + { + return 0; + } + + buffer_body.append(data, size * nmemb); + + return size * nmemb; +} diff --git a/src/main.cpp b/src/main.cpp index 6cd0f5f..9087596 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ /* This file is part of gitea2rss. - * Copyright © 2019 tastytea + * Copyright © 2019, 2020 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,33 +14,28 @@ * along with this program. If not, see . */ +#include "gitea2rss.hpp" +#include "version.hpp" #include #include -#include -#include -#include "version.hpp" -#include "gitea2rss.hpp" -using std::cout; using std::cerr; +using std::cout; using std::endl; using std::string; using std::chrono::system_clock; -using Poco::Environment; int main(int argc, char *argv[]) { - const string query = Environment::get("QUERY_STRING", ""); + + const string query{get_env_var("QUERY_STRING")}; string url; string type = "releases"; - Poco::Net::initializeSSL(); - - set_proxy(); - if (!query.empty()) { - const string baseurl = Environment::get("GITEA2RSS_BASEURL", ""); + cout << query << " AAAAAAAAA\n"; + const string baseurl{get_env_var("GITEA2RSS_BASEURL")}; if (baseurl.empty()) { cout << "Status: 500 Internal Server Error\n\n"; @@ -101,9 +96,7 @@ int main(int argc, char *argv[]) } cout << " \n" - "\n"; - - Poco::Net::uninitializeSSL(); + "\n"; return 0; } diff --git a/src/strings.cpp b/src/strings.cpp index 5a5a6d7..9747e32 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1,5 +1,5 @@ /* This file is part of gitea2rss. - * Copyright © 2019 tastytea + * Copyright © 2019, 2020 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,9 +14,12 @@ * along with this program. If not, see . */ +#include "gitea2rss.hpp" +#include #include #include -#include "gitea2rss.hpp" + +using std::getenv; const string get_baseurl(const string &url) { @@ -44,11 +47,8 @@ const string get_project(const string &url) const string escape_some_html(string html) { - const std::map names = - { - { '<', "<" }, - { '>', ">" } - }; + const std::map names = {{'<', "<"}, + {'>', ">"}}; for (auto &pair : names) { @@ -58,3 +58,13 @@ const string escape_some_html(string html) return html; } + +string get_env_var(const string &variable) +{ + const char *env{getenv(variable.c_str())}; + if (env != nullptr) + { + return env; + } + return ""; +} diff --git a/src/write.cpp b/src/write.cpp index d1e333a..98e6f12 100644 --- a/src/write.cpp +++ b/src/write.cpp @@ -1,5 +1,5 @@ /* This file is part of gitea2rss. - * Copyright © 2019 tastytea + * Copyright © 2019, 2020 tastytea * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,14 +14,14 @@ * along with this program. If not, see . */ +#include "gitea2rss.hpp" +#include "version.hpp" +#include #include #include -#include -#include "version.hpp" -#include "gitea2rss.hpp" using std::cout; -using Poco::Environment; +using std::getenv; void write_line(const uint8_t spaces, const string &tag, const string &value) { @@ -44,9 +44,9 @@ void write_line(const uint8_t spaces, const string &tag, const string &value) void write_preamble(const string &url, const string &type) { - const string request_uri = Environment::get("REQUEST_URI", ""); - const string server_name = Environment::get("SERVER_NAME", ""); - const string https = Environment::get("HTTPS", ""); + const string request_uri{get_env_var("REQUEST_URI")}; + const string server_name{get_env_var("SERVER_NAME")}; + const string https{get_env_var("HTTPS")}; string selfurl; if (!request_uri.empty() && !server_name.empty()) @@ -64,11 +64,11 @@ void write_preamble(const string &url, const string &type) } cout << "\n" - " \n"; + " \n"; if (cgi) { cout << " \n"; + + "\" rel=\"self\" type=\"application/rss+xml\"/>\n"; } write_line(4, "title", get_project(url) + " " + type); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f934cd4..c4389f3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,7 +9,7 @@ target_include_directories(${PROJECT_NAME}_testlib "$") target_link_libraries(${PROJECT_NAME}_testlib - PRIVATE Poco::Foundation Poco::Net Poco::NetSSL PkgConfig::jsoncpp) + PRIVATE CURL::libcurl PkgConfig::jsoncpp) file(GLOB sources_tests test_*.cpp)