diff options
Diffstat (limited to 'Src/external_dependencies/cpr/include')
49 files changed, 3375 insertions, 0 deletions
diff --git a/Src/external_dependencies/cpr/include/CMakeLists.txt b/Src/external_dependencies/cpr/include/CMakeLists.txt new file mode 100644 index 00000000..fbc657a2 --- /dev/null +++ b/Src/external_dependencies/cpr/include/CMakeLists.txt @@ -0,0 +1,67 @@ +cmake_minimum_required(VERSION 3.15)
+
+target_include_directories(cpr PUBLIC
+ $<INSTALL_INTERFACE:include>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/cpr_generated_includes/>)
+
+target_sources(cpr PRIVATE
+ # Header files (useful in IDEs)
+ cpr/accept_encoding.h
+ cpr/api.h
+ cpr/async.h
+ cpr/auth.h
+ cpr/bearer.h
+ cpr/body.h
+ cpr/buffer.h
+ cpr/cert_info.h
+ cpr/cookies.h
+ cpr/cpr.h
+ cpr/cprtypes.h
+ cpr/curlholder.h
+ cpr/curlholder.h
+ cpr/error.h
+ cpr/file.h
+ cpr/limit_rate.h
+ cpr/local_port.h
+ cpr/local_port_range.h
+ cpr/multipart.h
+ cpr/parameters.h
+ cpr/payload.h
+ cpr/proxies.h
+ cpr/proxyauth.h
+ cpr/response.h
+ cpr/session.h
+ cpr/singleton.h
+ cpr/ssl_ctx.h
+ cpr/ssl_options.h
+ cpr/threadpool.h
+ cpr/timeout.h
+ cpr/unix_socket.h
+ cpr/util.h
+ cpr/verbose.h
+ cpr/interface.h
+ cpr/redirect.h
+ cpr/http_version.h
+ cpr/interceptor.h
+ cpr/filesystem.h
+ cpr/curlmultiholder.h
+ cpr/multiperform.h
+ cpr/resolve.h
+ ${PROJECT_BINARY_DIR}/cpr_generated_includes/cpr/cprver.h
+)
+
+# Filesystem
+if(CPR_USE_BOOST_FILESYSTEM)
+ find_package(Boost 1.44 REQUIRED COMPONENTS filesystem)
+ if(Boost_FOUND)
+ target_link_libraries(cpr PUBLIC Boost::filesystem)
+ endif()
+endif()
+
+if (((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1) OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND NOT CPR_USE_BOOST_FILESYSTEM)
+ target_link_libraries(cpr PUBLIC stdc++fs)
+endif()
+
+install(DIRECTORY cpr DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+install(DIRECTORY ${PROJECT_BINARY_DIR}/cpr_generated_includes/cpr DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/Src/external_dependencies/cpr/include/cpr/accept_encoding.h b/Src/external_dependencies/cpr/include/cpr/accept_encoding.h new file mode 100644 index 00000000..e09ad06b --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/accept_encoding.h @@ -0,0 +1,36 @@ +#ifndef CPR_ACCEPT_ENCODING_H +#define CPR_ACCEPT_ENCODING_H + +#include <curl/curlver.h> +#include <initializer_list> +#include <map> +#include <string> +#include <vector> + +namespace cpr { + +enum class AcceptEncodingMethods { + identity, + deflate, + zlib, + gzip, +}; + +static const std::map<AcceptEncodingMethods, std::string> AcceptEncodingMethodsStringMap{{AcceptEncodingMethods::identity, "identity"}, {AcceptEncodingMethods::deflate, "deflate"}, {AcceptEncodingMethods::zlib, "zlib"}, {AcceptEncodingMethods::gzip, "gzip"}}; + +class AcceptEncoding { + public: + AcceptEncoding() = default; + AcceptEncoding(const std::initializer_list<AcceptEncodingMethods>& methods); + AcceptEncoding(const std::initializer_list<std::string>& methods); + + bool empty() const noexcept; + const std::string getString() const; + + private: + std::vector<std::string> methods_; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/api.h b/Src/external_dependencies/cpr/include/cpr/api.h new file mode 100644 index 00000000..7d335237 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/api.h @@ -0,0 +1,321 @@ +#ifndef CPR_API_H +#define CPR_API_H + +#include <fstream> +#include <functional> +#include <future> +#include <string> +#include <utility> + +#include "cpr/async.h" +#include "cpr/auth.h" +#include "cpr/bearer.h" +#include "cpr/cprtypes.h" +#include "cpr/multipart.h" +#include "cpr/multiperform.h" +#include "cpr/payload.h" +#include "cpr/response.h" +#include "cpr/session.h" +#include <cpr/filesystem.h> +#include <utility> + +namespace cpr { + +using AsyncResponse = std::future<Response>; + +namespace priv { + +template <bool processed_header, typename CurrentType> +void set_option_internal(Session& session, CurrentType&& current_option) { + session.SetOption(std::forward<CurrentType>(current_option)); +} + +template <> +inline void set_option_internal<true, Header>(Session& session, Header&& current_option) { + // Header option was already provided -> Update previous header + session.UpdateHeader(std::forward<Header>(current_option)); +} + +template <bool processed_header, typename CurrentType, typename... Ts> +void set_option_internal(Session& session, CurrentType&& current_option, Ts&&... ts) { + set_option_internal<processed_header, CurrentType>(session, std::forward<CurrentType>(current_option)); + + if (std::is_same<CurrentType, Header>::value) { + set_option_internal<true, Ts...>(session, std::forward<Ts>(ts)...); + } else { + set_option_internal<processed_header, Ts...>(session, std::forward<Ts>(ts)...); + } +} + +template <typename... Ts> +void set_option(Session& session, Ts&&... ts) { + set_option_internal<false, Ts...>(session, std::forward<Ts>(ts)...); +} + +// Idea: https://stackoverflow.com/a/19060157 +template <typename Tuple, std::size_t... I> +void apply_set_option_internal(Session& session, Tuple&& t, std::index_sequence<I...>) { + set_option(session, std::get<I>(std::forward<Tuple>(t))...); +} + +// Idea: https://stackoverflow.com/a/19060157 +template <typename Tuple> +void apply_set_option(Session& session, Tuple&& t) { + using Indices = std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>; + apply_set_option_internal(session, std::forward<Tuple>(t), Indices()); +} + +template <typename T> +void setup_multiperform_internal(MultiPerform& multiperform, T&& t) { + std::shared_ptr<Session> session = std::make_shared<Session>(); + apply_set_option(*session, t); + multiperform.AddSession(session); +} + +template <typename T, typename... Ts> +void setup_multiperform_internal(MultiPerform& multiperform, T&& t, Ts&&... ts) { + std::shared_ptr<Session> session = std::make_shared<Session>(); + apply_set_option(*session, t); + multiperform.AddSession(session); + setup_multiperform_internal<Ts...>(multiperform, std::forward<Ts>(ts)...); +} + +template <typename... Ts> +void setup_multiperform(MultiPerform& multiperform, Ts&&... ts) { + setup_multiperform_internal<Ts...>(multiperform, std::forward<Ts>(ts)...); +} + +} // namespace priv + +// Get methods +template <typename... Ts> +Response Get(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Get(); +} + +// Get async methods +template <typename... Ts> +AsyncResponse GetAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Get(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Get callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto GetCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Get(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Post methods +template <typename... Ts> +Response Post(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Post(); +} + +// Post async methods +template <typename... Ts> +AsyncResponse PostAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Post(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Post callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto PostCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Post(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Put methods +template <typename... Ts> +Response Put(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Put(); +} + +// Put async methods +template <typename... Ts> +AsyncResponse PutAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Put(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Put callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto PutCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Put(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Head methods +template <typename... Ts> +Response Head(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Head(); +} + +// Head async methods +template <typename... Ts> +AsyncResponse HeadAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Head(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Head callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto HeadCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Head(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Delete methods +template <typename... Ts> +Response Delete(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Delete(); +} + +// Delete async methods +template <typename... Ts> +AsyncResponse DeleteAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Delete(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Delete callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto DeleteCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Delete(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Options methods +template <typename... Ts> +Response Options(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Options(); +} + +// Options async methods +template <typename... Ts> +AsyncResponse OptionsAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Options(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Options callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto OptionsCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Options(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Patch methods +template <typename... Ts> +Response Patch(Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Patch(); +} + +// Patch async methods +template <typename... Ts> +AsyncResponse PatchAsync(Ts... ts) { + return cpr::async([](Ts... ts_inner) { return Patch(std::move(ts_inner)...); }, std::move(ts)...); +} + +// Patch callback methods +template <typename Then, typename... Ts> +// NOLINTNEXTLINE(fuchsia-trailing-return) +auto PatchCallback(Then then, Ts... ts) { + return cpr::async([](Then then_inner, Ts... ts_inner) { return then_inner(Patch(std::move(ts_inner)...)); }, std::move(then), std::move(ts)...); +} + +// Download methods +template <typename... Ts> +Response Download(std::ofstream& file, Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Download(file); +} + +// Download async method +template <typename... Ts> +AsyncResponse DownloadAsync(fs::path local_path, Ts... ts) { + return std::async( + std::launch::async, + [](fs::path local_path_, Ts... ts_) { +#ifdef CPR_USE_BOOST_FILESYSTEM + std::ofstream f(local_path_.string()); +#else + std::ofstream f(local_path_); +#endif + return Download(f, std::move(ts_)...); + }, + std::move(local_path), std::move(ts)...); +} + +// Download with user callback +template <typename... Ts> +Response Download(const WriteCallback& write, Ts&&... ts) { + Session session; + priv::set_option(session, std::forward<Ts>(ts)...); + return session.Download(write); +} + +// Multi requests +template <typename... Ts> +std::vector<Response> MultiGet(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Get(); +} + +template <typename... Ts> +std::vector<Response> MultiDelete(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Delete(); +} + +template <typename... Ts> +std::vector<Response> MultiPut(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Put(); +} + +template <typename... Ts> +std::vector<Response> MultiHead(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Head(); +} + +template <typename... Ts> +std::vector<Response> MultiOptions(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Options(); +} + +template <typename... Ts> +std::vector<Response> MultiPatch(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Patch(); +} + +template <typename... Ts> +std::vector<Response> MultiPost(Ts&&... ts) { + MultiPerform multiperform; + priv::setup_multiperform<Ts...>(multiperform, std::forward<Ts>(ts)...); + return multiperform.Post(); +} + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/async.h b/Src/external_dependencies/cpr/include/cpr/async.h new file mode 100644 index 00000000..6e7db4c1 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/async.h @@ -0,0 +1,49 @@ +#ifndef CPR_ASYNC_H +#define CPR_ASYNC_H + +#include "singleton.h" +#include "threadpool.h" + +namespace cpr { + +class GlobalThreadPool : public ThreadPool { + CPR_SINGLETON_DECL(GlobalThreadPool) + protected: + GlobalThreadPool() = default; + + public: + ~GlobalThreadPool() override = default; +}; + +/** + * Return a future, calling future.get() will wait task done and return RetType. + * async(fn, args...) + * async(std::bind(&Class::mem_fn, &obj)) + * async(std::mem_fn(&Class::mem_fn, &obj)) + **/ +template <class Fn, class... Args> +auto async(Fn&& fn, Args&&... args) { + return GlobalThreadPool::GetInstance()->Submit(std::forward<Fn>(fn), std::forward<Args>(args)...); +} + +class async { + public: + static void startup(size_t min_threads = CPR_DEFAULT_THREAD_POOL_MIN_THREAD_NUM, size_t max_threads = CPR_DEFAULT_THREAD_POOL_MAX_THREAD_NUM, std::chrono::milliseconds max_idle_ms = CPR_DEFAULT_THREAD_POOL_MAX_IDLE_TIME) { + GlobalThreadPool* gtp = GlobalThreadPool::GetInstance(); + if (gtp->IsStarted()) { + return; + } + gtp->SetMinThreadNum(min_threads); + gtp->SetMaxThreadNum(max_threads); + gtp->SetMaxIdleTime(max_idle_ms); + gtp->Start(); + } + + static void cleanup() { + GlobalThreadPool::ExitInstance(); + } +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/auth.h b/Src/external_dependencies/cpr/include/cpr/auth.h new file mode 100644 index 00000000..3354565f --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/auth.h @@ -0,0 +1,33 @@ +#ifndef CPR_AUTH_H +#define CPR_AUTH_H + +#include <string> + +#include <utility> + +namespace cpr { + +enum class AuthMode { BASIC, DIGEST, NTLM }; + +class Authentication { + public: + Authentication(const std::string& username, const std::string& password, const AuthMode& auth_mode) : auth_string_{username + ":" + password}, auth_mode_{auth_mode} {} + Authentication(std::string&& username, std::string&& password, AuthMode&& auth_mode) : auth_string_{std::move(username) + ":" + std::move(password)}, auth_mode_{std::move(auth_mode)} {} + Authentication(const Authentication& other) = default; + Authentication(Authentication&& old) noexcept = default; + ~Authentication() noexcept; + + Authentication& operator=(Authentication&& old) noexcept = default; + Authentication& operator=(const Authentication& other) = default; + + const char* GetAuthString() const noexcept; + AuthMode GetAuthMode() const noexcept; + + private: + std::string auth_string_; + AuthMode auth_mode_; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/bearer.h b/Src/external_dependencies/cpr/include/cpr/bearer.h new file mode 100644 index 00000000..3d254e2d --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/bearer.h @@ -0,0 +1,36 @@ +#ifndef CPR_BEARER_H +#define CPR_BEARER_H + +#include <curl/curlver.h> +#include <string> + +#include <utility> + +namespace cpr { + +// Only supported with libcurl >= 7.61.0. +// As an alternative use SetHeader and add the token manually. +#if LIBCURL_VERSION_NUM >= 0x073D00 +class Bearer { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Bearer(const std::string& token) : token_string_{token} {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Bearer(std::string&& token) : token_string_{std::move(token)} {} + Bearer(const Bearer& other) = default; + Bearer(Bearer&& old) noexcept = default; + virtual ~Bearer() noexcept; + + Bearer& operator=(Bearer&& old) noexcept = default; + Bearer& operator=(const Bearer& other) = default; + + virtual const char* GetToken() const noexcept; + + protected: + std::string token_string_; +}; +#endif + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/body.h b/Src/external_dependencies/cpr/include/cpr/body.h new file mode 100644 index 00000000..0c191c54 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/body.h @@ -0,0 +1,54 @@ +#ifndef CPR_BODY_H +#define CPR_BODY_H + +#include <exception> +#include <initializer_list> +#include <string> +#include <vector> +#include <fstream> + +#include "cpr/buffer.h" +#include "cpr/cprtypes.h" +#include "cpr/file.h" + +namespace cpr { + +class Body : public StringHolder<Body> { + public: + Body() : StringHolder<Body>() {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Body(const std::string& body) : StringHolder<Body>(body) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Body(std::string&& body) : StringHolder<Body>(std::move(body)) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Body(std::string_view body) : StringHolder<Body>(body) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Body(const char* body) : StringHolder<Body>(body) {} + Body(const char* str, size_t len) : StringHolder<Body>(str, len) {} + Body(const std::initializer_list<std::string> args) : StringHolder<Body>(args) {} + Body(const Buffer& buffer) : StringHolder<Body>(reinterpret_cast<const char*>(buffer.data), static_cast<size_t>(buffer.datalen)) {} + Body(const File& file) { + std::ifstream is(file.filepath, std::ifstream::binary); + if (!is) { + throw std::invalid_argument("Can't open the file for HTTP request body!"); + } + + is.seekg(0, std::ios::end); + const std::streampos length = is.tellg(); + is.seekg(0, std::ios::beg); + std::string buffer; + buffer.resize(static_cast<size_t>(length)); + is.read(&buffer[0], length); + str_ = std::move(buffer); + } + Body(const Body& other) = default; + Body(Body&& old) noexcept = default; + ~Body() override = default; + + Body& operator=(Body&& old) noexcept = default; + Body& operator=(const Body& other) = default; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/buffer.h b/Src/external_dependencies/cpr/include/cpr/buffer.h new file mode 100644 index 00000000..17065eba --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/buffer.h @@ -0,0 +1,35 @@ +#ifndef CPR_BUFFER_H +#define CPR_BUFFER_H + +#include <string> + +#include <cpr/filesystem.h> + +namespace cpr { + +struct Buffer { + using data_t = const unsigned char*; + + template <typename Iterator> + Buffer(Iterator begin, Iterator end, fs::path&& p_filename) + // Ignored here since libcurl reqires a long. + // There is also no way around the reinterpret_cast. + // NOLINTNEXTLINE(google-runtime-int, cppcoreguidelines-pro-type-reinterpret-cast) + : data{reinterpret_cast<data_t>(&(*begin))}, datalen{static_cast<long>(std::distance(begin, end))}, filename(std::move(p_filename)) { + is_random_access_iterator(begin, end); + static_assert(sizeof(*begin) == 1, "Only byte buffers can be used"); + } + + template <typename Iterator> + typename std::enable_if<std::is_same<typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>::value>::type is_random_access_iterator(Iterator /* begin */, Iterator /* end */) {} + + data_t data; + // Ignored here since libcurl reqires a long: + // NOLINTNEXTLINE(google-runtime-int) + long datalen; + const fs::path filename; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/callback.h b/Src/external_dependencies/cpr/include/cpr/callback.h new file mode 100644 index 00000000..e54c4fb1 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/callback.h @@ -0,0 +1,89 @@ +#ifndef CPR_CALLBACK_H +#define CPR_CALLBACK_H + +#include "cprtypes.h" + +#include <functional> +#include <utility> + +namespace cpr { + +class ReadCallback { + public: + ReadCallback() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + ReadCallback(std::function<bool(char* buffer, size_t& size, intptr_t userdata)> 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<bool(char* buffer, size_t& size, intptr_t userdata)> p_callback, intptr_t p_userdata = 0) : userdata(p_userdata), size{p_size}, callback{std::move(p_callback)} {} + bool operator()(char* buffer, size_t& buffer_size) const { + return callback(buffer, buffer_size, userdata); + } + + intptr_t userdata; + cpr_off_t size{}; + std::function<bool(char* buffer, size_t& size, intptr_t userdata)> callback; +}; + +class HeaderCallback { + public: + HeaderCallback() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + HeaderCallback(std::function<bool(std::string header, intptr_t userdata)> 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); + } + + intptr_t userdata; + std::function<bool(std::string header, intptr_t userdata)> callback; +}; + +class WriteCallback { + public: + WriteCallback() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + WriteCallback(std::function<bool(std::string data, intptr_t userdata)> 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); + } + + intptr_t userdata; + std::function<bool(std::string data, intptr_t userdata)> callback; +}; + +class ProgressCallback { + public: + ProgressCallback() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + ProgressCallback(std::function<bool(cpr_off_t downloadTotal, cpr_off_t downloadNow, cpr_off_t uploadTotal, cpr_off_t uploadNow, intptr_t userdata)> 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); + } + + intptr_t userdata; + std::function<bool(cpr_off_t downloadTotal, cpr_off_t downloadNow, cpr_off_t uploadTotal, cpr_off_t uploadNow, intptr_t userdata)> callback; +}; + +class DebugCallback { + public: + enum class InfoType { + TEXT = 0, + HEADER_IN = 1, + HEADER_OUT = 2, + DATA_IN = 3, + DATA_OUT = 4, + SSL_DATA_IN = 5, + SSL_DATA_OUT = 6, + }; + DebugCallback() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + DebugCallback(std::function<void(InfoType type, std::string data, intptr_t userdata)> 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); + } + + intptr_t userdata; + std::function<void(InfoType type, std::string data, intptr_t userdata)> callback; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/cert_info.h b/Src/external_dependencies/cpr/include/cpr/cert_info.h new file mode 100644 index 00000000..6c328ee7 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/cert_info.h @@ -0,0 +1,35 @@ +#ifndef CPR_CERT_INFO_H +#define CPR_CERT_INFO_H + +#include <initializer_list> +#include <string> +#include <vector> + +namespace cpr { + +class CertInfo { + private: + std::vector<std::string> cert_info_; + + public: + CertInfo() = default; + CertInfo(const std::initializer_list<std::string>& entry) : cert_info_{entry} {}; + ~CertInfo() noexcept = default; + + using iterator = std::vector<std::string>::iterator; + using const_iterator = std::vector<std::string>::const_iterator; + + std::string& operator[](const size_t& pos); + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + void emplace_back(const std::string& str); + void push_back(const std::string& str); + void pop_back(); +}; +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/connect_timeout.h b/Src/external_dependencies/cpr/include/cpr/connect_timeout.h new file mode 100644 index 00000000..546e8a58 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/connect_timeout.h @@ -0,0 +1,18 @@ +#ifndef CPR_CONNECT_TIMEOUT_H +#define CPR_CONNECT_TIMEOUT_H + +#include "cpr/timeout.h" + +namespace cpr { + +class ConnectTimeout : public Timeout { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + ConnectTimeout(const std::chrono::milliseconds& duration) : Timeout{duration} {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + ConnectTimeout(const std::int32_t& milliseconds) : Timeout{milliseconds} {} +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/cookies.h b/Src/external_dependencies/cpr/include/cpr/cookies.h new file mode 100644 index 00000000..c018ea4a --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/cookies.h @@ -0,0 +1,92 @@ +#ifndef CPR_COOKIES_H +#define CPR_COOKIES_H + +#include "cpr/curlholder.h" +#include <chrono> +#include <initializer_list> +#include <sstream> +#include <string> +#include <vector> + +namespace cpr { +/** + * EXPIRES_STRING_SIZE is an explicitly static and const variable that could be only accessed within the same namespace and is immutable. + * To be used for "std::array", the expression must have a constant value, so EXPIRES_STRING_SIZE must be a const value. + **/ +static const std::size_t EXPIRES_STRING_SIZE = 100; + +class Cookie { + public: + Cookie() = default; + /** + * Some notes for the default value used by expires: + * std::chrono::system_clock::time_point::min() won't work on Windows due to the min, max clash there. + * So we fall back to std::chrono::system_clock::from_time_t(0) for the minimum value here. + **/ + Cookie(const std::string& name, const std::string& value, const std::string& domain = "", bool p_isIncludingSubdomains = false, const std::string& path = "/", bool p_isHttpsOnly = false, std::chrono::system_clock::time_point expires = std::chrono::system_clock::from_time_t(0)) : name_{name}, value_{value}, domain_{domain}, includeSubdomains_{p_isIncludingSubdomains}, path_{path}, httpsOnly_{p_isHttpsOnly}, expires_{expires} {}; + const std::string GetDomain() const; + bool IsIncludingSubdomains() const; + const std::string GetPath() const; + bool IsHttpsOnly() const; + const std::chrono::system_clock::time_point GetExpires() const; + const std::string GetExpiresString() const; + const std::string GetName() const; + const std::string GetValue() const; + + private: + std::string name_; + std::string value_; + std::string domain_; + bool includeSubdomains_{}; + std::string path_; + bool httpsOnly_{}; + /** + * TODO: Update the implementation using `std::chrono::utc_clock` of C++20 + **/ + std::chrono::system_clock::time_point expires_{}; +}; + +class Cookies { + public: + /** + * Should we URL-encode cookies when making a request. + * Based on RFC6265, it is recommended but not mandatory to encode cookies. + * + * ------- + * To maximize compatibility with user agents, servers that wish to + * store arbitrary data in a cookie-value SHOULD encode that data, for + * example, using Base64 [RFC4648]. + * ------- + * Source: RFC6265 (https://www.ietf.org/rfc/rfc6265.txt) + **/ + bool encode{true}; + + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Cookies(bool p_encode = true) : encode{p_encode} {}; + Cookies(const std::initializer_list<cpr::Cookie>& cookies, bool p_encode = true) : encode{p_encode}, cookies_{cookies} {}; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Cookies(const cpr::Cookie& cookie, bool p_encode = true) : encode{p_encode}, cookies_{cookie} {}; + + cpr::Cookie& operator[](size_t pos); + const std::string GetEncoded(const CurlHolder& holder) const; + + using iterator = std::vector<cpr::Cookie>::iterator; + using const_iterator = std::vector<cpr::Cookie>::const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + void emplace_back(const Cookie& str); + void push_back(const Cookie& str); + void pop_back(); + + private: + std::vector<cpr::Cookie> cookies_; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/cpr.h b/Src/external_dependencies/cpr/include/cpr/cpr.h new file mode 100644 index 00000000..fbad1726 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/cpr.h @@ -0,0 +1,46 @@ +#ifndef CPR_CPR_H +#define CPR_CPR_H + +#include "cpr/api.h" +#include "cpr/auth.h" +#include "cpr/bearer.h" +#include "cpr/callback.h" +#include "cpr/cert_info.h" +#include "cpr/connect_timeout.h" +#include "cpr/cookies.h" +#include "cpr/cprtypes.h" +#include "cpr/cprver.h" +#include "cpr/curl_container.h" +#include "cpr/curlholder.h" +#include "cpr/error.h" +#include "cpr/http_version.h" +#include "cpr/interceptor.h" +#include "cpr/interface.h" +#include "cpr/limit_rate.h" +#include "cpr/local_port.h" +#include "cpr/local_port_range.h" +#include "cpr/low_speed.h" +#include "cpr/multipart.h" +#include "cpr/multiperform.h" +#include "cpr/parameters.h" +#include "cpr/payload.h" +#include "cpr/proxies.h" +#include "cpr/proxyauth.h" +#include "cpr/range.h" +#include "cpr/redirect.h" +#include "cpr/reserve_size.h" +#include "cpr/resolve.h" +#include "cpr/response.h" +#include "cpr/session.h" +#include "cpr/ssl_ctx.h" +#include "cpr/ssl_options.h" +#include "cpr/status_codes.h" +#include "cpr/timeout.h" +#include "cpr/unix_socket.h" +#include "cpr/user_agent.h" +#include "cpr/util.h" +#include "cpr/verbose.h" + +#define CPR_LIBCURL_VERSION_NUM LIBCURL_VERSION_NUM + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/cprtypes.h b/Src/external_dependencies/cpr/include/cpr/cprtypes.h new file mode 100644 index 00000000..4ad9e29b --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/cprtypes.h @@ -0,0 +1,137 @@ +#ifndef CPR_CPR_TYPES_H +#define CPR_CPR_TYPES_H + +#include <curl/system.h> +#include <initializer_list> +#include <map> +#include <memory> +#include <numeric> +#include <string> +#include <string_view> + +namespace cpr { + +/** + * Wrapper around "curl_off_t" to prevent applications from having to link against libcurl. + **/ +using cpr_off_t = curl_off_t; + +template <class T> +class StringHolder { + public: + StringHolder() = default; + explicit StringHolder(const std::string& str) : str_(str) {} + explicit StringHolder(std::string&& str) : str_(std::move(str)) {} + explicit StringHolder(std::string_view str) : str_(str) {} + explicit StringHolder(const char* str) : str_(str) {} + StringHolder(const char* str, size_t len) : str_(str, len) {} + StringHolder(const std::initializer_list<std::string> args) { + str_ = std::accumulate(args.begin(), args.end(), str_); + } + StringHolder(const StringHolder& other) = default; + StringHolder(StringHolder&& old) noexcept = default; + virtual ~StringHolder() = default; + + StringHolder& operator=(StringHolder&& old) noexcept = default; + + StringHolder& operator=(const StringHolder& other) = default; + + explicit operator std::string() const { + return str_; + } + + T operator+(const char* rhs) const { + return T(str_ + rhs); + } + + T operator+(const std::string& rhs) const { + return T(str_ + rhs); + } + + T operator+(const StringHolder<T>& rhs) const { + return T(str_ + rhs.str_); + } + + void operator+=(const char* rhs) { + str_ += rhs; + } + void operator+=(const std::string& rhs) { + str_ += rhs; + } + void operator+=(const StringHolder<T>& rhs) { + str_ += rhs; + } + + bool operator==(const char* rhs) const { + return str_ == rhs; + } + bool operator==(const std::string& rhs) const { + return str_ == rhs; + } + bool operator==(const StringHolder<T>& rhs) const { + return str_ == rhs.str_; + } + + bool operator!=(const char* rhs) const { + return str_.c_str() != rhs; + } + bool operator!=(const std::string& rhs) const { + return str_ != rhs; + } + bool operator!=(const StringHolder<T>& rhs) const { + return str_ != rhs.str_; + } + + const std::string& str() { + return str_; + } + const std::string& str() const { + return str_; + } + const char* c_str() const { + return str_.c_str(); + } + const char* data() const { + return str_.data(); + } + + protected: + std::string str_{}; +}; + +template <class T> +std::ostream& operator<<(std::ostream& os, const StringHolder<T>& s) { + os << s.str(); + return os; +} + +class Url : public StringHolder<Url> { + public: + Url() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Url(const std::string& url) : StringHolder<Url>(url) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Url(std::string&& url) : StringHolder<Url>(std::move(url)) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Url(std::string_view url) : StringHolder<Url>(url) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Url(const char* url) : StringHolder<Url>(url) {} + Url(const char* str, size_t len) : StringHolder<Url>(std::string(str, len)) {} + Url(const std::initializer_list<std::string> args) : StringHolder<Url>(args) {} + Url(const Url& other) = default; + Url(Url&& old) noexcept = default; + ~Url() override = default; + + Url& operator=(Url&& old) noexcept = default; + Url& operator=(const Url& other) = default; +}; + +struct CaseInsensitiveCompare { + bool operator()(const std::string& a, const std::string& b) const noexcept; +}; + +using Header = std::map<std::string, std::string, CaseInsensitiveCompare>; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/curl_container.h b/Src/external_dependencies/cpr/include/cpr/curl_container.h new file mode 100644 index 00000000..91a013b3 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/curl_container.h @@ -0,0 +1,53 @@ +#ifndef CURL_CONTAINER_H +#define CURL_CONTAINER_H + +#include <initializer_list> +#include <memory> +#include <string> +#include <vector> + +#include "cpr/curlholder.h" + + +namespace cpr { + +struct Parameter { + Parameter(const std::string& p_key, const std::string& p_value) : key{p_key}, value{p_value} {} + Parameter(std::string&& p_key, std::string&& p_value) : key{std::move(p_key)}, value{std::move(p_value)} {} + + std::string key; + std::string value; +}; + +struct Pair { + Pair(const std::string& p_key, const std::string& p_value) : key(p_key), value(p_value) {} + Pair(std::string&& p_key, std::string&& p_value) : key(std::move(p_key)), value(std::move(p_value)) {} + + std::string key; + std::string value; +}; + + +template <class T> +class CurlContainer { + public: + /** + * Enables or disables URL encoding for keys and values when calling GetContent(...). + **/ + bool encode = true; + + CurlContainer() = default; + CurlContainer(const std::initializer_list<T>&); + + void Add(const std::initializer_list<T>&); + void Add(const T&); + + const std::string GetContent(const CurlHolder&) const; + + protected: + std::vector<T> containerList_; +}; + +} // namespace cpr + +#endif // diff --git a/Src/external_dependencies/cpr/include/cpr/curlholder.h b/Src/external_dependencies/cpr/include/cpr/curlholder.h new file mode 100644 index 00000000..e6913b81 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/curlholder.h @@ -0,0 +1,54 @@ +#ifndef CPR_CURL_HOLDER_H +#define CPR_CURL_HOLDER_H + +#include <array> +#include <mutex> +#include <string> + +#include <curl/curl.h> + +namespace cpr { +struct CurlHolder { + private: + /** + * Mutex for curl_easy_init(). + * curl_easy_init() is not thread save. + * References: + * https://curl.haxx.se/libcurl/c/curl_easy_init.html + * https://curl.haxx.se/libcurl/c/threadsafe.html + **/ + + // Avoids initalization order problems in a static build + static std::mutex& curl_easy_init_mutex_() { + static std::mutex curl_easy_init_mutex_; + return curl_easy_init_mutex_; + } + + public: + CURL* handle{nullptr}; + struct curl_slist* chunk{nullptr}; + struct curl_slist* resolveCurlList{nullptr}; + struct curl_httppost* formpost{nullptr}; + std::array<char, CURL_ERROR_SIZE> error{}; + + CurlHolder(); + CurlHolder(const CurlHolder& other) = default; + CurlHolder(CurlHolder&& old) noexcept = default; + ~CurlHolder(); + + CurlHolder& operator=(CurlHolder&& old) noexcept = default; + CurlHolder& operator=(const CurlHolder& other) = default; + + /** + * Uses curl_easy_escape(...) for escaping the given string. + **/ + std::string urlEncode(const std::string& s) const; + + /** + * Uses curl_easy_unescape(...) for unescaping the given string. + **/ + std::string urlDecode(const std::string& s) const; +}; +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/curlmultiholder.h b/Src/external_dependencies/cpr/include/cpr/curlmultiholder.h new file mode 100644 index 00000000..ccd504b6 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/curlmultiholder.h @@ -0,0 +1,18 @@ +#ifndef CPR_CURLMULTIHOLDER_H +#define CPR_CURLMULTIHOLDER_H + +#include <curl/curl.h> + +namespace cpr { + +class CurlMultiHolder { + public: + CurlMultiHolder(); + ~CurlMultiHolder(); + + CURLM* handle{nullptr}; +}; + +} // namespace cpr + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/error.h b/Src/external_dependencies/cpr/include/cpr/error.h new file mode 100644 index 00000000..bb59a4cc --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/error.h @@ -0,0 +1,53 @@ +#ifndef CPR_ERROR_H +#define CPR_ERROR_H + +#include <cstdint> +#include <string> + +#include "cpr/cprtypes.h" +#include <utility> + +namespace cpr { + +enum class ErrorCode { + OK = 0, + CONNECTION_FAILURE, + EMPTY_RESPONSE, + HOST_RESOLUTION_FAILURE, + INTERNAL_ERROR, + INVALID_URL_FORMAT, + NETWORK_RECEIVE_ERROR, + NETWORK_SEND_FAILURE, + OPERATION_TIMEDOUT, + PROXY_RESOLUTION_FAILURE, + SSL_CONNECT_ERROR, + SSL_LOCAL_CERTIFICATE_ERROR, + SSL_REMOTE_CERTIFICATE_ERROR, + SSL_CACERT_ERROR, + GENERIC_SSL_ERROR, + UNSUPPORTED_PROTOCOL, + REQUEST_CANCELLED, + TOO_MANY_REDIRECTS, + UNKNOWN_ERROR = 1000, +}; + +class Error { + public: + ErrorCode code = ErrorCode::OK; + std::string message{}; + + Error() = default; + + Error(const std::int32_t& curl_code, std::string&& p_error_message) : code{getErrorCodeForCurlError(curl_code)}, message(std::move(p_error_message)) {} + + explicit operator bool() const { + return code != ErrorCode::OK; + } + + private: + static ErrorCode getErrorCodeForCurlError(std::int32_t curl_code); +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/file.h b/Src/external_dependencies/cpr/include/cpr/file.h new file mode 100644 index 00000000..5c47b638 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/file.h @@ -0,0 +1,55 @@ +#ifndef CPR_FILE_H +#define CPR_FILE_H + +#include <initializer_list> +#include <string> +#include <vector> + +#include <cpr/filesystem.h> + +namespace cpr { + +struct File { + explicit File(std::string&& p_filepath, const std::string& p_overrided_filename = {}) : filepath(std::move(p_filepath)), overrided_filename(p_overrided_filename) {} + explicit File(const std::string& p_filepath, const std::string& p_overrided_filename = {}) : filepath(p_filepath), overrided_filename(p_overrided_filename) {} + + const std::string filepath; + const std::string overrided_filename; + + bool hasOverridedFilename() const noexcept { + return !overrided_filename.empty(); + }; +}; + +class Files { + public: + Files() = default; + Files(const File& p_file) : files{p_file} {}; + Files(const std::initializer_list<File>& p_files) : files{p_files} {}; + Files(const std::initializer_list<std::string>& p_filepaths) { + for (const std::string& filepath : p_filepaths) { + files.emplace_back(File(filepath)); + } + }; + ~Files() noexcept = default; + + using iterator = std::vector<File>::iterator; + using const_iterator = std::vector<File>::const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + void emplace_back(const File& file); + void push_back(const File& file); + void pop_back(); + + private: + std::vector<File> files; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/filesystem.h b/Src/external_dependencies/cpr/include/cpr/filesystem.h new file mode 100644 index 00000000..f498f80f --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/filesystem.h @@ -0,0 +1,19 @@ +#ifndef CPR_FILESYSTEM_H +#define CPR_FILESYSTEM_H + +// Include filesystem into the namespace "fs" from either "filesystem" or "experimental/filesystem" or "boost/filesystem" +#if __has_include(<filesystem>) +#include <filesystem> +namespace fs = std::filesystem; +#elif __has_include("experimental/filesystem") +#include <experimental/filesystem> +namespace fs = std::experimental::filesystem; +//cppcheck-suppress preprocessorErrorDirective +#elif defined(CPR_USE_BOOST_FILESYSTEM) && __has_include(<boost/filesystem.hpp>) +#include <boost/filesystem.hpp> +namespace fs = boost::filesystem; +#else +#error "Failed to include <filesystem> header!" +#endif + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/http_version.h b/Src/external_dependencies/cpr/include/cpr/http_version.h new file mode 100644 index 00000000..45b50287 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/http_version.h @@ -0,0 +1,67 @@ +#ifndef CPR_HTTP_VERSION_H +#define CPR_HTTP_VERSION_H + +#include <curl/curlver.h> + +namespace cpr { +enum class HttpVersionCode { + /** + * Let libcurl decide which version is the best. + **/ + VERSION_NONE, + /** + * Enforce HTTP 1.0 requests. + **/ + VERSION_1_0, + /** + * Enforce HTTP 1.1 requests. + **/ + VERSION_1_1, +#if LIBCURL_VERSION_NUM >= 0x072100 // 7.33.0 + /** + * Attempt HTTP 2.0 requests. + * Fallback to HTTP 1.1 if negotiation fails. + **/ + VERSION_2_0, +#endif +#if LIBCURL_VERSION_NUM >= 0x072F00 // 7.47.0 + /** + * Attempt HTTP 2.0 for HTTPS requests only. + * Fallback to HTTP 1.1 if negotiation fails. + * HTTP 1.1 will be used for HTTP connections. + **/ + VERSION_2_0_TLS, +#endif +#if LIBCURL_VERSION_NUM >= 0x073100 // 7.49.0 + /** + * Start HTTP 2.0 for HTTP requests. + * Requires prior knowledge that the server supports HTTP 2.0. + * For HTTPS requests we will negotiate the protocol version in the TLS handshake. + **/ + VERSION_2_0_PRIOR_KNOWLEDGE, +#endif +#if LIBCURL_VERSION_NUM >= 0x074200 // 7.66.0 + /** + * Attempt HTTP 3.0 requests. + * Requires prior knowledge that the server supports HTTP 3.0 since there is no gracefully downgrade. + * Fallback to HTTP 1.1 if negotiation fails. + **/ + VERSION_3_0 +#endif +}; + +class HttpVersion { + public: + /** + * The HTTP version that should be used by libcurl when initiating a HTTP(S) connection. + * Default: HttpVersionCode::VERSION_NONE + **/ + HttpVersionCode code = HttpVersionCode::VERSION_NONE; + + HttpVersion() = default; + explicit HttpVersion(HttpVersionCode _code) : code(_code) {} +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/interceptor.h b/Src/external_dependencies/cpr/include/cpr/interceptor.h new file mode 100644 index 00000000..fdfe69c2 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/interceptor.h @@ -0,0 +1,36 @@ +#ifndef CPR_INTERCEPTOR_H +#define CPR_INTERCEPTOR_H + +#include "cpr/response.h" +#include "cpr/session.h" + +namespace cpr { + +class Interceptor { + public: + enum class ProceedHttpMethod { + GET_REQUEST = 0, + POST_REQUEST, + PUT_REQUEST, + DELETE_REQUEST, + PATCH_REQUEST, + HEAD_REQUEST, + OPTIONS_REQUEST, + DOWNLOAD_CALLBACK_REQUEST, + DOWNLOAD_FILE_REQUEST, + }; + + virtual ~Interceptor() = default; + virtual Response intercept(Session& session) = 0; + + protected: + static Response proceed(Session& session); + static Response proceed(Session& session, ProceedHttpMethod httpMethod); + static Response proceed(Session& session, ProceedHttpMethod httpMethod, std::ofstream& file); + static Response proceed(Session& session, ProceedHttpMethod httpMethod, const WriteCallback& write); +}; + +} // namespace cpr + + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/interface.h b/Src/external_dependencies/cpr/include/cpr/interface.h new file mode 100644 index 00000000..ded2fda1 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/interface.h @@ -0,0 +1,34 @@ +#ifndef CPR_INTERFACE_H +#define CPR_INTERFACE_H + +#include <initializer_list> +#include <string> + +#include "cpr/cprtypes.h" + +namespace cpr { + +class Interface : public StringHolder<Interface> { + public: + Interface() : StringHolder<Interface>() {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(const std::string& iface) : StringHolder<Interface>(iface) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(std::string&& iface) : StringHolder<Interface>(std::move(iface)) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(std::string_view iface) : StringHolder<Interface>(iface) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Interface(const char* iface) : StringHolder<Interface>(iface) {} + Interface(const char* str, size_t len) : StringHolder<Interface>(str, len) {} + Interface(const std::initializer_list<std::string> args) : StringHolder<Interface>(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/Src/external_dependencies/cpr/include/cpr/limit_rate.h b/Src/external_dependencies/cpr/include/cpr/limit_rate.h new file mode 100644 index 00000000..2b0e8a24 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/limit_rate.h @@ -0,0 +1,18 @@ +#ifndef CPR_SPEED_LIMIT_H +#define CPR_SPEED_LIMIT_H + +#include <cstdint> + +namespace cpr { + +class LimitRate { + public: + LimitRate(const std::int64_t p_downrate, const std::int64_t p_uprate) : downrate(p_downrate), uprate(p_uprate) {} + + std::int64_t downrate = 0; + std::int64_t uprate = 0; +}; + +} // namespace cpr + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/local_port.h b/Src/external_dependencies/cpr/include/cpr/local_port.h new file mode 100644 index 00000000..e853425a --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/local_port.h @@ -0,0 +1,23 @@ +#ifndef CPR_LOCAL_PORT_H +#define CPR_LOCAL_PORT_H + +#include <cstdint> + +namespace cpr { + +class LocalPort { + public: + // NOLINTNEXTLINE(google-explicit-constructor) + LocalPort(const std::uint16_t p_localport) : localport_(p_localport) {} + + operator std::uint16_t() const { + return localport_; + } + + private: + std::uint16_t localport_ = 0; +}; + +} // namespace cpr + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/local_port_range.h b/Src/external_dependencies/cpr/include/cpr/local_port_range.h new file mode 100644 index 00000000..cc2d7e25 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/local_port_range.h @@ -0,0 +1,23 @@ +#ifndef CPR_LOCAL_PORT_RANGE_H +#define CPR_LOCAL_PORT_RANGE_H + +#include <cstdint> + +namespace cpr { + +class LocalPortRange { + public: + // NOLINTNEXTLINE(google-explicit-constructor) + LocalPortRange(const std::uint16_t p_localportrange) : localportrange_(p_localportrange) {} + + operator std::uint16_t() const { + return localportrange_; + } + + private: + std::uint16_t localportrange_ = 0; +}; + +} // namespace cpr + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/low_speed.h b/Src/external_dependencies/cpr/include/cpr/low_speed.h new file mode 100644 index 00000000..ff77fd2e --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/low_speed.h @@ -0,0 +1,18 @@ +#ifndef CPR_LOW_SPEED_H +#define CPR_LOW_SPEED_H + +#include <cstdint> + +namespace cpr { + +class LowSpeed { + public: + LowSpeed(const std::int32_t p_limit, const std::int32_t p_time) : limit(p_limit), time(p_time) {} + + std::int32_t limit; + std::int32_t time; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/multipart.h b/Src/external_dependencies/cpr/include/cpr/multipart.h new file mode 100644 index 00000000..1c4c9dbf --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/multipart.h @@ -0,0 +1,45 @@ +#ifndef CPR_MULTIPART_H +#define CPR_MULTIPART_H + +#include <cstdint> +#include <initializer_list> +#include <string> +#include <type_traits> +#include <vector> + +#include "buffer.h" +#include "file.h" + +namespace cpr { + +struct Part { + Part(const std::string& p_name, const std::string& p_value, const std::string& p_content_type = {}) : name{p_name}, value{p_value}, content_type{p_content_type}, is_file{false}, is_buffer{false} {} + Part(const std::string& p_name, const std::int32_t& p_value, const std::string& p_content_type = {}) : name{p_name}, value{std::to_string(p_value)}, content_type{p_content_type}, is_file{false}, is_buffer{false} {} + Part(const std::string& p_name, const Files& p_files, const std::string& p_content_type = {}) : name{p_name}, value{}, content_type{p_content_type}, is_file{true}, is_buffer{false}, files{p_files} {} + Part(const std::string& p_name, Files&& p_files, const std::string& p_content_type = {}) : name{p_name}, value{}, content_type{p_content_type}, is_file{true}, is_buffer{false}, files{std::move(p_files)} {} + Part(const std::string& p_name, const Buffer& buffer, const std::string& p_content_type = {}) : name{p_name}, value{buffer.filename.string()}, content_type{p_content_type}, data{buffer.data}, datalen{buffer.datalen}, is_file{false}, is_buffer{true} {} + + std::string name; + // We don't use fs::path here, as this leads to problems using windows + std::string value; + std::string content_type; + Buffer::data_t data{nullptr}; + // Ignored here since libcurl reqires a long: + // NOLINTNEXTLINE(google-runtime-int) + long datalen{0}; + bool is_file; + bool is_buffer; + + Files files; +}; + +class Multipart { + public: + Multipart(const std::initializer_list<Part>& parts); + + std::vector<Part> parts; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/multiperform.h b/Src/external_dependencies/cpr/include/cpr/multiperform.h new file mode 100644 index 00000000..67f1637c --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/multiperform.h @@ -0,0 +1,119 @@ +#ifndef CPR_MULTIPERFORM_H +#define CPR_MULTIPERFORM_H + +#include <functional> +#include <memory> +#include <stdexcept> +#include <vector> + +#include "cpr/curlmultiholder.h" +#include "cpr/response.h" +#include "cpr/session.h" + +namespace cpr { + +class MultiPerform { + public: + enum class HttpMethod { + UNDEFINED = 0, + GET_REQUEST, + POST_REQUEST, + PUT_REQUEST, + DELETE_REQUEST, + PATCH_REQUEST, + HEAD_REQUEST, + OPTIONS_REQUEST, + DOWNLOAD_REQUEST, + }; + + MultiPerform(); + ~MultiPerform(); + + std::vector<Response> Get(); + std::vector<Response> Delete(); + template <typename... DownloadArgTypes> + std::vector<Response> Download(DownloadArgTypes... args); + std::vector<Response> Put(); + std::vector<Response> Head(); + std::vector<Response> Options(); + std::vector<Response> Patch(); + std::vector<Response> Post(); + + std::vector<Response> Perform(); + template <typename... DownloadArgTypes> + std::vector<Response> PerformDownload(DownloadArgTypes... args); + + void AddSession(std::shared_ptr<Session>& session, HttpMethod method = HttpMethod::UNDEFINED); + void RemoveSession(const std::shared_ptr<Session>& session); + + private: + void SetHttpMethod(HttpMethod method); + + void PrepareSessions(); + template <typename CurrentDownloadArgType, typename... DownloadArgTypes> + void PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg, DownloadArgTypes... args); + template <typename CurrentDownloadArgType> + void PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg); + void PrepareDownloadSession(size_t sessions_index, std::ofstream& file); + void PrepareDownloadSession(size_t sessions_index, const WriteCallback& write); + + void PrepareGet(); + void PrepareDelete(); + void PreparePut(); + void PreparePatch(); + void PrepareHead(); + void PrepareOptions(); + void PreparePost(); + template <typename... DownloadArgTypes> + void PrepareDownload(DownloadArgTypes... args); + + std::vector<Response> MakeRequest(); + std::vector<Response> MakeDownloadRequest(); + + void DoMultiPerform(); + std::vector<Response> ReadMultiInfo(std::function<Response(Session&, CURLcode)>&& complete_function); + + std::vector<std::pair<std::shared_ptr<Session>, HttpMethod>> sessions_; + std::unique_ptr<CurlMultiHolder> multicurl_; + bool is_download_multi_perform{false}; +}; + +template <typename CurrentDownloadArgType> +void MultiPerform::PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg) { + PrepareDownloadSession(sessions_index, current_arg); +} + +template <typename CurrentDownloadArgType, typename... DownloadArgTypes> +void MultiPerform::PrepareDownloadSessions(size_t sessions_index, CurrentDownloadArgType current_arg, DownloadArgTypes... args) { + PrepareDownloadSession(sessions_index, current_arg); + PrepareDownloadSessions<DownloadArgTypes...>(sessions_index + 1, args...); +} + + +template <typename... DownloadArgTypes> +void MultiPerform::PrepareDownload(DownloadArgTypes... args) { + SetHttpMethod(HttpMethod::DOWNLOAD_REQUEST); + PrepareDownloadSessions<DownloadArgTypes...>(0, args...); +} + +template <typename... DownloadArgTypes> +std::vector<Response> MultiPerform::Download(DownloadArgTypes... args) { + if (sizeof...(args) != sessions_.size()) { + throw std::invalid_argument("Number of download arguments has to match the number of sessions added to the multiperform!"); + } + PrepareDownload(args...); + return MakeDownloadRequest(); +} + +template <typename... DownloadArgTypes> +std::vector<Response> MultiPerform::PerformDownload(DownloadArgTypes... args) { + if (sizeof...(args) != sessions_.size()) { + throw std::invalid_argument("Number of download arguments has to match the number of sessions added to the multiperform!"); + } + PrepareDownloadSessions<DownloadArgTypes...>(0, args...); + return MakeDownloadRequest(); +} + +} // namespace cpr + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/parameters.h b/Src/external_dependencies/cpr/include/cpr/parameters.h new file mode 100644 index 00000000..0e34d4d7 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/parameters.h @@ -0,0 +1,18 @@ +#ifndef CPR_PARAMETERS_H +#define CPR_PARAMETERS_H + +#include <initializer_list> + +#include "cpr/curl_container.h" + +namespace cpr { + +class Parameters : public CurlContainer<Parameter> { + public: + Parameters() = default; + Parameters(const std::initializer_list<Parameter>& parameters); +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/payload.h b/Src/external_dependencies/cpr/include/cpr/payload.h new file mode 100644 index 00000000..686b540e --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/payload.h @@ -0,0 +1,23 @@ +#ifndef CPR_PAYLOAD_H +#define CPR_PAYLOAD_H + +#include <initializer_list> + +#include "cpr/curl_container.h" + + +namespace cpr { +class Payload : public CurlContainer<Pair> { + public: + template <class It> + Payload(const It begin, const It end) { + for (It pair = begin; pair != end; ++pair) { + Add(*pair); + } + } + Payload(const std::initializer_list<Pair>& pairs); +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/proxies.h b/Src/external_dependencies/cpr/include/cpr/proxies.h new file mode 100644 index 00000000..6970442d --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/proxies.h @@ -0,0 +1,23 @@ +#ifndef CPR_PROXIES_H +#define CPR_PROXIES_H + +#include <initializer_list> +#include <map> +#include <string> + +namespace cpr { +class Proxies { + public: + Proxies() = default; + Proxies(const std::initializer_list<std::pair<const std::string, std::string>>& hosts); + Proxies(const std::map<std::string, std::string>& hosts); + + bool has(const std::string& protocol) const; + const std::string& operator[](const std::string& protocol); + + private: + std::map<std::string, std::string> hosts_; +}; +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/proxyauth.h b/Src/external_dependencies/cpr/include/cpr/proxyauth.h new file mode 100644 index 00000000..16369ff1 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/proxyauth.h @@ -0,0 +1,44 @@ +#ifndef CPR_PROXYAUTH_H +#define CPR_PROXYAUTH_H + +#include <initializer_list> +#include <map> + +#include "cpr/auth.h" +#include "cpr/util.h" + +namespace cpr { +class EncodedAuthentication { + public: + EncodedAuthentication() : auth_string_{""} {} + EncodedAuthentication(const std::string& username, const std::string& password) : auth_string_{cpr::util::urlEncode(username) + ":" + cpr::util::urlEncode(password)} {} + EncodedAuthentication(std::string&& username, std::string&& password) : auth_string_{cpr::util::urlEncode(std::move(username)) + ":" + cpr::util::urlEncode(std::move(password))} {} + EncodedAuthentication(const EncodedAuthentication& other) = default; + EncodedAuthentication(EncodedAuthentication&& old) noexcept = default; + virtual ~EncodedAuthentication() noexcept; + + EncodedAuthentication& operator=(EncodedAuthentication&& old) noexcept = default; + EncodedAuthentication& operator=(const EncodedAuthentication& other) = default; + + const char* GetAuthString() const noexcept; + + protected: + std::string auth_string_; +}; + +class ProxyAuthentication { + public: + ProxyAuthentication() = default; + ProxyAuthentication(const std::initializer_list<std::pair<const std::string, EncodedAuthentication>>& auths) : proxyAuth_{auths} {} + ProxyAuthentication(const std::map<std::string, EncodedAuthentication>& auths) : proxyAuth_{auths} {} + + bool has(const std::string& protocol) const; + const char* operator[](const std::string& protocol); + + private: + std::map<std::string, EncodedAuthentication> proxyAuth_; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/range.h b/Src/external_dependencies/cpr/include/cpr/range.h new file mode 100644 index 00000000..2c5a145d --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/range.h @@ -0,0 +1,44 @@ +#ifndef CPR_RANGE_H +#define CPR_RANGE_H + +#include <cstdint> +#include <optional> + +namespace cpr { + +class Range { + public: + Range(const std::optional<std::int64_t> p_resume_from = std::nullopt, const std::optional<std::int64_t> p_finish_at = std::nullopt) { + resume_from = p_resume_from.value_or(0); + finish_at = p_finish_at.value_or(-1); + } + + std::int64_t resume_from; + std::int64_t finish_at; + + const std::string str() const { + std::string from_str = (resume_from < 0U) ? "" : std::to_string(resume_from); + std::string to_str = (finish_at < 0U) ? "" : std::to_string(finish_at); + return from_str + "-" + to_str; + } +}; + +class MultiRange { + public: + MultiRange(std::initializer_list<Range> rs) : ranges{rs} {} + + const std::string str() const { + std::string multi_range_string{}; + for (Range range : ranges) { + multi_range_string += ((multi_range_string.empty()) ? "" : ", ") + range.str(); + } + return multi_range_string; + } + + private: + std::vector<Range> ranges; +}; // namespace cpr + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/redirect.h b/Src/external_dependencies/cpr/include/cpr/redirect.h new file mode 100644 index 00000000..32b4372c --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/redirect.h @@ -0,0 +1,84 @@ +#ifndef CPR_REDIRECT_H +#define CPR_REDIRECT_H + +#include <cstdint> + +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 (google-runtime-int) + long maximum{50L}; + /** + * Follow 3xx redirects. + * Default: true + * https://curl.se/libcurl/c/CURLOPT_FOLLOWLOCATION.html + **/ + bool follow{true}; + /** + * Continue to send authentication (user+password) credentials when following locations, even when hostname changed. + * Default: false + * https://curl.se/libcurl/c/CURLOPT_UNRESTRICTED_AUTH.html + **/ + bool cont_send_cred{false}; + /** + * 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, bool p_cont_send_cred, PostRedirectFlags p_post_flags) : maximum(p_maximum), follow(p_follow), cont_send_cred(p_cont_send_cred), 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){}; + Redirect(bool p_follow, bool p_cont_send_cred) : follow(p_follow), cont_send_cred(p_cont_send_cred){}; + explicit Redirect(PostRedirectFlags p_post_flags) : post_flags(p_post_flags){}; +}; +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/reserve_size.h b/Src/external_dependencies/cpr/include/cpr/reserve_size.h new file mode 100644 index 00000000..5eae4c80 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/reserve_size.h @@ -0,0 +1,17 @@ +#ifndef CPR_RESERVE_SIZE_H +#define CPR_RESERVE_SIZE_H + +#include <cstdint> + +namespace cpr { + +class ReserveSize { + public: + ReserveSize(const size_t _size) : size(_size) {} + + size_t size = 0; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/resolve.h b/Src/external_dependencies/cpr/include/cpr/resolve.h new file mode 100644 index 00000000..86a7c892 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/resolve.h @@ -0,0 +1,23 @@ +#ifndef CPR_RESOLVE_H +#define CPR_RESOLVE_H + +#include <string> +#include <set> + +namespace cpr { + class Resolve { + public: + std::string host; + std::string addr; + std::set<uint16_t> ports; + + Resolve(const std::string& host_param, const std::string& addr_param, const std::set<uint16_t>& ports_param = std::set<uint16_t>{80U, 443U}): host(host_param), addr(addr_param), ports(ports_param) { + if (this->ports.empty()) { + this->ports.insert(80U); + this->ports.insert(443U); + } + } + }; +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/response.h b/Src/external_dependencies/cpr/include/cpr/response.h new file mode 100644 index 00000000..5c296daa --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/response.h @@ -0,0 +1,58 @@ +#ifndef CPR_RESPONSE_H +#define CPR_RESPONSE_H + +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "cpr/cert_info.h" +#include "cpr/cookies.h" +#include "cpr/cprtypes.h" +#include "cpr/error.h" +#include "cpr/ssl_options.h" +#include "cpr/util.h" + +namespace cpr { + +class MultiPerform; + +class Response { + private: + friend MultiPerform; + std::shared_ptr<CurlHolder> curl_{nullptr}; + + public: + // Ignored here since libcurl uses a long for this. + // NOLINTNEXTLINE(google-runtime-int) + long status_code{}; + std::string text{}; + Header header{}; + Url url{}; + double elapsed{}; + Cookies cookies{}; + Error error{}; + std::string raw_header{}; + std::string status_line{}; + std::string reason{}; + cpr_off_t uploaded_bytes{}; + cpr_off_t downloaded_bytes{}; + // Ignored here since libcurl uses a long for this. + // NOLINTNEXTLINE(google-runtime-int) + long redirect_count{}; + + Response() = default; + Response(std::shared_ptr<CurlHolder> curl, std::string&& p_text, std::string&& p_header_string, Cookies&& p_cookies, Error&& p_error); + std::vector<CertInfo> GetCertInfos(); + Response(const Response& other) = default; + Response(Response&& old) noexcept = default; + ~Response() noexcept = default; + + Response& operator=(Response&& old) noexcept = default; + Response& operator=(const Response& other) = default; +}; +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/session.h b/Src/external_dependencies/cpr/include/cpr/session.h new file mode 100644 index 00000000..7b500926 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/session.h @@ -0,0 +1,297 @@ +#ifndef CPR_SESSION_H +#define CPR_SESSION_H + +#include <cstdint> +#include <fstream> +#include <future> +#include <memory> +#include <queue> + +#include "cpr/accept_encoding.h" +#include "cpr/auth.h" +#include "cpr/bearer.h" +#include "cpr/body.h" +#include "cpr/callback.h" +#include "cpr/connect_timeout.h" +#include "cpr/cookies.h" +#include "cpr/cprtypes.h" +#include "cpr/curlholder.h" +#include "cpr/http_version.h" +#include "cpr/interface.h" +#include "cpr/limit_rate.h" +#include "cpr/local_port.h" +#include "cpr/local_port_range.h" +#include "cpr/low_speed.h" +#include "cpr/multipart.h" +#include "cpr/parameters.h" +#include "cpr/payload.h" +#include "cpr/proxies.h" +#include "cpr/proxyauth.h" +#include "cpr/range.h" +#include "cpr/redirect.h" +#include "cpr/reserve_size.h" +#include "cpr/resolve.h" +#include "cpr/response.h" +#include "cpr/ssl_options.h" +#include "cpr/timeout.h" +#include "cpr/unix_socket.h" +#include "cpr/user_agent.h" +#include "cpr/verbose.h" + +namespace cpr { + +using AsyncResponse = std::future<Response>; + +class Interceptor; +class MultiPerform; + +class Session : public std::enable_shared_from_this<Session> { + public: + Session(); + Session(const Session& other) = delete; + Session(Session&& old) = default; + + ~Session() = default; + + Session& operator=(Session&& old) noexcept = default; + Session& operator=(const Session& other) = delete; + + void SetUrl(const Url& url); + void SetParameters(const Parameters& parameters); + void SetParameters(Parameters&& parameters); + void SetHeader(const Header& header); + void UpdateHeader(const Header& header); + void SetTimeout(const Timeout& timeout); + void SetConnectTimeout(const ConnectTimeout& timeout); + void SetAuth(const Authentication& auth); +// Only supported with libcurl >= 7.61.0. +// As an alternative use SetHeader and add the token manually. +#if LIBCURL_VERSION_NUM >= 0x073D00 + void SetBearer(const Bearer& token); +#endif + void SetUserAgent(const UserAgent& ua); + void SetPayload(Payload&& payload); + void SetPayload(const Payload& payload); + void SetProxies(Proxies&& proxies); + void SetProxies(const Proxies& proxies); + void SetProxyAuth(ProxyAuthentication&& proxy_auth); + void SetProxyAuth(const ProxyAuthentication& proxy_auth); + void SetMultipart(Multipart&& multipart); + void SetMultipart(const Multipart& multipart); + void SetRedirect(const Redirect& redirect); + void SetCookies(const Cookies& cookies); + void SetBody(Body&& body); + void SetBody(const Body& body); + void SetLowSpeed(const LowSpeed& low_speed); + void SetVerifySsl(const VerifySsl& verify); + void SetUnixSocket(const UnixSocket& unix_socket); + void SetSslOptions(const SslOptions& options); + void SetReadCallback(const ReadCallback& read); + void SetHeaderCallback(const HeaderCallback& header); + void SetWriteCallback(const WriteCallback& write); + void SetProgressCallback(const ProgressCallback& progress); + void SetDebugCallback(const DebugCallback& debug); + void SetVerbose(const Verbose& verbose); + void SetInterface(const Interface& iface); + void SetLocalPort(const LocalPort& local_port); + void SetLocalPortRange(const LocalPortRange& local_port_range); + void SetHttpVersion(const HttpVersion& version); + void SetRange(const Range& range); + void SetResolve(const Resolve& resolve); + void SetResolves(const std::vector<Resolve>& resolves); + void SetMultiRange(const MultiRange& multi_range); + void SetReserveSize(const ReserveSize& reserve_size); + void SetAcceptEncoding(const AcceptEncoding& accept_encoding); + void SetAcceptEncoding(AcceptEncoding&& accept_encoding); + void SetLimitRate(const LimitRate& limit_rate); + + // Used in templated functions + void SetOption(const Url& url); + void SetOption(const Parameters& parameters); + void SetOption(Parameters&& parameters); + void SetOption(const Header& header); + void SetOption(const Timeout& timeout); + void SetOption(const ConnectTimeout& timeout); + void SetOption(const Authentication& auth); +// Only supported with libcurl >= 7.61.0. +// As an alternative use SetHeader and add the token manually. +#if LIBCURL_VERSION_NUM >= 0x073D00 + void SetOption(const Bearer& auth); +#endif + void SetOption(const UserAgent& ua); + void SetOption(Payload&& payload); + void SetOption(const Payload& payload); + void SetOption(const LimitRate& limit_rate); + void SetOption(Proxies&& proxies); + void SetOption(const Proxies& proxies); + void SetOption(ProxyAuthentication&& proxy_auth); + void SetOption(const ProxyAuthentication& proxy_auth); + void SetOption(Multipart&& multipart); + void SetOption(const Multipart& multipart); + void SetOption(const Redirect& redirect); + void SetOption(const Cookies& cookies); + void SetOption(Body&& body); + void SetOption(const Body& body); + void SetOption(const ReadCallback& read); + void SetOption(const HeaderCallback& header); + void SetOption(const WriteCallback& write); + void SetOption(const ProgressCallback& progress); + void SetOption(const DebugCallback& debug); + void SetOption(const LowSpeed& low_speed); + void SetOption(const VerifySsl& verify); + void SetOption(const Verbose& verbose); + void SetOption(const UnixSocket& unix_socket); + void SetOption(const SslOptions& options); + void SetOption(const Interface& iface); + void SetOption(const LocalPort& local_port); + void SetOption(const LocalPortRange& local_port_range); + void SetOption(const HttpVersion& version); + void SetOption(const Range& range); + void SetOption(const MultiRange& multi_range); + void SetOption(const ReserveSize& reserve_size); + void SetOption(const AcceptEncoding& accept_encoding); + void SetOption(AcceptEncoding&& accept_encoding); + void SetOption(const Resolve& resolve); + void SetOption(const std::vector<Resolve>& resolves); + + cpr_off_t GetDownloadFileLength(); + /** + * Attempt to preallocate enough memory for specified number of characters in the response string. + * Pass 0 to disable this behavior and let the response string be allocated dynamically on demand. + * + * Example: + * cpr::Session session; + * session.SetUrl(cpr::Url{"http://xxx/file"}); + * session.ResponseStringReserve(1024 * 512); // Reserve space for at least 1024 * 512 characters + * cpr::Response r = session.Get(); + **/ + void ResponseStringReserve(size_t size); + Response Delete(); + Response Download(const WriteCallback& write); + Response Download(std::ofstream& file); + Response Get(); + Response Head(); + Response Options(); + Response Patch(); + Response Post(); + Response Put(); + + AsyncResponse GetAsync(); + AsyncResponse DeleteAsync(); + AsyncResponse DownloadAsync(const WriteCallback& write); + AsyncResponse DownloadAsync(std::ofstream& file); + AsyncResponse HeadAsync(); + AsyncResponse OptionsAsync(); + AsyncResponse PatchAsync(); + AsyncResponse PostAsync(); + AsyncResponse PutAsync(); + + template <typename Then> + auto GetCallback(Then then); + template <typename Then> + auto PostCallback(Then then); + template <typename Then> + auto PutCallback(Then then); + template <typename Then> + auto HeadCallback(Then then); + template <typename Then> + auto DeleteCallback(Then then); + template <typename Then> + auto OptionsCallback(Then then); + template <typename Then> + auto PatchCallback(Then then); + + std::shared_ptr<CurlHolder> GetCurlHolder(); + std::string GetFullRequestUrl(); + + void PrepareDelete(); + void PrepareGet(); + void PrepareHead(); + void PrepareOptions(); + void PreparePatch(); + void PreparePost(); + void PreparePut(); + void PrepareDownload(const WriteCallback& write); + void PrepareDownload(std::ofstream& file); + Response Complete(CURLcode curl_error); + Response CompleteDownload(CURLcode curl_error); + + void AddInterceptor(const std::shared_ptr<Interceptor>& pinterceptor); + + private: + // Interceptors should be able to call the private procceed() function + friend Interceptor; + friend MultiPerform; + + bool hasBodyOrPayload_{false}; + bool chunkedTransferEncoding_{false}; + std::shared_ptr<CurlHolder> curl_; + Url url_; + Parameters parameters_; + Proxies proxies_; + ProxyAuthentication proxyAuth_; + Header header_; + AcceptEncoding acceptEncoding_; + /** + * Will be set by the read callback. + * Ensures that the "Transfer-Encoding" is set to "chunked", if not overriden in header_. + **/ + ReadCallback readcb_; + HeaderCallback headercb_; + WriteCallback writecb_; + ProgressCallback progresscb_; + DebugCallback debugcb_; + size_t response_string_reserve_size_{0}; + std::string response_string_; + std::string header_string_; + std::queue<std::shared_ptr<Interceptor>> interceptors_; + bool isUsedInMultiPerform{false}; + + Response makeDownloadRequest(); + Response makeRequest(); + Response proceed(); + void prepareCommon(); + void prepareCommonDownload(); + void SetHeaderInternal(); + std::shared_ptr<Session> GetSharedPtrFromThis(); + CURLcode DoEasyPerform(); +}; + +template <typename Then> +auto Session::GetCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Get()); }, std::move(then)); +} + +template <typename Then> +auto Session::PostCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Post()); }, std::move(then)); +} + +template <typename Then> +auto Session::PutCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Put()); }, std::move(then)); +} + +template <typename Then> +auto Session::HeadCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Head()); }, std::move(then)); +} + +template <typename Then> +auto Session::DeleteCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Delete()); }, std::move(then)); +} + +template <typename Then> +auto Session::OptionsCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Options()); }, std::move(then)); +} + +template <typename Then> +auto Session::PatchCallback(Then then) { + return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Patch()); }, std::move(then)); +} + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/singleton.h b/Src/external_dependencies/cpr/include/cpr/singleton.h new file mode 100644 index 00000000..e2ea13bb --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/singleton.h @@ -0,0 +1,47 @@ +#ifndef CPR_SINGLETON_H +#define CPR_SINGLETON_H + +#include <mutex> + +#ifndef CPR_DISABLE_COPY +#define CPR_DISABLE_COPY(Class) \ + Class(const Class&) = delete; \ + Class& operator=(const Class&) = delete; +#endif + +#ifndef CPR_SINGLETON_DECL +#define CPR_SINGLETON_DECL(Class) \ + public: \ + static Class* GetInstance(); \ + static void ExitInstance(); \ + private: \ + CPR_DISABLE_COPY(Class) \ + static Class* s_pInstance; \ + static std::mutex s_mutex; +#endif + +#ifndef CPR_SINGLETON_IMPL +#define CPR_SINGLETON_IMPL(Class) \ + Class* Class::s_pInstance = nullptr; \ + std::mutex Class::s_mutex; \ + Class* Class::GetInstance() { \ + if (s_pInstance == nullptr) { \ + s_mutex.lock(); \ + if (s_pInstance == nullptr) { \ + s_pInstance = new Class; \ + } \ + s_mutex.unlock(); \ + } \ + return s_pInstance; \ + } \ + void Class::ExitInstance() { \ + s_mutex.lock(); \ + if (s_pInstance) { \ + delete s_pInstance; \ + s_pInstance = nullptr; \ + } \ + s_mutex.unlock(); \ + } +#endif + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/ssl_ctx.h b/Src/external_dependencies/cpr/include/cpr/ssl_ctx.h new file mode 100644 index 00000000..d495fb2b --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/ssl_ctx.h @@ -0,0 +1,26 @@ +#ifndef CPR_SSL_CTX_H +#define CPR_SSL_CTX_H + +#include "cpr/ssl_options.h" +#include <curl/curl.h> + +#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION + +namespace cpr { + +/** + * This callback function loads a CA certificate from raw_cert_buf and gets called by libcurl + * just before the initialization of an SSL connection. + * The raw_cert_buf argument is set with the CURLOPT_SSL_CTX_DATA option and has to be a nul + * terminated buffer. + * + * Sources: https://curl.se/libcurl/c/CURLOPT_SSL_CTX_FUNCTION.html + * https://curl.se/libcurl/c/CURLOPT_SSL_CTX_DATA.html + */ +CURLcode sslctx_function_load_ca_cert_from_buffer(CURL* curl, void* sslctx, void* raw_cert_buf); + +} // Namespace cpr + +#endif + +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/ssl_options.h b/Src/external_dependencies/cpr/include/cpr/ssl_options.h new file mode 100644 index 00000000..7a1784ef --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/ssl_options.h @@ -0,0 +1,622 @@ +#ifndef CPR_SSLOPTIONS_H +#define CPR_SSLOPTIONS_H + +#include <memory> +#include <string> +#include <vector> + +#include <cpr/filesystem.h> +#include <curl/curl.h> + +#include "cpr/util.h" +#include <utility> + +#define __LIBCURL_VERSION_GTE(major, minor) ((LIBCURL_VERSION_MAJOR > (major)) || ((LIBCURL_VERSION_MAJOR == (major)) && (LIBCURL_VERSION_MINOR >= (minor)))) +#define __LIBCURL_VERSION_LT(major, minor) ((LIBCURL_VERSION_MAJOR < (major)) || ((LIBCURL_VERSION_MAJOR == (major)) && (LIBCURL_VERSION_MINOR < (minor)))) + +#ifndef SUPPORT_ALPN +#define SUPPORT_ALPN __LIBCURL_VERSION_GTE(7, 36) +#endif +#ifndef SUPPORT_NPN +#define SUPPORT_NPN __LIBCURL_VERSION_GTE(7, 36) +#endif + +#ifndef SUPPORT_SSLv2 +#define SUPPORT_SSLv2 __LIBCURL_VERSION_LT(7, 19) +#endif +#ifndef SUPPORT_SSLv3 +#define SUPPORT_SSLv3 __LIBCURL_VERSION_LT(7, 39) +#endif +#ifndef SUPPORT_TLSv1_0 +#define SUPPORT_TLSv1_0 __LIBCURL_VERSION_GTE(7, 34) +#endif +#ifndef SUPPORT_TLSv1_1 +#define SUPPORT_TLSv1_1 __LIBCURL_VERSION_GTE(7, 34) +#endif +#ifndef SUPPORT_TLSv1_2 +#define SUPPORT_TLSv1_2 __LIBCURL_VERSION_GTE(7, 34) +#endif +#ifndef SUPPORT_TLSv1_3 +#define SUPPORT_TLSv1_3 __LIBCURL_VERSION_GTE(7, 52) +#endif +#ifndef SUPPORT_MAX_TLS_VERSION +#define SUPPORT_MAX_TLS_VERSION __LIBCURL_VERSION_GTE(7, 54) +#endif +#ifndef SUPPORT_MAX_TLSv1_1 +#define SUPPORT_MAX_TLSv1_1 __LIBCURL_VERSION_GTE(7, 54) +#endif +#ifndef SUPPORT_MAX_TLSv1_2 +#define SUPPORT_MAX_TLSv1_2 __LIBCURL_VERSION_GTE(7, 54) +#endif +#ifndef SUPPORT_MAX_TLSv1_3 +#define SUPPORT_MAX_TLSv1_3 __LIBCURL_VERSION_GTE(7, 54) +#endif +#ifndef SUPPORT_TLSv13_CIPHERS +#define SUPPORT_TLSv13_CIPHERS __LIBCURL_VERSION_GTE(7, 61) +#endif +#ifndef SUPPORT_SESSIONID_CACHE +#define SUPPORT_SESSIONID_CACHE __LIBCURL_VERSION_GTE(7, 16) +#endif +#ifndef SUPPORT_SSL_FALSESTART +#define SUPPORT_SSL_FALSESTART __LIBCURL_VERSION_GTE(7, 42) +#endif +#ifndef SUPPORT_SSL_NO_REVOKE +#define SUPPORT_SSL_NO_REVOKE __LIBCURL_VERSION_GTE(7, 44) +#endif +#ifndef SUPPORT_CURLOPT_SSLKEY_BLOB +#define SUPPORT_CURLOPT_SSLKEY_BLOB __LIBCURL_VERSION_GTE(7, 71) +#endif +#ifndef SUPPORT_CURLOPT_SSL_CTX_FUNCTION +#define SUPPORT_CURLOPT_SSL_CTX_FUNCTION __LIBCURL_VERSION_GTE(7, 11) +#endif + +namespace cpr { + +class VerifySsl { + public: + VerifySsl() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + VerifySsl(bool p_verify) : verify(p_verify) {} + + explicit operator bool() const { + return verify; + } + + bool verify = true; +}; + +namespace ssl { + +// set SSL client certificate +class CertFile { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + CertFile(fs::path&& p_filename) : filename(std::move(p_filename)) {} + + virtual ~CertFile() = default; + + const fs::path filename; + + virtual const char* GetCertType() const { + return "PEM"; + } +}; + +using PemCert = CertFile; + +class DerCert : public CertFile { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + DerCert(fs::path&& p_filename) : CertFile(std::move(p_filename)) {} + + virtual ~DerCert() = default; + + const char* GetCertType() const override { + return "DER"; + } +}; + +// specify private keyfile for TLS and SSL client cert +class KeyFile { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + KeyFile(fs::path&& p_filename) : filename(std::move(p_filename)) {} + + template <typename FileType, typename PassType> + KeyFile(FileType&& p_filename, PassType p_password) : filename(std::forward<FileType>(p_filename)), password(std::move(p_password)) {} + + virtual ~KeyFile() { + util::secureStringClear(password); + } + + fs::path filename; + std::string password; + + virtual const char* GetKeyType() const { + return "PEM"; + } +}; + +#if SUPPORT_CURLOPT_SSLKEY_BLOB +class KeyBlob { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + KeyBlob(std::string&& p_blob) : blob(std::move(p_blob)) {} + + template <typename BlobType, typename PassType> + KeyBlob(BlobType&& p_blob, PassType p_password) : blob(std::forward<BlobType>(p_blob)), password(std::move(p_password)) {} + + virtual ~KeyBlob() { + util::secureStringClear(password); + } + + std::string blob; + std::string password; + + virtual const char* GetKeyType() const { + return "PEM"; + } +}; +#endif + +using PemKey = KeyFile; + +class DerKey : public KeyFile { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + DerKey(fs::path&& p_filename) : KeyFile(std::move(p_filename)) {} + + template <typename FileType, typename PassType> + DerKey(FileType&& p_filename, PassType p_password) : KeyFile(std::forward<FileType>(p_filename), std::move(p_password)) {} + + virtual ~DerKey() = default; + + const char* GetKeyType() const override { + return "DER"; + } +}; + +class PinnedPublicKey { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + PinnedPublicKey(std::string&& p_pinned_public_key) : pinned_public_key(std::move(p_pinned_public_key)) {} + + const std::string pinned_public_key; +}; + +#if SUPPORT_ALPN +// This option enables/disables ALPN in the SSL handshake (if the SSL backend libcurl is built to +// use supports it), which can be used to negotiate http2. +class ALPN { + public: + ALPN() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + ALPN(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = true; +}; +#endif // SUPPORT_ALPN + +#if SUPPORT_NPN +// This option enables/disables NPN in the SSL handshake (if the SSL backend libcurl is built to +// use supports it), which can be used to negotiate http2. +class NPN { + public: + NPN() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + NPN(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = true; +}; +#endif // SUPPORT_NPN + +// This option determines whether libcurl verifies that the server cert is for the server it is +// known as. +class VerifyHost { + public: + VerifyHost() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + VerifyHost(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = true; +}; + +// This option determines whether libcurl verifies the authenticity of the peer's certificate. +class VerifyPeer { + public: + VerifyPeer() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + VerifyPeer(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = true; +}; + +// This option determines whether libcurl verifies the status of the server cert using the +// "Certificate Status Request" TLS extension (aka. OCSP stapling). +class VerifyStatus { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + VerifyStatus(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = false; +}; + +// TLS v1.0 or later +struct TLSv1 {}; +#if SUPPORT_SSLv2 +// SSL v2 (but not SSLv3) +struct SSLv2 {}; +#endif +#if SUPPORT_SSLv3 +// SSL v3 (but not SSLv2) +struct SSLv3 {}; +#endif +#if SUPPORT_TLSv1_0 +// TLS v1.0 or later (Added in 7.34.0) +struct TLSv1_0 {}; +#endif +#if SUPPORT_TLSv1_1 +// TLS v1.1 or later (Added in 7.34.0) +struct TLSv1_1 {}; +#endif +#if SUPPORT_TLSv1_2 +// TLS v1.2 or later (Added in 7.34.0) +struct TLSv1_2 {}; +#endif +#if SUPPORT_TLSv1_3 +// TLS v1.3 or later (Added in 7.52.0) +struct TLSv1_3 {}; +#endif +#if SUPPORT_MAX_TLS_VERSION +// The flag defines the maximum supported TLS version by libcurl, or the default value from the SSL +// library is used. +struct MaxTLSVersion {}; +#endif +#if SUPPORT_MAX_TLSv1_0 +// The flag defines maximum supported TLS version as TLSv1.0. (Added in 7.54.0) +struct MaxTLSv1_0 {}; +#endif +#if SUPPORT_MAX_TLSv1_1 +// The flag defines maximum supported TLS version as TLSv1.1. (Added in 7.54.0) +struct MaxTLSv1_1 {}; +#endif +#if SUPPORT_MAX_TLSv1_2 +// The flag defines maximum supported TLS version as TLSv1.2. (Added in 7.54.0) +struct MaxTLSv1_2 {}; +#endif +#if SUPPORT_MAX_TLSv1_3 +// The flag defines maximum supported TLS version as TLSv1.3. (Added in 7.54.0) +struct MaxTLSv1_3 {}; +#endif + +// path to Certificate Authority (CA) bundle +class CaInfo { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + CaInfo(fs::path&& p_filename) : filename(std::move(p_filename)) {} + + fs::path filename; +}; + +// specify directory holding CA certificates +class CaPath { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + CaPath(fs::path&& p_filename) : filename(std::move(p_filename)) {} + + fs::path filename; +}; + +#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION +class CaBuffer { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + CaBuffer(std::string&& p_buffer) : buffer(std::move(p_buffer)) {} + + const std::string buffer; +}; +#endif + +// specify a Certificate Revocation List file +class Crl { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Crl(fs::path&& p_filename) : filename(std::move(p_filename)) {} + + fs::path filename; +}; + +// specify ciphers to use for TLS +class Ciphers { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Ciphers(std::string&& p_ciphers) : ciphers(std::move(p_ciphers)) {} + + std::string ciphers; +}; + +#if SUPPORT_TLSv13_CIPHERS +// specify ciphers suites to use for TLS 1.3 +class TLS13_Ciphers { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + TLS13_Ciphers(std::string&& p_ciphers) : ciphers(std::move(p_ciphers)) {} + + std::string ciphers; +}; +#endif + +#if SUPPORT_SESSIONID_CACHE +// enable/disable use of the SSL session-ID cache +class SessionIdCache { + public: + SessionIdCache() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + SessionIdCache(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = true; +}; +#endif + +#if SUPPORT_SSL_FALSESTART +class SslFastStart { + public: + SslFastStart() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + SslFastStart(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = false; +}; +#endif + +class NoRevoke { + public: + NoRevoke() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + NoRevoke(bool p_enabled) : enabled(p_enabled) {} + + explicit operator bool() const { + return enabled; + } + + bool enabled = false; +}; + +} // namespace ssl + +struct SslOptions { + // We don't use fs::path here, as this leads to problems using windows + std::string cert_file; + std::string cert_type; + // We don't use fs::path here, as this leads to problems using windows + std::string key_file; +#if SUPPORT_CURLOPT_SSLKEY_BLOB + std::string key_blob; +#endif + std::string key_type; + std::string key_pass; + std::string pinned_public_key; +#if SUPPORT_ALPN + bool enable_alpn = true; +#endif // SUPPORT_ALPN +#if SUPPORT_NPN + bool enable_npn = true; +#endif // SUPPORT_ALPN + bool verify_host = true; + bool verify_peer = true; + bool verify_status = false; + int ssl_version = CURL_SSLVERSION_DEFAULT; +#if SUPPORT_SSL_NO_REVOKE + bool ssl_no_revoke = false; +#endif +#if SUPPORT_MAX_TLS_VERSION + int max_version = CURL_SSLVERSION_MAX_DEFAULT; +#endif + // We don't use fs::path here, as this leads to problems using windows + std::string ca_info; + // We don't use fs::path here, as this leads to problems using windows + std::string ca_path; +#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION + std::string ca_buffer; +#endif + // We don't use fs::path here, as this leads to problems using windows + std::string crl_file; + std::string ciphers; +#if SUPPORT_TLSv13_CIPHERS + std::string tls13_ciphers; +#endif +#if SUPPORT_SESSIONID_CACHE + bool session_id_cache = true; +#endif + + ~SslOptions() noexcept { +#if SUPPORT_CURLOPT_SSLKEY_BLOB + util::secureStringClear(key_blob); +#endif + util::secureStringClear(key_pass); + } + + void SetOption(const ssl::CertFile& opt) { + cert_file = opt.filename.string(); + cert_type = opt.GetCertType(); + } + void SetOption(const ssl::KeyFile& opt) { + key_file = opt.filename.string(); + key_type = opt.GetKeyType(); + key_pass = opt.password; + } +#if SUPPORT_CURLOPT_SSLKEY_BLOB + void SetOption(const ssl::KeyBlob& opt) { + key_blob = opt.blob; + key_type = opt.GetKeyType(); + key_pass = opt.password; + } +#endif + void SetOption(const ssl::PinnedPublicKey& opt) { + pinned_public_key = opt.pinned_public_key; + } + +#if SUPPORT_ALPN + void SetOption(const ssl::ALPN& opt) { + enable_alpn = opt.enabled; + } +#endif // SUPPORT_ALPN +#if SUPPORT_NPN + void SetOption(const ssl::NPN& opt) { + enable_npn = opt.enabled; + } +#endif // SUPPORT_NPN + void SetOption(const ssl::VerifyHost& opt) { + verify_host = opt.enabled; + } + void SetOption(const ssl::VerifyPeer& opt) { + verify_peer = opt.enabled; + } + void SetOption(const ssl::VerifyStatus& opt) { + verify_status = opt.enabled; + } + void SetOption(const ssl::TLSv1& /*opt*/) { + ssl_version = CURL_SSLVERSION_TLSv1; + } +#if SUPPORT_SSL_NO_REVOKE + void SetOption(const ssl::NoRevoke& opt) { + ssl_no_revoke = opt.enabled; + } +#endif +#if SUPPORT_SSLv2 + void SetOption(const ssl::SSLv2& /*opt*/) { + ssl_version = CURL_SSLVERSION_SSLv2; + } +#endif +#if SUPPORT_SSLv3 + void SetOption(const ssl::SSLv3& /*opt*/) { + ssl_version = CURL_SSLVERSION_SSLv3; + } +#endif +#if SUPPORT_TLSv1_0 + void SetOption(const ssl::TLSv1_0& /*opt*/) { + ssl_version = CURL_SSLVERSION_TLSv1_0; + } +#endif +#if SUPPORT_TLSv1_1 + void SetOption(const ssl::TLSv1_1& /*opt*/) { + ssl_version = CURL_SSLVERSION_TLSv1_1; + } +#endif +#if SUPPORT_TLSv1_2 + void SetOption(const ssl::TLSv1_2& /*opt*/) { + ssl_version = CURL_SSLVERSION_TLSv1_2; + } +#endif +#if SUPPORT_TLSv1_3 + void SetOption(const ssl::TLSv1_3& /*opt*/) { + ssl_version = CURL_SSLVERSION_TLSv1_3; + } +#endif +#if SUPPORT_MAX_TLS_VERSION + void SetOption(const ssl::MaxTLSVersion& /*opt*/) { + max_version = CURL_SSLVERSION_DEFAULT; + } +#endif +#if SUPPORT_MAX_TLSv1_0 + void SetOption(const ssl::MaxTLSv1_0& opt) { + max_version = CURL_SSLVERSION_MAX_TLSv1_0; + } +#endif +#if SUPPORT_MAX_TLSv1_1 + void SetOption(const ssl::MaxTLSv1_1& /*opt*/) { + max_version = CURL_SSLVERSION_MAX_TLSv1_1; + } +#endif +#if SUPPORT_MAX_TLSv1_2 + void SetOption(const ssl::MaxTLSv1_2& /*opt*/) { + max_version = CURL_SSLVERSION_MAX_TLSv1_2; + } +#endif +#if SUPPORT_MAX_TLSv1_3 + void SetOption(const ssl::MaxTLSv1_3& /*opt*/) { + max_version = CURL_SSLVERSION_MAX_TLSv1_3; + } +#endif + void SetOption(const ssl::CaInfo& opt) { + ca_info = opt.filename.string(); + } + void SetOption(const ssl::CaPath& opt) { + ca_path = opt.filename.string(); + } +#if SUPPORT_CURLOPT_SSL_CTX_FUNCTION + void SetOption(const ssl::CaBuffer& opt) { + ca_buffer = opt.buffer; + } +#endif + void SetOption(const ssl::Crl& opt) { + crl_file = opt.filename.string(); + } + void SetOption(const ssl::Ciphers& opt) { + ciphers = opt.ciphers; + } +#if SUPPORT_TLSv13_CIPHERS + void SetOption(const ssl::TLS13_Ciphers& opt) { + tls13_ciphers = opt.ciphers; + } +#endif +#if SUPPORT_SESSIONID_CACHE + void SetOption(const ssl::SessionIdCache& opt) { + session_id_cache = opt.enabled; + } +#endif +}; + +namespace priv { + +template <typename T> +void set_ssl_option(SslOptions& opts, T&& t) { + opts.SetOption(std::forward<T>(t)); +} + +template <typename T, typename... Ts> +void set_ssl_option(SslOptions& opts, T&& t, Ts&&... ts) { + set_ssl_option(opts, std::forward<T>(t)); + set_ssl_option(opts, std::move(ts)...); +} + +} // namespace priv + +template <typename... Ts> +SslOptions Ssl(Ts&&... ts) { + SslOptions opts; + priv::set_ssl_option(opts, std::move(ts)...); + return opts; +} + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/status_codes.h b/Src/external_dependencies/cpr/include/cpr/status_codes.h new file mode 100644 index 00000000..6c7acd6b --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/status_codes.h @@ -0,0 +1,100 @@ +#ifndef _CPR_STATUS_CODES +#define _CPR_STATUS_CODES +#include <cstdint> +namespace cpr { +namespace status { +// Information responses +constexpr std::int32_t HTTP_CONTINUE = 100; +constexpr std::int32_t HTTP_SWITCHING_PROTOCOL = 101; +constexpr std::int32_t HTTP_PROCESSING = 102; +constexpr std::int32_t HTTP_EARLY_HINTS = 103; +// Successful responses +constexpr std::int32_t HTTP_OK = 200; +constexpr std::int32_t HTTP_CREATED = 201; +constexpr std::int32_t HTTP_ACCEPTED = 202; +constexpr std::int32_t HTTP_NON_AUTHORITATIVE_INFORMATION = 203; +constexpr std::int32_t HTTP_NO_CONTENT = 204; +constexpr std::int32_t HTTP_RESET_CONTENT = 205; +constexpr std::int32_t HTTP_PARTIAL_CONTENT = 206; +constexpr std::int32_t HTTP_MULTI_STATUS = 207; +constexpr std::int32_t HTTP_ALREADY_REPORTED = 208; +constexpr std::int32_t HTTP_IM_USED = 226; +// Redirection messages +constexpr std::int32_t HTTP_MULTIPLE_CHOICE = 300; +constexpr std::int32_t HTTP_MOVED_PERMANENTLY = 301; +constexpr std::int32_t HTTP_FOUND = 302; +constexpr std::int32_t HTTP_SEE_OTHER = 303; +constexpr std::int32_t HTTP_NOT_MODIFIED = 304; +constexpr std::int32_t HTTP_USE_PROXY = 305; +constexpr std::int32_t HTTP_UNUSED = 306; +constexpr std::int32_t HTTP_TEMPORARY_REDIRECT = 307; +constexpr std::int32_t HTTP_PERMANENT_REDIRECT = 308; +// Client error responses +constexpr std::int32_t HTTP_BAD_REQUEST = 400; +constexpr std::int32_t HTTP_UNAUTHORIZED = 401; +constexpr std::int32_t HTTP_PAYMENT_REQUIRED = 402; +constexpr std::int32_t HTTP_FORBIDDEN = 403; +constexpr std::int32_t HTTP_NOT_FOUND = 404; +constexpr std::int32_t HTTP_METHOD_NOT_ALLOWED = 405; +constexpr std::int32_t HTTP_NOT_ACCEPTABLE = 406; +constexpr std::int32_t HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; +constexpr std::int32_t HTTP_REQUEST_TIMEOUT = 408; +constexpr std::int32_t HTTP_CONFLICT = 409; +constexpr std::int32_t HTTP_GONE = 410; +constexpr std::int32_t HTTP_LENGTH_REQUIRED = 411; +constexpr std::int32_t HTTP_PRECONDITION_FAILED = 412; +constexpr std::int32_t HTTP_PAYLOAD_TOO_LARGE = 413; +constexpr std::int32_t HTTP_URI_TOO_LONG = 414; +constexpr std::int32_t HTTP_UNSUPPORTED_MEDIA_TYPE = 415; +constexpr std::int32_t HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; +constexpr std::int32_t HTTP_EXPECTATION_FAILED = 417; +constexpr std::int32_t HTTP_IM_A_TEAPOT = 418; +constexpr std::int32_t HTTP_MISDIRECTED_REQUEST = 421; +constexpr std::int32_t HTTP_UNPROCESSABLE_ENTITY = 422; +constexpr std::int32_t HTTP_LOCKED = 423; +constexpr std::int32_t HTTP_FAILED_DEPENDENCY = 424; +constexpr std::int32_t HTTP_TOO_EARLY = 425; +constexpr std::int32_t HTTP_UPGRADE_REQUIRED = 426; +constexpr std::int32_t HTTP_PRECONDITION_REQUIRED = 428; +constexpr std::int32_t HTTP_TOO_MANY_REQUESTS = 429; +constexpr std::int32_t HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; +constexpr std::int32_t HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; +// Server response errors +constexpr std::int32_t HTTP_INTERNAL_SERVER_ERROR = 500; +constexpr std::int32_t HTTP_NOT_IMPLEMENTED = 501; +constexpr std::int32_t HTTP_BAD_GATEWAY = 502; +constexpr std::int32_t HTTP_SERVICE_UNAVAILABLE = 503; +constexpr std::int32_t HTTP_GATEWAY_TIMEOUT = 504; +constexpr std::int32_t HTTP_HTTP_VERSION_NOT_SUPPORTED = 505; +constexpr std::int32_t HTTP_VARIANT_ALSO_NEGOTIATES = 506; +constexpr std::int32_t HTTP_INSUFFICIENT_STORAGE = 507; +constexpr std::int32_t HTTP_LOOP_DETECTED = 508; +constexpr std::int32_t HTTP_NOT_EXTENDED = 510; +constexpr std::int32_t HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; + +constexpr std::int32_t INFO_CODE_OFFSET = 100; +constexpr std::int32_t SUCCESS_CODE_OFFSET = 200; +constexpr std::int32_t REDIRECT_CODE_OFFSET = 300; +constexpr std::int32_t CLIENT_ERROR_CODE_OFFSET = 400; +constexpr std::int32_t SERVER_ERROR_CODE_OFFSET = 500; +constexpr std::int32_t MISC_CODE_OFFSET = 600; + +constexpr bool is_informational(const std::int32_t code) { + return (code >= INFO_CODE_OFFSET && code < SUCCESS_CODE_OFFSET); +} +constexpr bool is_success(const std::int32_t code) { + return (code >= SUCCESS_CODE_OFFSET && code < REDIRECT_CODE_OFFSET); +} +constexpr bool is_redirect(const std::int32_t code) { + return (code >= REDIRECT_CODE_OFFSET && code < CLIENT_ERROR_CODE_OFFSET); +} +constexpr bool is_client_error(const std::int32_t code) { + return (code >= CLIENT_ERROR_CODE_OFFSET && code < SERVER_ERROR_CODE_OFFSET); +} +constexpr bool is_server_error(const std::int32_t code) { + return (code >= SERVER_ERROR_CODE_OFFSET && code < MISC_CODE_OFFSET); +} + +} // namespace status +} // namespace cpr +#endif
\ No newline at end of file diff --git a/Src/external_dependencies/cpr/include/cpr/threadpool.h b/Src/external_dependencies/cpr/include/cpr/threadpool.h new file mode 100644 index 00000000..bb7e7f21 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/threadpool.h @@ -0,0 +1,122 @@ +#ifndef CPR_THREAD_POOL_H +#define CPR_THREAD_POOL_H + +#include <atomic> +#include <chrono> +#include <condition_variable> +#include <functional> +#include <future> +#include <list> +#include <memory> +#include <mutex> +#include <queue> +#include <thread> +#include <utility> + +#define CPR_DEFAULT_THREAD_POOL_MAX_THREAD_NUM std::thread::hardware_concurrency() + +constexpr size_t CPR_DEFAULT_THREAD_POOL_MIN_THREAD_NUM = 1; +constexpr std::chrono::milliseconds CPR_DEFAULT_THREAD_POOL_MAX_IDLE_TIME{60000}; + +namespace cpr { + +class ThreadPool { + public: + using Task = std::function<void()>; + + explicit ThreadPool(size_t min_threads = CPR_DEFAULT_THREAD_POOL_MIN_THREAD_NUM, size_t max_threads = CPR_DEFAULT_THREAD_POOL_MAX_THREAD_NUM, std::chrono::milliseconds max_idle_ms = CPR_DEFAULT_THREAD_POOL_MAX_IDLE_TIME); + + virtual ~ThreadPool(); + + void SetMinThreadNum(size_t min_threads) { + min_thread_num = min_threads; + } + void SetMaxThreadNum(size_t max_threads) { + max_thread_num = max_threads; + } + void SetMaxIdleTime(std::chrono::milliseconds ms) { + max_idle_time = ms; + } + size_t GetCurrentThreadNum() { + return cur_thread_num; + } + size_t GetIdleThreadNum() { + return idle_thread_num; + } + bool IsStarted() { + return status != STOP; + } + bool IsStopped() { + return status == STOP; + } + + int Start(size_t start_threads = 0); + int Stop(); + int Pause(); + int Resume(); + int Wait(); + + /** + * Return a future, calling future.get() will wait task done and return RetType. + * Submit(fn, args...) + * Submit(std::bind(&Class::mem_fn, &obj)) + * Submit(std::mem_fn(&Class::mem_fn, &obj)) + **/ + template <class Fn, class... Args> + auto Submit(Fn&& fn, Args&&... args) { + if (status == STOP) { + Start(); + } + if (idle_thread_num <= 0 && cur_thread_num < max_thread_num) { + CreateThread(); + } + using RetType = decltype(fn(args...)); + auto task = std::make_shared<std::packaged_task<RetType()> >(std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)); + std::future<RetType> future = task->get_future(); + { + std::lock_guard<std::mutex> locker(task_mutex); + tasks.emplace([task] { (*task)(); }); + } + + task_cond.notify_one(); + return future; + } + + private: + bool CreateThread(); + void AddThread(std::thread* thread); + void DelThread(std::thread::id id); + + public: + size_t min_thread_num; + size_t max_thread_num; + std::chrono::milliseconds max_idle_time; + + private: + enum Status { + STOP, + RUNNING, + PAUSE, + }; + + struct ThreadData { + std::shared_ptr<std::thread> thread; + std::thread::id id; + Status status; + time_t start_time; + time_t stop_time; + }; + + std::atomic<Status> status; + std::atomic<size_t> cur_thread_num; + std::atomic<size_t> idle_thread_num; + std::list<ThreadData> threads; + std::mutex thread_mutex; + std::queue<Task> tasks; + std::mutex task_mutex; + std::condition_variable task_cond; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/timeout.h b/Src/external_dependencies/cpr/include/cpr/timeout.h new file mode 100644 index 00000000..492470ec --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/timeout.h @@ -0,0 +1,27 @@ +#ifndef CPR_TIMEOUT_H +#define CPR_TIMEOUT_H + +#include <chrono> +#include <cstdint> + +namespace cpr { + +class Timeout { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Timeout(const std::chrono::milliseconds& duration) : ms{duration} {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Timeout(const std::int32_t& milliseconds) : Timeout{std::chrono::milliseconds(milliseconds)} {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Timeout(const std::chrono::seconds& duration) : ms{1000 * duration.count()} {} + + // No way around since curl uses a long here. + // NOLINTNEXTLINE(google-runtime-int) + long Milliseconds() const; + + std::chrono::milliseconds ms; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/unix_socket.h b/Src/external_dependencies/cpr/include/cpr/unix_socket.h new file mode 100644 index 00000000..9d4d77c0 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/unix_socket.h @@ -0,0 +1,21 @@ +#ifndef CPR_UNIX_SOCKET_H +#define CPR_UNIX_SOCKET_H + +#include <string> + +namespace cpr { + +class UnixSocket { + public: + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + UnixSocket(std::string&& unix_socket) : unix_socket_(std::move(unix_socket)) {} + + const char* GetUnixSocketString() const noexcept; + + private: + const std::string unix_socket_; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/user_agent.h b/Src/external_dependencies/cpr/include/cpr/user_agent.h new file mode 100644 index 00000000..369a80d9 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/user_agent.h @@ -0,0 +1,33 @@ +#ifndef CPR_USERAGENT_H +#define CPR_USERAGENT_H + +#include <initializer_list> +#include <string> + +#include "cpr/cprtypes.h" + +namespace cpr { +class UserAgent : public StringHolder<UserAgent> { + public: + UserAgent() : StringHolder<UserAgent>() {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + UserAgent(const std::string& useragent) : StringHolder<UserAgent>(useragent) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + UserAgent(std::string&& useragent) : StringHolder<UserAgent>(std::move(useragent)) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + UserAgent(std::string_view useragent) : StringHolder<UserAgent>(useragent) {} + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + UserAgent(const char* useragent) : StringHolder<UserAgent>(useragent) {} + UserAgent(const char* str, size_t len) : StringHolder<UserAgent>(str, len) {} + UserAgent(const std::initializer_list<std::string> args) : StringHolder<UserAgent>(args) {} + UserAgent(const UserAgent& other) = default; + UserAgent(UserAgent&& old) noexcept = default; + ~UserAgent() override = default; + + UserAgent& operator=(UserAgent&& old) noexcept = default; + UserAgent& operator=(const UserAgent& other) = default; +}; + +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/util.h b/Src/external_dependencies/cpr/include/cpr/util.h new file mode 100644 index 00000000..f35ad473 --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/util.h @@ -0,0 +1,45 @@ +#ifndef CPR_UTIL_H +#define CPR_UTIL_H + +#include <fstream> +#include <string> +#include <vector> + +#include "cpr/callback.h" +#include "cpr/cookies.h" +#include "cpr/cprtypes.h" +#include "cpr/curlholder.h" + +namespace cpr { +namespace util { + +Header parseHeader(const std::string& headers, std::string* status_line = nullptr, std::string* reason = nullptr); +Cookies parseCookies(curl_slist* raw_cookies); +size_t readUserFunction(char* ptr, size_t size, size_t nitems, const ReadCallback* read); +size_t headerUserFunction(char* ptr, size_t size, size_t nmemb, const HeaderCallback* header); +size_t writeFunction(char* ptr, size_t size, size_t nmemb, std::string* data); +size_t writeFileFunction(char* ptr, size_t size, size_t nmemb, std::ofstream* file); +size_t writeUserFunction(char* ptr, size_t size, size_t nmemb, const WriteCallback* write); +#if LIBCURL_VERSION_NUM < 0x072000 +int progressUserFunction(const ProgressCallback* progress, double dltotal, double dlnow, double ultotal, double ulnow); +#else +int progressUserFunction(const ProgressCallback* progress, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); +#endif +int debugUserFunction(CURL* handle, curl_infotype type, char* data, size_t size, const DebugCallback* debug); +std::vector<std::string> split(const std::string& to_split, char delimiter); +std::string urlEncode(const std::string& s); +std::string urlDecode(const std::string& s); + +/** + * Override the content of the provided string to hide sensitive data. The + * string content after invocation is undefined. The string size is reset to zero. + * impl. based on: + * https://github.com/ojeda/secure_clear/blob/master/example-implementation/secure_clear.h + **/ +void secureStringClear(std::string& s); +bool isTrue(const std::string& s); + +} // namespace util +} // namespace cpr + +#endif diff --git a/Src/external_dependencies/cpr/include/cpr/verbose.h b/Src/external_dependencies/cpr/include/cpr/verbose.h new file mode 100644 index 00000000..2bf0df8f --- /dev/null +++ b/Src/external_dependencies/cpr/include/cpr/verbose.h @@ -0,0 +1,18 @@ +#ifndef CPR_VERBOSE_H_ +#define CPR_VERBOSE_H_ + +namespace cpr { + +class Verbose { + public: + Verbose() = default; + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + Verbose(const bool p_verbose) : verbose{p_verbose} {} + + bool verbose = true; +}; + +} // namespace cpr + + +#endif /* CPR_VERBOSE_H_ */ |