From f23a2fe38920152817ab2e92d802984bd264b448 Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Sun, 22 Aug 2021 20:28:37 +0300 Subject: [PATCH] Update CPR to latest git. --- vendor/CPR/CMakeLists.txt | 4 +- vendor/CPR/CONTRIBUTING.md | 27 ----- vendor/CPR/README.md | 141 ------------------------- vendor/CPR/cpr/curlholder.cpp | 3 - vendor/CPR/cpr/proxyauth.cpp | 1 - vendor/CPR/cpr/redirect.cpp | 40 +++++++ vendor/CPR/cpr/response.cpp | 2 +- vendor/CPR/cpr/session.cpp | 134 ++++++++++++++--------- vendor/CPR/cpr/timeout.cpp | 11 +- vendor/CPR/cpr/util.cpp | 10 +- vendor/CPR/include/cpr/callback.h | 51 +++++---- vendor/CPR/include/cpr/cpr.h | 2 + vendor/CPR/include/cpr/interface.h | 32 ++++++ vendor/CPR/include/cpr/max_redirects.h | 18 ---- vendor/CPR/include/cpr/redirect.h | 77 ++++++++++++++ vendor/CPR/include/cpr/session.h | 12 ++- 16 files changed, 284 insertions(+), 281 deletions(-) delete mode 100644 vendor/CPR/CONTRIBUTING.md delete mode 100644 vendor/CPR/README.md create mode 100644 vendor/CPR/cpr/redirect.cpp create mode 100644 vendor/CPR/include/cpr/interface.h delete mode 100644 vendor/CPR/include/cpr/max_redirects.h create mode 100644 vendor/CPR/include/cpr/redirect.h diff --git a/vendor/CPR/CMakeLists.txt b/vendor/CPR/CMakeLists.txt index 0b1376e4..0696dde2 100644 --- a/vendor/CPR/CMakeLists.txt +++ b/vendor/CPR/CMakeLists.txt @@ -13,6 +13,7 @@ add_library(CPR STATIC cpr/payload.cpp cpr/proxies.cpp cpr/proxyauth.cpp + cpr/redirect.cpp cpr/session.cpp cpr/timeout.cpp cpr/unix_socket.cpp @@ -30,14 +31,15 @@ add_library(CPR STATIC include/cpr/curlholder.h include/cpr/digest.h include/cpr/error.h + include/cpr/interface.h include/cpr/limit_rate.h - include/cpr/max_redirects.h include/cpr/multipart.h include/cpr/ntlm.h include/cpr/parameters.h include/cpr/payload.h include/cpr/proxies.h include/cpr/proxyauth.h + include/cpr/redirect.h include/cpr/response.h include/cpr/session.h include/cpr/ssl_options.h diff --git a/vendor/CPR/CONTRIBUTING.md b/vendor/CPR/CONTRIBUTING.md deleted file mode 100644 index abfb97c3..00000000 --- a/vendor/CPR/CONTRIBUTING.md +++ /dev/null @@ -1,27 +0,0 @@ -# Contributing to C++ Requests - -Please fork this repository and contribute back using [pull requests](https://github.com/whoshuu/cpr/pulls). Features can be requested using [issues](https://github.com/whoshuu/cpr/issues). All code, comments, and critiques are greatly appreciated. - -## Formatting - -To avoid unproductive debates on formatting, this project uses `clang-format` to ensure a consistent style across all source files. Currently, `clang-format` 3.8 is the version of `clang-format` we use. The format file can be found [here](https://github.com/whoshuu/cpr/blob/master/.clang-format). To install `clang-format` on Ubuntu, run this: - -``` -apt-get install clang-format-3.8 -``` - -To install `clang-format` on OS X, run this: - -``` -brew install clang-format -``` - -Note that `brew` might install a later version of `clang-format`, but it should be mostly compatible with what's run on the Travis servers. - -To run `clang-format` on every source file, run this in the root directory: - -``` -./format-check.sh -``` - -This should indicate which files need formatting and also show a diff of the requested changes. More specific usage instructions can be found on the official [LLVM website](http://releases.llvm.org/3.8.0/tools/clang/docs/ClangFormat.html). diff --git a/vendor/CPR/README.md b/vendor/CPR/README.md deleted file mode 100644 index 157d86af..00000000 --- a/vendor/CPR/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# C++ Requests: Curl for People - -[![Documentation](https://img.shields.io/badge/docs-online-informational?style=flat&link=https://whoshuu.github.io/cpr/)](https://whoshuu.github.io/cpr/) -![CI](https://github.com/whoshuu/cpr/workflows/CI/badge.svg) - -## Announcements - -The cpr project has new maintainers: [Fabian Sauter](https://github.com/com8) and [Tim Stack](https://github.com/tstack). - -## TLDR - -C++ Requests is a simple wrapper around [libcurl](http://curl.haxx.se/libcurl) inspired by the excellent [Python Requests](https://github.com/kennethreitz/requests) project. - -Despite its name, libcurl's easy interface is anything but, and making mistakes misusing it is a common source of error and frustration. Using the more expressive language facilities of C++11, this library captures the essence of making network calls into a few concise idioms. - -Here's a quick GET request: - -```c++ -#include - -int main(int argc, char** argv) { - cpr::Response r = cpr::Get(cpr::Url{"https://api.github.com/repos/whoshuu/cpr/contributors"}, - cpr::Authentication{"user", "pass"}, - cpr::Parameters{{"anon", "true"}, {"key", "value"}}); - r.status_code; // 200 - r.header["content-type"]; // application/json; charset=utf-8 - r.text; // JSON text string -} -``` - -And here's [less functional, more complicated code, without cpr](https://gist.github.com/whoshuu/2dc858b8730079602044). - -## Documentation - -[![Documentation](https://img.shields.io/badge/docs-online-informational?style=for-the-badge&link=https://whoshuu.github.io/cpr/)](https://whoshuu.github.io/cpr/) -You can find the latest documentation [here](https://whoshuu.github.io/cpr). It's a work in progress, but it should give you a better idea of how to use the library than the [tests](https://github.com/whoshuu/cpr/tree/master/test) currently do. - -## Features - -C++ Requests currently supports: - -* Custom headers -* Url encoded parameters -* Url encoded POST values -* Multipart form POST upload -* File POST upload -* Basic authentication -* Bearer authentication -* Digest authentication -* NTLM authentication -* Connection and request timeout specification -* Timeout for low speed connection -* Asynchronous requests -* :cookie: support! -* Proxy support -* Callback interfaces -* PUT methods -* DELETE methods -* HEAD methods -* OPTIONS methods -* PATCH methods -* Thread Safe access to [libCurl](https://curl.haxx.se/libcurl/c/threadsafe.html) -* OpenSSL and WinSSL support for HTTPS requests - -## Planned - -For a quick overview about the planed features, have a look at the next [Milestones](https://github.com/whoshuu/cpr/milestones). - -## Usage - -If you already have a project you need to integrate C++ Requests with, the primary way is to use CMake `fetch_content`. -Add the following to your `CMakeLists.txt`. - - -```cmake -include(FetchContent) -FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/whoshuu/cpr.git GIT_TAG c8d33915dbd88ad6c92b258869b03aba06587ff9) # the commit hash for 1.5.0 -FetchContent_MakeAvailable(cpr) -``` - -This will produce the target `cpr::cpr` which you can link against the typical way: - -```cmake -target_link_libraries(your_target_name PRIVATE cpr::cpr) -``` - -That should do it! -There's no need to handle `libcurl` yourself. All dependencies are taken care of for you. - -## Requirements - -The only explicit requirements are: - -* a `C++11` compatible compiler such as Clang or GCC. The minimum required version of GCC is unknown, so if anyone has trouble building this library with a specific version of GCC, do let me know -* If you would like to perform https requests `OpenSSL` and its development libraries are required. - -## Building cpr - Using vcpkg - -You can download and install cpr using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: -```Bash -git clone https://github.com/Microsoft/vcpkg.git -cd vcpkg -./bootstrap-vcpkg.sh -./vcpkg integrate install -./vcpkg install cpr -``` -The `cpr` port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. - -## Building cpr - Using Conan - -You can download and install `cpr` using the [Conan](https://conan.io/) package manager. Setup your CMakeLists.txt (see [Conan documentation](https://docs.conan.io/en/latest/integrations/build_system.html) on how to use MSBuild, Meson and others) like this: - -```CMake -project(myproject CXX) - -add_executable(${PROJECT_NAME} main.cpp) - -include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) # Include Conan-generated file -conan_basic_setup(TARGETS) # Introduce Conan-generated targets - -target_link_libraries(${PROJECT_NAME} CONAN_PKG::cpr) -``` -Create `conanfile.txt` in your source dir: -``` -[requires] -cpr/1.5.0 - -[generators] -cmake -``` -Install and run Conan, then build your project as always: - -```Bash -pip install conan -mkdir build -cd build -conan install ../ --build=missing -cmake ../ -cmake --build . -``` -The `cpr` package in Conan is kept up to date by Conan contributors. If the version is out of date, please [create an issue or pull request](https://github.com/conan-io/conan-center-index) on the `conan-center-index` repository. diff --git a/vendor/CPR/cpr/curlholder.cpp b/vendor/CPR/cpr/curlholder.cpp index 3b27e5ed..4596ed7f 100644 --- a/vendor/CPR/cpr/curlholder.cpp +++ b/vendor/CPR/cpr/curlholder.cpp @@ -6,9 +6,6 @@ namespace cpr { // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) std::mutex CurlHolder::curl_easy_init_mutex_{}; -#ifndef _WIN32 // There is no thread sanitizer on windows -__attribute__((no_sanitize("thread"))) -#endif CurlHolder::CurlHolder() { /** * Allow multithreaded access to CPR by locking curl_easy_init(). diff --git a/vendor/CPR/cpr/proxyauth.cpp b/vendor/CPR/cpr/proxyauth.cpp index 6ef41248..47d914de 100644 --- a/vendor/CPR/cpr/proxyauth.cpp +++ b/vendor/CPR/cpr/proxyauth.cpp @@ -11,7 +11,6 @@ bool ProxyAuthentication::has(const std::string& protocol) const { const char* ProxyAuthentication::operator[](const std::string& protocol) { return proxyAuth_[protocol].GetAuthString(); - ; } } // namespace cpr diff --git a/vendor/CPR/cpr/redirect.cpp b/vendor/CPR/cpr/redirect.cpp new file mode 100644 index 00000000..fade1304 --- /dev/null +++ b/vendor/CPR/cpr/redirect.cpp @@ -0,0 +1,40 @@ +#include "cpr/redirect.h" + +namespace cpr { +PostRedirectFlags operator|(PostRedirectFlags lhs, PostRedirectFlags rhs) { + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +PostRedirectFlags operator&(PostRedirectFlags lhs, PostRedirectFlags rhs) { + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +PostRedirectFlags operator^(PostRedirectFlags lhs, PostRedirectFlags rhs) { + return static_cast(static_cast(lhs) ^ static_cast(rhs)); +} + +PostRedirectFlags operator~(PostRedirectFlags flag) { + return static_cast(~static_cast(flag)); +} + +PostRedirectFlags& operator|=(PostRedirectFlags& lhs, PostRedirectFlags rhs) { + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + uint8_t tmp = static_cast(lhs); + lhs = static_cast(tmp); + return lhs; +} + +PostRedirectFlags& operator&=(PostRedirectFlags& lhs, PostRedirectFlags rhs) { + lhs = static_cast(static_cast(lhs) & static_cast(rhs)); + return lhs; +} + +PostRedirectFlags& operator^=(PostRedirectFlags& lhs, PostRedirectFlags rhs) { + lhs = static_cast(static_cast(lhs) ^ static_cast(rhs)); + return lhs; +} + +bool any(PostRedirectFlags flag) { + return flag != PostRedirectFlags::NONE; +} +} // namespace cpr diff --git a/vendor/CPR/cpr/response.cpp b/vendor/CPR/cpr/response.cpp index 52c653b1..366bff5e 100644 --- a/vendor/CPR/cpr/response.cpp +++ b/vendor/CPR/cpr/response.cpp @@ -35,7 +35,7 @@ std::vector Response::GetCertInfo() { std::vector info; info.resize(ci->num_of_certs); - for (size_t i = 0; i < ci->num_of_certs; i++) { + for (int i = 0; i < ci->num_of_certs; i++) { // No way around here. // NOLINTNEXTLINE (cppcoreguidelines-pro-bounds-pointer-arithmetic) info[i] = std::string{ci->certinfo[i]->data}; diff --git a/vendor/CPR/cpr/session.cpp b/vendor/CPR/cpr/session.cpp index f75b2eec..1994ecb6 100644 --- a/vendor/CPR/cpr/session.cpp +++ b/vendor/CPR/cpr/session.cpp @@ -49,8 +49,7 @@ class Session::Impl { void SetMultipart(Multipart&& multipart); void SetMultipart(const Multipart& multipart); void SetNTLM(const NTLM& auth); - void SetRedirect(const bool& redirect); - void SetMaxRedirects(const MaxRedirects& max_redirects); + void SetRedirect(const Redirect& redirect); void SetCookies(const Cookies& cookies); void SetBody(Body&& body); void SetBody(const Body& body); @@ -65,7 +64,9 @@ class Session::Impl { void SetUnixSocket(const UnixSocket& unix_socket); void SetVerbose(const Verbose& verbose); void SetSslOptions(const SslOptions& options); + void SetInterface(const Interface& iface); + cpr_off_t GetDownloadFileLength(); Response Delete(); Response Download(const WriteCallback& write); Response Download(std::ofstream& file); @@ -121,9 +122,8 @@ Session::Impl::Impl() : curl_(new CurlHolder()) { curl_version_info_data* version_info = curl_version_info(CURLVERSION_NOW); std::string version = "curl/" + std::string{version_info->version}; curl_easy_setopt(curl_->handle, CURLOPT_USERAGENT, version.c_str()); - curl_easy_setopt(curl_->handle, CURLOPT_FOLLOWLOCATION, 1L); + SetRedirect(Redirect()); curl_easy_setopt(curl_->handle, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(curl_->handle, CURLOPT_MAXREDIRS, 50L); curl_easy_setopt(curl_->handle, CURLOPT_ERRORBUFFER, curl_->error.data()); curl_easy_setopt(curl_->handle, CURLOPT_COOKIEFILE, ""); #ifdef CPR_CURL_NOSIGNAL @@ -209,6 +209,14 @@ void Session::Impl::SetAuth(const Authentication& auth) { curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString()); } +void Session::Impl::SetInterface(const Interface& iface) { + if (iface.str().empty()) { + curl_easy_setopt(curl_->handle, CURLOPT_INTERFACE, nullptr); + } else { + curl_easy_setopt(curl_->handle, CURLOPT_INTERFACE, iface.c_str()); + } +} + // Only supported with libcurl >= 7.61.0. // As an alternative use SetHeader and add the token manually. #if LIBCURL_VERSION_NUM >= 0x073D00 @@ -232,16 +240,14 @@ void Session::Impl::SetUserAgent(const UserAgent& ua) { void Session::Impl::SetPayload(Payload&& payload) { hasBodyOrPayload_ = true; const std::string content = payload.GetContent(*curl_); - curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, - static_cast(content.length())); + curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast(content.length())); curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, content.c_str()); } void Session::Impl::SetPayload(const Payload& payload) { hasBodyOrPayload_ = true; const std::string content = payload.GetContent(*curl_); - curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, - static_cast(content.length())); + curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast(content.length())); curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, content.c_str()); } @@ -269,9 +275,7 @@ void Session::Impl::SetMultipart(Multipart&& multipart) { std::vector formdata; if (part.is_buffer) { // Do not use formdata, to prevent having to use reinterpreter_cast: - curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, part.name.c_str(), CURLFORM_BUFFER, - part.value.c_str(), CURLFORM_BUFFERPTR, part.data, CURLFORM_BUFFERLENGTH, - part.datalen, CURLFORM_END); + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, part.name.c_str(), CURLFORM_BUFFER, part.value.c_str(), CURLFORM_BUFFERPTR, part.data, CURLFORM_BUFFERLENGTH, part.datalen, CURLFORM_END); } else { formdata.push_back({CURLFORM_COPYNAME, part.name.c_str()}); if (part.is_file) { @@ -302,9 +306,7 @@ void Session::Impl::SetMultipart(const Multipart& multipart) { std::vector formdata; if (part.is_buffer) { // Do not use formdata, to prevent having to use reinterpreter_cast: - curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, part.name.c_str(), CURLFORM_BUFFER, - part.value.c_str(), CURLFORM_BUFFERPTR, part.data, CURLFORM_BUFFERLENGTH, - part.datalen, CURLFORM_END); + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, part.name.c_str(), CURLFORM_BUFFER, part.value.c_str(), CURLFORM_BUFFERPTR, part.data, CURLFORM_BUFFERLENGTH, part.datalen, CURLFORM_END); } else { formdata.push_back({CURLFORM_COPYNAME, part.name.c_str()}); if (part.is_file) { @@ -338,12 +340,22 @@ void Session::Impl::SetNTLM(const NTLM& auth) { curl_easy_setopt(curl_->handle, CURLOPT_USERPWD, auth.GetAuthString()); } -void Session::Impl::SetRedirect(const bool& redirect) { - curl_easy_setopt(curl_->handle, CURLOPT_FOLLOWLOCATION, std::int32_t(redirect)); -} +void Session::Impl::SetRedirect(const Redirect& redirect) { + curl_easy_setopt(curl_->handle, CURLOPT_FOLLOWLOCATION, redirect.follow ? 1L : 0L); + curl_easy_setopt(curl_->handle, CURLOPT_MAXREDIRS, redirect.maximum); -void Session::Impl::SetMaxRedirects(const MaxRedirects& max_redirects) { - curl_easy_setopt(curl_->handle, CURLOPT_MAXREDIRS, max_redirects.number_of_redirects); + // NOLINTNEXTLINE (google-runtime-int) + long mask = 0; + if (any(redirect.post_flags & PostRedirectFlags::POST_301)) { + mask |= CURL_REDIR_POST_301; + } + if (any(redirect.post_flags & PostRedirectFlags::POST_302)) { + mask |= CURL_REDIR_POST_302; + } + if (any(redirect.post_flags & PostRedirectFlags::POST_303)) { + mask |= CURL_REDIR_POST_303; + } + curl_easy_setopt(curl_->handle, CURLOPT_POSTREDIR, mask); } void Session::Impl::SetCookies(const Cookies& cookies) { @@ -353,15 +365,13 @@ void Session::Impl::SetCookies(const Cookies& cookies) { void Session::Impl::SetBody(Body&& body) { hasBodyOrPayload_ = true; - curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, - static_cast(body.str().length())); + curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast(body.str().length())); curl_easy_setopt(curl_->handle, CURLOPT_COPYPOSTFIELDS, body.c_str()); } void Session::Impl::SetBody(const Body& body) { hasBodyOrPayload_ = true; - curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, - static_cast(body.str().length())); + curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast(body.str().length())); curl_easy_setopt(curl_->handle, CURLOPT_POSTFIELDS, body.c_str()); } @@ -449,13 +459,15 @@ void Session::Impl::SetSslOptions(const SslOptions& options) { #if LIBCURL_VERSION_NUM >= 0x072900 curl_easy_setopt(curl_->handle, CURLOPT_SSL_VERIFYSTATUS, options.verify_status ? ON : OFF); #endif + + int maxTlsVersion = options.ssl_version; +#if SUPPORT_MAX_TLS_VERSION + maxTlsVersion |= options.max_version; +#endif + curl_easy_setopt(curl_->handle, CURLOPT_SSLVERSION, // Ignore here since this has been defined by libcurl. - options.ssl_version -#if SUPPORT_MAX_TLS_VERSION - | options.max_version -#endif - ); + maxTlsVersion); #if SUPPORT_SSL_NO_REVOKE if (options.ssl_no_revoke) { curl_easy_setopt(curl_->handle, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); @@ -479,8 +491,7 @@ void Session::Impl::SetSslOptions(const SslOptions& options) { } #endif #if SUPPORT_SESSIONID_CACHE - curl_easy_setopt(curl_->handle, CURLOPT_SSL_SESSIONID_CACHE, - options.session_id_cache ? ON : OFF); + curl_easy_setopt(curl_->handle, CURLOPT_SSL_SESSIONID_CACHE, options.session_id_cache ? ON : OFF); #endif } @@ -491,6 +502,27 @@ void Session::Impl::PrepareDelete() { prepareCommon(); } +cpr_off_t Session::Impl::GetDownloadFileLength() { + cpr_off_t downloadFileLenth = -1; + curl_easy_setopt(curl_->handle, CURLOPT_URL, url_.c_str()); + + std::string protocol = url_.str().substr(0, url_.str().find(':')); + if (proxies_.has(protocol)) { + curl_easy_setopt(curl_->handle, CURLOPT_PROXY, proxies_[protocol].c_str()); + if (proxyAuth_.has(protocol)) { + curl_easy_setopt(curl_->handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERPWD, proxyAuth_[protocol]); + } + } + + curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1); + curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 1); + if (curl_easy_perform(curl_->handle) == CURLE_OK) { + curl_easy_getinfo(curl_->handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &downloadFileLenth); + } + return downloadFileLenth; +} + Response Session::Impl::Delete() { PrepareDelete(); return makeRequest(); @@ -498,7 +530,7 @@ Response Session::Impl::Delete() { Response Session::Impl::Download(const WriteCallback& write) { curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "GET"); + curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1); SetWriteCallback(write); @@ -507,7 +539,7 @@ Response Session::Impl::Download(const WriteCallback& write) { Response Session::Impl::Download(std::ofstream& file) { curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "GET"); + curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl_->handle, CURLOPT_WRITEFUNCTION, cpr::util::writeFileFunction); curl_easy_setopt(curl_->handle, CURLOPT_WRITEDATA, &file); @@ -525,7 +557,7 @@ void Session::Impl::PrepareGet() { curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr); curl_easy_setopt(curl_->handle, CURLOPT_HTTPGET, 1L); } - prepareCommon(); + prepareCommon(); } Response Session::Impl::Get() { @@ -536,7 +568,7 @@ Response Session::Impl::Get() { void Session::Impl::PrepareHead() { curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 1L); curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, nullptr); - prepareCommon(); + prepareCommon(); } Response Session::Impl::Head() { @@ -587,7 +619,7 @@ Response Session::Impl::Post() { void Session::Impl::PreparePut() { curl_easy_setopt(curl_->handle, CURLOPT_NOBODY, 0L); curl_easy_setopt(curl_->handle, CURLOPT_CUSTOMREQUEST, "PUT"); - prepareCommon(); + prepareCommon(); } Response Session::Impl::Put() { @@ -616,8 +648,6 @@ Response Session::Impl::makeDownloadRequest() { curl_easy_setopt(curl_->handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERPWD, proxyAuth_[protocol]); } - } else { - curl_easy_setopt(curl_->handle, CURLOPT_PROXY, ""); } curl_->error[0] = '\0'; @@ -633,14 +663,18 @@ Response Session::Impl::makeDownloadRequest() { CURLcode curl_error = curl_easy_perform(curl_->handle); + if (!headercb_.callback) { + curl_easy_setopt(curl_->handle, CURLOPT_HEADERFUNCTION, nullptr); + curl_easy_setopt(curl_->handle, CURLOPT_HEADERDATA, 0); + } + curl_slist* raw_cookies{nullptr}; curl_easy_getinfo(curl_->handle, CURLINFO_COOKIELIST, &raw_cookies); Cookies cookies = util::parseCookies(raw_cookies); curl_slist_free_all(raw_cookies); std::string errorMsg = curl_->error.data(); - return Response(curl_, "", std::move(header_string), std::move(cookies), - Error(curl_error, std::move(errorMsg))); + return Response(curl_, "", std::move(header_string), std::move(cookies), Error(curl_error, std::move(errorMsg))); } void Session::Impl::prepareCommon() { @@ -665,8 +699,6 @@ void Session::Impl::prepareCommon() { curl_easy_setopt(curl_->handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); curl_easy_setopt(curl_->handle, CURLOPT_PROXYUSERPWD, proxyAuth_[protocol]); } - } else { - curl_easy_setopt(curl_->handle, CURLOPT_PROXY, nullptr); } #if LIBCURL_VERSION_MAJOR >= 7 @@ -700,14 +732,12 @@ void Session::Impl::prepareCommon() { curl_easy_setopt(curl_->handle, CURLOPT_CERTINFO, 1L); } -Response Session::Impl::makeRequest() -{ +Response Session::Impl::makeRequest() { CURLcode curl_error = curl_easy_perform(curl_->handle); return Complete(curl_error); } -Response Session::Impl::Complete(CURLcode curl_error) -{ +Response Session::Impl::Complete(CURLcode curl_error) { curl_slist* raw_cookies{nullptr}; curl_easy_getinfo(curl_->handle, CURLINFO_COOKIELIST, &raw_cookies); Cookies cookies = util::parseCookies(raw_cookies); @@ -717,13 +747,12 @@ Response Session::Impl::Complete(CURLcode curl_error) hasBodyOrPayload_ = false; std::string errorMsg = curl_->error.data(); - return Response(curl_, std::move(response_string_), std::move(header_string_), std::move(cookies), - Error(curl_error, std::move(errorMsg))); + return Response(curl_, std::move(response_string_), std::move(header_string_), std::move(cookies), Error(curl_error, std::move(errorMsg))); } // clang-format off Session::Session() : pimpl_(new Impl()) {} -Session::Session(Session&& old) noexcept = default; +Session::Session(Session&& /*old*/) noexcept = default; Session::~Session() = default; Session& Session::operator=(Session&& old) noexcept = default; void Session::SetReadCallback(const ReadCallback& read) { pimpl_->SetReadCallback(read); } @@ -750,8 +779,7 @@ void Session::SetProxyAuth(const ProxyAuthentication& proxy_auth) { pimpl_->SetP void Session::SetMultipart(const Multipart& multipart) { pimpl_->SetMultipart(multipart); } void Session::SetMultipart(Multipart&& multipart) { pimpl_->SetMultipart(std::move(multipart)); } void Session::SetNTLM(const NTLM& auth) { pimpl_->SetNTLM(auth); } -void Session::SetRedirect(const bool& redirect) { pimpl_->SetRedirect(redirect); } -void Session::SetMaxRedirects(const MaxRedirects& max_redirects) { pimpl_->SetMaxRedirects(max_redirects); } +void Session::SetRedirect(const Redirect& redirect) { pimpl_->SetRedirect(redirect); } void Session::SetCookies(const Cookies& cookies) { pimpl_->SetCookies(cookies); } void Session::SetBody(const Body& body) { pimpl_->SetBody(body); } void Session::SetBody(Body&& body) { pimpl_->SetBody(std::move(body)); } @@ -760,6 +788,7 @@ void Session::SetVerifySsl(const VerifySsl& verify) { pimpl_->SetVerifySsl(verif void Session::SetUnixSocket(const UnixSocket& unix_socket) { pimpl_->SetUnixSocket(unix_socket); } void Session::SetSslOptions(const SslOptions& options) { pimpl_->SetSslOptions(options); } void Session::SetVerbose(const Verbose& verbose) { pimpl_->SetVerbose(verbose); } +void Session::SetInterface(const Interface& iface) { pimpl_->SetInterface(iface); } void Session::SetOption(const ReadCallback& read) { pimpl_->SetReadCallback(read); } void Session::SetOption(const HeaderCallback& header) { pimpl_->SetHeaderCallback(header); } void Session::SetOption(const WriteCallback& write) { pimpl_->SetWriteCallback(write); } @@ -789,8 +818,7 @@ void Session::SetOption(const ProxyAuthentication& proxy_auth) { pimpl_->SetProx void Session::SetOption(const Multipart& multipart) { pimpl_->SetMultipart(multipart); } void Session::SetOption(Multipart&& multipart) { pimpl_->SetMultipart(std::move(multipart)); } void Session::SetOption(const NTLM& auth) { pimpl_->SetNTLM(auth); } -void Session::SetOption(const bool& redirect) { pimpl_->SetRedirect(redirect); } -void Session::SetOption(const MaxRedirects& max_redirects) { pimpl_->SetMaxRedirects(max_redirects); } +void Session::SetOption(const Redirect& redirect) { pimpl_->SetRedirect(redirect); } void Session::SetOption(const Cookies& cookies) { pimpl_->SetCookies(cookies); } void Session::SetOption(const Body& body) { pimpl_->SetBody(body); } void Session::SetOption(Body&& body) { pimpl_->SetBody(std::move(body)); } @@ -799,7 +827,9 @@ void Session::SetOption(const VerifySsl& verify) { pimpl_->SetVerifySsl(verify); void Session::SetOption(const Verbose& verbose) { pimpl_->SetVerbose(verbose); } void Session::SetOption(const UnixSocket& unix_socket) { pimpl_->SetUnixSocket(unix_socket); } void Session::SetOption(const SslOptions& options) { pimpl_->SetSslOptions(options); } +void Session::SetOption(const Interface& iface) { pimpl_->SetInterface(iface); } +cpr_off_t Session::GetDownloadFileLength() { return pimpl_->GetDownloadFileLength(); } Response Session::Delete() { return pimpl_->Delete(); } Response Session::Download(const WriteCallback& write) { return pimpl_->Download(write); } Response Session::Download(std::ofstream& file) { return pimpl_->Download(file); } diff --git a/vendor/CPR/cpr/timeout.cpp b/vendor/CPR/cpr/timeout.cpp index 431b7406..986e3e71 100644 --- a/vendor/CPR/cpr/timeout.cpp +++ b/vendor/CPR/cpr/timeout.cpp @@ -2,28 +2,25 @@ #include #include -#include #include +#include namespace cpr { // No way around since curl uses a long here. // NOLINTNEXTLINE(google-runtime-int) long Timeout::Milliseconds() const { - static_assert(std::is_same::value, - "Following casting expects milliseconds."); + static_assert(std::is_same::value, "Following casting expects milliseconds."); // No way around since curl uses a long here. // NOLINTNEXTLINE(google-runtime-int) if (ms.count() > std::numeric_limits::max()) { - throw std::overflow_error( - "cpr::Timeout: timeout value overflow: " + std::to_string(ms.count()) + " ms."); + throw std::overflow_error("cpr::Timeout: timeout value overflow: " + std::to_string(ms.count()) + " ms."); } // No way around since curl uses a long here. // NOLINTNEXTLINE(google-runtime-int) if (ms.count() < std::numeric_limits::min()) { - throw std::underflow_error( - "cpr::Timeout: timeout value underflow: " + std::to_string(ms.count()) + " ms."); + throw std::underflow_error("cpr::Timeout: timeout value underflow: " + std::to_string(ms.count()) + " ms."); } // No way around since curl uses a long here. diff --git a/vendor/CPR/cpr/util.cpp b/vendor/CPR/cpr/util.cpp index 26e9336d..9cf425ed 100644 --- a/vendor/CPR/cpr/util.cpp +++ b/vendor/CPR/cpr/util.cpp @@ -89,12 +89,12 @@ std::vector split(const std::string& to_split, char delimiter) { size_t readUserFunction(char* ptr, size_t size, size_t nitems, const ReadCallback* read) { size *= nitems; - return read->callback(ptr, size) ? size : CURL_READFUNC_ABORT; + return (*read)(ptr, size) ? size : CURL_READFUNC_ABORT; } size_t headerUserFunction(char* ptr, size_t size, size_t nmemb, const HeaderCallback* header) { size *= nmemb; - return header->callback({ptr, size}) ? size : 0; + return (*header)({ptr, size}) ? size : 0; } size_t writeFunction(char* ptr, size_t size, size_t nmemb, std::string* data) { @@ -111,7 +111,7 @@ size_t writeFileFunction(char* ptr, size_t size, size_t nmemb, std::ofstream* fi size_t writeUserFunction(char* ptr, size_t size, size_t nmemb, const WriteCallback* write) { size *= nmemb; - return write->callback({ptr, size}) ? size : 0; + return (*write)({ptr, size}) ? size : 0; } #if LIBCURL_VERSION_NUM < 0x072000 @@ -121,12 +121,12 @@ int progressUserFunction(const ProgressCallback* progress, double dltotal, doubl int progressUserFunction(const ProgressCallback* progress, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { #endif - return progress->callback(dltotal, dlnow, ultotal, ulnow) ? 0 : 1; + return (*progress)(dltotal, dlnow, ultotal, ulnow) ? 0 : 1; } int debugUserFunction(CURL* /*handle*/, curl_infotype type, char* data, size_t size, const DebugCallback* debug) { - debug->callback(DebugCallback::InfoType(type), std::string(data, size)); + (*debug)(DebugCallback::InfoType(type), std::string(data, size)); return 0; } diff --git a/vendor/CPR/include/cpr/callback.h b/vendor/CPR/include/cpr/callback.h index e7c24a96..b90c1bbd 100644 --- a/vendor/CPR/include/cpr/callback.h +++ b/vendor/CPR/include/cpr/callback.h @@ -12,46 +12,54 @@ class ReadCallback { public: ReadCallback() = default; // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - ReadCallback(std::function p_callback) - : size{-1}, callback{std::move(p_callback)} {} - ReadCallback(cpr_off_t p_size, std::function p_callback) - : size{p_size}, callback{std::move(p_callback)} {} + ReadCallback(std::function p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), size{-1}, callback{std::move(p_callback)} {} + ReadCallback(cpr_off_t p_size, std::function p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), size{p_size}, callback{std::move(p_callback)} {} + bool operator()(char* buffer, size_t& size) const { + return callback(buffer, size, userdata); + } + intptr_t userdata; cpr_off_t size{}; - std::function callback; + std::function callback; }; class HeaderCallback { public: HeaderCallback() = default; // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - HeaderCallback(std::function p_callback) - : callback(std::move(p_callback)) {} + HeaderCallback(std::function p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), callback(std::move(p_callback)) {} + bool operator()(std::string header) const { + return callback(std::move(header), userdata); + } - std::function callback; + intptr_t userdata; + std::function callback; }; class WriteCallback { public: WriteCallback() = default; // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - WriteCallback(std::function p_callback) : callback(std::move(p_callback)) {} + WriteCallback(std::function p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), callback(std::move(p_callback)) {} + bool operator()(std::string data) const { + return callback(std::move(data), userdata); + } - std::function callback; + intptr_t userdata; + std::function callback; }; class ProgressCallback { public: ProgressCallback() = default; // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - ProgressCallback(std::function - p_callback) - : callback(std::move(p_callback)) {} + ProgressCallback(std::function p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), callback(std::move(p_callback)) {} + bool operator()(cpr_off_t downloadTotal, cpr_off_t downloadNow, cpr_off_t uploadTotal, cpr_off_t uploadNow) const { + return callback(downloadTotal, downloadNow, uploadTotal, uploadNow, userdata); + } - std::function - callback; + intptr_t userdata; + std::function callback; }; class DebugCallback { @@ -67,10 +75,13 @@ class DebugCallback { }; DebugCallback() = default; // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - DebugCallback(std::function p_callback) - : callback(std::move(p_callback)) {} + DebugCallback(std::function p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), callback(std::move(p_callback)) {} + void operator()(InfoType type, std::string data) const { + callback(type, std::move(data), userdata); + } - std::function callback; + intptr_t userdata; + std::function callback; }; } // namespace cpr diff --git a/vendor/CPR/include/cpr/cpr.h b/vendor/CPR/include/cpr/cpr.h index 9b7bb199..82330d2c 100644 --- a/vendor/CPR/include/cpr/cpr.h +++ b/vendor/CPR/include/cpr/cpr.h @@ -4,6 +4,8 @@ #include "cpr/api.h" #include "cpr/auth.h" #include "cpr/cprtypes.h" +#include "cpr/interface.h" +#include "cpr/redirect.h" #include "cpr/response.h" #include "cpr/session.h" #include "cpr/status_codes.h" diff --git a/vendor/CPR/include/cpr/interface.h b/vendor/CPR/include/cpr/interface.h new file mode 100644 index 00000000..ea8225d1 --- /dev/null +++ b/vendor/CPR/include/cpr/interface.h @@ -0,0 +1,32 @@ +#ifndef CPR_INTERFACE_H +#define CPR_INTERFACE_H + +#include +#include + +#include "cpr/cprtypes.h" + +namespace cpr { + +class Interface : public StringHolder { + public: + Interface() : StringHolder() {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(const std::string& iface) : StringHolder(iface) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(std::string&& iface) : StringHolder(std::move(iface)) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(const char* iface) : StringHolder(iface) {} + Interface(const char* str, size_t len) : StringHolder(str, len) {} + Interface(const std::initializer_list args) : StringHolder(args) {} + Interface(const Interface& other) = default; + Interface(Interface&& old) noexcept = default; + ~Interface() override = default; + + Interface& operator=(Interface&& old) noexcept = default; + Interface& operator=(const Interface& other) = default; +}; + +} // namespace cpr + +#endif \ No newline at end of file diff --git a/vendor/CPR/include/cpr/max_redirects.h b/vendor/CPR/include/cpr/max_redirects.h deleted file mode 100644 index 0eb5dfd7..00000000 --- a/vendor/CPR/include/cpr/max_redirects.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef CPR_MAX_REDIRECTS_H -#define CPR_MAX_REDIRECTS_H - -#include - -namespace cpr { - -class MaxRedirects { - public: - explicit MaxRedirects(const std::int32_t p_number_of_redirects) - : number_of_redirects(p_number_of_redirects) {} - - std::int32_t number_of_redirects; -}; - -} // namespace cpr - -#endif diff --git a/vendor/CPR/include/cpr/redirect.h b/vendor/CPR/include/cpr/redirect.h new file mode 100644 index 00000000..4ce34777 --- /dev/null +++ b/vendor/CPR/include/cpr/redirect.h @@ -0,0 +1,77 @@ +#ifndef CPR_REDIRECT_H +#define CPR_REDIRECT_H + +#include + +namespace cpr { +enum class PostRedirectFlags : uint8_t { + /** + * Respect RFC 7231 (section 6.4.2 to 6.4.4). + * Same as CURL_REDIR_POST_301 (https://curl.se/libcurl/c/CURLOPT_POSTREDIR.html). + **/ + POST_301 = 0x1 << 0, + /** + * Maintain the request method after a 302 redirect. + * Same as CURL_REDIR_POST_302 (https://curl.se/libcurl/c/CURLOPT_POSTREDIR.html). + **/ + POST_302 = 0x1 << 1, + /** + * Maintain the request method after a 303 redirect. + * Same as CURL_REDIR_POST_303 (https://curl.se/libcurl/c/CURLOPT_POSTREDIR.html). + **/ + POST_303 = 0x1 << 2, + /** + * Default value. + * Convenience option to enable all flags. + * Same as CURL_REDIR_POST_ALL (https://curl.se/libcurl/c/CURLOPT_POSTREDIR.html). + **/ + POST_ALL = POST_301 | POST_302 | POST_303, + /** + * * Convenience option to disable all flags. + **/ + NONE = 0x0 +}; + +PostRedirectFlags operator|(PostRedirectFlags lhs, PostRedirectFlags rhs); +PostRedirectFlags operator&(PostRedirectFlags lhs, PostRedirectFlags rhs); +PostRedirectFlags operator^(PostRedirectFlags lhs, PostRedirectFlags rhs); +PostRedirectFlags operator~(PostRedirectFlags flag); +PostRedirectFlags& operator|=(PostRedirectFlags& lhs, PostRedirectFlags rhs); +PostRedirectFlags& operator&=(PostRedirectFlags& lhs, PostRedirectFlags rhs); +PostRedirectFlags& operator^=(PostRedirectFlags& lhs, PostRedirectFlags rhs); +bool any(PostRedirectFlags flag); + +class Redirect { + public: + /** + * The maximum number of redirects to follow. + * 0: Refuse any redirects. + * -1: Infinite number of redirects. + * Default: 50 + * https://curl.se/libcurl/c/CURLOPT_MAXREDIRS.html + **/ + // NOLINTNEXTLINE (cppcoreguidelines-avoid-magic-numbers, google-runtime-int) + long maximum{50L}; + /** + * Follow 3xx redirects. + * Default: true + * https://curl.se/libcurl/c/CURLOPT_FOLLOWLOCATION.html + **/ + bool follow{true}; + /** + * Flags to control how to act after a redirect for a post request. + * Default: POST_ALL + **/ + PostRedirectFlags post_flags{PostRedirectFlags::POST_ALL}; + + Redirect() = default; + // NOLINTNEXTLINE (google-runtime-int) + Redirect(long p_maximum, bool p_follow, PostRedirectFlags p_post_flags) : maximum(p_maximum), follow(p_follow), post_flags(p_post_flags){}; + // NOLINTNEXTLINE (google-runtime-int) + explicit Redirect(long p_maximum) : maximum(p_maximum){}; + explicit Redirect(bool p_follow) : follow(p_follow){}; + explicit Redirect(PostRedirectFlags p_post_flags) : post_flags(p_post_flags){}; +}; +} // namespace cpr + +#endif diff --git a/vendor/CPR/include/cpr/session.h b/vendor/CPR/include/cpr/session.h index ad0225d1..d272a2af 100644 --- a/vendor/CPR/include/cpr/session.h +++ b/vendor/CPR/include/cpr/session.h @@ -14,15 +14,16 @@ #include "cpr/cprtypes.h" #include "cpr/curlholder.h" #include "cpr/digest.h" +#include "cpr/interface.h" #include "cpr/limit_rate.h" #include "cpr/low_speed.h" -#include "cpr/max_redirects.h" #include "cpr/multipart.h" #include "cpr/ntlm.h" #include "cpr/parameters.h" #include "cpr/payload.h" #include "cpr/proxies.h" #include "cpr/proxyauth.h" +#include "cpr/redirect.h" #include "cpr/response.h" #include "cpr/ssl_options.h" #include "cpr/timeout.h" @@ -62,8 +63,7 @@ class Session { void SetMultipart(Multipart&& multipart); void SetMultipart(const Multipart& multipart); void SetNTLM(const NTLM& auth); - void SetRedirect(const bool& redirect); - void SetMaxRedirects(const MaxRedirects& max_redirects); + void SetRedirect(const Redirect& redirect); void SetCookies(const Cookies& cookies); void SetBody(Body&& body); void SetBody(const Body& body); @@ -77,6 +77,7 @@ class Session { void SetProgressCallback(const ProgressCallback& progress); void SetDebugCallback(const DebugCallback& debug); void SetVerbose(const Verbose& verbose); + void SetInterface(const Interface& iface); // Used in templated functions void SetOption(const Url& url); @@ -103,8 +104,7 @@ class Session { void SetOption(Multipart&& multipart); void SetOption(const Multipart& multipart); void SetOption(const NTLM& auth); - void SetOption(const bool& redirect); - void SetOption(const MaxRedirects& max_redirects); + void SetOption(const Redirect& redirect); void SetOption(const Cookies& cookies); void SetOption(Body&& body); void SetOption(const Body& body); @@ -118,7 +118,9 @@ class Session { void SetOption(const Verbose& verbose); void SetOption(const UnixSocket& unix_socket); void SetOption(const SslOptions& options); + void SetOption(const Interface& iface); + cpr_off_t GetDownloadFileLength(); Response Delete(); Response Download(const WriteCallback& write); Response Download(std::ofstream& file);