From ebe7695ee5803dd3c2bb4f22f5e12d776c985d56 Mon Sep 17 00:00:00 2001 From: Paul Cristian Sarbu Date: Wed, 15 Feb 2023 14:47:15 +0100 Subject: structure cleanup: move libcurl utilities to other_tools... ...in order to not include unwanted dependencies in just proper. As the whole other_tools folder is meant to be excluded from bootstrapping, also remove the bootstrap guards. --- src/other_tools/utils/curl_easy_handle.cpp | 151 +++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/other_tools/utils/curl_easy_handle.cpp (limited to 'src/other_tools/utils/curl_easy_handle.cpp') diff --git a/src/other_tools/utils/curl_easy_handle.cpp b/src/other_tools/utils/curl_easy_handle.cpp new file mode 100644 index 00000000..29e7670e --- /dev/null +++ b/src/other_tools/utils/curl_easy_handle.cpp @@ -0,0 +1,151 @@ +// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/other_tools/utils/curl_easy_handle.hpp" + +#include + +#include "src/buildtool/file_system/file_system_manager.hpp" +#include "src/buildtool/logging/logger.hpp" + +extern "C" { +#include "curl/curl.h" +} + +void curl_easy_closer(gsl::owner curl) { + curl_easy_cleanup(curl); +} + +auto CurlEasyHandle::Create() noexcept -> std::shared_ptr { + try { + auto curl = std::make_shared(); + auto* handle = curl_easy_init(); + if (handle == nullptr) { + return nullptr; + } + curl->handle_.reset(handle); + return curl; + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "create curl easy handle failed with:\n{}", + ex.what()); + return nullptr; + } +} + +auto CurlEasyHandle::EasyWriteToFile(gsl::owner data, + size_t size, + size_t nmemb, + gsl::owner userptr) + -> std::streamsize { + auto actual_size = static_cast(size * nmemb); + auto* file = static_cast(userptr); + file->write(data, actual_size); // append chunk + return actual_size; +} + +auto CurlEasyHandle::EasyWriteToString(gsl::owner data, + size_t size, + size_t nmemb, + gsl::owner userptr) + -> std::streamsize { + size_t actual_size = size * nmemb; + (static_cast(userptr))->append(data, actual_size); + return static_cast(actual_size); +} + +auto CurlEasyHandle::DownloadToFile( + std::string const& url, + std::filesystem::path const& file_path) noexcept -> int { + try { + // set URL + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_URL, url.c_str()); + + // ensure redirects are allowed, otherwise it might simply read empty + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_FOLLOWLOCATION, 1); + + // set callback for writing to file + std::ofstream file(file_path.c_str(), std::ios::binary); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_WRITEFUNCTION, EasyWriteToFile); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt( + handle_.get(), CURLOPT_WRITEDATA, static_cast(&file)); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_VERBOSE, 1); + + // perform download + auto res = curl_easy_perform(handle_.get()); + + // close file + file.close(); + + // check result + if (res != CURLE_OK) { + // cleanup failed downloaded file, if created + [[maybe_unused]] auto tmp_res = + FileSystemManager::RemoveFile(file_path); + } + return res; + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "curl download to file failed with:\n{}", + ex.what()); + return 1; + } +} + +auto CurlEasyHandle::DownloadToString(std::string const& url) noexcept + -> std::optional { + try { + // set URL + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_URL, url.c_str()); + + // ensure redirects are allowed, otherwise it might simply read empty + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_FOLLOWLOCATION, 1); + + // set callback for writing to string + std::string content{}; + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt( + handle_.get(), CURLOPT_WRITEFUNCTION, EasyWriteToString); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt( + handle_.get(), CURLOPT_WRITEDATA, static_cast(&content)); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + curl_easy_setopt(handle_.get(), CURLOPT_VERBOSE, 1); + + // perform download + auto res = curl_easy_perform(handle_.get()); + + // check result + if (res != CURLE_OK) { + return std::nullopt; + } + return content; + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "curl download to string failed with:\n{}", + ex.what()); + return std::nullopt; + } +} -- cgit v1.2.3